cb22561995-10-11Fredrik Hübinette (Hubbe) /*\
06983f1996-09-22Fredrik Hübinette (Hubbe) ||| This file a part of Pike, and is copyright by Fredrik Hubinette ||| Pike is distributed as GPL (General Public License)
cb22561995-10-11Fredrik Hübinette (Hubbe) ||| See the files COPYING and DISCLAIMER for more information. \*/
acbf0a1999-02-20Henrik Grubbström (Grubba) /**/
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
a468a02001-07-24Henrik Grubbström (Grubba) RCSID("$Id: lex.c,v 1.99 2001/07/24 13:51:53 grubba Exp $");
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "language.h" #include "array.h" #include "lex.h" #include "stralloc.h" #include "dynamic_buffer.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "constants.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "hashtable.h" #include "stuff.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "interpret.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "object.h" #include "las.h" #include "operators.h" #include "opcodes.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "builtin_functions.h" #include "main.h"
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) #include "mapping.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
bdfb861997-12-22Fredrik Hübinette (Hubbe) #ifdef HAVE_SYS_PARAM_H
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <sys/param.h>
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <ctype.h> #include <math.h> #include <fcntl.h> #include <errno.h>
78ec7a1996-06-21Fredrik Hübinette (Hubbe) #include "time_stuff.h"
5267b71995-08-09Fredrik Hübinette (Hubbe)  #define LEXDEBUG 0
9b08a21998-03-31Fredrik Hübinette (Hubbe) #ifdef INSTR_PROFILING
fe80732001-06-29Fredrik Hübinette (Hubbe)  /* * If you have a 64 bit machine and 15+ Gb memory, this * routine should handle -p4 nicely. -Hubbe * (-p3 only requires ~38Mb on a 32bit machine) */ struct instr_counter { long runned; struct instr_counter* next[256]; }; int last_instruction[256]; struct instr_counter *instr_counter_storage; struct instr_counter *init_instr_storage_pointers(int depth) { int e; struct instr_counter *d; if(!depth) return 0; d=ALLOC_STRUCT(instr_counter); if(!d) { fprintf(stderr,"-p%d: out of memory.\n",p_flag); exit(2); } dmalloc_accept_leak(d); d->runned=0; for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++) d->next[e]=init_instr_storage_pointers(depth-1); return d; }
eff6212001-07-09Henrik Grubbström (Grubba) void add_runned(PIKE_OPCODE_T instr)
fe80732001-06-29Fredrik Hübinette (Hubbe) { int e; struct instr_counter **tmp=&instr_counter_storage; for(e=0;e<p_flag;e++) { tmp[0]->runned++; tmp=tmp[0]->next + last_instruction[e]; last_instruction[e]=last_instruction[e+1]; }
afa1c62001-07-09Henrik Grubbström (Grubba) #ifndef HAVE_COMPUTED_GOTO
fe80732001-06-29Fredrik Hübinette (Hubbe)  ((char **)(tmp))[0]++;
afa1c62001-07-09Henrik Grubbström (Grubba) #endif /* !HAVE_COMPUTED_GOTO */
fe80732001-06-29Fredrik Hübinette (Hubbe)  last_instruction[e]=instr; } void present_runned(struct instr_counter *d, int depth, int maxdepth) { int e; if(depth == maxdepth) { long runned = depth < p_flag ? d->runned : (long)d; if(!runned) return; fprintf(stderr,"%010ld @%d@: ",runned,maxdepth); for(e=0;e<depth;e++) { if(e) fprintf(stderr," :: "); fprintf(stderr,"%s", low_get_f_name(last_instruction[e] + F_OFFSET,0)); } fprintf(stderr,"\n"); }else{ for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++) { last_instruction[depth]=e; present_runned(d->next[e],depth+1, maxdepth); } } }
9b08a21998-03-31Fredrik Hübinette (Hubbe) #endif
be478c1997-08-30Henrik Grubbström (Grubba) void exit_lex(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
e82b301997-01-29Fredrik Hübinette (Hubbe)  if(p_flag)
06983f1996-09-22Fredrik Hübinette (Hubbe)  {
d9a93b2001-07-01Fredrik Hübinette (Hubbe)  extern void present_constant_profiling(void);
06983f1996-09-22Fredrik Hübinette (Hubbe)  int e;
d9a93b2001-07-01Fredrik Hübinette (Hubbe)  present_constant_profiling();
fe80732001-06-29Fredrik Hübinette (Hubbe)  fprintf(stderr,"Opcode compiles: (opcode, compiled)\n");
06983f1996-09-22Fredrik Hübinette (Hubbe)  for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++) {
fe80732001-06-29Fredrik Hübinette (Hubbe)  fprintf(stderr,"%08ld;;%-30s\n", (long)instrs[e].compiles, low_get_f_name(e+F_OFFSET,0));
06983f1996-09-22Fredrik Hübinette (Hubbe)  }
9b08a21998-03-31Fredrik Hübinette (Hubbe)  #ifdef INSTR_PROFILING
fe80732001-06-29Fredrik Hübinette (Hubbe)  for(e=0;e<=p_flag;e++)
9b08a21998-03-31Fredrik Hübinette (Hubbe)  {
fe80732001-06-29Fredrik Hübinette (Hubbe)  fprintf(stderr,"Opcode x %d usage:\n",e); present_runned(instr_counter_storage, 0, e);
9b08a21998-03-31Fredrik Hübinette (Hubbe)  }
06983f1996-09-22Fredrik Hübinette (Hubbe)  } #endif
fe80732001-06-29Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) }
f822262001-07-16Fredrik Hübinette (Hubbe) #ifdef PIKE_USE_MACHINE_CODE #define ADDR(X) , (void *)PIKE_CONCAT(opcode_,X) #define NULLADDR , 0
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f822262001-07-16Fredrik Hübinette (Hubbe) #define OPCODE0(OP,DESC) void PIKE_CONCAT(opcode_,OP)(void); #define OPCODE1(OP,DESC) void PIKE_CONCAT(opcode_,OP)(INT32); #define OPCODE2(OP,DESC) void PIKE_CONCAT(opcode_,OP)(INT32,INT32);
87c7592000-04-18Fredrik Hübinette (Hubbe) 
f822262001-07-16Fredrik Hübinette (Hubbe) #define OPCODE0_TAIL(OP,DESC) void PIKE_CONCAT(opcode_,OP)(void); #define OPCODE1_TAIL(OP,DESC) void PIKE_CONCAT(opcode_,OP)(INT32); #define OPCODE2_TAIL(OP,DESC) void PIKE_CONCAT(opcode_,OP)(INT32,INT32);
7951942000-04-20Fredrik Hübinette (Hubbe) 
f822262001-07-16Fredrik Hübinette (Hubbe) #define OPCODE0_JUMP(OP,DESC) void PIKE_CONCAT(opcode_,OP)(void); #define OPCODE1_JUMP(OP,DESC) void PIKE_CONCAT(opcode_,OP)(INT32); #define OPCODE2_JUMP(OP,DESC) void PIKE_CONCAT(opcode_,OP)(INT32,INT32); #define OPCODE0_TAILJUMP(OP,DESC) void PIKE_CONCAT(opcode_,OP)(void); #define OPCODE1_TAILJUMP(OP,DESC) void PIKE_CONCAT(opcode_,OP)(INT32); #define OPCODE2_TAILJUMP(OP,DESC) void PIKE_CONCAT(opcode_,OP)(INT32,INT32); #include "interpret_protos.h" #undef OPCODE0 #undef OPCODE1 #undef OPCODE2 #undef OPCODE0_TAIL #undef OPCODE1_TAIL #undef OPCODE2_TAIL #undef OPCODE0_JUMP #undef OPCODE1_JUMP #undef OPCODE2_JUMP #undef OPCODE0_TAILJUMP #undef OPCODE1_TAILJUMP #undef OPCODE2_TAILJUMP #else #define ADDR(X) #define NULLADDR #endif #define OPCODE0(OP,DESC) { DESC, OP, 0 ADDR(OP) }, #define OPCODE1(OP,DESC) { DESC, OP, I_HASARG ADDR(OP) }, #define OPCODE2(OP,DESC) { DESC, OP, I_TWO_ARGS ADDR(OP) }, #define OPCODE0_TAIL(OP,DESC) { DESC, OP, 0 ADDR(OP) }, #define OPCODE1_TAIL(OP,DESC) { DESC, OP, I_HASARG ADDR(OP) }, #define OPCODE2_TAIL(OP,DESC) { DESC, OP, I_TWO_ARGS ADDR(OP) }, #define OPCODE0_JUMP(OP,DESC) { DESC, OP, I_ISJUMP ADDR(OP) }, #define OPCODE1_JUMP(OP,DESC) { DESC, OP, I_HASARG ADDR(OP) }, #define OPCODE2_JUMP(OP,DESC) { DESC, OP, I_TWO_ARGS ADDR(OP) }, #define OPCODE0_TAILJUMP(OP,DESC) { DESC, OP, I_ISJUMP ADDR(OP) }, #define OPCODE1_TAILJUMP(OP,DESC) { DESC, OP, I_HASARG ADDR(OP) }, #define OPCODE2_TAILJUMP(OP,DESC) { DESC, OP, I_TWO_ARGS ADDR(OP) },
7951942000-04-20Fredrik Hübinette (Hubbe) 
87c7592000-04-18Fredrik Hübinette (Hubbe) #define LEXER
5267b71995-08-09Fredrik Hübinette (Hubbe) struct keyword instr_names[]= {
dbecc32000-10-30Henrik Grubbström (Grubba) #ifndef PIKE_PRECOMPILER
87c7592000-04-18Fredrik Hübinette (Hubbe) #include "interpret_protos.h"
dbecc32000-10-30Henrik Grubbström (Grubba) #endif /* !PIKE_PRECOMPILER */
f822262001-07-16Fredrik Hübinette (Hubbe) { "%=", F_MOD_EQ,0 NULLADDR }, { "&=", F_AND_EQ,0 NULLADDR }, { "|=", F_OR_EQ,0 NULLADDR }, { "*=", F_MULT_EQ,0 NULLADDR }, { "+=", F_ADD_EQ,0 NULLADDR }, { "-=", F_SUB_EQ,0 NULLADDR }, { "/=", F_DIV_EQ,0 NULLADDR }, { "<<=", F_LSH_EQ,0 NULLADDR }, { ">>=", F_RSH_EQ,0 NULLADDR }, { "^=", F_XOR_EQ,0 NULLADDR }, { "arg+=1024", F_PREFIX_1024,0 NULLADDR }, { "arg+=256", F_PREFIX_256,0 NULLADDR }, { "arg+=256*X", F_PREFIX_CHARX256,0 NULLADDR }, { "arg+=256*XX", F_PREFIX_WORDX256,0 NULLADDR }, { "arg+=256*XXX", F_PREFIX_24BITX256,0 NULLADDR }, { "arg+=512", F_PREFIX_512,0 NULLADDR }, { "arg+=768", F_PREFIX_768,0 NULLADDR }, { "arg+=1024", F_PREFIX2_1024,0 NULLADDR }, { "arg+=256", F_PREFIX2_256,0 NULLADDR }, { "arg+=256*X", F_PREFIX2_CHARX256,0 NULLADDR }, { "arg+=256*XX", F_PREFIX2_WORDX256,0 NULLADDR }, { "arg+=256*XXX", F_PREFIX2_24BITX256,0 NULLADDR }, { "arg+=512", F_PREFIX2_512,0 NULLADDR }, { "arg+=768", F_PREFIX2_768,0 NULLADDR }, { "break", F_BREAK,0 NULLADDR }, { "case", F_CASE,0 NULLADDR }, { "continue", F_CONTINUE,0 NULLADDR }, { "default", F_DEFAULT,0 NULLADDR }, { "do-while", F_DO,0 NULLADDR }, { "for", F_FOR,0 NULLADDR }, { "pointer", F_POINTER, I_ISPOINTER NULLADDR }, { "data", F_DATA, I_DATA NULLADDR }, { "byte", F_BYTE, I_DATA NULLADDR }, { "lvalue_list", F_LVALUE_LIST,0 NULLADDR }, { "label", F_LABEL,I_HASARG NULLADDR }, { "align", F_ALIGN, I_HASARG NULLADDR }, { "nop", F_NOP,0 NULLADDR },
a468a02001-07-24Henrik Grubbström (Grubba) { "entry", F_ENTRY,0 NULLADDR },
f822262001-07-16Fredrik Hübinette (Hubbe) { "function start", F_START_FUNCTION,0 NULLADDR }, { "notreached!", F_NOTREACHED, 0 NULLADDR },
5267b71995-08-09Fredrik Hübinette (Hubbe) }; struct instr instrs[F_MAX_INSTR - F_OFFSET]; struct reserved { struct hash_entry link; int token; };
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) void init_lex()
5267b71995-08-09Fredrik Hübinette (Hubbe) { unsigned int i;
a96ce92000-04-19Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG int fatal_later=0;
fe80732001-06-29Fredrik Hübinette (Hubbe) #ifdef INSTR_PROFILING instr_counter_storage=init_instr_storage_pointers(p_flag); #endif
a96ce92000-04-19Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  for(i=0; i<NELEM(instr_names);i++) {
a96ce92000-04-19Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(instr_names[i].token >= F_MAX_INSTR)
a96ce92000-04-19Fredrik Hübinette (Hubbe)  { fprintf(stderr,"Error in instr_names[%u]\n\n",i); fatal_later++; }
e82b301997-01-29Fredrik Hübinette (Hubbe)  if(instrs[instr_names[i].token - F_OFFSET].name)
a96ce92000-04-19Fredrik Hübinette (Hubbe)  { fprintf(stderr,"Duplicate name for %s\n",instr_names[i].word); fatal_later++; } #endif
e82b301997-01-29Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  instrs[instr_names[i].token - F_OFFSET].name = instr_names[i].word;
2d12341997-03-10Fredrik Hübinette (Hubbe)  instrs[instr_names[i].token - F_OFFSET].flags=instr_names[i].flags;
f822262001-07-16Fredrik Hübinette (Hubbe) #ifdef PIKE_USE_MACHINE_CODE instrs[instr_names[i].token - F_OFFSET].address=instr_names[i].address; #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
a96ce92000-04-19Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG for(i=1; i<F_MAX_OPCODE-F_OFFSET;i++) { if(!instrs[i].name) { fprintf(stderr,"Opcode %d does not have a name.\n",i); fatal_later++; } } if(fatal_later) fatal("Found %d errors in instrs.\n",fatal_later); #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) } char *low_get_f_name(int n,struct program *p) { static char buf[30]; if (n<F_MAX_OPCODE && instrs[n-F_OFFSET].name) { return instrs[n-F_OFFSET].name; }else if(n >= F_MAX_OPCODE) { if(p &&
5c8e891995-10-29Fredrik Hübinette (Hubbe)  (int)p->num_constants > (int)(n-F_MAX_OPCODE) &&
454d541999-09-18Fredrik Hübinette (Hubbe)  p->constants[n-F_MAX_OPCODE].sval.type==T_FUNCTION && (p->constants[n-F_MAX_OPCODE].sval.subtype == FUNCTION_BUILTIN) && p->constants[n-F_MAX_OPCODE].sval.u.efun)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
454d541999-09-18Fredrik Hübinette (Hubbe)  return p->constants[n-F_MAX_OPCODE].sval.u.efun->name->str;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{ sprintf(buf, "Call efun %d", n - F_MAX_OPCODE); return buf; } }else{ sprintf(buf, "<OTHER %d>", n); return buf; } } char *get_f_name(int n) { static char buf[30]; if (n<F_MAX_OPCODE && instrs[n-F_OFFSET].name) { return instrs[n-F_OFFSET].name; }else if(n >= F_MAX_OPCODE) {
edf4d02000-07-06Fredrik Hübinette (Hubbe)  if(Pike_fp && Pike_fp->context.prog && (int)Pike_fp->context.prog->num_constants > (int)(n-F_MAX_OPCODE) && Pike_fp->context.prog->constants[n-F_MAX_OPCODE].sval.type==T_FUNCTION && Pike_fp->context.prog->constants[n-F_MAX_OPCODE].sval.subtype == FUNCTION_BUILTIN && Pike_fp->context.prog->constants[n-F_MAX_OPCODE].sval.u.efun)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
edf4d02000-07-06Fredrik Hübinette (Hubbe)  return Pike_fp->context.prog->constants[n-F_MAX_OPCODE].sval.u.efun->name->str;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }else{ sprintf(buf, "Call efun %d", n - F_MAX_OPCODE); return buf; } }else{ sprintf(buf, "<OTHER %d>", n); return buf; } }
afa1c62001-07-09Henrik Grubbström (Grubba) #ifdef HAVE_COMPUTED_GOTO char *get_opcode_name(PIKE_OPCODE_T n) { int fcode; int low = 0; int high = F_MAX_OPCODE - F_OFFSET; static char buf[64]; if (!n) { return "<NULL opcode!>"; } while (low < high) { int mid = (low+high)/2; if (opcode_to_fcode[mid].opcode < n) { low = mid + 1; } else if (opcode_to_fcode[mid].opcode > n) { high = mid; } else { return get_f_name(opcode_to_fcode[mid].fcode); } } sprintf(buf, "<Unknown opcode 0x%p>", n); return buf; } #endif /* HAVE_COMPUTED_GOTO */
0d202a1995-10-20Fredrik Hübinette (Hubbe) char *get_token_name(int n) { static char buf[30]; if (n<F_MAX_INSTR && instrs[n-F_OFFSET].name) { return instrs[n-F_OFFSET].name; }else{ sprintf(buf, "<OTHER %d>", n); return buf; } }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) struct lex lex;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
acbf0a1999-02-20Henrik Grubbström (Grubba) /* Make lexers for shifts 0, 1 and 2. */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
acbf0a1999-02-20Henrik Grubbström (Grubba) #define SHIFT 0
fe104b2000-11-25Henrik Grubbström (Grubba) #include "lexer0.h"
acbf0a1999-02-20Henrik Grubbström (Grubba) #undef SHIFT #define SHIFT 1
fe104b2000-11-25Henrik Grubbström (Grubba) #include "lexer1.h"
acbf0a1999-02-20Henrik Grubbström (Grubba) #undef SHIFT #define SHIFT 2
fe104b2000-11-25Henrik Grubbström (Grubba) #include "lexer2.h"
acbf0a1999-02-20Henrik Grubbström (Grubba) #undef SHIFT
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) int yylex(YYSTYPE *yylval)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
acbf0a1999-02-20Henrik Grubbström (Grubba) #if LEXDEBUG>8 fprintf(stderr, "YYLEX: Calling lexer at 0x%08lx\n", (long)lex.current_lexer); #endif /* LEXDEBUG > 8 */ return(lex.current_lexer(yylval));
5267b71995-08-09Fredrik Hübinette (Hubbe) }