semantics.c

Mon, 31 Dec 2001 08:25:04 +0000

author
eric
date
Mon, 31 Dec 2001 08:25:04 +0000
changeset 24
6575fcfbdb1b
parent 22
198616589af5
child 25
139b91f9a224
permissions
-rw-r--r--

track bookmark level.

     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"
    10 typedef struct
    11 {
    12   boolean has_size;
    13   page_size_t size;
    15   boolean has_rotation;
    16   int rotation;
    18   boolean has_crop;
    19   crop_t crop;
    20 } input_modifiers_t;
    23 typedef struct input_context_t
    24 {
    25   struct input_context_t *parent;
    26   struct input_context_t *next;
    28   int image_count;  /* how many pages reference this context,
    29 		      including those from subcontexts */
    31   char *input_file;
    33   input_modifiers_t modifiers [INPUT_MODIFIER_TYPE_COUNT];
    34 } input_context_t;
    37 typedef struct input_image_t
    38 {
    39   struct input_image_t *next;
    40   input_context_t *input_context;
    41   range_t range;
    42 } input_image_t;
    45 typedef struct output_context_t
    46 {
    47   struct output_context_t *parent;
    48   struct output_context_t *next;
    50   int page_count;  /* how many pages reference this context,
    51 		      including those from subcontexts */
    53   char *output_file;
    54   bookmark_t *first_bookmark;
    55   bookmark_t *last_bookmark;
    56   char *page_number_format;
    57 } output_context_t;
    60 typedef struct output_page_t
    61 {
    62   struct output_page_t *next;
    63   output_context_t *output_context;
    64   range_t range;
    65   bookmark_t *bookmark_list;
    66 } output_page_t;
    69 #define SEMANTIC_DEBUG
    70 #ifdef SEMANTIC_DEBUG
    71 #define SDBG(x) printf x
    72 #else
    73 #define SDBG(x)
    74 #endif
    77 FILE *yyin;
    78 int line;  /* line number in spec file */
    80 int bookmark_level;
    82 input_context_t *first_input_context;
    83 input_context_t *last_input_context;
    85 input_modifier_type_t current_modifier_context;
    87 input_image_t *first_input_image;
    88 input_image_t *last_input_image;
    90 output_context_t *first_output_context;
    91 output_context_t *last_output_context;
    93 output_page_t *first_output_page;
    94 output_page_t *last_output_page;
    97 void input_push_context (void)
    98 {
    99   input_context_t *new_input_context;
   101   new_input_context = malloc (sizeof (input_context_t));
   102   if (! new_input_context)
   103     {
   104       fprintf (stderr, "failed to malloc an input context\n");
   105       return;
   106     }
   108   if (last_input_context)
   109     {
   110       memcpy (new_input_context, last_input_context, sizeof (input_context_t));
   111       new_input_context->image_count = 0;
   112     }
   113   else
   114     {
   115       memset (new_input_context, 0, sizeof (input_context_t));
   116       first_input_context = new_input_context;
   117     }
   119   new_input_context->parent = last_input_context;
   120   last_input_context = new_input_context;
   121 };
   123 void input_pop_context (void)
   124 {
   125   if (! last_input_context)
   126     {
   127       fprintf (stderr, "failed to pop an input context\n");
   128       return;
   129     }
   131   last_input_context = last_input_context->parent;
   132 };
   134 void input_set_modifier_context (input_modifier_type_t type)
   135 {
   136   current_modifier_context = type;
   137 #ifdef SEMANTIC_DEBUG
   138   SDBG(("modifier type "));
   139   switch (type)
   140     {
   141     case INPUT_MODIFIER_ALL: SDBG(("all")); break;
   142     case INPUT_MODIFIER_ODD: SDBG(("odd")); break;
   143     case INPUT_MODIFIER_EVEN: SDBG(("even")); break;
   144     default: SDBG(("unknown %d", type));
   145     }
   146   SDBG(("\n"));
   147 #endif /* SEMANTIC_DEBUG */
   148 }
   150 static void input_clone (void)
   151 {
   152   input_context_t *new_input_context;
   154   if (! last_input_context->image_count)
   155     return;
   157   new_input_context = malloc (sizeof (input_context_t));
   158   if (! new_input_context)
   159     {
   160       fprintf (stderr, "failed to malloc an input context\n");
   161       return;
   162     }
   164   memcpy (new_input_context, last_input_context, sizeof (input_context_t));
   165   new_input_context->image_count = 0;
   166   last_input_context->next = new_input_context;
   167 }
   169 void input_set_file (char *name)
   170 {
   171   input_clone ();
   172   last_input_context->input_file = name;
   173 };
   175 void input_set_rotation (int rotation)
   176 {
   177   last_input_context->modifiers [current_modifier_context].has_rotation = 1;
   178   last_input_context->modifiers [current_modifier_context].rotation = rotation;
   179   SDBG(("rotation %d\n", rotation));
   180 }
   182 static void increment_input_image_count (int count)
   183 {
   184   input_context_t *context;
   186   for (context = last_input_context; context; context = context->parent)
   187     context->image_count += count;
   188 }
   190 void input_images (range_t range)
   191 {
   192   input_image_t *new_image;
   193   int count = ((range.last - range.first) + 1);
   195 #ifdef SEMANTIC_DEBUG
   196   if (range.first == range.last)
   197     SDBG(("image %d\n", range.first));
   198   else
   199     SDBG(("images %d..%d\n", range.first, range.last));
   200 #endif /* SEMANTIC_DEBUG */
   202   new_image = calloc (1, sizeof (input_image_t));
   203   if (! new_image)
   204     {
   205       fprintf (stderr, "failed to malloc an input image struct\n");
   206       return;
   207     }
   208   if (first_input_image)
   209     {
   210       last_input_image->next = new_image;
   211       last_input_image = new_image;
   212     }
   213   else
   214     {
   215       first_input_image = last_input_image = new_image;
   216     }
   217   new_image->range = range;
   218   new_image->input_context = last_input_context;
   219   increment_input_image_count (count);
   220 }
   223 void output_push_context (void)
   224 {
   225   output_context_t *new_output_context;
   227   new_output_context = malloc (sizeof (output_context_t));
   228   if (! new_output_context)
   229     {
   230       fprintf (stderr, "failed to malloc an output context\n");
   231       return;
   232     }
   234   if (last_output_context)
   235     {
   236       memcpy (new_output_context, last_output_context, sizeof (output_context_t));
   237       new_output_context->page_count = 0;
   238       new_output_context->first_bookmark = NULL;
   239       new_output_context->last_bookmark = NULL;
   240     }
   241   else
   242     {
   243       memset (new_output_context, 0, sizeof (output_context_t));
   244       first_output_context = new_output_context;
   245     }
   247   new_output_context->parent = last_output_context;
   248   last_output_context = new_output_context;
   249 };
   251 void output_pop_context (void)
   252 {
   253   if (! last_output_context)
   254     {
   255       fprintf (stderr, "failed to pop an output context\n");
   256       return;
   257     }
   259   last_output_context = last_output_context->parent;
   260 };
   262 static void output_clone (void)
   263 {
   264   output_context_t *new_output_context;
   266   if (! last_output_context->page_count)
   267     return;
   269   new_output_context = malloc (sizeof (output_context_t));
   270   if (! new_output_context)
   271     {
   272       fprintf (stderr, "failed to malloc an output context\n");
   273       return;
   274     }
   276   memcpy (new_output_context, last_output_context, sizeof (output_context_t));
   277   new_output_context->page_count = 0;
   278   last_output_context->next = new_output_context;
   279 }
   281 void output_set_file (char *name)
   282 {
   283   output_clone ();
   284   last_output_context->output_file = name;
   285 };
   287 void output_set_bookmark (char *name)
   288 {
   289   bookmark_t *new_bookmark;
   291   /* As the language is defined (parser.y), a bookmark can only appear
   292      at the beginning of a context! */
   293   if (last_output_context->page_count)
   294     {
   295       fprintf (stderr, "internal error, bookmark not at beginning of context\n");
   296       exit (2);
   297     }
   299   new_bookmark = calloc (1, sizeof (bookmark_t));
   300   if (! new_bookmark)
   301     {
   302       fprintf (stderr, "failed to calloc a bookmark\n");
   303       return;
   304     }
   306   new_bookmark->level = bookmark_level;
   307   new_bookmark->name = name;
   308   if (last_output_context->first_bookmark)
   309     last_output_context->last_bookmark->next = new_bookmark;
   310   else
   311     last_output_context->first_bookmark = new_bookmark;
   312   last_output_context->last_bookmark = new_bookmark;
   313 }
   315 void output_set_page_number_format (char *format)
   316 {
   317   output_clone ();
   318   last_output_context->page_number_format = format;
   319 }
   321 static void increment_output_page_count (int count)
   322 {
   323   output_context_t *context;
   325   for (context = last_output_context; context; context = context->parent)
   326     context->page_count += count;
   327 }
   330 void output_pages (range_t range)
   331 {
   332   output_page_t *new_page;
   333   output_context_t *context;
   334   int count = ((range.last - range.first) + 1);
   336 #ifdef SEMANTIC_DEBUG
   337   if (range.first == range.last)
   338     SDBG(("page %d\n", range.first));
   339   else
   340     SDBG(("pages %d..%d\n", range.first, range.last));
   341 #endif /* SEMANTIC_DEBUG */
   343   new_page = calloc (1, sizeof (output_page_t));
   344   if (! new_page)
   345     {
   346       fprintf (stderr, "failed to malloc an output page struct\n");
   347       return;
   348     }
   349   if (first_output_page)
   350     {
   351       last_output_page->next = new_page;
   352       last_output_page = new_page;
   353     }
   354   else
   355     {
   356       first_output_page = last_output_page = new_page;
   357     }
   358   new_page->range = range;
   359   new_page->output_context = last_output_context;
   361   /* transfer bookmarks from context(s) to page */
   362   for (context = last_output_context; context; context = context->parent)
   363     if (context->first_bookmark)
   364       {
   365 	context->last_bookmark->next = new_page->bookmark_list;
   366 	new_page->bookmark_list = context->first_bookmark;
   367 	context->first_bookmark = NULL;
   368 	context->last_bookmark = NULL;
   369       }
   371   increment_output_page_count (count);
   372 }
   375 void yyerror (char *s)
   376 {
   377   fprintf (stderr, "%d: %s\n", line, s);
   378 }
   381 static char *get_input_file (input_context_t *context)
   382 {
   383   for (; context; context = context->parent)
   384     if (context->input_file)
   385       return (context->input_file);
   386   fprintf (stderr, "no input file name found\n");
   387   exit (2);
   388 }
   390 static int get_input_rotation (input_context_t *context, input_modifier_type_t type)
   391 {
   392   for (; context; context = context->parent)
   393     {
   394       if (context->modifiers [type].has_rotation)
   395 	return (context->modifiers [type].rotation);
   396       if (context->modifiers [INPUT_MODIFIER_ALL].has_rotation)
   397 	return (context->modifiers [INPUT_MODIFIER_ALL].rotation);
   398     }
   399   return (0);  /* default */
   400 }
   402 static char *get_output_file (output_context_t *context)
   403 {
   404   for (; context; context = context->parent)
   405     if (context->output_file)
   406       return (context->output_file);
   407   fprintf (stderr, "no output file name found\n");
   408   exit (2);
   409 }
   411 static char *get_output_page_number_format (output_context_t *context)
   412 {
   413   for (; context; context = context->parent)
   414     if (context->page_number_format)
   415       return (context->page_number_format);
   416   return (NULL);  /* default */
   417 }
   420 #ifdef SEMANTIC_DEBUG
   421 void dump_input_tree (void)
   422 {
   423   input_image_t *image;
   424   int i;
   426   printf ("input images:\n");
   427   for (image = first_input_image; image; image = image->next)
   428     for (i = image->range.first; i <= image->range.last; i++)
   429       {
   430 	input_modifier_type_t parity = (i % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
   431 	printf ("file '%s' image %d, rotation %d\n",
   432 	        get_input_file (image->input_context),
   433 		i, 
   434 		get_input_rotation (image->input_context, parity));
   435       }
   436 }
   438 void dump_output_tree (void)
   439 {
   440   int i;
   441   output_page_t *page;
   442   bookmark_t *bookmark;
   444   printf ("output pages:\n");
   445   for (page = first_output_page; page; page = page->next)
   446     {
   447       if (page->bookmark_list)
   448 	{
   449 	  for (bookmark = page->bookmark_list; bookmark; bookmark = bookmark->next)
   450 	    printf ("bookmark %d '%s'\n", bookmark->level, bookmark->name);
   451 	}
   452       for (i = page->range.first; i <= page->range.last; i++)
   453 	{
   454 	  printf ("file '%s' ", get_output_file (page->output_context));
   455 	  printf ("format '%s' ", get_output_page_number_format (page->output_context));
   456 	  printf ("page %d\n", i);
   457 	}
   458     }
   459 }
   460 #endif /* SEMANTIC_DEBUG */
   462 boolean parse_spec_file (char *fn)
   463 {
   464   boolean result = 0;
   466   yyin = fopen (fn, "r");
   467   if (! yyin)
   468     {
   469       fprintf (stderr, "can't open spec file '%s'\n", fn);
   470       goto fail;
   471     }
   473   line = 1;
   475   input_push_context ();  /* create root input context */
   476   input_push_context ();  /* create inital input context */
   478   output_push_context ();  /* create root output context */
   479   output_push_context ();  /* create initial output context */
   481   yyparse ();
   483   if (first_input_context->image_count != first_output_context->page_count)
   484     {
   485       fprintf (stderr, "input image count %d != output page count %d\n",
   486 	       first_input_context->image_count,
   487 	       first_output_context->page_count);
   488       goto fail;
   489     }
   491   fprintf (stderr, "%d pages specified\n", first_input_context->image_count);
   493   result = 1;
   495 #ifdef SEMANTIC_DEBUG
   496   dump_input_tree ();
   497   dump_output_tree ();
   498 #endif /* SEMANTIC_DEBUG */
   500  fail:
   501   if (yyin)
   502     fclose (yyin);
   504   return (result);
   505 }