📄 tic_parse.c
字号:
/* Copyright (c) 1984 AT&T *//* All Rights Reserved *//* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T *//* The copyright notice above does not evidence any *//* actual or intended publication of such source code. */#ifndef lintstatic char sccsid[] = "@(#)tic_parse.c 1.1 92/07/30 SMI"; /* from S5R3.1 1.15 */#endif/********************************************************************** COPYRIGHT NOTICE ************************************************************************ This software is copyright (C) 1982 by Pavel Curtis ** ** Permission is granted to reproduce and distribute ** this file by any means so long as no fee is charged ** above a nominal handling fee and so long as this ** notice is always included in the copies. ** ** Other rights are reserved except as explicitly granted ** by written permission of the author. ** Pavel Curtis ** Computer Science Dept. ** 405 Upson Hall ** Cornell University ** Ithaca, NY 14853 ** ** Ph- (607) 256-4934 ** ** Pavel.Cornell@Udel-Relay (ARPAnet) ** decvax!cornell!pavel (UUCPnet) **********************************************************************//* * comp_parse.c -- The high-level (ha!) parts of the compiler, * that is, the routines which drive the scanner, * etc. * * $Log: RCS/comp_parse.v $ * Revision 2.1 82/10/25 14:45:43 pavel * Added Copyright Notice * * Revision 2.0 82/10/24 15:16:39 pavel * Beta-one Test Release * * Revision 1.3 82/08/23 22:29:39 pavel * The REAL Alpha-one Release Version * * Revision 1.2 82/08/19 19:09:53 pavel * Alpha Test Release One * * Revision 1.1 82/08/12 18:37:12 pavel * Initial revision * * */#include <sys/types.h>#include <sys/stat.h>#include <stdio.h>#include <ctype.h>#include "curses_inc.h"#include "compiler.h"#include "object.h"extern char check_only;extern char *progname;char *string_table;int next_free; /* next free character in string_table */unsigned int table_size = 0; /* current string_table size */short term_names; /* string table offset - current terminal */int part2 = 0; /* set to allow old compiled defns to be used */int complete = 0; /* 1 if entry done with no forward uses */struct use_item{ long offset; int line_number; struct use_item *fptr, *bptr;};struct use_header{ struct use_item *head, *tail;};struct use_header use_list = {NULL, NULL};int use_count = 0;/* * The use_list is a doubly-linked list with NULLs terminating the lists: * * use_item use_item use_item * --------- --------- --------- * | | | | | | offset * |-------| |-------| |-------| * | ----+-->| ----+-->| NULL | fptr * |-------| |-------| |-------| * | NULL |<--+---- |<--+---- | bptr * --------- --------- --------- * ^ ^ * | ------------------ | * | | | | | * +--+---- | ----+---+ * | | | * ------------------ * head tail * use_list * *//* * compile() * * Main loop of the compiler. * * get_token() * if curr_token != NAMES * err_abort() * while (not at end of file) * do an entry * */compile(){ char line[1024]; int token_type; struct use_item *ptr; int old_use_count; token_type = get_token(); if (token_type != NAMES) err_abort("File does not start with terminal names in column one"); while (token_type != EOF) token_type = do_entry((struct use_item *) NULL); DEBUG(2, "Starting handling of forward USE's\n", ""); for (part2=0; part2<2; part2++) { old_use_count = -1; DEBUG(2, "\n\nPART %d\n\n", part2); while (use_list.head != NULL && old_use_count != use_count) { old_use_count = use_count; for (ptr = use_list.tail; ptr != NULL; ptr = ptr->bptr) { fseek(stdin, ptr->offset, 0); curr_line = ptr->line_number; reset_input(); if ((token_type = get_token()) != NAMES) syserr_abort("Token after a seek not NAMES"); (void) do_entry(ptr); if (complete) dequeue(ptr); } for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr) { fseek(stdin, ptr->offset, 0); curr_line = ptr->line_number; reset_input(); if ((token_type = get_token()) != NAMES) syserr_abort("Token after a seek not NAMES"); (void) do_entry(ptr); if (complete) dequeue(ptr); } DEBUG(2, "Finished a pass through enqueued forward USE's\n", ""); } } if (use_list.head != NULL && !check_only) { fprintf(stderr, "\nError in following up use-links. Either there is\n"); fprintf(stderr, "a loop in the links or they reference non-existent\n"); fprintf(stderr, "terminals. The following is a list of the entries\n"); fprintf(stderr, "involved:\n\n"); for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr) { fseek(stdin, ptr->offset, 0); if (fgets(line, 1024, stdin) == NULL) { if (ferror(stdin)) syserr_abort("I/O error on standard input"); else err_abort("Premature EOF"); } fprintf(stderr, "%s", line); } exit(1); }}dump_list(str)char *str;{ struct use_item *ptr; char line[512]; fprintf(stderr, "dump_list %s\n", str); for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr) { fseek(stdin, ptr->offset, 0); fgets(line, 1024, stdin); fprintf(stderr, "ptr %x off %d bptr %x fptr %x str %s", ptr, ptr->offset, ptr->bptr, ptr->fptr, line); } fprintf(stderr, "\n");}/* * int * do_entry(item_ptr) * * Compile one entry. During the first pass, item_ptr is NULL. In pass * two, item_ptr points to the current entry in the use_list. * * found-forward-use = FALSE * re-initialise internal arrays * save names in string_table * get_token() * while (not EOF and not NAMES) * if found-forward-use * do nothing * else if 'use' * if handle_use() < 0 * found-forward-use = TRUE * else * check for existance and type-correctness * enter cap into structure * if STRING * save string in string_table * get_token() * if ! found-forward-use * dump compiled entry into filesystem * */intdo_entry(item_ptr)struct use_item *item_ptr;{ long entry_offset; register int token_type; register struct name_table_entry *entry_ptr; int found_forward_use = FALSE; short Booleans[MAXBOOLS], Numbers[MAXNUMS], Strings[MAXSTRINGS]; init_structure(Booleans, Numbers, Strings); complete = 0; term_names = save_str(curr_token.tk_name); DEBUG(2, "Starting '%s'\n", curr_token.tk_name); entry_offset = entry_file_pos; for (token_type = get_token(); token_type != EOF && token_type != NAMES; token_type = get_token()) { if (found_forward_use) /* do nothing */ ; else if (strcmp(curr_token.tk_name, "use") == 0) { if (handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings) < 0) found_forward_use = TRUE; } else { entry_ptr = find_entry(curr_token.tk_name); if (entry_ptr == NOTFOUND) { warning("Unknown Capability - '%s'", curr_token.tk_name); continue; } if (token_type != CANCEL && entry_ptr->nte_type != token_type) warning("Wrong type used for capability '%s'", curr_token.tk_name); switch (token_type) { case CANCEL: switch (entry_ptr->nte_type) { case BOOLEAN: Booleans[entry_ptr->nte_index] = -2; break; case NUMBER: Numbers[entry_ptr->nte_index] = -2; break; case STRING: Strings[entry_ptr->nte_index] = -2; break; } break; case BOOLEAN: if (Booleans[entry_ptr->nte_index] == 0) Booleans[entry_ptr->nte_index] = TRUE; break; case NUMBER: if (Numbers[entry_ptr->nte_index] == -1) Numbers[entry_ptr->nte_index] = curr_token.tk_valnumber; break; case STRING: if (Strings[entry_ptr->nte_index] == -1) Strings[entry_ptr->nte_index] = save_str(curr_token.tk_valstring); break; default: warning("Unknown token type"); panic_mode(','); continue; } } /* end else cur_token.name != "use" */ } /* endwhile (not EOF and not NAMES) */ if (found_forward_use) return(token_type); dump_structure(Booleans, Numbers, Strings); complete = 1; return(token_type);}/* Change all cancellations to a non-entry. For booleans, @ -> false For nums, @ -> -1 For strings, @ -> -1 This only has to be done for entries which have to be compatible with the pre-Vr3 format.*/#ifndef NOCANCELCOMPATelim_cancellations(Booleans, Numbers, Strings)short Booleans[];short Numbers[];short Strings[];{ register int i; for (i=0; i < BoolCount; i++) { if (Booleans[i] == -2) Booleans[i] = FALSE; } for (i=0; i < NumCount; i++) { if (Numbers[i] == -2) Numbers[i] = -1; } for (i=0; i < StrCount; i++) { if (Strings[i] == -2) Strings[i] = -1; }}#endif /* NOCANCELCOMPAT *//* Change the cancellation signal from the -2 used internally to the 2 used within the binary.*/change_cancellations(Booleans)short Booleans[];{ register int i; for (i=0; i < BoolCount; i++) { if (Booleans[i] == -2) Booleans[i] = 2; }}/* * enqueue(offset) * * Put a record of the given offset onto the use-list. * */enqueue(offset)long offset;{ struct use_item *item; char *malloc(); item = (struct use_item *) malloc(sizeof(struct use_item)); if (item == NULL) syserr_abort("Not enough memory for use_list element"); item->offset = offset; item->line_number = curr_line; if (use_list.head != NULL) { item->bptr = use_list.tail; use_list.tail->fptr = item; item->fptr = NULL; use_list.tail = item; } else { use_list.tail = use_list.head = item; item->fptr = item->bptr = NULL; } use_count ++;}/* * dequeue(ptr) * * remove the pointed-to item from the use_list * */dequeue(ptr)struct use_item *ptr;{ if (ptr->fptr == NULL) use_list.tail = ptr->bptr; else (ptr->fptr)->bptr = ptr->bptr; if (ptr->bptr == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -