Commit | Line | Data |
---|---|---|
65ecbd52 C |
1 | /* |
2 | * awk.h -- Definitions for gawk. | |
3 | */ | |
4 | ||
5 | /* | |
6 | * Copyright (C) 1986, 1988, 1989, 1991, 1992 the Free Software Foundation, Inc. | |
7 | * | |
8 | * This file is part of GAWK, the GNU implementation of the | |
9 | * AWK Progamming Language. | |
10 | * | |
11 | * GAWK is free software; you can redistribute it and/or modify | |
12 | * it under the terms of the GNU General Public License as published by | |
13 | * the Free Software Foundation; either version 2 of the License, or | |
14 | * (at your option) any later version. | |
15 | * | |
16 | * GAWK is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | * GNU General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License | |
22 | * along with GAWK; see the file COPYING. If not, write to | |
23 | * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
24 | */ | |
25 | ||
26 | /* ------------------------------ Includes ------------------------------ */ | |
27 | #include <stdio.h> | |
28 | #include <limits.h> | |
29 | #include <ctype.h> | |
30 | #include <setjmp.h> | |
31 | #include <varargs.h> | |
32 | #include <time.h> | |
33 | #include <errno.h> | |
34 | #if !defined(errno) && !defined(MSDOS) | |
35 | extern int errno; | |
36 | #endif | |
37 | #ifdef __GNU_LIBRARY__ | |
38 | #ifndef linux | |
39 | #include <signum.h> | |
40 | #endif | |
41 | #endif | |
42 | ||
43 | /* ----------------- System dependencies (with more includes) -----------*/ | |
44 | ||
45 | #if !defined(VMS) || (!defined(VAXC) && !defined(__DECC)) | |
46 | #include <sys/types.h> | |
47 | #include <sys/stat.h> | |
48 | #else /* VMS w/ VAXC or DECC */ | |
49 | #include <types.h> | |
50 | #include <stat.h> | |
51 | #include <file.h> /* avoid <fcntl.h> in io.c */ | |
52 | #endif | |
53 | ||
54 | #include <signal.h> | |
55 | ||
56 | #include "config.h" | |
57 | ||
58 | #ifdef __STDC__ | |
59 | #define P(s) s | |
60 | #define MALLOC_ARG_T size_t | |
61 | #else | |
62 | #define P(s) () | |
63 | #define MALLOC_ARG_T unsigned | |
64 | #define volatile | |
65 | #define const | |
66 | #endif | |
67 | ||
68 | #ifndef SIGTYPE | |
69 | #define SIGTYPE void | |
70 | #endif | |
71 | ||
72 | #ifdef SIZE_T_MISSING | |
73 | typedef unsigned int size_t; | |
74 | #endif | |
75 | ||
76 | #ifndef SZTC | |
77 | #define SZTC | |
78 | #define INTC | |
79 | #endif | |
80 | ||
81 | #ifdef STDC_HEADERS | |
82 | #include <stdlib.h> | |
83 | #include <string.h> | |
84 | #ifdef NeXT | |
85 | #include <libc.h> | |
86 | #undef atof | |
87 | #else | |
88 | #if defined(atarist) || defined(VMS) | |
89 | #include <unixlib.h> | |
90 | #else /* atarist || VMS */ | |
91 | #ifndef MSDOS | |
92 | #include <unistd.h> | |
93 | #endif /* MSDOS */ | |
94 | #endif /* atarist || VMS */ | |
95 | #endif /* Next */ | |
96 | #else /* STDC_HEADERS */ | |
97 | #include "protos.h" | |
98 | #endif /* STDC_HEADERS */ | |
99 | ||
100 | #if defined(ultrix) && !defined(Ultrix41) | |
101 | extern char * getenv P((char *name)); | |
102 | extern double atof P((char *s)); | |
103 | #endif | |
104 | ||
105 | #ifndef __GNUC__ | |
106 | #ifdef sparc | |
107 | /* nasty nasty SunOS-ism */ | |
108 | #include <alloca.h> | |
109 | #ifdef lint | |
110 | extern char *alloca(); | |
111 | #endif | |
112 | #else /* not sparc */ | |
113 | #if !defined(alloca) && !defined(ALLOCA_PROTO) | |
114 | extern char *alloca(); | |
115 | #endif | |
116 | #endif /* sparc */ | |
117 | #endif /* __GNUC__ */ | |
118 | ||
119 | #ifdef HAVE_UNDERSCORE_SETJMP | |
120 | /* nasty nasty berkelixm */ | |
121 | #define setjmp _setjmp | |
122 | #define longjmp _longjmp | |
123 | #endif | |
124 | ||
125 | /* | |
126 | * if you don't have vprintf, try this and cross your fingers. | |
127 | */ | |
128 | #if defined(VPRINTF_MISSING) | |
129 | #define vfprintf(fp,fmt,arg) _doprnt((fmt), (arg), (fp)) | |
130 | #endif | |
131 | ||
132 | #ifdef VMS | |
133 | /* some macros to redirect to code in vms/vms_misc.c */ | |
134 | #define exit vms_exit | |
135 | #define open vms_open | |
136 | #define strerror vms_strerror | |
137 | #define strdup vms_strdup | |
138 | extern void exit P((int)); | |
139 | extern int open P((const char *,int,...)); | |
140 | extern char *strerror P((int)); | |
141 | extern char *strdup P((const char *str)); | |
142 | extern int vms_devopen P((const char *,int)); | |
143 | # ifndef NO_TTY_FWRITE | |
144 | #define fwrite tty_fwrite | |
145 | #define fclose tty_fclose | |
146 | extern size_t fwrite P((const void *,size_t,size_t,FILE *)); | |
147 | extern int fclose P((FILE *)); | |
148 | # endif | |
149 | extern FILE *popen P((const char *,const char *)); | |
150 | extern int pclose P((FILE *)); | |
151 | extern void vms_arg_fixup P((int *,char ***)); | |
152 | /* some things not in STDC_HEADERS */ | |
153 | extern int gnu_strftime P((char *,size_t,const char *,const struct tm *)); | |
154 | extern int unlink P((const char *)); | |
155 | extern int getopt P((int,char **,char *)); | |
156 | extern int isatty P((int)); | |
157 | #ifndef fileno | |
158 | extern int fileno P((FILE *)); | |
159 | #endif | |
160 | extern int close(), dup(), dup2(), fstat(), read(), stat(); | |
161 | #endif /*VMS*/ | |
162 | ||
163 | #ifdef MSDOS | |
164 | #include <io.h> | |
165 | extern FILE *popen P((char *, char *)); | |
166 | extern int pclose P((FILE *)); | |
167 | #endif | |
168 | ||
169 | #define GNU_REGEX | |
170 | #ifdef GNU_REGEX | |
171 | #include "regex.h" | |
172 | #include "dfa.h" | |
173 | typedef struct Regexp { | |
174 | struct re_pattern_buffer pat; | |
175 | struct re_registers regs; | |
176 | struct regexp dfareg; | |
177 | int dfa; | |
178 | } Regexp; | |
179 | #define RESTART(rp,s) (rp)->regs.start[0] | |
180 | #define REEND(rp,s) (rp)->regs.end[0] | |
181 | #else /* GNU_REGEX */ | |
182 | #endif /* GNU_REGEX */ | |
183 | ||
184 | #ifdef atarist | |
185 | #define read _text_read /* we do not want all these CR's to mess our input */ | |
186 | extern int _text_read (int, char *, int); | |
187 | #endif | |
188 | ||
189 | #ifndef DEFPATH | |
190 | #define DEFPATH ".:/usr/local/lib/awk:/usr/lib/awk" | |
191 | #endif | |
192 | ||
193 | #ifndef ENVSEP | |
194 | #define ENVSEP ':' | |
195 | #endif | |
196 | ||
197 | /* ------------------ Constants, Structures, Typedefs ------------------ */ | |
198 | #define AWKNUM double | |
199 | ||
200 | typedef enum { | |
201 | /* illegal entry == 0 */ | |
202 | Node_illegal, | |
203 | ||
204 | /* binary operators lnode and rnode are the expressions to work on */ | |
205 | Node_times, | |
206 | Node_quotient, | |
207 | Node_mod, | |
208 | Node_plus, | |
209 | Node_minus, | |
210 | Node_cond_pair, /* conditional pair (see Node_line_range) */ | |
211 | Node_subscript, | |
212 | Node_concat, | |
213 | Node_exp, | |
214 | ||
215 | /* unary operators subnode is the expression to work on */ | |
216 | /*10*/ Node_preincrement, | |
217 | Node_predecrement, | |
218 | Node_postincrement, | |
219 | Node_postdecrement, | |
220 | Node_unary_minus, | |
221 | Node_field_spec, | |
222 | ||
223 | /* assignments lnode is the var to assign to, rnode is the exp */ | |
224 | Node_assign, | |
225 | Node_assign_times, | |
226 | Node_assign_quotient, | |
227 | Node_assign_mod, | |
228 | /*20*/ Node_assign_plus, | |
229 | Node_assign_minus, | |
230 | Node_assign_exp, | |
231 | ||
232 | /* boolean binaries lnode and rnode are expressions */ | |
233 | Node_and, | |
234 | Node_or, | |
235 | ||
236 | /* binary relationals compares lnode and rnode */ | |
237 | Node_equal, | |
238 | Node_notequal, | |
239 | Node_less, | |
240 | Node_greater, | |
241 | Node_leq, | |
242 | /*30*/ Node_geq, | |
243 | Node_match, | |
244 | Node_nomatch, | |
245 | ||
246 | /* unary relationals works on subnode */ | |
247 | Node_not, | |
248 | ||
249 | /* program structures */ | |
250 | Node_rule_list, /* lnode is a rule, rnode is rest of list */ | |
251 | Node_rule_node, /* lnode is pattern, rnode is statement */ | |
252 | Node_statement_list, /* lnode is statement, rnode is more list */ | |
253 | Node_if_branches, /* lnode is to run on true, rnode on false */ | |
254 | Node_expression_list, /* lnode is an exp, rnode is more list */ | |
255 | Node_param_list, /* lnode is a variable, rnode is more list */ | |
256 | ||
257 | /* keywords */ | |
258 | /*40*/ Node_K_if, /* lnode is conditonal, rnode is if_branches */ | |
259 | Node_K_while, /* lnode is condtional, rnode is stuff to run */ | |
260 | Node_K_for, /* lnode is for_struct, rnode is stuff to run */ | |
261 | Node_K_arrayfor, /* lnode is for_struct, rnode is stuff to run */ | |
262 | Node_K_break, /* no subs */ | |
263 | Node_K_continue, /* no stuff */ | |
264 | Node_K_print, /* lnode is exp_list, rnode is redirect */ | |
265 | Node_K_printf, /* lnode is exp_list, rnode is redirect */ | |
266 | Node_K_next, /* no subs */ | |
267 | Node_K_exit, /* subnode is return value, or NULL */ | |
268 | /*50*/ Node_K_do, /* lnode is conditional, rnode stuff to run */ | |
269 | Node_K_return, | |
270 | Node_K_delete, | |
271 | Node_K_getline, | |
272 | Node_K_function, /* lnode is statement list, rnode is params */ | |
273 | ||
274 | /* I/O redirection for print statements */ | |
275 | Node_redirect_output, /* subnode is where to redirect */ | |
276 | Node_redirect_append, /* subnode is where to redirect */ | |
277 | Node_redirect_pipe, /* subnode is where to redirect */ | |
278 | Node_redirect_pipein, /* subnode is where to redirect */ | |
279 | Node_redirect_input, /* subnode is where to redirect */ | |
280 | ||
281 | /* Variables */ | |
282 | /*60*/ Node_var, /* rnode is value, lnode is array stuff */ | |
283 | Node_var_array, /* array is ptr to elements, asize num of | |
284 | * eles */ | |
285 | Node_val, /* node is a value - type in flags */ | |
286 | ||
287 | /* Builtins subnode is explist to work on, proc is func to call */ | |
288 | Node_builtin, | |
289 | ||
290 | /* | |
291 | * pattern: conditional ',' conditional ; lnode of Node_line_range | |
292 | * is the two conditionals (Node_cond_pair), other word (rnode place) | |
293 | * is a flag indicating whether or not this range has been entered. | |
294 | */ | |
295 | Node_line_range, | |
296 | ||
297 | /* | |
298 | * boolean test of membership in array lnode is string-valued | |
299 | * expression rnode is array name | |
300 | */ | |
301 | Node_in_array, | |
302 | ||
303 | Node_func, /* lnode is param. list, rnode is body */ | |
304 | Node_func_call, /* lnode is name, rnode is argument list */ | |
305 | ||
306 | Node_cond_exp, /* lnode is conditonal, rnode is if_branches */ | |
307 | Node_regex, | |
308 | /*70*/ Node_hashnode, | |
309 | Node_ahash, | |
310 | Node_NF, | |
311 | Node_NR, | |
312 | Node_FNR, | |
313 | Node_FS, | |
314 | Node_RS, | |
315 | Node_FIELDWIDTHS, | |
316 | Node_IGNORECASE, | |
317 | Node_OFS, | |
318 | Node_ORS, | |
319 | Node_OFMT, | |
320 | Node_CONVFMT, | |
321 | Node_K_nextfile | |
322 | } NODETYPE; | |
323 | ||
324 | /* | |
325 | * NOTE - this struct is a rather kludgey -- it is packed to minimize | |
326 | * space usage, at the expense of cleanliness. Alter at own risk. | |
327 | */ | |
328 | typedef struct exp_node { | |
329 | union { | |
330 | struct { | |
331 | union { | |
332 | struct exp_node *lptr; | |
333 | char *param_name; | |
334 | } l; | |
335 | union { | |
336 | struct exp_node *rptr; | |
337 | struct exp_node *(*pptr) (); | |
338 | Regexp *preg; | |
339 | struct for_loop_header *hd; | |
340 | struct exp_node **av; | |
341 | int r_ent; /* range entered */ | |
342 | } r; | |
343 | union { | |
344 | char *name; | |
345 | struct exp_node *extra; | |
346 | } x; | |
347 | short number; | |
348 | unsigned char reflags; | |
349 | # define CASE 1 | |
350 | # define CONST 2 | |
351 | # define FS_DFLT 4 | |
352 | } nodep; | |
353 | struct { | |
354 | AWKNUM fltnum; /* this is here for optimal packing of | |
355 | * the structure on many machines | |
356 | */ | |
357 | char *sp; | |
358 | size_t slen; | |
359 | unsigned char sref; | |
360 | char idx; | |
361 | } val; | |
362 | struct { | |
363 | struct exp_node *next; | |
364 | char *name; | |
365 | int length; | |
366 | struct exp_node *value; | |
367 | } hash; | |
368 | #define hnext sub.hash.next | |
369 | #define hname sub.hash.name | |
370 | #define hlength sub.hash.length | |
371 | #define hvalue sub.hash.value | |
372 | struct { | |
373 | struct exp_node *next; | |
374 | struct exp_node *name; | |
375 | struct exp_node *value; | |
376 | } ahash; | |
377 | #define ahnext sub.ahash.next | |
378 | #define ahname sub.ahash.name | |
379 | #define ahvalue sub.ahash.value | |
380 | } sub; | |
381 | NODETYPE type; | |
382 | unsigned short flags; | |
383 | # define MALLOC 1 /* can be free'd */ | |
384 | # define TEMP 2 /* should be free'd */ | |
385 | # define PERM 4 /* can't be free'd */ | |
386 | # define STRING 8 /* assigned as string */ | |
387 | # define STR 16 /* string value is current */ | |
388 | # define NUM 32 /* numeric value is current */ | |
389 | # define NUMBER 64 /* assigned as number */ | |
390 | # define MAYBE_NUM 128 /* user input: if NUMERIC then | |
391 | * a NUMBER | |
392 | */ | |
393 | char *vname; /* variable's name */ | |
394 | } NODE; | |
395 | ||
396 | #define lnode sub.nodep.l.lptr | |
397 | #define nextp sub.nodep.l.lptr | |
398 | #define rnode sub.nodep.r.rptr | |
399 | #define source_file sub.nodep.x.name | |
400 | #define source_line sub.nodep.number | |
401 | #define param_cnt sub.nodep.number | |
402 | #define param sub.nodep.l.param_name | |
403 | ||
404 | #define subnode lnode | |
405 | #define proc sub.nodep.r.pptr | |
406 | ||
407 | #define re_reg sub.nodep.r.preg | |
408 | #define re_flags sub.nodep.reflags | |
409 | #define re_text lnode | |
410 | #define re_exp sub.nodep.x.extra | |
411 | #define re_cnt sub.nodep.number | |
412 | ||
413 | #define forsub lnode | |
414 | #define forloop rnode->sub.nodep.r.hd | |
415 | ||
416 | #define stptr sub.val.sp | |
417 | #define stlen sub.val.slen | |
418 | #define stref sub.val.sref | |
419 | #define stfmt sub.val.idx | |
420 | ||
421 | #define numbr sub.val.fltnum | |
422 | ||
423 | #define var_value lnode | |
424 | #define var_array sub.nodep.r.av | |
425 | ||
426 | #define condpair lnode | |
427 | #define triggered sub.nodep.r.r_ent | |
428 | ||
429 | #ifdef DONTDEF | |
430 | int primes[] = {31, 61, 127, 257, 509, 1021, 2053, 4099, 8191, 16381}; | |
431 | #endif | |
432 | /* a quick profile suggests that the following is a good value */ | |
433 | #define HASHSIZE 127 | |
434 | ||
435 | typedef struct for_loop_header { | |
436 | NODE *init; | |
437 | NODE *cond; | |
438 | NODE *incr; | |
439 | } FOR_LOOP_HEADER; | |
440 | ||
441 | /* for "for(iggy in foo) {" */ | |
442 | struct search { | |
443 | NODE **arr_ptr; | |
444 | NODE **arr_end; | |
445 | NODE *bucket; | |
446 | NODE *retval; | |
447 | }; | |
448 | ||
449 | /* for faster input, bypass stdio */ | |
450 | typedef struct iobuf { | |
451 | int fd; | |
452 | char *buf; | |
453 | char *off; | |
454 | char *end; | |
455 | size_t size; /* this will be determined by an fstat() call */ | |
456 | int cnt; | |
457 | long secsiz; | |
458 | int flag; | |
459 | # define IOP_IS_TTY 1 | |
460 | # define IOP_IS_INTERNAL 2 | |
461 | # define IOP_NO_FREE 4 | |
462 | } IOBUF; | |
463 | ||
464 | typedef void (*Func_ptr)(); | |
465 | ||
466 | /* | |
467 | * structure used to dynamically maintain a linked-list of open files/pipes | |
468 | */ | |
469 | struct redirect { | |
470 | unsigned int flag; | |
471 | # define RED_FILE 1 | |
472 | # define RED_PIPE 2 | |
473 | # define RED_READ 4 | |
474 | # define RED_WRITE 8 | |
475 | # define RED_APPEND 16 | |
476 | # define RED_NOBUF 32 | |
477 | # define RED_USED 64 | |
478 | # define RED_EOF 128 | |
479 | char *value; | |
480 | FILE *fp; | |
481 | IOBUF *iop; | |
482 | int pid; | |
483 | int status; | |
484 | struct redirect *prev; | |
485 | struct redirect *next; | |
486 | }; | |
487 | ||
488 | /* structure for our source, either a command line string or a source file */ | |
489 | struct src { | |
490 | enum srctype { CMDLINE = 1, SOURCEFILE } stype; | |
491 | char *val; | |
492 | }; | |
493 | ||
494 | /* longjmp return codes, must be nonzero */ | |
495 | /* Continue means either for loop/while continue, or next input record */ | |
496 | #define TAG_CONTINUE 1 | |
497 | /* Break means either for/while break, or stop reading input */ | |
498 | #define TAG_BREAK 2 | |
499 | /* Return means return from a function call; leave value in ret_node */ | |
500 | #define TAG_RETURN 3 | |
501 | ||
502 | #define HUGE INT_MAX | |
503 | ||
504 | /* -------------------------- External variables -------------------------- */ | |
505 | /* gawk builtin variables */ | |
506 | extern int NF; | |
507 | extern int NR; | |
508 | extern int FNR; | |
509 | extern int IGNORECASE; | |
510 | extern char *RS; | |
511 | extern char *OFS; | |
512 | extern int OFSlen; | |
513 | extern char *ORS; | |
514 | extern int ORSlen; | |
515 | extern char *OFMT; | |
516 | extern char *CONVFMT; | |
517 | extern int CONVFMTidx; | |
518 | extern int OFMTidx; | |
519 | extern NODE *FS_node, *NF_node, *RS_node, *NR_node; | |
520 | extern NODE *FILENAME_node, *OFS_node, *ORS_node, *OFMT_node; | |
521 | extern NODE *CONVFMT_node; | |
522 | extern NODE *FNR_node, *RLENGTH_node, *RSTART_node, *SUBSEP_node; | |
523 | extern NODE *IGNORECASE_node; | |
524 | extern NODE *FIELDWIDTHS_node; | |
525 | ||
526 | extern NODE **stack_ptr; | |
527 | extern NODE *Nnull_string; | |
528 | extern NODE **fields_arr; | |
529 | extern int sourceline; | |
530 | extern char *source; | |
531 | extern NODE *expression_value; | |
532 | ||
533 | extern NODE *_t; /* used as temporary in tree_eval */ | |
534 | ||
535 | extern const char *myname; | |
536 | ||
537 | extern NODE *nextfree; | |
538 | extern int field0_valid; | |
539 | extern int do_unix; | |
540 | extern int do_posix; | |
541 | extern int do_lint; | |
542 | extern int in_begin_rule; | |
543 | extern int in_end_rule; | |
544 | ||
545 | /* ------------------------- Pseudo-functions ------------------------- */ | |
546 | ||
547 | #define is_identchar(c) (isalnum(c) || (c) == '_') | |
548 | ||
549 | ||
550 | #ifndef MPROF | |
551 | #define getnode(n) if (nextfree) n = nextfree, nextfree = nextfree->nextp;\ | |
552 | else n = more_nodes() | |
553 | #define freenode(n) ((n)->nextp = nextfree, nextfree = (n)) | |
554 | #else | |
555 | #define getnode(n) emalloc(n, NODE *, sizeof(NODE), "getnode") | |
556 | #define freenode(n) free(n) | |
557 | #endif | |
558 | ||
559 | #ifdef DEBUG | |
560 | #define tree_eval(t) r_tree_eval(t) | |
561 | #else | |
562 | #define tree_eval(t) (_t = (t),(_t) == NULL ? Nnull_string : \ | |
563 | ((_t)->type == Node_val ? (_t) : \ | |
564 | ((_t)->type == Node_var ? (_t)->var_value : \ | |
565 | ((_t)->type == Node_param_list ? \ | |
566 | (stack_ptr[(_t)->param_cnt])->var_value : \ | |
567 | r_tree_eval((_t)))))) | |
568 | #endif | |
569 | ||
570 | #define make_number(x) mk_number((x), (MALLOC|NUM|NUMBER)) | |
571 | #define tmp_number(x) mk_number((x), (MALLOC|TEMP|NUM|NUMBER)) | |
572 | ||
573 | #define free_temp(n) do {if ((n)->flags&TEMP) { unref(n); }} while (0) | |
574 | #define make_string(s,l) make_str_node((s), SZTC (l),0) | |
575 | #define SCAN 1 | |
576 | #define ALREADY_MALLOCED 2 | |
577 | ||
578 | #define cant_happen() fatal("internal error line %d, file: %s", \ | |
579 | __LINE__, __FILE__); | |
580 | ||
581 | #if defined(__STDC__) && !defined(NO_TOKEN_PASTING) | |
582 | #define emalloc(var,ty,x,str) (void)((var=(ty)malloc((MALLOC_ARG_T)(x))) ||\ | |
583 | (fatal("%s: %s: can't allocate memory (%s)",\ | |
584 | (str), #var, strerror(errno)),0)) | |
585 | #define erealloc(var,ty,x,str) (void)((var=(ty)realloc((char *)var,\ | |
586 | (MALLOC_ARG_T)(x))) ||\ | |
587 | (fatal("%s: %s: can't allocate memory (%s)",\ | |
588 | (str), #var, strerror(errno)),0)) | |
589 | #else /* __STDC__ */ | |
590 | #define emalloc(var,ty,x,str) (void)((var=(ty)malloc((MALLOC_ARG_T)(x))) ||\ | |
591 | (fatal("%s: %s: can't allocate memory (%s)",\ | |
592 | (str), "var", strerror(errno)),0)) | |
593 | #define erealloc(var,ty,x,str) (void)((var=(ty)realloc((char *)var,\ | |
594 | (MALLOC_ARG_T)(x))) ||\ | |
595 | (fatal("%s: %s: can't allocate memory (%s)",\ | |
596 | (str), "var", strerror(errno)),0)) | |
597 | #endif /* __STDC__ */ | |
598 | ||
599 | #ifdef DEBUG | |
600 | #define force_number r_force_number | |
601 | #define force_string r_force_string | |
602 | #else /* not DEBUG */ | |
603 | #ifdef lint | |
604 | extern AWKNUM force_number(); | |
605 | #endif | |
606 | #ifdef MSDOS | |
607 | extern double _msc51bug; | |
608 | #define force_number(n) (_msc51bug=(_t = (n),(_t->flags & NUM) ? _t->numbr : r_force_number(_t))) | |
609 | #else /* not MSDOS */ | |
610 | #define force_number(n) (_t = (n),(_t->flags & NUM) ? _t->numbr : r_force_number(_t)) | |
611 | #endif /* MSDOS */ | |
612 | #define force_string(s) (_t = (s),(_t->flags & STR) ? _t : r_force_string(_t)) | |
613 | #endif /* not DEBUG */ | |
614 | ||
615 | #define STREQ(a,b) (*(a) == *(b) && strcmp((a), (b)) == 0) | |
616 | #define STREQN(a,b,n) ((n)&& *(a)== *(b) && strncmp((a), (b), SZTC (n)) == 0) | |
617 | ||
618 | /* ------------- Function prototypes or defs (as appropriate) ------------- */ | |
619 | ||
620 | /* array.c */ | |
621 | extern NODE *concat_exp P((NODE *tree)); | |
622 | extern void assoc_clear P((NODE *symbol)); | |
623 | extern unsigned int hash P((char *s, int len)); | |
624 | extern int in_array P((NODE *symbol, NODE *subs)); | |
625 | extern NODE **assoc_lookup P((NODE *symbol, NODE *subs)); | |
626 | extern void do_delete P((NODE *symbol, NODE *tree)); | |
627 | extern void assoc_scan P((NODE *symbol, struct search *lookat)); | |
628 | extern void assoc_next P((struct search *lookat)); | |
629 | /* awk.tab.c */ | |
630 | extern char *tokexpand P((void)); | |
631 | extern char nextc P((void)); | |
632 | extern NODE *node P((NODE *left, NODETYPE op, NODE *right)); | |
633 | extern NODE *install P((char *name, NODE *value)); | |
634 | extern NODE *lookup P((char *name)); | |
635 | extern NODE *variable P((char *name, int can_free)); | |
636 | extern int yyparse P((void)); | |
637 | /* builtin.c */ | |
638 | extern NODE *do_exp P((NODE *tree)); | |
639 | extern NODE *do_index P((NODE *tree)); | |
640 | extern NODE *do_int P((NODE *tree)); | |
641 | extern NODE *do_length P((NODE *tree)); | |
642 | extern NODE *do_log P((NODE *tree)); | |
643 | extern NODE *do_sprintf P((NODE *tree)); | |
644 | extern void do_printf P((NODE *tree)); | |
645 | extern void print_simple P((NODE *tree, FILE *fp)); | |
646 | extern NODE *do_sqrt P((NODE *tree)); | |
647 | extern NODE *do_substr P((NODE *tree)); | |
648 | extern NODE *do_strftime P((NODE *tree)); | |
649 | extern NODE *do_systime P((NODE *tree)); | |
650 | extern NODE *do_system P((NODE *tree)); | |
651 | extern void do_print P((NODE *tree)); | |
652 | extern NODE *do_tolower P((NODE *tree)); | |
653 | extern NODE *do_toupper P((NODE *tree)); | |
654 | extern NODE *do_atan2 P((NODE *tree)); | |
655 | extern NODE *do_sin P((NODE *tree)); | |
656 | extern NODE *do_cos P((NODE *tree)); | |
657 | extern NODE *do_rand P((NODE *tree)); | |
658 | extern NODE *do_srand P((NODE *tree)); | |
659 | extern NODE *do_match P((NODE *tree)); | |
660 | extern NODE *do_gsub P((NODE *tree)); | |
661 | extern NODE *do_sub P((NODE *tree)); | |
662 | /* eval.c */ | |
663 | extern int interpret P((NODE *volatile tree)); | |
664 | extern NODE *r_tree_eval P((NODE *tree)); | |
665 | extern int cmp_nodes P((NODE *t1, NODE *t2)); | |
666 | extern NODE **get_lhs P((NODE *ptr, Func_ptr *assign)); | |
667 | extern void set_IGNORECASE P((void)); | |
668 | void set_OFS P((void)); | |
669 | void set_ORS P((void)); | |
670 | void set_OFMT P((void)); | |
671 | void set_CONVFMT P((void)); | |
672 | /* field.c */ | |
673 | extern void init_fields P((void)); | |
674 | extern void set_record P((char *buf, int cnt, int freeold)); | |
675 | extern void reset_record P((void)); | |
676 | extern void set_NF P((void)); | |
677 | extern NODE **get_field P((int num, Func_ptr *assign)); | |
678 | extern NODE *do_split P((NODE *tree)); | |
679 | extern void set_FS P((void)); | |
680 | extern void set_RS P((void)); | |
681 | extern void set_FIELDWIDTHS P((void)); | |
682 | /* io.c */ | |
683 | extern void set_FNR P((void)); | |
684 | extern void set_NR P((void)); | |
685 | extern void do_input P((void)); | |
686 | extern struct redirect *redirect P((NODE *tree, int *errflg)); | |
687 | extern NODE *do_close P((NODE *tree)); | |
688 | extern int flush_io P((void)); | |
689 | extern int close_io P((void)); | |
690 | extern int devopen P((char *name, char *mode)); | |
691 | extern int pathopen P((char *file)); | |
692 | extern NODE *do_getline P((NODE *tree)); | |
693 | extern void do_nextfile P((void)); | |
694 | /* iop.c */ | |
695 | extern int optimal_bufsize P((int fd)); | |
696 | extern IOBUF *iop_alloc P((int fd)); | |
697 | extern int get_a_record P((char **out, IOBUF *iop, int rs, int *errcode)); | |
698 | /* main.c */ | |
699 | extern int main P((int argc, char **argv)); | |
700 | extern Regexp *mk_re_parse P((char *s, int ignorecase)); | |
701 | extern void load_environ P((void)); | |
702 | extern char *arg_assign P((char *arg)); | |
703 | extern SIGTYPE catchsig P((int sig, int code)); | |
704 | /* msg.c */ | |
705 | #ifdef MSDOS | |
706 | extern void err P((char *s, char *emsg, char *va_list, ...)); | |
707 | extern void msg P((char *va_alist, ...)); | |
708 | extern void warning P((char *va_alist, ...)); | |
709 | extern void fatal P((char *va_alist, ...)); | |
710 | #else | |
711 | extern void err (); | |
712 | extern void msg (); | |
713 | extern void warning (); | |
714 | extern void fatal (); | |
715 | #endif | |
716 | /* node.c */ | |
717 | extern AWKNUM r_force_number P((NODE *n)); | |
718 | extern NODE *r_force_string P((NODE *s)); | |
719 | extern NODE *dupnode P((NODE *n)); | |
720 | extern NODE *mk_number P((AWKNUM x, unsigned int flags)); | |
721 | extern NODE *make_str_node P((char *s, size_t len, int scan )); | |
722 | extern NODE *tmp_string P((char *s, size_t len )); | |
723 | extern NODE *more_nodes P((void)); | |
724 | #ifdef DEBUG | |
725 | extern void freenode P((NODE *it)); | |
726 | #endif | |
727 | extern void unref P((NODE *tmp)); | |
728 | extern int parse_escape P((char **string_ptr)); | |
729 | /* re.c */ | |
730 | extern Regexp *make_regexp P((char *s, int len, int ignorecase, int dfa)); | |
731 | extern int research P((Regexp *rp, char *str, int start, int len, int need_start)); | |
732 | extern void refree P((Regexp *rp)); | |
733 | extern void reg_error P((const char *s)); | |
734 | extern Regexp *re_update P((NODE *t)); | |
735 | extern void resyntax P((int syntax)); | |
736 | extern void resetup P((void)); | |
737 | ||
738 | /* strcase.c */ | |
739 | extern int strcasecmp P((const char *s1, const char *s2)); | |
740 | extern int strncasecmp P((const char *s1, const char *s2, register size_t n)); | |
741 | ||
742 | #ifdef atarist | |
743 | /* atari/tmpnam.c */ | |
744 | extern char *tmpnam P((char *buf)); | |
745 | extern char *tempnam P((const char *path, const char *base)); | |
746 | #endif | |
747 | ||
748 | /* Figure out what '\a' really is. */ | |
749 | #ifdef __STDC__ | |
750 | #define BELL '\a' /* sure makes life easy, don't it? */ | |
751 | #else | |
752 | # if 'z' - 'a' == 25 /* ascii */ | |
753 | # if 'a' != 97 /* machine is dumb enough to use mark parity */ | |
754 | # define BELL '\207' | |
755 | # else | |
756 | # define BELL '\07' | |
757 | # endif | |
758 | # else | |
759 | # define BELL '\057' | |
760 | # endif | |
761 | #endif | |
762 | ||
763 | extern char casetable[]; /* for case-independent regexp matching */ |