📄 tic_parse.c
字号:
use_list.head = ptr->fptr; else (ptr->bptr)->fptr = ptr->fptr; use_count --;}/* * invalid_term_name(name) * * Look for invalid characters in a term name. These include * space, tab and '/'. * * Generate an error message if given name does not begin with a * digit or letter, then exit. * * return TRUE if name is invalid. * */static int invalid_term_name(name)register char *name;{ int error = 0; if (! isdigit(*name) && ! islower(*name) && ! isupper(*name)) error++; for ( ; *name ; name++) if (isalnum(*name)) continue; else if (isspace(*name) || (*name == '/')) return 1; if (error) { fprintf(stderr, "%s: Line %d: Illegal terminal name - '%s'\n", progname, curr_line, name); fprintf(stderr, "Terminal names must start with a letter or digit\n"); exit(1); } return 0;}/* * dump_structure() * * Save the compiled version of a description in the filesystem. * * make a copy of the name-list * break it up into first-name and all-but-last-name * if necessary * clear CANCELS out of the structure * creat(first-name) * write object information to first-name * close(first-name) * for each valid name * link to first-name * */dump_structure(Booleans, Numbers, Strings)short Booleans[];short Numbers[];short Strings[];{ struct stat statbuf; FILE *fp; char name_list[1024]; register char *first_name, *other_names, *cur_name; char filename[1024]; char linkname[1024]; int len; int alphastart = 0; extern char *strchr(), *strrchr(); strcpy(name_list, term_names + string_table); DEBUG(7, "Name list = '%s'\n", name_list); first_name = name_list; /* Set othernames to 1 past first '|' in the list. */ /* Null out that '|' in the process. */ other_names = strchr(first_name, '|'); if (other_names) *other_names++ = '\0'; if (invalid_term_name(first_name)) warning("'%s': bad first term name.", first_name); DEBUG(7, "First name = '%s'\n", first_name); DEBUG(7, "Other names = '%s'\n", other_names ? other_names : "NULL"); if ((len = strlen(first_name)) > 100) warning("'%s': terminal name too long.", first_name); else if (len == 1) warning("'%s': terminal name too short.", first_name); check_dir(first_name[0]); sprintf(filename, "%c/%s", first_name[0], first_name); if (stat(filename, &statbuf) >= 0 && statbuf.st_mtime >= start_time) { warning("'%s' defined in more than one entry.", first_name); fprintf(stderr, "Entry being used is '%s'.\n", (unsigned) term_names + string_table); } if (!check_only) { unlink(filename); fp = fopen(filename, "w"); if (fp == NULL) { perror(filename); syserr_abort("Can't open %s/%s\n", destination, filename); } DEBUG(1, "Created %s\n", filename); } else DEBUG(1, "Would have created %s\n", filename);#ifndef NOCANCELCOMPAT /* if there is no '+' in the name, eliminate */ /* cancellation markings. */ if (strchr(first_name, '+') == 0) elim_cancellations(Booleans, Numbers, Strings); else#endif /* NOCANCELCOMPAT */ change_cancellations(Booleans); if (!check_only) { if (write_object(fp, Booleans, Numbers, Strings) < 0) { syserr_abort("Error in writing %s/%s", destination, filename); } fclose(fp); } alphastart = isalpha(first_name[0]); while (other_names) { cur_name = other_names; other_names = strchr(cur_name, '|'); if (other_names) *other_names++ = '\0'; if (*cur_name == '\0') continue; if ((len = strlen(cur_name)) > 100) { warning("'%s': terminal name too long.", cur_name); continue; } else if (len == 1) { warning("'%s': terminal name too short.", cur_name); continue; } if (invalid_term_name(cur_name)) { if (other_names) warning("'%s': bad term name found in list.", cur_name); continue; } check_dir(cur_name[0]); sprintf(linkname, "%c/%s", cur_name[0], cur_name); alphastart |= isalpha(cur_name[0]); if (strcmp(first_name, cur_name) == 0) { warning("Terminal name '%s' synonym for itself", first_name); } else { if (!check_only) { if (stat(linkname, &statbuf) >= 0 && statbuf.st_mtime >= start_time) { warning("'%s' defined in more than one entry.", cur_name); fprintf(stderr, "Entry being used is '%s'.\n", (unsigned) term_names + string_table); } unlink(linkname); if (link(filename, linkname) < 0) syserr_abort("Can't link %s to %s", filename, linkname); DEBUG(1, "Linked %s\n", linkname); } else DEBUG(1, "Would have linked %s\n", linkname); } } if (!alphastart) { warning("At least one synonym should begin with a letter."); }}/* * int * write_object(fp, Booleans, Numbers, Strings) * * Write out the compiled entry to the given file. * Return 0 if OK or -1 if not. * */#define swap(x) (((x >> 8) & 0377) + 256 * (x & 0377))#define might_swap(x) (must_swap() ? swap(x) : (x))intwrite_object(fp, Booleans, Numbers, Strings)FILE *fp;short Booleans[];short Numbers[];short Strings[];{ struct header header; char *namelist; short namelen; char zero = '\0'; register int i; char cBooleans[MAXBOOLS]; register int l_next_free; namelist = term_names + string_table; namelen = strlen(namelist) + 1; l_next_free = next_free; if (l_next_free % 256 == 255) l_next_free++; if (must_swap()) { header.magic = swap(MAGIC); header.name_size = swap(namelen); header.bool_count = swap(BoolCount); header.num_count = swap(NumCount); header.str_count = swap(StrCount); header.str_size = swap(l_next_free); } else { header.magic = MAGIC; header.name_size = namelen; header.bool_count = BoolCount; header.num_count = NumCount; header.str_count = StrCount; header.str_size = l_next_free; } for (i=0; i < BoolCount; i++) cBooleans[i] = Booleans[i]; if (fwrite(&header, sizeof(header), 1, fp) != 1 || fwrite(namelist, sizeof(char), namelen, fp) != namelen || fwrite(cBooleans, sizeof(char), BoolCount, fp) != BoolCount) return(-1); if ((namelen+BoolCount) % 2 != 0 && fwrite(&zero, sizeof(char), 1, fp) != 1) return(-1); if (must_swap()) { for (i=0; i < NumCount; i++) Numbers[i] = swap(Numbers[i]); for (i=0; i < StrCount; i++) Strings[i] = swap(Strings[i]); } if (fwrite((char *)Numbers, sizeof(short), NumCount, fp) != NumCount || fwrite((char *)Strings, sizeof(short), StrCount, fp) != StrCount || fwrite(string_table, sizeof(char), l_next_free, fp) != l_next_free) return(-1); return(0);}/* * int * save_str(string) * * copy string into next free part of string_table, doing a realloc() * if necessary. return offset of beginning of string from start of * string_table. * */intsave_str(string)char *string;{ char *malloc(), *realloc(); int old_next_free; /* Do not let an offset be 255. It reads as -1 in Vr2 binaries. */ if (next_free % 256 == 255) next_free++; old_next_free = next_free; if (table_size == 0) { if ((string_table = malloc(1024)) == NULL) syserr_abort("Out of memory"); table_size = 1024; DEBUG(5, "Made initial string table allocation. Size is %u\n", table_size); } while (table_size < next_free + strlen(string)) { if ((string_table = realloc(string_table, table_size + 1024)) == NULL) syserr_abort("Out of memory"); table_size += 1024; DEBUG(5, "Extended string table. Size now %u\n", table_size); } strcpy(&string_table[next_free], string); DEBUG(7, "Saved string '%s' ", string); DEBUG(7, "at location %d\n", next_free); next_free += strlen(string) + 1; return(old_next_free);}/* * init_structure(Booleans, Numbers, Strings) * * Initialise the given arrays * Reset the next_free counter to zero. * */init_structure(Booleans, Numbers, Strings)short Booleans[];short Numbers[], Strings[];{ int i; for (i=0; i < BoolCount; i++) Booleans[i] = FALSE; for (i=0; i < NumCount; i++) Numbers[i] = -1; for (i=0; i < StrCount; i++) Strings[i] = -1; next_free = 0;}/*** int** handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings)**** Merge the compiled file whose name is in cur_token.valstring** with the current entry.**** if it's a forward use-link** if item_ptr == NULL** queue it up for later handling** else** ignore it (we're already going through the queue)** else it's a backward use-link** read in the object file for that terminal** merge contents with current structure**** Returned value is 0 if it was a backward link and we** successfully read it in, -1 if a forward link.*/inthandle_use(item_ptr, entry_offset, Booleans, Numbers, Strings)long entry_offset;struct use_item *item_ptr;short Booleans[];short Numbers[];short Strings[];{ struct _bool_struct use_bools; struct _num_struct use_nums; struct _str_struct use_strs; struct stat statbuf; char filename[50]; int i; char *UB = &use_bools._auto_left_margin;/* first bool */ short *UN = &use_nums._columns; /* first num */ char **US = &use_strs.strs._back_tab; /* first str */ if (invalid_term_name(curr_token.tk_valstring)) warning("%s: bad term name", curr_token.tk_valstring); sprintf(filename, "%c/%s", curr_token.tk_valstring[0], curr_token.tk_valstring); if (stat(filename, &statbuf) < 0 || part2==0 && statbuf.st_mtime < start_time) { DEBUG(2, "Forward USE to %s", curr_token.tk_valstring); if (item_ptr == NULL) { DEBUG(2, " (enqueued)\n", ""); enqueue(entry_offset); } else DEBUG(2, " (skipped)\n", ""); return(-1); } else { DEBUG(2, "Backward USE to %s\n", curr_token.tk_valstring); if (read_entry(filename, &use_bools, &use_nums, &use_strs) < 0) syserr_abort("Error in re-reading compiled file %s", filename); for (i=0; i < BoolCount; i++) { if (Booleans[i] == FALSE) if (UB[i] == TRUE) /* now true */ Booleans[i] = TRUE; else if (UB[i] > TRUE) /* cancelled */ Booleans[i] = -2; } for (i=0; i < NumCount; i++) { if (Numbers[i] == -1) Numbers[i] = UN[i]; } for (i=0; i < StrCount; i++) { if (Strings[i] == -1) if (US[i] == (char *) -1) Strings[i] = -2; else if (US[i] != (char *) 0) Strings[i] = save_str(US[i]); } } return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -