|
|
1.1 ! root 1: /* ! 2: * AWK - part 2 ! 3: * Initialisation, and ! 4: * other compiler support. ! 5: * Symbol table maintenance ! 6: * and lookup. ! 7: */ ! 8: ! 9: #include "awk.h" ! 10: #include "y.tab.h" ! 11: ! 12: void keyenter(); ! 13: void funcenter(); ! 14: ! 15: typedef struct FUNC { ! 16: int (*f_funcp)(); ! 17: CHAR *f_name; ! 18: CHAR f_minarg; /* Minimum number of arguments */ ! 19: CHAR f_maxarg; /* Maximum # args (-1 = variable) */ ! 20: } FUNC; ! 21: ! 22: FUNC functions[] = { ! 23: f_length, "length", 0, 1, ! 24: f_sqrt, "sqrt", 1, 1, ! 25: f_log, "log", 1, 1, ! 26: f_exp, "exp", 1, 1, ! 27: f_int, "int", 1, 1, ! 28: f_substr, "substr", 2, 3, ! 29: f_index, "index", 2, 2, ! 30: f_sprintf, "sprintf", 1, -1, ! 31: f_split, "split", 2, 3, ! 32: f_abs, "abs", 1, 1, ! 33: }; ! 34: ! 35: typedef struct KEYW { ! 36: int k_lval; ! 37: CHAR *k_name; ! 38: } KEYW; ! 39: ! 40: KEYW keywords[] = { ! 41: BEGIN_, "BEGIN", ! 42: END_, "END", ! 43: PRINT_, "print", ! 44: PRINTF_, "printf", ! 45: IF_, "if", ! 46: ELSE_, "else", ! 47: WHILE_, "while", ! 48: FOR_, "for", ! 49: IN_, "in", ! 50: BREAK_, "break", ! 51: CONTINUE_, "continue", ! 52: NEXT_, "next", ! 53: EXIT_, "exit", ! 54: }; ! 55: ! 56: /* ! 57: * Initialisation -- ! 58: * Turn on buffering for output. ! 59: * Initialse static constant values, ! 60: * install keywords, ! 61: * and install built-in functions. ! 62: */ ! 63: awkinit() ! 64: { ! 65: setbuf(stdin, inbuf); ! 66: setbuf(stdout, outbuf); ! 67: setbuf(stderr, NULL); ! 68: /* ! 69: * Initialise keywords into ! 70: * the symbol table. ! 71: */ ! 72: { ! 73: register KEYW *kp; ! 74: ! 75: for (kp = keywords; kp < endof(keywords); kp++) ! 76: keyenter(kp->k_name, kp->k_lval); ! 77: } ! 78: /* ! 79: * Install functions into symbol ! 80: * table. ! 81: */ ! 82: { ! 83: register FUNC *fp; ! 84: ! 85: for (fp = functions; fp < endof(functions); fp++) ! 86: funcenter(fp->f_name, fp->f_funcp, fp->f_minarg, ! 87: fp->f_maxarg); ! 88: } ! 89: xzero.t_INT = 0; ! 90: xone.t_INT = 1; ! 91: xone.t_op = xzero.t_op = ATERM; ! 92: xone.t_flag = xzero.t_flag = T_INT|T_NUM; ! 93: xfield0.n_op = AFIELD; ! 94: xfield0.n_O1 = &xzero; ! 95: /* ! 96: * Set up the built-in variables. ! 97: */ ! 98: NRp = install("NR", (INT)0); ! 99: NFp = install("NF", (INT)0); ! 100: FILENAMEp = lookup("FILENAME"); ! 101: sassign(FSp = install("FS", (INT)0), " \t"); ! 102: sassign(RSp = install("RS", (INT)0), "\n"); ! 103: sassign(OFSp = install("OFS", (INT)0), " "); ! 104: sassign(ORSp = install("ORS", (INT)0), "\n"); ! 105: sassign(OFMTp = install("OFMT", (INT)0), "%ld"); ! 106: } ! 107: ! 108: /* ! 109: * Lookup an identifier - `id' and ! 110: * if it is not found, initialise it ! 111: * with the NULL string. ! 112: * The hash value is the sum of all ! 113: * the characters in the name + ! 114: * the length of the name. ! 115: */ ! 116: NODE * ! 117: lookup(id) ! 118: CHAR *id; ! 119: { ! 120: register CHAR *ip; ! 121: register TERM *tp; ! 122: register unsigned hash; ! 123: register unsigned nb; ! 124: ! 125: hash = 0; ! 126: nb = sizeof (CHAR); ! 127: for (ip = id; *ip != '\0'; hash++, nb++) ! 128: hash += *ip++; ! 129: for (tp = symtab[hash%NHASH]; tp != NULL; tp = tp->t_next) ! 130: if (hash==tp->t_hval && tp->t_flag&T_VAR ! 131: && streq(tp->t_name, id)) ! 132: return (tp); ! 133: tp = (TERM *)xalloc(sizeof(NODE) + nb); ! 134: strcpy(tp->t_name, id); ! 135: tp->t_STRING = xalloc(sizeof(CHAR)); ! 136: tp->t_STRING[0] = '\0'; ! 137: tp->t_op = ATERM; ! 138: tp->t_flag = T_VAR|T_ALLOC; ! 139: tp->t_hval = hash; ! 140: tp->t_ahval = -1; ! 141: tp->t_next = symtab[hash %= NHASH]; ! 142: symtab[hash] = tp; ! 143: return ((NODE *)tp); ! 144: } ! 145: ! 146: /* ! 147: * Lookup for an array. ! 148: * Arguments are `array' and `index' ! 149: * (both strings). Hashing is an ! 150: * extension of that in lookup(). ! 151: * New array elements are given value the ! 152: * NULL string. ! 153: */ ! 154: NODE * ! 155: alookup(array, index) ! 156: CHAR *array; ! 157: CHAR *index; ! 158: { ! 159: register CHAR *ip; ! 160: register TERM *tp; ! 161: register unsigned hash; ! 162: register unsigned nba, nbi; ! 163: register unsigned hash2; ! 164: ! 165: hash = 0; ! 166: nba = nbi = sizeof (CHAR); ! 167: for (ip = array; *ip != '\0'; hash++, nba++) ! 168: hash += *ip++; ! 169: hash2 = hash; ! 170: for (ip = index; *ip != '\0'; hash++, nbi++) ! 171: hash += *ip++; ! 172: for (tp = symtab[hash % NHASH]; tp != NULL; tp = tp->t_next) ! 173: if (hash==tp->t_hval && tp->t_flag&T_ARRAY ! 174: && streq(tp->t_name, array) && streq(tp->t_name+nba, index)) ! 175: return (tp); ! 176: tp = (TERM *)xalloc(sizeof(NODE) + nba + nbi); ! 177: strcpy(tp->t_name, array); ! 178: strcpy(tp->t_name+nba, index); ! 179: tp->t_STRING = xalloc(sizeof(CHAR)); ! 180: tp->t_STRING[0] = '\0'; ! 181: tp->t_op = ATERM; ! 182: tp->t_flag = T_ARRAY|T_ALLOC; ! 183: tp->t_hval = hash; ! 184: tp->t_ahval = hash2; ! 185: tp->t_next = symtab[hash %= NHASH]; ! 186: symtab[hash] = tp; ! 187: return ((NODE *)tp); ! 188: } ! 189: ! 190: /* ! 191: * Install a built-in integer ! 192: * name with value `val'. ! 193: */ ! 194: NODE * ! 195: install(id, val) ! 196: CHAR *id; ! 197: INT val; ! 198: { ! 199: register NODE *np; ! 200: ! 201: np = lookup(id); ! 202: np->t_flag |= T_NUM|T_INT; ! 203: free(np->t_STRING); ! 204: np->t_INT = val; ! 205: return (np); ! 206: } ! 207: ! 208: /* ! 209: * Enter a keyword in the symbol table. ! 210: * `lval' is the lexical value of the keyword ! 211: * and the TERM type is `AKEYW'. ! 212: */ ! 213: void ! 214: keyenter(word, lval) ! 215: CHAR *word; ! 216: int lval; ! 217: { ! 218: register CHAR *ip; ! 219: register unsigned hash; ! 220: register TERM *tp; ! 221: register int nb; ! 222: ! 223: hash = 0; ! 224: nb = sizeof (CHAR); ! 225: for (ip = word; *ip != '\0'; hash++, nb++) ! 226: hash += *ip++; ! 227: tp = (TERM *)xalloc(nb + sizeof(TERM)); ! 228: tp->t_hval = hash; ! 229: tp->t_op = AKEYW; ! 230: tp->t_flag = T_ALLOC|T_VAR; ! 231: strcpy(tp->t_name, word); ! 232: tp->t_INT = lval; ! 233: tp->t_next = symtab[hash %= NHASH]; ! 234: symtab[hash] = tp; ! 235: } ! 236: ! 237: /* ! 238: * Enter a function name into the ! 239: * symbol table. ! 240: * `min' and `max' are the minimum and ! 241: * maximum number of arguments, respectively. ! 242: */ ! 243: void ! 244: funcenter(name, fun, min, max) ! 245: CHAR *name; ! 246: int (*fun)(); ! 247: int min, max; ! 248: { ! 249: register CHAR *np; ! 250: register unsigned hash; ! 251: register TERM *tp; ! 252: register unsigned nb; ! 253: ! 254: hash = 0; ! 255: nb = sizeof (CHAR); ! 256: for (np = name; *np != '\0'; hash++, nb++) ! 257: hash += *np++; ! 258: tp = (TERM *)xalloc(nb + sizeof(TERM)); ! 259: tp->t_hval = hash; ! 260: tp->t_op = AFUNC; ! 261: tp->t_flag = T_ALLOC|T_VAR; ! 262: strcpy(tp->t_name, name); ! 263: tp->t_FUNC = fun; ! 264: tp->t_MINARG = min; ! 265: tp->t_MAXARG = max; ! 266: tp->t_next = symtab[hash %= NHASH]; ! 267: symtab[hash] = tp; ! 268: } ! 269: ! 270: /* ! 271: * Assign a new value to a string. ! 272: * It produces a static string. ! 273: */ ! 274: sassign(np, s) ! 275: register NODE *np; ! 276: STRING s; ! 277: { ! 278: if ((np->t_flag & (T_ALLOC|T_NUM)) == T_ALLOC) ! 279: free(np->t_STRING); ! 280: np->t_flag &= ~(T_ALLOC|T_NUM); ! 281: np->t_STRING = s; ! 282: } ! 283: ! 284: /* ! 285: * Assign an INT to a node. ! 286: */ ! 287: iassign(np, i) ! 288: register NODE *np; ! 289: INT i; ! 290: { ! 291: if ((np->t_flag & (T_ALLOC|T_NUM)) == T_ALLOC) ! 292: free(np->t_STRING); ! 293: np->t_flag &= ~T_ALLOC; ! 294: np->t_flag |= T_INT|T_NUM; ! 295: np->t_INT = i; ! 296: } ! 297: ! 298: /* ! 299: * Initialise (or reset) the mapping ! 300: * table for field extraction. It is ! 301: * set to non-zero for every character ! 302: * that can end a field + '\0' ! 303: * Note that FSMAP is defined over `wordbuf' ! 304: * which is only used lexically and by `sprintf' ! 305: * Therefore this routine must be called if this ! 306: * buffer is disturbed. ! 307: */ ! 308: fsmapinit(fsp) ! 309: register CHAR *fsp; ! 310: { ! 311: register CHAR *cp; ! 312: ! 313: whitesw = !strcmp(fsp, " \t"); ! 314: for (cp = FSMAP; cp < &FSMAP[NCSET]; ) ! 315: *cp++ = 0; ! 316: while (*fsp != '\0') ! 317: FSMAP[*fsp++] = 1; ! 318: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.