Mon, 31 Dec 2001 08:25:04 +0000
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 }