1/*
2 * awk.h -- Definitions for gawk.
3 */
4
5/*
6 * Copyright (C) 1986, 1988, 1989, 1991-2003 the Free Software Foundation, Inc.
7 *
8 * This file is part of GAWK, the GNU implementation of the
9 * AWK Programming 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 this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
24 */
25
26/* ------------------------------ Includes ------------------------------ */
27
28/*
29 * config.h absolutely, positively, *M*U*S*T* be included before
30 * any system headers.  Otherwise, extreme death, destruction
31 * and loss of life results.
32 *
33 * Well, OK, gawk just won't work on systems using egcs and LFS.  But
34 * that's almost as bad.
35 */
36#ifdef HAVE_CONFIG_H
37#include <config.h>
38#endif
39
40#ifndef _GNU_SOURCE
41#define _GNU_SOURCE	1	/* enable GNU extensions */
42#endif /* _GNU_SOURCE */
43
44#include <stdio.h>
45#include <assert.h>
46#ifdef HAVE_LIMITS_H
47#include <limits.h>
48#endif /* HAVE_LIMITS_H */
49#include <ctype.h>
50#include <setjmp.h>
51
52#include "gettext.h"
53#define _(msgid)  gettext(msgid)
54#define N_(msgid) msgid
55
56#if ! (defined(HAVE_LIBINTL_H) && defined(ENABLE_NLS) && ENABLE_NLS > 0)
57#ifndef LOCALEDIR
58#define LOCALEDIR NULL
59#endif /* LOCALEDIR */
60#endif
61
62#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
63#include <stdarg.h>
64#else
65#include <varargs.h>
66#endif
67#include <signal.h>
68#include <time.h>
69#include <errno.h>
70#if ! defined(errno) && ! defined(MSDOS) && ! defined(OS2)
71extern int errno;
72#endif
73#ifdef HAVE_SIGNUM_H
74#include <signum.h>
75#endif
76#if defined(HAVE_MBRLEN) && defined(HAVE_MBRTOWC) && defined(HAVE_WCHAR_H) && defined(HAVE_WCTYPE_H)
77/* We can handle multibyte strings.  */
78#define MBS_SUPPORT
79#include <wchar.h>
80#include <wctype.h>
81#endif
82
83/* ----------------- System dependencies (with more includes) -----------*/
84
85/* This section is the messiest one in the file, not a lot that can be done */
86
87/* First, get the ctype stuff right; from Jim Meyering */
88#if defined(STDC_HEADERS) || (!defined(isascii) && !defined(HAVE_ISASCII))
89#define IN_CTYPE_DOMAIN(c) 1
90#else
91#define IN_CTYPE_DOMAIN(c) isascii((unsigned char) c)
92#endif
93
94#ifdef isblank
95#define ISBLANK(c) (IN_CTYPE_DOMAIN(c) && isblank((unsigned char) c))
96#else
97#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
98#endif
99#ifdef isgraph
100#define ISGRAPH(c) (IN_CTYPE_DOMAIN(c) && isgraph((unsigned char) c))
101#else
102#define ISGRAPH(c) (IN_CTYPE_DOMAIN(c) && isprint((unsigned char) c) && !isspace((unsigned char) c))
103#endif
104
105#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint ((unsigned char) c))
106#define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit ((unsigned char) c))
107#define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum ((unsigned char) c))
108#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha ((unsigned char) c))
109#define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl ((unsigned char) c))
110#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower ((unsigned char) c))
111#define ISPUNCT(c) (IN_CTYPE_DOMAIN (c) && ispunct (unsigned char) (c))
112#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace ((unsigned char) c))
113#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper ((unsigned char) c))
114#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit ((unsigned char) c))
115
116#ifndef TOUPPER
117#define TOUPPER(c)	toupper((unsigned char) c)
118#endif
119#ifndef TOLOWER
120#define TOLOWER(c)	tolower((unsigned char) c)
121#endif
122
123#ifdef __STDC__
124#define	P(s)	s
125#define MALLOC_ARG_T size_t
126#else	/* not __STDC__ */
127#define	P(s)	()
128#define MALLOC_ARG_T unsigned
129#define volatile
130#endif	/* not __STDC__ */
131
132#ifndef VMS
133#include <sys/types.h>
134#include <sys/stat.h>
135#else	/* VMS */
136#include <stddef.h>
137#include <stat.h>
138#include <file.h>	/* avoid <fcntl.h> in io.c */
139#endif	/* VMS */
140
141#if ! defined(S_ISREG) && defined(S_IFREG)
142#define	S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
143#endif
144
145#ifdef STDC_HEADERS
146#include <stdlib.h>
147#else	/* not STDC_HEADERS */
148#include "protos.h"
149#endif	/* not STDC_HEADERS */
150
151#ifdef HAVE_STRING_H
152#include <string.h>
153#ifdef NEED_MEMORY_H
154#include <memory.h>
155#endif	/* NEED_MEMORY_H */
156#else	/* not HAVE_STRING_H */
157#ifdef HAVE_STRINGS_H
158#include <strings.h>
159#endif	/* HAVE_STRINGS_H */
160#endif	/* not HAVE_STRING_H */
161
162#ifdef NeXT
163#if __GNUC__ < 2 || __GNUC_MINOR__ < 7
164#include <libc.h>
165#endif
166#undef atof
167#define getopt GNU_getopt
168#define GFMT_WORKAROUND
169#endif	/* NeXT */
170
171#if defined(atarist) || defined(VMS)
172#include <unixlib.h>
173#endif	/* atarist || VMS */
174
175#if ! defined(MSDOS) && ! defined(OS2) && ! defined(WIN32) && ! defined(__EMX__) && ! defined(__CYGWIN__) && ! (defined(__BEOS__) || defined(__HAIKU__)) && ! defined(O_BINARY) /*duh*/
176#define O_BINARY	0
177#endif
178
179#if defined(TANDEM)
180#define variable variabl
181#define open(name, how, mode)	open(name, how)	/* !!! ANSI C !!! */
182#endif
183
184#if HAVE_UNISTD_H
185#include <unistd.h>
186#endif	/* HAVE_UNISTD_H */
187
188#ifndef HAVE_VPRINTF
189/* if you don't have vprintf, try this and cross your fingers. */
190#ifdef	HAVE_DOPRNT
191#define vfprintf(fp,fmt,arg)	_doprnt((fmt), (arg), (fp))
192#else	/* not HAVE_DOPRNT */
193you
194lose
195#endif	/* not HAVE_DOPRNT */
196#endif	/* HAVE_VPRINTF */
197
198#ifndef HAVE_SETLOCALE
199#define setlocale(locale, val)	/* nothing */
200#endif /* HAVE_SETLOCALE */
201
202/* use this as lintwarn("...")
203   this is a hack but it gives us the right semantics */
204#define lintwarn (*(set_loc(__FILE__, __LINE__),lintfunc))
205
206#ifdef VMS
207#include "vms/redirect.h"
208#endif  /*VMS*/
209
210#ifdef atarist
211#include "unsupported/atari/redirect.h"
212#endif
213
214#define RE_TRANSLATE_TYPE const char *
215#define	GNU_REGEX
216#ifdef GNU_REGEX
217#include "regex.h"
218typedef struct Regexp {
219	struct re_pattern_buffer pat;
220	struct re_registers regs;
221} Regexp;
222#define	RESTART(rp,s)	(rp)->regs.start[0]
223#define	REEND(rp,s)	(rp)->regs.end[0]
224#define	SUBPATSTART(rp,s,n)	(rp)->regs.start[n]
225#define	SUBPATEND(rp,s,n)	(rp)->regs.end[n]
226#define	NUMSUBPATS(rp,s)	(rp)->regs.num_regs
227#endif	/* GNU_REGEX */
228
229/* Stuff for losing systems. */
230#ifdef STRTOD_NOT_C89
231extern double gawk_strtod();
232#define strtod gawk_strtod
233#endif
234
235#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
236# define __attribute__(x)
237#endif
238
239#ifndef ATTRIBUTE_UNUSED
240#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
241#endif /* ATTRIBUTE_UNUSED */
242
243#ifndef ATTRIBUTE_NORETURN
244#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
245#endif /* ATTRIBUTE_NORETURN */
246
247#ifndef ATTRIBUTE_PRINTF
248#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
249#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
250#endif /* ATTRIBUTE_PRINTF */
251
252/* We use __extension__ in some places to suppress -pedantic warnings
253   about GCC extensions.  This feature didn't work properly before
254   gcc 2.8.  */
255#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
256#define __extension__
257#endif
258
259/* this is defined by Windows32 extension libraries. It must be added to
260 * every variable which is exported (including function pointers) */
261#if defined(WIN32_EXTENSION) && !defined(ATTRIBUTE_EXPORTED)
262# define ATTRIBUTE_EXPORTED __declspec(dllimport)
263#else
264# define ATTRIBUTE_EXPORTED
265#endif
266
267
268/* ------------------ Constants, Structures, Typedefs  ------------------ */
269
270#ifndef AWKNUM
271#define AWKNUM	double
272#endif
273
274#ifndef TRUE
275/* a bit hackneyed, but what the heck */
276#define TRUE	1
277#define FALSE	0
278#endif
279
280#define LINT_INVALID	1	/* only warn about invalid */
281#define LINT_ALL	2	/* warn about all things */
282
283/* Figure out what '\a' really is. */
284#ifdef __STDC__
285#define BELL	'\a'		/* sure makes life easy, don't it? */
286#else
287#	if 'z' - 'a' == 25	/* ascii */
288#		if 'a' != 97	/* machine is dumb enough to use mark parity */
289#			define BELL	'\207'
290#		else
291#			define BELL	'\07'
292#		endif
293#	else
294#		define BELL	'\057'
295#	endif
296#endif
297
298typedef enum nodevals {
299	/* illegal entry == 0 */
300	Node_illegal,
301
302	/* binary operators  lnode and rnode are the expressions to work on */
303	Node_times,
304	Node_quotient,
305	Node_mod,
306	Node_plus,
307	Node_minus,
308	Node_cond_pair,		/* conditional pair (see Node_line_range) */
309	Node_subscript,
310	Node_concat,
311	Node_exp,
312
313	/* unary operators   subnode is the expression to work on */
314	Node_preincrement,
315	Node_predecrement,
316	Node_postincrement,
317	Node_postdecrement,
318	Node_unary_minus,
319	Node_field_spec,
320
321	/* assignments   lnode is the var to assign to, rnode is the exp */
322	Node_assign,
323	Node_assign_times,
324	Node_assign_quotient,
325	Node_assign_mod,
326	Node_assign_plus,
327	Node_assign_minus,
328	Node_assign_exp,
329
330	/* boolean binaries   lnode and rnode are expressions */
331	Node_and,
332	Node_or,
333
334	/* binary relationals   compares lnode and rnode */
335	Node_equal,
336	Node_notequal,
337	Node_less,
338	Node_greater,
339	Node_leq,
340	Node_geq,
341	Node_match,
342	Node_nomatch,
343
344	/* unary relationals   works on subnode */
345	Node_not,
346
347	/* program structures */
348	Node_rule_list,		/* lnode is a rule, rnode is rest of list */
349	Node_rule_node,		/* lnode is pattern, rnode is statement */
350	Node_statement_list,	/* lnode is statement, rnode is more list */
351	Node_switch_body,	/* lnode is the case list, rnode is default list */
352	Node_case_list,	/* lnode is the case, rnode is a statement list */
353	Node_if_branches,	/* lnode is to run on true, rnode on false */
354	Node_expression_list,	/* lnode is an exp, rnode is more list */
355	Node_param_list,	/* lnode is a variable, rnode is more list */
356
357	/* keywords */
358	Node_K_if,		/* lnode is conditonal, rnode is if_branches */
359	Node_K_switch,		/* lnode is switch value, rnode is body of case statements */
360	Node_K_case,		/* lnode is case value, rnode is stuff to run */
361	Node_K_default,		/* lnode is empty, rnode is stuff to run */
362	Node_K_while,		/* lnode is condtional, rnode is stuff to run */
363	Node_K_for,		/* lnode is for_struct, rnode is stuff to run */
364	Node_K_arrayfor,	/* lnode is for_struct, rnode is stuff to run */
365	Node_K_break,		/* no subs */
366	Node_K_continue,	/* no subs */
367	Node_K_print,		/* lnode is exp_list, rnode is redirect */
368	Node_K_print_rec,	/* lnode is NULL, rnode is redirect */
369	Node_K_printf,		/* lnode is exp_list, rnode is redirect */
370	Node_K_next,		/* no subs */
371	Node_K_exit,		/* subnode is return value, or NULL */
372	Node_K_do,		/* lnode is conditional, rnode stuff to run */
373	Node_K_return,		/* lnode is return value */
374	Node_K_delete,		/* lnode is array, rnode is subscript */
375	Node_K_delete_loop,	/* lnode is array, rnode is subscript */
376	Node_K_getline,		/* lnode is opt var, rnode is redirection */
377	Node_K_function,	/* lnode is statement list, rnode is params */
378	Node_K_nextfile,	/* no subs */
379
380	/* I/O redirection for print statements */
381	Node_redirect_output,	/* subnode is where to redirect */
382	Node_redirect_append,	/* subnode is where to redirect */
383	Node_redirect_pipe,	/* subnode is where to redirect */
384	Node_redirect_pipein,	/* subnode is where to redirect */
385	Node_redirect_input,	/* subnode is where to redirect */
386	Node_redirect_twoway,	/* subnode is where to redirect */
387
388	/* Variables */
389	Node_var_new,		/* newly created variable, may become an array */
390	Node_var,		/* scalar variable, lnode is value */
391	Node_var_array,		/* array is ptr to elements, table_size num of eles */
392	Node_val,		/* node is a value - type in flags */
393
394	/* Builtins   subnode is explist to work on, builtin is func to call */
395	Node_builtin,
396
397	/*
398	 * pattern: conditional ',' conditional ;  lnode of Node_line_range
399	 * is the two conditionals (Node_cond_pair), other word (rnode place)
400	 * is a flag indicating whether or not this range has been entered.
401	 */
402	Node_line_range,
403
404	/*
405	 * boolean test of membership in array
406	 * lnode is string-valued, expression rnode is array name
407	 */
408	Node_in_array,
409
410	Node_func,		/* lnode is param. list, rnode is body */
411	Node_func_call,		/* lnode is name, rnode is argument list */
412
413	Node_cond_exp,		/* lnode is conditonal, rnode is if_branches */
414	Node_regex,		/* a regexp, text, compiled, flags, etc */
415	Node_dynregex,		/* a dynamic regexp */
416	Node_hashnode,		/* an identifier in the symbol table */
417	Node_ahash,		/* an array element */
418	Node_array_ref,		/* array passed by ref as parameter */
419
420	Node_BINMODE,		/* variables recognized in the grammar */
421	Node_CONVFMT,
422	Node_FIELDWIDTHS,
423	Node_FNR,
424	Node_FS,
425	Node_IGNORECASE,
426	Node_LINT,
427	Node_NF,
428	Node_NR,
429	Node_OFMT,
430	Node_OFS,
431	Node_ORS,
432	Node_RS,
433	Node_TEXTDOMAIN,
434	Node_final		/* sentry value, not legal */
435} NODETYPE;
436
437/*
438 * NOTE - this struct is a rather kludgey -- it is packed to minimize
439 * space usage, at the expense of cleanliness.  Alter at own risk.
440 */
441typedef struct exp_node {
442	union {
443		struct {
444			union {
445				struct exp_node *lptr;
446				char *param_name;
447				long ll;
448			} l;
449			union {
450				struct exp_node *rptr;
451				struct exp_node *(*pptr) P((struct exp_node *));
452				Regexp *preg;
453				struct for_loop_header *hd;
454				struct exp_node **av;
455				int r_ent;	/* range entered */
456			} r;
457			union {
458				struct exp_node *extra;
459				long xl;
460				char **param_list;
461			} x;
462			char *name;
463			short number;
464			unsigned long reflags;
465#				define	CASE	1
466#				define	CONST	2
467#				define	FS_DFLT	4
468		} nodep;
469		struct {
470			AWKNUM fltnum;	/* this is here for optimal packing of
471					 * the structure on many machines
472					 */
473			char *sp;
474			size_t slen;
475			long sref;
476			int idx;
477		} val;
478		struct {
479			struct exp_node *next;
480			char *name;
481			size_t length;
482			struct exp_node *value;
483			long ref;
484		} hash;
485#define	hnext	sub.hash.next
486#define	hname	sub.hash.name
487#define	hlength	sub.hash.length
488#define	hvalue	sub.hash.value
489
490#define	ahnext		sub.hash.next
491#define	ahname_str	sub.hash.name
492#define ahname_len	sub.hash.length
493#define	ahvalue	sub.hash.value
494#define ahname_ref	sub.hash.ref
495	} sub;
496	NODETYPE type;
497	unsigned short flags;
498#		define	MALLOC	1	/* can be free'd */
499#		define	TEMP	2	/* should be free'd */
500#		define	PERM	4	/* can't be free'd */
501#		define	STRING	8	/* assigned as string */
502#		define	STRCUR	16	/* string value is current */
503#		define	NUMCUR	32	/* numeric value is current */
504#		define	NUMBER	64	/* assigned as number */
505#		define	MAYBE_NUM 128	/* user input: if NUMERIC then
506					 * a NUMBER */
507#		define	ARRAYMAXED 256	/* array is at max size */
508#		define	FUNC	512	/* this parameter is really a
509					 * function name; see awkgram.y */
510#		define	FIELD	1024	/* this is a field */
511#		define	INTLSTR	2048	/* use localized version */
512} NODE;
513
514#define vname sub.nodep.name
515#define exec_count sub.nodep.reflags
516
517#define lnode	sub.nodep.l.lptr
518#define nextp	sub.nodep.l.lptr
519#define rnode	sub.nodep.r.rptr
520#define source_file	sub.nodep.name
521#define	source_line	sub.nodep.number
522#define	param_cnt	sub.nodep.number
523#define param	sub.nodep.l.param_name
524#define parmlist	sub.nodep.x.param_list
525
526#define subnode	lnode
527#define builtin sub.nodep.r.pptr
528#define callresult sub.nodep.x.extra
529#define funcbody sub.nodep.x.extra
530
531#define re_reg	sub.nodep.r.preg
532#define re_flags sub.nodep.reflags
533#define re_text lnode
534#define re_exp	sub.nodep.x.extra
535
536#define forloop	rnode->sub.nodep.r.hd
537
538#define stptr	sub.val.sp
539#define stlen	sub.val.slen
540#define stref	sub.val.sref
541#define	stfmt	sub.val.idx
542
543#define numbr	sub.val.fltnum
544
545/* Node_var: */
546#define var_value lnode
547
548/* Node_var_array: */
549#define var_array sub.nodep.r.av
550#define array_size sub.nodep.l.ll
551#define table_size sub.nodep.x.xl
552
553/* Node_array_ref: */
554#define orig_array sub.nodep.x.extra
555#define prev_array rnode
556
557#define printf_count sub.nodep.x.xl
558
559#define condpair lnode
560#define triggered sub.nodep.r.r_ent
561
562/* a regular for loop */
563typedef struct for_loop_header {
564	NODE *init;
565	NODE *cond;
566	NODE *incr;
567} FOR_LOOP_HEADER;
568
569typedef struct iobuf {
570	const char *name;       /* filename */
571	int fd;                 /* file descriptor */
572	struct stat sbuf;       /* stat buf */
573	char *buf;              /* start data buffer */
574	char *off;              /* start of current record in buffer */
575	char *dataend;          /* first byte in buffer to hold new data,
576				   NULL if not read yet */
577	char *end;              /* end of buffer */
578	size_t readsize;        /* set from fstat call */
579	size_t size;            /* buffer size */
580	ssize_t count;          /* amount read last time */
581	size_t scanoff;         /* where we were in the buffer when we had
582				   to regrow/refill */
583	int flag;
584#		define	IOP_IS_TTY	1
585#		define	IOP_IS_INTERNAL	2
586#		define	IOP_NO_FREE	4
587#		define	IOP_NOFREE_OBJ	8
588#               define  IOP_AT_EOF      16
589#               define  IOP_CLOSED      32
590} IOBUF;
591
592typedef void (*Func_ptr) P((void));
593
594/* structure used to dynamically maintain a linked-list of open files/pipes */
595struct redirect {
596	unsigned int flag;
597#		define	RED_FILE	1
598#		define	RED_PIPE	2
599#		define	RED_READ	4
600#		define	RED_WRITE	8
601#		define	RED_APPEND	16
602#		define	RED_NOBUF	32
603#		define	RED_USED	64	/* closed temporarily to reuse fd */
604#		define	RED_EOF		128
605#		define	RED_TWOWAY	256
606#		define	RED_PTY		512
607#		define	RED_SOCKET	1024
608#		define	RED_TCP		2048
609	char *value;
610	FILE *fp;
611	FILE *ifp;	/* input fp, needed for PIPES_SIMULATED */
612	IOBUF *iop;
613	int pid;
614	int status;
615	struct redirect *prev;
616	struct redirect *next;
617	const char *mode;
618};
619
620/*
621 * structure for our source, either a command line string or a source file.
622 * the same structure is used to remember variable pre-assignments.
623 */
624struct src {
625       enum srctype { CMDLINE = 1, SOURCEFILE,
626			PRE_ASSIGN, PRE_ASSIGN_FS } stype;
627       char *val;
628};
629
630/* for debugging purposes */
631struct flagtab {
632	int val;
633	const char *name;
634};
635
636/* longjmp return codes, must be nonzero */
637/* Continue means either for loop/while continue, or next input record */
638#define TAG_CONTINUE 1
639/* Break means either for/while break, or stop reading input */
640#define TAG_BREAK 2
641/* Return means return from a function call; leave value in ret_node */
642#define	TAG_RETURN 3
643
644#ifndef LONG_MAX
645#define LONG_MAX ((long)(~(1L << (sizeof (long) * 8 - 1))))
646#endif
647#ifndef ULONG_MAX
648#define ULONG_MAX (~(unsigned long)0)
649#endif
650#ifndef LONG_MIN
651#define LONG_MIN ((long)(-LONG_MAX - 1L))
652#endif
653#define HUGE    LONG_MAX
654
655/* -------------------------- External variables -------------------------- */
656/* gawk builtin variables */
657extern long NF;
658extern long NR;
659extern long FNR;
660extern int BINMODE;
661extern int IGNORECASE;
662extern int RS_is_null;
663extern char *OFS;
664extern int OFSlen;
665extern char *ORS;
666extern int ORSlen;
667extern char *OFMT;
668extern char *CONVFMT;
669ATTRIBUTE_EXPORTED extern int CONVFMTidx;
670extern int OFMTidx;
671extern char *TEXTDOMAIN;
672extern NODE *BINMODE_node, *CONVFMT_node, *FIELDWIDTHS_node, *FILENAME_node;
673extern NODE *FNR_node, *FS_node, *IGNORECASE_node, *NF_node;
674extern NODE *NR_node, *OFMT_node, *OFS_node, *ORS_node, *RLENGTH_node;
675extern NODE *RSTART_node, *RS_node, *RT_node, *SUBSEP_node, *PROCINFO_node;
676extern NODE *LINT_node, *ERRNO_node, *TEXTDOMAIN_node;
677ATTRIBUTE_EXPORTED extern NODE **stack_ptr;
678extern NODE *Nnull_string;
679extern NODE *Null_field;
680extern NODE **fields_arr;
681extern int sourceline;
682extern char *source;
683extern NODE *expression_value;
684
685#if __GNUC__ < 2
686# if defined(WIN32_EXTENSION)
687static
688# else
689extern
690#endif
691NODE *_t;	/* used as temporary in tree_eval */
692#endif
693
694extern NODE *nextfree;
695extern int field0_valid;
696extern int do_traditional;
697extern int do_posix;
698extern int do_intervals;
699extern int do_intl;
700extern int do_non_decimal_data;
701extern int do_dump_vars;
702extern int do_tidy_mem;
703extern int in_begin_rule;
704extern int in_end_rule;
705extern int whiny_users;
706#ifdef NO_LINT
707#define do_lint 0
708#define do_lint_old 0
709#else
710ATTRIBUTE_EXPORTED extern int do_lint;
711extern int do_lint_old;
712#endif
713#ifdef MBS_SUPPORT
714extern int gawk_mb_cur_max;
715#endif
716
717#if defined (HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0
718extern GETGROUPS_T *groupset;
719extern int ngroups;
720#endif
721
722extern const char *myname;
723
724extern char quote;
725extern char *defpath;
726extern char envsep;
727
728extern const char casetable[];	/* for case-independent regexp matching */
729
730/* ------------------------- Pseudo-functions ------------------------- */
731
732#define is_identchar(c)		(isalnum(c) || (c) == '_')
733#define isnondecimal(str)	(((str)[0]) == '0' && (ISDIGIT((str)[1]) \
734					|| (str)[1] == 'x' || (str)[1] == 'X'))
735
736#define var_uninitialized(n)	((n)->var_value == Nnull_string)
737
738#ifdef MPROF
739#define	getnode(n)	emalloc((n), NODE *, sizeof(NODE), "getnode"), (n)->flags = 0, (n)-exec_count = 0;
740#define	freenode(n)	free(n)
741#else	/* not MPROF */
742#define	getnode(n)	if (nextfree) n = nextfree, nextfree = nextfree->nextp;\
743			else n = more_nodes()
744#ifndef NO_PROFILING
745#define	freenode(n)	((n)->flags = 0,\
746		(n)->exec_count = 0, (n)->nextp = nextfree, nextfree = (n))
747#else /* not PROFILING */
748#define	freenode(n)	((n)->flags = 0,\
749		(n)->nextp = nextfree, nextfree = (n))
750#endif	/* not PROFILING */
751#endif	/* not MPROF */
752
753#ifndef GAWKDEBUG
754#define DUPNODE_MACRO 1
755/*
756 * Speed up the path leading to r_dupnode, as well as duplicating TEMP nodes,
757 * on expense of slowing down the access to PERM nodes (by two instructions).
758 * This is right since PERM nodes are realtively rare.
759 *
760 * The code also sets MALLOC flag for PERM nodes, which should not matter.
761 */
762#define DUPNODE_COMMON	(_t->flags & (TEMP|PERM)) != 0 ? \
763			  (_t->flags &= ~TEMP, _t->flags |= MALLOC, _t) : \
764			  r_dupnode(_t)
765#if __GNUC__ >= 2
766#define dupnode(n)	({NODE * _t = (n); DUPNODE_COMMON;})
767#else
768#define dupnode(n)	(_t = (n), DUPNODE_COMMON)
769#endif
770#else	/* GAWKDEBUG */
771#define dupnode(n)	r_dupnode(n)
772#endif	/* GAWKDEBUG */
773
774#define get_array(t)	get_actual(t, TRUE)	/* allowed to die fatally */
775#define get_param(t)	get_actual(t, FALSE)	/* not allowed */
776
777#ifdef MEMDEBUG
778#undef freenode
779#define	get_lhs(p, a, r)	r_get_lhs((p), (a), (r))
780#define	m_tree_eval(t, iscond)	r_tree_eval(t, iscond)
781#else
782#define	get_lhs(p, a, r) ((p)->type == Node_var && \
783			  ! var_uninitialized(p) ? \
784			  (&(p)->var_value) : \
785			 r_get_lhs((p), (a), (r)))
786#define TREE_EVAL_MACRO 1
787#if __GNUC__ >= 2
788#define	m_tree_eval(t, iscond) __extension__ \
789                        ({NODE * _t = (t);                 \
790			   if (_t == NULL)                 \
791			       _t = Nnull_string;          \
792			   else {                          \
793			       switch(_t->type) {          \
794			       case Node_val:              \
795				   if (_t->flags&INTLSTR)  \
796					_t = r_force_string(_t); \
797				   break;                  \
798			       case Node_var:              \
799				   if (! var_uninitialized(_t)) { \
800				       _t = _t->var_value;     		   \
801				       break;                  		   \
802				   }					   \
803				   /*FALLTHROUGH*/			   \
804			       default:                    \
805				   _t = r_tree_eval(_t, iscond);\
806				   break;                  \
807			       }                           \
808			   }                               \
809			   _t;})
810#else
811#define	m_tree_eval(t, iscond)	(_t = (t), _t == NULL ? Nnull_string : \
812			(_t->type == Node_param_list ? \
813			  r_tree_eval(_t, iscond) : \
814			((_t->type == Node_val && (_t->flags&INTLSTR)) ? \
815				r_force_string(_t) : \
816			(_t->type == Node_val ? _t : \
817			(_t->type == Node_var && \
818			 ! var_uninitialized(_t) ? _t->var_value : \
819			 r_tree_eval(_t, iscond))))))
820#endif /* __GNUC__ */
821#endif /* not MEMDEBUG */
822#define tree_eval(t)	m_tree_eval(t, FALSE)
823
824#define	make_number(x)	mk_number((x), (unsigned int)(MALLOC|NUMCUR|NUMBER))
825#define	tmp_number(x)	mk_number((x), (unsigned int)(MALLOC|TEMP|NUMCUR|NUMBER))
826
827#define	free_temp(n)	do { NODE *_n = (n); if (_n->flags&TEMP) unref(_n);} \
828				while (FALSE)
829
830#define	make_string(s, l)	make_str_node((s), (size_t) (l), 0)
831#define		SCAN			1
832#define		ALREADY_MALLOCED	2
833
834#define	cant_happen()	r_fatal("internal error line %d, file: %s", \
835				__LINE__, __FILE__)
836
837#ifdef HAVE_STRINGIZE
838#define	emalloc(var,ty,x,str)	(void)((var=(ty)malloc((MALLOC_ARG_T)(x))) ||\
839				 (fatal(_("%s: %s: can't allocate %ld bytes of memory (%s)"),\
840					(str), #var, (long) (x), strerror(errno)),0))
841#define	erealloc(var,ty,x,str)	(void)((var=(ty)realloc((char *)var,\
842						  (MALLOC_ARG_T)(x))) ||\
843				 (fatal(_("%s: %s: can't allocate %ld bytes of memory (%s)"),\
844					(str), #var, (long) (x), strerror(errno)),0))
845#else /* HAVE_STRINGIZE */
846#define	emalloc(var,ty,x,str)	(void)((var=(ty)malloc((MALLOC_ARG_T)(x))) ||\
847				 (fatal(_("%s: %s: can't allocate %ld bytes of memory (%s)"),\
848					(str), "var", (long) (x), strerror(errno)),0))
849#define	erealloc(var,ty,x,str)	(void)((var=(ty)realloc((char *)var,\
850						  (MALLOC_ARG_T)(x))) ||\
851				 (fatal(_("%s: %s: can't allocate %ld bytes of memory (%s)"),\
852					(str), "var", (long) (x), strerror(errno)),0))
853#endif /* HAVE_STRINGIZE */
854
855#ifdef GAWKDEBUG
856#define	force_number	r_force_number
857#define	force_string	r_force_string
858#else /* not GAWKDEBUG */
859#ifdef lint
860extern AWKNUM force_number();
861#endif
862#if __GNUC__ >= 2
863#define	force_number(n)	__extension__ ({NODE *_tn = (n);\
864			(_tn->flags & NUMCUR) ?_tn->numbr : r_force_number(_tn);})
865#define	force_string(s)	__extension__ ({NODE *_ts = (s);\
866			  ((_ts->flags & INTLSTR) ? \
867				r_force_string(_ts) : \
868			  ((_ts->flags & STRCUR) && \
869			   (_ts->stfmt == -1 || _ts->stfmt == CONVFMTidx)) ?\
870			  _ts : r_force_string(_ts));})
871#else
872#ifdef MSDOS
873extern double _msc51bug;
874#define	force_number(n)	(_msc51bug=(_t = (n),\
875			  (_t->flags & NUMCUR) ? _t->numbr : r_force_number(_t)))
876#else /* not MSDOS */
877#define	force_number(n)	(_t = (n),\
878			 (_t->flags & NUMCUR) ? _t->numbr : r_force_number(_t))
879#endif /* not MSDOS */
880#define	force_string(s)	(_t = (s),(_t->flags & INTLSTR) ? \
881					r_force_string(_t) :\
882				((_t->flags & STRCUR) && \
883				 (_t->stfmt == -1 || \
884				 _t->stfmt == CONVFMTidx))? \
885			 _t : r_force_string(_t))
886
887#endif /* not __GNUC__ */
888#endif /* not GAWKDEBUG */
889
890#define	STREQ(a,b)	(*(a) == *(b) && strcmp((a), (b)) == 0)
891#define	STREQN(a,b,n)	((n) && *(a)== *(b) && \
892			 strncmp((a), (b), (size_t) (n)) == 0)
893
894#define fatal		set_loc(__FILE__, __LINE__), r_fatal
895
896/* ------------- Function prototypes or defs (as appropriate) ------------- */
897
898/* array.c */
899extern NODE *get_actual P((NODE *symbol, int canfatal));
900extern char *array_vname P((const NODE *symbol));
901extern void array_init P((void));
902extern NODE *concat_exp P((NODE *tree));
903extern void assoc_clear P((NODE *symbol));
904extern NODE *in_array P((NODE *symbol, NODE *subs));
905extern NODE **assoc_lookup P((NODE *symbol, NODE *subs, int reference));
906extern void do_delete P((NODE *symbol, NODE *tree));
907extern void do_delete_loop P((NODE *symbol, NODE *tree));
908extern NODE *assoc_dump P((NODE *symbol));
909extern NODE *do_adump P((NODE *tree));
910extern NODE *do_asort P((NODE *tree));
911extern NODE *do_asorti P((NODE *tree));
912extern unsigned long (*hash)P((const char *s, size_t len, unsigned long hsize));
913/* awkgram.c */
914extern char *tokexpand P((void));
915extern NODE *node P((NODE *left, NODETYPE op, NODE *right));
916extern NODE *install P((char *name, NODE *value));
917extern NODE *lookup P((const char *name));
918extern NODE *variable P((char *name, int can_free, NODETYPE type));
919extern int yyparse P((void));
920extern void dump_funcs P((void));
921extern void dump_vars P((const char *fname));
922extern void release_all_vars P((void));
923extern const char *getfname P((NODE *(*)(NODE *)));
924extern NODE *stopme P((NODE *tree));
925extern void shadow_funcs P((void));
926/* builtin.c */
927extern double double_to_int P((double d));
928extern NODE *do_exp P((NODE *tree));
929extern NODE *do_fflush P((NODE *tree));
930extern NODE *do_index P((NODE *tree));
931extern NODE *do_int P((NODE *tree));
932extern NODE *do_length P((NODE *tree));
933extern NODE *do_log P((NODE *tree));
934extern NODE *do_mktime P((NODE *tree));
935extern NODE *do_sprintf P((NODE *tree));
936extern void do_printf P((NODE *tree));
937extern void print_simple P((NODE *tree, FILE *fp));
938extern NODE *do_sqrt P((NODE *tree));
939extern NODE *do_substr P((NODE *tree));
940extern NODE *do_strftime P((NODE *tree));
941extern NODE *do_systime P((NODE *tree));
942extern NODE *do_system P((NODE *tree));
943extern void do_print P((NODE *tree));
944extern void do_print_rec P((NODE *tree));
945extern NODE *do_tolower P((NODE *tree));
946extern NODE *do_toupper P((NODE *tree));
947extern NODE *do_atan2 P((NODE *tree));
948extern NODE *do_sin P((NODE *tree));
949extern NODE *do_cos P((NODE *tree));
950extern NODE *do_rand P((NODE *tree));
951extern NODE *do_srand P((NODE *tree));
952extern NODE *do_match P((NODE *tree));
953extern NODE *do_gsub P((NODE *tree));
954extern NODE *do_sub P((NODE *tree));
955extern NODE *do_gensub P((NODE *tree));
956extern NODE *format_tree P((const char *, size_t, NODE *, long));
957extern NODE *do_lshift P((NODE *tree));
958extern NODE *do_rshift P((NODE *tree));
959extern NODE *do_and P((NODE *tree));
960extern NODE *do_or P((NODE *tree));
961extern NODE *do_xor P((NODE *tree));
962extern NODE *do_compl P((NODE *tree));
963extern NODE *do_strtonum P((NODE *tree));
964extern AWKNUM nondec2awknum P((char *str, size_t len));
965extern NODE *do_dcgettext P((NODE *tree));
966extern NODE *do_dcngettext P((NODE *tree));
967extern NODE *do_bindtextdomain P((NODE *tree));
968#ifdef MBS_SUPPORT
969extern int strncasecmpmbs P((const char *, mbstate_t, const char *,
970			     mbstate_t, size_t));
971#endif
972/* eval.c */
973extern int interpret P((NODE *volatile tree));
974extern NODE *r_tree_eval P((NODE *tree, int iscond));
975extern int cmp_nodes P((NODE *t1, NODE *t2));
976extern NODE **r_get_lhs P((NODE *ptr, Func_ptr *assign, int reference));
977extern void set_IGNORECASE P((void));
978extern void set_OFS P((void));
979extern void set_ORS P((void));
980extern void set_OFMT P((void));
981extern void set_CONVFMT P((void));
982extern void set_BINMODE P((void));
983extern void set_LINT P((void));
984extern void set_TEXTDOMAIN P((void));
985extern void update_ERRNO P((void));
986extern const char *redflags2str P((int));
987extern const char *flags2str P((int));
988extern const char *genflags2str P((int flagval, const struct flagtab *tab));
989extern const char *nodetype2str P((NODETYPE type));
990extern NODE *assign_val P((NODE **lhs_p, NODE *rhs));
991#ifdef PROFILING
992extern void dump_fcall_stack P((FILE *fp));
993#endif
994/* ext.c */
995NODE *do_ext P((NODE *));
996#ifdef DYNAMIC
997void make_builtin P((char *, NODE *(*)(NODE *), int));
998NODE *get_argument P((NODE *, int));
999void set_value P((NODE *));
1000#endif
1001/* field.c */
1002extern void init_fields P((void));
1003extern void set_record P((const char *buf, int cnt));
1004extern void reset_record P((void));
1005extern void set_NF P((void));
1006extern NODE **get_field P((long num, Func_ptr *assign));
1007extern NODE *do_split P((NODE *tree));
1008extern void set_FS P((void));
1009extern void set_RS P((void));
1010extern void set_FIELDWIDTHS P((void));
1011extern int using_fieldwidths P((void));
1012/* gawkmisc.c */
1013extern char *gawk_name P((const char *filespec));
1014extern void os_arg_fixup P((int *argcp, char ***argvp));
1015extern int os_devopen P((const char *name, int flag));
1016extern void os_close_on_exec P((int fd, const char *name, const char *what,
1017				const char *dir));
1018extern int os_isdir P((int fd));
1019extern int os_is_setuid P((void));
1020extern int os_setbinmode P((int fd, int mode));
1021extern void os_restore_mode P((int fd));
1022extern size_t optimal_bufsize P((int fd, struct stat *sbuf));
1023extern int ispath P((const char *file));
1024extern int isdirpunct P((int c));
1025#if defined(_MSC_VER) && !defined(_WIN32)
1026extern char *memcpy_ulong P((char *dest, const char *src, unsigned long l));
1027extern void *memset_ulong P((void *dest, int val, unsigned long l));
1028#define memcpy memcpy_ulong
1029#define memset memset_ulong
1030#endif
1031/* io.c */
1032extern void set_FNR P((void));
1033extern void set_NR P((void));
1034extern void do_input P((void));
1035extern struct redirect *redirect P((NODE *tree, int *errflg));
1036extern NODE *do_close P((NODE *tree));
1037extern int flush_io P((void));
1038extern int close_io P((void));
1039extern int devopen P((const char *name, const char *mode));
1040extern int pathopen P((const char *file));
1041extern NODE *do_getline P((NODE *tree));
1042extern void do_nextfile P((void)) ATTRIBUTE_NORETURN;
1043extern struct redirect *getredirect P((const char *str, int len));
1044/* main.c */
1045extern int main P((int argc, char **argv));
1046extern NODE *load_environ P((void));
1047extern NODE *load_procinfo P((void));
1048extern int arg_assign P((char *arg, int initing));
1049/* msg.c */
1050extern void err P((const char *s, const char *emsg, va_list argp)) ATTRIBUTE_PRINTF(2, 0);
1051#if _MSC_VER == 510
1052extern void msg P((va_list va_alist, ...));
1053extern void error P((va_list va_alist, ...));
1054extern void warning P((va_list va_alist, ...));
1055extern void set_loc P((const char *file, int line));
1056extern void r_fatal P((va_list va_alist, ...));
1057extern void (*lintfunc) P((va_list va_alist, ...));
1058#else
1059#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
1060extern void msg (const char *mesg, ...) ATTRIBUTE_PRINTF_1;
1061extern void error (const char *mesg, ...) ATTRIBUTE_PRINTF_1;
1062extern void warning (const char *mesg, ...) ATTRIBUTE_PRINTF_1;
1063extern void set_loc (const char *file, int line);
1064extern void r_fatal (const char *mesg, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
1065ATTRIBUTE_EXPORTED
1066#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)
1067extern void (*lintfunc) (const char *mesg, ...) ATTRIBUTE_PRINTF_1;
1068#else
1069extern void (*lintfunc) (const char *mesg, ...);
1070#endif
1071#else
1072extern void msg ();
1073extern void error ();
1074extern void warning ();
1075extern void set_loc ();
1076extern void r_fatal ();
1077extern void (*lintfunc) ();
1078#endif
1079#endif
1080/* profile.c */
1081extern void init_profiling P((int *flag, const char *def_file));
1082extern void init_profiling_signals P((void));
1083extern void set_prof_file P((const char *filename));
1084extern void dump_prog P((NODE *begin, NODE *prog, NODE *end));
1085extern void pp_func P((const char *name, size_t namelen, NODE *f));
1086extern void pp_string_fp P((FILE *fp, const char *str, size_t namelen,
1087			int delim, int breaklines));
1088/* node.c */
1089extern AWKNUM r_force_number P((NODE *n));
1090extern NODE *format_val P((const char *format, int index, NODE *s));
1091extern NODE *r_force_string P((NODE *s));
1092extern NODE *r_dupnode P((NODE *n));
1093extern NODE *copynode P((NODE *n));
1094extern NODE *mk_number P((AWKNUM x, unsigned int flags));
1095extern NODE *make_str_node P((char *s, unsigned long len, int scan ));
1096extern NODE *tmp_string P((char *s, size_t len ));
1097extern NODE *more_nodes P((void));
1098#ifdef MEMDEBUG
1099extern void freenode P((NODE *it));
1100#endif
1101extern void unref P((NODE *tmp));
1102extern int parse_escape P((const char **string_ptr));
1103/* re.c */
1104extern Regexp *make_regexp P((const char *s, size_t len, int ignorecase));
1105extern int research P((Regexp *rp, const char *str, int start,
1106		       size_t len, int need_start));
1107extern void refree P((Regexp *rp));
1108extern void reg_error P((const char *s));
1109extern Regexp *re_update P((NODE *t));
1110extern void resyntax P((int syntax));
1111extern void resetup P((void));
1112extern int reisstring P((const char *text, size_t len, Regexp *re, const char *buf));
1113extern int remaybelong P((const char *text, size_t len));
1114
1115/* strncasecmp.c */
1116#ifndef BROKEN_STRNCASECMP
1117extern int strcasecmp P((const char *s1, const char *s2));
1118extern int strncasecmp P((const char *s1, const char *s2, register size_t n));
1119#endif
1120
1121#if defined(atarist)
1122#if defined(PIPES_SIMULATED)
1123/* unsupported/atari/tmpnam.c */
1124extern char *tmpnam P((char *buf));
1125extern char *tempnam P((const char *path, const char *base));
1126#else
1127#include <wait.h>
1128#endif
1129#include <fcntl.h>
1130#define INVALID_HANDLE  (__SMALLEST_VALID_HANDLE - 1)
1131#else
1132#define INVALID_HANDLE (-1)
1133#endif /* atarist */
1134
1135#ifdef HAVE_SYS_WAIT_H
1136#include <sys/wait.h>
1137#endif
1138#ifndef WEXITSTATUS
1139#define WEXITSTATUS(stat_val) ((((unsigned) (stat_val)) >> 8) & 0xFF)
1140#endif
1141
1142#ifndef STATIC
1143#define STATIC static
1144#endif
1145