Mon, 31 Dec 2001 07:44:23 +0000
*** empty log message ***
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@16 | 8 | |
eric@16 | 9 | |
eric@19 | 10 | #define SEMANTIC_DEBUG |
eric@19 | 11 | #ifdef SEMANTIC_DEBUG |
eric@19 | 12 | #define SDBG(x) printf x |
eric@19 | 13 | #else |
eric@19 | 14 | #define SDBG(x) |
eric@19 | 15 | #endif |
eric@19 | 16 | |
eric@19 | 17 | |
eric@16 | 18 | FILE *yyin; |
eric@16 | 19 | int line; /* line number in spec file */ |
eric@16 | 20 | |
eric@16 | 21 | |
eric@20 | 22 | input_context_t *first_input_context; |
eric@20 | 23 | input_context_t *last_input_context; |
eric@20 | 24 | |
eric@20 | 25 | input_modifier_type_t current_modifier_context; |
eric@18 | 26 | |
eric@20 | 27 | input_image_t *first_input_image; |
eric@20 | 28 | input_image_t *last_input_image; |
eric@18 | 29 | |
eric@20 | 30 | output_context_t *first_output_context; |
eric@20 | 31 | output_context_t *last_output_context; |
eric@20 | 32 | |
eric@20 | 33 | output_page_t *first_output_page; |
eric@20 | 34 | output_page_t *last_output_page; |
eric@16 | 35 | |
eric@16 | 36 | |
eric@19 | 37 | void input_push_context (void) |
eric@16 | 38 | { |
eric@18 | 39 | input_context_t *new_input_context; |
eric@18 | 40 | |
eric@18 | 41 | new_input_context = malloc (sizeof (input_context_t)); |
eric@18 | 42 | if (! new_input_context) |
eric@18 | 43 | { |
eric@20 | 44 | fprintf (stderr, "failed to malloc an input context\n"); |
eric@18 | 45 | return; |
eric@18 | 46 | } |
eric@18 | 47 | |
eric@20 | 48 | if (last_input_context) |
eric@18 | 49 | { |
eric@20 | 50 | memcpy (new_input_context, last_input_context, sizeof (input_context_t)); |
eric@20 | 51 | new_input_context->image_count = 0; |
eric@18 | 52 | } |
eric@18 | 53 | else |
eric@20 | 54 | { |
eric@20 | 55 | memset (new_input_context, 0, sizeof (input_context_t)); |
eric@20 | 56 | first_input_context = new_input_context; |
eric@20 | 57 | } |
eric@18 | 58 | |
eric@20 | 59 | new_input_context->parent = last_input_context; |
eric@20 | 60 | last_input_context = new_input_context; |
eric@16 | 61 | }; |
eric@16 | 62 | |
eric@16 | 63 | void input_pop_context (void) |
eric@16 | 64 | { |
eric@20 | 65 | if (! last_input_context) |
eric@18 | 66 | { |
eric@18 | 67 | fprintf (stderr, "failed to pop an input context\n"); |
eric@18 | 68 | return; |
eric@18 | 69 | } |
eric@18 | 70 | |
eric@20 | 71 | last_input_context = last_input_context->parent; |
eric@16 | 72 | }; |
eric@16 | 73 | |
eric@19 | 74 | void input_set_modifier_context (input_modifier_type_t type) |
eric@19 | 75 | { |
eric@19 | 76 | current_modifier_context = type; |
eric@19 | 77 | #ifdef SEMANTIC_DEBUG |
eric@19 | 78 | SDBG(("modifier type ")); |
eric@19 | 79 | switch (type) |
eric@19 | 80 | { |
eric@19 | 81 | case INPUT_MODIFIER_ALL: SDBG(("all")); break; |
eric@19 | 82 | case INPUT_MODIFIER_ODD: SDBG(("odd")); break; |
eric@19 | 83 | case INPUT_MODIFIER_EVEN: SDBG(("even")); break; |
eric@19 | 84 | default: SDBG(("unknown %d", type)); |
eric@19 | 85 | } |
eric@19 | 86 | SDBG(("\n")); |
eric@19 | 87 | #endif /* SEMANTIC_DEBUG */ |
eric@19 | 88 | } |
eric@19 | 89 | |
eric@20 | 90 | void input_clone (void) |
eric@20 | 91 | { |
eric@20 | 92 | input_context_t *new_input_context; |
eric@20 | 93 | |
eric@20 | 94 | if (! last_input_context->image_count) |
eric@20 | 95 | return; |
eric@20 | 96 | |
eric@20 | 97 | new_input_context = malloc (sizeof (input_context_t)); |
eric@20 | 98 | if (! new_input_context) |
eric@20 | 99 | { |
eric@20 | 100 | fprintf (stderr, "failed to malloc an input context\n"); |
eric@20 | 101 | return; |
eric@20 | 102 | } |
eric@20 | 103 | |
eric@20 | 104 | memcpy (new_input_context, last_input_context, sizeof (input_context_t)); |
eric@20 | 105 | new_input_context->image_count = 0; |
eric@20 | 106 | last_input_context->next = new_input_context; |
eric@20 | 107 | } |
eric@20 | 108 | |
eric@16 | 109 | void input_set_file (char *name) |
eric@16 | 110 | { |
eric@20 | 111 | input_clone (); |
eric@20 | 112 | last_input_context->input_file = name; |
eric@16 | 113 | }; |
eric@16 | 114 | |
eric@19 | 115 | void input_set_rotation (int rotation) |
eric@19 | 116 | { |
eric@20 | 117 | last_input_context->modifiers [current_modifier_context].has_rotation = 1; |
eric@20 | 118 | last_input_context->modifiers [current_modifier_context].rotation = rotation; |
eric@19 | 119 | SDBG(("rotation %d\n", rotation)); |
eric@19 | 120 | } |
eric@19 | 121 | |
eric@20 | 122 | void increment_input_image_count (int count) |
eric@16 | 123 | { |
eric@20 | 124 | input_context_t *context; |
eric@20 | 125 | |
eric@20 | 126 | for (context = last_input_context; context; context = context->parent) |
eric@20 | 127 | context->image_count += count; |
eric@20 | 128 | } |
eric@20 | 129 | |
eric@20 | 130 | void input_images (range_t range) |
eric@20 | 131 | { |
eric@20 | 132 | input_image_t *new_image; |
eric@20 | 133 | int count = ((range.last - range.first) + 1); |
eric@20 | 134 | |
eric@19 | 135 | #ifdef SEMANTIC_DEBUG |
eric@20 | 136 | if (range.first == range.last) |
eric@20 | 137 | SDBG(("image %d\n", range.first)); |
eric@16 | 138 | else |
eric@20 | 139 | SDBG(("images %d..%d\n", range.first, range.last)); |
eric@19 | 140 | #endif /* SEMANTIC_DEBUG */ |
eric@20 | 141 | |
eric@20 | 142 | new_image = calloc (1, sizeof (input_image_t)); |
eric@20 | 143 | if (! new_image) |
eric@20 | 144 | { |
eric@20 | 145 | fprintf (stderr, "failed to malloc an input image struct\n"); |
eric@20 | 146 | return; |
eric@20 | 147 | } |
eric@20 | 148 | if (first_input_image) |
eric@20 | 149 | { |
eric@20 | 150 | last_input_image->next = new_image; |
eric@20 | 151 | last_input_image = new_image; |
eric@20 | 152 | } |
eric@20 | 153 | else |
eric@20 | 154 | { |
eric@20 | 155 | first_input_image = last_input_image = new_image; |
eric@20 | 156 | } |
eric@20 | 157 | new_image->range = range; |
eric@20 | 158 | new_image->input_context = last_input_context; |
eric@20 | 159 | increment_input_image_count (count); |
eric@16 | 160 | } |
eric@16 | 161 | |
eric@18 | 162 | |
eric@18 | 163 | void output_push_context (void) |
eric@18 | 164 | { |
eric@20 | 165 | output_context_t *new_output_context; |
eric@20 | 166 | |
eric@20 | 167 | new_output_context = malloc (sizeof (output_context_t)); |
eric@20 | 168 | if (! new_output_context) |
eric@20 | 169 | { |
eric@20 | 170 | fprintf (stderr, "failed to malloc an output context\n"); |
eric@20 | 171 | return; |
eric@20 | 172 | } |
eric@20 | 173 | |
eric@20 | 174 | if (last_output_context) |
eric@20 | 175 | { |
eric@20 | 176 | memcpy (new_output_context, last_output_context, sizeof (output_context_t)); |
eric@20 | 177 | new_output_context->page_count = 0; |
eric@21 | 178 | new_output_context->first_bookmark = NULL; |
eric@21 | 179 | new_output_context->last_bookmark = NULL; |
eric@20 | 180 | } |
eric@20 | 181 | else |
eric@20 | 182 | { |
eric@20 | 183 | memset (new_output_context, 0, sizeof (output_context_t)); |
eric@20 | 184 | first_output_context = new_output_context; |
eric@20 | 185 | } |
eric@20 | 186 | |
eric@20 | 187 | new_output_context->parent = last_output_context; |
eric@20 | 188 | last_output_context = new_output_context; |
eric@18 | 189 | }; |
eric@18 | 190 | |
eric@20 | 191 | void output_pop_context (void) |
eric@20 | 192 | { |
eric@20 | 193 | if (! last_output_context) |
eric@20 | 194 | { |
eric@20 | 195 | fprintf (stderr, "failed to pop an output context\n"); |
eric@20 | 196 | return; |
eric@20 | 197 | } |
eric@20 | 198 | |
eric@20 | 199 | last_output_context = last_output_context->parent; |
eric@20 | 200 | }; |
eric@20 | 201 | |
eric@20 | 202 | void output_clone (void) |
eric@20 | 203 | { |
eric@20 | 204 | output_context_t *new_output_context; |
eric@20 | 205 | |
eric@20 | 206 | if (! last_output_context->page_count) |
eric@20 | 207 | return; |
eric@20 | 208 | |
eric@20 | 209 | new_output_context = malloc (sizeof (output_context_t)); |
eric@20 | 210 | if (! new_output_context) |
eric@20 | 211 | { |
eric@20 | 212 | fprintf (stderr, "failed to malloc an output context\n"); |
eric@20 | 213 | return; |
eric@20 | 214 | } |
eric@20 | 215 | |
eric@20 | 216 | memcpy (new_output_context, last_output_context, sizeof (output_context_t)); |
eric@20 | 217 | new_output_context->page_count = 0; |
eric@20 | 218 | last_output_context->next = new_output_context; |
eric@20 | 219 | } |
eric@20 | 220 | |
eric@16 | 221 | void output_set_file (char *name) |
eric@16 | 222 | { |
eric@20 | 223 | output_clone (); |
eric@20 | 224 | last_output_context->output_file = name; |
eric@16 | 225 | }; |
eric@16 | 226 | |
eric@20 | 227 | void output_set_bookmark (char *name) |
eric@16 | 228 | { |
eric@20 | 229 | bookmark_t *new_bookmark; |
eric@20 | 230 | |
eric@20 | 231 | /* As the language is defined (parser.y), a bookmark can only appear |
eric@20 | 232 | at the beginning of a context! */ |
eric@20 | 233 | if (last_output_context->page_count) |
eric@20 | 234 | { |
eric@20 | 235 | fprintf (stderr, "internal error, bookmark not at beginning of context\n"); |
eric@20 | 236 | exit (2); |
eric@20 | 237 | } |
eric@20 | 238 | |
eric@20 | 239 | new_bookmark = calloc (1, sizeof (bookmark_t)); |
eric@20 | 240 | if (! new_bookmark) |
eric@20 | 241 | { |
eric@20 | 242 | fprintf (stderr, "failed to calloc a bookmark\n"); |
eric@20 | 243 | return; |
eric@20 | 244 | } |
eric@20 | 245 | |
eric@20 | 246 | new_bookmark->name = name; |
eric@20 | 247 | if (last_output_context->first_bookmark) |
eric@20 | 248 | last_output_context->last_bookmark->next = new_bookmark; |
eric@20 | 249 | else |
eric@20 | 250 | last_output_context->first_bookmark = new_bookmark; |
eric@20 | 251 | last_output_context->last_bookmark = new_bookmark; |
eric@20 | 252 | } |
eric@20 | 253 | |
eric@20 | 254 | void output_set_page_number_format (char *format) |
eric@20 | 255 | { |
eric@20 | 256 | output_clone (); |
eric@20 | 257 | last_output_context->page_number_format = format; |
eric@20 | 258 | } |
eric@20 | 259 | |
eric@20 | 260 | void increment_output_page_count (int count) |
eric@20 | 261 | { |
eric@20 | 262 | output_context_t *context; |
eric@20 | 263 | |
eric@20 | 264 | for (context = last_output_context; context; context = context->parent) |
eric@20 | 265 | context->page_count += count; |
eric@20 | 266 | } |
eric@20 | 267 | |
eric@21 | 268 | |
eric@20 | 269 | void output_pages (range_t range) |
eric@20 | 270 | { |
eric@20 | 271 | output_page_t *new_page; |
eric@21 | 272 | output_context_t *context; |
eric@20 | 273 | int count = ((range.last - range.first) + 1); |
eric@20 | 274 | |
eric@19 | 275 | #ifdef SEMANTIC_DEBUG |
eric@20 | 276 | if (range.first == range.last) |
eric@20 | 277 | SDBG(("page %d\n", range.first)); |
eric@16 | 278 | else |
eric@20 | 279 | SDBG(("pages %d..%d\n", range.first, range.last)); |
eric@19 | 280 | #endif /* SEMANTIC_DEBUG */ |
eric@20 | 281 | |
eric@20 | 282 | new_page = calloc (1, sizeof (output_page_t)); |
eric@20 | 283 | if (! new_page) |
eric@20 | 284 | { |
eric@20 | 285 | fprintf (stderr, "failed to malloc an output page struct\n"); |
eric@20 | 286 | return; |
eric@20 | 287 | } |
eric@20 | 288 | if (first_output_page) |
eric@20 | 289 | { |
eric@20 | 290 | last_output_page->next = new_page; |
eric@20 | 291 | last_output_page = new_page; |
eric@20 | 292 | } |
eric@20 | 293 | else |
eric@20 | 294 | { |
eric@20 | 295 | first_output_page = last_output_page = new_page; |
eric@20 | 296 | } |
eric@20 | 297 | new_page->range = range; |
eric@20 | 298 | new_page->output_context = last_output_context; |
eric@20 | 299 | |
eric@21 | 300 | /* transfer bookmarks from context(s) to page */ |
eric@21 | 301 | for (context = last_output_context; context; context = context->parent) |
eric@21 | 302 | if (context->first_bookmark) |
eric@21 | 303 | { |
eric@21 | 304 | context->last_bookmark->next = new_page->bookmark_list; |
eric@21 | 305 | new_page->bookmark_list = context->first_bookmark; |
eric@21 | 306 | context->first_bookmark = NULL; |
eric@21 | 307 | context->last_bookmark = NULL; |
eric@21 | 308 | } |
eric@20 | 309 | |
eric@20 | 310 | increment_output_page_count (count); |
eric@16 | 311 | } |
eric@16 | 312 | |
eric@16 | 313 | |
eric@16 | 314 | void yyerror (char *s) |
eric@16 | 315 | { |
eric@16 | 316 | fprintf (stderr, "%d: %s\n", line, s); |
eric@16 | 317 | } |
eric@16 | 318 | |
eric@16 | 319 | |
eric@20 | 320 | char *get_input_file (input_context_t *context) |
eric@20 | 321 | { |
eric@20 | 322 | for (; context; context = context->parent) |
eric@20 | 323 | if (context->input_file) |
eric@20 | 324 | return (context->input_file); |
eric@20 | 325 | fprintf (stderr, "no input file name found\n"); |
eric@20 | 326 | exit (2); |
eric@20 | 327 | } |
eric@20 | 328 | |
eric@20 | 329 | int get_input_rotation (input_context_t *context, input_modifier_type_t type) |
eric@20 | 330 | { |
eric@20 | 331 | for (; context; context = context->parent) |
eric@20 | 332 | { |
eric@20 | 333 | if (context->modifiers [type].has_rotation) |
eric@20 | 334 | return (context->modifiers [type].rotation); |
eric@20 | 335 | if (context->modifiers [INPUT_MODIFIER_ALL].has_rotation) |
eric@20 | 336 | return (context->modifiers [INPUT_MODIFIER_ALL].rotation); |
eric@20 | 337 | } |
eric@20 | 338 | return (0); /* default */ |
eric@20 | 339 | } |
eric@20 | 340 | |
eric@20 | 341 | char *get_output_file (output_context_t *context) |
eric@20 | 342 | { |
eric@20 | 343 | for (; context; context = context->parent) |
eric@20 | 344 | if (context->output_file) |
eric@20 | 345 | return (context->output_file); |
eric@20 | 346 | fprintf (stderr, "no output file name found\n"); |
eric@20 | 347 | exit (2); |
eric@20 | 348 | } |
eric@20 | 349 | |
eric@20 | 350 | char *get_output_page_number_format (output_context_t *context) |
eric@20 | 351 | { |
eric@20 | 352 | for (; context; context = context->parent) |
eric@20 | 353 | if (context->page_number_format) |
eric@20 | 354 | return (context->page_number_format); |
eric@20 | 355 | return (NULL); /* default */ |
eric@20 | 356 | } |
eric@20 | 357 | |
eric@20 | 358 | |
eric@20 | 359 | #ifdef SEMANTIC_DEBUG |
eric@20 | 360 | void dump_input_tree (void) |
eric@20 | 361 | { |
eric@20 | 362 | input_image_t *image; |
eric@20 | 363 | int i; |
eric@20 | 364 | |
eric@20 | 365 | printf ("input images:\n"); |
eric@20 | 366 | for (image = first_input_image; image; image = image->next) |
eric@20 | 367 | for (i = image->range.first; i <= image->range.last; i++) |
eric@20 | 368 | { |
eric@20 | 369 | input_modifier_type_t parity = (i % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN; |
eric@20 | 370 | printf ("file '%s' image %d, rotation %d\n", |
eric@20 | 371 | get_input_file (image->input_context), |
eric@20 | 372 | i, |
eric@20 | 373 | get_input_rotation (image->input_context, parity)); |
eric@20 | 374 | } |
eric@20 | 375 | } |
eric@20 | 376 | |
eric@20 | 377 | void dump_output_tree (void) |
eric@20 | 378 | { |
eric@20 | 379 | int i; |
eric@20 | 380 | output_page_t *page; |
eric@20 | 381 | bookmark_t *bookmark; |
eric@20 | 382 | |
eric@20 | 383 | printf ("output pages:\n"); |
eric@20 | 384 | for (page = first_output_page; page; page = page->next) |
eric@20 | 385 | { |
eric@20 | 386 | if (page->bookmark_list) |
eric@20 | 387 | { |
eric@20 | 388 | for (bookmark = page->bookmark_list; bookmark; bookmark = bookmark->next) |
eric@20 | 389 | printf ("bookmark '%s' ", bookmark->name); |
eric@20 | 390 | printf ("\n"); |
eric@20 | 391 | } |
eric@20 | 392 | for (i = page->range.first; i <= page->range.last; i++) |
eric@20 | 393 | { |
eric@20 | 394 | printf ("file '%s' ", get_output_file (page->output_context)); |
eric@20 | 395 | printf ("format '%s' ", get_output_page_number_format (page->output_context)); |
eric@20 | 396 | printf ("page %d\n", i); |
eric@20 | 397 | } |
eric@20 | 398 | } |
eric@20 | 399 | } |
eric@20 | 400 | #endif /* SEMANTIC_DEBUG */ |
eric@20 | 401 | |
eric@16 | 402 | boolean parse_spec_file (char *fn) |
eric@16 | 403 | { |
eric@16 | 404 | boolean result = 0; |
eric@16 | 405 | |
eric@16 | 406 | yyin = fopen (fn, "r"); |
eric@16 | 407 | if (! yyin) |
eric@16 | 408 | { |
eric@16 | 409 | fprintf (stderr, "can't open spec file '%s'\n", fn); |
eric@16 | 410 | goto fail; |
eric@16 | 411 | } |
eric@16 | 412 | |
eric@16 | 413 | line = 1; |
eric@16 | 414 | |
eric@20 | 415 | input_push_context (); /* create root input context */ |
eric@20 | 416 | input_push_context (); /* create inital input context */ |
eric@20 | 417 | |
eric@20 | 418 | output_push_context (); /* create root output context */ |
eric@18 | 419 | output_push_context (); /* create initial output context */ |
eric@18 | 420 | |
eric@16 | 421 | yyparse (); |
eric@16 | 422 | |
eric@20 | 423 | if (first_input_context->image_count != first_output_context->page_count) |
eric@18 | 424 | { |
eric@20 | 425 | fprintf (stderr, "input image count %d != output page count %d\n", |
eric@20 | 426 | first_input_context->image_count, |
eric@20 | 427 | first_output_context->page_count); |
eric@18 | 428 | goto fail; |
eric@18 | 429 | } |
eric@18 | 430 | |
eric@20 | 431 | fprintf (stderr, "%d pages specified\n", first_input_context->image_count); |
eric@18 | 432 | |
eric@16 | 433 | result = 1; |
eric@16 | 434 | |
eric@20 | 435 | #ifdef SEMANTIC_DEBUG |
eric@20 | 436 | dump_input_tree (); |
eric@20 | 437 | dump_output_tree (); |
eric@20 | 438 | #endif /* SEMANTIC_DEBUG */ |
eric@20 | 439 | |
eric@16 | 440 | fail: |
eric@16 | 441 | if (yyin) |
eric@16 | 442 | fclose (yyin); |
eric@16 | 443 | |
eric@16 | 444 | return (result); |
eric@16 | 445 | } |