|
|
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.