semantics.c

Mon, 26 Aug 2002 06:03:55 +0000

author
eric
date
Mon, 26 Aug 2002 06:03:55 +0000
changeset 48
3d0be1c1c1b2
parent 45
23ef95d6ff07
child 49
be20d7e8466f
permissions
-rw-r--r--

now use C99 stdint.h and stdbool.h

     1 #include <stdbool.h>
     2 #include <stdint.h>
     3 #include <stdlib.h>
     4 #include <string.h>
     5 #include <stdio.h>
     7 #include "semantics.h"
     8 #include "parser.tab.h"
     9 #include "t2p.h"
    12 typedef struct
    13 {
    14   bool has_page_size;
    15   page_size_t page_size;
    17   bool has_rotation;
    18   int rotation;
    20   bool has_crop;
    21   crop_t crop;
    22 } input_modifiers_t;
    25 typedef struct input_context_t
    26 {
    27   struct input_context_t *parent;
    28   struct input_context_t *next;
    30   int image_count;  /* how many pages reference this context,
    31 		      including those from subcontexts */
    33   char *input_file;
    35   input_modifiers_t modifiers [INPUT_MODIFIER_TYPE_COUNT];
    36 } input_context_t;
    39 typedef struct input_image_t
    40 {
    41   struct input_image_t *next;
    42   input_context_t *input_context;
    43   range_t range;
    44 } input_image_t;
    47 typedef struct output_context_t
    48 {
    49   struct output_context_t *parent;
    50   struct output_context_t *next;
    52   int page_count;  /* how many pages reference this context,
    53 		      including those from subcontexts */
    55   char *output_file;
    56   pdf_file_attributes_t file_attributes;
    58   bookmark_t *first_bookmark;
    59   bookmark_t *last_bookmark;
    61   bool has_page_label;
    62   page_label_t page_label;
    63 } output_context_t;
    66 typedef struct output_page_t
    67 {
    68   struct output_page_t *next;
    69   output_context_t *output_context;
    70   range_t range;
    71   bookmark_t *bookmark_list;
    72 } output_page_t;
    75 #undef SEMANTIC_DEBUG
    77 #ifdef SEMANTIC_DEBUG
    78 #define SDBG(x) printf x
    79 #else
    80 #define SDBG(x)
    81 #endif
    84 FILE *yyin;
    85 int line;  /* line number in spec file */
    87 int bookmark_level;
    89 input_context_t *first_input_context;
    90 input_context_t *last_input_context;
    92 input_modifier_type_t current_modifier_context;
    94 input_image_t *first_input_image;
    95 input_image_t *last_input_image;
    97 output_context_t *first_output_context;
    98 output_context_t *last_output_context;
   100 output_page_t *first_output_page;
   101 output_page_t *last_output_page;
   104 void input_push_context (void)
   105 {
   106   input_context_t *new_input_context;
   108   new_input_context = malloc (sizeof (input_context_t));
   109   if (! new_input_context)
   110     {
   111       fprintf (stderr, "failed to malloc an input context\n");
   112       return;
   113     }
   115   if (last_input_context)
   116     {
   117       memcpy (new_input_context, last_input_context, sizeof (input_context_t));
   118       new_input_context->image_count = 0;
   119     }
   120   else
   121     {
   122       memset (new_input_context, 0, sizeof (input_context_t));
   123       first_input_context = new_input_context;
   124     }
   126   new_input_context->parent = last_input_context;
   127   last_input_context = new_input_context;
   128 };
   130 void input_pop_context (void)
   131 {
   132   if (! last_input_context)
   133     {
   134       fprintf (stderr, "failed to pop an input context\n");
   135       return;
   136     }
   138   last_input_context = last_input_context->parent;
   139 };
   141 void input_set_modifier_context (input_modifier_type_t type)
   142 {
   143   current_modifier_context = type;
   144 #ifdef SEMANTIC_DEBUG
   145   SDBG(("modifier type "));
   146   switch (type)
   147     {
   148     case INPUT_MODIFIER_ALL: SDBG(("all")); break;
   149     case INPUT_MODIFIER_ODD: SDBG(("odd")); break;
   150     case INPUT_MODIFIER_EVEN: SDBG(("even")); break;
   151     default: SDBG(("unknown %d", type));
   152     }
   153   SDBG(("\n"));
   154 #endif /* SEMANTIC_DEBUG */
   155 }
   157 static void input_clone (void)
   158 {
   159   input_context_t *new_input_context;
   161   if (! last_input_context->image_count)
   162     return;
   164   new_input_context = malloc (sizeof (input_context_t));
   165   if (! new_input_context)
   166     {
   167       fprintf (stderr, "failed to malloc an input context\n");
   168       return;
   169     }
   171   memcpy (new_input_context, last_input_context, sizeof (input_context_t));
   172   new_input_context->image_count = 0;
   173   last_input_context->next = new_input_context;
   174   last_input_context = new_input_context;
   175 }
   177 void input_set_file (char *name)
   178 {
   179   input_clone ();
   180   last_input_context->input_file = name;
   181 };
   183 void input_set_rotation (int rotation)
   184 {
   185   last_input_context->modifiers [current_modifier_context].has_rotation = 1;
   186   last_input_context->modifiers [current_modifier_context].rotation = rotation;
   187   SDBG(("rotation %d\n", rotation));
   188 }
   190 void input_set_page_size (page_size_t size)
   191 {
   192   last_input_context->modifiers [current_modifier_context].has_page_size = 1;
   193   last_input_context->modifiers [current_modifier_context].page_size = size;
   194   SDBG(("page size %f, %f\n", size.width, size.height));
   195 }
   197 static void increment_input_image_count (int count)
   198 {
   199   input_context_t *context;
   201   for (context = last_input_context; context; context = context->parent)
   202     context->image_count += count;
   203 }
   205 void input_images (range_t range)
   206 {
   207   input_image_t *new_image;
   208   int count = ((range.last - range.first) + 1);
   210 #ifdef SEMANTIC_DEBUG
   211   if (range.first == range.last)
   212     SDBG(("image %d\n", range.first));
   213   else
   214     SDBG(("images %d..%d\n", range.first, range.last));
   215 #endif /* SEMANTIC_DEBUG */
   217   new_image = calloc (1, sizeof (input_image_t));
   218   if (! new_image)
   219     {
   220       fprintf (stderr, "failed to malloc an input image struct\n");
   221       return;
   222     }
   223   if (first_input_image)
   224     {
   225       last_input_image->next = new_image;
   226       last_input_image = new_image;
   227     }
   228   else
   229     {
   230       first_input_image = last_input_image = new_image;
   231     }
   232   new_image->range = range;
   233   new_image->input_context = last_input_context;
   234   increment_input_image_count (count);
   235 }
   238 void output_push_context (void)
   239 {
   240   output_context_t *new_output_context;
   242   new_output_context = malloc (sizeof (output_context_t));
   243   if (! new_output_context)
   244     {
   245       fprintf (stderr, "failed to malloc an output context\n");
   246       return;
   247     }
   249   if (last_output_context)
   250     {
   251       memcpy (new_output_context, last_output_context, sizeof (output_context_t));
   252       new_output_context->page_count = 0;
   253       new_output_context->first_bookmark = NULL;
   254       new_output_context->last_bookmark = NULL;
   255     }
   256   else
   257     {
   258       memset (new_output_context, 0, sizeof (output_context_t));
   259       first_output_context = new_output_context;
   260     }
   262   new_output_context->parent = last_output_context;
   263   last_output_context = new_output_context;
   264 };
   266 void output_pop_context (void)
   267 {
   268   if (! last_output_context)
   269     {
   270       fprintf (stderr, "failed to pop an output context\n");
   271       return;
   272     }
   274   last_output_context = last_output_context->parent;
   275 };
   277 static void output_clone (void)
   278 {
   279   output_context_t *new_output_context;
   281   if (! last_output_context->page_count)
   282     return;
   284   new_output_context = malloc (sizeof (output_context_t));
   285   if (! new_output_context)
   286     {
   287       fprintf (stderr, "failed to malloc an output context\n");
   288       return;
   289     }
   291   memcpy (new_output_context, last_output_context, sizeof (output_context_t));
   292   new_output_context->page_count = 0;
   293   last_output_context->next = new_output_context;
   294 }
   296 void output_set_file (char *name)
   297 {
   298   output_clone ();
   299   last_output_context->output_file = name;
   300   last_output_context->file_attributes.author = NULL;
   301   last_output_context->file_attributes.creator = NULL;
   302   last_output_context->file_attributes.title = NULL;
   303   last_output_context->file_attributes.subject = NULL;
   304   last_output_context->file_attributes.keywords = NULL;
   305 };
   307 void output_set_author (char *author)
   308 {
   309   last_output_context->file_attributes.author = author;
   310 }
   312 void output_set_creator (char *creator)
   313 {
   314   last_output_context->file_attributes.creator = creator;
   315 }
   317 void output_set_title (char *title)
   318 {
   319   last_output_context->file_attributes.title = title;
   320 }
   322 void output_set_subject (char *subject)
   323 {
   324   last_output_context->file_attributes.subject = subject;
   325 }
   327 void output_set_keywords (char *keywords)
   328 {
   329   last_output_context->file_attributes.keywords = keywords;
   330 }
   332 void output_set_bookmark (char *name)
   333 {
   334   bookmark_t *new_bookmark;
   336   /* As the language is defined (parser.y), a bookmark can only appear
   337      at the beginning of a context! */
   338   if (last_output_context->page_count)
   339     {
   340       fprintf (stderr, "internal error, bookmark not at beginning of context\n");
   341       exit (2);
   342     }
   344   new_bookmark = calloc (1, sizeof (bookmark_t));
   345   if (! new_bookmark)
   346     {
   347       fprintf (stderr, "failed to calloc a bookmark\n");
   348       return;
   349     }
   351   new_bookmark->level = bookmark_level;
   352   new_bookmark->name = name;
   353   if (last_output_context->first_bookmark)
   354     last_output_context->last_bookmark->next = new_bookmark;
   355   else
   356     last_output_context->first_bookmark = new_bookmark;
   357   last_output_context->last_bookmark = new_bookmark;
   358 }
   360 void output_set_page_label (page_label_t label)
   361 {
   362   output_clone ();
   363   last_output_context->has_page_label = 1;
   364   last_output_context->page_label = label;
   365 }
   367 static void increment_output_page_count (int count)
   368 {
   369   output_context_t *context;
   371   for (context = last_output_context; context; context = context->parent)
   372     context->page_count += count;
   373 }
   376 void output_pages (range_t range)
   377 {
   378   output_page_t *new_page;
   379   output_context_t *context;
   380   int count = ((range.last - range.first) + 1);
   382 #ifdef SEMANTIC_DEBUG
   383   if (range.first == range.last)
   384     SDBG(("page %d\n", range.first));
   385   else
   386     SDBG(("pages %d..%d\n", range.first, range.last));
   387 #endif /* SEMANTIC_DEBUG */
   389   new_page = calloc (1, sizeof (output_page_t));
   390   if (! new_page)
   391     {
   392       fprintf (stderr, "failed to malloc an output page struct\n");
   393       return;
   394     }
   395   if (first_output_page)
   396     {
   397       last_output_page->next = new_page;
   398       last_output_page = new_page;
   399     }
   400   else
   401     {
   402       first_output_page = last_output_page = new_page;
   403     }
   404   new_page->range = range;
   405   new_page->output_context = last_output_context;
   407   /* transfer bookmarks from context(s) to page */
   408   for (context = last_output_context; context; context = context->parent)
   409     if (context->first_bookmark)
   410       {
   411 	context->last_bookmark->next = new_page->bookmark_list;
   412 	new_page->bookmark_list = context->first_bookmark;
   413 	context->first_bookmark = NULL;
   414 	context->last_bookmark = NULL;
   415       }
   417   increment_output_page_count (count);
   418 }
   421 void yyerror (char *s)
   422 {
   423   fprintf (stderr, "%d: %s\n", line, s);
   424 }
   427 static char *get_input_file (input_context_t *context)
   428 {
   429   for (; context; context = context->parent)
   430     if (context->input_file)
   431       return (context->input_file);
   432   fprintf (stderr, "no input file name found\n");
   433   exit (2);
   434 }
   436 static bool get_input_rotation (input_context_t *context,
   437 				input_modifier_type_t type,
   438 				int *rotation)
   439 {
   440   for (; context; context = context->parent)
   441     {
   442       if (context->modifiers [type].has_rotation)
   443 	{
   444 	  * rotation = context->modifiers [type].rotation;
   445 	  return (1);
   446 	}
   447       if (context->modifiers [INPUT_MODIFIER_ALL].has_rotation)
   448 	{
   449 	  * rotation = context->modifiers [INPUT_MODIFIER_ALL].rotation;
   450 	  return (1);
   451 	}
   452     }
   453   return (0);  /* default */
   454 }
   456 static bool get_input_page_size (input_context_t *context,
   457 				 input_modifier_type_t type,
   458 				 page_size_t *page_size)
   459 {
   460   for (; context; context = context->parent)
   461     {
   462       if (context->modifiers [type].has_page_size)
   463 	{
   464 	  * page_size = context->modifiers [type].page_size;
   465 	  return (1);
   466 	}
   467       if (context->modifiers [INPUT_MODIFIER_ALL].has_page_size)
   468 	{
   469 	  * page_size = context->modifiers [INPUT_MODIFIER_ALL].page_size;
   470 	  return (1);
   471 	}
   472     }
   473   return (0);  /* default */
   474 }
   476 static char *get_output_file (output_context_t *context)
   477 {
   478   for (; context; context = context->parent)
   479     if (context->output_file)
   480       return (context->output_file);
   481   fprintf (stderr, "no output file found\n");
   482   exit (2);
   483 }
   485 static pdf_file_attributes_t *get_output_file_attributes (output_context_t *context)
   486 {
   487   for (; context; context = context->parent)
   488     if (context->output_file)
   489       return (& context->file_attributes);
   490   fprintf (stderr, "no output file found\n");
   491   exit (2);
   492 }
   494 static page_label_t *get_output_page_label (output_context_t *context)
   495 {
   496   for (; context; context = context->parent)
   497     if (context->has_page_label)
   498       return (& context->page_label);
   499   return (NULL);  /* default */
   500 }
   503 #ifdef SEMANTIC_DEBUG
   504 void dump_input_tree (void)
   505 {
   506   input_image_t *image;
   507   int i;
   509   printf ("input images:\n");
   510   for (image = first_input_image; image; image = image->next)
   511     for (i = image->range.first; i <= image->range.last; i++)
   512       {
   513 	input_modifier_type_t parity = (i % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
   514 	bool has_rotation, has_page_size;
   515 	int rotation;
   516 	page_size_t page_size;
   518 	has_rotation = get_input_rotation (image->input_context,
   519 					   parity,
   520 					   & rotation);
   521 	has_page_size = get_input_page_size (image->input_context,
   522 					     parity,
   523 					     & page_size);
   524 	printf ("file '%s' image %d",
   525 	        get_input_file (image->input_context),
   526 		i);
   527 	if (has_rotation)
   528 	  printf (" rotation %d", rotation);
   529 	if (has_page_size)
   530 	  printf (" size %f, %f", page_size.width, page_size.height);
   531 	printf ("\n");
   532 	printf ("context: %08x\n", image->input_context);
   533       }
   534 }
   536 void dump_output_tree (void)
   537 {
   538   int i;
   539   output_page_t *page;
   540   bookmark_t *bookmark;
   542   printf ("output pages:\n");
   543   for (page = first_output_page; page; page = page->next)
   544     {
   545       if (page->bookmark_list)
   546 	{
   547 	  for (bookmark = page->bookmark_list; bookmark; bookmark = bookmark->next)
   548 	    printf ("bookmark %d \"%s\"\n", bookmark->level, bookmark->name);
   549 	}
   550       for (i = page->range.first; i <= page->range.last; i++)
   551 	{
   552 	  page_label_t *label = get_output_page_label (page->output_context);
   553 	  printf ("file \"%s\" ", get_output_file (page->output_context));
   554 	  if (label)
   555 	    {
   556 	      printf ("label ");
   557 	      if (label->prefix)
   558 		printf ("\"%s\" ", label->prefix);
   559 	      if (label->style)
   560 		printf ("'%c' ", label->style);
   561 	    }
   562 	  printf ("page %d\n", i);
   563 	}
   564     }
   565 }
   566 #endif /* SEMANTIC_DEBUG */
   569 static inline int range_count (range_t range)
   570 {
   571   return ((range.last - range.first) + 1);
   572 }
   575 bool parse_spec_file (char *fn)
   576 {
   577   bool result = 0;
   579   yyin = fopen (fn, "r");
   580   if (! yyin)
   581     {
   582       fprintf (stderr, "can't open spec file '%s'\n", fn);
   583       goto fail;
   584     }
   586   line = 1;
   588   input_push_context ();  /* create root input context */
   589   input_push_context ();  /* create inital input context */
   591   output_push_context ();  /* create root output context */
   592   output_push_context ();  /* create initial output context */
   594   yyparse ();
   596   if (first_input_context->image_count != first_output_context->page_count)
   597     {
   598       fprintf (stderr, "input image count %d != output page count %d\n",
   599 	       first_input_context->image_count,
   600 	       first_output_context->page_count);
   601       goto fail;
   602     }
   604   fprintf (stderr, "%d pages specified\n", first_input_context->image_count);
   606   result = 1;
   608 #ifdef SEMANTIC_DEBUG
   609   dump_input_tree ();
   610   dump_output_tree ();
   611 #endif /* SEMANTIC_DEBUG */
   613  fail:
   614   if (yyin)
   615     fclose (yyin);
   617   return (result);
   618 }
   621 bool process_specs (void)
   622 {
   623   input_image_t *image = NULL;
   624   output_page_t *page = NULL;
   625   int i = 0;
   626   int p = 0;
   627   int page_index = 0;
   628   input_attributes_t input_attributes;
   629   input_modifier_type_t parity;
   630   page_label_t *page_label;
   632   for (;;)
   633     {
   634       if ((! image) || (i >= range_count (image->range)))
   635 	{
   636 	  if (image)
   637 	    image = image->next;
   638 	  else
   639 	    image = first_input_image;
   640 	  if (! image)
   641 	    return (0);
   642 	  i = 0;
   643 	  if (! open_tiff_input_file (get_input_file (image->input_context)))
   644 	    return (0);
   645 	}
   647       if ((! page) || (p >= range_count (page->range)))
   648 	{
   649 	  if (page)
   650 	    page = page->next;
   651 	  else
   652 	    page = first_output_page;
   653 	  p = 0;
   654 	  if (! open_pdf_output_file (get_output_file (page->output_context),
   655 				      get_output_file_attributes (page->output_context)))
   656 	    return (0);
   657 	  page_label = get_output_page_label (page->output_context);
   658 	  process_page_numbers (page_index,
   659 				range_count (page->range),
   660 				page->range.first,
   661 				page_label);
   662 	}
   664       parity = ((image->range.first + i) % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
   666       memset (& input_attributes, 0, sizeof (input_attributes));
   668       input_attributes.rotation = 0;
   669       input_attributes.has_rotation = get_input_rotation (image->input_context,
   670 							  parity,
   671 							  & input_attributes.rotation);
   673       input_attributes.has_page_size = get_input_page_size (image->input_context,
   674 							    parity,
   675 							    & input_attributes.page_size);
   677       process_page (image->range.first + i,
   678 		    input_attributes,
   679 		    page->bookmark_list);
   680       i++;
   681       p++;
   682       page_index++;
   683     }
   685   return (1);
   686 }