Main Page | Class List | Directories | File List | Class Members | File Members

awk.h

Go to the documentation of this file.
00001 /*
00002  * awk.h -- Definitions for gawk. 
00003  */
00004 
00005 /* 
00006  * Copyright (C) 1986, 1988, 1989, 1991-2003 the Free Software Foundation, Inc.
00007  * 
00008  * This file is part of GAWK, the GNU implementation of the
00009  * AWK Programming Language.
00010  * 
00011  * GAWK is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  * 
00016  * GAWK is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  * 
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00024  */
00025 
00026 /* ------------------------------ Includes ------------------------------ */
00027 
00028 /*
00029  * config.h absolutely, positively, *M*U*S*T* be included before
00030  * any system headers.  Otherwise, extreme death, destruction
00031  * and loss of life results.
00032  *
00033  * Well, OK, gawk just won't work on systems using egcs and LFS.  But
00034  * that's almost as bad.
00035  */
00036 #ifdef HAVE_CONFIG_H
00037 #include <config.h>
00038 #endif
00039 
00040 #ifndef _GNU_SOURCE
00041 #define _GNU_SOURCE     1       /* enable GNU extensions */
00042 #endif /* _GNU_SOURCE */
00043 
00044 #include <stdio.h>
00045 #include <assert.h>
00046 #ifdef HAVE_LIMITS_H
00047 #include <limits.h>
00048 #endif /* HAVE_LIMITS_H */
00049 #include <ctype.h>
00050 #include <setjmp.h>
00051 
00052 #include "gettext.h"
00053 #define _(msgid)  gettext(msgid)
00054 #define N_(msgid) msgid
00055 
00056 #if ! (defined(HAVE_LIBINTL_H) && defined(ENABLE_NLS) && ENABLE_NLS > 0)
00057 #ifndef LOCALEDIR
00058 #define LOCALEDIR NULL
00059 #endif /* LOCALEDIR */
00060 #endif
00061 
00062 #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
00063 #include <stdarg.h>
00064 #else
00065 #include <varargs.h>
00066 #endif
00067 #include <signal.h>
00068 #include <time.h>
00069 #include <errno.h>
00070 #if ! defined(errno) && ! defined(MSDOS) && ! defined(OS2)
00071 extern int errno;
00072 #endif
00073 #ifdef HAVE_SIGNUM_H
00074 #include <signum.h>
00075 #endif
00076 #if defined(HAVE_MBRLEN) && defined(HAVE_MBRTOWC) && defined(HAVE_WCHAR_H) && defined(HAVE_WCTYPE_H)
00077 /* We can handle multibyte strings.  */
00078 #define MBS_SUPPORT
00079 #include <wchar.h>
00080 #include <wctype.h>
00081 #endif
00082 
00083 /* ----------------- System dependencies (with more includes) -----------*/
00084 
00085 /* This section is the messiest one in the file, not a lot that can be done */
00086 
00087 /* First, get the ctype stuff right; from Jim Meyering */
00088 #if defined(STDC_HEADERS) || (!defined(isascii) && !defined(HAVE_ISASCII))
00089 #define IN_CTYPE_DOMAIN(c) 1
00090 #else
00091 #define IN_CTYPE_DOMAIN(c) isascii((unsigned char) c)
00092 #endif
00093 
00094 #ifdef isblank
00095 #define ISBLANK(c) (IN_CTYPE_DOMAIN(c) && isblank((unsigned char) c))
00096 #else
00097 #define ISBLANK(c) ((c) == ' ' || (c) == '\t')
00098 #endif
00099 #ifdef isgraph
00100 #define ISGRAPH(c) (IN_CTYPE_DOMAIN(c) && isgraph((unsigned char) c))
00101 #else
00102 #define ISGRAPH(c) (IN_CTYPE_DOMAIN(c) && isprint((unsigned char) c) && !isspace((unsigned char) c))
00103 #endif
00104 
00105 #define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint ((unsigned char) c))
00106 #define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit ((unsigned char) c))
00107 #define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum ((unsigned char) c))
00108 #define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha ((unsigned char) c))
00109 #define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl ((unsigned char) c))
00110 #define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower ((unsigned char) c))
00111 #define ISPUNCT(c) (IN_CTYPE_DOMAIN (c) && ispunct (unsigned char) (c))
00112 #define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace ((unsigned char) c))
00113 #define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper ((unsigned char) c))
00114 #define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit ((unsigned char) c))
00115 
00116 #ifndef TOUPPER
00117 #define TOUPPER(c)      toupper((unsigned char) c)
00118 #endif
00119 #ifndef TOLOWER
00120 #define TOLOWER(c)      tolower((unsigned char) c)
00121 #endif
00122 
00123 #ifdef __STDC__
00124 #define P(s)    s
00125 #define MALLOC_ARG_T size_t
00126 #else   /* not __STDC__ */
00127 #define P(s)    ()
00128 #define MALLOC_ARG_T unsigned
00129 #define volatile
00130 #endif  /* not __STDC__ */
00131 
00132 #ifndef VMS
00133 #include <sys/types.h>
00134 #include <sys/stat.h>
00135 #else   /* VMS */
00136 #include <stddef.h>
00137 #include <stat.h>
00138 #include <file.h>       /* avoid <fcntl.h> in io.c */
00139 #endif  /* VMS */
00140 
00141 #if ! defined(S_ISREG) && defined(S_IFREG)
00142 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
00143 #endif
00144 
00145 #ifdef STDC_HEADERS
00146 #include <stdlib.h>
00147 #else   /* not STDC_HEADERS */
00148 #include "protos.h"
00149 #endif  /* not STDC_HEADERS */
00150 
00151 #ifdef HAVE_STRING_H
00152 #include <string.h>
00153 #ifdef NEED_MEMORY_H
00154 #include <memory.h>
00155 #endif  /* NEED_MEMORY_H */
00156 #else   /* not HAVE_STRING_H */
00157 #ifdef HAVE_STRINGS_H
00158 #include <strings.h>
00159 #endif  /* HAVE_STRINGS_H */
00160 #endif  /* not HAVE_STRING_H */
00161 
00162 #ifdef NeXT
00163 #if __GNUC__ < 2 || __GNUC_MINOR__ < 7
00164 #include <libc.h>
00165 #endif
00166 #undef atof
00167 #define getopt GNU_getopt
00168 #define GFMT_WORKAROUND
00169 #endif  /* NeXT */
00170 
00171 #if defined(atarist) || defined(VMS)
00172 #include <unixlib.h>
00173 #endif  /* atarist || VMS */
00174 
00175 #if ! defined(MSDOS) && ! defined(OS2) && ! defined(WIN32) && ! defined(__EMX__) && ! defined(__CYGWIN__) && ! defined(O_BINARY) /*duh*/
00176 #define O_BINARY        0
00177 #endif
00178 
00179 #if defined(TANDEM)
00180 #define variable variabl
00181 #define open(name, how, mode)   open(name, how) /* !!! ANSI C !!! */
00182 #endif
00183 
00184 #if HAVE_UNISTD_H
00185 #include <unistd.h>
00186 #endif  /* HAVE_UNISTD_H */
00187 
00188 #ifndef HAVE_VPRINTF
00189 /* if you don't have vprintf, try this and cross your fingers. */
00190 #ifdef  HAVE_DOPRNT
00191 #define vfprintf(fp,fmt,arg)    _doprnt((fmt), (arg), (fp))
00192 #else   /* not HAVE_DOPRNT */
00193 you
00194 lose
00195 #endif  /* not HAVE_DOPRNT */
00196 #endif  /* HAVE_VPRINTF */
00197 
00198 #ifndef HAVE_SETLOCALE
00199 #define setlocale(locale, val)  /* nothing */
00200 #endif /* HAVE_SETLOCALE */
00201 
00202 /* use this as lintwarn("...")
00203    this is a hack but it gives us the right semantics */
00204 #define lintwarn (*(set_loc(__FILE__, __LINE__),lintfunc))
00205 
00206 #ifdef VMS
00207 #include "vms/redirect.h"
00208 #endif  /*VMS*/
00209 
00210 #ifdef atarist
00211 #include "unsupported/atari/redirect.h"
00212 #endif
00213 
00214 #define RE_TRANSLATE_TYPE const char *
00215 #define GNU_REGEX
00216 #ifdef GNU_REGEX
00217 #include "regex.h"
00218 typedef struct Regexp {
00219         struct re_pattern_buffer pat;
00220         struct re_registers regs;
00221 } Regexp;
00222 #define RESTART(rp,s)   (rp)->regs.start[0]
00223 #define REEND(rp,s)     (rp)->regs.end[0]
00224 #define SUBPATSTART(rp,s,n)     (rp)->regs.start[n]
00225 #define SUBPATEND(rp,s,n)       (rp)->regs.end[n]
00226 #define NUMSUBPATS(rp,s)        (rp)->regs.num_regs
00227 #endif  /* GNU_REGEX */
00228 
00229 /* Stuff for losing systems. */
00230 #ifdef STRTOD_NOT_C89
00231 extern double gawk_strtod();
00232 #define strtod gawk_strtod
00233 #endif
00234 
00235 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
00236 # define __attribute__(x)
00237 #endif
00238 
00239 #ifndef ATTRIBUTE_UNUSED
00240 #define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
00241 #endif /* ATTRIBUTE_UNUSED */
00242 
00243 #ifndef ATTRIBUTE_NORETURN
00244 #define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
00245 #endif /* ATTRIBUTE_NORETURN */
00246 
00247 #ifndef ATTRIBUTE_PRINTF
00248 #define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
00249 #define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
00250 #endif /* ATTRIBUTE_PRINTF */
00251 
00252 /* We use __extension__ in some places to suppress -pedantic warnings
00253    about GCC extensions.  This feature didn't work properly before
00254    gcc 2.8.  */
00255 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
00256 #define __extension__
00257 #endif
00258 
00259 /* this is defined by Windows32 extension libraries. It must be added to
00260  * every variable which is exported (including function pointers) */
00261 #if defined(WIN32_EXTENSION) && !defined(ATTRIBUTE_EXPORTED)
00262 # define ATTRIBUTE_EXPORTED __declspec(dllimport)
00263 #else
00264 # define ATTRIBUTE_EXPORTED
00265 #endif
00266 
00267 
00268 /* ------------------ Constants, Structures, Typedefs  ------------------ */
00269 
00270 #ifndef AWKNUM
00271 #define AWKNUM  double
00272 #endif
00273 
00274 #ifndef TRUE
00275 /* a bit hackneyed, but what the heck */
00276 #define TRUE    1
00277 #define FALSE   0
00278 #endif
00279 
00280 #define LINT_INVALID    1       /* only warn about invalid */
00281 #define LINT_ALL        2       /* warn about all things */
00282 
00283 /* Figure out what '\a' really is. */
00284 #ifdef __STDC__
00285 #define BELL    '\a'            /* sure makes life easy, don't it? */
00286 #else
00287 #       if 'z' - 'a' == 25      /* ascii */
00288 #               if 'a' != 97    /* machine is dumb enough to use mark parity */
00289 #                       define BELL     '\207'
00290 #               else
00291 #                       define BELL     '\07'
00292 #               endif
00293 #       else
00294 #               define BELL     '\057'
00295 #       endif
00296 #endif
00297 
00298 typedef enum nodevals {
00299         /* illegal entry == 0 */
00300         Node_illegal,
00301 
00302         /* binary operators  lnode and rnode are the expressions to work on */
00303         Node_times,
00304         Node_quotient,
00305         Node_mod,
00306         Node_plus,
00307         Node_minus,
00308         Node_cond_pair,         /* conditional pair (see Node_line_range) */
00309         Node_subscript,
00310         Node_concat,
00311         Node_exp,
00312 
00313         /* unary operators   subnode is the expression to work on */
00314         Node_preincrement,
00315         Node_predecrement,
00316         Node_postincrement,
00317         Node_postdecrement,
00318         Node_unary_minus,
00319         Node_field_spec,
00320 
00321         /* assignments   lnode is the var to assign to, rnode is the exp */
00322         Node_assign,
00323         Node_assign_times,
00324         Node_assign_quotient,
00325         Node_assign_mod,
00326         Node_assign_plus,
00327         Node_assign_minus,
00328         Node_assign_exp,
00329 
00330         /* boolean binaries   lnode and rnode are expressions */
00331         Node_and,
00332         Node_or,
00333 
00334         /* binary relationals   compares lnode and rnode */
00335         Node_equal,
00336         Node_notequal,
00337         Node_less,
00338         Node_greater,
00339         Node_leq,
00340         Node_geq,
00341         Node_match,
00342         Node_nomatch,
00343 
00344         /* unary relationals   works on subnode */
00345         Node_not,
00346 
00347         /* program structures */
00348         Node_rule_list,         /* lnode is a rule, rnode is rest of list */
00349         Node_rule_node,         /* lnode is pattern, rnode is statement */
00350         Node_statement_list,    /* lnode is statement, rnode is more list */
00351         Node_switch_body,       /* lnode is the case list, rnode is default list */
00352         Node_case_list, /* lnode is the case, rnode is a statement list */
00353         Node_if_branches,       /* lnode is to run on true, rnode on false */
00354         Node_expression_list,   /* lnode is an exp, rnode is more list */
00355         Node_param_list,        /* lnode is a variable, rnode is more list */
00356 
00357         /* keywords */
00358         Node_K_if,              /* lnode is conditonal, rnode is if_branches */
00359         Node_K_switch,          /* lnode is switch value, rnode is body of case statements */
00360         Node_K_case,            /* lnode is case value, rnode is stuff to run */
00361         Node_K_default,         /* lnode is empty, rnode is stuff to run */
00362         Node_K_while,           /* lnode is condtional, rnode is stuff to run */
00363         Node_K_for,             /* lnode is for_struct, rnode is stuff to run */
00364         Node_K_arrayfor,        /* lnode is for_struct, rnode is stuff to run */
00365         Node_K_break,           /* no subs */
00366         Node_K_continue,        /* no subs */
00367         Node_K_print,           /* lnode is exp_list, rnode is redirect */
00368         Node_K_print_rec,       /* lnode is NULL, rnode is redirect */
00369         Node_K_printf,          /* lnode is exp_list, rnode is redirect */
00370         Node_K_next,            /* no subs */
00371         Node_K_exit,            /* subnode is return value, or NULL */
00372         Node_K_do,              /* lnode is conditional, rnode stuff to run */
00373         Node_K_return,          /* lnode is return value */
00374         Node_K_delete,          /* lnode is array, rnode is subscript */
00375         Node_K_delete_loop,     /* lnode is array, rnode is subscript */
00376         Node_K_getline,         /* lnode is opt var, rnode is redirection */
00377         Node_K_function,        /* lnode is statement list, rnode is params */
00378         Node_K_nextfile,        /* no subs */
00379 
00380         /* I/O redirection for print statements */
00381         Node_redirect_output,   /* subnode is where to redirect */
00382         Node_redirect_append,   /* subnode is where to redirect */
00383         Node_redirect_pipe,     /* subnode is where to redirect */
00384         Node_redirect_pipein,   /* subnode is where to redirect */
00385         Node_redirect_input,    /* subnode is where to redirect */
00386         Node_redirect_twoway,   /* subnode is where to redirect */
00387 
00388         /* Variables */
00389         Node_var_new,           /* newly created variable, may become an array */
00390         Node_var,               /* scalar variable, lnode is value */
00391         Node_var_array,         /* array is ptr to elements, table_size num of eles */
00392         Node_val,               /* node is a value - type in flags */
00393 
00394         /* Builtins   subnode is explist to work on, builtin is func to call */
00395         Node_builtin,
00396 
00397         /*
00398          * pattern: conditional ',' conditional ;  lnode of Node_line_range
00399          * is the two conditionals (Node_cond_pair), other word (rnode place)
00400          * is a flag indicating whether or not this range has been entered.
00401          */
00402         Node_line_range,
00403 
00404         /*
00405          * boolean test of membership in array
00406          * lnode is string-valued, expression rnode is array name 
00407          */
00408         Node_in_array,
00409 
00410         Node_func,              /* lnode is param. list, rnode is body */
00411         Node_func_call,         /* lnode is name, rnode is argument list */
00412 
00413         Node_cond_exp,          /* lnode is conditonal, rnode is if_branches */
00414         Node_regex,             /* a regexp, text, compiled, flags, etc */
00415         Node_dynregex,          /* a dynamic regexp */
00416         Node_hashnode,          /* an identifier in the symbol table */
00417         Node_ahash,             /* an array element */
00418         Node_array_ref,         /* array passed by ref as parameter */
00419 
00420         Node_BINMODE,           /* variables recognized in the grammar */
00421         Node_CONVFMT,
00422         Node_FIELDWIDTHS,
00423         Node_FNR,
00424         Node_FS,
00425         Node_IGNORECASE,
00426         Node_LINT,
00427         Node_NF,
00428         Node_NR,
00429         Node_OFMT,
00430         Node_OFS,
00431         Node_ORS,
00432         Node_RS,
00433         Node_TEXTDOMAIN,
00434         Node_final              /* sentry value, not legal */
00435 } NODETYPE;
00436 
00437 /*
00438  * NOTE - this struct is a rather kludgey -- it is packed to minimize
00439  * space usage, at the expense of cleanliness.  Alter at own risk.
00440  */
00441 typedef struct exp_node {
00442         union {
00443                 struct {
00444                         union {
00445                                 struct exp_node *lptr;
00446                                 char *param_name;
00447                                 long ll;
00448                         } l;
00449                         union {
00450                                 struct exp_node *rptr;
00451                                 struct exp_node *(*pptr) P((struct exp_node *));
00452                                 Regexp *preg;
00453                                 struct for_loop_header *hd;
00454                                 struct exp_node **av;
00455                                 int r_ent;      /* range entered */
00456                         } r;
00457                         union {
00458                                 struct exp_node *extra;
00459                                 long xl;
00460                                 char **param_list;
00461                         } x;
00462                         char *name;
00463                         short number;
00464                         unsigned long reflags;
00465 #                               define  CASE    1
00466 #                               define  CONST   2
00467 #                               define  FS_DFLT 4
00468                 } nodep;
00469                 struct {
00470                         AWKNUM fltnum;  /* this is here for optimal packing of
00471                                          * the structure on many machines
00472                                          */
00473                         char *sp;
00474                         size_t slen;
00475                         long sref;
00476                         int idx;
00477                 } val;
00478                 struct {
00479                         struct exp_node *next;
00480                         char *name;
00481                         size_t length;
00482                         struct exp_node *value;
00483                         long ref;
00484                 } hash;
00485 #define hnext   sub.hash.next
00486 #define hname   sub.hash.name
00487 #define hlength sub.hash.length
00488 #define hvalue  sub.hash.value
00489 
00490 #define ahnext          sub.hash.next
00491 #define ahname_str      sub.hash.name
00492 #define ahname_len      sub.hash.length
00493 #define ahvalue sub.hash.value
00494 #define ahname_ref      sub.hash.ref
00495         } sub;
00496         NODETYPE type;
00497         unsigned short flags;
00498 #               define  MALLOC  1       /* can be free'd */
00499 #               define  TEMP    2       /* should be free'd */
00500 #               define  PERM    4       /* can't be free'd */
00501 #               define  STRING  8       /* assigned as string */
00502 #               define  STRCUR  16      /* string value is current */
00503 #               define  NUMCUR  32      /* numeric value is current */
00504 #               define  NUMBER  64      /* assigned as number */
00505 #               define  MAYBE_NUM 128   /* user input: if NUMERIC then
00506                                          * a NUMBER */
00507 #               define  ARRAYMAXED 256  /* array is at max size */
00508 #               define  FUNC    512     /* this parameter is really a
00509                                          * function name; see awkgram.y */
00510 #               define  FIELD   1024    /* this is a field */
00511 #               define  INTLSTR 2048    /* use localized version */
00512 } NODE;
00513 
00514 #define vname sub.nodep.name
00515 #define exec_count sub.nodep.reflags
00516 
00517 #define lnode   sub.nodep.l.lptr
00518 #define nextp   sub.nodep.l.lptr
00519 #define rnode   sub.nodep.r.rptr
00520 #define source_file     sub.nodep.name
00521 #define source_line     sub.nodep.number
00522 #define param_cnt       sub.nodep.number
00523 #define param   sub.nodep.l.param_name
00524 #define parmlist        sub.nodep.x.param_list
00525 
00526 #define subnode lnode
00527 #define builtin sub.nodep.r.pptr
00528 #define callresult sub.nodep.x.extra
00529 #define funcbody sub.nodep.x.extra
00530 
00531 #define re_reg  sub.nodep.r.preg
00532 #define re_flags sub.nodep.reflags
00533 #define re_text lnode
00534 #define re_exp  sub.nodep.x.extra
00535 
00536 #define forloop rnode->sub.nodep.r.hd
00537 
00538 #define stptr   sub.val.sp
00539 #define stlen   sub.val.slen
00540 #define stref   sub.val.sref
00541 #define stfmt   sub.val.idx
00542 
00543 #define numbr   sub.val.fltnum
00544 
00545 /* Node_var: */
00546 #define var_value lnode
00547 
00548 /* Node_var_array: */
00549 #define var_array sub.nodep.r.av
00550 #define array_size sub.nodep.l.ll
00551 #define table_size sub.nodep.x.xl
00552 
00553 /* Node_array_ref: */
00554 #define orig_array sub.nodep.x.extra
00555 #define prev_array rnode
00556 
00557 #define printf_count sub.nodep.x.xl
00558 
00559 #define condpair lnode
00560 #define triggered sub.nodep.r.r_ent
00561 
00562 /* a regular for loop */
00563 typedef struct for_loop_header {
00564         NODE *init;
00565         NODE *cond;
00566         NODE *incr;
00567 } FOR_LOOP_HEADER;
00568 
00569 typedef struct iobuf {
00570         const char *name;       /* filename */
00571         int fd;                 /* file descriptor */
00572         struct stat sbuf;       /* stat buf */
00573         char *buf;              /* start data buffer */
00574         char *off;              /* start of current record in buffer */
00575         char *dataend;          /* first byte in buffer to hold new data,
00576                                    NULL if not read yet */
00577         char *end;              /* end of buffer */
00578         size_t readsize;        /* set from fstat call */
00579         size_t size;            /* buffer size */
00580         ssize_t count;          /* amount read last time */
00581         size_t scanoff;         /* where we were in the buffer when we had
00582                                    to regrow/refill */
00583         int flag;
00584 #               define  IOP_IS_TTY      1
00585 #               define  IOP_IS_INTERNAL 2
00586 #               define  IOP_NO_FREE     4
00587 #               define  IOP_NOFREE_OBJ  8
00588 #               define  IOP_AT_EOF      16
00589 #               define  IOP_CLOSED      32
00590 } IOBUF;
00591 
00592 typedef void (*Func_ptr) P((void));
00593 
00594 /* structure used to dynamically maintain a linked-list of open files/pipes */
00595 struct redirect {
00596         unsigned int flag;
00597 #               define  RED_FILE        1
00598 #               define  RED_PIPE        2
00599 #               define  RED_READ        4
00600 #               define  RED_WRITE       8
00601 #               define  RED_APPEND      16
00602 #               define  RED_NOBUF       32
00603 #               define  RED_USED        64      /* closed temporarily to reuse fd */
00604 #               define  RED_EOF         128
00605 #               define  RED_TWOWAY      256
00606 #               define  RED_PTY         512
00607 #               define  RED_SOCKET      1024
00608 #               define  RED_TCP         2048
00609         char *value;
00610         FILE *fp;
00611         FILE *ifp;      /* input fp, needed for PIPES_SIMULATED */
00612         IOBUF *iop;
00613         int pid;
00614         int status;
00615         struct redirect *prev;
00616         struct redirect *next;
00617         const char *mode;
00618 };
00619 
00620 /*
00621  * structure for our source, either a command line string or a source file.
00622  * the same structure is used to remember variable pre-assignments.
00623  */
00624 struct src {
00625        enum srctype { CMDLINE = 1, SOURCEFILE,
00626                         PRE_ASSIGN, PRE_ASSIGN_FS } stype;
00627        char *val;
00628 };
00629 
00630 /* for debugging purposes */
00631 struct flagtab {
00632         int val;
00633         const char *name;
00634 };
00635 
00636 /* longjmp return codes, must be nonzero */
00637 /* Continue means either for loop/while continue, or next input record */
00638 #define TAG_CONTINUE 1
00639 /* Break means either for/while break, or stop reading input */
00640 #define TAG_BREAK 2
00641 /* Return means return from a function call; leave value in ret_node */
00642 #define TAG_RETURN 3
00643 
00644 #ifndef LONG_MAX
00645 #define LONG_MAX ((long)(~(1L << (sizeof (long) * 8 - 1))))
00646 #endif
00647 #ifndef ULONG_MAX
00648 #define ULONG_MAX (~(unsigned long)0)
00649 #endif
00650 #ifndef LONG_MIN
00651 #define LONG_MIN ((long)(-LONG_MAX - 1L))
00652 #endif
00653 #define HUGE    LONG_MAX 
00654 
00655 /* -------------------------- External variables -------------------------- */
00656 /* gawk builtin variables */
00657 extern long NF;
00658 extern long NR;
00659 extern long FNR;
00660 extern int BINMODE;
00661 extern int IGNORECASE;
00662 extern int RS_is_null;
00663 extern char *OFS;
00664 extern int OFSlen;
00665 extern char *ORS;
00666 extern int ORSlen;
00667 extern char *OFMT;
00668 extern char *CONVFMT;
00669 ATTRIBUTE_EXPORTED extern int CONVFMTidx;
00670 extern int OFMTidx;
00671 extern char *TEXTDOMAIN;
00672 extern NODE *BINMODE_node, *CONVFMT_node, *FIELDWIDTHS_node, *FILENAME_node;
00673 extern NODE *FNR_node, *FS_node, *IGNORECASE_node, *NF_node;
00674 extern NODE *NR_node, *OFMT_node, *OFS_node, *ORS_node, *RLENGTH_node;
00675 extern NODE *RSTART_node, *RS_node, *RT_node, *SUBSEP_node, *PROCINFO_node;
00676 extern NODE *LINT_node, *ERRNO_node, *TEXTDOMAIN_node;
00677 ATTRIBUTE_EXPORTED extern NODE **stack_ptr;
00678 extern NODE *Nnull_string;
00679 extern NODE *Null_field;
00680 extern NODE **fields_arr;
00681 extern int sourceline;
00682 extern char *source;
00683 extern NODE *expression_value;
00684 
00685 #if __GNUC__ < 2
00686 # if defined(WIN32_EXTENSION)
00687 static
00688 # else
00689 extern
00690 #endif
00691 NODE *_t;       /* used as temporary in tree_eval */
00692 #endif
00693 
00694 extern NODE *nextfree;
00695 extern int field0_valid;
00696 extern int do_traditional;
00697 extern int do_posix;
00698 extern int do_intervals;
00699 extern int do_intl;
00700 extern int do_non_decimal_data;
00701 extern int do_dump_vars;
00702 extern int do_tidy_mem;
00703 extern int in_begin_rule;
00704 extern int in_end_rule;
00705 extern int whiny_users;
00706 #ifdef NO_LINT
00707 #define do_lint 0
00708 #define do_lint_old 0
00709 #else
00710 ATTRIBUTE_EXPORTED extern int do_lint;
00711 extern int do_lint_old;
00712 #endif
00713 #ifdef MBS_SUPPORT
00714 extern int gawk_mb_cur_max;
00715 #endif
00716 
00717 #if defined (HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0
00718 extern GETGROUPS_T *groupset;
00719 extern int ngroups;
00720 #endif
00721 
00722 extern const char *myname;
00723 
00724 extern char quote;
00725 extern char *defpath;
00726 extern char envsep;
00727 
00728 extern const char casetable[];  /* for case-independent regexp matching */
00729 
00730 /* ------------------------- Pseudo-functions ------------------------- */
00731 
00732 #define is_identchar(c)         (isalnum(c) || (c) == '_')
00733 #define isnondecimal(str)       (((str)[0]) == '0' && (ISDIGIT((str)[1]) \
00734                                         || (str)[1] == 'x' || (str)[1] == 'X'))
00735 
00736 #define var_uninitialized(n)    ((n)->var_value == Nnull_string)
00737 
00738 #ifdef MPROF
00739 #define getnode(n)      emalloc((n), NODE *, sizeof(NODE), "getnode"), (n)->flags = 0, (n)-exec_count = 0;
00740 #define freenode(n)     free(n)
00741 #else   /* not MPROF */
00742 #define getnode(n)      if (nextfree) n = nextfree, nextfree = nextfree->nextp;\
00743                         else n = more_nodes()
00744 #ifndef NO_PROFILING
00745 #define freenode(n)     ((n)->flags = 0,\
00746                 (n)->exec_count = 0, (n)->nextp = nextfree, nextfree = (n))
00747 #else /* not PROFILING */
00748 #define freenode(n)     ((n)->flags = 0,\
00749                 (n)->nextp = nextfree, nextfree = (n))
00750 #endif  /* not PROFILING */
00751 #endif  /* not MPROF */
00752 
00753 #ifndef GAWKDEBUG
00754 #define DUPNODE_MACRO 1
00755 /*
00756  * Speed up the path leading to r_dupnode, as well as duplicating TEMP nodes,
00757  * on expense of slowing down the access to PERM nodes (by two instructions).
00758  * This is right since PERM nodes are realtively rare.
00759  *
00760  * The code also sets MALLOC flag for PERM nodes, which should not matter.
00761  */
00762 #define DUPNODE_COMMON  (_t->flags & (TEMP|PERM)) != 0 ? \
00763                           (_t->flags &= ~TEMP, _t->flags |= MALLOC, _t) : \
00764                           r_dupnode(_t)
00765 #if __GNUC__ >= 2
00766 #define dupnode(n)      ({NODE * _t = (n); DUPNODE_COMMON;})
00767 #else
00768 #define dupnode(n)      (_t = (n), DUPNODE_COMMON)
00769 #endif
00770 #else   /* GAWKDEBUG */
00771 #define dupnode(n)      r_dupnode(n)
00772 #endif  /* GAWKDEBUG */
00773 
00774 #define get_array(t)    get_actual(t, TRUE)     /* allowed to die fatally */
00775 #define get_param(t)    get_actual(t, FALSE)    /* not allowed */
00776 
00777 #ifdef MEMDEBUG
00778 #undef freenode
00779 #define get_lhs(p, a, r)        r_get_lhs((p), (a), (r))
00780 #define m_tree_eval(t, iscond)  r_tree_eval(t, iscond)
00781 #else
00782 #define get_lhs(p, a, r) ((p)->type == Node_var && \
00783                           ! var_uninitialized(p) ? \
00784                           (&(p)->var_value) : \
00785                          r_get_lhs((p), (a), (r)))
00786 #define TREE_EVAL_MACRO 1
00787 #if __GNUC__ >= 2
00788 #define m_tree_eval(t, iscond) __extension__ \
00789                         ({NODE * _t = (t);                 \
00790                            if (_t == NULL)                 \
00791                                _t = Nnull_string;          \
00792                            else {                          \
00793                                switch(_t->type) {          \
00794                                case Node_val:              \
00795                                    if (_t->flags&INTLSTR)  \
00796                                         _t = r_force_string(_t); \
00797                                    break;                  \
00798                                case Node_var:              \
00799                                    if (! var_uninitialized(_t)) { \
00800                                        _t = _t->var_value;                 \
00801                                        break;                              \
00802                                    }                                       \
00803                                    /*FALLTHROUGH*/                         \
00804                                default:                    \
00805                                    _t = r_tree_eval(_t, iscond);\
00806                                    break;                  \
00807                                }                           \
00808                            }                               \
00809                            _t;})
00810 #else
00811 #define m_tree_eval(t, iscond)  (_t = (t), _t == NULL ? Nnull_string : \
00812                         (_t->type == Node_param_list ? \
00813                           r_tree_eval(_t, iscond) : \
00814                         ((_t->type == Node_val && (_t->flags&INTLSTR)) ? \
00815                                 r_force_string(_t) : \
00816                         (_t->type == Node_val ? _t : \
00817                         (_t->type == Node_var && \
00818                          ! var_uninitialized(_t) ? _t->var_value : \
00819                          r_tree_eval(_t, iscond))))))
00820 #endif /* __GNUC__ */
00821 #endif /* not MEMDEBUG */
00822 #define tree_eval(t)    m_tree_eval(t, FALSE)
00823 
00824 #define make_number(x)  mk_number((x), (unsigned int)(MALLOC|NUMCUR|NUMBER))
00825 #define tmp_number(x)   mk_number((x), (unsigned int)(MALLOC|TEMP|NUMCUR|NUMBER))
00826 
00827 #define free_temp(n)    do { NODE *_n = (n); if (_n->flags&TEMP) unref(_n);} \
00828                                 while (FALSE)
00829 
00830 #define make_string(s, l)       make_str_node((s), (size_t) (l), 0)
00831 #define         SCAN                    1
00832 #define         ALREADY_MALLOCED        2
00833 
00834 #define cant_happen()   r_fatal("internal error line %d, file: %s", \
00835                                 __LINE__, __FILE__)
00836 
00837 #ifdef HAVE_STRINGIZE
00838 #define emalloc(var,ty,x,str)   (void)((var=(ty)malloc((MALLOC_ARG_T)(x))) ||\
00839                                  (fatal(_("%s: %s: can't allocate %ld bytes of memory (%s)"),\
00840                                         (str), #var, (long) (x), strerror(errno)),0))
00841 #define erealloc(var,ty,x,str)  (void)((var=(ty)realloc((char *)var,\
00842                                                   (MALLOC_ARG_T)(x))) ||\
00843                                  (fatal(_("%s: %s: can't allocate %ld bytes of memory (%s)"),\
00844                                         (str), #var, (long) (x), strerror(errno)),0))
00845 #else /* HAVE_STRINGIZE */
00846 #define emalloc(var,ty,x,str)   (void)((var=(ty)malloc((MALLOC_ARG_T)(x))) ||\
00847                                  (fatal(_("%s: %s: can't allocate %ld bytes of memory (%s)"),\
00848                                         (str), "var", (long) (x), strerror(errno)),0))
00849 #define erealloc(var,ty,x,str)  (void)((var=(ty)realloc((char *)var,\
00850                                                   (MALLOC_ARG_T)(x))) ||\
00851                                  (fatal(_("%s: %s: can't allocate %ld bytes of memory (%s)"),\
00852                                         (str), "var", (long) (x), strerror(errno)),0))
00853 #endif /* HAVE_STRINGIZE */
00854 
00855 #ifdef GAWKDEBUG
00856 #define force_number    r_force_number
00857 #define force_string    r_force_string
00858 #else /* not GAWKDEBUG */
00859 #ifdef lint
00860 extern AWKNUM force_number();
00861 #endif
00862 #if __GNUC__ >= 2
00863 #define force_number(n) __extension__ ({NODE *_tn = (n);\
00864                         (_tn->flags & NUMCUR) ?_tn->numbr : r_force_number(_tn);})
00865 #define force_string(s) __extension__ ({NODE *_ts = (s);\
00866                           ((_ts->flags & INTLSTR) ? \
00867                                 r_force_string(_ts) : \
00868                           ((_ts->flags & STRCUR) && \
00869                            (_ts->stfmt == -1 || _ts->stfmt == CONVFMTidx)) ?\
00870                           _ts : r_force_string(_ts));})
00871 #else
00872 #ifdef MSDOS
00873 extern double _msc51bug;
00874 #define force_number(n) (_msc51bug=(_t = (n),\
00875                           (_t->flags & NUMCUR) ? _t->numbr : r_force_number(_t)))
00876 #else /* not MSDOS */
00877 #define force_number(n) (_t = (n),\
00878                          (_t->flags & NUMCUR) ? _t->numbr : r_force_number(_t))
00879 #endif /* not MSDOS */
00880 #define force_string(s) (_t = (s),(_t->flags & INTLSTR) ? \
00881                                         r_force_string(_t) :\
00882                                 ((_t->flags & STRCUR) && \
00883                                  (_t->stfmt == -1 || \
00884                                  _t->stfmt == CONVFMTidx))? \
00885                          _t : r_force_string(_t))
00886 
00887 #endif /* not __GNUC__ */
00888 #endif /* not GAWKDEBUG */
00889 
00890 #define STREQ(a,b)      (*(a) == *(b) && strcmp((a), (b)) == 0)
00891 #define STREQN(a,b,n)   ((n) && *(a)== *(b) && \
00892                          strncmp((a), (b), (size_t) (n)) == 0)
00893 
00894 #define fatal           set_loc(__FILE__, __LINE__), r_fatal
00895 
00896 /* ------------- Function prototypes or defs (as appropriate) ------------- */
00897 
00898 /* array.c */
00899 extern NODE *get_actual P((NODE *symbol, int canfatal));
00900 extern char *array_vname P((const NODE *symbol));
00901 extern void array_init P((void));
00902 extern NODE *concat_exp P((NODE *tree));
00903 extern void assoc_clear P((NODE *symbol));
00904 extern NODE *in_array P((NODE *symbol, NODE *subs));
00905 extern NODE **assoc_lookup P((NODE *symbol, NODE *subs, int reference));
00906 extern void do_delete P((NODE *symbol, NODE *tree));
00907 extern void do_delete_loop P((NODE *symbol, NODE *tree));
00908 extern NODE *assoc_dump P((NODE *symbol));
00909 extern NODE *do_adump P((NODE *tree));
00910 extern NODE *do_asort P((NODE *tree));
00911 extern NODE *do_asorti P((NODE *tree));
00912 extern unsigned long (*hash)P((const char *s, size_t len, unsigned long hsize));
00913 /* awkgram.c */
00914 extern char *tokexpand P((void));
00915 extern NODE *node P((NODE *left, NODETYPE op, NODE *right));
00916 extern NODE *install P((char *name, NODE *value));
00917 extern NODE *lookup P((const char *name));
00918 extern NODE *variable P((char *name, int can_free, NODETYPE type));
00919 extern int yyparse P((void));
00920 extern void dump_funcs P((void));
00921 extern void dump_vars P((const char *fname));
00922 extern void release_all_vars P((void));
00923 extern const char *getfname P((NODE *(*)(NODE *)));
00924 extern NODE *stopme P((NODE *tree));
00925 extern void shadow_funcs P((void));
00926 /* builtin.c */
00927 extern double double_to_int P((double d));
00928 extern NODE *do_exp P((NODE *tree));
00929 extern NODE *do_fflush P((NODE *tree));
00930 extern NODE *do_index P((NODE *tree));
00931 extern NODE *do_int P((NODE *tree));
00932 extern NODE *do_length P((NODE *tree));
00933 extern NODE *do_log P((NODE *tree));
00934 extern NODE *do_mktime P((NODE *tree));
00935 extern NODE *do_sprintf P((NODE *tree));
00936 extern void do_printf P((NODE *tree));
00937 extern void print_simple P((NODE *tree, FILE *fp));
00938 extern NODE *do_sqrt P((NODE *tree));
00939 extern NODE *do_substr P((NODE *tree));
00940 extern NODE *do_strftime P((NODE *tree));
00941 extern NODE *do_systime P((NODE *tree));
00942 extern NODE *do_system P((NODE *tree));
00943 extern void do_print P((NODE *tree));
00944 extern void do_print_rec P((NODE *tree));
00945 extern NODE *do_tolower P((NODE *tree));
00946 extern NODE *do_toupper P((NODE *tree));
00947 extern NODE *do_atan2 P((NODE *tree));
00948 extern NODE *do_sin P((NODE *tree));
00949 extern NODE *do_cos P((NODE *tree));
00950 extern NODE *do_rand P((NODE *tree));
00951 extern NODE *do_srand P((NODE *tree));
00952 extern NODE *do_match