semantics.c

Tue, 01 Jan 2002 03:44:40 +0000

author
eric
date
Tue, 01 Jan 2002 03:44:40 +0000
changeset 26
4368c5fd9242
parent 25
139b91f9a224
child 30
35fad7ec7732
permissions
-rw-r--r--

handle input and output files properly.

eric@18 1 #include <stdlib.h>
eric@18 2 #include <string.h>
eric@16 3 #include <stdio.h>
eric@16 4
eric@16 5 #include "type.h"
eric@18 6 #include "semantics.h"
eric@16 7 #include "parser.tab.h"
eric@25 8 #include "tiff2pdf.h"
eric@16 9
eric@16 10
eric@22 11 typedef struct
eric@22 12 {
eric@22 13 boolean has_size;
eric@22 14 page_size_t size;
eric@22 15
eric@22 16 boolean has_rotation;
eric@22 17 int rotation;
eric@22 18
eric@22 19 boolean has_crop;
eric@22 20 crop_t crop;
eric@22 21 } input_modifiers_t;
eric@22 22
eric@22 23
eric@22 24 typedef struct input_context_t
eric@22 25 {
eric@22 26 struct input_context_t *parent;
eric@22 27 struct input_context_t *next;
eric@22 28
eric@22 29 int image_count; /* how many pages reference this context,
eric@22 30 including those from subcontexts */
eric@22 31
eric@22 32 char *input_file;
eric@22 33
eric@22 34 input_modifiers_t modifiers [INPUT_MODIFIER_TYPE_COUNT];
eric@22 35 } input_context_t;
eric@22 36
eric@22 37
eric@22 38 typedef struct input_image_t
eric@22 39 {
eric@22 40 struct input_image_t *next;
eric@22 41 input_context_t *input_context;
eric@22 42 range_t range;
eric@22 43 } input_image_t;
eric@22 44
eric@22 45
eric@22 46 typedef struct output_context_t
eric@22 47 {
eric@22 48 struct output_context_t *parent;
eric@22 49 struct output_context_t *next;
eric@22 50
eric@22 51 int page_count; /* how many pages reference this context,
eric@22 52 including those from subcontexts */
eric@22 53
eric@22 54 char *output_file;
eric@22 55 bookmark_t *first_bookmark;
eric@22 56 bookmark_t *last_bookmark;
eric@25 57
eric@25 58 boolean has_page_label;
eric@25 59 page_label_t page_label;
eric@22 60 } output_context_t;
eric@22 61
eric@22 62
eric@22 63 typedef struct output_page_t
eric@22 64 {
eric@22 65 struct output_page_t *next;
eric@22 66 output_context_t *output_context;
eric@22 67 range_t range;
eric@22 68 bookmark_t *bookmark_list;
eric@22 69 } output_page_t;
eric@22 70
eric@22 71
eric@19 72 #define SEMANTIC_DEBUG
eric@19 73 #ifdef SEMANTIC_DEBUG
eric@19 74 #define SDBG(x) printf x
eric@19 75 #else
eric@19 76 #define SDBG(x)
eric@19 77 #endif
eric@19 78
eric@19 79
eric@16 80 FILE *yyin;
eric@16 81 int line; /* line number in spec file */
eric@16 82
eric@24 83 int bookmark_level;
eric@16 84
eric@20 85 input_context_t *first_input_context;
eric@20 86 input_context_t *last_input_context;
eric@20 87
eric@20 88 input_modifier_type_t current_modifier_context;
eric@18 89
eric@20 90 input_image_t *first_input_image;
eric@20 91 input_image_t *last_input_image;
eric@18 92
eric@20 93 output_context_t *first_output_context;
eric@20 94 output_context_t *last_output_context;
eric@20 95
eric@20 96 output_page_t *first_output_page;
eric@20 97 output_page_t *last_output_page;
eric@16 98
eric@16 99
eric@19 100 void input_push_context (void)
eric@16 101 {
eric@18 102 input_context_t *new_input_context;
eric@18 103
eric@18 104 new_input_context = malloc (sizeof (input_context_t));
eric@18 105 if (! new_input_context)
eric@18 106 {
eric@20 107 fprintf (stderr, "failed to malloc an input context\n");
eric@18 108 return;
eric@18 109 }
eric@18 110
eric@20 111 if (last_input_context)
eric@18 112 {
eric@20 113 memcpy (new_input_context, last_input_context, sizeof (input_context_t));
eric@20 114 new_input_context->image_count = 0;
eric@18 115 }
eric@18 116 else
eric@20 117 {
eric@20 118 memset (new_input_context, 0, sizeof (input_context_t));
eric@20 119 first_input_context = new_input_context;
eric@20 120 }
eric@18 121
eric@20 122 new_input_context->parent = last_input_context;
eric@20 123 last_input_context = new_input_context;
eric@16 124 };
eric@16 125
eric@16 126 void input_pop_context (void)
eric@16 127 {
eric@20 128 if (! last_input_context)
eric@18 129 {
eric@18 130 fprintf (stderr, "failed to pop an input context\n");
eric@18 131 return;
eric@18 132 }
eric@18 133
eric@20 134 last_input_context = last_input_context->parent;
eric@16 135 };
eric@16 136
eric@19 137 void input_set_modifier_context (input_modifier_type_t type)
eric@19 138 {
eric@19 139 current_modifier_context = type;
eric@19 140 #ifdef SEMANTIC_DEBUG
eric@19 141 SDBG(("modifier type "));
eric@19 142 switch (type)
eric@19 143 {
eric@19 144 case INPUT_MODIFIER_ALL: SDBG(("all")); break;
eric@19 145 case INPUT_MODIFIER_ODD: SDBG(("odd")); break;
eric@19 146 case INPUT_MODIFIER_EVEN: SDBG(("even")); break;
eric@19 147 default: SDBG(("unknown %d", type));
eric@19 148 }
eric@19 149 SDBG(("\n"));
eric@19 150 #endif /* SEMANTIC_DEBUG */
eric@19 151 }
eric@19 152
eric@22 153 static void input_clone (void)
eric@20 154 {
eric@20 155 input_context_t *new_input_context;
eric@20 156
eric@20 157 if (! last_input_context->image_count)
eric@20 158 return;
eric@20 159
eric@20 160 new_input_context = malloc (sizeof (input_context_t));
eric@20 161 if (! new_input_context)
eric@20 162 {
eric@20 163 fprintf (stderr, "failed to malloc an input context\n");
eric@20 164 return;
eric@20 165 }
eric@20 166
eric@20 167 memcpy (new_input_context, last_input_context, sizeof (input_context_t));
eric@20 168 new_input_context->image_count = 0;
eric@20 169 last_input_context->next = new_input_context;
eric@20 170 }
eric@20 171
eric@16 172 void input_set_file (char *name)
eric@16 173 {
eric@20 174 input_clone ();
eric@20 175 last_input_context->input_file = name;
eric@16 176 };
eric@16 177
eric@19 178 void input_set_rotation (int rotation)
eric@19 179 {
eric@20 180 last_input_context->modifiers [current_modifier_context].has_rotation = 1;
eric@20 181 last_input_context->modifiers [current_modifier_context].rotation = rotation;
eric@19 182 SDBG(("rotation %d\n", rotation));
eric@19 183 }
eric@19 184
eric@22 185 static void increment_input_image_count (int count)
eric@16 186 {
eric@20 187 input_context_t *context;
eric@20 188
eric@20 189 for (context = last_input_context; context; context = context->parent)
eric@20 190 context->image_count += count;
eric@20 191 }
eric@20 192
eric@20 193 void input_images (range_t range)
eric@20 194 {
eric@20 195 input_image_t *new_image;
eric@20 196 int count = ((range.last - range.first) + 1);
eric@20 197
eric@19 198 #ifdef SEMANTIC_DEBUG
eric@20 199 if (range.first == range.last)
eric@20 200 SDBG(("image %d\n", range.first));
eric@16 201 else
eric@20 202 SDBG(("images %d..%d\n", range.first, range.last));
eric@19 203 #endif /* SEMANTIC_DEBUG */
eric@20 204
eric@20 205 new_image = calloc (1, sizeof (input_image_t));
eric@20 206 if (! new_image)
eric@20 207 {
eric@20 208 fprintf (stderr, "failed to malloc an input image struct\n");
eric@20 209 return;
eric@20 210 }
eric@20 211 if (first_input_image)
eric@20 212 {
eric@20 213 last_input_image->next = new_image;
eric@20 214 last_input_image = new_image;
eric@20 215 }
eric@20 216 else
eric@20 217 {
eric@20 218 first_input_image = last_input_image = new_image;
eric@20 219 }
eric@20 220 new_image->range = range;
eric@20 221 new_image->input_context = last_input_context;
eric@20 222 increment_input_image_count (count);
eric@16 223 }
eric@16 224
eric@18 225
eric@18 226 void output_push_context (void)
eric@18 227 {
eric@20 228 output_context_t *new_output_context;
eric@20 229
eric@20 230 new_output_context = malloc (sizeof (output_context_t));
eric@20 231 if (! new_output_context)
eric@20 232 {
eric@20 233 fprintf (stderr, "failed to malloc an output context\n");
eric@20 234 return;
eric@20 235 }
eric@20 236
eric@20 237 if (last_output_context)
eric@20 238 {
eric@20 239 memcpy (new_output_context, last_output_context, sizeof (output_context_t));
eric@20 240 new_output_context->page_count = 0;
eric@21 241 new_output_context->first_bookmark = NULL;
eric@21 242 new_output_context->last_bookmark = NULL;
eric@20 243 }
eric@20 244 else
eric@20 245 {
eric@20 246 memset (new_output_context, 0, sizeof (output_context_t));
eric@20 247 first_output_context = new_output_context;
eric@20 248 }
eric@20 249
eric@20 250 new_output_context->parent = last_output_context;
eric@20 251 last_output_context = new_output_context;
eric@18 252 };
eric@18 253
eric@20 254 void output_pop_context (void)
eric@20 255 {
eric@20 256 if (! last_output_context)
eric@20 257 {
eric@20 258 fprintf (stderr, "failed to pop an output context\n");
eric@20 259 return;
eric@20 260 }
eric@20 261
eric@20 262 last_output_context = last_output_context->parent;
eric@20 263 };
eric@20 264
eric@22 265 static void output_clone (void)
eric@20 266 {
eric@20 267 output_context_t *new_output_context;
eric@20 268
eric@20 269 if (! last_output_context->page_count)
eric@20 270 return;
eric@20 271
eric@20 272 new_output_context = malloc (sizeof (output_context_t));
eric@20 273 if (! new_output_context)
eric@20 274 {
eric@20 275 fprintf (stderr, "failed to malloc an output context\n");
eric@20 276 return;
eric@20 277 }
eric@20 278
eric@20 279 memcpy (new_output_context, last_output_context, sizeof (output_context_t));
eric@20 280 new_output_context->page_count = 0;
eric@20 281 last_output_context->next = new_output_context;
eric@20 282 }
eric@20 283
eric@16 284 void output_set_file (char *name)
eric@16 285 {
eric@20 286 output_clone ();
eric@20 287 last_output_context->output_file = name;
eric@16 288 };
eric@16 289
eric@20 290 void output_set_bookmark (char *name)
eric@16 291 {
eric@20 292 bookmark_t *new_bookmark;
eric@20 293
eric@20 294 /* As the language is defined (parser.y), a bookmark can only appear
eric@20 295 at the beginning of a context! */
eric@20 296 if (last_output_context->page_count)
eric@20 297 {
eric@20 298 fprintf (stderr, "internal error, bookmark not at beginning of context\n");
eric@20 299 exit (2);
eric@20 300 }
eric@20 301
eric@20 302 new_bookmark = calloc (1, sizeof (bookmark_t));
eric@20 303 if (! new_bookmark)
eric@20 304 {
eric@20 305 fprintf (stderr, "failed to calloc a bookmark\n");
eric@20 306 return;
eric@20 307 }
eric@20 308
eric@24 309 new_bookmark->level = bookmark_level;
eric@20 310 new_bookmark->name = name;
eric@20 311 if (last_output_context->first_bookmark)
eric@20 312 last_output_context->last_bookmark->next = new_bookmark;
eric@20 313 else
eric@20 314 last_output_context->first_bookmark = new_bookmark;
eric@20 315 last_output_context->last_bookmark = new_bookmark;
eric@20 316 }
eric@20 317
eric@25 318 void output_set_page_label (page_label_t label)
eric@20 319 {
eric@20 320 output_clone ();
eric@25 321 last_output_context->has_page_label = 1;
eric@25 322 last_output_context->page_label = label;
eric@20 323 }
eric@20 324
eric@22 325 static void increment_output_page_count (int count)
eric@20 326 {
eric@20 327 output_context_t *context;
eric@20 328
eric@20 329 for (context = last_output_context; context; context = context->parent)
eric@20 330 context->page_count += count;
eric@20 331 }
eric@20 332
eric@21 333
eric@20 334 void output_pages (range_t range)
eric@20 335 {
eric@20 336 output_page_t *new_page;
eric@21 337 output_context_t *context;
eric@20 338 int count = ((range.last - range.first) + 1);
eric@20 339
eric@19 340 #ifdef SEMANTIC_DEBUG
eric@20 341 if (range.first == range.last)
eric@20 342 SDBG(("page %d\n", range.first));
eric@16 343 else
eric@20 344 SDBG(("pages %d..%d\n", range.first, range.last));
eric@19 345 #endif /* SEMANTIC_DEBUG */
eric@20 346
eric@20 347 new_page = calloc (1, sizeof (output_page_t));
eric@20 348 if (! new_page)
eric@20 349 {
eric@20 350 fprintf (stderr, "failed to malloc an output page struct\n");
eric@20 351 return;
eric@20 352 }
eric@20 353 if (first_output_page)
eric@20 354 {
eric@20 355 last_output_page->next = new_page;
eric@20 356 last_output_page = new_page;
eric@20 357 }
eric@20 358 else
eric@20 359 {
eric@20 360 first_output_page = last_output_page = new_page;
eric@20 361 }
eric@20 362 new_page->range = range;
eric@20 363 new_page->output_context = last_output_context;
eric@20 364
eric@21 365 /* transfer bookmarks from context(s) to page */
eric@21 366 for (context = last_output_context; context; context = context->parent)
eric@21 367 if (context->first_bookmark)
eric@21 368 {
eric@21 369 context->last_bookmark->next = new_page->bookmark_list;
eric@21 370 new_page->bookmark_list = context->first_bookmark;
eric@21 371 context->first_bookmark = NULL;
eric@21 372 context->last_bookmark = NULL;
eric@21 373 }
eric@20 374
eric@20 375 increment_output_page_count (count);
eric@16 376 }
eric@16 377
eric@16 378
eric@16 379 void yyerror (char *s)
eric@16 380 {
eric@16 381 fprintf (stderr, "%d: %s\n", line, s);
eric@16 382 }
eric@16 383
eric@16 384
eric@22 385 static char *get_input_file (input_context_t *context)
eric@20 386 {
eric@20 387 for (; context; context = context->parent)
eric@20 388 if (context->input_file)
eric@20 389 return (context->input_file);
eric@20 390 fprintf (stderr, "no input file name found\n");
eric@20 391 exit (2);
eric@20 392 }
eric@20 393
eric@22 394 static int get_input_rotation (input_context_t *context, input_modifier_type_t type)
eric@20 395 {
eric@20 396 for (; context; context = context->parent)
eric@20 397 {
eric@20 398 if (context->modifiers [type].has_rotation)
eric@20 399 return (context->modifiers [type].rotation);
eric@20 400 if (context->modifiers [INPUT_MODIFIER_ALL].has_rotation)
eric@20 401 return (context->modifiers [INPUT_MODIFIER_ALL].rotation);
eric@20 402 }
eric@20 403 return (0); /* default */
eric@20 404 }
eric@20 405
eric@22 406 static char *get_output_file (output_context_t *context)
eric@20 407 {
eric@20 408 for (; context; context = context->parent)
eric@20 409 if (context->output_file)
eric@20 410 return (context->output_file);
eric@20 411 fprintf (stderr, "no output file name found\n");
eric@20 412 exit (2);
eric@20 413 }
eric@20 414
eric@25 415 static page_label_t *get_output_page_label (output_context_t *context)
eric@20 416 {
eric@20 417 for (; context; context = context->parent)
eric@25 418 if (context->has_page_label)
eric@25 419 return (& context->page_label);
eric@20 420 return (NULL); /* default */
eric@20 421 }
eric@20 422
eric@20 423
eric@20 424 #ifdef SEMANTIC_DEBUG
eric@20 425 void dump_input_tree (void)
eric@20 426 {
eric@20 427 input_image_t *image;
eric@20 428 int i;
eric@20 429
eric@20 430 printf ("input images:\n");
eric@20 431 for (image = first_input_image; image; image = image->next)
eric@20 432 for (i = image->range.first; i <= image->range.last; i++)
eric@20 433 {
eric@20 434 input_modifier_type_t parity = (i % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
eric@20 435 printf ("file '%s' image %d, rotation %d\n",
eric@20 436 get_input_file (image->input_context),
eric@20 437 i,
eric@20 438 get_input_rotation (image->input_context, parity));
eric@20 439 }
eric@20 440 }
eric@20 441
eric@20 442 void dump_output_tree (void)
eric@20 443 {
eric@20 444 int i;
eric@20 445 output_page_t *page;
eric@20 446 bookmark_t *bookmark;
eric@20 447
eric@20 448 printf ("output pages:\n");
eric@20 449 for (page = first_output_page; page; page = page->next)
eric@20 450 {
eric@20 451 if (page->bookmark_list)
eric@20 452 {
eric@20 453 for (bookmark = page->bookmark_list; bookmark; bookmark = bookmark->next)
eric@25 454 printf ("bookmark %d \"%s\"\n", bookmark->level, bookmark->name);
eric@20 455 }
eric@20 456 for (i = page->range.first; i <= page->range.last; i++)
eric@20 457 {
eric@25 458 page_label_t *label = get_output_page_label (page->output_context);
eric@25 459 printf ("file \"%s\" ", get_output_file (page->output_context));
eric@25 460 if (label)
eric@25 461 {
eric@25 462 printf ("label ");
eric@25 463 if (label->prefix)
eric@25 464 printf ("\"%s\" ", label->prefix);
eric@25 465 if (label->style)
eric@25 466 printf ("'%c' ", label->style);
eric@25 467 }
eric@20 468 printf ("page %d\n", i);
eric@20 469 }
eric@20 470 }
eric@20 471 }
eric@20 472 #endif /* SEMANTIC_DEBUG */
eric@20 473
eric@25 474
eric@25 475 static inline int range_count (range_t range)
eric@25 476 {
eric@25 477 return ((range.last - range.first) + 1);
eric@25 478 }
eric@25 479
eric@25 480
eric@16 481 boolean parse_spec_file (char *fn)
eric@16 482 {
eric@16 483 boolean result = 0;
eric@16 484
eric@16 485 yyin = fopen (fn, "r");
eric@16 486 if (! yyin)
eric@16 487 {
eric@16 488 fprintf (stderr, "can't open spec file '%s'\n", fn);
eric@16 489 goto fail;
eric@16 490 }
eric@16 491
eric@16 492 line = 1;
eric@16 493
eric@20 494 input_push_context (); /* create root input context */
eric@20 495 input_push_context (); /* create inital input context */
eric@20 496
eric@20 497 output_push_context (); /* create root output context */
eric@18 498 output_push_context (); /* create initial output context */
eric@18 499
eric@16 500 yyparse ();
eric@16 501
eric@20 502 if (first_input_context->image_count != first_output_context->page_count)
eric@18 503 {
eric@20 504 fprintf (stderr, "input image count %d != output page count %d\n",
eric@20 505 first_input_context->image_count,
eric@20 506 first_output_context->page_count);
eric@18 507 goto fail;
eric@18 508 }
eric@18 509
eric@20 510 fprintf (stderr, "%d pages specified\n", first_input_context->image_count);
eric@18 511
eric@16 512 result = 1;
eric@16 513
eric@20 514 #ifdef SEMANTIC_DEBUG
eric@20 515 dump_input_tree ();
eric@20 516 dump_output_tree ();
eric@20 517 #endif /* SEMANTIC_DEBUG */
eric@20 518
eric@16 519 fail:
eric@16 520 if (yyin)
eric@16 521 fclose (yyin);
eric@16 522
eric@16 523 return (result);
eric@16 524 }
eric@26 525
eric@26 526
eric@26 527 boolean process_specs (void)
eric@26 528 {
eric@26 529 input_image_t *image = NULL;
eric@26 530 output_page_t *page = NULL;
eric@26 531 int i = 0;
eric@26 532 int p = 0;
eric@26 533 int page_index = 0;
eric@26 534 input_attributes_t input_attributes;
eric@26 535 input_modifier_type_t parity;
eric@26 536 page_label_t *page_label;
eric@26 537
eric@26 538 for (;;)
eric@26 539 {
eric@26 540 if ((! image) || (i >= range_count (image->range)))
eric@26 541 {
eric@26 542 if (image)
eric@26 543 image = image->next;
eric@26 544 else
eric@26 545 image = first_input_image;
eric@26 546 if (! image)
eric@26 547 return (0);
eric@26 548 i = 0;
eric@26 549 if (! open_tiff_input_file (get_input_file (image->input_context)))
eric@26 550 return (0);
eric@26 551 }
eric@26 552
eric@26 553 if ((! page) || (p >= range_count (page->range)))
eric@26 554 {
eric@26 555 if (page)
eric@26 556 page = page->next;
eric@26 557 else
eric@26 558 page = first_output_page;
eric@26 559 p = 0;
eric@26 560 if (! open_pdf_output_file (get_output_file (page->output_context)))
eric@26 561 return (0);
eric@26 562 page_label = get_output_page_label (page->output_context);
eric@26 563 process_page_numbers (page_index,
eric@26 564 range_count (page->range),
eric@26 565 page->range.first,
eric@26 566 page_label);
eric@26 567 }
eric@26 568
eric@26 569 parity = ((image->range.first + i) % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
eric@26 570
eric@26 571 memset (& input_attributes, 0, sizeof (input_attributes));
eric@26 572 input_attributes.rotation = get_input_rotation (image->input_context,
eric@26 573 parity);;
eric@26 574
eric@26 575 process_page (image->range.first + i,
eric@26 576 input_attributes,
eric@26 577 page->bookmark_list);
eric@26 578 i++;
eric@26 579 p++;
eric@26 580 page_index++;
eric@26 581 }
eric@26 582
eric@26 583 return (1);
eric@26 584 }