Branch: Tag:

1998-01-13

1998-01-13 23:01:47 by Fredrik Hübinette (Hubbe) <hubbe@hubbe.net>

Compiler update to use two pass

Rev: src/acconfig.h:1.14
Rev: src/builtin_functions.c:1.59
Rev: src/builtin_functions.h:1.5
Rev: src/compilation.h:1.4
Rev: src/configure.in:1.149
Rev: src/cpp.c:1.3
Rev: src/docode.c:1.24
Rev: src/docode.h:1.4
Rev: src/gc.c:1.24
Rev: src/interpret.c:1.57
Rev: src/interpret.h:1.16
Rev: src/language.yacc:1.51
Rev: src/las.c:1.40
Rev: src/las.h:1.9
Rev: src/lex.c:1.37
Rev: src/lex.h:1.7
Rev: src/main.c:1.32
Rev: src/modules/Image/blit.c:1.26
Rev: src/modules/Image/colortable.c:1.33
Rev: src/modules/Image/dct.c:1.11
Rev: src/modules/Image/image.c:1.73
Rev: src/modules/Image/matrix.c:1.13
Rev: src/modules/Image/operator.c:1.11
Rev: src/modules/Image/pattern.c:1.11
Rev: src/modules/Image/pnm.c:1.9
Rev: src/modules/Image/polyfill.c:1.18
Rev: src/modules/Image/togif.c:1.29
Rev: src/modules/Image/x.c:1.17
Rev: src/modules/Pipe/pipe.c:1.15
Rev: src/modules/Regexp/glue.c:1.9
Rev: src/modules/_Crypto/cbc.c:1.10
Rev: src/modules/_Crypto/crypto.c:1.24
Rev: src/modules/_Crypto/des.c:1.11
Rev: src/modules/_Crypto/pipe.c:1.11
Rev: src/modules/_Crypto/sha.c:1.9
Rev: src/modules/files/socktest.pike:1.6
Rev: src/modules/system/system.c:1.37
Rev: src/object.c:1.31
Rev: src/object.h:1.13
Rev: src/opcodes.c:1.10
Rev: src/operators.c:1.22
Rev: src/peep.c:1.16
Rev: src/peep.in:1.9
Rev: src/pike_types.c:1.27
Rev: src/pike_types.h:1.6
Rev: src/program.c:1.48
Rev: src/program.h:1.24
Rev: src/program_areas.h:1.2
Rev: src/stralloc.c:1.21
Rev: src/stralloc.h:1.10
Rev: src/svalue.c:1.18
Rev: src/testsuite.in:1.64
Rev: src/threads.c:1.51
Rev: src/threads.h:1.26

