Mon, 31 Dec 2001 08:25:04 +0000
added input and output attribute structures as arguments to process_page().
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 bookmark_t
46 {
47 struct bookmark_t *next;
48 char *name;
49 } bookmark_t;
52 typedef struct output_context_t
53 {
54 struct output_context_t *parent;
55 struct output_context_t *next;
57 int page_count; /* how many pages reference this context,
58 including those from subcontexts */
60 char *output_file;
61 bookmark_t *first_bookmark;
62 bookmark_t *last_bookmark;
63 char *page_number_format;
64 } output_context_t;
67 typedef struct output_page_t
68 {
69 struct output_page_t *next;
70 output_context_t *output_context;
71 range_t range;
72 bookmark_t *bookmark_list;
73 } output_page_t;
76 #define 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 */
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 }
175 void input_set_file (char *name)
176 {
177 input_clone ();
178 last_input_context->input_file = name;
179 };
181 void input_set_rotation (int rotation)
182 {
183 last_input_context->modifiers [current_modifier_context].has_rotation = 1;
184 last_input_context->modifiers [current_modifier_context].rotation = rotation;
185 SDBG(("rotation %d\n", rotation));
186 }
188 static void increment_input_image_count (int count)
189 {
190 input_context_t *context;
192 for (context = last_input_context; context; context = context->parent)
193 context->image_count += count;
194 }
196 void input_images (range_t range)
197 {
198 input_image_t *new_image;
199 int count = ((range.last - range.first) + 1);
201 #ifdef SEMANTIC_DEBUG
202 if (range.first == range.last)
203 SDBG(("image %d\n", range.first));
204 else
205 SDBG(("images %d..%d\n", range.first, range.last));
206 #endif /* SEMANTIC_DEBUG */
208 new_image = calloc (1, sizeof (input_image_t));
209 if (! new_image)
210 {
211 fprintf (stderr, "failed to malloc an input image struct\n");
212 return;
213 }
214 if (first_input_image)
215 {
216 last_input_image->next = new_image;
217 last_input_image = new_image;
218 }
219 else
220 {
221 first_input_image = last_input_image = new_image;
222 }
223 new_image->range = range;
224 new_image->input_context = last_input_context;
225 increment_input_image_count (count);
226 }
229 void output_push_context (void)
230 {
231 output_context_t *new_output_context;
233 new_output_context = malloc (sizeof (output_context_t));
234 if (! new_output_context)
235 {
236 fprintf (stderr, "failed to malloc an output context\n");
237 return;
238 }
240 if (last_output_context)
241 {
242 memcpy (new_output_context, last_output_context, sizeof (output_context_t));
243 new_output_context->page_count = 0;
244 new_output_context->first_bookmark = NULL;
245 new_output_context->last_bookmark = NULL;
246 }
247 else
248 {
249 memset (new_output_context, 0, sizeof (output_context_t));
250 first_output_context = new_output_context;
251 }
253 new_output_context->parent = last_output_context;
254 last_output_context = new_output_context;
255 };
257 void output_pop_context (void)
258 {
259 if (! last_output_context)
260 {
261 fprintf (stderr, "failed to pop an output context\n");
262 return;
263 }
265 last_output_context = last_output_context->parent;
266 };
268 static void output_clone (void)
269 {
270 output_context_t *new_output_context;
272 if (! last_output_context->page_count)
273 return;
275 new_output_context = malloc (sizeof (output_context_t));
276 if (! new_output_context)
277 {
278 fprintf (stderr, "failed to malloc an output context\n");
279 return;
280 }
282 memcpy (new_output_context, last_output_context, sizeof (output_context_t));
283 new_output_context->page_count = 0;
284 last_output_context->next = new_output_context;
285 }
287 void output_set_file (char *name)
288 {
289 output_clone ();
290 last_output_context->output_file = name;
291 };
293 void output_set_bookmark (char *name)
294 {
295 bookmark_t *new_bookmark;
297 /* As the language is defined (parser.y), a bookmark can only appear
298 at the beginning of a context! */
299 if (last_output_context->page_count)
300 {
301 fprintf (stderr, "internal error, bookmark not at beginning of context\n");
302 exit (2);
303 }
305 new_bookmark = calloc (1, sizeof (bookmark_t));
306 if (! new_bookmark)
307 {
308 fprintf (stderr, "failed to calloc a bookmark\n");
309 return;
310 }
312 new_bookmark->name = name;
313 if (last_output_context->first_bookmark)
314 last_output_context->last_bookmark->next = new_bookmark;
315 else
316 last_output_context->first_bookmark = new_bookmark;
317 last_output_context->last_bookmark = new_bookmark;
318 }
320 void output_set_page_number_format (char *format)
321 {
322 output_clone ();
323 last_output_context->page_number_format = format;
324 }
326 static void increment_output_page_count (int count)
327 {
328 output_context_t *context;
330 for (context = last_output_context; context; context = context->parent)
331 context->page_count += count;
332 }
335 void output_pages (range_t range)
336 {
337 output_page_t *new_page;
338 output_context_t *context;
339 int count = ((range.last - range.first) + 1);
341 #ifdef SEMANTIC_DEBUG
342 if (range.first == range.last)
343 SDBG(("page %d\n", range.first));
344 else
345 SDBG(("pages %d..%d\n", range.first, range.last));
346 #endif /* SEMANTIC_DEBUG */
348 new_page = calloc (1, sizeof (output_page_t));
349 if (! new_page)
350 {
351 fprintf (stderr, "failed to malloc an output page struct\n");
352 return;
353 }
354 if (first_output_page)
355 {
356 last_output_page->next = new_page;
357 last_output_page = new_page;
358 }
359 else
360 {
361 first_output_page = last_output_page = new_page;
362 }
363 new_page->range = range;
364 new_page->output_context = last_output_context;
366 /* transfer bookmarks from context(s) to page */
367 for (context = last_output_context; context; context = context->parent)
368 if (context->first_bookmark)
369 {
370 context->last_bookmark->next = new_page->bookmark_list;
371 new_page->bookmark_list = context->first_bookmark;
372 context->first_bookmark = NULL;
373 context->last_bookmark = NULL;
374 }
376 increment_output_page_count (count);
377 }
380 void yyerror (char *s)
381 {
382 fprintf (stderr, "%d: %s\n", line, s);
383 }
386 static char *get_input_file (input_context_t *context)
387 {
388 for (; context; context = context->parent)
389 if (context->input_file)
390 return (context->input_file);
391 fprintf (stderr, "no input file name found\n");
392 exit (2);
393 }
395 static int get_input_rotation (input_context_t *context, input_modifier_type_t type)
396 {
397 for (; context; context = context->parent)
398 {
399 if (context->modifiers [type].has_rotation)
400 return (context->modifiers [type].rotation);
401 if (context->modifiers [INPUT_MODIFIER_ALL].has_rotation)
402 return (context->modifiers [INPUT_MODIFIER_ALL].rotation);
403 }
404 return (0); /* default */
405 }
407 static char *get_output_file (output_context_t *context)
408 {
409 for (; context; context = context->parent)
410 if (context->output_file)
411 return (context->output_file);
412 fprintf (stderr, "no output file name found\n");
413 exit (2);
414 }
416 static char *get_output_page_number_format (output_context_t *context)
417 {
418 for (; context; context = context->parent)
419 if (context->page_number_format)
420 return (context->page_number_format);
421 return (NULL); /* default */
422 }
425 #ifdef SEMANTIC_DEBUG
426 void dump_input_tree (void)
427 {
428 input_image_t *image;
429 int i;
431 printf ("input images:\n");
432 for (image = first_input_image; image; image = image->next)
433 for (i = image->range.first; i <= image->range.last; i++)
434 {
435 input_modifier_type_t parity = (i % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
436 printf ("file '%s' image %d, rotation %d\n",
437 get_input_file (image->input_context),
438 i,
439 get_input_rotation (image->input_context, parity));
440 }
441 }
443 void dump_output_tree (void)
444 {
445 int i;
446 output_page_t *page;
447 bookmark_t *bookmark;
449 printf ("output pages:\n");
450 for (page = first_output_page; page; page = page->next)
451 {
452 if (page->bookmark_list)
453 {
454 for (bookmark = page->bookmark_list; bookmark; bookmark = bookmark->next)
455 printf ("bookmark '%s' ", bookmark->name);
456 printf ("\n");
457 }
458 for (i = page->range.first; i <= page->range.last; i++)
459 {
460 printf ("file '%s' ", get_output_file (page->output_context));
461 printf ("format '%s' ", get_output_page_number_format (page->output_context));
462 printf ("page %d\n", i);
463 }
464 }
465 }
466 #endif /* SEMANTIC_DEBUG */
468 boolean parse_spec_file (char *fn)
469 {
470 boolean result = 0;
472 yyin = fopen (fn, "r");
473 if (! yyin)
474 {
475 fprintf (stderr, "can't open spec file '%s'\n", fn);
476 goto fail;
477 }
479 line = 1;
481 input_push_context (); /* create root input context */
482 input_push_context (); /* create inital input context */
484 output_push_context (); /* create root output context */
485 output_push_context (); /* create initial output context */
487 yyparse ();
489 if (first_input_context->image_count != first_output_context->page_count)
490 {
491 fprintf (stderr, "input image count %d != output page count %d\n",
492 first_input_context->image_count,
493 first_output_context->page_count);
494 goto fail;
495 }
497 fprintf (stderr, "%d pages specified\n", first_input_context->image_count);
499 result = 1;
501 #ifdef SEMANTIC_DEBUG
502 dump_input_tree ();
503 dump_output_tree ();
504 #endif /* SEMANTIC_DEBUG */
506 fail:
507 if (yyin)
508 fclose (yyin);
510 return (result);
511 }