/* $Header: arg.h,v 3.0.1.8 90/11/10 01:04:36 lwall Locked $
 *
 *    Copyright (c) 1989, Larry Wall
 *
 *    You may distribute under the terms of the GNU General Public License
 *    as specified in the README file that comes with the perl 3.0 kit.
 *
 * $Log:	arg.h,v $
 * Revision 3.0.1.8  90/11/10  01:04:36  lwall
 * patch38: added alarm function
 * patch38: socket, recv, select, socketpair, setsockopt didn't eval all args
 * 
 * Revision 3.0.1.7  90/10/15  14:53:59  lwall
 * patch29: added SysV IPC
 * patch29: added waitpid
 * patch29: added cmp and <=>
 * patch29: added caller
 * patch29: added scalar
 * patch29: added sysread and syswrite
 * patch29: added -M, -A and -C
 * patch29: index and substr now have optional 3rd args
 * patch29: you can now read into the middle string
 * patch29: various portability fixes
 * 
 * Revision 3.0.1.6  90/08/09  02:25:14  lwall
 * patch19: added require operator
 * patch19: added truncate operator
 * 
 * Revision 3.0.1.5  90/03/27  15:29:41  lwall
 * patch16: MSDOS support
 * 
 * Revision 3.0.1.4  90/03/12  16:18:21  lwall
 * patch13: added list slice operator (LIST)[LIST]
 * patch13: added splice operator: @oldelems = splice(@array,$offset,$len,LIST)
 * 
 * Revision 3.0.1.3  90/02/28  16:21:55  lwall
 * patch9: added pipe function
 * 
 * Revision 3.0.1.2  89/12/21  19:13:14  lwall
 * patch7: send() didn't allow a TO argument
 * 
 * Revision 3.0.1.1  89/10/26  23:02:35  lwall
 * patch1: reverse didn't work
 * 
 * Revision 3.0  89/10/18  15:08:27  lwall
 * 3.0 baseline
 * 
 */