4:   ||| See the files COPYING and DISCLAIMER for more information.   \*/   #include "global.h" - RCSID("$Id: program.c,v 1.47 1998/01/02 01:05:51 hubbe Exp $"); + RCSID("$Id: program.c,v 1.48 1998/01/13 22:56:49 hubbe Exp $");   #include "program.h"   #include "object.h"   #include "dynamic_buffer.h"
28:   #include <errno.h>   #include <fcntl.h>    +  + #undef ATTRIBUTE + #define ATTRIBUTE(X) +  +    /*    * Define the size of the cache that is used for method lookup.    */   #define FIND_FUNCTION_HASHSIZE 4711       - #define FILE_STATE - #define PROGRAM_STATE -  +    #define STRUCT   #include "compilation.h" - #undef STRUCT +       #define DECLARE   #include "compilation.h" - #undef DECLARE +     - #undef FILE_STATE - #undef PROGRAM_STATE +     -  +    char *lfun_names[] = {    "__INIT",    "create",
91:   };      struct program *first_program = 0; + static int current_program_id=0;    - struct program fake_program; + struct program *new_program=0; + struct program *malloc_size_program=0;    - static int current_program_id=0; + int compiler_pass; + int compilation_depth; + struct compiler_frame *compiler_frame=0;   static INT32 last_line = 0;   static INT32 last_pc = 0;   static struct pike_string *last_file = 0; - dynamic_buffer inherit_names; +    dynamic_buffer used_modules;    - void free_all_local_names(void); + /* So what if we don't have templates? / Hubbe */    -  + #ifdef DEBUG + #define CHECK_FOO(NUMTYPE,TYPE,NAME) \ +  if(malloc_size_program-> PIKE_CONCAT(num_,NAME) < new_program-> PIKE_CONCAT(num_,NAME)) \ +  fatal("new_program->num_" #NAME " is out of order\n"); \ +  if(new_program->flags & PROGRAM_OPTIMIZED) \ +  fatal("Tried to reallocate fixed program.\n") +  + #else + #define CHECK_FOO(NUMTYPE,TYPE,NAME) + #endif +  + #define FOO(NUMTYPE,TYPE,NAME) \ + void PIKE_CONCAT(add_to_,NAME) (TYPE ARG) { \ +  CHECK_FOO(NUMTYPE,TYPE,NAME); \ +  if(malloc_size_program->PIKE_CONCAT(num_,NAME) == new_program->PIKE_CONCAT(num_,NAME)) { \ +  void *tmp; \ +  malloc_size_program->PIKE_CONCAT(num_,NAME) *= 2; \ +  malloc_size_program->PIKE_CONCAT(num_,NAME)++; \ +  tmp=realloc((char *)new_program->NAME, \ +  sizeof(TYPE) * \ +  malloc_size_program->PIKE_CONCAT(num_,NAME)); \ +  if(!tmp) fatal("Out of memory.\n"); \ +  new_program->NAME=tmp; \ +  } \ +  new_program->NAME[new_program->PIKE_CONCAT(num_,NAME)++]=(ARG); \ + } +  + #include "program_areas.h" +  + void ins_int(INT32 i, void (*func)(char tmp)) + { +  int e; +  for(e=0;e<(long)sizeof(i);e++) func(EXTRACT_UCHAR(((char *)&i)+e)); + } +  + void ins_short(INT16 i, void (*func)(char tmp)) + { +  int e; +  for(e=0;e<(long)sizeof(i);e++) func(EXTRACT_UCHAR(((char *)&i)+e)); + } +    void use_module(struct svalue *s)   {    if( (1<<s->type) & (BIT_MAPPING | BIT_OBJECT))
116:   }       - static int low_find_shared_string_identifier(struct pike_string *name, +  + int low_find_shared_string_identifier(struct pike_string *name,    struct program *prog);    - int find_module_identifier(struct pike_string *ident) +  +  + struct node_s *find_module_identifier(struct pike_string *ident)   {    JMP_BUF tmp; -  +  node *ret;    - #ifdef DEBUG -  if(recoveries && sp-evaluator_stack < recoveries->sp) -  fatal("Stack error in compiation (underflow)\n"); - #endif -  +     if(SETJMP(tmp))    {    ONERROR tmp;
152:    {   /* fprintf(stderr,"MOD: %s, %d %d\n",ident->str, current_line, sp[-1].type); */    UNSETJMP(tmp); -  return 1; +  ret=mksvaluenode(sp-1); +  pop_stack(); +  return ret;    }    pop_stack();    }
160:    UNSETJMP(tmp);       { -  struct program_state *p; -  for(p=previous_program_state;p;p=p->previous) +  struct program_state *p=previous_program_state; +  int n; +  for(n=0;n<compilation_depth;n++,p=p->previous)    { -  INT32 i; -  if(previous_file_state && -  previous_file_state->previous_program_state==p->previous) -  break; -  -  i=low_find_shared_string_identifier(ident, &p->fake_program); +  int i=low_find_shared_string_identifier(ident, p->new_program);    if(i!=-1)    {    struct identifier *id; -  id=ID_FROM_INT(&p->fake_program, i); +  id=ID_FROM_INT(p->new_program, i);    if(IDENTIFIER_IS_CONSTANT(id->identifier_flags))    { -  push_svalue(PROG_FROM_INT(&p->fake_program, i)->constants+ +  ret=mksvaluenode(PROG_FROM_INT(p->new_program, i)->constants+    id->func.offset); -  return 1; +  return ret;    }else{ -  yyerror("Identifier is not a constant"); -  return 0; +  return mkexternalnode(n, i, id);    }    }    }    } -  +     return 0;   }    - /* This should be optimized */ + struct program *parent_compilation(int level) + { +  int n; +  struct program_state *p=previous_program_state; +  for(n=0;n<level;n++) +  { +  if(n>=compilation_depth) return 0; +  p=p->previous; +  if(!p) return 0; +  } +  return p->new_program; + } +  + #define ID_TO_PROGRAM_CACHE_SIZE 512 + struct program *id_to_program_cache[ID_TO_PROGRAM_CACHE_SIZE]; +    struct program *id_to_program(INT32 id)   {    struct program *p; -  +  INT32 h; +  if(!id) return 0; +  h=id & (ID_TO_PROGRAM_CACHE_SIZE-1); +  +  if((p=id_to_program_cache[h])) +  if(p->id==id) return p; +     if(id) -  +  {    for(p=first_program;p;p=p->next) -  +  {    if(id==p->id) -  +  { +  if(id_to_program_cache[h]) +  free_program(id_to_program_cache[h]); +  +  id_to_program_cache[h]=p; +  p->refs++;    return p; -  +  } +  } +  }    return 0;   }    - #define SETUP(X,Y,TYPE,AREA) \ -  fake_program.X=(TYPE *)areas[AREA].s.str; \ -  fake_program.Y=areas[AREA].s.len/sizeof(TYPE) + /* Here starts routines which are used to build new programs */    - /* -  * This routine sets up the struct fake_program to work almost like a -  * normal program, but all pointers points to the program we are currently -  * compiling + /* Re-allocate all the memory in the program in one chunk. because: +  * 1) The individual blocks are munch bigger than they need to be +  * 2) cuts down on malloc overhead (maybe) +  * 3) localizes memory access (decreases paging)    */ - void setup_fake_program(void) + void optimize_program(struct program *p)   { -  fake_program.refs=0xffffff; -  SETUP(program, program_size, unsigned char, A_PROGRAM); -  SETUP(strings, num_strings, struct pike_string *, A_STRINGS); -  SETUP(inherits, num_inherits, struct inherit, A_INHERITS); -  SETUP(identifiers, num_identifiers, struct identifier, A_IDENTIFIERS); -  SETUP(identifier_references, num_identifier_references, struct reference, A_IDENTIFIER_REFERENCES); -  SETUP(constants, num_constants, struct svalue, A_CONSTANTS); -  SETUP(linenumbers, num_linenumbers, char, A_LINENUMBERS); +  SIZE_T size=0; +  char *data;    -  fake_program.inherits[0].prog=&fake_program; -  fake_program.next=0; -  fake_program.prev=0; -  fake_program.flags=0; - /* -  fake_program.lfuns=0; -  fake_prog.num_lfuns=0; - */ - #ifdef PROFILING -  fake_program.num_clones = 0; - #endif /* PROFILING */ -  fake_object.prog=&fake_program; +  /* Already done (shouldn't happen, but who knows?) */ +  if(p->flags & PROGRAM_OPTIMIZED) return; +  + #define FOO(NUMTYPE,TYPE,NAME) \ +  size+=MY_ALIGN(p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0])); + #include "program_areas.h" +  +  data=malloc(size); +  if(!data) return; /* We are out of memory, but we don't care! */ +  +  size=0; +  + #define FOO(NUMTYPE,TYPE,NAME) \ +  MEMCPY(data+size,p->NAME,p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0])); \ +  free((char *)p->NAME); \ +  p->NAME=(TYPE *)(data+size); \ +  size+=MY_ALIGN(p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0])); + #include "program_areas.h" +  +  p->total_size=size + sizeof(struct program); +  +  p->flags |= PROGRAM_OPTIMIZED;   }    - /* Here starts routines which are used to build new programs */ + /* internal function to make the index-table */ + static int funcmp(const void *a,const void *b) + { +  return +  my_order_strcmp(ID_FROM_INT(new_program, *(unsigned short *)a)->name, +  ID_FROM_INT(new_program, *(unsigned short *)b)->name); + }    -  + void fixate_program(void) + { +  INT32 i,e,t; +  if(new_program->flags & PROGRAM_FIXED) return; + #ifdef DEBUG +  if(new_program->flags & PROGRAM_OPTIMIZED) +  fatal("Cannot fixate optimized program\n"); + #endif +  +  /* Ok, sort for binsearch */ +  for(e=i=0;i<(int)new_program->num_identifier_references;i++) +  { +  struct reference *funp; +  struct identifier *fun; +  funp=new_program->identifier_references+i; +  if(funp->id_flags & (ID_HIDDEN|ID_STATIC)) continue; +  if(funp->id_flags & ID_INHERITED) +  { +  if(funp->id_flags & ID_PRIVATE) continue; +  fun=ID_FROM_PTR(new_program, funp); + /* if(fun->func.offset == -1) continue; * prototype */ +  +  /* check for multiple definitions */ +  for(t=i+1;t>=0 && t<(int)new_program->num_identifier_references;t++) +  { +  struct reference *funpb; +  struct identifier *funb; +  +  funpb=new_program->identifier_references+t; +  if(funpb->id_flags & (ID_HIDDEN|ID_STATIC)) continue; +  funb=ID_FROM_PTR(new_program,funpb); +  /* if(funb->func.offset == -1) continue; * prototype */ +  if(fun->name==funb->name) t=-10; +  } +  if(t<0) continue; +  } +  add_to_identifier_index(i); +  } +  fsort((void *)new_program->identifier_index, +  new_program->num_identifier_index, +  sizeof(unsigned short),(fsortfun)funcmp); +  +  +  for(i=0;i<NUM_LFUNS;i++) +  new_program->lfuns[i]=find_identifier(lfun_names[i],new_program); +  +  new_program->flags |= PROGRAM_FIXED; + } +    /*    * Start building a new program    */ - void start_new_program(void) + void low_start_new_program(struct program *p, +  struct pike_string *name, +  int flags)   {    int e;       threads_disabled++; -  if(local_variables) -  setup_fake_program(); - #define PROGRAM_STATE +  compilation_depth++; +  +  if(!p) +  { +  p=ALLOC_STRUCT(program); +  MEMSET(p, 0, sizeof(struct program)); +  +  p->refs=1; +  p->id=++current_program_id; +  +  if((p->next=first_program)) first_program->prev=p; +  first_program=p; +  }else{ +  p->refs++; +  } +  +  if(name) +  { +  struct svalue s; +  s.type=T_PROGRAM; +  s.u.program=p; +  add_constant(name, &s, flags); +  } +    #define PUSH   #include "compilation.h" - #undef PUSH - #undef PROGRAM_STATE +     -  if(previous_program_state->fake_program.num_inherits) -  previous_program_state->fake_program.inherits[0].prog= -  &previous_program_state->fake_program; -  +     init_type_stack();    -  for(e=0; e<NUM_AREAS; e++) low_reinit_buf(areas + e); -  low_reinit_buf(& inherit_names); +     low_reinit_buf(& used_modules); -  fake_program.id = ++current_program_id; +     -  +  if(p && (p->flags & PROGRAM_FINISHED))    { -  struct inherit inherit; -  struct pike_string *name; -  -  inherit.prog=&fake_program; -  inherit.inherit_level=0; -  inherit.identifier_level=0; -  inherit.storage_offset=0; -  add_to_mem_block(A_INHERITS,(char *)&inherit,sizeof inherit); -  name=make_shared_string("this"); -  low_my_binary_strcat((char *)&name,sizeof(name), &inherit_names); +  yyerror("Pass2: Program already done"); +  p=0;    }    -  +  malloc_size_program = ALLOC_STRUCT(program); +  new_program=p;    -  +  if(new_program->program)    { -  + #define FOO(NUMTYPE,TYPE,NAME) \ +  malloc_size_program->PIKE_CONCAT(num_,NAME)=new_program->PIKE_CONCAT(num_,NAME); + #include "program_areas.h" +  }else{ +  static struct pike_string *s; +  struct inherit i; +  + #define START_SIZE 64 + #define FOO(NUMTYPE,TYPE,NAME) \ +  malloc_size_program->PIKE_CONCAT(num_,NAME)=START_SIZE; \ +  new_program->NAME=(TYPE *)xalloc(sizeof(TYPE) * START_SIZE); + #include "program_areas.h" +  +  i.prog=new_program; +  i.identifier_level=0; +  i.storage_offset=0; +  i.inherit_level=0; +  i.parent=0; +  i.parent_identifier=0; +  i.name=0; +  add_to_inherits(i); +  } +  +  {    struct svalue tmp;    tmp.type=T_MAPPING;   #ifdef __CHECKER__
287:    use_module(& tmp);    }    +  init_node=0;    num_parse_error=0; -  local_variables=ALLOC_STRUCT(locals); -  local_variables->next=0; -  local_variables->current_number_of_locals=0; -  local_variables->max_number_of_locals=0; -  local_variables->current_type=0; -  local_variables->current_return_type=0; +  +  push_compiler_frame();   }    - static void low_free_program(struct program *p) + void start_new_program(void)   { -  +  low_start_new_program(0,0,0); + } +  +  + void really_free_program(struct program *p) + {    unsigned INT16 e; -  +  +  if(id_to_program_cache[p->id & (ID_TO_PROGRAM_CACHE_SIZE-1)]==p) +  id_to_program_cache[p->id & (ID_TO_PROGRAM_CACHE_SIZE-1)]=0; +     for(e=0; e<p->num_strings; e++)    free_string(p->strings[e]);   
312:    free_svalue(p->constants+e);       for(e=1; e<p->num_inherits; e++) +  {    free_program(p->inherits[e].prog); -  +  if(p->inherits[e].parent) +  free_object(p->inherits[e].parent);    }    - void really_free_program(struct program *p) - { -  low_free_program(p); -  +     if(p->prev)    p->prev->next=p->next;    else
327:    if(p->next)    p->next->prev=p->prev;    +  if(p->flags & PROGRAM_OPTIMIZED) +  { +  if(p->program) +  free(p->program); + #define FOO(NUMTYPE,TYPE,NAME) p->NAME=0; + #include "program_areas.h" +  }else{ + #define FOO(NUMTYPE,TYPE,NAME) \ +  if(p->NAME) { free((char *)p->NAME); p->NAME=0; } + #include "program_areas.h" +  } +     free((char *)p);       GC_FREE();   }      #ifdef DEBUG -  +    void dump_program_desc(struct program *p)   {    int e,d,q;
349: Inside #if defined(DEBUG)
   }   */    -  fprintf(stderr,"All identifiers: (this=%08x)\n",(unsigned int)p); +  fprintf(stderr,"All identifiers:\n");    for(e=0;e<(int)p->num_identifier_references;e++)    {    fprintf(stderr,"%3d:",e);    for(d=0;d<INHERIT_FROM_INT(p,e)->inherit_level;d++) fprintf(stderr," "); -  fprintf(stderr," (%08x) %s;\t", -  (unsigned int)INHERIT_FROM_INT(p,e)->prog, -  ID_FROM_INT(p,e)->name->str); -  if(p->identifier_references[e].id_flags&ID_HIDDEN) -  fprintf(stderr," (hidden)"); -  if(p->identifier_references[e].id_flags&ID_INHERITED) -  fprintf(stderr," (inherited)"); -  fprintf(stderr,"\n"); +  fprintf(stderr,"%s;\n",ID_FROM_INT(p,e)->name->str);    }    fprintf(stderr,"All sorted identifiers:\n"); -  for(q=0;q<(int)p->num_identifier_indexes;q++) +  for(q=0;q<(int)p->num_identifier_index;q++)    {    e=p->identifier_index[q];    fprintf(stderr,"%3d (%3d):",e,q);    for(d=0;d<INHERIT_FROM_INT(p,e)->inherit_level;d++) fprintf(stderr," "); -  fprintf(stderr," (%08x) %s;\t", -  (unsigned int)INHERIT_FROM_INT(p,e)->prog, -  ID_FROM_INT(p,e)->name->str); -  if(p->identifier_references[e].id_flags & ID_HIDDEN) -  fprintf(stderr," (hidden)"); -  if(p->identifier_references[e].id_flags&ID_INHERITED) -  fprintf(stderr," (inherited)"); -  fprintf(stderr,"\n"); +  fprintf(stderr,"%s;\n", ID_FROM_INT(p,e)->name->str);    }   }   #endif      static void toss_compilation_resources(void)   { -  struct pike_string **names; -  struct svalue *modules; -  int e; +  free_program(new_program); +  new_program=0;    -  for (e=0; e<NUM_AREAS; e++) toss_buffer(areas+e); -  -  names=(struct pike_string **)inherit_names.s.str; -  e=inherit_names.s.len / sizeof(struct pike_string *); -  while(--e>=0) if(names[e]) free_string(names[e]); -  toss_buffer(& inherit_names); -  -  modules=(struct svalue *)used_modules.s.str; -  e=used_modules.s.len / sizeof(struct svalue); -  while(--e>=0) free_svalue(modules+e); -  toss_buffer(& used_modules); -  -  /* Clean up */ -  while(local_variables) +  if(malloc_size_program)    { -  struct locals *l; -  for(e=0;e<local_variables->current_number_of_locals;e++) -  { -  free_string(local_variables->variable[e].name); -  free_string(local_variables->variable[e].type); +  free((char *)malloc_size_program); +  malloc_size_program=0;    }    -  if(local_variables->current_type) -  free_string(local_variables->current_type); +  while(compiler_frame) +  pop_compiler_frame();    -  if(local_variables->current_return_type) -  free_string(local_variables->current_return_type); -  -  l=local_variables->next; -  free((char *)local_variables); -  local_variables=l; -  } -  +     if(last_file)    {    free_string(last_file);    last_file=0;    } - } +     - /* -  * Something went wrong. -  * toss resources of program we were building -  */ - void toss_current_program(void) +     { -  setup_fake_program(); -  low_free_program(&fake_program); -  toss_compilation_resources(); +  struct svalue *modules=(struct svalue *)used_modules.s.str; +  INT32 e; +  +  for(e=0;e<(long)(used_modules.s.len / sizeof(struct svalue));e++) +  free_svalue(modules+e); +  +  toss_buffer(&used_modules);    }    -  + } +    #ifdef DEBUG   void check_program(struct program *p)   {
465: Inside #if defined(DEBUG)
   if(p->storage_needed < 0)    fatal("Program->storage_needed < 0.\n");    +  if(p->num_identifier_index > p->num_identifier_references) +  fatal("Too many identifier index entries in program!\n"); +  + #if 0    size=MY_ALIGN(sizeof(struct program));    size+=MY_ALIGN(p->num_linenumbers);    size+=MY_ALIGN(p->program_size);
485: Inside #if defined(DEBUG)
   if(size < (INT32)p->total_size)    fatal("Program size is in error.\n");    + #define CHECKRANGE(X,Y) \ + if((char *)(p->X) < (char *)p || (char *)(p->X)> ((char *)p)+size) fatal("Program->%s is wrong.\n",Y)    - #define CHECKRANGE(X,Y) if((char *)(p->X) < (char *)p || (char *)(p->X)> ((char *)p)+size) fatal("Program->%s is wrong.\n",Y) -  +     CHECKRANGE(program,"program");    CHECKRANGE(strings,"strings");    CHECKRANGE(inherits,"inherits");
509:    if(p->checksum != checksum)    fatal("Someone changed a program!!!\n");    } + #endif       for(e=0;e<(int)p->num_constants;e++) -  { +     check_svalue(p->constants + e); -  } +        for(e=0;e<(int)p->num_strings;e++)    check_string(p->strings[e]);
540:    fatal("Identifier offset is wrong!\n");    }    -  -  for(e=0;e<(int)p->num_identifier_indexes;e++) +  for(e=0;e<(int)p->num_identifier_index;e++)    {    if(p->identifier_index[e] > p->num_identifier_references)    fatal("Program->identifier_indexes[%ld] is wrong\n",(long)e);
549:       for(e=0;e<(int)p->num_inherits;e++)    { -  struct program *tmp_prog=p->inherits[e].prog; -  INT32 d; -  +     if(p->inherits[e].storage_offset < 0)    fatal("Inherit->storage_offset is wrong.\n"); -  -  for(d=0;d<(int)tmp_prog->num_identifiers;d++) -  { -  struct identifier *id=tmp_prog->identifiers+d; -  -  if(IDENTIFIER_IS_VARIABLE(id->identifier_flags)) -  { -  INT32 offset,size,e2; -  offset=p->inherits[e].storage_offset + id->func.offset; -  size=id->run_time_type == T_MIXED ? sizeof(struct svalue) : sizeof(union anything); -  -  if(offset < 0 || offset+size > p->storage_needed) -  fatal("Variable located outside allocated space.\n"); -  -  -  for(e2=0;e2<(int)p->num_inherits;e2++) -  { -  struct program *tmp_prog2=p->inherits[e2].prog; -  INT32 d2; -  -  for(d2=0;d2<(int)tmp_prog2->num_identifiers;d2++) -  { -  struct identifier *id2=tmp_prog2->identifiers+d2; -  -  if(e==e2 && d==d2) continue; -  -  if(IDENTIFIER_IS_VARIABLE(id2->identifier_flags)) -  { -  INT32 offset2,size2; -  -  offset2=p->inherits[e2].storage_offset + id2->func.offset; -  size2=id2->run_time_type == T_MIXED ? sizeof(struct svalue) : sizeof(union anything); -  if( (offset > offset2) ? -  (offset2+size2 > offset) : -  (offset+size > offset2)) -  { -  fatal("Variable %s (%ld+%ld) and %s (%ld+%ld) overlap.\n", -  id->name->str, (long)offset, (long)size, -  id2->name->str, (long)offset2, (long)size2); +     }   } -  } -  } -  } -  } -  } - } +    #endif    - /* internal function to make the index-table */ - static int funcmp(const void *a,const void *b) + struct program *end_first_pass(int finish)   { -  return -  my_order_strcmp(ID_FROM_INT(&fake_program, *(unsigned short *)a)->name, -  ID_FROM_INT(&fake_program, *(unsigned short *)b)->name); - } -  - /* -  * Finish this program, returning the newly built program -  */ -  - #define INS_BLOCK(PTR,PTRS,TYPE,AREA) \ - prog->PTR=(TYPE *)p; \ - if((prog->PTRS = areas[AREA].s.len/sizeof(TYPE))) \ - { \ -  MEMCPY(p,areas[AREA].s.str, areas[AREA].s.len); \ -  p+=MY_ALIGN(areas[AREA].s.len); \ - } -  - struct program *end_program(void) - { -  struct pike_string **names; -  int size, i,e,t; -  char *p; +     struct program *prog;       /*    * Define the __INIT function, but only if there was any code    * to initialize.    */ -  if (init_node) +  if(init_node)    {    union idptr tmp;    struct pike_string *s; -  push_locals(); +     s=make_shared_string("__INIT");    dooptcode(s,    mknode(F_ARG_LIST,    init_node,mknode(F_RETURN,mkintnode(0),0)),    function_type_string,    0); -  pop_locals(); +     free_string(s);    init_node=0;    }    -  +  pop_compiler_frame(); /* Pop __INIT local variables */ +     exit_type_stack();    -  if (num_parse_error > 0) +  if(num_parse_error > 0)    { -  toss_current_program(); +     prog=0;    }else{ -  setup_fake_program(); -  size = MY_ALIGN(sizeof (struct program)); -  for (i=0; i<NUM_AREAS; i++) size += MY_ALIGN(areas[i].s.len); -  size+=MY_ALIGN(fake_program.num_identifier_references * sizeof(unsigned short)); +  prog=new_program; +  prog->refs++;    -  p = (char *)xalloc(size); -  prog = (struct program *)p; -  *prog = fake_program; -  prog->total_size = size; -  prog->refs = 1; -  prog->flags=0; -  p += MY_ALIGN(sizeof (struct program)); -  -  INS_BLOCK(program,program_size,unsigned char,A_PROGRAM); -  INS_BLOCK(linenumbers,num_linenumbers,char,A_LINENUMBERS); -  INS_BLOCK(identifiers,num_identifiers,struct identifier,A_IDENTIFIERS); -  INS_BLOCK(identifier_references,num_identifier_references,struct reference,A_IDENTIFIER_REFERENCES); -  INS_BLOCK(strings,num_strings,struct pike_string *,A_STRINGS); -  INS_BLOCK(inherits,num_inherits,struct inherit,A_INHERITS); -  INS_BLOCK(constants,num_constants,struct svalue,A_CONSTANTS); -  - #ifdef PROFILING -  /* There is probably a better place for this, but... */ -  for (i=0; i < prog->num_identifiers; i++) { -  prog->identifiers[i].num_calls = 0; -  } - #endif /* PROFILING */ -  -  /* Ok, sort for binsearch */ -  prog->identifier_index=(unsigned short *)p; -  for(e=i=0;i<(int)prog->num_identifier_references;i++) -  { -  struct reference *funp; -  struct identifier *fun; -  funp=prog->identifier_references+i; -  if(funp->id_flags & (ID_HIDDEN|ID_STATIC)) continue; -  -  if(funp->id_flags & ID_INHERITED) -  { -  fun=ID_FROM_PTR(prog, funp); -  /* if(fun->func.offset == -1) continue; prototype */ -  -  /* check for multiple definitions */ -  for(t=i+1;t>=0 && t<(int)prog->num_identifier_references;t++) -  { -  struct reference *funpb; -  struct identifier *funb; -  -  funpb=prog->identifier_references+t; -  if(funpb->id_flags & (ID_HIDDEN|ID_STATIC)) continue; -  funb=ID_FROM_PTR(prog,funpb); -  if(funb->func.offset == -1) continue; /* prototype */ -  if(fun->name==funb->name) t=-10; -  } -  if(t<0) continue; -  } -  -  prog->identifier_index[e]=i; -  e++; -  } -  prog->num_identifier_indexes=e; -  fsort((void *)prog->identifier_index, e,sizeof(unsigned short),(fsortfun)funcmp); -  -  p+=MY_ALIGN(prog->num_identifier_indexes*sizeof(unsigned short)); -  -  toss_compilation_resources(); -  -  prog->inherits[0].prog=prog; -  prog->prev=0; -  if((prog->next=first_program)) -  first_program->prev=prog; -  first_program=prog; -  -  for(i=0;i<NUM_LFUNS;i++) -  prog->lfuns[i]=find_identifier(lfun_names[i],prog); -  +    #ifdef DEBUG    check_program(prog);    if(l_flag)    dump_program_desc(prog);   #endif    -  +  new_program->flags |= PROGRAM_PASS_1_DONE; +  +  if(finish) +  { +  fixate_program(); +  optimize_program(new_program); +  new_program->flags |= PROGRAM_FINISHED; +  } +     GC_ALLOC();    } -  +  toss_compilation_resources();    - #define PROGRAM_STATE +    #define POP   #include "compilation.h" - #undef POP - #undef PROGRAM_STATE -  if(fake_program.num_inherits) -  fake_program.inherits[0].prog=&fake_program; +  +  compilation_depth--;    threads_disabled--;    free_all_nodes();    return prog;   }      /* -  +  * Finish this program, returning the newly built program +  */ + struct program *end_program(void) + { +  return end_first_pass(1); + } +  +  + /*    * Allocate needed for this program in the object structure.    * An offset to the data is returned.    */   SIZE_T add_storage(SIZE_T size)   {    SIZE_T offset; -  offset=fake_program.storage_needed; +  offset=new_program->storage_needed;    size=MY_ALIGN(size); -  fake_program.storage_needed += size; +  new_program->storage_needed += size;    return offset;   }   
773:    */   void set_init_callback(void (*init)(struct object *))   { -  fake_program.init=init; +  new_program->init=init;   }      /*
782:    */   void set_exit_callback(void (*exit)(struct object *))   { -  fake_program.exit=exit; +  new_program->exit=exit;   }      /*
791:    */   void set_gc_mark_callback(void (*m)(struct object *))   { -  fake_program.gc_marked=m; +  new_program->gc_marked=m;   }    -  - int low_reference_inherited_identifier(int e,struct pike_string *name) + int low_reference_inherited_identifier(int e, +  struct pike_string *name)   {    struct reference funp;    struct program *p;    int i,d;    -  p=fake_program.inherits[e].prog; +  p=new_program->inherits[e].prog;    i=find_shared_string_identifier(name,p);    if(i==-1) return i;       if(p->identifier_references[i].id_flags & ID_HIDDEN)    return -1;    -  if(ID_FROM_INT(p,i)->func.offset == -1) /* prototype */ -  return -1; -  +     funp=p->identifier_references[i];    funp.inherit_offset+=e;    funp.id_flags|=ID_HIDDEN;    -  for(d=0;d<(int)fake_program.num_identifier_references;d++) +  for(d=0;d<(int)new_program->num_identifier_references;d++)    {    struct reference *fp; -  fp=fake_program.identifier_references+d; +  fp=new_program->identifier_references+d;       if(!MEMCMP((char *)fp,(char *)&funp,sizeof funp)) return d;    }    -  add_to_mem_block(A_IDENTIFIER_REFERENCES,(char *)&funp,sizeof funp); -  return fake_program.num_identifier_references; +  add_to_identifier_references(funp); +  return new_program->num_identifier_references -1;   }    -  -  +    int reference_inherited_identifier(struct pike_string *super_name,    struct pike_string *function_name)   { -  struct pike_string **names; +     int e,i;      #ifdef DEBUG
840:    fatal("reference_inherited_function on nonshared string.\n");   #endif    -  names=(struct pike_string **)inherit_names.s.str; -  setup_fake_program(); -  -  for(e=fake_program.num_inherits-1;e>0;e--) +  for(e=new_program->num_inherits-1;e>0;e--)    { -  if(fake_program.inherits[e].inherit_level!=1) continue; -  if(!names[e]) continue; +  if(new_program->inherits[e].inherit_level!=1) continue; +  if(!new_program->inherits[e].name) continue;       if(super_name) -  { -  int l; -  l=names[e]->len; -  if(l<super_name->len) continue; -  if(strncmp(super_name->str, -  names[e]->str+l-super_name->len, -  super_name->len)) +  if(super_name != new_program->inherits[e].name)    continue; -  } +        i=low_reference_inherited_identifier(e,function_name);    if(i==-1) continue;
868:      void rename_last_inherit(struct pike_string *n)   { -  struct pike_string **names; -  int e; -  names=(struct pike_string **)inherit_names.s.str; -  e=inherit_names.s.len / sizeof(struct pike_string *); -  free_string(names[e-1]); -  copy_shared_string(names[e-1],n); +  if(new_program->inherits[new_program->num_inherits].name) +  free_string(new_program->inherits[new_program->num_inherits].name); +  copy_shared_string(new_program->inherits[new_program->num_inherits].name, +  n);   }      /*    * make this program inherit another program    */ - void do_inherit(struct program *p,INT32 flags, struct pike_string *name) + void do_inherit(struct svalue *prog, +  INT32 flags, +  struct pike_string *name)   {    int e, inherit_offset, storage_offset;    struct inherit inherit;    struct pike_string *s;    -  setup_fake_program(); +  struct program *p=program_from_svalue(prog);    -  inherit_offset = fake_program.num_inherits; +     -  storage_offset=fake_program.storage_needed; +  if(!p) +  { +  yyerror("Illegal program pointer."); +  return; +  } +  +  inherit_offset = new_program->num_inherits; +  +  storage_offset=new_program->storage_needed;    add_storage(p->storage_needed);       for(e=0; e<(int)p->num_inherits; e++)    {    inherit=p->inherits[e];    inherit.prog->refs++; -  inherit.identifier_level += fake_program.num_identifier_references; +  inherit.identifier_level += new_program->num_identifier_references;    inherit.storage_offset += storage_offset;    inherit.inherit_level ++; -  add_to_mem_block(A_INHERITS,(char *)&inherit,sizeof inherit); +  if(!e) +  { +  if(prog->type == T_FUNCTION) +  { +  inherit.parent=prog->u.object; +  inherit.parent_identifier=prog->subtype; +  } +  } +  if(inherit.parent) inherit.parent->refs++;    -  low_my_binary_strcat((char *)&name,sizeof(name),&inherit_names); +     if(name)    { -  +  if(e==0) +  { +  inherit.name=name;    reference_shared_string(name); -  name=0; +     } -  +  else if(inherit.name) +  { +  struct pike_string *s; +  s=begin_shared_string(inherit.name->len + name->len + 2); +  MEMCPY(s->str,name->str,name->len); +  MEMCPY(s->str+name->len,"::",2); +  MEMCPY(s->str+name->len+2,inherit.name->str,inherit.name->len); +  inherit.name=end_shared_string(s);    } -  +  else +  { +  inherit.name=0; +  } +  }else{ +  inherit.name=0; +  } +  add_to_inherits(inherit); +  }       for (e=0; e < (int)p->num_identifier_references; e++)    {
923:    {    int n;    n = isidentifier(name); -  if (n != -1 && ID_FROM_INT(&fake_program,n)->func.offset != -1) +  if (n != -1 && ID_FROM_INT(new_program,n)->func.offset != -1)    my_yyerror("Illegal to redefine 'nomask' function/variable \"%s\"",name->str);    }   
935:    fun.id_flags |= flags;       fun.id_flags |= ID_INHERITED; -  add_to_mem_block(A_IDENTIFIER_REFERENCES, (char *)&fun, sizeof fun); +  add_to_identifier_references(fun);    }       /* Ska det h{r vara s} h{r? */
953:    }   }    - void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *name) + void simple_do_inherit(struct pike_string *s, +  INT32 flags, +  struct pike_string *name)   {    reference_shared_string(s);    push_string(s); -  reference_shared_string(current_file); -  push_string(current_file); +  ref_push_string(lex.current_file);    SAFE_APPLY_MASTER("handle_inherit", 2);       if(sp[-1].type != T_PROGRAM)
973:    free_string(s);    s=name;    } -  do_inherit(sp[-1].u.program, flags, s); +  do_inherit(sp-1, flags, s);    free_string(s);    pop_stack();   }
984:   int isidentifier(struct pike_string *s)   {    INT32 e; -  setup_fake_program(); -  for(e=(int)fake_program.num_identifier_references-1;e>=0;e--) +  for(e=new_program->num_identifier_references-1;e>=0;e--)    { -  if(fake_program.identifier_references[e].id_flags & ID_HIDDEN) continue; +  if(new_program->identifier_references[e].id_flags & ID_HIDDEN) continue;    -  if(ID_FROM_INT(& fake_program, e)->name == s) +  if(ID_FROM_INT(new_program, e)->name == s)    return e;    }    return -1;   }    -  + /* argument must be a shared string */   int low_define_variable(struct pike_string *name,    struct pike_string *type,    INT32 flags,
1002:    INT32 run_time_type)   {    int n; +     struct identifier dummy;    struct reference ref;    -  + #ifdef DEBUG +  if(new_program->flags & (PROGRAM_FIXED | PROGRAM_OPTIMIZED)) +  fatal("Attempting to add variable to fixed program\n"); + #endif +     copy_shared_string(dummy.name, name);    copy_shared_string(dummy.type, type);    dummy.identifier_flags = 0;    dummy.run_time_type=run_time_type;    dummy.func.offset=offset; -  +    #ifdef PROFILING -  dummy.num_calls = 0; - #endif /* PROFILING */ +  dummy.num_calls=0; + #endif       ref.id_flags=flags; -  ref.identifier_offset=areas[A_IDENTIFIERS].s.len / sizeof dummy; +  ref.identifier_offset=new_program->num_identifiers;    ref.inherit_offset=0;    -  add_to_mem_block(A_IDENTIFIERS, (char *)&dummy, sizeof dummy); -  fake_program.num_identifiers ++; +  add_to_identifiers(dummy);    -  n=areas[A_IDENTIFIER_REFERENCES].s.len / sizeof ref; -  add_to_mem_block(A_IDENTIFIER_REFERENCES, (char *)&ref, sizeof ref); -  fake_program.num_identifier_references ++; +  n=new_program->num_identifier_references; +  add_to_identifier_references(ref);       return n;   }    -  +    int map_variable(char *name,    char *type,    INT32 flags,
1061:    if(type == void_type_string)    yyerror("Variables can't be of type void");    -  setup_fake_program(); +     n = isidentifier(name);    -  +  if(new_program->flags & PROGRAM_PASS_1_DONE) +  { +  if(n==-1) +  yyerror("Pass2: Variable disappeared!"); +  else +  return n; +  } +  + #ifdef DEBUG +  if(new_program->flags & (PROGRAM_FIXED | PROGRAM_OPTIMIZED)) +  fatal("Attempting to add variable to fixed program\n"); + #endif +     if(n != -1)    { -  setup_fake_program(); +        if (IDENTIFIERP(n)->id_flags & ID_NOMASK)    my_yyerror("Illegal to redefine 'nomask' variable/functions \"%s\"", name->str);    -  if(PROG_FROM_INT(& fake_program, n) == &fake_program) +  if(PROG_FROM_INT(new_program, n) == new_program)    my_yyerror("Variable '%s' defined twice.",name->str);    -  if(ID_FROM_INT(& fake_program, n)->type != type) +  if(ID_FROM_INT(new_program, n)->type != type)    my_yyerror("Illegal to redefine inherited variable with different type.");    -  if(ID_FROM_INT(& fake_program, n)->identifier_flags != flags) +  if(ID_FROM_INT(new_program, n)->identifier_flags != flags)    my_yyerror("Illegal to redefine inherited variable with different type.");       } else {    int run_time_type=compile_type_to_runtime_type(type); -  if(run_time_type == T_FUNCTION) run_time_type = T_MIXED; +     -  n=low_define_variable(name, type, flags, +  switch(run_time_type) +  { +  case T_FUNCTION: +  case T_PROGRAM: +  run_time_type = T_MIXED; +  } +  +  n=low_define_variable(name,type,flags,    add_storage(run_time_type == T_MIXED ?    sizeof(struct svalue) :    sizeof(union anything)),    run_time_type); -  +  +     }       return n;
1109:    return ret;   }    -  + /* FIXME: add_constant with c==0 means declaration */   int add_constant(struct pike_string *name,    struct svalue *c,    INT32 flags)
1123:    fatal("define_constant on nonshared string.\n");   #endif    -  setup_fake_program(); +     n = isidentifier(name);    -  +  +  if(new_program->flags & PROGRAM_PASS_1_DONE) +  { +  if(n==-1) +  { +  yyerror("Pass2: Constant disappeared!"); +  }else{ + #if 1 +  struct identifier *id; +  id=ID_FROM_INT(new_program,n); +  if(id->func.offset>=0) +  { +  struct pike_string *s; +  struct svalue *c=PROG_FROM_INT(new_program,n)->constants+ +  id->func.offset; +  s=get_type_of_svalue(c); +  free_string(id->type); +  id->type=s; +  } + #endif +  return n; +  } +  } +  + #ifdef DEBUG +  if(new_program->flags & (PROGRAM_FIXED | PROGRAM_OPTIMIZED)) +  fatal("Attempting to add constant to fixed program\n"); + #endif +     copy_shared_string(dummy.name, name);    dummy.type = get_type_of_svalue(c);   
1134:       dummy.func.offset=store_constant(c, 0);    - #ifdef PROFILING -  /* Not strictly necessary, but... */ -  dummy.num_calls = 0; - #endif /* PROFILING */ -  +     ref.id_flags=flags; -  ref.identifier_offset=fake_program.num_identifiers; +  ref.identifier_offset=new_program->num_identifiers;    ref.inherit_offset=0;    -  add_to_mem_block(A_IDENTIFIERS, (char *)&dummy, sizeof dummy); -  fake_program.num_identifiers ++; + #ifdef PROFILEING +  dummy.num_calls=0; + #endif    -  +  add_to_identifiers(dummy); +     if(n != -1)    { -  if (IDENTIFIERP(n)->id_flags & ID_NOMASK) +  if(IDENTIFIERP(n)->id_flags & ID_NOMASK)    my_yyerror("Illegal to redefine 'nomask' identifier \"%s\"", name->str);    -  if(PROG_FROM_INT(& fake_program, n) == &fake_program) +  if(PROG_FROM_INT(new_program, n) == new_program)    my_yyerror("Identifier '%s' defined twice.",name->str);    -  fake_program.identifier_references[n]=ref; +  new_program->identifier_references[n]=ref;    } else { -  n=areas[A_IDENTIFIER_REFERENCES].s.len / sizeof ref; -  add_to_mem_block(A_IDENTIFIER_REFERENCES, (char *)&ref, sizeof ref); -  fake_program.num_identifier_references ++; +  n=new_program->num_identifier_references; +  add_to_identifier_references(ref);    }       return n;
1270:       i=isidentifier(name);    -  setup_fake_program(); +        if(i >= 0)    {    /* already defined */    -  funp=ID_FROM_INT(&fake_program, i); -  ref=fake_program.identifier_references[i]; +  funp=ID_FROM_INT(new_program, i); +  ref=new_program->identifier_references[i];       if(ref.inherit_offset == 0) /* not inherited */    {
1294:    }    }    -  /* it's just another prototype, don't define anything */ -  if(!func || func->offset == -1) return i; -  -  if((ref.id_flags & ID_NOMASK) && -  !(funp->func.offset == -1)) +  if((ref.id_flags & ID_NOMASK) && !(funp->func.offset == -1))    {    my_yyerror("Illegal to redefine 'nomask' function %s.",name->str);    }
1326:    else    fun.func.offset = -1;    - #ifdef PROFILING -  fun.num_calls = 0; - #endif /* PROFILING */ -  -  ref.identifier_offset=fake_program.num_identifiers; -  add_to_mem_block(A_IDENTIFIERS, (char *)&fun, sizeof(fun)); +  ref.identifier_offset=new_program->num_identifiers; +  add_to_identifiers(fun);    }       ref.inherit_offset = 0;    ref.id_flags = flags; -  fake_program.identifier_references[i]=ref; +  new_program->identifier_references[i]=ref;    }else{    /* define it */   
1352:    else    fun.func.offset = -1;    -  i=fake_program.num_identifiers; -  add_to_mem_block(A_IDENTIFIERS, (char *)&fun, sizeof(fun)); +  i=new_program->num_identifiers; + #ifdef PROFILING +  fun.num_calls = 0; + #endif /* PROFILING */    -  +  add_to_identifiers(fun); +     ref.id_flags = flags;    ref.identifier_offset = i;    ref.inherit_offset = 0;    -  i=fake_program.num_identifier_references; -  add_to_mem_block(A_IDENTIFIER_REFERENCES, (char *)&ref, sizeof ref); -  +  i=new_program->num_identifier_references; +  add_to_identifier_references(ref);    }    return i;   }
1371:    * lookup the number of a function in a program given the name in    * a shared_string    */ - static int low_find_shared_string_identifier(struct pike_string *name, + int low_find_shared_string_identifier(struct pike_string *name,    struct program *prog)   {    int max,min,tst;    struct reference *funp;    struct identifier *fun; -  unsigned short *funindex; +     -  funindex = prog->identifier_index; -  if(funindex) +  if(prog->flags & PROGRAM_FIXED)    { -  max = prog->num_identifier_indexes; +  unsigned short *funindex = prog->identifier_index; +  + #ifdef DEBUG +  if(!funindex) +  fatal("No funindex in fixed program\n"); + #endif +  +  max = prog->num_identifier_index;    min = 0;    while(max != min)    {
1401:    funp = prog->identifier_references + i;    if(funp->id_flags & ID_HIDDEN) continue;    fun = ID_FROM_PTR(prog, funp); -  if(fun->func.offset == -1) continue; /* Prototype */ +  /* if(fun->func.offset == -1) continue; * Prototype */    if(!is_same_string(fun->name,name)) continue;    if(funp->id_flags & ID_INHERITED)    {
1448:    struct program *prog)   {   #ifdef FIND_FUNCTION_HASHSIZE -  if(prog!=&fake_program) +  if(prog -> flags & PROGRAM_FIXED)    {    unsigned int hashval;    hashval=my_hash_string(name);
1483:   int store_prog_string(struct pike_string *str)   {    unsigned int i; -  struct pike_string **p; +     -  p = (struct pike_string **)areas[A_STRINGS].s.str; -  -  for (i=0;i<areas[A_STRINGS].s.len / sizeof str;i++) -  if (p[i] == str) +  for (i=0;i<new_program->num_strings;i++) +  if (new_program->strings[i] == str)    return i;       reference_shared_string(str); -  add_to_mem_block(A_STRINGS, (char *)&str, sizeof str); +  add_to_strings(str);    return i;   }      int store_constant(struct svalue *foo, int equal)   { -  struct svalue *s,tmp; +  struct svalue tmp;    unsigned int e; -  s=(struct svalue *)areas[A_CONSTANTS].s.str; +     -  for(e=0;e<areas[A_CONSTANTS].s.len / sizeof(struct svalue);e++) -  if(equal ? is_equal(s+e,foo) : is_eq(s+e,foo)) +  for(e=0;e<new_program->num_constants;e++) +  { +  struct svalue *s=new_program->constants + e; +  if(equal ? is_equal(s,foo) : is_eq(s,foo))    return e; -  +  }       assign_svalue_no_free(&tmp,foo); -  add_to_mem_block(A_CONSTANTS,(char *)&tmp,sizeof(struct svalue)); +  add_to_constants(tmp);    return e;   }   
1536:      void start_line_numbering(void)   { -  if(last_file) { free_string(last_file); last_file=0; } +  if(last_file) +  { +  free_string(last_file); +  last_file=0; +  }    last_pc=last_line=0;   }    - static void insert_small_number(int a,int area) + static void insert_small_number(INT32 a)   {    if(a>-127 && a<127)    { -  ins_byte(a,area); +  add_to_linenumbers(a);    }else if(a>=-32768 && a<32768){ -  ins_signed_byte(-127,area); -  ins_short(a,area); +  add_to_linenumbers(a); +  ins_short(a, add_to_linenumbers);    }else{ -  ins_signed_byte(-128,area); -  ins_int(a,area); +  add_to_linenumbers(-128); +  ins_int(a, add_to_linenumbers);    }   }   
1562:    {    char *tmp;    if(last_file) free_string(last_file); -  ins_byte(127,A_LINENUMBERS); -  for(tmp=current_file->str; *tmp; tmp++) ins_byte(*tmp,A_LINENUMBERS); -  ins_byte(0,A_LINENUMBERS); +  add_to_linenumbers(127); +  for(tmp=current_file->str; *tmp; tmp++) +  add_to_linenumbers(*tmp); +  add_to_linenumbers(0);    copy_shared_string(last_file, current_file);    } -  insert_small_number(PC-last_pc,A_LINENUMBERS); -  insert_small_number(current_line-last_line,A_LINENUMBERS); +  insert_small_number(PC-last_pc); +  insert_small_number(current_line-last_line);    last_line=current_line;    last_pc=PC;    }
1589:    if (prog == 0) return "Unkown program";    offset = pc - prog->program;    -  if(prog == & fake_program) +  if(prog == new_program)    {    linep[0]=0;    return "Optimizer";    }    - #ifdef DEBUG -  if (offset > (INT32)prog->program_size || offset<0) -  fatal("Illegal offset %ld in program.\n", (long)offset); - #endif -  +     cnt=prog->linenumbers;    off=line=0;    file="Line not found"; -  +  if (offset > (INT32)prog->num_program || offset<0) +  return file; +     while(cnt < prog->linenumbers + prog->num_linenumbers)    {    if(*cnt == 127)
1618:    return file;   }    - void my_yyerror(char *fmt,...) + void my_yyerror(char *fmt,...) ATTRIBUTE((format(printf,1,2)))   {    va_list args; -  char buf[1000]; +  char buf[8192];    va_start(args,fmt);    VSPRINTF(buf,fmt,args);   
1632:    va_end(args);   }    - /* -  * Compile an PIKE file. Input is supposed to be initalized already. -  */ - void compile(void) + struct program *compile(struct pike_string *prog)   { -  int yyparse(void); +  struct program *p; +  struct lex save_lex; +  int save_depth=compilation_depth; +  void yyparse(void);    -  start_line_numbering(); +  save_lex=lex;    -  num_parse_error = 0; -  init_node=0; +  lex.end=prog->str+prog->len; +  lex.current_line=1; +  lex.current_file=make_shared_string("-"); +  lex.pragmas=0;    -  yyparse(); /* Parse da program */ - #ifdef DEBUG -  if(recoveries && sp-evaluator_stack < recoveries->sp) -  fatal("Stack error in compilation (underflow after yyparse)\n"); - #endif -  free_all_local_names(); - } +  start_new_program(); +  compilation_depth=0;    - struct program *compile_file(struct pike_string *file_name) - { -  int fd; -  struct program *p; +  start_line_numbering();    -  while(1) -  { -  fd=open(file_name->str,O_RDONLY); -  if(fd >= 0) break; -  if(errno != EINTR) -  { - #ifdef HAVE_STRERROR -  error("Couldn't open file '%s'. (%s)\n",file_name->str,strerror(errno)); - #else -  error("Couldn't open file '%s'. (ERRNO=%d)\n",file_name->str,errno); - #endif -  } -  } +  compiler_pass=1; +  lex.pos=prog->str; +  yyparse(); /* Parse da program */    - #define FILE_STATE - #define PUSH - #include "compilation.h" - #undef PUSH +  p=end_first_pass(0);    -  start_new_file(fd,file_name); -  start_new_program(); -  compile(); +  if(p && !num_parse_error) +  { +  low_start_new_program(p,0,0); +  compiler_pass=2; +  lex.pos=prog->str; +  yyparse(); /* Parse da program again */    p=end_program(); -  end_new_file(); -  - #define POP - #include "compilation.h" - #undef POP - #undef FILE_STATE -  -  if(!p) error("Failed to compile %s.\n",file_name->str); -  return p; +     }    - struct program *compile_string(struct pike_string *prog, -  struct pike_string *name) - { -  struct program *p; +     - #define FILE_STATE - #define PUSH - #include "compilation.h" - #undef PUSH +  free_string(lex.current_file); +  lex=save_lex;    -  start_new_string(prog->str,prog->len,name); -  start_new_program(); -  compile(); -  p=end_program(); -  end_new_file(); +  compilation_depth=save_depth;    - #define POP - #include "compilation.h" - #undef POP - #undef FILE_STATE -  +     if(!p) error("Compilation failed.\n");    return p;   }
1786:   #endif   }    + #ifdef GC2 +    void gc_mark_program_as_referenced(struct program *p)   {    if(gc_mark(p)) -  +  { +  int e;    gc_mark_svalues(p->constants, p->num_constants); -  +  +  for(e=0;e<p->num_inherits;e++) +  { +  if(p->inherits[e].parent) +  gc_mark_object_as_referenced(p->inherits[e].parent); +  +  if(e) +  gc_mark_program_as_referenced(p->inherits[e].prog);    }    -  +  } + } +    void gc_check_all_programs(void)   {    struct program *p;    for(p=first_program;p;p=p->next)    { -  debug_gc_check_svalues(p->constants, p->num_constants, T_PROGRAM, p); +  int e; +  gc_check_svalues(p->constants, p->num_constants);    -  +  for(e=0;e<p->num_inherits;e++) +  { +  if(p->inherits[e].parent) +  {   #ifdef DEBUG -  +  if(gc_check(p->inherits[e].parent)==-2) +  fprintf(stderr,"(program at 0x%lx -> inherit[%d].parent)\n", +  (long)p, +  e); + #else +  gc_check(p->inherits[e].parent); + #endif +  } +  +  if(d_flag && p->inherits[e].name) +  gc_check(p->inherits[e].name); +  +  if(e) +  gc_check(p->inherits[e].prog); +  } +     if(d_flag)    {    int e;
1812: Inside #if defined(DEBUG)
   gc_check(p->identifiers[e].type);    }    } - #endif +     }   }   
1832:    {    if(gc_do_free(p))    { +  int e;    p->refs++;    free_svalues(p->constants, p->num_constants, -1); -  +  for(e=0;e<p->num_inherits;e++) +  { +  if(p->inherits[e].parent) +  { +  free_object(p->inherits[e].parent); +  p->inherits[e].parent=0; +  } +  }    next=p->next;    free_program(p);    }else{
1842:    }   }    + #endif /* GC2 */    -  +    void count_memory_in_programs(INT32 *num_, INT32 *size_)   {    INT32 size=0, num=0;
1855:    *num_=num;    *size_=size;   } - void push_locals(void) +  + void push_compiler_frame(void)   { -  struct locals *l; -  l=ALLOC_STRUCT(locals); -  l->current_type=0; -  l->current_return_type=0; -  l->next=local_variables; -  l->current_number_of_locals=0; -  l->max_number_of_locals=0; -  local_variables=l; +  struct compiler_frame *f; +  f=ALLOC_STRUCT(compiler_frame); +  f->current_type=0; +  f->current_return_type=0; +  f->current_number_of_locals=0; +  f->max_number_of_locals=0; +  f->previous=compiler_frame; +  compiler_frame=f;   }    - void pop_locals(void) + void pop_local_variables(int level)   { -  struct locals *l; -  free_all_local_names(); -  l=local_variables->next; -  if(local_variables->current_type) -  free_string(local_variables->current_type); -  if(local_variables->current_return_type) -  free_string(local_variables->current_return_type); -  free((char *)local_variables); +  while(compiler_frame->current_number_of_locals > level) +  { +  int e; +  e=--(compiler_frame->current_number_of_locals); +  free_string(compiler_frame->variable[e].name); +  free_string(compiler_frame->variable[e].type); +  } + }    -  local_variables=l; -  /* insert check if ( local->next == parent locals ) here */ +  + void pop_compiler_frame(void) + { +  struct compiler_frame *f; +  int e; +  f=compiler_frame; + #ifdef DEBUG +  if(!f) +  fatal("Popping out of compiler frames\n"); + #endif +  +  pop_local_variables(0); +  if(f->current_type) +  free_string(f->current_type); +  +  if(f->current_return_type) +  free_string(f->current_return_type); +  +  compiler_frame=f->previous; +  free((char *)f);   }      
1897:    oid=o->prog->id;    pid=p->id;    hval=oid*9248339 + pid; -  hval %= GET_STORAGE_CACHE_SIZE; +  hval%=GET_STORAGE_CACHE_SIZE;   #ifdef DEBUG    if(hval>GET_STORAGE_CACHE_SIZE)    fatal("hval>GET_STORAGE_CACHE_SIZE");
1926:    if(offset == -1) return 0;    return o->storage + offset;   } +  + struct program *low_program_from_function(struct program *p, +  INT32 i) + { +  struct svalue *f; +  struct identifier *id=ID_FROM_INT(p, i); +  if(!IDENTIFIER_IS_CONSTANT(id->identifier_flags)) return 0; +  if(id->func.offset==-1) return 0; +  f=PROG_FROM_INT(p,i)->constants + id->func.offset; +  if(f->type!=T_PROGRAM) return 0; +  return f->u.program; + } +  + struct program *program_from_function(struct svalue *f) + { +  struct identifier *id; +  if(f->type != T_FUNCTION) return 0; +  if(f->subtype == FUNCTION_BUILTIN) return 0; +  if(!f->u.object->prog) return 0; +  return low_program_from_function(f->u.object->prog, f->subtype); + } +  + struct program *program_from_svalue(struct svalue *s) + { +  switch(s->type) +  { +  case T_FUNCTION: +  return program_from_function(s); +  case T_PROGRAM: +  return s->u.program; +  default: +  return 0; +  } + } +  + #define FIND_CHILD_HASHSIZE 5003 + struct find_child_cache_s + { +  INT32 pid,cid,id; + }; +  + static struct find_child_cache_s find_child_cache[FIND_CHILD_HASHSIZE]; +  + int find_child(struct program *parent, struct program *child) + { +  INT32 h=(parent->id * 9248339 + child->id) % FIND_CHILD_HASHSIZE; +  if(find_child_cache[h].pid == parent->id && +  find_child_cache[h].cid == child->id) +  { +  return find_child_cache[h].id; +  }else{ +  INT32 i; +  for(i=0;i<parent->num_identifier_references;i++) +  { +  if(low_program_from_function(parent, i)==child) +  { +  find_child_cache[h].pid=parent->id; +  find_child_cache[h].cid=child->id; +  find_child_cache[h].id=i; +  return i; +  } +  } +  } +  return -1; + } +  + void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2))) + { +  char buf[4711]; +  va_list args; +  va_start(args,fmt); +  VSPRINTF(buf, fmt, args); +  va_end(args); +  +  if(strlen(buf)>sizeof(buf)) +  fatal("Buffer overfloat in yywarning!\n"); +  +  if(get_master()) +  { +  ref_push_string(lex.current_file); +  push_int(lex.current_line); +  push_text(buf); +  SAFE_APPLY_MASTER("compile_warning",3); +  pop_stack(); +  } + }