semantics.c

Tue, 01 Jan 2002 03:44:40 +0000

author
eric
date
Tue, 01 Jan 2002 03:44:40 +0000
changeset 26
4368c5fd9242
parent 25
139b91f9a224
child 30
35fad7ec7732
permissions
-rw-r--r--

handle input and output files properly.

     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 "tiff2pdf.h"
    11 typedef struct
    12 {
    13   boolean has_size;
    14   page_size_t 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   bookmark_t *first_bookmark;
    56   bookmark_t *last_bookmark;
    58   boolean has_page_label;
    59   page_label_t page_label;
    60 } output_context_t;
    63 typedef struct output_page_t
    64 {
    65   struct output_page_t *next;
    66   output_context_t *output_context;
    67   range_t range;
    68   bookmark_t *bookmark_list;
    69 } output_page_t;
    72 #define SEMANTIC_DEBUG
    73 #ifdef SEMANTIC_DEBUG
    74 #define SDBG(x) printf x
    75 #else
    76 #define SDBG(x)
    77 #endif
    80 FILE *yyin;
    81 int line;  /* line number in spec file */
    83 int bookmark_level;
    85 input_context_t *first_input_context;
    86 input_context_t *last_input_context;
    88 input_modifier_type_t current_modifier_context;
    90 input_image_t *first_input_image;
    91 input_image_t *last_input_image;
    93 output_context_t *first_output_context;
    94 output_context_t *last_output_context;
    96 output_page_t *first_output_page;
    97 output_page_t *last_output_page;
   100 void input_push_context (void)
   101 {
   102   input_context_t *new_input_context;
   104   new_input_context = malloc (sizeof (input_context_t));
   105   if (! new_input_context)
   106     {
   107       fprintf (stderr, "failed to malloc an input context\n");
   108       return;
   109     }
   111   if (last_input_context)
   112     {
   113       memcpy (new_input_context, last_input_context, sizeof (input_context_t));
   114       new_input_context->image_count = 0;
   115     }
   116   else
   117     {
   118       memset (new_input_context, 0, sizeof (input_context_t));
   119       first_input_context = new_input_context;
   120     }
   122   new_input_context->parent = last_input_context;
   123   last_input_context = new_input_context;
   124 };
   126 void input_pop_context (void)
   127 {
   128   if (! last_input_context)
   129     {
   130       fprintf (stderr, "failed to pop an input context\n");
   131       return;
   132     }
   134   last_input_context = last_input_context->parent;
   135 };
   137 void input_set_modifier_context (input_modifier_type_t type)
   138 {
   139   current_modifier_context = type;
   140 #ifdef SEMANTIC_DEBUG
   141   SDBG(("modifier type "));
   142   switch (type)
   143     {
   144     case INPUT_MODIFIER_ALL: SDBG(("all")); break;
   145     case INPUT_MODIFIER_ODD: SDBG(("odd")); break;
   146     case INPUT_MODIFIER_EVEN: SDBG(("even")); break;
   147     default: SDBG(("unknown %d", type));
   148     }
   149   SDBG(("\n"));
   150 #endif /* SEMANTIC_DEBUG */
   151 }
   153 static void input_clone (void)
   154 {
   155   input_context_t *new_input_context;
   157   if (! last_input_context->image_count)
   158     return;
   160   new_input_context = malloc (sizeof (input_context_t));
   161   if (! new_input_context)
   162     {
   163       fprintf (stderr, "failed to malloc an input context\n");
   164       return;
   165     }
   167   memcpy (new_input_context, last_input_context, sizeof (input_context_t));
   168   new_input_context->image_count = 0;
   169   last_input_context->next = new_input_context;
   170 }
   172 void input_set_file (char *name)
   173 {
   174   input_clone ();
   175   last_input_context->input_file = name;
   176 };
   178 void input_set_rotation (int rotation)
   179 {
   180   last_input_context->modifiers [current_modifier_context].has_rotation = 1;
   181   last_input_context->modifiers [current_modifier_context].rotation = rotation;
   182   SDBG(("rotation %d\n", rotation));
   183 }
   185 static void increment_input_image_count (int count)
   186 {
   187   input_context_t *context;
   189   for (context = last_input_context; context; context = context->parent)
   190     context->image_count += count;
   191 }
   193 void input_images (range_t range)
   194 {
   195   input_image_t *new_image;
   196   int count = ((range.last - range.first) + 1);
   198 #ifdef SEMANTIC_DEBUG
   199   if (range.first == range.last)
   200     SDBG(("image %d\n", range.first));
   201   else
   202     SDBG(("images %d..%d\n", range.first, range.last));
   203 #endif /* SEMANTIC_DEBUG */
   205   new_image = calloc (1, sizeof (input_image_t));
   206   if (! new_image)
   207     {
   208       fprintf (stderr, "failed to malloc an input image struct\n");
   209       return;
   210     }
   211   if (first_input_image)
   212     {
   213       last_input_image->next = new_image;
   214       last_input_image = new_image;
   215     }
   216   else
   217     {
   218       first_input_image = last_input_image = new_image;
   219     }
   220   new_image->range = range;
   221   new_image->input_context = last_input_context;
   222   increment_input_image_count (count);
   223 }
   226 void output_push_context (void)
   227 {
   228   output_context_t *new_output_context;
   230   new_output_context = malloc (sizeof (output_context_t));
   231   if (! new_output_context)
   232     {
   233       fprintf (stderr, "failed to malloc an output context\n");
   234       return;
   235     }
   237   if (last_output_context)
   238     {
   239       memcpy (new_output_context, last_output_context, sizeof (output_context_t));
   240       new_output_context->page_count = 0;
   241       new_output_context->first_bookmark = NULL;
   242       new_output_context->last_bookmark = NULL;
   243     }
   244   else
   245     {
   246       memset (new_output_context, 0, sizeof (output_context_t));
   247       first_output_context = new_output_context;
   248     }
   250   new_output_context->parent = last_output_context;
   251   last_output_context = new_output_context;
   252 };
   254 void output_pop_context (void)
   255 {
   256   if (! last_output_context)
   257     {
   258       fprintf (stderr, "failed to pop an output context\n");
   259       return;
   260     }
   262   last_output_context = last_output_context->parent;
   263 };
   265 static void output_clone (void)
   266 {
   267   output_context_t *new_output_context;
   269   if (! last_output_context->page_count)
   270     return;
   272   new_output_context = malloc (sizeof (output_context_t));
   273   if (! new_output_context)
   274     {
   275       fprintf (stderr, "failed to malloc an output context\n");
   276       return;
   277     }
   279   memcpy (new_output_context, last_output_context, sizeof (output_context_t));
   280   new_output_context->page_count = 0;
   281   last_output_context->next = new_output_context;
   282 }
   284 void output_set_file (char *name)
   285 {
   286   output_clone ();
   287   last_output_context->output_file = name;
   288 };
   290 void output_set_bookmark (char *name)
   291 {
   292   bookmark_t *new_bookmark;
   294   /* As the language is defined (parser.y), a bookmark can only appear
   295      at the beginning of a context! */
   296   if (last_output_context->page_count)
   297     {
   298       fprintf (stderr, "internal error, bookmark not at beginning of context\n");
   299       exit (2);
   300     }
   302   new_bookmark = calloc (1, sizeof (bookmark_t));
   303   if (! new_bookmark)
   304     {
   305       fprintf (stderr, "failed to calloc a bookmark\n");
   306       return;
   307     }
   309   new_bookmark->level = bookmark_level;
   310   new_bookmark->name = name;
   311   if (last_output_context->first_bookmark)
   312     last_output_context->last_bookmark->next = new_bookmark;
   313   else
   314     last_output_context->first_bookmark = new_bookmark;
   315   last_output_context->last_bookmark = new_bookmark;
   316 }
   318 void output_set_page_label (page_label_t label)
   319 {
   320   output_clone ();
   321   last_output_context->has_page_label = 1;
   322   last_output_context->page_label = label;
   323 }
   325 static void increment_output_page_count (int count)
   326 {
   327   output_context_t *context;
   329   for (context = last_output_context; context; context = context->parent)
   330     context->page_count += count;
   331 }
   334 void output_pages (range_t range)
   335 {
   336   output_page_t *new_page;
   337   output_context_t *context;
   338   int count = ((range.last - range.first) + 1);
   340 #ifdef SEMANTIC_DEBUG
   341   if (range.first == range.last)
   342     SDBG(("page %d\n", range.first));
   343   else
   344     SDBG(("pages %d..%d\n", range.first, range.last));
   345 #endif /* SEMANTIC_DEBUG */
   347   new_page = calloc (1, sizeof (output_page_t));
   348   if (! new_page)
   349     {
   350       fprintf (stderr, "failed to malloc an output page struct\n");
   351       return;
   352     }
   353   if (first_output_page)
   354     {
   355       last_output_page->next = new_page;
   356       last_output_page = new_page;
   357     }
   358   else
   359     {
   360       first_output_page = last_output_page = new_page;
   361     }
   362   new_page->range = range;
   363   new_page->output_context = last_output_context;
   365   /* transfer bookmarks from context(s) to page */
   366   for (context = last_output_context; context; context = context->parent)
   367     if (context->first_bookmark)
   368       {
   369 	context->last_bookmark->next = new_page->bookmark_list;
   370 	new_page->bookmark_list = context->first_bookmark;
   371 	context->first_bookmark = NULL;
   372 	context->last_bookmark = NULL;
   373       }
   375   increment_output_page_count (count);
   376 }
   379 void yyerror (char *s)
   380 {
   381   fprintf (stderr, "%d: %s\n", line, s);
   382 }
   385 static char *get_input_file (input_context_t *context)
   386 {
   387   for (; context; context = context->parent)
   388     if (context->input_file)
   389       return (context->input_file);
   390   fprintf (stderr, "no input file name found\n");
   391   exit (2);
   392 }
   394 static int get_input_rotation (input_context_t *context, input_modifier_type_t type)
   395 {
   396   for (; context; context = context->parent)
   397     {
   398       if (context->modifiers [type].has_rotation)
   399 	return (context->modifiers [type].rotation);
   400       if (context->modifiers [INPUT_MODIFIER_ALL].has_rotation)
   401 	return (context->modifiers [INPUT_MODIFIER_ALL].rotation);
   402     }
   403   return (0);  /* default */
   404 }
   406 static char *get_output_file (output_context_t *context)
   407 {
   408   for (; context; context = context->parent)
   409     if (context->output_file)
   410       return (context->output_file);
   411   fprintf (stderr, "no output file name found\n");
   412   exit (2);
   413 }
   415 static page_label_t *get_output_page_label (output_context_t *context)
   416 {
   417   for (; context; context = context->parent)
   418     if (context->has_page_label)
   419       return (& context->page_label);
   420   return (NULL);  /* default */
   421 }
   424 #ifdef SEMANTIC_DEBUG
   425 void dump_input_tree (void)
   426 {
   427   input_image_t *image;
   428   int i;
   430   printf ("input images:\n");
   431   for (image = first_input_image; image; image = image->next)
   432     for (i = image->range.first; i <= image->range.last; i++)
   433       {
   434 	input_modifier_type_t parity = (i % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
   435 	printf ("file '%s' image %d, rotation %d\n",
   436 	        get_input_file (image->input_context),
   437 		i, 
   438 		get_input_rotation (image->input_context, parity));
   439       }
   440 }
   442 void dump_output_tree (void)
   443 {
   444   int i;
   445   output_page_t *page;
   446   bookmark_t *bookmark;
   448   printf ("output pages:\n");
   449   for (page = first_output_page; page; page = page->next)
   450     {
   451       if (page->bookmark_list)
   452 	{
   453 	  for (bookmark = page->bookmark_list; bookmark; bookmark = bookmark->next)
   454 	    printf ("bookmark %d \"%s\"\n", bookmark->level, bookmark->name);
   455 	}
   456       for (i = page->range.first; i <= page->range.last; i++)
   457 	{
   458 	  page_label_t *label = get_output_page_label (page->output_context);
   459 	  printf ("file \"%s\" ", get_output_file (page->output_context));
   460 	  if (label)
   461 	    {
   462 	      printf ("label ");
   463 	      if (label->prefix)
   464 		printf ("\"%s\" ", label->prefix);
   465 	      if (label->style)
   466 		printf ("'%c' ", label->style);
   467 	    }
   468 	  printf ("page %d\n", i);
   469 	}
   470     }
   471 }
   472 #endif /* SEMANTIC_DEBUG */
   475 static inline int range_count (range_t range)
   476 {
   477   return ((range.last - range.first) + 1);
   478 }
   481 boolean parse_spec_file (char *fn)
   482 {
   483   boolean result = 0;
   485   yyin = fopen (fn, "r");
   486   if (! yyin)
   487     {
   488       fprintf (stderr, "can't open spec file '%s'\n", fn);
   489       goto fail;
   490     }
   492   line = 1;
   494   input_push_context ();  /* create root input context */
   495   input_push_context ();  /* create inital input context */
   497   output_push_context ();  /* create root output context */
   498   output_push_context ();  /* create initial output context */
   500   yyparse ();
   502   if (first_input_context->image_count != first_output_context->page_count)
   503     {
   504       fprintf (stderr, "input image count %d != output page count %d\n",
   505 	       first_input_context->image_count,
   506 	       first_output_context->page_count);
   507       goto fail;
   508     }
   510   fprintf (stderr, "%d pages specified\n", first_input_context->image_count);
   512   result = 1;
   514 #ifdef SEMANTIC_DEBUG
   515   dump_input_tree ();
   516   dump_output_tree ();
   517 #endif /* SEMANTIC_DEBUG */
   519  fail:
   520   if (yyin)
   521     fclose (yyin);
   523   return (result);
   524 }
   527 boolean process_specs (void)
   528 {
   529   input_image_t *image = NULL;
   530   output_page_t *page = NULL;
   531   int i = 0;
   532   int p = 0;
   533   int page_index = 0;
   534   input_attributes_t input_attributes;
   535   input_modifier_type_t parity;
   536   page_label_t *page_label;
   538   for (;;)
   539     {
   540       if ((! image) || (i >= range_count (image->range)))
   541 	{
   542 	  if (image)
   543 	    image = image->next;
   544 	  else
   545 	    image = first_input_image;
   546 	  if (! image)
   547 	    return (0);
   548 	  i = 0;
   549 	  if (! open_tiff_input_file (get_input_file (image->input_context)))
   550 	    return (0);
   551 	}
   553       if ((! page) || (p >= range_count (page->range)))
   554 	{
   555 	  if (page)
   556 	    page = page->next;
   557 	  else
   558 	    page = first_output_page;
   559 	  p = 0;
   560 	  if (! open_pdf_output_file (get_output_file (page->output_context)))
   561 	    return (0);
   562 	  page_label = get_output_page_label (page->output_context);
   563 	  process_page_numbers (page_index,
   564 				range_count (page->range),
   565 				page->range.first,
   566 				page_label);
   567 	}
   569       parity = ((image->range.first + i) % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
   571       memset (& input_attributes, 0, sizeof (input_attributes));
   572       input_attributes.rotation = get_input_rotation (image->input_context,
   573 						      parity);;
   575       process_page (image->range.first + i,
   576 		    input_attributes,
   577 		    page->bookmark_list);
   578       i++;
   579       p++;
   580       page_index++;
   581     }
   583   return (1);
   584 }