#define O_NULL 0
#define O_ITEM 1
#define O_ITEM2 2
#define O_ITEM3 3
#define O_CONCAT 4
#define O_MATCH 5
#define O_NMATCH 6
#define O_SUBST 7
#define O_NSUBST 8
#define O_ASSIGN 9
#define O_MULTIPLY 10
#define O_DIVIDE 11
#define O_MODULO 12
#define O_ADD 13
#define O_SUBTRACT 14
#define O_LEFT_SHIFT 15
#define O_RIGHT_SHIFT 16
#define O_LT 17
#define O_GT 18
#define O_LE 19
#define O_GE 20
#define O_EQ 21
#define O_NE 22
#define O_BIT_AND 23
#define O_XOR 24
#define O_BIT_OR 25
#define O_AND 26
#define O_OR 27
#define O_COND_EXPR 28
#define O_COMMA 29
#define O_NEGATE 30
#define O_NOT 31
#define O_COMPLEMENT 32
#define O_WRITE 33
#define O_OPEN 34
#define O_TRANS 35
#define O_NTRANS 36
#define O_CLOSE 37
#define O_ARRAY 38
#define O_HASH 39
#define O_LARRAY 40
#define O_LHASH 41
#define O_PUSH 42
#define O_POP 43
#define O_SHIFT 44
#define O_SPLIT 45
#define O_LENGTH 46
#define O_SPRINTF 47
#define O_SUBSTR 48
#define O_JOIN 49
#define O_SLT 50
#define O_SGT 51
#define O_SLE 52
#define O_SGE 53
#define O_SEQ 54
#define O_SNE 55
#define O_SUBR 56
#define O_PRINT 57
#define O_CHDIR 58
#define O_DIE 59
#define O_EXIT 60
#define O_RESET 61
#define O_LIST 62
#define O_SELECT 63
#define O_EOF 64
#define O_TELL 65
#define O_SEEK 66
#define O_LAST 67
#define O_NEXT 68
#define O_REDO 69
#define O_GOTO 70
#define O_INDEX 71
#define O_TIME 72
#define O_LOCALTIME 73
#define O_GMTIME 74
#define O_STAT 75
#define O_CRYPT 76
#define O_EXP 77
#define O_LOG 78
#define O_SQRT 79
#define O_INT 80
#define O_PRTF 81
#define O_ORD 82
#define O_SLEEP 83
#define O_FLIP 84
#define O_FLOP 85
#define O_KEYS 86
#define O_VALUES 87
#define O_EACH 88
#define O_CHOP 89
#define O_EXEC_OP 90
#define O_SYSTEM 91
#define O_OCT 92
#define O_HEX 93
#define O_RENAME 94
#define O_UNLINK 95
#define O_UNSHIFT 96
#define O_REPEAT 97
#define O_EVAL 98
#define O_FTREAD 99
#define O_FTWRITE 100
#define O_FTLOCK 101
#define O_FTPREAD 102
#define O_FTPWRITE 103
#define O_FTIS 104
#define O_FTZERO 105
#define O_FTSIZE 106
#define O_FTFILE 107
#define O_FTDIR 108
#define O_FTTTY 109
#define O_DOFILE 110
#define O_FTTEXT 111
#define O_FTBINARY 112
#define O_SORT 113
#define O_DELETE 114
#define O_STUDY 115
#define O_ATAN2 116
#define O_SIN 117
#define O_COS 118
#define O_RAND 119
#define O_SRAND 120
#define O_POW 121
#define O_RETURN 122
#define O_GETC 123
#define O_MKDIR 124
#define O_RMDIR 125
#define O_RINDEX 126
#define O_PACK 127
#define O_UNPACK 128
#define O_READ 129
#define O_WARN 130
#define O_DBMOPEN 131
#define O_DBMCLOSE 132
#define O_ASLICE 133
#define O_HSLICE 134
#define O_LASLICE 135
#define O_LHSLICE 136
#define O_F_OR_R 137
#define O_RANGE 138
#define O_RCAT 139
#define O_AASSIGN 140
#define O_SASSIGN 141
#define O_REVERSE 142
#define O_ADDROF 143
#define O_DBSUBR 144
#define O_DEFINED 145
#define O_UNDEF 146
#define O_AELEM 147
#define O_HELEM 148
#define O_LAELEM 149
#define O_LHELEM 150
#define O_LOCAL 151
#define O_VEC 152
#define O_GREP 153
#define O_OPENDIR 154
#define O_READDIR 155
#define O_TELLDIR 156
#define O_SEEKDIR 157
#define O_REWINDDIR 158
#define O_CLOSEDIR 159
#define O_SYSCALL 160
#define O_LSLICE 161
#define O_SPLICE 162
#define O_REQUIRE 163
#define O_TRUNCATE 164
#define O_NCMP 165
#define O_SCMP 166
#define O_CALLER 167
#define O_SCALAR 168
#define O_FTTIME 169
#define O_KILL 170
#define MAXO 171

