semantics.c

Sun, 25 Aug 2002 13:21:28 +0000

author
eric
date
Sun, 25 Aug 2002 13:21:28 +0000
changeset 45
23ef95d6ff07
parent 44
0f78374addae
child 48
3d0be1c1c1b2
permissions
-rw-r--r--

cloning an input context wasn't updating last_input_context

     1 #include <stdlib.h>
     2 #include <string.h>
     3 #include <stdio.h>
     5 #include "type.h"
     6 #include "semantics.h"
     7 #include "parser.tab.h"
     8 #include "t2p.h"
    11 typedef struct
    12 {
    13   boolean has_page_size;
    14   page_size_t page_size;
    16   boolean has_rotation;
    17   int rotation;
    19   boolean has_crop;
    20   crop_t crop;
    21 } input_modifiers_t;
    24 typedef struct input_context_t
    25 {
    26   struct input_context_t *parent;
    27   struct input_context_t *next;
    29   int image_count;  /* how many pages reference this context,
    30 		      including those from subcontexts */
    32   char *input_file;
    34   input_modifiers_t modifiers [INPUT_MODIFIER_TYPE_COUNT];
    35 } input_context_t;
    38 typedef struct input_image_t
    39 {
    40   struct input_image_t *next;
    41   input_context_t *input_context;
    42   range_t range;
    43 } input_image_t;
    46 typedef struct output_context_t
    47 {
    48   struct output_context_t *parent;
    49   struct output_context_t *next;
    51   int page_count;  /* how many pages reference this context,
    52 		      including those from subcontexts */
    54   char *output_file;
    55   pdf_file_attributes_t file_attributes;
    57   bookmark_t *first_bookmark;
    58   bookmark_t *last_bookmark;
    60   boolean has_page_label;
    61   page_label_t page_label;
    62 } output_context_t;
    65 typedef struct output_page_t
    66 {
    67   struct output_page_t *next;
    68   output_context_t *output_context;
    69   range_t range;
    70   bookmark_t *bookmark_list;
    71 } output_page_t;
    74 #undef SEMANTIC_DEBUG
    76 #ifdef SEMANTIC_DEBUG
    77 #define SDBG(x) printf x
    78 #else
    79 #define SDBG(x)
    80 #endif
    83 FILE *yyin;
    84 int line;  /* line number in spec file */
    86 int bookmark_level;
    88 input_context_t *first_input_context;
    89 input_context_t *last_input_context;
    91 input_modifier_type_t current_modifier_context;
    93 input_image_t *first_input_image;
    94 input_image_t *last_input_image;
    96 output_context_t *first_output_context;
    97 output_context_t *last_output_context;
    99 output_page_t *first_output_page;
   100 output_page_t *last_output_page;
   103 void input_push_context (void)
   104 {
   105   input_context_t *new_input_context;
   107   new_input_context = malloc (sizeof (input_context_t));
   108   if (! new_input_context)
   109     {
   110       fprintf (stderr, "failed to malloc an input context\n");
   111       return;
   112     }
   114   if (last_input_context)
   115     {
   116       memcpy (new_input_context, last_input_context, sizeof (input_context_t));
   117       new_input_context->image_count = 0;
   118     }
   119   else
   120     {
   121       memset (new_input_context, 0, sizeof (input_context_t));
   122       first_input_context = new_input_context;
   123     }
   125   new_input_context->parent = last_input_context;
   126   last_input_context = new_input_context;
   127 };
   129 void input_pop_context (void)
   130 {
   131   if (! last_input_context)
   132     {
   133       fprintf (stderr, "failed to pop an input context\n");
   134       return;
   135     }
   137   last_input_context = last_input_context->parent;
   138 };
   140 void input_set_modifier_context (input_modifier_type_t type)
   141 {
   142   current_modifier_context = type;
   143 #ifdef SEMANTIC_DEBUG
   144   SDBG(("modifier type "));
   145   switch (type)
   146     {
   147     case INPUT_MODIFIER_ALL: SDBG(("all")); break;
   148     case INPUT_MODIFIER_ODD: SDBG(("odd")); break;
   149     case INPUT_MODIFIER_EVEN: SDBG(("even")); break;
   150     default: SDBG(("unknown %d", type));
   151     }
   152   SDBG(("\n"));
   153 #endif /* SEMANTIC_DEBUG */
   154 }
   156 static void input_clone (void)
   157 {
   158   input_context_t *new_input_context;
   160   if (! last_input_context->image_count)
   161     return;
   163   new_input_context = malloc (sizeof (input_context_t));
   164   if (! new_input_context)
   165     {
   166       fprintf (stderr, "failed to malloc an input context\n");
   167       return;
   168     }
   170   memcpy (new_input_context, last_input_context, sizeof (input_context_t));
   171   new_input_context->image_count = 0;
   172   last_input_context->next = new_input_context;
   173   last_input_context = new_input_context;
   174 }
   176 void input_set_file (char *name)
   177 {
   178   input_clone ();
   179   last_input_context->input_file = name;
   180 };
   182 void input_set_rotation (int rotation)
   183 {
   184   last_input_context->modifiers [current_modifier_context].has_rotation = 1;
   185   last_input_context->modifiers [current_modifier_context].rotation = rotation;
   186   SDBG(("rotation %d\n", rotation));
   187 }
   189 void input_set_page_size (page_size_t size)
   190 {
   191   last_input_context->modifiers [current_modifier_context].has_page_size = 1;
   192   last_input_context->modifiers [current_modifier_context].page_size = size;
   193   SDBG(("page size %f, %f\n", size.width, size.height));
   194 }
   196 static void increment_input_image_count (int count)
   197 {
   198   input_context_t *context;
   200   for (context = last_input_context; context; context = context->parent)
   201     context->image_count += count;
   202 }
   204 void input_images (range_t range)
   205 {
   206   input_image_t *new_image;
   207   int count = ((range.last - range.first) + 1);
   209 #ifdef SEMANTIC_DEBUG
   210   if (range.first == range.last)
   211     SDBG(("image %d\n", range.first));
   212   else
   213     SDBG(("images %d..%d\n", range.first, range.last));
   214 #endif /* SEMANTIC_DEBUG */
   216   new_image = calloc (1, sizeof (input_image_t));
   217   if (! new_image)
   218     {
   219       fprintf (stderr, "failed to malloc an input image struct\n");
   220       return;
   221     }
   222   if (first_input_image)
   223     {
   224       last_input_image->next = new_image;
   225       last_input_image = new_image;
   226     }
   227   else
   228     {
   229       first_input_image = last_input_image = new_image;
   230     }
   231   new_image->range = range;
   232   new_image->input_context = last_input_context;
   233   increment_input_image_count (count);
   234 }
   237 void output_push_context (void)
   238 {
   239   output_context_t *new_output_context;
   241   new_output_context = malloc (sizeof (output_context_t));
   242   if (! new_output_context)
   243     {
   244       fprintf (stderr, "failed to malloc an output context\n");
   245       return;
   246     }
   248   if (last_output_context)
   249     {
   250       memcpy (new_output_context, last_output_context, sizeof (output_context_t));
   251       new_output_context->page_count = 0;
   252       new_output_context->first_bookmark = NULL;
   253       new_output_context->last_bookmark = NULL;
   254     }
   255   else
   256     {
   257       memset (new_output_context, 0, sizeof (output_context_t));
   258       first_output_context = new_output_context;
   259     }
   261   new_output_context->parent = last_output_context;
   262   last_output_context = new_output_context;
   263 };
   265 void output_pop_context (void)
   266 {
   267   if (! last_output_context)
   268     {
   269       fprintf (stderr, "failed to pop an output context\n");
   270       return;
   271     }
   273   last_output_context = last_output_context->parent;
   274 };
   276 static void output_clone (void)
   277 {
   278   output_context_t *new_output_context;
   280   if (! last_output_context->page_count)
   281     return;
   283   new_output_context = malloc (sizeof (output_context_t));
   284   if (! new_output_context)
   285     {
   286       fprintf (stderr, "failed to malloc an output context\n");
   287       return;
   288     }
   290   memcpy (new_output_context, last_output_context, sizeof (output_context_t));
   291   new_output_context->page_count = 0;
   292   last_output_context->next = new_output_context;
   293 }
   295 void output_set_file (char *name)
   296 {
   297   output_clone ();
   298   last_output_context->output_file = name;
   299   last_output_context->file_attributes.author = NULL;
   300   last_output_context->file_attributes.creator = NULL;
   301   last_output_context->file_attributes.title = NULL;
   302   last_output_context->file_attributes.subject = NULL;
   303   last_output_context->file_attributes.keywords = NULL;
   304 };
   306 void output_set_author (char *author)
   307 {
   308   last_output_context->file_attributes.author = author;
   309 }
   311 void output_set_creator (char *creator)
   312 {
   313   last_output_context->file_attributes.creator = creator;
   314 }
   316 void output_set_title (char *title)
   317 {
   318   last_output_context->file_attributes.title = title;
   319 }
   321 void output_set_subject (char *subject)
   322 {
   323   last_output_context->file_attributes.subject = subject;
   324 }
   326 void output_set_keywords (char *keywords)
   327 {
   328   last_output_context->file_attributes.keywords = keywords;
   329 }
   331 void output_set_bookmark (char *name)
   332 {
   333   bookmark_t *new_bookmark;
   335   /* As the language is defined (parser.y), a bookmark can only appear
   336      at the beginning of a context! */
   337   if (last_output_context->page_count)
   338     {
   339       fprintf (stderr, "internal error, bookmark not at beginning of context\n");
   340       exit (2);
   341     }
   343   new_bookmark = calloc (1, sizeof (bookmark_t));
   344   if (! new_bookmark)
   345     {
   346       fprintf (stderr, "failed to calloc a bookmark\n");
   347       return;
   348     }
   350   new_bookmark->level = bookmark_level;
   351   new_bookmark->name = name;
   352   if (last_output_context->first_bookmark)
   353     last_output_context->last_bookmark->next = new_bookmark;
   354   else
   355     last_output_context->first_bookmark = new_bookmark;
   356   last_output_context->last_bookmark = new_bookmark;
   357 }
   359 void output_set_page_label (page_label_t label)
   360 {
   361   output_clone ();
   362   last_output_context->has_page_label = 1;
   363   last_output_context->page_label = label;
   364 }
   366 static void increment_output_page_count (int count)
   367 {
   368   output_context_t *context;
   370   for (context = last_output_context; context; context = context->parent)
   371     context->page_count += count;
   372 }
   375 void output_pages (range_t range)
   376 {
   377   output_page_t *new_page;
   378   output_context_t *context;
   379   int count = ((range.last - range.first) + 1);
   381 #ifdef SEMANTIC_DEBUG
   382   if (range.first == range.last)
   383     SDBG(("page %d\n", range.first));
   384   else
   385     SDBG(("pages %d..%d\n", range.first, range.last));
   386 #endif /* SEMANTIC_DEBUG */
   388   new_page = calloc (1, sizeof (output_page_t));
   389   if (! new_page)
   390     {
   391       fprintf (stderr, "failed to malloc an output page struct\n");
   392       return;
   393     }
   394   if (first_output_page)
   395     {
   396       last_output_page->next = new_page;
   397       last_output_page = new_page;
   398     }
   399   else
   400     {
   401       first_output_page = last_output_page = new_page;
   402     }
   403   new_page->range = range;
   404   new_page->output_context = last_output_context;
   406   /* transfer bookmarks from context(s) to page */
   407   for (context = last_output_context; context; context = context->parent)
   408     if (context->first_bookmark)
   409       {
   410 	context->last_bookmark->next = new_page->bookmark_list;
   411 	new_page->bookmark_list = context->first_bookmark;
   412 	context->first_bookmark = NULL;
   413 	context->last_bookmark = NULL;
   414       }
   416   increment_output_page_count (count);
   417 }
   420 void yyerror (char *s)
   421 {
   422   fprintf (stderr, "%d: %s\n", line, s);
   423 }
   426 static char *get_input_file (input_context_t *context)
   427 {
   428   for (; context; context = context->parent)
   429     if (context->input_file)
   430       return (context->input_file);
   431   fprintf (stderr, "no input file name found\n");
   432   exit (2);
   433 }
   435 static boolean get_input_rotation (input_context_t *context,
   436 				   input_modifier_type_t type,
   437 				   int *rotation)
   438 {
   439   for (; context; context = context->parent)
   440     {
   441       if (context->modifiers [type].has_rotation)
   442 	{
   443 	  * rotation = context->modifiers [type].rotation;
   444 	  return (1);
   445 	}
   446       if (context->modifiers [INPUT_MODIFIER_ALL].has_rotation)
   447 	{
   448 	  * rotation = context->modifiers [INPUT_MODIFIER_ALL].rotation;
   449 	  return (1);
   450 	}
   451     }
   452   return (0);  /* default */
   453 }
   455 static boolean get_input_page_size (input_context_t *context,
   456 				    input_modifier_type_t type,
   457 				    page_size_t *page_size)
   458 {
   459   for (; context; context = context->parent)
   460     {
   461       if (context->modifiers [type].has_page_size)
   462 	{
   463 	  * page_size = context->modifiers [type].page_size;
   464 	  return (1);
   465 	}
   466       if (context->modifiers [INPUT_MODIFIER_ALL].has_page_size)
   467 	{
   468 	  * page_size = context->modifiers [INPUT_MODIFIER_ALL].page_size;
   469 	  return (1);
   470 	}
   471     }
   472   return (0);  /* default */
   473 }
   475 static char *get_output_file (output_context_t *context)
   476 {
   477   for (; context; context = context->parent)
   478     if (context->output_file)
   479       return (context->output_file);
   480   fprintf (stderr, "no output file found\n");
   481   exit (2);
   482 }
   484 static pdf_file_attributes_t *get_output_file_attributes (output_context_t *context)
   485 {
   486   for (; context; context = context->parent)
   487     if (context->output_file)
   488       return (& context->file_attributes);
   489   fprintf (stderr, "no output file found\n");
   490   exit (2);
   491 }
   493 static page_label_t *get_output_page_label (output_context_t *context)
   494 {
   495   for (; context; context = context->parent)
   496     if (context->has_page_label)
   497       return (& context->page_label);
   498   return (NULL);  /* default */
   499 }
   502 #ifdef SEMANTIC_DEBUG
   503 void dump_input_tree (void)
   504 {
   505   input_image_t *image;
   506   int i;
   508   printf ("input images:\n");
   509   for (image = first_input_image; image; image = image->next)
   510     for (i = image->range.first; i <= image->range.last; i++)
   511       {
   512 	input_modifier_type_t parity = (i % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
   513 	boolean has_rotation, has_page_size;
   514 	int rotation;
   515 	page_size_t page_size;
   517 	has_rotation = get_input_rotation (image->input_context,
   518 					   parity,
   519 					   & rotation);
   520 	has_page_size = get_input_page_size (image->input_context,
   521 					     parity,
   522 					     & page_size);
   523 	printf ("file '%s' image %d",
   524 	        get_input_file (image->input_context),
   525 		i);
   526 	if (has_rotation)
   527 	  printf (" rotation %d", rotation);
   528 	if (has_page_size)
   529 	  printf (" size %f, %f", page_size.width, page_size.height);
   530 	printf ("\n");
   531 	printf ("context: %08x\n", image->input_context);
   532       }
   533 }
   535 void dump_output_tree (void)
   536 {
   537   int i;
   538   output_page_t *page;
   539   bookmark_t *bookmark;
   541   printf ("output pages:\n");
   542   for (page = first_output_page; page; page = page->next)
   543     {
   544       if (page->bookmark_list)
   545 	{
   546 	  for (bookmark = page->bookmark_list; bookmark; bookmark = bookmark->next)
   547 	    printf ("bookmark %d \"%s\"\n", bookmark->level, bookmark->name);
   548 	}
   549       for (i = page->range.first; i <= page->range.last; i++)
   550 	{
   551 	  page_label_t *label = get_output_page_label (page->output_context);
   552 	  printf ("file \"%s\" ", get_output_file (page->output_context));
   553 	  if (label)
   554 	    {
   555 	      printf ("label ");
   556 	      if (label->prefix)
   557 		printf ("\"%s\" ", label->prefix);
   558 	      if (label->style)
   559 		printf ("'%c' ", label->style);
   560 	    }
   561 	  printf ("page %d\n", i);
   562 	}
   563     }
   564 }
   565 #endif /* SEMANTIC_DEBUG */
   568 static inline int range_count (range_t range)
   569 {
   570   return ((range.last - range.first) + 1);
   571 }
   574 boolean parse_spec_file (char *fn)
   575 {
   576   boolean result = 0;
   578   yyin = fopen (fn, "r");
   579   if (! yyin)
   580     {
   581       fprintf (stderr, "can't open spec file '%s'\n", fn);
   582       goto fail;
   583     }
   585   line = 1;
   587   input_push_context ();  /* create root input context */
   588   input_push_context ();  /* create inital input context */
   590   output_push_context ();  /* create root output context */
   591   output_push_context ();  /* create initial output context */
   593   yyparse ();
   595   if (first_input_context->image_count != first_output_context->page_count)
   596     {
   597       fprintf (stderr, "input image count %d != output page count %d\n",
   598 	       first_input_context->image_count,
   599 	       first_output_context->page_count);
   600       goto fail;
   601     }
   603   fprintf (stderr, "%d pages specified\n", first_input_context->image_count);
   605   result = 1;
   607 #ifdef SEMANTIC_DEBUG
   608   dump_input_tree ();
   609   dump_output_tree ();
   610 #endif /* SEMANTIC_DEBUG */
   612  fail:
   613   if (yyin)
   614     fclose (yyin);
   616   return (result);
   617 }
   620 boolean process_specs (void)
   621 {
   622   input_image_t *image = NULL;
   623   output_page_t *page = NULL;
   624   int i = 0;
   625   int p = 0;
   626   int page_index = 0;
   627   input_attributes_t input_attributes;
   628   input_modifier_type_t parity;
   629   page_label_t *page_label;
   631   for (;;)
   632     {
   633       if ((! image) || (i >= range_count (image->range)))
   634 	{
   635 	  if (image)
   636 	    image = image->next;
   637 	  else
   638 	    image = first_input_image;
   639 	  if (! image)
   640 	    return (0);
   641 	  i = 0;
   642 	  if (! open_tiff_input_file (get_input_file (image->input_context)))
   643 	    return (0);
   644 	}
   646       if ((! page) || (p >= range_count (page->range)))
   647 	{
   648 	  if (page)
   649 	    page = page->next;
   650 	  else
   651 	    page = first_output_page;
   652 	  p = 0;
   653 	  if (! open_pdf_output_file (get_output_file (page->output_context),
   654 				      get_output_file_attributes (page->output_context)))
   655 	    return (0);
   656 	  page_label = get_output_page_label (page->output_context);
   657 	  process_page_numbers (page_index,
   658 				range_count (page->range),
   659 				page->range.first,
   660 				page_label);
   661 	}
   663       parity = ((image->range.first + i) % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
   665       memset (& input_attributes, 0, sizeof (input_attributes));
   667       input_attributes.rotation = 0;
   668       input_attributes.has_rotation = get_input_rotation (image->input_context,
   669 							  parity,
   670 							  & input_attributes.rotation);
   672       input_attributes.has_page_size = get_input_page_size (image->input_context,
   673 							    parity,
   674 							    & input_attributes.page_size);
   676       process_page (image->range.first + i,
   677 		    input_attributes,
   678 		    page->bookmark_list);
   679       i++;
   680       p++;
   681       page_index++;
   682     }
   684   return (1);
   685 }