|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 6422 (0x1916) Types: TextFile Notes: UNIX file Names: »awk2.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─⟦this⟧ »cmd/awk/awk2.c«
/* * AWK - part 2 * Initialisation, and * other compiler support. * Symbol table maintenance * and lookup. */ #include "awk.h" #include "y.tab.h" void keyenter(); void funcenter(); typedef struct FUNC { int (*f_funcp)(); char *f_name; char f_minarg; /* Minimum number of arguments */ char f_maxarg; /* Maximum # args (-1 = variable) */ } FUNC; FUNC functions[] = { f_length, "length", 0, 1, f_sqrt, "sqrt", 1, 1, f_log, "log", 1, 1, f_exp, "exp", 1, 1, f_int, "int", 1, 1, f_substr, "substr", 2, 3, f_index, "index", 2, 2, f_sprintf, "sprintf", 1, -1, f_split, "split", 2, 3, f_abs, "abs", 1, 1, }; typedef struct KEYW { int k_lval; char *k_name; } KEYW; KEYW keywords[] = { BEGIN_, "BEGIN", END_, "END", PRINT_, "print", PRINTF_, "printf", IF_, "if", ELSE_, "else", WHILE_, "while", FOR_, "for", IN_, "in", BREAK_, "break", CONTINUE_, "continue", NEXT_, "next", EXIT_, "exit", }; /* * Initialisation -- * Turn on buffering for output. * Initialse static constant values, * install keywords, * and install built-in functions. */ awkinit() { setbuf(stdin, inbuf); setbuf(stdout, outbuf); setbuf(stderr, NULL); /* * Initialise keywords into * the symbol table. */ { register KEYW *kp; for (kp = keywords; kp < endof(keywords); kp++) keyenter(kp->k_name, kp->k_lval); } /* * Install functions into symbol * table. */ { register FUNC *fp; for (fp = functions; fp < endof(functions); fp++) funcenter(fp->f_name, fp->f_funcp, fp->f_minarg, fp->f_maxarg); } xzero.t_INT = 0; xone.t_INT = 1; xone.t_op = xzero.t_op = ATERM; xone.t_flag = xzero.t_flag = T_INT|T_NUM; xfield0.n_op = AFIELD; xfield0.n_O1 = &xzero; /* * Set up the built-in variables. */ NRp = install("NR", (INT)0); NFp = install("NF", (INT)0); FILENAMEp = lookup("FILENAME"); sassign(FSp = install("FS", (INT)0), " \t\n"); sassign(RSp = install("RS", (INT)0), "\n"); sassign(OFSp = install("OFS", (INT)0), " "); sassign(ORSp = install("ORS", (INT)0), "\n"); sassign(OFMTp = install("OFMT", (INT)0), "%D"); } /* * Lookup an identifier - `id' and * if it is not found, initialise it * with the NULL string. * The hash value is the sum of all * the characters in the name + * the length of the name. */ NODE * lookup(id) char *id; { register char *ip; register TERM *tp; register unsigned hash; register unsigned nb; hash = 0; nb = sizeof (char); for (ip = id; *ip != '\0'; hash++, nb++) hash += *ip++; for (tp = symtab[hash%NHASH]; tp != NULL; tp = tp->t_next) if (hash==tp->t_hval && tp->t_flag&T_VAR && streq(tp->t_name, id)) return (tp); tp = (TERM *)xalloc(sizeof(NODE) + nb); strcpy(tp->t_name, id); tp->t_STRING = xalloc(sizeof(char)); tp->t_STRING[0] = '\0'; tp->t_op = ATERM; tp->t_flag = T_VAR|T_ALLOC; tp->t_hval = hash; tp->t_ahval = -1; tp->t_next = symtab[hash %= NHASH]; symtab[hash] = tp; return ((NODE *)tp); } /* * Lookup for an array. * Arguments are `array' and `index' * (both strings). Hashing is an * extension of that in lookup(). * New array elements are given value the * NULL string. */ NODE * alookup(array, index) char *array; char *index; { register char *ip; register TERM *tp; register unsigned hash; register unsigned nba, nbi; register unsigned hash2; hash = 0; nba = nbi = sizeof (char); for (ip = array; *ip != '\0'; hash++, nba++) hash += *ip++; hash2 = hash; for (ip = index; *ip != '\0'; hash++, nbi++) hash += *ip++; for (tp = symtab[hash % NHASH]; tp != NULL; tp = tp->t_next) if (hash==tp->t_hval && tp->t_flag&T_ARRAY && streq(tp->t_name, array) && streq(tp->t_name+nba, index)) return (tp); tp = (TERM *)xalloc(sizeof(NODE) + nba + nbi); strcpy(tp->t_name, array); strcpy(tp->t_name+nba, index); tp->t_STRING = xalloc(sizeof(char)); tp->t_STRING[0] = '\0'; tp->t_op = ATERM; tp->t_flag = T_ARRAY|T_ALLOC; tp->t_hval = hash; tp->t_ahval = hash2; tp->t_next = symtab[hash %= NHASH]; symtab[hash] = tp; return ((NODE *)tp); } /* * Install a built-in integer * name with value `val'. */ NODE * install(id, val) char *id; INT val; { register NODE *np; np = lookup(id); np->t_flag |= T_NUM|T_INT; free(np->t_STRING); np->t_INT = val; return (np); } /* * Enter a keyword in the symbol table. * `lval' is the lexical value of the keyword * and the TERM type is `AKEYW'. */ void keyenter(word, lval) char *word; int lval; { register char *ip; register unsigned hash; register TERM *tp; register int nb; hash = 0; nb = sizeof (char); for (ip = word; *ip != '\0'; hash++, nb++) hash += *ip++; tp = (TERM *)xalloc(nb + sizeof(TERM)); tp->t_hval = hash; tp->t_op = AKEYW; tp->t_flag = T_ALLOC|T_VAR; strcpy(tp->t_name, word); tp->t_INT = lval; tp->t_next = symtab[hash %= NHASH]; symtab[hash] = tp; } /* * Enter a function name into the * symbol table. * `min' and `max' are the minimum and * maximum number of arguments, respectively. */ void funcenter(name, fun, min, max) char *name; int (*fun)(); int min, max; { register char *np; register unsigned hash; register TERM *tp; register unsigned nb; hash = 0; nb = sizeof (char); for (np = name; *np != '\0'; hash++, nb++) hash += *np++; tp = (TERM *)xalloc(nb + sizeof(TERM)); tp->t_hval = hash; tp->t_op = AFUNC; tp->t_flag = T_ALLOC|T_VAR; strcpy(tp->t_name, name); tp->t_FUNC = fun; tp->t_MINARG = min; tp->t_MAXARG = max; tp->t_next = symtab[hash %= NHASH]; symtab[hash] = tp; } /* * Assign a new value to a string. * It produces a static string. */ sassign(np, s) register NODE *np; STRING s; { if ((np->t_flag & (T_ALLOC|T_NUM)) == T_ALLOC) free(np->t_STRING); np->t_flag &= ~(T_ALLOC|T_NUM); np->t_STRING = s; } /* * Assign an INT to a node. */ iassign(np, i) register NODE *np; INT i; { if ((np->t_flag & (T_ALLOC|T_NUM)) == T_ALLOC) free(np->t_STRING); np->t_flag &= ~T_ALLOC; np->t_flag |= T_INT|T_NUM; np->t_INT = i; } /* * Initialise (or reset) the mapping * table for field extraction. It is * set to non-zero for every character * that can end a field + '\0' * Note that FSMAP is defined over `wordbuf' * which is only used lexically and by `sprintf' * Therefore this routine must be called if this * buffer is disturbed. */ fsmapinit(fsp) register char *fsp; { register char *cp; for (cp = FSMAP; cp < &FSMAP[NCSET]; ) *cp++ = 0; while (*fsp != '\0') FSMAP[*fsp++] = 1; }