#ifndef DOINIT
extern char *opname[];
#else
char *opname[] = {
    "NULL",
    "ITEM",
    "ITEM2",
    "ITEM3",
    "CONCAT",
    "MATCH",
    "NMATCH",
    "SUBST",
    "NSUBST",
    "ASSIGN",
    "MULTIPLY",
    "DIVIDE",
    "MODULO",
    "ADD",
    "SUBTRACT",
    "LEFT_SHIFT",
    "RIGHT_SHIFT",
    "LT",
    "GT",
    "LE",
    "GE",
    "EQ",
    "NE",
    "BIT_AND",
    "XOR",
    "BIT_OR",
    "AND",
    "OR",
    "COND_EXPR",
    "COMMA",
    "NEGATE",
    "NOT",
    "COMPLEMENT",
    "WRITE",
    "OPEN",
    "TRANS",
    "NTRANS",
    "CLOSE",
    "ARRAY",
    "HASH",
    "LARRAY",
    "LHASH",
    "PUSH",
    "POP",
    "SHIFT",
    "SPLIT",
    "LENGTH",
    "SPRINTF",
    "SUBSTR",
    "JOIN",
    "SLT",
    "SGT",
    "SLE",
    "SGE",
    "SEQ",
    "SNE",
    "SUBR",
    "PRINT",
    "CHDIR",
    "DIE",
    "EXIT",
    "RESET",
    "LIST",
    "SELECT",
    "EOF",
    "TELL",
    "SEEK",
    "LAST",
    "NEXT",
    "REDO",
    "GOTO",/* shudder */
    "INDEX",
    "TIME",
    "LOCALTIME",
    "GMTIME",
    "STAT",
    "CRYPT",
    "EXP",
    "LOG",
    "SQRT",
    "INT",
    "PRINTF",
    "ORD",
    "SLEEP",
    "FLIP",
    "FLOP",
    "KEYS",
    "VALUES",
    "EACH",
    "CHOP",
    "EXEC",
    "SYSTEM",
    "OCT",
    "HEX",
    "RENAME",
    "UNLINK",
    "UNSHIFT",
    "REPEAT",
    "EVAL",
    "FTREAD",
    "FTWRITE",
    "FTLOCK",
    "FTPREAD",
    "FTPWRITE",
    "FTIS",
    "FTZERO",
    "FTSIZE",
    "FTFILE",
    "FTDIR",
    "FTTTY",
    "DOFILE",
    "FTTEXT",
    "FTBINARY",
    "SORT",
    "DELETE",
    "STUDY",
    "ATAN2",
    "SIN",
    "COS",
    "RAND",
    "SRAND",
    "POW",
    "RETURN",
    "GETC",
    "MKDIR",
    "RMDIR",
    "RINDEX",
    "PACK",
    "UNPACK",
    "READ",
    "WARN",
    "DBMOPEN",
    "DBMCLOSE",
    "ASLICE",
    "HSLICE",
    "LASLICE",
    "LHSLICE",
    "FLIP_OR_RANGE",
    "RANGE",
    "RCAT",
    "AASSIGN",
    "SASSIGN",
    "REVERSE",
    "ADDRESS_OF",
    "DBSUBR",
    "DEFINED",
    "UNDEF",
    "AELEM",
    "HELEM",
    "LAELEM",
    "LHELEM",
    "LOCAL",
    "VEC",
    "GREP",
    "OPENDIR",
    "READDIR",
    "TELLDIR",
    "SEEKDIR",
    "REWINDDIR",
    "CLOSEDIR",
    "SYSCALL",
    "LSLICE",
    "SPLICE",
    "REQUIRE",
    "TRUNCATE",
    "NCMP",
    "SCMP",
    "CALLER",
    "SCALAR",
    "FTTIME",
    "KILL",
    "171"
};
#endif

#define A_NULL 0
#define A_EXPR 1
#define A_CMD 2
#define A_STAB 3
#define A_LVAL 4
#define A_SINGLE 5
#define A_DOUBLE 6
#define A_BACKTICK 7
#define A_READ 8
#define A_SPAT 9
#define A_LEXPR 10
#define A_ARYLEN 11
#define A_ARYSTAB 12
#define A_LARYLEN 13
#define A_GLOB 14
#define A_WORD 15
#define A_INDREAD 16
#define A_LARYSTAB 17
#define A_STAR 18
#define A_LSTAR 19
#define A_WANTARRAY 20

#define A_MASK 31
#define A_DONT 32		/* or this into type to suppress evaluation */

