diff --git a/src/ChangeLog b/src/ChangeLog index e14319deab94c66f05bba387cb81472114a43523..35d4e3c644ad5f7bab8707ef681199598287effe 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +Thu Mar 13 17:06:09 1997 Fredrik Hubinette <hubbe@cytocin.hubbe.net> + + * changed check_args() and check_all_args(), they are much more + flexible and a bit easier to use now. + Wed Mar 12 03:58:53 1997 Fredrik Hubinette <hubbe@cytocin.hubbe.net> * renamed clone() to clone_object(), threads works with linux now. diff --git a/src/interpret.c b/src/interpret.c index 937dd84105dc5caff5ffdb9b8b6d6c83ef5d1e6d..276c946f1a8d2cdb99b1d19c3dca45ee6be3b83d 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: interpret.c,v 1.35 1997/03/12 12:15:27 hubbe Exp $"); +RCSID("$Id: interpret.c,v 1.36 1997/03/14 04:37:14 hubbe Exp $"); #include "interpret.h" #include "object.h" #include "program.h" @@ -954,6 +954,11 @@ static void eval_instruction(unsigned char *pc) break; } + CASE(F_RETURN_1); + pop_n_elems(sp-fp->locals); + push_int(1); + goto do_return; + CASE(F_RETURN_0); pop_n_elems(sp-fp->locals); push_int(0); @@ -1055,6 +1060,9 @@ static void eval_instruction(unsigned char *pc) CASE(F_DIVIDE); o_divide(); break; CASE(F_MOD); o_mod(); break; + CASE(F_ADD_INT); push_int(GET_ARG()); f_add(2); break; + CASE(F_ADD_NEG_INT); push_int(-GET_ARG()); f_add(2); break; + CASE(F_PUSH_ARRAY); if(sp[-1].type!=T_ARRAY) error("Bad argument to @\n"); sp--; @@ -1137,6 +1145,15 @@ static void eval_instruction(unsigned char *pc) pop_stack(); break; + CASE(F_MARK_APPLY); + strict_apply_svalue(fp->context.prog->constants + GET_ARG(), 0); + break; + + CASE(F_MARK_APPLY_POP); + strict_apply_svalue(fp->context.prog->constants + GET_ARG(), 0); + pop_stack(); + break; + CASE(F_APPLY); strict_apply_svalue(fp->context.prog->constants + GET_ARG(), sp - *--mark_sp ); break; diff --git a/src/language.yacc b/src/language.yacc index 5502aa48d1d7b1edcd4725ba248bb212b92362d3..742996f4038688b257795f77813668d464f6bebd 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -13,7 +13,7 @@ %token F_PREFIX_CHARX256 F_PREFIX_WORDX256 F_PREFIX_24BITX256 %token F_POP_VALUE F_POP_N_ELEMS F_MARK F_MARK2 %token F_CALL_LFUN F_CALL_LFUN_AND_POP -%token F_APPLY F_APPLY_AND_POP +%token F_APPLY F_APPLY_AND_POP F_MARK_APPLY F_MARK_APPLY_POP %token F_BRANCH F_BRANCH_WHEN_ZERO F_BRANCH_WHEN_NON_ZERO %token F_BRANCH_WHEN_LT F_BRANCH_WHEN_GT @@ -43,12 +43,12 @@ %token F_INC F_DEC F_POST_INC F_POST_DEC F_INC_AND_POP F_DEC_AND_POP %token F_INC_LOCAL F_INC_LOCAL_AND_POP F_POST_INC_LOCAL %token F_DEC_LOCAL F_DEC_LOCAL_AND_POP F_POST_DEC_LOCAL -%token F_RETURN F_DUMB_RETURN F_RETURN_0 F_THROW_ZERO +%token F_RETURN F_DUMB_RETURN F_RETURN_0 F_RETURN_1 F_THROW_ZERO %token F_ASSIGN F_ASSIGN_AND_POP %token F_ASSIGN_LOCAL F_ASSIGN_LOCAL_AND_POP %token F_ASSIGN_GLOBAL F_ASSIGN_GLOBAL_AND_POP -%token F_ADD F_SUBTRACT +%token F_ADD F_SUBTRACT F_ADD_INT F_ADD_NEG_INT %token F_MULTIPLY F_DIVIDE F_MOD %token F_LT F_GT F_EQ F_GE F_LE F_NE @@ -158,7 +158,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.31 1997/03/11 22:31:21 grubba Exp $"); +RCSID("$Id: language.yacc,v 1.32 1997/03/14 04:37:15 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif diff --git a/src/lex.c b/src/lex.c index 248d9dc15f4fbb6774950bdc1abd7bf431c6a9d7..6760ba7e7037693bbe60a4f7206027785e0e1e4c 100644 --- a/src/lex.c +++ b/src/lex.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: lex.c,v 1.18 1997/03/11 03:36:41 hubbe Exp $"); +RCSID("$Id: lex.c,v 1.19 1997/03/14 04:37:16 hubbe Exp $"); #include "language.h" #include "array.h" #include "lex.h" @@ -243,6 +243,7 @@ struct keyword instr_names[]= { "range", F_RANGE }, { "return", F_RETURN }, { "return 0", F_RETURN_0 }, +{ "return 1", F_RETURN_1 }, { "sscanf", F_SSCANF, I_HASARG }, { "string", F_STRING, I_HASARG }, { "switch", F_SWITCH, I_HASARG }, @@ -277,6 +278,10 @@ struct keyword instr_names[]= { "2 locals", F_2_LOCALS, I_HASARG }, { "byte", F_BYTE, I_HASARG }, { "nop", F_NOP }, +{ "add integer", F_ADD_INT, I_HASARG }, +{ "add -integer", F_ADD_NEG_INT, I_HASARG }, +{ "mark & call", F_MARK_APPLY, I_HASARG }, +{ "mark, call & pop", F_MARK_APPLY_POP, I_HASARG }, }; struct instr instrs[F_MAX_INSTR - F_OFFSET]; diff --git a/src/mapping.c b/src/mapping.c index 2a21191824dbee67182c8f1c456ec4041cf251fe..5e234522dcac312f2340779aea904d949947b5d3 100644 --- a/src/mapping.c +++ b/src/mapping.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: mapping.c,v 1.14 1997/03/11 23:32:28 grubba Exp $"); +RCSID("$Id: mapping.c,v 1.15 1997/03/14 04:37:16 hubbe Exp $"); #include "main.h" #include "types.h" #include "object.h" @@ -764,12 +764,19 @@ node * make_node_from_mapping(struct mapping *m) node *n; ind=mapping_indices(m); val=mapping_indices(m); - n=mkefuncallnode("mkmapping",mknode(F_ARG_LIST,make_node_from_array(ind),make_node_from_array(val))); + n=mkefuncallnode("mkmapping", + mknode(F_ARG_LIST, + make_node_from_array(ind), + make_node_from_array(val))); free_array(ind); free_array(val); return n; }else{ struct svalue s; + + if(!m->size) + return mkefuncallnode("aggregate_mapping",0); + s.type=T_MAPPING; s.subtype=0; s.u.mapping=m; diff --git a/src/module_support.c b/src/module_support.c index 5d8f0f58df8da2fd53f7a71eee252efa09d79b9a..d5d77a685bb25922ed9f529967092a958d55b741 100644 --- a/src/module_support.c +++ b/src/module_support.c @@ -4,65 +4,127 @@ #include "svalue.h" #include "stralloc.h" -/* Checks that minargs arguments are OK. - * - * Returns the number of the first bad argument, - * or 0 if all arguments were OK. +enum error_type { + ERR_NONE, + ERR_TOO_FEW, + ERR_TOO_MANY, + ERR_BAD_ARG, +}; + +struct expect_result { + enum error_type error_type; + int argno; /* Which argument was it */ + unsigned INT32 expected; /* What type was expected */ + TYPE_T got; /* What type did we actually receive */ +}; + +/* Checks that args_to_check arguments are OK. + * Returns 1 if everything worked ok, zero otherwise. + * If something went wrong, 'exepect_result' tells you what went wrong. + * Make sure to finish the argument list with a zero. */ -int va_check_args(struct svalue *s, int minargs, va_list arglist) +static int va_check_args(struct svalue *s, + int args_to_check, + struct expect_result *res, + va_list arglist) { - int argno; - - for (argno=0; argno < minargs; argno++) + res->error_type = ERR_NONE; + res->expected = 0; + + for (res->argno=0; res->argno < args_to_check; res->argno++) { - int type_mask = va_arg(arglist, unsigned INT32); + if(!(res->expected & BIT_MANY)) + { + res->expected = va_arg(arglist, unsigned int); + if(!res->expected) + { + res->error_type = ERR_TOO_MANY; + return 0; + } + } - if (!((1UL << s[argno].type) & type_mask)) + if (!((1UL << s[res->argno].type) & res->expected)) { - return(argno+1); + res->got=s[res->argno].type; + res->error_type = ERR_BAD_ARG; + return 0; } } - return(0); + if(!(res->expected & BIT_MANY)) + { + res->expected = va_arg(arglist, unsigned int); + } + + if(!res->expected || (res->expected & BIT_VOID)) return 1; + res->error_type = ERR_TOO_FEW; + return 0; } /* Returns the number of the first bad argument, + * -X if there were too few arguments * or 0 if all arguments were OK. */ -int check_args(int args, int minargs, ...) +int check_args(int args, ...) { va_list arglist; - int argno; + struct expect_result tmp; - if (args < minargs) { - return(args+1); - } - - va_start(arglist, minargs); - argno = va_check_args(sp - args, minargs, arglist); + va_start(arglist, args); + va_check_args(sp - args, args, &tmp, arglist); va_end(arglist); - return(argno); + if(tmp.error_type == ERR_NONE) return 0; + return tmp.argno+1; } /* This function generates errors if any of the minargs first arguments * is not OK. */ -void check_all_args(const char *fnname, int args, int minargs, ... ) +void check_all_args(const char *fnname, int args, ... ) { va_list arglist; + struct expect_result tmp; int argno; - if (args < minargs) { - error("Too few arguments to %s()\n", fnname); - } - - va_start(arglist, minargs); - argno = va_check_args(sp - args, minargs, arglist); + va_start(arglist, args); + va_check_args(sp - args, args, &tmp, arglist); va_end(arglist); - if (argno) { - error("Bad argument %d to %s()\n", argno, fnname); + switch(tmp.error_type) + { + case ERR_NONE: return; + case ERR_TOO_FEW: + error("Too few arguments to %s()\n",fnname); + case ERR_TOO_MANY: + error("Too many argumens to %s()\n",fnname); + + case ERR_BAD_ARG: + { + char buf[1000]; + int e,d; + buf[0]=0; + for(e=0;e<16;e++) + { + if(tmp.expected & (1<<e)) + { + if(buf[0]) + { + if(tmp.expected & 0xffff & (0xffff << e)) + strcat(buf,", "); + else + strcat(buf," or "); + } + strcat(buf, get_name_of_type(e)); + } + } + + error("Bad argument %d to %s(), (expecting %s, got %s)\n", + tmp.argno+1, + fnname, + buf, + get_name_of_type(tmp.got)); + } } } diff --git a/src/module_support.h b/src/module_support.h index 67636a372a87020c53da524901177048cf255c83..f2dd99c4a62563c027911c4c0e3462bcda68bbed 100644 --- a/src/module_support.h +++ b/src/module_support.h @@ -8,9 +8,10 @@ #include <stdarg.h> /* Prototypes begin here */ -int va_check_args(struct svalue *s, int minargs, va_list arglist); -int check_args(int args, int minargs, ...); -void check_all_args(const char *fnname, int args, int minargs, ... ); +enum error_type; +struct expect_result; +int check_args(int args, ...); +void check_all_args(const char *fnname, int args, ... ); int va_get_args(struct svalue *s, INT32 num_args, char *fmt, diff --git a/src/modules/Yp/yp.c b/src/modules/Yp/yp.c index 693b5e619f5a4703792deac11b43b96ce4167386..cb47767b72727fed9ecbdacd29e529186eedaa90 100644 --- a/src/modules/Yp/yp.c +++ b/src/modules/Yp/yp.c @@ -65,7 +65,7 @@ static void f_create(INT32 args) f_default_yp_domain(0); args = 1; } - check_all_args("yp->create", args, 1, BIT_STRING); + check_all_args("yp->create", args, BIT_STRING,0); if(this->domain) { @@ -84,7 +84,7 @@ static void f_all(INT32 args) int retlen, retkeylen; char *map; struct mapping *res_map; - check_all_args("yp->all", args, 1, BIT_STRING); + check_all_args("yp->all", args, BIT_STRING, 0); map = sp[-1].u.string->str; res_map = allocate_mapping( (this->last_size?this->last_size+2:40) ); @@ -120,7 +120,7 @@ void f_map(INT32 args) struct svalue *f = &sp[-1]; - check_all_args("map", args, 2, BIT_STRING, BIT_FUNCTION|BIT_ARRAY ); + check_all_args("map", args, BIT_STRING, BIT_FUNCTION|BIT_ARRAY, 0 ); map = sp[-2].u.string->str; @@ -143,7 +143,7 @@ static void f_order(INT32 args) { int err; unsigned long ret; - check_all_args("yp->order()", args, 1, BIT_STRING); + check_all_args("yp->order", args, BIT_STRING, 0); err = yp_order( this->domain, sp[-args].u.string->str, &ret); YPERROR("order", err ); @@ -157,7 +157,7 @@ static void f_match(INT32 args) char *retval; int retlen; - check_all_args("yp->match", args, 2, BIT_STRING, BIT_STRING); + check_all_args("yp->match", args, BIT_STRING, BIT_STRING, 0); err = yp_match( this->domain, sp[-args].u.string->str, sp[-args+1].u.string->str, sp[-args+1].u.string->len, diff --git a/src/modules/files/file.c b/src/modules/files/file.c index 7ea1159fea4d511f920a9900437baee5eb2d9ca2..bde0cf767327d62ba382effb54194b25faf75421 100644 --- a/src/modules/files/file.c +++ b/src/modules/files/file.c @@ -6,7 +6,7 @@ #define READ_BUFFER 8192 #include "global.h" -RCSID("$Id: file.c,v 1.29 1997/03/12 12:21:50 hubbe Exp $"); +RCSID("$Id: file.c,v 1.30 1997/03/14 04:38:54 hubbe Exp $"); #include "types.h" #include "interpret.h" #include "svalue.h" @@ -1220,7 +1220,7 @@ static void file_open_socket(INT32 args) static void file_set_keepalive(INT32 args) { int tmp, i; - check_all_args("file->set_keepalive()",args, 1, T_INT); + check_all_args("file->set_keepalive",args, T_INT,0); tmp=sp[-args].u.integer; i=setsockopt(FD,SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp)); if(i) diff --git a/src/modules/system/system.c b/src/modules/system/system.c index a2e821e2671cbc226df43398d761f0382d77d0fc..fc494825a95bc5325a13fc08c8a2e3710fbfd418 100644 --- a/src/modules/system/system.c +++ b/src/modules/system/system.c @@ -1,5 +1,5 @@ /* - * $Id: system.c,v 1.13 1997/03/05 14:52:02 grubba Exp $ + * $Id: system.c,v 1.14 1997/03/14 04:39:20 hubbe Exp $ * * System-call module for Pike * @@ -14,7 +14,7 @@ #include "system.h" #include <global.h> -RCSID("$Id: system.c,v 1.13 1997/03/05 14:52:02 grubba Exp $"); +RCSID("$Id: system.c,v 1.14 1997/03/14 04:39:20 hubbe Exp $"); #include <module_support.h> #include <las.h> #include <interpret.h> @@ -376,9 +376,9 @@ void f_chroot(INT32 args) int res; #ifdef HAVE_FCHROOT - check_all_args("chroot", args, 1, BIT_STRING|BIT_OBJECT); + check_all_args("chroot", args, BIT_STRING|BIT_OBJECT, 0); #else - check_all_args("chroot", args, 1, BIT_STRING); + check_all_args("chroot", args, BIT_STRING, 0); #endif /* HAVE_FCHROOT */ diff --git a/src/operators.c b/src/operators.c index 0e26ab803db982310f255b71676347d804d7f2b4..fef1e67c0e5282b55164fd30a30ae2e2514b96d9 100644 --- a/src/operators.c +++ b/src/operators.c @@ -5,7 +5,7 @@ \*/ #include <math.h> #include "global.h" -RCSID("$Id: operators.c,v 1.11 1997/03/11 23:32:32 grubba Exp $"); +RCSID("$Id: operators.c,v 1.12 1997/03/14 04:37:17 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "multiset.h" @@ -511,6 +511,44 @@ void o_and() } } +/* This function is used to speed up or/xor/and on + * arrays multisets and mappings. This is done by + * calling the operator for each pair of arguments + * first, then recursively doing the same on the + * results until only one value remains. + */ +static void speedup(INT32 args, void (*func)(void)) +{ + switch(sp[-args].type) + { + case T_MAPPING: + case T_ARRAY: + case T_MULTISET: + { + int e=-1; + while(args > 1) + { + struct svalue tmp; + func(); + args--; + e++; + if(e - args >= -1) + { + e=0; + }else{ + tmp=sp[e-args]; + sp[e-args]=sp[-1]; + sp[-1]=tmp; + } + } + return; + } + + default: + while(--args > 0) func(); + } +} + void f_and(INT32 args) { switch(args) @@ -523,7 +561,7 @@ void f_and(INT32 args) { CALL_OPERATOR(LFUN_AND, args); }else{ - while(--args > 0) o_and(); + speedup(args, o_and); } } } @@ -623,7 +661,7 @@ void f_or(INT32 args) { CALL_OPERATOR(LFUN_OR, args); } else { - while(--args > 0) o_or(); + speedup(args, o_or); } } } @@ -724,7 +762,7 @@ void f_xor(INT32 args) { CALL_OPERATOR(LFUN_XOR, args); } else { - while(--args > 0) o_xor(); + speedup(args, o_xor); } } } diff --git a/src/peep.in b/src/peep.in index 49481badcf9ce7e4030f8cbc0366708c2889ecec..7b48f5b1140c9de8d05f5a0e18d7cb43ce0759af 100644 --- a/src/peep.in +++ b/src/peep.in @@ -12,6 +12,8 @@ ASSIGN_GLOBAL POP_VALUE : ASSIGN_GLOBAL_AND_POP($1a) ASSIGN_LOCAL POP_VALUE : ASSIGN_LOCAL_AND_POP($1a) CALL_LFUN POP_VALUE : CALL_LFUN_AND_POP($1a) APPLY POP_VALUE : APPLY_AND_POP($1a) +MARK APPLY : MARK_APPLY($2a) +MARK_APPLY POP_VALUE : MARK_APPLY_POP($1a) NUMBER(0) : CONST0 NUMBER(1) : CONST1 NUMBER(-1) : CONST_1 @@ -22,6 +24,8 @@ CONST_1 NEGATE : CONST1 NUMBER NEGATE : NEG_NUMBER($1a) NUMBER [$1a < 0] : NEG_NUMBER (-$1a) NEG_NUMBER NEGATE : NUMBER ($1a) +NEGATE NEGATE : +COMPL COMPL : NEGATE CONST_1 ADD : COMPL NEGATE CONST1 SUBTRACT : COMPL CONST0 ASSIGN_LOCAL_AND_POP : CLEAR_LOCAL($2a) @@ -42,6 +46,7 @@ CONST0 XOR: CONST_1 XOR: COMPL EQ CONST0: NOT CONST0 RETURN: RETURN_0 +CONST1 RETURN: RETURN_1 INC POP_VALUE: INC_AND_POP POST_INC POP_VALUE: INC_AND_POP DEC POP_VALUE: DEC_AND_POP @@ -117,3 +122,28 @@ NUMBER [$1a < 0] INDEX: NEG_INT_INDEX (-$1a) NUMBER [$1a >= 0] INDEX: POS_INT_INDEX ($1a) NEG_NUMBER [$1a >= 0] INDEX: NEG_INT_INDEX ($1a) NEG_NUMBER [$1a < 0] INDEX: POS_INT_INDEX (-$1a) + +BRANCH_WHEN_ZERO BRANCH LABEL ($1a): BRANCH_WHEN_NON_ZERO($2a) LABEL($1a) +BRANCH_WHEN_NON_ZERO BRANCH LABEL ($1a): BRANCH_WHEN_ZERO($2a) LABEL($1a) + +BRANCH_WHEN_EQ BRANCH LABEL ($1a) : BRANCH_WHEN_NE($2a) LABEL($1a) +BRANCH_WHEN_NE BRANCH LABEL ($1a) : BRANCH_WHEN_EQ($2a) LABEL($1a) + +BRANCH_WHEN_LT BRANCH LABEL ($1a) : BRANCH_WHEN_GE($2a) LABEL($1a) +BRANCH_WHEN_GE BRANCH LABEL ($1a) : BRANCH_WHEN_LT($2a) LABEL($1a) + +BRANCH_WHEN_LE BRANCH LABEL ($1a) : BRANCH_WHEN_GT($2a) LABEL($1a) +BRANCH_WHEN_GT BRANCH LABEL ($1a) : BRANCH_WHEN_LE($2a) LABEL($1a) + + +CONST0 ADD: ADD_INT (0) +CONST1 ADD: ADD_INT (1) +CONST_1 ADD: ADD_NEG_INT (1) +NUMBER [$1a >= 0] ADD : ADD_INT ($1a) +NUMBER [$1a < 0] ADD : ADD_NEG_INT (-$1a) + +CONST0 SUBTRACT: ADD_INT (0) +CONST1 SUBTRACT: ADD_NEG_INT (-1) +CONST_1 SUBTRACT: ADD_INT (1) +NUMBER [$1a >= 0] SUBTRACT : ADD_NEG_INT ($1a) +NUMBER [$1a < 0] SUBTRACT : ADD_INT (-$1a) diff --git a/src/pike_types.c b/src/pike_types.c index 0f18b28531c432c904a015a5e31043f1d5dc3cec..0a5ae85b8cebe2239143cf292fd9cc4a88c9122d 100644 --- a/src/pike_types.c +++ b/src/pike_types.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: pike_types.c,v 1.18 1997/03/08 12:54:08 hubbe Exp $"); +RCSID("$Id: pike_types.c,v 1.19 1997/03/14 04:37:18 hubbe Exp $"); #include <ctype.h> #include "svalue.h" #include "pike_types.h" @@ -1218,6 +1218,7 @@ char *get_name_of_type(int t) case T_OBJECT: return "object"; case T_PROGRAM: return "program"; case T_STRING: return "string"; + case T_VOID: return "void"; default: return "unknown"; } } diff --git a/src/svalue.h b/src/svalue.h index 296293ad83cf78e1f736f3c701645cfbfc74b1e9..965388fffd2d4b4f5b68813a2f3c7bc706c4d38f 100644 --- a/src/svalue.h +++ b/src/svalue.h @@ -85,15 +85,16 @@ struct svalue #define T_FLOAT 7 #define T_INT 8 +#define T_VOID 16 +#define T_MANY 17 + #define T_DELETED 246 #define T_NOT 247 #define T_AND 248 #define T_UNKNOWN 249 -#define T_MANY 250 #define T_OR 251 #define T_SHORT_LVALUE 252 #define T_LVALUE 253 -#define T_VOID 254 #define T_MIXED 255 #define BIT_ARRAY (1<<T_ARRAY) @@ -106,10 +107,20 @@ struct svalue #define BIT_INT (1<<T_INT) #define BIT_FLOAT (1<<T_FLOAT) -/* Used to signifiy that this array might not be finished yet */ +/* Used to signify that this array might not be finished yet */ /* garbage collect uses this */ #define BIT_UNFINISHED (1<<15) +/* This is only used in typechecking to signify that this + * argument may be omitted. + */ +#define BIT_VOID (1<< T_VOID) + +/* This is used in typechecking to signify that the rest of the + * arguments has to be of this type. + */ +#define BIT_MANY (1 << T_MANY) + #define BIT_NOTHING 0 #define BIT_MIXED 0x7fff #define BIT_BASIC (BIT_INT|BIT_FLOAT|BIT_STRING)