|
|
1.1 ! root 1: /* ! 2: * AWK - Common support routines. ! 3: * node allocation, etc. ! 4: */ ! 5: ! 6: #include "awk.h" ! 7: #include "y.tab.h" ! 8: ! 9: static int eosflag; /* for pgetc/pungetc */ ! 10: ! 11: /* ! 12: * Allocate n bytes of ! 13: * storage, checking for ! 14: * running out of space. ! 15: * This version doesn't call malloc, but ! 16: * rather uses sbrk and doles out storage ! 17: * itself. This sames much time for ! 18: * searching long alloc lists. However, ! 19: * i/o calls must all be buffered staticly. ! 20: * A call with 0 bytes returns the pointer to ! 21: * the end which can be saved for a call to xfree. ! 22: * The following are 2 pointers maintained by the allocator/xfree. ! 23: */ ! 24: static int *xallrp; /* Running pointer for xalloc */ ! 25: static int *xallep; /* End pointer for xfree */ ! 26: CHAR * ! 27: xalloc(size) ! 28: register unsigned size; ! 29: { ! 30: register int *rp; ! 31: ! 32: if ((rp = (int *)malloc(size)) == NULL) ! 33: awkerr("Out of memory"); ! 34: return ((CHAR *)rp); ! 35: } ! 36: ! 37: /* ! 38: * Create an expression tree node. ! 39: * The only required argument is the ! 40: * operation code. The other three ! 41: * are operands. ! 42: */ ! 43: /* VARARGS 1 */ ! 44: NODE * ! 45: node(op, o1, o2, o3, o4) ! 46: int op; ! 47: NODE *o1, *o2, *o3, *o4; ! 48: { ! 49: register NODE *np; ! 50: ! 51: np = (NODE *)xalloc(sizeof (NODE)); ! 52: np->n_op = op; ! 53: np->n_flag = 0; ! 54: np->n_O1 = o1; ! 55: np->n_O2 = o2; ! 56: np->n_O3 = o3; ! 57: np->n_O4 = o4; ! 58: return (np); ! 59: } ! 60: ! 61: /* ! 62: * Produce a node with a character (int) ! 63: * int it (mostly for regular expressions). ! 64: */ ! 65: NODE * ! 66: cnode(op, c) ! 67: int op, c; ! 68: { ! 69: register NODE *np; ! 70: ! 71: np = (NODE *)xalloc(sizeof (NODE)); ! 72: np->n_op = op; ! 73: np->n_flag = 0; ! 74: np->n_o1.n_char = c; ! 75: np->n_O2 = np->n_O3 = np->n_O4 = NULL; ! 76: return (np); ! 77: } ! 78: ! 79: /* ! 80: * Produce a string node. ! 81: * While running, this node ! 82: * is considered temporary. ! 83: */ ! 84: NODE * ! 85: snode(s, type) ! 86: register CHAR *s; ! 87: int type; ! 88: { ! 89: register NODE *np; ! 90: ! 91: np = (NODE *)xalloc(sizeof(TERM)); ! 92: np->t_op = ATERM; ! 93: np->t_flag = type; ! 94: np->t_un.t_str = s; ! 95: if (runflag) { ! 96: np->t_next = tempnodes; ! 97: tempnodes = np; ! 98: } ! 99: return (np); ! 100: } ! 101: ! 102: /* ! 103: * Build a node for a (long) ! 104: * integer. ! 105: */ ! 106: NODE * ! 107: inode(i) ! 108: INT i; ! 109: { ! 110: register NODE *np; ! 111: ! 112: np = (NODE *)xalloc(sizeof(NODE)); ! 113: np->t_op = ATERM; ! 114: np->t_flag = T_NUM|T_INT; ! 115: np->t_un.t_int = i; ! 116: if (runflag) { ! 117: np->t_next = tempnodes; ! 118: tempnodes = np; ! 119: } ! 120: return (np); ! 121: } ! 122: ! 123: /* ! 124: * Build a node for a (double) ! 125: * floating point number. ! 126: */ ! 127: NODE * ! 128: fnode(f) ! 129: FLOAT f; ! 130: { ! 131: register NODE *np; ! 132: ! 133: np = (NODE *)xalloc(sizeof(NODE)); ! 134: np->t_op = ATERM; ! 135: np->t_flag = T_NUM; ! 136: np->t_un.t_float = f; ! 137: if (runflag) { ! 138: np->t_next = tempnodes; ! 139: tempnodes = np; ! 140: } ! 141: return (np); ! 142: } ! 143: ! 144: /* ! 145: * Free a terminal node. This ! 146: * looks at the flags to see if ! 147: * it is a string, and frees it if ! 148: * it is also an allocated string. ! 149: */ ! 150: freenode(np) ! 151: register NODE *np; ! 152: { ! 153: if ((np->t_flag&(T_NUM|T_ALLOC)) == T_ALLOC) ! 154: free(np->t_STRING); ! 155: free(np); ! 156: } ! 157: ! 158: /* ! 159: * Checks to see if a node is numeric. ! 160: * Here it must be not in string form ! 161: * but in number form. This is ! 162: * used mostly for comparisons. ! 163: */ ! 164: isnumeric(np) ! 165: register NODE *np; ! 166: { ! 167: if (np->t_flag & T_NUM) ! 168: return (1); ! 169: return (0); ! 170: } ! 171: ! 172: /* ! 173: * Return 1 if a number is of the floating ! 174: * type. This will check strings as well ! 175: * as numbers. ! 176: */ ! 177: isfloat(np) ! 178: register NODE *np; ! 179: { ! 180: register CHAR *cp; ! 181: register int isfloat = 0, sawDigit = 0; ! 182: ! 183: if (np->t_flag & T_NUM) ! 184: return (!(np->t_flag & T_INT)); ! 185: ! 186: for (cp = np->t_STRING;;cp++) { ! 187: switch (*cp) { ! 188: case 0: ! 189: return (isfloat); ! 190: case 'e': ! 191: case 'E': ! 192: if (!sawDigit) ! 193: return (0); ! 194: case '.': ! 195: sawDigit = isfloat = 1; ! 196: break; ! 197: case ' ': ! 198: case '\t': ! 199: if (sawDigit) ! 200: return (0); ! 201: break; ! 202: default: ! 203: if (isdigit(*cp) || '-' == *cp) { ! 204: sawDigit = 1; ! 205: break; ! 206: } ! 207: return (0); ! 208: } ! 209: } ! 210: } ! 211: ! 212: /* ! 213: * Fetch a character from ! 214: * the program, either on ! 215: * the command line or in a file. ! 216: */ ! 217: pgetc() ! 218: { ! 219: register int c; ! 220: ! 221: if (parg != NULL) { ! 222: if (eosflag) ! 223: return (EOF); ! 224: else if ((c = *parg++) == '\0') { ! 225: eosflag = 1; ! 226: return ('\n'); ! 227: } ! 228: } else { ! 229: while ((c = getc(pfp)) == '\\') { ! 230: if ((c = getc(pfp)) != '\n') { ! 231: ungetc(c, pfp); ! 232: return ('\\'); ! 233: } ! 234: /* bypass \ newline */ ! 235: if (lineno == 0) ! 236: lineno++; ! 237: lineno++; ! 238: } ! 239: } ! 240: if (c == '\n') { ! 241: if (lineno == 0) ! 242: lineno++; ! 243: lineno++; ! 244: } ! 245: return (c); ! 246: } ! 247: ! 248: /* ! 249: * Set up a new string for the ! 250: * lexical analyser to read. ! 251: */ ! 252: pgetinit(s) ! 253: CHAR *s; ! 254: { ! 255: parg = s; ! 256: eosflag = 0; ! 257: lineno = 0; ! 258: } ! 259: ! 260: /* ! 261: * Return a character to the ! 262: * program input. ! 263: */ ! 264: pungetc(c) ! 265: int c; ! 266: { ! 267: if (parg != NULL) { ! 268: if (eosflag) ! 269: c = '\0'; ! 270: *--parg = c; ! 271: eosflag = 0; ! 272: } else ! 273: ungetc(c, pfp); ! 274: if (c == '\n') ! 275: --lineno; ! 276: } ! 277: ! 278: /* ! 279: * Error routines and usage ! 280: * messages. ! 281: */ ! 282: usage() ! 283: { ! 284: fprintf(stderr, ! 285: "Usage: awk [-y] [-Fc] [-f prog] [parameters] [prog] [file ...]\n"); ! 286: exit(1); ! 287: } ! 288: ! 289: /* VARARGS */ ! 290: awkerr(x) ! 291: { ! 292: fprintf(stderr, "awk: "); ! 293: if (FILENAME[0] != '\0') ! 294: fprintf(stderr, "%s: ", FILENAME); ! 295: if (lineno != 0) ! 296: fprintf(stderr, "%d: ", lineno); ! 297: fprintf(stderr, "%r", &x); ! 298: putc('\n', stderr); ! 299: exit(1); ! 300: } ! 301: ! 302: /* VARARGS */ ! 303: awkwarn(x) ! 304: { ! 305: fprintf(stderr, "awk: "); ! 306: if (FILENAME[0] != '\0') ! 307: fprintf(stderr, "%s: ", FILENAME); ! 308: if (lineno != 0) ! 309: fprintf(stderr, "%d: ", lineno); ! 310: fprintf(stderr, "Warning: %r", &x); ! 311: putc('\n', stderr); ! 312: } ! 313: ! 314: /* VARARGS */ ! 315: yyerror(x) ! 316: { ! 317: awkerr(x); ! 318: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.