#ifndef DOINIT
extern char *argname[];
#else
char *argname[] = {
    "A_NULL",
    "EXPR",
    "CMD",
    "STAB",
    "LVAL",
    "SINGLE",
    "DOUBLE",
    "BACKTICK",
    "READ",
    "SPAT",
    "LEXPR",
    "ARYLEN",
    "ARYSTAB",
    "LARYLEN",
    "GLOB",
    "WORD",
    "INDREAD",
    "LARYSTAB",
    "STAR",
    "LSTAR",
    "WANTARRAY",
    "21"
};
#endif

#ifndef DOINIT
extern bool hoistable[];
#else
bool hoistable[] =
  {0,	/* A_NULL */
   0,	/* EXPR */
   1,	/* CMD */
   1,	/* STAB */
   0,	/* LVAL */
   1,	/* SINGLE */
   0,	/* DOUBLE */
   0,	/* BACKTICK */
   0,	/* READ */
   0,	/* SPAT */
   0,	/* LEXPR */
   1,	/* ARYLEN */
   1,	/* ARYSTAB */
   0,	/* LARYLEN */
   0,	/* GLOB */
   1,	/* WORD */
   0,	/* INDREAD */
   0,	/* LARYSTAB */
   1,	/* STAR */
   1,	/* LSTAR */
   1,	/* WANTARRAY */
   0,	/* 21 */
};
#endif

union argptr {
    ARG		*arg_arg;
    char	*arg_cval;
    STAB	*arg_stab;
    SPAT	*arg_spat;
    CMD		*arg_cmd;
    STR		*arg_str;
    HASH	*arg_hash;
};

struct arg {
    union argptr arg_ptr;
    short	arg_len;
    unsigned short arg_type;
    unsigned short arg_flags;
};

#define AF_ARYOK 1		/* op can handle multiple values here */
#define AF_POST 2		/* post *crement this item */
#define AF_PRE 4		/* pre *crement this item */
#define AF_UP 8			/* increment rather than decrement */
#define AF_COMMON 16		/* left and right have symbols in common */
#define AF_UNUSED 32		/*  */
#define AF_LISTISH 64		/* turn into list if important */
#define AF_LOCAL 128		/* list of local variables */

/*
 * Most of the ARG pointers are used as pointers to arrays of ARG.  When
 * so used, the 0th element is special, and represents the operator to
 * use on the list of arguments following.  The arg_len in the 0th element
 * gives the maximum argument number, and the arg_str is used to store
 * the return value in a more-or-less static location.  Sorry it's not
 * re-entrant (yet), but it sure makes it efficient.  The arg_type of the
 * 0th element is an operator (O_*) rather than an argument type (A_*).
 */

#define Nullarg Null(ARG*)

