semantics.c

Tue, 01 Jan 2002 10:16:50 +0000

author
eric
date
Tue, 01 Jan 2002 10:16:50 +0000
changeset 32
3aac131058da
parent 30
35fad7ec7732
child 36
a338db73c6f4
permissions
-rw-r--r--

added start of page size support.

     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_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 #define SEMANTIC_DEBUG
    75 #ifdef SEMANTIC_DEBUG
    76 #define SDBG(x) printf x
    77 #else
    78 #define SDBG(x)
    79 #endif
    82 FILE *yyin;
    83 int line;  /* line number in spec file */
    85 int bookmark_level;
    87 input_context_t *first_input_context;
    88 input_context_t *last_input_context;
    90 input_modifier_type_t current_modifier_context;
    92 input_image_t *first_input_image;
    93 input_image_t *last_input_image;
    95 output_context_t *first_output_context;
    96 output_context_t *last_output_context;
    98 output_page_t *first_output_page;
    99 output_page_t *last_output_page;
   102 void input_push_context (void)
   103 {
   104   input_context_t *new_input_context;
   106   new_input_context = malloc (sizeof (input_context_t));
   107   if (! new_input_context)
   108     {
   109       fprintf (stderr, "failed to malloc an input context\n");
   110       return;
   111     }
   113   if (last_input_context)
   114     {
   115       memcpy (new_input_context, last_input_context, sizeof (input_context_t));
   116       new_input_context->image_count = 0;
   117     }
   118   else
   119     {
   120       memset (new_input_context, 0, sizeof (input_context_t));
   121       first_input_context = new_input_context;
   122     }
   124   new_input_context->parent = last_input_context;
   125   last_input_context = new_input_context;
   126 };
   128 void input_pop_context (void)
   129 {
   130   if (! last_input_context)
   131     {
   132       fprintf (stderr, "failed to pop an input context\n");
   133       return;
   134     }
   136   last_input_context = last_input_context->parent;
   137 };
   139 void input_set_modifier_context (input_modifier_type_t type)
   140 {
   141   current_modifier_context = type;
   142 #ifdef SEMANTIC_DEBUG
   143   SDBG(("modifier type "));
   144   switch (type)
   145     {
   146     case INPUT_MODIFIER_ALL: SDBG(("all")); break;
   147     case INPUT_MODIFIER_ODD: SDBG(("odd")); break;
   148     case INPUT_MODIFIER_EVEN: SDBG(("even")); break;
   149     default: SDBG(("unknown %d", type));
   150     }
   151   SDBG(("\n"));
   152 #endif /* SEMANTIC_DEBUG */
   153 }
   155 static void input_clone (void)
   156 {
   157   input_context_t *new_input_context;
   159   if (! last_input_context->image_count)
   160     return;
   162   new_input_context = malloc (sizeof (input_context_t));
   163   if (! new_input_context)
   164     {
   165       fprintf (stderr, "failed to malloc an input context\n");
   166       return;
   167     }
   169   memcpy (new_input_context, last_input_context, sizeof (input_context_t));
   170   new_input_context->image_count = 0;
   171   last_input_context->next = new_input_context;
   172 }
   174 void input_set_file (char *name)
   175 {
   176   input_clone ();
   177   last_input_context->input_file = name;
   178 };
   180 void input_set_rotation (int rotation)
   181 {
   182   last_input_context->modifiers [current_modifier_context].has_rotation = 1;
   183   last_input_context->modifiers [current_modifier_context].rotation = rotation;
   184   SDBG(("rotation %d\n", rotation));
   185 }
   187 void input_set_page_size (page_size_t size)
   188 {
   189   last_input_context->modifiers [current_modifier_context].has_page_size = 1;
   190   last_input_context->modifiers [current_modifier_context].page_size = size;
   191   printf ("page size %f, %f\n", size.width, size.height);
   192   SDBG(("page size %f, %f\n", size.width, size.height));
   193 }
   195 static void increment_input_image_count (int count)
   196 {
   197   input_context_t *context;
   199   for (context = last_input_context; context; context = context->parent)
   200     context->image_count += count;
   201 }
   203 void input_images (range_t range)
   204 {
   205   input_image_t *new_image;
   206   int count = ((range.last - range.first) + 1);
   208 #ifdef SEMANTIC_DEBUG
   209   if (range.first == range.last)
   210     SDBG(("image %d\n", range.first));
   211   else
   212     SDBG(("images %d..%d\n", range.first, range.last));
   213 #endif /* SEMANTIC_DEBUG */
   215   new_image = calloc (1, sizeof (input_image_t));
   216   if (! new_image)
   217     {
   218       fprintf (stderr, "failed to malloc an input image struct\n");
   219       return;
   220     }
   221   if (first_input_image)
   222     {
   223       last_input_image->next = new_image;
   224       last_input_image = new_image;
   225     }
   226   else
   227     {
   228       first_input_image = last_input_image = new_image;
   229     }
   230   new_image->range = range;
   231   new_image->input_context = last_input_context;
   232   increment_input_image_count (count);
   233 }
   236 void output_push_context (void)
   237 {
   238   output_context_t *new_output_context;
   240   new_output_context = malloc (sizeof (output_context_t));
   241   if (! new_output_context)
   242     {
   243       fprintf (stderr, "failed to malloc an output context\n");
   244       return;
   245     }
   247   if (last_output_context)
   248     {
   249       memcpy (new_output_context, last_output_context, sizeof (output_context_t));
   250       new_output_context->page_count = 0;
   251       new_output_context->first_bookmark = NULL;
   252       new_output_context->last_bookmark = NULL;
   253     }
   254   else
   255     {
   256       memset (new_output_context, 0, sizeof (output_context_t));
   257       first_output_context = new_output_context;
   258     }
   260   new_output_context->parent = last_output_context;
   261   last_output_context = new_output_context;
   262 };
   264 void output_pop_context (void)
   265 {
   266   if (! last_output_context)
   267     {
   268       fprintf (stderr, "failed to pop an output context\n");
   269       return;
   270     }
   272   last_output_context = last_output_context->parent;
   273 };
   275 static void output_clone (void)
   276 {
   277   output_context_t *new_output_context;
   279   if (! last_output_context->page_count)
   280     return;
   282   new_output_context = malloc (sizeof (output_context_t));
   283   if (! new_output_context)
   284     {
   285       fprintf (stderr, "failed to malloc an output context\n");
   286       return;
   287     }
   289   memcpy (new_output_context, last_output_context, sizeof (output_context_t));
   290   new_output_context->page_count = 0;
   291   last_output_context->next = new_output_context;
   292 }
   294 void output_set_file (char *name)
   295 {
   296   output_clone ();
   297   last_output_context->output_file = name;
   298   last_output_context->file_attributes.author = NULL;
   299   last_output_context->file_attributes.creator = NULL;
   300   last_output_context->file_attributes.title = NULL;
   301   last_output_context->file_attributes.subject = NULL;
   302   last_output_context->file_attributes.keywords = NULL;
   303 };
   305 void output_set_author (char *author)
   306 {
   307   last_output_context->file_attributes.author = author;
   308 }
   310 void output_set_creator (char *creator)
   311 {
   312   last_output_context->file_attributes.creator = creator;
   313 }
   315 void output_set_title (char *title)
   316 {
   317   last_output_context->file_attributes.title = title;
   318 }
   320 void output_set_subject (char *subject)
   321 {
   322   last_output_context->file_attributes.subject = subject;
   323 }
   325 void output_set_keywords (char *keywords)
   326 {
   327   last_output_context->file_attributes.keywords = keywords;
   328 }
   330 void output_set_bookmark (char *name)
   331 {
   332   bookmark_t *new_bookmark;
   334   /* As the language is defined (parser.y), a bookmark can only appear
   335      at the beginning of a context! */
   336   if (last_output_context->page_count)
   337     {
   338       fprintf (stderr, "internal error, bookmark not at beginning of context\n");
   339       exit (2);
   340     }
   342   new_bookmark = calloc (1, sizeof (bookmark_t));
   343   if (! new_bookmark)
   344     {
   345       fprintf (stderr, "failed to calloc a bookmark\n");
   346       return;
   347     }
   349   new_bookmark->level = bookmark_level;
   350   new_bookmark->name = name;
   351   if (last_output_context->first_bookmark)
   352     last_output_context->last_bookmark->next = new_bookmark;
   353   else
   354     last_output_context->first_bookmark = new_bookmark;
   355   last_output_context->last_bookmark = new_bookmark;
   356 }
   358 void output_set_page_label (page_label_t label)
   359 {
   360   output_clone ();
   361   last_output_context->has_page_label = 1;
   362   last_output_context->page_label = label;
   363 }
   365 static void increment_output_page_count (int count)
   366 {
   367   output_context_t *context;
   369   for (context = last_output_context; context; context = context->parent)
   370     context->page_count += count;
   371 }
   374 void output_pages (range_t range)
   375 {
   376   output_page_t *new_page;
   377   output_context_t *context;
   378   int count = ((range.last - range.first) + 1);
   380 #ifdef SEMANTIC_DEBUG
   381   if (range.first == range.last)
   382     SDBG(("page %d\n", range.first));
   383   else
   384     SDBG(("pages %d..%d\n", range.first, range.last));
   385 #endif /* SEMANTIC_DEBUG */
   387   new_page = calloc (1, sizeof (output_page_t));
   388   if (! new_page)
   389     {
   390       fprintf (stderr, "failed to malloc an output page struct\n");
   391       return;
   392     }
   393   if (first_output_page)
   394     {
   395       last_output_page->next = new_page;
   396       last_output_page = new_page;
   397     }
   398   else
   399     {
   400       first_output_page = last_output_page = new_page;
   401     }
   402   new_page->range = range;
   403   new_page->output_context = last_output_context;
   405   /* transfer bookmarks from context(s) to page */
   406   for (context = last_output_context; context; context = context->parent)
   407     if (context->first_bookmark)
   408       {
   409 	context->last_bookmark->next = new_page->bookmark_list;
   410 	new_page->bookmark_list = context->first_bookmark;
   411 	context->first_bookmark = NULL;
   412 	context->last_bookmark = NULL;
   413       }
   415   increment_output_page_count (count);
   416 }
   419 void yyerror (char *s)
   420 {
   421   fprintf (stderr, "%d: %s\n", line, s);
   422 }
   425 static char *get_input_file (input_context_t *context)
   426 {
   427   for (; context; context = context->parent)
   428     if (context->input_file)
   429       return (context->input_file);
   430   fprintf (stderr, "no input file name found\n");
   431   exit (2);
   432 }
   434 static boolean get_input_rotation (input_context_t *context,
   435 				   input_modifier_type_t type,
   436 				   int *rotation)
   437 {
   438   for (; context; context = context->parent)
   439     {
   440       if (context->modifiers [type].has_rotation)
   441 	{
   442 	  * rotation = context->modifiers [type].rotation;
   443 	  return (1);
   444 	}
   445       if (context->modifiers [INPUT_MODIFIER_ALL].has_rotation)
   446 	{
   447 	  * rotation = context->modifiers [INPUT_MODIFIER_ALL].rotation;
   448 	  return (1);
   449 	}
   450     }
   451   return (0);  /* default */
   452 }
   454 static boolean get_input_page_size (input_context_t *context,
   455 				    input_modifier_type_t type,
   456 				    page_size_t *page_size)
   457 {
   458   for (; context; context = context->parent)
   459     {
   460       if (context->modifiers [type].has_page_size)
   461 	{
   462 	  * page_size = context->modifiers [type].page_size;
   463 	  return (1);
   464 	}
   465       if (context->modifiers [INPUT_MODIFIER_ALL].has_page_size)
   466 	{
   467 	  * page_size = context->modifiers [INPUT_MODIFIER_ALL].page_size;
   468 	  return (1);
   469 	}
   470     }
   471   return (0);  /* default */
   472 }
   474 static char *get_output_file (output_context_t *context)
   475 {
   476   for (; context; context = context->parent)
   477     if (context->output_file)
   478       return (context->output_file);
   479   fprintf (stderr, "no output file found\n");
   480   exit (2);
   481 }
   483 static pdf_file_attributes_t *get_output_file_attributes (output_context_t *context)
   484 {
   485   for (; context; context = context->parent)
   486     if (context->output_file)
   487       return (& context->file_attributes);
   488   fprintf (stderr, "no output file found\n");
   489   exit (2);
   490 }
   492 static page_label_t *get_output_page_label (output_context_t *context)
   493 {
   494   for (; context; context = context->parent)
   495     if (context->has_page_label)
   496       return (& context->page_label);
   497   return (NULL);  /* default */
   498 }
   501 #ifdef SEMANTIC_DEBUG
   502 void dump_input_tree (void)
   503 {
   504   input_image_t *image;
   505   int i;
   507   printf ("input images:\n");
   508   for (image = first_input_image; image; image = image->next)
   509     for (i = image->range.first; i <= image->range.last; i++)
   510       {
   511 	input_modifier_type_t parity = (i % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
   512 	boolean has_rotation, has_page_size;
   513 	int rotation;
   514 	page_size_t page_size;
   516 	has_rotation = get_input_rotation (image->input_context,
   517 					   parity,
   518 					   & rotation);
   519 	has_page_size = get_input_page_size (image->input_context,
   520 					     parity,
   521 					     & page_size);
   522 	printf ("file '%s' image %d",
   523 	        get_input_file (image->input_context),
   524 		i);
   525 	if (has_rotation)
   526 	  printf (" rotation %d", rotation);
   527 	if (has_page_size)
   528 	  printf (" size %f, %f", page_size.width, page_size.height);
   529 	printf ("\n");
   530       }
   531 }
   533 void dump_output_tree (void)
   534 {
   535   int i;
   536   output_page_t *page;
   537   bookmark_t *bookmark;
   539   printf ("output pages:\n");
   540   for (page = first_output_page; page; page = page->next)
   541     {
   542       if (page->bookmark_list)
   543 	{
   544 	  for (bookmark = page->bookmark_list; bookmark; bookmark = bookmark->next)
   545 	    printf ("bookmark %d \"%s\"\n", bookmark->level, bookmark->name);
   546 	}
   547       for (i = page->range.first; i <= page->range.last; i++)
   548 	{
   549 	  page_label_t *label = get_output_page_label (page->output_context);
   550 	  printf ("file \"%s\" ", get_output_file (page->output_context));
   551 	  if (label)
   552 	    {
   553 	      printf ("label ");
   554 	      if (label->prefix)
   555 		printf ("\"%s\" ", label->prefix);
   556 	      if (label->style)
   557 		printf ("'%c' ", label->style);
   558 	    }
   559 	  printf ("page %d\n", i);
   560 	}
   561     }
   562 }
   563 #endif /* SEMANTIC_DEBUG */
   566 static inline int range_count (range_t range)
   567 {
   568   return ((range.last - range.first) + 1);
   569 }
   572 boolean parse_spec_file (char *fn)
   573 {
   574   boolean result = 0;
   576   yyin = fopen (fn, "r");
   577   if (! yyin)
   578     {
   579       fprintf (stderr, "can't open spec file '%s'\n", fn);
   580       goto fail;
   581     }
   583   line = 1;
   585   input_push_context ();  /* create root input context */
   586   input_push_context ();  /* create inital input context */
   588   output_push_context ();  /* create root output context */
   589   output_push_context ();  /* create initial output context */
   591   yyparse ();
   593   if (first_input_context->image_count != first_output_context->page_count)
   594     {
   595       fprintf (stderr, "input image count %d != output page count %d\n",
   596 	       first_input_context->image_count,
   597 	       first_output_context->page_count);
   598       goto fail;
   599     }
   601   fprintf (stderr, "%d pages specified\n", first_input_context->image_count);
   603   result = 1;
   605 #ifdef SEMANTIC_DEBUG
   606   dump_input_tree ();
   607   dump_output_tree ();
   608 #endif /* SEMANTIC_DEBUG */
   610  fail:
   611   if (yyin)
   612     fclose (yyin);
   614   return (result);
   615 }
   618 boolean process_specs (void)
   619 {
   620   input_image_t *image = NULL;
   621   output_page_t *page = NULL;
   622   int i = 0;
   623   int p = 0;
   624   int page_index = 0;
   625   input_attributes_t input_attributes;
   626   input_modifier_type_t parity;
   627   page_label_t *page_label;
   629   for (;;)
   630     {
   631       if ((! image) || (i >= range_count (image->range)))
   632 	{
   633 	  if (image)
   634 	    image = image->next;
   635 	  else
   636 	    image = first_input_image;
   637 	  if (! image)
   638 	    return (0);
   639 	  i = 0;
   640 	  if (! open_tiff_input_file (get_input_file (image->input_context)))
   641 	    return (0);
   642 	}
   644       if ((! page) || (p >= range_count (page->range)))
   645 	{
   646 	  if (page)
   647 	    page = page->next;
   648 	  else
   649 	    page = first_output_page;
   650 	  p = 0;
   651 	  if (! open_pdf_output_file (get_output_file (page->output_context),
   652 				      get_output_file_attributes (page->output_context)))
   653 	    return (0);
   654 	  page_label = get_output_page_label (page->output_context);
   655 	  process_page_numbers (page_index,
   656 				range_count (page->range),
   657 				page->range.first,
   658 				page_label);
   659 	}
   661       parity = ((image->range.first + i) % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
   663       memset (& input_attributes, 0, sizeof (input_attributes));
   665       input_attributes.rotation = 0;
   666       input_attributes.has_rotation = get_input_rotation (image->input_context,
   667 							  parity,
   668 							  & input_attributes.rotation);
   670       input_attributes.has_page_size = get_input_page_size (image->input_context,
   671 							    parity,
   672 							    & input_attributes.page_size);
   674       process_page (image->range.first + i,
   675 		    input_attributes,
   676 		    page->bookmark_list);
   677       i++;
   678       p++;
   679       page_index++;
   680     }
   682   return (1);
   683 }