1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* Copyright (c) 1988 AT&T */ 27 /* All Rights Reserved */ 28 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 /* 43 * ******************************************************************* 44 * COPYRIGHT NOTICE * 45 * ******************************************************************** 46 * This software is copyright (C) 1982 by Pavel Curtis * 47 * * 48 * Permission is granted to reproduce and distribute * 49 * this file by any means so long as no fee is charged * 50 * above a nominal handling fee and so long as this * 51 * notice is always included in the copies. * 52 * * 53 * Other rights are reserved except as explicitly granted * 54 * by written permission of the author. * 55 * Pavel Curtis * 56 * Computer Science Dept. * 57 * 405 Upson Hall * 58 * Cornell University * 59 * Ithaca, NY 14853 * 60 * * 61 * Ph- (607) 256-4934 * 62 * * 63 * Pavel.Cornell@Udel-Relay (ARPAnet) * 64 * decvax!cornell!pavel (UUCPnet) * 65 * ******************************************************************** 66 */ 67 68 /* 69 * comp_parse.c -- The high-level (ha!) parts of the compiler, 70 * that is, the routines which drive the scanner, 71 * etc. 72 * 73 * $Log: RCS/comp_parse.v $ 74 * Revision 2.1 82/10/25 14:45:43 pavel 75 * Added Copyright Notice 76 * 77 * Revision 2.0 82/10/24 15:16:39 pavel 78 * Beta-one Test Release 79 * 80 * Revision 1.3 82/08/23 22:29:39 pavel 81 * The REAL Alpha-one Release Version 82 * 83 * Revision 1.2 82/08/19 19:09:53 pavel 84 * Alpha Test Release One 85 * 86 * Revision 1.1 82/08/12 18:37:12 pavel 87 * Initial revision 88 * 89 * 90 */ 91 92 #include <sys/types.h> 93 #include <sys/stat.h> 94 #include <stdio.h> 95 #include <ctype.h> 96 #include <stdlib.h> 97 #include <strings.h> 98 #include <unistd.h> 99 #include "curses_inc.h" 100 #include "compiler.h" 101 #include "object.h" 102 103 extern char check_only; 104 extern char *progname; 105 106 char *string_table; 107 int next_free; /* next free character in string_table */ 108 unsigned int table_size = 0; /* current string_table size */ 109 short term_names; /* string table offset - current terminal */ 110 int part2 = 0; /* set to allow old compiled defns to be used */ 111 int complete = 0; /* 1 if entry done with no forward uses */ 112 113 struct use_item { 114 long offset; 115 struct use_item *fptr, *bptr; 116 }; 117 118 struct use_header { 119 struct use_item *head, *tail; 120 }; 121 122 struct use_header use_list = {NULL, NULL}; 123 int use_count = 0; 124 125 void dequeue(struct use_item *); 126 void init_structure(short Booleans[], short Numbers[], short Strings[]); 127 void dump_structure(short Booleans[], short Numbers[], short Strings[]); 128 129 /* 130 * The use_list is a doubly-linked list with NULLs terminating the lists: 131 * 132 * use_item use_item use_item 133 * --------- --------- --------- 134 * | | | | | | offset 135 * |-------| |-------| |-------| 136 * | ----+-->| ----+-->| NULL | fptr 137 * |-------| |-------| |-------| 138 * | NULL |<--+---- |<--+---- | bptr 139 * --------- --------- --------- 140 * ^ ^ 141 * | ------------------ | 142 * | | | | | 143 * +--+---- | ----+---+ 144 * | | | 145 * ------------------ 146 * head tail 147 * use_list 148 * 149 */ 150 151 152 /* 153 * compile() 154 * 155 * Main loop of the compiler. 156 * 157 * get_token() 158 * if curr_token != NAMES 159 * err_abort() 160 * while (not at end of file) 161 * do an entry 162 * 163 */ 164 165 void 166 compile() 167 { 168 char line[1024]; 169 int token_type; 170 struct use_item *ptr; 171 int old_use_count; 172 173 token_type = get_token(); 174 175 if (token_type != NAMES) 176 err_abort( 177 "File does not start with terminal names in column one"); 178 179 while (token_type != EOF) 180 token_type = do_entry((struct use_item *)NULL); 181 182 DEBUG(2, "Starting handling of forward USE's\n", ""); 183 184 for (part2 = 0; part2 < 2; part2++) { 185 old_use_count = -1; 186 DEBUG(2, "\n\nPART %d\n\n", part2); 187 while (use_list.head != NULL && old_use_count != use_count) { 188 old_use_count = use_count; 189 for (ptr = use_list.tail; ptr != NULL; 190 ptr = ptr->bptr) { 191 fseek(stdin, ptr->offset, 0); 192 reset_input(); 193 if ((token_type = get_token()) != NAMES) 194 syserr_abort( 195 "Token after a seek not NAMES"); 196 (void) do_entry(ptr); 197 if (complete) 198 dequeue(ptr); 199 } 200 201 for (ptr = use_list.head; ptr != NULL; 202 ptr = ptr->fptr) { 203 fseek(stdin, ptr->offset, 0); 204 reset_input(); 205 if ((token_type = get_token()) != NAMES) 206 syserr_abort( 207 "Token after a seek not NAMES"); 208 (void) do_entry(ptr); 209 if (complete) 210 dequeue(ptr); 211 } 212 213 DEBUG(2, 214 "Finished a pass through enqueued forward USE's\n", ""); 215 } 216 } 217 218 if (use_list.head != NULL && !check_only) { 219 fprintf(stderr, 220 "\nError in following up use-links. Either there is\n"); 221 fprintf(stderr, 222 "a loop in the links or they reference non-existant\n"); 223 fprintf(stderr, 224 "terminals. The following is a list of the entries\n"); 225 fprintf(stderr, "involved:\n\n"); 226 227 for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr) { 228 fseek(stdin, ptr->offset, 0); 229 fgets(line, 1024, stdin); 230 fprintf(stderr, "%s", line); 231 } 232 233 exit(1); 234 } 235 } 236 237 void 238 dump_list(char *str) 239 { 240 struct use_item *ptr; 241 char line[512]; 242 243 fprintf(stderr, "dump_list %s\n", str); 244 for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr) { 245 fseek(stdin, ptr->offset, 0); 246 fgets(line, 1024, stdin); 247 fprintf(stderr, "ptr %x off %d bptr %x fptr %x str %s", 248 ptr, ptr->offset, ptr->bptr, ptr->fptr, line); 249 } 250 fprintf(stderr, "\n"); 251 } 252 253 /* 254 * int 255 * do_entry(item_ptr) 256 * 257 * Compile one entry. During the first pass, item_ptr is NULL. In pass 258 * two, item_ptr points to the current entry in the use_list. 259 * 260 * found-forward-use = FALSE 261 * re-initialise internal arrays 262 * save names in string_table 263 * get_token() 264 * while (not EOF and not NAMES) 265 * if found-forward-use 266 * do nothing 267 * else if 'use' 268 * if handle_use() < 0 269 * found-forward-use = TRUE 270 * else 271 * check for existance and type-correctness 272 * enter cap into structure 273 * if STRING 274 * save string in string_table 275 * get_token() 276 * if ! found-forward-use 277 * dump compiled entry into filesystem 278 * 279 */ 280 281 int 282 do_entry(item_ptr) 283 struct use_item *item_ptr; 284 { 285 long entry_offset; 286 int token_type; 287 struct name_table_entry *entry_ptr; 288 int found_forward_use = FALSE; 289 short Booleans[MAXBOOLS], 290 Numbers[MAXNUMS], 291 Strings[MAXSTRINGS]; 292 293 init_structure(Booleans, Numbers, Strings); 294 complete = 0; 295 term_names = save_str(curr_token.tk_name); 296 DEBUG(2, "Starting '%s'\n", curr_token.tk_name); 297 entry_offset = curr_file_pos; 298 299 for (token_type = get_token(); 300 token_type != EOF && token_type != NAMES; 301 token_type = get_token()) { 302 if (found_forward_use) 303 /* do nothing */; 304 else if (strcmp(curr_token.tk_name, "use") == 0) { 305 if (handle_use(item_ptr, entry_offset, 306 Booleans, Numbers, Strings) < 0) 307 found_forward_use = TRUE; 308 } else { 309 entry_ptr = find_entry(curr_token.tk_name); 310 311 if (entry_ptr == NOTFOUND) { 312 warning("Unknown Capability - '%s'", 313 curr_token.tk_name); 314 continue; 315 } 316 317 318 if (token_type != CANCEL && 319 entry_ptr->nte_type != token_type) 320 warning("Wrong type used for capability '%s'", 321 curr_token.tk_name); 322 switch (token_type) { 323 case CANCEL: 324 switch (entry_ptr->nte_type) { 325 case BOOLEAN: 326 Booleans[entry_ptr->nte_index] = -2; 327 break; 328 329 case NUMBER: 330 Numbers[entry_ptr->nte_index] = -2; 331 break; 332 333 case STRING: 334 Strings[entry_ptr->nte_index] = -2; 335 break; 336 } 337 break; 338 339 case BOOLEAN: 340 if (Booleans[entry_ptr->nte_index] == 0) 341 Booleans[entry_ptr->nte_index] = TRUE; 342 break; 343 344 case NUMBER: 345 if (Numbers[entry_ptr->nte_index] == -1) 346 Numbers[entry_ptr->nte_index] = 347 curr_token.tk_valnumber; 348 break; 349 350 case STRING: 351 if (Strings[entry_ptr->nte_index] == -1) 352 Strings[entry_ptr->nte_index] = 353 save_str(curr_token.tk_valstring); 354 break; 355 356 default: 357 warning("Unknown token type"); 358 panic_mode(','); 359 continue; 360 } 361 } /* end else cur_token.name != "use" */ 362 363 } /* endwhile (not EOF and not NAMES) */ 364 365 if (found_forward_use) 366 return (token_type); 367 368 dump_structure(Booleans, Numbers, Strings); 369 370 complete = 1; 371 return (token_type); 372 } 373 374 /* 375 Change all cancellations to a non-entry. 376 For booleans, @ -> false 377 For nums, @ -> -1 378 For strings, @ -> -1 379 380 This only has to be done for entries which 381 have to be compatible with the pre-Vr3 format. 382 */ 383 #ifndef NOCANCELCOMPAT 384 void 385 elim_cancellations(short Booleans[], short Numbers[], short Strings[]) 386 { 387 int i; 388 for (i = 0; i < BoolCount; i++) { 389 if (Booleans[i] == -2) 390 Booleans[i] = FALSE; 391 } 392 393 for (i = 0; i < NumCount; i++) { 394 if (Numbers[i] == -2) 395 Numbers[i] = -1; 396 } 397 398 for (i = 0; i < StrCount; i++) { 399 if (Strings[i] == -2) 400 Strings[i] = -1; 401 } 402 } 403 #endif /* NOCANCELCOMPAT */ 404 /* 405 Change the cancellation signal from the -2 used internally to 406 the 2 used within the binary. 407 */ 408 void 409 change_cancellations(short Booleans[]) 410 { 411 int i; 412 for (i = 0; i < BoolCount; i++) { 413 if (Booleans[i] == -2) 414 Booleans[i] = 2; 415 } 416 417 } 418 419 /* 420 * enqueue(offset) 421 * 422 * Put a record of the given offset onto the use-list. 423 * 424 */ 425 426 void 427 enqueue(long offset) 428 { 429 struct use_item *item; 430 431 item = (struct use_item *)malloc(sizeof (struct use_item)); 432 433 if (item == NULL) 434 syserr_abort("Not enough memory for use_list element"); 435 436 item->offset = offset; 437 438 if (use_list.head != NULL) { 439 item->bptr = use_list.tail; 440 use_list.tail->fptr = item; 441 item->fptr = NULL; 442 use_list.tail = item; 443 } else { 444 use_list.tail = use_list.head = item; 445 item->fptr = item->bptr = NULL; 446 } 447 448 use_count ++; 449 } 450 451 /* 452 * dequeue(ptr) 453 * 454 * remove the pointed-to item from the use_list 455 * 456 */ 457 458 void 459 dequeue(struct use_item *ptr) 460 { 461 if (ptr->fptr == NULL) 462 use_list.tail = ptr->bptr; 463 else 464 (ptr->fptr)->bptr = ptr->bptr; 465 466 if (ptr->bptr == NULL) 467 use_list.head = ptr->fptr; 468 else 469 (ptr->bptr)->fptr = ptr->fptr; 470 471 use_count --; 472 } 473 474 /* 475 * invalid_term_name(name) 476 * 477 * Look for invalid characters in a term name. These include 478 * space, tab and '/'. 479 * 480 * Generate an error message if given name does not begin with a 481 * digit or letter, then exit. 482 * 483 * return TRUE if name is invalid. 484 * 485 */ 486 487 static int 488 invalid_term_name(char *name) 489 { 490 int error = 0; 491 if (! isdigit(*name) && ! islower(*name) && ! isupper(*name)) 492 error++; 493 494 for (; *name; name++) 495 if (isalnum(*name)) 496 continue; 497 else if (isspace(*name) || (*name == '/')) 498 return (1); 499 if (error) { 500 fprintf(stderr, "%s: Line %d: Illegal terminal name - '%s'\n", 501 progname, curr_line, name); 502 fprintf(stderr, 503 "Terminal names must start with a letter or digit\n"); 504 exit(1); 505 } 506 return (0); 507 } 508 509 /* 510 * dump_structure() 511 * 512 * Save the compiled version of a description in the filesystem. 513 * 514 * make a copy of the name-list 515 * break it up into first-name and all-but-last-name 516 * if necessary 517 * clear CANCELS out of the structure 518 * creat(first-name) 519 * write object information to first-name 520 * close(first-name) 521 * for each valid name 522 * link to first-name 523 * 524 */ 525 526 void 527 dump_structure(short Booleans[], short Numbers[], short Strings[]) 528 { 529 struct stat64 statbuf; 530 FILE *fp; 531 char name_list[1024]; 532 char *first_name, *other_names, *cur_name; 533 char filename[128 + 2 + 1]; 534 char linkname[128 + 2 + 1]; 535 int len; 536 int alphastart = 0; 537 extern char *strchr(), *strrchr(); 538 539 strcpy(name_list, term_names + string_table); 540 DEBUG(7, "Name list = '%s'\n", name_list); 541 542 first_name = name_list; 543 /* Set othernames to 1 past first '|' in the list. */ 544 /* Null out that '|' in the process. */ 545 other_names = strchr(first_name, '|'); 546 if (other_names) 547 *other_names++ = '\0'; 548 549 if (invalid_term_name(first_name)) 550 warning("'%s': bad first term name.", first_name); 551 552 553 DEBUG(7, "First name = '%s'\n", first_name); 554 DEBUG(7, "Other names = '%s'\n", other_names ? other_names : "NULL"); 555 556 if ((len = strlen(first_name)) > 128) 557 warning("'%s': terminal name too long.", first_name); 558 else if (len == 1) 559 warning("'%s': terminal name too short.", first_name); 560 561 check_dir(first_name[0]); 562 563 sprintf(filename, "%c/%s", first_name[0], first_name); 564 565 if (strlen(filename) > 16) 566 warning("'%s' filename too long, truncating to '%.16s'\n", 567 filename, filename); 568 if (stat64(filename, &statbuf) >= 0 && statbuf.st_mtime >= start_time) { 569 warning("'%s' defined in more than one entry.", first_name); 570 fprintf(stderr, "Entry being used is '%s'.\n", 571 (unsigned)term_names + string_table); 572 } 573 574 if (!check_only) { 575 unlink(filename); 576 fp = fopen(filename, "w"); 577 if (fp == NULL) { 578 perror(filename); 579 syserr_abort("Can't open %s/%s\n", 580 destination, filename); 581 } 582 DEBUG(1, "Created %.16s\n", filename); 583 } else DEBUG(1, "Would have created %.16s\n", filename); 584 585 #ifndef NOCANCELCOMPAT 586 /* if there is no '+' in the name, eliminate */ 587 /* cancellation markings. */ 588 if (strchr(first_name, '+') == 0) 589 elim_cancellations(Booleans, Numbers, Strings); 590 else 591 #endif /* NOCANCELCOMPAT */ 592 change_cancellations(Booleans); 593 594 if (!check_only) { 595 if (write_object(fp, Booleans, Numbers, Strings) < 0) { 596 syserr_abort("Error in writing %s/%s", 597 destination, filename); 598 } 599 fclose(fp); 600 } 601 602 alphastart = isalpha(first_name[0]); 603 604 while (other_names) { 605 cur_name = other_names; 606 other_names = strchr(cur_name, '|'); 607 if (other_names) 608 *other_names++ = '\0'; 609 if (*cur_name == '\0') 610 continue; 611 612 if ((len = strlen(cur_name)) > 128) { 613 warning("'%s': terminal name too long.", cur_name); 614 continue; 615 } else if (len == 1) { 616 warning("'%s': terminal name too short.", first_name); 617 continue; 618 } 619 620 if (invalid_term_name(cur_name)) { 621 if (other_names) 622 warning("'%s': bad term name found in list.", 623 cur_name); 624 continue; 625 } 626 627 check_dir(cur_name[0]); 628 629 sprintf(linkname, "%c/%s", cur_name[0], cur_name); 630 631 if (strlen(linkname) > 16) { 632 if (other_names) { 633 warning( 634 "'%s' linkname too long, truncating to '%.16s'\n", linkname, linkname); 635 } else { 636 continue; 637 } 638 } 639 alphastart |= isalpha(cur_name[0]); 640 641 if (strcmp(first_name, cur_name) == 0) { 642 warning("Terminal name '%s' synonym for itself", 643 first_name); 644 } else { 645 if (!check_only) { 646 if (stat64(linkname, &statbuf) >= 0 && 647 statbuf.st_mtime >= start_time) { 648 warning( 649 "'%s' defined in more than one entry.", cur_name); 650 fprintf(stderr, 651 "Entry being used is '%s'.\n", 652 (unsigned)term_names + 653 string_table); 654 } 655 unlink(linkname); 656 if (link(filename, linkname) < 0) 657 syserr_abort("Can't link %s to %s", 658 filename, linkname); 659 DEBUG(1, "Linked %.16s\n", linkname); 660 } else DEBUG(1, "Would have linked %.16s\n", linkname); 661 } 662 } 663 664 if (!alphastart) { 665 warning("At least one synonym should begin with a letter."); 666 } 667 } 668 669 /* 670 * int 671 * write_object(fp, Booleans, Numbers, Strings) 672 * 673 * Write out the compiled entry to the given file. 674 * Return 0 if OK or -1 if not. 675 * 676 */ 677 678 #define swap(x) (((x >> 8) & 0377) + 256 * (x & 0377)) 679 680 #define might_swap(x) (must_swap() ? swap(x) : (x)) 681 682 683 int 684 write_object(fp, Booleans, Numbers, Strings) 685 FILE *fp; 686 short Booleans[]; 687 short Numbers[]; 688 short Strings[]; 689 { 690 struct header header; 691 char *namelist; 692 short namelen; 693 char zero = '\0'; 694 int i; 695 char cBooleans[MAXBOOLS]; 696 int l_next_free; 697 698 namelist = term_names + string_table; 699 namelen = strlen(namelist) + 1; 700 701 l_next_free = next_free; 702 if (l_next_free % 256 == 255) 703 l_next_free++; 704 705 if (must_swap()) { 706 header.magic = swap(MAGIC); 707 header.name_size = swap(namelen); 708 header.bool_count = swap(BoolCount); 709 header.num_count = swap(NumCount); 710 header.str_count = swap(StrCount); 711 header.str_size = swap(l_next_free); 712 } else { 713 header.magic = MAGIC; 714 header.name_size = namelen; 715 header.bool_count = BoolCount; 716 header.num_count = NumCount; 717 header.str_count = StrCount; 718 header.str_size = l_next_free; 719 } 720 721 for (i = 0; i < BoolCount; i++) 722 cBooleans[i] = Booleans[i]; 723 724 if (fwrite(&header, sizeof (header), 1, fp) != 1 || 725 fwrite(namelist, sizeof (char), namelen, fp) != namelen || 726 fwrite(cBooleans, sizeof (char), BoolCount, fp) != 727 BoolCount) 728 return (-1); 729 730 if ((namelen+BoolCount) % 2 != 0 && 731 fwrite(&zero, sizeof (char), 1, fp) != 1) 732 return (-1); 733 734 if (must_swap()) { 735 for (i = 0; i < NumCount; i++) 736 Numbers[i] = swap(Numbers[i]); 737 for (i = 0; i < StrCount; i++) 738 Strings[i] = swap(Strings[i]); 739 } 740 741 if (fwrite((char *)Numbers, sizeof (short), NumCount, fp) != NumCount || 742 fwrite((char *)Strings, sizeof (short), StrCount, fp) 743 != StrCount || 744 fwrite(string_table, sizeof (char), l_next_free, fp) 745 != l_next_free) 746 return (-1); 747 748 return (0); 749 } 750 751 /* 752 * int 753 * save_str(string) 754 * 755 * copy string into next free part of string_table, doing a realloc() 756 * if necessary. return offset of beginning of string from start of 757 * string_table. 758 * 759 */ 760 761 int 762 save_str(string) 763 char *string; 764 { 765 int old_next_free; 766 767 /* Do not let an offset be 255. It reads as -1 in Vr2 binaries. */ 768 if (next_free % 256 == 255) 769 next_free++; 770 771 old_next_free = next_free; 772 773 if (table_size == 0) { 774 if ((string_table = malloc(1024)) == NULL) 775 syserr_abort("Out of memory"); 776 table_size = 1024; 777 DEBUG(5, "Made initial string table allocation. Size is %u\n", 778 table_size); 779 } 780 781 while (table_size <= next_free + strlen(string)) { 782 if ((string_table = realloc(string_table, table_size + 1024)) 783 == NULL) 784 syserr_abort("Out of memory"); 785 table_size += 1024; 786 DEBUG(5, "Extended string table. Size now %u\n", table_size); 787 } 788 789 strcpy(&string_table[next_free], string); 790 DEBUG(7, "Saved string '%s' ", string); 791 DEBUG(7, "at location %d\n", next_free); 792 next_free += strlen(string) + 1; 793 794 return (old_next_free); 795 } 796 797 /* 798 * init_structure(Booleans, Numbers, Strings) 799 * 800 * Initialise the given arrays 801 * Reset the next_free counter to zero. 802 * 803 */ 804 805 void 806 init_structure(short Booleans[], short Numbers[], short Strings[]) 807 { 808 int i; 809 810 for (i = 0; i < BoolCount; i++) 811 Booleans[i] = FALSE; 812 813 for (i = 0; i < NumCount; i++) 814 Numbers[i] = -1; 815 816 for (i = 0; i < StrCount; i++) 817 Strings[i] = -1; 818 819 next_free = 0; 820 } 821 822 /* 823 * int 824 * handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings) 825 * 826 * Merge the compiled file whose name is in cur_token.valstring 827 * with the current entry. 828 * 829 * if it's a forward use-link 830 * if item_ptr == NULL 831 * queue it up for later handling 832 * else 833 * ignore it (we're already going through the queue) 834 * else it's a backward use-link 835 * read in the object file for that terminal 836 * merge contents with current structure 837 * 838 * Returned value is 0 if it was a backward link and we 839 * successfully read it in, -1 if a forward link. 840 */ 841 842 int 843 handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings) 844 long entry_offset; 845 struct use_item *item_ptr; 846 short Booleans[]; 847 short Numbers[]; 848 short Strings[]; 849 { 850 struct _bool_struct use_bools; 851 struct _num_struct use_nums; 852 struct _str_struct use_strs; 853 struct stat64 statbuf; 854 char filename[50]; 855 int i; 856 char *UB = &use_bools._auto_left_margin; /* first bool */ 857 short *UN = &use_nums._columns; /* first num */ 858 char **US = &use_strs.strs._back_tab; /* first str */ 859 860 if (invalid_term_name(curr_token.tk_valstring)) 861 warning("%s: bad term name", curr_token.tk_valstring); 862 863 sprintf(filename, "%c/%s", curr_token.tk_valstring[0], 864 curr_token.tk_valstring); 865 866 if (stat64(filename, &statbuf) < 0 || 867 part2 == 0 && statbuf.st_mtime < start_time) { 868 DEBUG(2, "Forward USE to %s", curr_token.tk_valstring); 869 870 if (item_ptr == NULL) { 871 DEBUG(2, " (enqueued)\n", ""); 872 enqueue(entry_offset); 873 } else DEBUG(2, " (skipped)\n", ""); 874 875 return (-1); 876 } else { 877 DEBUG(2, "Backward USE to %s\n", curr_token.tk_valstring); 878 if (read_entry(filename, &use_bools, &use_nums, &use_strs) < 0) 879 syserr_abort("Error in re-reading compiled file %s", 880 filename); 881 882 for (i = 0; i < BoolCount; i++) { 883 if (Booleans[i] == FALSE) 884 if (UB[i] == TRUE) /* now true */ 885 Booleans[i] = TRUE; 886 else if (UB[i] > TRUE) /* cancelled */ 887 Booleans[i] = -2; 888 } 889 890 for (i = 0; i < NumCount; i++) { 891 if (Numbers[i] == -1) 892 Numbers[i] = UN[i]; 893 } 894 895 for (i = 0; i < StrCount; i++) { 896 if (Strings[i] == -1) 897 if (US[i] == (char *)-1) 898 Strings[i] = -2; 899 else if (US[i] != (char *)0) 900 Strings[i] = save_str(US[i]); 901 } 902 903 } 904 return (0); 905 } 906