#ifndef DOINIT
EXT unsigned short opargs[MAXO+1];
#else
#define A(e1,e2,e3)        (e1+(e2<<2)+(e3<<4))
#define A5(e1,e2,e3,e4,e5) (e1+(e2<<2)+(e3<<4)+(e4<<6)+(e5<<8))
unsigned short opargs[MAXO+1] = {
	A(0,0,0),	/* NULL */
	A(1,0,0),	/* ITEM */
	A(0,0,0),	/* ITEM2 */
	A(0,0,0),	/* ITEM3 */
	A(1,1,0),	/* CONCAT */
	A(1,0,0),	/* MATCH */
	A(1,0,0),	/* NMATCH */
	A(1,0,0),	/* SUBST */
	A(1,0,0),	/* NSUBST */
	A(1,1,0),	/* ASSIGN */
	A(1,1,0),	/* MULTIPLY */
	A(1,1,0),	/* DIVIDE */
	A(1,1,0),	/* MODULO */
	A(1,1,0),	/* ADD */
	A(1,1,0),	/* SUBTRACT */
	A(1,1,0),	/* LEFT_SHIFT */
	A(1,1,0),	/* RIGHT_SHIFT */
	A(1,1,0),	/* LT */
	A(1,1,0),	/* GT */
	A(1,1,0),	/* LE */
	A(1,1,0),	/* GE */
	A(1,1,0),	/* EQ */
	A(1,1,0),	/* NE */
	A(1,1,0),	/* BIT_AND */
	A(1,1,0),	/* XOR */
	A(1,1,0),	/* BIT_OR */
	A(1,0,0),	/* AND */
	A(1,0,0),	/* OR */
	A(1,0,0),	/* COND_EXPR */
	A(1,1,0),	/* COMMA */
	A(1,0,0),	/* NEGATE */
	A(1,0,0),	/* NOT */
	A(1,0,0),	/* COMPLEMENT */
	A(1,0,0),	/* WRITE */
	A(1,1,0),	/* OPEN */
	A(1,0,0),	/* TRANS */
	A(1,0,0),	/* NTRANS */
	A(1,0,0),	/* CLOSE */
	A(0,0,0),	/* ARRAY */
	A(0,0,0),	/* HASH */
	A(0,0,0),	/* LARRAY */
	A(0,0,0),	/* LHASH */
	A(0,3,0),	/* PUSH */
	A(0,0,0),	/* POP */
	A(0,0,0),	/* SHIFT */
	A(1,0,1),	/* SPLIT */
	A(1,0,0),	/* LENGTH */
	A(3,0,0),	/* SPRINTF */
	A(1,1,1),	/* SUBSTR */
	A(1,3,0),	/* JOIN */
	A(1,1,0),	/* SLT */
	A(1,1,0),	/* SGT */
	A(1,1,0),	/* SLE */
	A(1,1,0),	/* SGE */
	A(1,1,0),	/* SEQ */
	A(1,1,0),	/* SNE */
	A(0,3,0),	/* SUBR */
	A(1,3,0),	/* PRINT */
	A(1,0,0),	/* CHDIR */
	A(0,3,0),	/* DIE */
	A(1,0,0),	/* EXIT */
	A(1,0,0),	/* RESET */
	A(3,0,0),	/* LIST */
	A(1,0,0),	/* SELECT */
	A(1,0,0),	/* EOF */
	A(1,0,0),	/* TELL */
	A(1,1,1),	/* SEEK */
	A(0,0,0),	/* LAST */
	A(0,0,0),	/* NEXT */
	A(0,0,0),	/* REDO */
	A(0,0,0),	/* GOTO */
	A(1,1,1),	/* INDEX */
	A(0,0,0),	/* TIME */
	A(1,0,0),	/* LOCALTIME */
	A(1,0,0),	/* GMTIME */
	A(1,0,0),	/* STAT */
	A(1,1,0),	/* CRYPT */
	A(1,0,0),	/* EXP */
	A(1,0,0),	/* LOG */
	A(1,0,0),	/* SQRT */
	A(1,0,0),	/* INT */
	A(1,3,0),	/* PRINTF */
	A(1,0,0),	/* ORD */
	A(1,0,0),	/* SLEEP */
	A(1,0,0),	/* FLIP */
	A(0,1,0),	/* FLOP */
	A(0,0,0),	/* KEYS */
	A(0,0,0),	/* VALUES */
	A(0,0,0),	/* EACH */
	A(3,0,0),	/* CHOP */
	A(1,3,0),	/* EXEC */
	A(1,3,0),	/* SYSTEM */
	A(1,0,0),	/* OCT */
	A(1,0,0),	/* HEX */
	A(1,1,0),	/* RENAME */
	A(0,3,0),	/* UNLINK */
	A(0,3,0),	/* UNSHIFT */
	A(1,1,0),	/* REPEAT */
	A(1,0,0),	/* EVAL */
	A(1,0,0),	/* FTREAD */
	A(1,0,0),	/* FTWRITE */
	A(1,0,0),	/* FTLOCK */
	A(1,0,0),	/* FTPREAD */
	A(1,0,0),	/* FTPWRITE */
	A(1,0,0),	/* FTIS */
	A(1,0,0),	/* FTZERO */
	A(1,0,0),	/* FTSIZE */
	A(1,0,0),	/* FTFILE */
	A(1,0,0),	/* FTDIR */
	A(1,0,0),	/* FTTTY */
	A(1,0,0),	/* DOFILE */
	A(1,0,0),	/* FTTEXT */
	A(1,0,0),	/* FTBINARY */
	A(1,3,0),	/* SORT */
	A(0,1,0),	/* DELETE */
	A(1,0,0),	/* STUDY */
	A(1,1,0),	/* ATAN2 */
	A(1,0,0),	/* SIN */
	A(1,0,0),	/* COS */
	A(1,0,0),	/* RAND */
	A(1,0,0),	/* SRAND */
	A(1,1,0),	/* POW */
	A(0,3,0),	/* RETURN */
	A(1,0,0),	/* GETC */
	A(1,0,0),	/* MKDIR */
	A(1,0,0),	/* RMDIR */
	A(1,1,1),	/* RINDEX */
	A(1,3,0),	/* PACK */
	A(1,1,0),	/* UNPACK */
	A(1,1,3),	/* READ */
	A(0,3,0),	/* WARN */
	A(1,1,1),	/* DBMOPEN */
	A(1,0,0),	/* DBMCLOSE */
	A(0,3,0),	/* ASLICE */
	A(0,3,0),	/* HSLICE */
	A(0,3,0),	/* LASLICE */
	A(0,3,0),	/* LHSLICE */
	A(1,0,0),	/* F_OR_R */
	A(1,1,0),	/* RANGE */
	A(1,1,0),	/* RCAT */
	A(3,3,0),	/* AASSIGN */
	A(0,0,0),	/* SASSIGN */
	A(0,3,0),	/* REVERSE */
	A(1,0,0),	/* ADDROF */
	A(0,3,0),	/* DBSUBR */
	A(1,0,0),	/* DEFINED */
	A(1,0,0),	/* UNDEF */
	A(0,1,0),	/* AELEM */
	A(0,1,0),	/* HELEM */
	A(0,1,0),	/* LAELEM */
	A(0,1,0),	/* LHELEM */
	A(1,0,0),	/* LOCAL */
	A(1,1,1),	/* VEC */
	A(0,3,0),	/* GREP */
	A(1,1,0),	/* OPENDIR */
	A(1,0,0),	/* READDIR */
	A(1,0,0),	/* TELLDIR */
	A(1,1,0),	/* SEEKDIR */
	A(1,0,0),	/* REWINDDIR */
	A(1,0,0),	/* CLOSEDIR */
	A(1,3,0),	/* SYSCALL */
	A(0,3,3),	/* LSLICE */
	A(0,3,1),	/* SPLICE */
	A(1,0,0),	/* REQUIRE */
	A(1,1,0),	/* TRUNCATE */
	A(1,1,0),	/* NCMP */
	A(1,1,0),	/* SCMP */
	A(1,0,0),	/* CALLER */
	A(1,0,0),	/* SCALAR */
	A(1,0,0),	/* FTTIME */
	A(1,0,0),	/* KILL */
	0
};
#undef A
#undef A5
#endif

extern int do_trans PROTO((STR *, ARG *));
extern int do_split PROTO((STR *, SPAT *, int, int, int *));
extern bool do_eof PROTO((STAB *));
extern long do_tell PROTO((STAB *));
extern bool do_seek PROTO((STAB *, long, int));
extern int do_tms PROTO((STR *, int, int *));
extern int do_time PROTO((STR *, struct tm *, int, int *));
extern int do_stat PROTO((STR *, ARG *, int, int *));
extern STR *do_push PROTO((ARRAY *, int *));
extern FILE *nextargv PROTO((STAB *));
extern STR *do_fttext PROTO((ARG *, STR *));
extern int do_slice PROTO((STAB *, STR *, int, int, int, int *));
