: Run this shell script with "sh" not "csh" PATH=:/bin:/usr/bin:/usr/ucb export PATH if test ! -d =src then echo 'Making directory "=src"' mkdir =src fi echo 'x - =src/comp_captab.c' sed 's/^X//' <<'//go.sysin dd *' >=src/comp_captab.c X/* * comp_captab.c -- The names of the capabilities in a form ready for * the making of a hash table for the compiler. * */ #include "compiler.h" #include "term.h" struct name_table_entry cap_table[] = { 0, "bw", BOOLEAN, 0, 0, "am", BOOLEAN, 1, 0, "xsb", BOOLEAN, 2, 0, "xhp", BOOLEAN, 3, 0, "xenl", BOOLEAN, 4, 0, "eo", BOOLEAN, 5, 0, "gn", BOOLEAN, 6, 0, "hc", BOOLEAN, 7, 0, "km", BOOLEAN, 8, 0, "hs", BOOLEAN, 9, 0, "in", BOOLEAN, 10, 0, "da", BOOLEAN, 11, 0, "db", BOOLEAN, 12, 0, "mir", BOOLEAN, 13, 0, "msgr", BOOLEAN, 14, 0, "os", BOOLEAN, 15, 0, "eslok", BOOLEAN, 16, 0, "xt", BOOLEAN, 17, 0, "hz", BOOLEAN, 18, 0, "ul", BOOLEAN, 19, 0, "xon", BOOLEAN, 20, 0, "cols", NUMBER, 0, 0, "it", NUMBER, 1, 0, "lines", NUMBER, 2, 0, "lm", NUMBER, 3, 0, "xmc", NUMBER, 4, 0, "pb", NUMBER, 5, 0, "vt", NUMBER, 6, 0, "wsl", NUMBER, 7, 0, "nlab", NUMBER, 8, 0, "lh", NUMBER, 9, 0, "lw", NUMBER, 10, 0, "cbt", STRING, 0, 0, "bel", STRING, 1, 0, "cr", STRING, 2, 0, "csr", STRING, 3, 0, "tbc", STRING, 4, 0, "clear", STRING, 5, 0, "el", STRING, 6, 0, "ed", STRING, 7, 0, "hpa", STRING, 8, 0, "CC", STRING, 9, 0, "cup", STRING, 10, 0, "cud1", STRING, 11, 0, "home", STRING, 12, 0, "civis", STRING, 13, 0, "cub1", STRING, 14, 0, "mrcup", STRING, 15, 0, "cnorm", STRING, 16, 0, "cuf1", STRING, 17, 0, "ll", STRING, 18, 0, "cuu1", STRING, 19, 0, "cvvis", STRING, 20, 0, "dch1", STRING, 21, 0, "dl1", STRING, 22, 0, "dsl", STRING, 23, 0, "hd", STRING, 24, 0, "smacs", STRING, 25, 0, "blink", STRING, 26, 0, "bold", STRING, 27, 0, "smcup", STRING, 28, 0, "smdc", STRING, 29, 0, "dim", STRING, 30, 0, "smir", STRING, 31, 0, "invis", STRING, 32, 0, "prot", STRING, 33, 0, "rev", STRING, 34, 0, "smso", STRING, 35, 0, "smul", STRING, 36, 0, "ech", STRING, 37, 0, "rmacs", STRING, 38, 0, "sgr0", STRING, 39, 0, "rmcup", STRING, 40, 0, "rmdc", STRING, 41, 0, "rmir", STRING, 42, 0, "rmso", STRING, 43, 0, "rmul", STRING, 44, 0, "flash", STRING, 45, 0, "ff", STRING, 46, 0, "fsl", STRING, 47, 0, "is1", STRING, 48, 0, "is2", STRING, 49, 0, "is3", STRING, 50, 0, "if", STRING, 51, 0, "ich1", STRING, 52, 0, "il1", STRING, 53, 0, "ip", STRING, 54, 0, "kbs", STRING, 55, 0, "ktbc", STRING, 56, 0, "kclr", STRING, 57, 0, "kctab", STRING, 58, 0, "kdch1", STRING, 59, 0, "kdl1", STRING, 60, 0, "kcud1", STRING, 61, 0, "krmir", STRING, 62, 0, "kel", STRING, 63, 0, "ked", STRING, 64, 0, "kf0", STRING, 65, 0, "kf1", STRING, 66, 0, "kf10", STRING, 67, 0, "kf2", STRING, 68, 0, "kf3", STRING, 69, 0, "kf4", STRING, 70, 0, "kf5", STRING, 71, 0, "kf6", STRING, 72, 0, "kf7", STRING, 73, 0, "kf8", STRING, 74, 0, "kf9", STRING, 75, 0, "khome", STRING, 76, 0, "kich1", STRING, 77, 0, "kil1", STRING, 78, 0, "kcub1", STRING, 79, 0, "kll", STRING, 80, 0, "knp", STRING, 81, 0, "kpp", STRING, 82, 0, "kcuf1", STRING, 83, 0, "kind", STRING, 84, 0, "kri", STRING, 85, 0, "khts", STRING, 86, 0, "kcuu1", STRING, 87, 0, "rmkx", STRING, 88, 0, "smkx", STRING, 89, 0, "lf0", STRING, 90, 0, "lf1", STRING, 91, 0, "lf10", STRING, 92, 0, "lf2", STRING, 93, 0, "lf3", STRING, 94, 0, "lf4", STRING, 95, 0, "lf5", STRING, 96, 0, "lf6", STRING, 97, 0, "lf7", STRING, 98, 0, "lf8", STRING, 99, 0, "lf9", STRING, 100, 0, "rmm", STRING, 101, 0, "smm", STRING, 102, 0, "nel", STRING, 103, 0, "pad", STRING, 104, 0, "dch", STRING, 105, 0, "dl", STRING, 106, 0, "cud", STRING, 107, 0, "ich", STRING, 108, 0, "indn", STRING, 109, 0, "il", STRING, 110, 0, "cub", STRING, 111, 0, "cuf", STRING, 112, 0, "rin", STRING, 113, 0, "cuu", STRING, 114, 0, "pfkey", STRING, 115, 0, "pfloc", STRING, 116, 0, "pfx", STRING, 117, 0, "mc0", STRING, 118, 0, "mc4", STRING, 119, 0, "mc5", STRING, 120, 0, "rep", STRING, 121, 0, "rs1", STRING, 122, 0, "rs2", STRING, 123, 0, "rs3", STRING, 124, 0, "rf", STRING, 125, 0, "rc", STRING, 126, 0, "vpa", STRING, 127, 0, "sc", STRING, 128, 0, "ind", STRING, 129, 0, "ri", STRING, 130, 0, "sgr", STRING, 131, 0, "hts", STRING, 132, 0, "wind", STRING, 133, 0, "ht", STRING, 134, 0, "tsl", STRING, 135, 0, "uc", STRING, 136, 0, "hu", STRING, 137, 0, "iprog", STRING, 138, 0, "ka1", STRING, 139, 0, "ka3", STRING, 140, 0, "kb2", STRING, 141, 0, "kc1", STRING, 142, 0, "kc3", STRING, 143, 0, "mc5p", STRING, 144, 0, "rmp", STRING, 145, 0, "acsc", STRING, 146, 0, "pln", STRING, 147, }; struct name_table_entry *cap_hash_table[360]; int Hashtabsize = 360; int Captabsize = 180; #if (BOOLCOUNT!=21)||(NUMCOUNT!=11)||(STRCOUNT!=148) --> term.h and comp_captab.c disagree about the <-- --> numbers of booleans, numbers and/or strings <-- #endif //go.sysin dd * echo 'x - =src/comp_error.c' sed 's/^X//' <<'//go.sysin dd *' >=src/comp_error.c X/********************************************************************* * 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) * *********************************************************************/ X/* * comp_error.c -- Error message routines * * $Log: RCS/comp_error.v $ * Revision 2.1 82/10/25 14:45:31 pavel * Added Copyright Notice * * Revision 2.0 82/10/24 15:16:32 pavel * Beta-one Test Release * * Revision 1.3 82/08/23 22:29:31 pavel * The REAL Alpha-one Release Version * * Revision 1.2 82/08/19 19:09:44 pavel * Alpha Test Release One * * Revision 1.1 82/08/12 18:36:02 pavel * Initial revision * * */ static char RCSid[] = "$Header: RCS/comp_error.v Revision 2.1 82/10/25 14:45:31 pavel Exp$"; #include "compiler.h" extern char *string_table; extern short term_names; warning(fmt, a1, a2, a3, a4, a5, a6) char *fmt, *a1, *a2, *a3, *a4, *a5, *a6; { fprintf (stderr, "compile: Warning: near line %d: ", curr_line); fprintf (stderr, "terminal '%s', ", string_table+term_names); fprintf (stderr, fmt, a1, a2, a3, a4, a5, a6); fprintf (stderr, "\n"); } err_abort(fmt, a1, a2, a3, a4, a5, a6) char *fmt, *a1, *a2, *a3, *a4, *a5, *a6; { fprintf (stderr, "compile: Line %d: ", curr_line); fprintf (stderr, "terminal '%s', ", string_table+term_names); fprintf (stderr, fmt, a1, a2, a3, a4, a5, a6); fprintf (stderr, "\n"); exit(1); } syserr_abort(fmt, a1, a2, a3, a4, a5, a6) char *fmt, *a1, *a2, *a3, *a4, *a5, *a6; { fprintf (stderr, "PROGRAM ERROR: Line %d: ", curr_line); fprintf (stderr, "terminal '%s', ", string_table+term_names); fprintf (stderr, fmt, a1, a2, a3, a4, a5, a6); fprintf (stderr, "\n"); abort(); } //go.sysin dd * echo 'x - =src/comp_hash.c' sed 's/^X//' <<'//go.sysin dd *' >=src/comp_hash.c X/********************************************************************* * 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) * *********************************************************************/ X/* * comp_hash.c --- Routines to deal with the hashtable of capability * names. * * $Log: RCS/comp_hash.v $ * Revision 2.1 82/10/25 14:45:34 pavel * Added Copyright Notice * * Revision 2.0 82/10/24 15:16:34 pavel * Beta-one Test Release * * Revision 1.3 82/08/23 22:29:33 pavel * The REAL Alpha-one Release Version * * Revision 1.2 82/08/19 19:09:46 pavel * Alpha Test Release One * * Revision 1.1 82/08/12 18:36:23 pavel * Initial revision * * */ static char RCSid[] = "$Header: RCS/comp_hash.v Revision 2.1 82/10/25 14:45:34 pavel Exp$"; #include "compiler.h" #include "term.h" X/* * make_hash_table() * * Takes the entries in cap_table[] and hashes them into cap_hash_table[] * by name. There are Captabsize entries in cap_table[] and Hashtabsize * slots in cap_hash_table[]. * */ make_hash_table() { int i; int hashvalue; int collisions = 0; for (i=0; i < Captabsize; i++) { hashvalue = hash_function(cap_table[i].nte_name); DEBUG(9, "%d\n", hashvalue); if (cap_hash_table[hashvalue] != (struct name_table_entry *) 0) collisions++; cap_table[i].nte_link = cap_hash_table[hashvalue]; cap_hash_table[hashvalue] = &cap_table[i]; } DEBUG(3, "Hash table complete\n%d collisions ", collisions); DEBUG(3, "out of %d entries\n", Captabsize); } X/* * int hash_function(string) * * Computes the hashing function on the given string. * * The current hash function is the sum of each consectutive pair * of characters, taken as two-byte integers, mod Hashtabsize. * */ static int hash_function(string) char *string; { long sum = 0; while (*string) { sum += *string + (*(string + 1) << 8); string++; } return (sum % Hashtabsize); } X/* * struct name_table_entry * * find_entry(string) * * Finds the entry for the given string in the hash table if present. * Returns a pointer to the entry in the table or 0 if not found. * */ struct name_table_entry * find_entry(string) char *string; { int hashvalue; struct name_table_entry *ptr; hashvalue = hash_function(string); ptr = cap_hash_table[hashvalue]; while (ptr != (struct name_table_entry *) 0 && strcmp(ptr->nte_name, string) != 0) ptr = ptr->nte_link; return (ptr); } //go.sysin dd * echo 'x - =src/comp_main.c' sed 's/^X//' <<'//go.sysin dd *' >=src/comp_main.c X/********************************************************************* * 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) * *********************************************************************/ X/* * comp_main.c --- Main program for terminfo compiler * * $Log: RCS/comp_main.v $ * Revision 2.1 82/10/25 14:45:37 pavel * Added Copyright Notice * * Revision 2.0 82/10/24 15:16:37 pavel * Beta-one Test Release * * Revision 1.3 82/08/23 22:29:36 pavel * The REAL Alpha-one Release Version * * Revision 1.2 82/08/19 19:09:49 pavel * Alpha Test Release One * * Revision 1.1 82/08/12 18:36:55 pavel * Initial revision * * */ static char RCSid[] = "$Header: RCS/comp_main.v Revision 2.1 82/10/25 14:45:37 pavel Exp$"; #include #include #include "compiler.h" char *source_file = "/etc/terminfo"; char *destination = SRCDIR; char *usage_string = "\tcompile [-v[n]] source-file\n"; char check_only = 0; main (argc, argv) int argc; char *argv[]; { int i; int argflag = FALSE; debug_level = 0; for (i=1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'c': check_only = 1; break; case 'v': debug_level = argv[i][2] ? atoi(&argv[i][2]) : 1; break; default: fprintf(stderr, "%s: Unknown option. Usage is:\n\t%s\n", argv[0], usage_string); exit(1); } } else if (argflag) { fprintf(stderr, "%s: Too many file names. Usage is:\n\t%s\n", argv[0], usage_string); exit(1); } else { argflag = TRUE; source_file = argv[i]; } } init(argv[0]); make_hash_table(); compile(); exit(0); } X/* * init(progname) * * Miscelaneous initialisations * * Open source file as standard input * Check for access rights to destination directories * Create any directories which don't exist. * */ init(progname) char *progname; { struct stat statbuf; char *dirnames = "abcdefghijklmnopqrstuvwxyz0123456789"; char *getenv(); char dir[2]; start_time = time(0); curr_line = 0; if (freopen(source_file, "r", stdin) == NULL) { fprintf(stderr, "%s: Can't open %s\n", progname, source_file); exit(1); } if (getenv("TERMINFO") != NULL) destination = getenv("TERMINFO"); if (access(destination, 7) < 0) { fprintf(stderr, "%s: %s non-existant or permission denied\n", progname, destination); exit(1); } if (chdir(destination) < 0) { fprintf(stderr, "%s: %s is not a directory\n", progname, destination); exit(1); } dir[1] = '\0'; for (dir[0] = *dirnames; *dirnames != '\0'; dir[0] = *(++dirnames)) { if (stat(dir, &statbuf) < 0) { mkdir(dir); chmod(dir, 0755); } else if (access(dir, 7) < 0) { fprintf(stderr, "%s: %s/%s: Permission denied\n", progname, destination, dir); exit(1); } else if ((statbuf.st_mode & S_IFMT) != S_IFDIR) { fprintf(stderr, "%s: %s/%s: Not a directory\n", progname, destination, dir); exit(1); } } } X/* * mkdir(dirname) * * forks and execs the mkdir program to create the given directory * */ mkdir(dirname) char *dirname; { int fork_rtn; int status; fork_rtn = fork(); switch (fork_rtn) { case 0: /* Child */ execl("/bin/mkdir", "mkdir", dirname, 0); exit(1); case -1: /* Error */ fprintf(stderr, "compile: SYSTEM ERROR!! Fork failed!!!\n"); abort(); default: wait(&status); if (status != 0) syserr_abort("mkdir returned bad status"); break; } } //go.sysin dd * echo 'x - =src/comp_parse.c' sed 's/^X//' <<'//go.sysin dd *' >=src/comp_parse.c X/********************************************************************* * 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) * *********************************************************************/ X/* * comp_parse.c -- The high-level (ha!) parts of the compiler, * that is, the routines which drive the scanner, * etc. * * $Log: comp_parse.c,v $ * Revision 3.1 84/12/13 11:19:32 john * Revisions by Mark Horton * * 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 * * */ static char RCSid[] = "$Header: comp_parse.c,v 3.1 84/12/13 11:19:32 john Exp $"; #include #include #include #include #include "compiler.h" #include "term.h" #include "object.h" char *string_table; int next_free; /* next free character in string_table */ 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; struct use_item *fptr, *bptr; }; struct use_header { struct use_item *head, *tail; }; struct use_header use_list = {NULL, NULL}; int use_count = 0; X/* * 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 * */ X/* * 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(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); 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); 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) { fprintf(stderr, "\nError in following up use-links. Either there is\n"); fprintf(stderr, "a loop in the links or they reference non-existant\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); fgets(line, 1024, stdin); 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"); } X/* * 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 * clear CANCELS out of the structure * dump compiled entry into filesystem * */ int do_entry(item_ptr) struct use_item *item_ptr; { long entry_offset; int i; register int token_type; register struct name_table_entry *entry_ptr; int found_forward_use = FALSE; char Booleans[BOOLCOUNT]; short Numbers[NUMCOUNT], Strings[STRCOUNT]; 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 = curr_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: Booleans[entry_ptr->nte_index] = TRUE; break; case NUMBER: Numbers[entry_ptr->nte_index] = curr_token.tk_valnumber; break; case STRING: 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); 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; } dump_structure(term_names, Booleans, Numbers, Strings); complete = 1; return(token_type); } X/* * 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; 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 ++; } X/* * 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) use_list.head = ptr->fptr; else (ptr->bptr)->fptr = ptr->fptr; use_count --; } X/* * 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 * creat(first-name) * write object information to first-name * close(first-name) * for each name in all-but-last-name * link to first-name * */ dump_structure(term_names, Booleans, Numbers, Strings) short term_names; char Booleans[]; short Numbers[]; short Strings[]; { struct stat statbuf; FILE *fp; char name_list[1024]; register char *first_name, *other_names; register char *ptr; char filename[50]; char linkname[50]; extern char check_only; strcpy(name_list, term_names + string_table); DEBUG(7, "Name list = '%s'\n", name_list); first_name = name_list; ptr = &name_list[strlen(name_list) - 1]; other_names = ptr + 1; while (ptr > name_list && *ptr != '|') ptr--; if (ptr != name_list) { *ptr = '\0'; for (ptr = name_list; *ptr != '\0' && *ptr != '|'; ptr++) ; if (*ptr == '\0') other_names = ptr; else { *ptr = '\0'; other_names = ptr + 1; } } if (check_only) { DEBUG(1, "Checked %s\n", first_name); return; } DEBUG(7, "First name = '%s'\n", first_name); DEBUG(7, "Other names = '%s'\n", other_names); if (strlen(first_name) > 100) warning("'%s': terminal name too long.", first_name); check_name(first_name); 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); } 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); if (write_object(fp, term_names, Booleans, Numbers, Strings) < 0) { syserr_abort("Error in writing %s/%s", destination, filename); } fclose(fp); while (*other_names != '\0') { ptr = other_names++; while (*other_names != '|' && *other_names != '\0') other_names++; if (*other_names != '\0') *(other_names++) = '\0'; if (strlen(ptr) > 100) { warning("'%s': terminal name too long.", ptr); continue; } sprintf(linkname, "%c/%s", ptr[0], ptr); if (strcmp(filename, linkname) == 0) { warning("Terminal name '%s' synonym for itself", first_name); } else if (stat(linkname, &statbuf) >= 0 && statbuf.st_mtime >= start_time) { warning("'%s' defined in more than one entry.", ptr); fprintf(stderr, "Entry being used is '%s'.\n", (unsigned) term_names + string_table); } else { unlink(linkname); if (link(filename, linkname) < 0) syserr_abort("Can't link %s to %s", filename, linkname); DEBUG(1, "Linked %s\n", linkname); } } } X/* * int * write_object(fp, term_names, 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)) int write_object(fp, term_names, Booleans, Numbers, Strings) XFILE *fp; short term_names; char Booleans[]; short Numbers[]; short Strings[]; { struct header header; char *namelist; short namelen; char zero = '\0'; int i; namelist = term_names + string_table; namelen = strlen(namelist) + 1; 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(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 = next_free; } if (fwrite(&header, sizeof(header), 1, fp) != 1 || fwrite(namelist, sizeof(char), namelen, fp) != namelen || fwrite(Booleans, 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(Numbers, sizeof(short), NUMCOUNT, fp) != NUMCOUNT || fwrite(Strings, sizeof(short), STRCOUNT, fp) != STRCOUNT || fwrite(string_table, sizeof(char), next_free, fp) != next_free) return(-1); } X/* * check_name(name) * * Generate an error message if given name does not begin with a * digit or lower-case letter. * */ check_name(name) char *name; { if (! isdigit(name[0]) && ! islower(name[0])) { fprintf(stderr, "compile: Line %d: Illegal terminal name - '%s'\n", curr_line, name); fprintf(stderr, "Terminal names must start with lowercase or digit\n"); exit(1); } } X/* * 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. * */ int save_str(string) char *string; { char *malloc(), *realloc(); int 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 %d\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 %d\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); } X/* * init_structure(Booleans, Numbers, Strings) * * Initialise the given arrays * Reset the next_free counter to zero. * */ init_structure(Booleans, Numbers, Strings) char 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; } X/* ** 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. */ int handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings) long entry_offset; struct use_item *item_ptr; char Booleans[]; short Numbers[]; short Strings[]; { struct term use_term; struct stat statbuf; char filename[50]; int i; check_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_term) < 0) syserr_abort("Error in re-reading compiled file %s", filename); for (i=0; i < BOOLCOUNT; i++) { if (Booleans[i] == FALSE && use_term.Booleans[i] == TRUE) Booleans[i] = TRUE; } for (i=0; i < NUMCOUNT; i++) { if (Numbers[i] == -1 && use_term.Numbers[i] != -1) Numbers[i] = use_term.Numbers[i]; } for (i=0; i < STRCOUNT; i++) { if (Strings[i] == -1 && use_term.Strings[i] != (char *) 0) Strings[i] = save_str(use_term.Strings[i]); } } } //go.sysin dd * echo 'x - =src/comp_scan.c' sed 's/^X//' <<'//go.sysin dd *' >=src/comp_scan.c X/********************************************************************* * 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) * *********************************************************************/ X/* * comp_scan.c --- Lexical scanner for terminfo compiler. * * $Log: RCS/comp_scan.v $ * Revision 2.1 82/10/25 14:45:55 pavel * Added Copyright Notice * * Revision 2.0 82/10/24 15:17:12 pavel * Beta-one Test Release * * Revision 1.3 82/08/23 22:30:03 pavel * The REAL Alpha-one Release Version * * Revision 1.2 82/08/19 19:10:06 pavel * Alpha Test Release One * * Revision 1.1 82/08/12 18:37:46 pavel * Initial revision * * */ static char RCSid[] = "$Header: RCS/comp_scan.v Revision 2.1 82/10/25 14:45:55 pavel Exp$"; #include #include #include "compiler.h" #define iswhite(ch) (ch == ' ' || ch == '\t') static int first_column; /* See 'next_char()' below */ X/* * int * get_token() * * Scans the input for the next token, storing the specifics in the * global structure 'curr_token' and returning one of the following: * * NAMES A line beginning in column 1. 'name' * will be set to point to everything up to * but not including the first comma on the line. * BOOLEAN An entry consisting of a name followed by * a comma. 'name' will be set to point to the * name of the capability. * NUMBER An entry of the form * name#digits, * 'name' will be set to point to the capability * name and 'valnumber' to the number given. * STRING An entry of the form * name=characters, * 'name' is set to the capability name and * 'valstring' to the string of characters, with * input translations done. * CANCEL An entry of the form * name@, * 'name' is set to the capability name and * 'valnumber' to -1. * EOF The end of the file has been reached. * */ int get_token() { long number; int type; register char ch; static char buffer[1024]; register char *ptr; int dot_flag = FALSE; while ((ch = next_char()) == '\n' || iswhite(ch)) ; if (ch == EOF) type = EOF; else { if (ch == '.') { dot_flag = TRUE; while ((ch = next_char()) == ' ' || ch == '\t') ; } if (! isalnum(ch)) { warning("Illegal character - '%c'", ch); panic_mode(','); } ptr = buffer; *(ptr++) = ch; if (first_column) { while ((ch = next_char()) != ',' && ch != '\n' && ch != EOF) *(ptr++) = ch; if (ch == EOF) err_abort("Premature EOF"); else if (ch == '\n') { warning("Newline in middle of terminal name"); panic_mode(','); } *ptr = '\0'; curr_token.tk_name = buffer; type = NAMES; } else { ch = next_char(); while (isalnum(ch)) { *(ptr++) = ch; ch = next_char(); } *ptr++ = '\0'; switch (ch) { case ',': curr_token.tk_name = buffer; type = BOOLEAN; break; case '@': if (next_char() != ',') warning("Missing comma"); curr_token.tk_name = buffer; type = CANCEL; break; case '#': number = 0; while (isdigit(ch = next_char())) number = number * 10 + ch - '0'; if (ch != ',') warning("Missing comma"); curr_token.tk_name = buffer; curr_token.tk_valnumber = number; type = NUMBER; break; case '=': ch = trans_string(ptr); if (ch != ',') warning("Missing comma"); curr_token.tk_name = buffer; curr_token.tk_valstring = ptr; type = STRING; break; default: warning("Illegal character - '%c'", ch); } } /* end else (first_column == FALSE) */ } /* end else (ch != EOF) */ if (dot_flag == TRUE) DEBUG(8, "Commented out ", ""); if (debug_level >= 8) { fprintf(stderr, "Token: "); switch (type) { case BOOLEAN: fprintf(stderr, "Boolean; name='%s'\n", curr_token.tk_name); break; case NUMBER: fprintf(stderr, "Number; name='%s', value=%d\n", curr_token.tk_name, curr_token.tk_valnumber); break; case STRING: fprintf(stderr, "String; name='%s', value='%s'\n", curr_token.tk_name, curr_token.tk_valstring); break; case CANCEL: fprintf(stderr, "Cancel; name='%s'\n", curr_token.tk_name); break; case NAMES: fprintf(stderr, "Names; value='%s'\n", curr_token.tk_name); break; case EOF: fprintf(stderr, "End of file\n"); break; default: warning("Bad token type"); } } if (dot_flag == TRUE) /* if commented out, use the next one */ type = get_token(); return(type); } X/* * char * next_char() * * Returns the next character in the input stream. Comments and leading * white space are stripped. The global state variable 'firstcolumn' is * set TRUE if the character returned is from the first column of the input * line. The global variable curr_line is incremented for each new line. * The global variable curr_file_pos is set to the file offset of the * beginning of each line. * */ int curr_column = -1; char line[1024]; char next_char() { char *rtn_value; long ftell(); if (curr_column < 0 || curr_column > 1023 || line[curr_column] == '\0') { do { curr_file_pos = ftell(stdin); if ((rtn_value = fgets(line, 1024, stdin)) != NULL) curr_line++; } while (rtn_value != NULL && line[0] == '#'); if (rtn_value == NULL) return (EOF); curr_column = 0; while (iswhite(line[curr_column])) curr_column++; } if (curr_column == 0 && line[0] != '\n') first_column = TRUE; else first_column = FALSE; return (line[curr_column++]); } backspace() { curr_column--; if (curr_column < 0) syserr_abort("Backspaced off beginning of line"); } X/* * reset_input() * * Resets the input-reading routines. Used after a seek has been done. * */ reset_input() { curr_column = -1; } X/* * char * trans_string(ptr) * * Reads characters using next_char() until encountering a comma, newline * or end-of-file. The returned value is the character which caused * reading to stop. The following translations are done on the input: * * ^X goes to ctrl-X (i.e. X & 037) * {\E,\n,\r,\b,\t,\f} go to * {ESCAPE,newline,carriage-return,backspace,tab,formfeed} * {\^,\\} go to {carat,backslash} * \ddd (for ddd = up to three octal digits) goes to * the character ddd * * \e == \E * \0 == \200 * */ char trans_string(ptr) char *ptr; { register int count = 0; int number; int i; char ch; while ((ch = next_char()) != ',' && ch != EOF) { if (ch == '^') { ch = next_char(); if (ch == EOF) err_abort("Premature EOF"); if (! isprint(ch)) { warning("Illegal ^ character - '%c'", ch); } *(ptr++) = ch & 037; } else if (ch == '\\') { ch = next_char(); if (ch == EOF) err_abort("Premature EOF"); if (ch >= '0' && ch <= '7') { number = ch - '0'; for (i=0; i < 2; i++) { ch = next_char(); if (ch == EOF) err_abort("Premature EOF"); if (ch < '0' || ch > '7') { backspace(); break; } number = number * 8 + ch - '0'; } if (number == 0) number = 0200; *(ptr++) = (char) number; } else { switch (ch) { case 'E': case 'e': *(ptr++) = '\033'; break; case 'l': case 'n': *(ptr++) = '\n'; break; case 'r': *(ptr++) = '\r'; break; case 'b': *(ptr++) = '\008'; break; case 's': *(ptr++) = ' '; break; case 'f': *(ptr++) = '\014'; break; case 't': *(ptr++) = '\t'; break; case '\\': *(ptr++) = '\\'; break; case '^': *(ptr++) = '^'; break; case ',': *(ptr++) = ','; break; case ':': *(ptr++) = ':'; break; default: warning("Illegal character in \\ sequence"); *(ptr++) = ch; } /* endswitch (ch) */ } /* endelse (ch < '0' || ch > '7') */ } /* end else if (ch == '\\') */ else { *(ptr++) = ch; } count ++; if (count > 500) warning("Very long string found. Missing comma?"); } /* end while */ *ptr = '\0'; return(ch); } X/* * Panic mode error recovery - skip everything until a "ch" is found. */ panic_mode(ch) char ch; { int c; for (;;) { c = next_char(); if (c == ch) return; if (c == EOF); return; } } //go.sysin dd * echo 'x - =src/compiler.h' sed 's/^X//' <<'//go.sysin dd *' >=src/compiler.h X/********************************************************************* * 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) * *********************************************************************/ X/* * compiler.h - Global variables and structures for the terminfo * compiler. * * $Header: RCS/compiler.v Revision 2.1 82/10/25 14:46:04 pavel Exp$ * * $Log: RCS/compiler.v $ Revision 2.1 82/10/25 14:46:04 pavel Added Copyright Notice Revision 2.0 82/10/24 15:17:20 pavel Beta-one Test Release Revision 1.3 82/08/23 22:30:09 pavel The REAL Alpha-one Release Version Revision 1.2 82/08/19 19:10:10 pavel Alpha Test Release One Revision 1.1 82/08/12 18:38:11 pavel Initial revision * */ #include #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define SINGLE /* only one terminal (actually none) */ char *destination; /* destination directory for object files */ long start_time; /* time at start of compilation */ long time(); int curr_line; /* current line # in input */ long curr_file_pos; /* file offset of current line */ int debug_level; /* level of debugging output */ #define DEBUG(level, fmt, a1) \ if (debug_level >= level)\ fprintf(stderr, fmt, a1); /* * These are the types of tokens returned by the scanner. * The first three are also used in the hash table of capability * names. The scanner returns one of these values after loading * the specifics into the global structure curr_token. * */ #define BOOLEAN 0 /* Boolean capability */ #define NUMBER 1 /* Numeric capability */ #define STRING 2 /* String-valued capability */ #define CANCEL 3 /* Capability to be cancelled in following tc's */ #define NAMES 4 /* The names for a terminal type */ /* * The global structure in which the specific parts of a * scanned token are returned. * */ struct token { char *tk_name; /* name of capability */ int tk_valnumber; /* value of capability (if a number) */ char *tk_valstring; /* value of capability (if a string) */ }; struct token curr_token; /* * The file comp_captab.c contains an array of these structures, * one per possible capability. These are then made into a hash * table array of the same structures for use by the parser. * */ struct name_table_entry { struct name_table_entry *nte_link; char *nte_name; /* name to hash on */ int nte_type; /* BOOLEAN, NUMBER or STRING */ short nte_index; /* index of associated variable in its array */ }; extern struct name_table_entry cap_table[]; extern struct name_table_entry *cap_hash_table[]; extern int Captabsize; extern int Hashtabsize; #define NOTFOUND ((struct name_table_entry *) 0) /* * Function types * */ struct name_table_entry *find_entry(); /* look up entry in hash table */ char next_char(); char trans_string(); //go.sysin dd * exit