Mon, 26 Aug 2002 06:03:55 +0000
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 }