e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
aedfb12002-10-09Martin Nilsson 
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h" #include "program.h" #include "object.h" #include "dynamic_buffer.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "pike_types.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "stralloc.h" #include "las.h" #include "lex.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "fsort.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "docode.h" #include "interpret.h" #include "hashtable.h"
2acdd31995-10-29Fredrik Hübinette (Hubbe) #include "main.h"
9173f72002-11-25Martin Stjernholm #include "pike_memory.h"
624d091996-02-24Fredrik Hübinette (Hubbe) #include "gc.h"
07513e1996-10-04Fredrik Hübinette (Hubbe) #include "threads.h"
0683be1997-01-26Fredrik Hübinette (Hubbe) #include "constants.h"
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) #include "operators.h"
3eb19a1998-01-30Henrik Grubbström (Grubba) #include "builtin_functions.h"
1994981998-04-07Fredrik Hübinette (Hubbe) #include "stuff.h"
05590d1998-04-23Fredrik Hübinette (Hubbe) #include "mapping.h" #include "cyclic.h"
51059b1999-12-26Henrik Grubbström (Grubba) #include "pike_types.h"
f76b4c2000-05-11Henrik Grubbström (Grubba) #include "opcodes.h"
ac87152000-09-25Fredrik Hübinette (Hubbe) #include "version.h"
d476592013-06-12Arne Goedeke #include "block_allocator.h"
1c1c5e2001-04-08Fredrik Hübinette (Hubbe) #include "block_alloc.h"
0e0cd72001-07-20Henrik Grubbström (Grubba) #include "pikecode.h"
e021fe2008-04-14Henrik Grubbström (Grubba) #include "pike_compiler.h"
a173002008-04-15Martin Nilsson #include "module_support.h"
8079a42014-01-11Tobias S. Josefowitz #include "bitvector.h"
8aeeb21996-11-19Fredrik Hübinette (Hubbe)  #include <errno.h>
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <fcntl.h>
6ad2372002-05-11Martin Nilsson #define sp Pike_sp
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
8b5b3a2014-04-28Henrik Grubbström (Grubba) #ifdef PIKE_THREADS static COND_T Pike_compiler_cond; static THREAD_T Pike_compiler_thread; static int lock_depth = 0; PMOD_EXPORT void lock_pike_compiler(void) {
1a57432014-05-12Henrik Grubbström (Grubba)  if (lock_depth && (Pike_compiler_thread != th_self())) { SWAP_OUT_CURRENT_THREAD(); while (lock_depth && (Pike_compiler_thread != th_self())) { co_wait_interpreter(&Pike_compiler_cond); } SWAP_IN_CURRENT_THREAD();
8b5b3a2014-04-28Henrik Grubbström (Grubba)  } lock_depth++; Pike_compiler_thread = th_self(); } PMOD_EXPORT void unlock_pike_compiler(void) { #ifdef PIKE_DEBUG if (lock_depth < 1) { Pike_fatal("Pike compiler running unlocked!\n"); } #endif lock_depth--; co_broadcast(&Pike_compiler_cond); } #else PMOD_EXPORT void lock_pike_compiler(void) { } PMOD_EXPORT void unlock_pike_compiler(void) { } #endif
e021fe2008-04-14Henrik Grubbström (Grubba) static void low_enter_compiler(struct object *ce, int inherit);
1c1c5e2001-04-08Fredrik Hübinette (Hubbe) static void exit_program_struct(struct program *);
f3c7152001-04-14Fredrik Hübinette (Hubbe) static size_t add_xstorage(size_t size, size_t alignment, ptrdiff_t modulo_orig);
1c1c5e2001-04-08Fredrik Hübinette (Hubbe) 
d476592013-06-12Arne Goedeke static struct block_allocator program_allocator = BA_INIT_PAGES(sizeof(struct program), 4);
1c1c5e2001-04-08Fredrik Hübinette (Hubbe) 
d476592013-06-12Arne Goedeke ATTRIBUTE((malloc))
3b54e52014-08-21Martin Nilsson struct program * alloc_program(void) {
d476592013-06-12Arne Goedeke  return ba_alloc(&program_allocator); }
1c1c5e2001-04-08Fredrik Hübinette (Hubbe) 
d476592013-06-12Arne Goedeke void really_free_program(struct program * p) { exit_program_struct(p); ba_free(&program_allocator, p); }
1c1c5e2001-04-08Fredrik Hübinette (Hubbe) 
d476592013-06-12Arne Goedeke void count_memory_in_programs(size_t *num, size_t *_size) { size_t size; struct program *p; ba_count_all(&program_allocator, num, &size); for(p=first_program;p;p=p->next) { size+=p->total_size - sizeof (struct program); }
5b472b2013-11-03Arne Goedeke  *_size = size;
d476592013-06-12Arne Goedeke }
3b54e52014-08-21Martin Nilsson void free_all_program_blocks(void) {
d476592013-06-12Arne Goedeke  ba_destroy(&program_allocator); }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
1549c61999-07-02Henrik Grubbström (Grubba) /* #define COMPILER_DEBUG */
a786431999-11-18Martin Stjernholm /* #define PROGRAM_BUILD_DEBUG */
b6f8c31999-07-01Henrik Grubbström (Grubba)  #ifdef COMPILER_DEBUG #define CDFPRINTF(X) fprintf X
9d80342013-08-14Marcus Comstedt #ifndef PIKE_THREADS
8b5b3a2014-04-28Henrik Grubbström (Grubba) /* The CDFPRINTF lines wants to print lock_depth, so fake one of those */ static const int lock_depth = 1;
9d80342013-08-14Marcus Comstedt #endif
b6f8c31999-07-01Henrik Grubbström (Grubba) #else /* !COMPILER_DEBUG */ #define CDFPRINTF(X) #endif /* COMPILER_DEBUG */
189fd01997-01-28Fredrik Hübinette (Hubbe) /*
5985c12000-10-25Fredrik Hübinette (Hubbe)  * These two values should probably be fine-tuned, but doing so * more or less requires running a predictable 'typical' application * and testing different hashsizes and tresholds. I tried to do it * mathematically by measuring the extremes (no cache hits, 100% * cache hits etc.) but it seems that the processor cache becomes * exhausted in some of my measurements, which renders my mathematical * model useless. * * Further measurements seems to indicate that this cache can slow * things down a bit if the hit/miss rate is not fairly high. * For normal applications, the hitrate is most likely well over 90%, * but that should be verified.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  * - Holistiska Centralbyrån (Hubbe)
189fd01997-01-28Fredrik Hübinette (Hubbe)  */
5985c12000-10-25Fredrik Hübinette (Hubbe)  /* Define the size of the cache that is used for method lookup. */ /* A value of zero disables this cache */
b6e4212012-05-21Per Hedbor #define FIND_FUNCTION_HASHSIZE 16384
5985c12000-10-25Fredrik Hübinette (Hubbe)  /* Programs with less methods will not use the cache for method lookups.. */
f1f7e72013-06-12Per Hedbor #define FIND_FUNCTION_HASH_TRESHOLD 0
189fd01997-01-28Fredrik Hübinette (Hubbe) 
5c8e891995-10-29Fredrik Hübinette (Hubbe) #define DECLARE #include "compilation.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
6a22502014-09-30Per Hedbor struct pike_string *this_program_string, *this_string; static struct pike_string *this_function_string;
ebf5bb2004-09-18Per Hedbor static struct pike_string *UNDEFINED_string;
9e26861999-12-31Martin Stjernholm 
94d66b2008-05-24Henrik Grubbström (Grubba) /* Common compiler subsystems */ struct pike_string *parser_system_string; struct pike_string *type_check_system_string;
99682c2014-08-12Per Hedbor /* NOTE: There is a corresponding list to this one in Tools.AutoDoc.PikeObjects If new lfuns are added it might be beneficial to also add them to that list. */
ebf5bb2004-09-18Per Hedbor const char *const lfun_names[] = {
5580691996-06-21Fredrik Hübinette (Hubbe)  "__INIT", "create", "destroy", "`+", "`-", "`&", "`|", "`^", "`<<", "`>>", "`*", "`/", "`%", "`~", "`==", "`<", "`>", "__hash", "cast", "`!",
774b061996-08-03Fredrik Hübinette (Hubbe)  "`[]", "`[]=",
dffa011997-01-15Fredrik Hübinette (Hubbe)  "`->", "`->=",
0683be1997-01-26Fredrik Hübinette (Hubbe)  "_sizeof", "_indices", "_values", "`()",
1b89ad1997-10-10Fredrik Hübinette (Hubbe)  "``+", "``-", "``&", "``|", "``^", "``<<", "``>>", "``*", "``/", "``%",
ee37801999-02-09Fredrik Hübinette (Hubbe)  "`+=",
aa73fc1999-10-21Fredrik Hübinette (Hubbe)  "_is_type", "_sprintf",
2ba9191999-10-23Fredrik Hübinette (Hubbe)  "_equal",
5b74242001-02-05Henrik Grubbström (Grubba)  "_m_delete",
226d642001-02-24Henrik Grubbström (Grubba)  "_get_iterator",
408a1e2004-10-30Martin Stjernholm  "`[..]",
142c802003-09-04Henrik Grubbström (Grubba)  /* NOTE: After this point there are only fake lfuns. */ "_search",
7195af2011-01-15Henrik Grubbström (Grubba)  "_types",
1031362011-01-21Henrik Grubbström (Grubba)  "_serialize", "_deserialize",
a3a0072013-09-18Per Hedbor  "_size_object",
e24c3d2013-11-18Henrik Grubbström (Grubba)  "_random",
5580691996-06-21Fredrik Hübinette (Hubbe) };
286afb2001-02-05Henrik Grubbström (Grubba) struct pike_string *lfun_strings[NELEM(lfun_names)]; static struct mapping *lfun_ids;
51059b1999-12-26Henrik Grubbström (Grubba) /* mapping(string:type) */ static struct mapping *lfun_types;
cae3cb2005-01-20Martin Nilsson static const char *const raw_lfun_types[] = {
51059b1999-12-26Henrik Grubbström (Grubba)  tFuncV(tNone,tVoid,tVoid), /* "__INIT", */ tFuncV(tNone,tZero,tVoid), /* "create", */
09f2882005-02-09Martin Stjernholm  tFuncV(tOr(tVoid,tInt),tVoid,tVoid), /* "destroy", */
f0ace32003-11-10Martin Stjernholm  tFuncV(tZero,tZero,tMix), /* "`+", */ tFunc(tOr(tVoid,tZero),tMix), /* "`-", */
51059b1999-12-26Henrik Grubbström (Grubba)  tFuncV(tNone,tZero,tMix), /* "`&", */ tFuncV(tNone,tZero,tMix), /* "`|", */ tFuncV(tNone,tZero,tMix), /* "`^", */ tFuncV(tZero,tVoid,tMix), /* "`<<", */ tFuncV(tZero,tVoid,tMix), /* "`>>", */ tFuncV(tNone,tZero,tMix), /* "`*", */ tFuncV(tNone,tZero,tMix), /* "`/", */ tFuncV(tNone,tZero,tMix), /* "`%", */ tFuncV(tNone,tVoid,tMix), /* "`~", */ tFuncV(tMix,tVoid,tInt), /* "`==", */ tFuncV(tMix,tVoid,tInt), /* "`<", */ tFuncV(tMix,tVoid,tInt), /* "`>", */ tFuncV(tNone,tVoid,tInt), /* "__hash", */ tFuncV(tString,tVoid,tMix), /* "cast", */ tFuncV(tNone,tVoid,tInt), /* "`!", */ tFuncV(tZero,tVoid,tMix), /* "`[]", */ tFuncV(tZero tSetvar(0,tZero),tVoid,tVar(0)), /* "`[]=", */
4bd5202012-04-29Henrik Grubbström (Grubba)  tFuncV(tStr tOr(tVoid,tObj) tOr(tVoid,tInt),tVoid,tMix), /* "`->", */ tFuncV(tStr tSetvar(0,tZero) tOr(tVoid,tObj) tOr(tVoid,tInt),tVoid,tVar(0)), /* "`->=", */ tFuncV(tOr(tVoid,tObj) tOr(tVoid,tInt),tVoid,tInt), /* "_sizeof", */ tFuncV(tOr(tVoid,tObj) tOr(tVoid,tInt),tVoid,tArray), /* "_indices", */ tFuncV(tOr(tVoid,tObj) tOr(tVoid,tInt),tVoid,tArray), /* "_values", */
51059b1999-12-26Henrik Grubbström (Grubba)  tFuncV(tNone,tZero,tMix), /* "`()", */
f0ace32003-11-10Martin Stjernholm  tFuncV(tZero,tZero,tMix), /* "``+", */ tFuncV(tZero,tVoid,tMix), /* "``-", */
51059b1999-12-26Henrik Grubbström (Grubba)  tFuncV(tNone,tZero,tMix), /* "``&", */ tFuncV(tNone,tZero,tMix), /* "``|", */ tFuncV(tNone,tZero,tMix), /* "``^", */ tFuncV(tZero,tVoid,tMix), /* "``<<", */ tFuncV(tZero,tVoid,tMix), /* "``>>", */ tFuncV(tNone,tZero,tMix), /* "``*", */ tFuncV(tNone,tZero,tMix), /* "``/", */ tFuncV(tNone,tZero,tMix), /* "``%", */
f0ace32003-11-10Martin Stjernholm  tFuncV(tZero,tZero,tMix), /* "`+=", */
51059b1999-12-26Henrik Grubbström (Grubba)  tFuncV(tStr,tVoid,tInt), /* "_is_type", */
d8bfc01999-12-27Henrik Grubbström (Grubba)  tFuncV(tInt tOr(tMap(tStr,tInt),tVoid),tVoid,tStr), /* "_sprintf", */
51059b1999-12-26Henrik Grubbström (Grubba)  tFuncV(tMix,tVoid,tInt), /* "_equal", */
3cd7482001-04-28Martin Stjernholm  tFuncV(tZero,tVoid,tMix), /* "_m_delete", */
ef34d52001-02-24Henrik Grubbström (Grubba)  tFuncV(tNone,tVoid,tObj), /* "_get_iterator", */
408a1e2004-10-30Martin Stjernholm  tFuncV(tZero tRangeBound tZero tRangeBound, tVoid, tMix), /* "`[..]" */
142c802003-09-04Henrik Grubbström (Grubba)  /* NOTE: After this point there are only fake lfuns. */ tFuncV(tZero tOr(tZero, tVoid), tVoid, tMix), /* "_search", */
7195af2011-01-15Henrik Grubbström (Grubba)  tFuncV(tNone,tVoid,tArray), /* "_types", */
1031362011-01-21Henrik Grubbström (Grubba)  tFuncV(tObj tZero, tVoid, tVoid), /* "_serialize", */ tFuncV(tObj tZero, tVoid, tVoid), /* "_deserialize", */
a3a0072013-09-18Per Hedbor  tFuncV(tZero, tVoid, tInt), /* "_size_object", */
e24c3d2013-11-18Henrik Grubbström (Grubba)  tFuncV(tNone, tVoid, tMix), /* "_random", */
51059b1999-12-26Henrik Grubbström (Grubba) };
6fa59e2006-10-27Henrik Grubbström (Grubba) /* These two are not true LFUNs! */ static struct pike_type *lfun_getter_type_string = NULL; static struct pike_type *lfun_setter_type_string = NULL;
47251d2002-12-11Henrik Grubbström (Grubba) /*! @namespace lfun::
dd2c602002-12-20Henrik Grubbström (Grubba)  *! *! Callback functions used to overload various builtin functions. *! *! The functions can be grouped into a few sets: *! *! @ul *! @item *! Object initialization and destruction. *! *! @[__INIT()], @[create()], @[destroy()] *! *! @item *! Unary operator overloading. *! *! @[`~()], @[`!()], *! @[_values()], @[cast()], *! @[_sizeof()], @[_indices()], *! @[__hash()] *! *! @item
dfceb02003-11-10Martin Stjernholm  *! Binary asymmetric operator overloading.
dd2c602002-12-20Henrik Grubbström (Grubba)  *! *! @[`+()], @[``+()], *! @[`-()], @[``-()], *! @[`&()], @[``&()], *! @[`|()], @[``|()], *! @[`^()], @[``^()], *! @[`<<()], @[``<<()], *! @[`>>()], @[``>>()], *! @[`*()], @[``*()], *! @[`/()], @[``/()], *! @[`%()], @[``%()] *! *! @item
dfceb02003-11-10Martin Stjernholm  *! Binary symmetric operator overloading.
dd2c602002-12-20Henrik Grubbström (Grubba)  *! *! The optimizer will make assumptions about the relations *! between these functions. *! *! @[`==()], @[_equal()], @[`<()], @[`>()] *! *! @item *! Other binary operator overloading. *! *! @[`[]()], @[`[]=()], @[`->()], *! @[`->=()], @[`+=()], @[`()()] *! *! @item *! Overloading of other builtin functions. *! *! @[_is_type()], @[_sprintf()], @[_m_delete()],
142c802003-09-04Henrik Grubbström (Grubba)  *! @[_get_iterator()], @[_search()]
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @endul *! *! @note
9779872008-06-28Martin Stjernholm  *! Although these functions are called from outside the object they *! exist in, they will still be used even if they are declared *! @expr{protected@}. It is in fact recommended to declare them *! @expr{protected@}, since that will hinder them being used for *! other purposes.
dd2c602002-12-20Henrik Grubbström (Grubba)  *! *! @seealso *! @[::]
397e7d2001-10-28Martin Nilsson  */
1a5b2f2001-02-09Henrik Grubbström (Grubba) /*! @decl void lfun::__INIT() *!
dfceb02003-11-10Martin Stjernholm  *! Inherit and variable initialization. *! *! This function is generated automatically by the compiler. It's *! called just before @[lfun::create()] when an object is *! instantiated. *! *! It first calls any @expr{__INIT@} functions in inherited classes *! (regardless of modifiers on the inherits). It then executes all *! the variable initialization expressions in this class, in the *! order they occur.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @note
dfceb02003-11-10Martin Stjernholm  *! This function can not be overloaded or blocked from executing.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso *! @[lfun::create()] */ /*! @decl void lfun::create(zero ... args) *!
83c2612001-05-05Henrik Grubbström (Grubba)  *! Object creation callback. *! *! This function is called right after @[lfun::__INIT()]. *!
dfceb02003-11-10Martin Stjernholm  *! @[args] are the arguments passed when the program was called.
269dd92001-05-23Henrik Grubbström (Grubba)  *! *! @note
e1aec82014-11-15Stephen R. van den Berg  *! This function can be created implicitly *! by the compiler using the syntax:
f79bd82003-04-01Martin Nilsson  *! @code *! class Foo(int foo) { *! int bar; *! } *! @endcode
dfceb02003-11-10Martin Stjernholm  *! In the above case an implicit @[lfun::create()] is created, and *! it's equvivalent to:
f79bd82003-04-01Martin Nilsson  *! @code *! class Foo { *! int foo; *! int bar;
9779872008-06-28Martin Stjernholm  *! protected void create(int foo)
f79bd82003-04-01Martin Nilsson  *! { *! local::foo = foo; *! } *! } *! @endcode
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso *! @[lfun::__INIT()], @[lfun::destroy()] */
09f2882005-02-09Martin Stjernholm /*! @decl void lfun::destroy (void|int reason)
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
83c2612001-05-05Henrik Grubbström (Grubba)  *! Object destruction callback. *!
09f2882005-02-09Martin Stjernholm  *! This function is called right before the object is destructed. *! That can happen either through a call to @[predef::destruct()], *! when there are no more references to the object, or when the *! garbage collector discovers that it's part of a cyclic data *! structure that has become garbage. *! *! @param reason *! A flag that tells why the object is destructed: *! *! @int *! @value Object.DESTRUCT_EXPLICIT *! Destructed explicitly by @[predef::destruct]. *! @value Object.DESTRUCT_NO_REFS *! Destructed due to running out of references. *! @value Object.DESTRUCT_GC *! Destructed by the garbage collector. *! @value Object.DESTRUCT_CLEANUP
e7634f2007-05-13Martin Stjernholm  *! Destructed as part of the cleanup when the pike process *! exits. Occurs only if Pike has been compiled with the *! configure option @tt{--with-cleanup-on-exit@}. See note *! below.
09f2882005-02-09Martin Stjernholm  *! @endint
dfceb02003-11-10Martin Stjernholm  *! *! @note
e7634f2007-05-13Martin Stjernholm  *! Objects are normally not destructed when a process exits, so *! @expr{destroy@} functions aren't called then. Use @[atexit] to get *! called when the process exits. *! *! @note
dfceb02003-11-10Martin Stjernholm  *! Regarding destruction order during garbage collection: *! *! If an object is destructed by the garbage collector, it's part of *! a reference cycle with other things but with no external *! references. If there are other objects with @expr{destroy@} *! functions in the same cycle, it becomes a problem which to call *! first. *! *! E.g. if this object has a variable with another object which *! (directly or indirectly) points back to this one, you might find *! that the other object already has been destructed and the variable *! thus contains zero. *! *! The garbage collector tries to minimize such problems by defining *! an order as far as possible: *! *! @ul *! @item *! If an object A contains an @[lfun::destroy] and an object B does *! not, then A is destructed before B. *! @item *! If A references B single way, then A is destructed before B. *! @item *! If A and B are in a cycle, and there is a reference somewhere *! from B to A that is weaker than any reference from A to B, then *! A is destructed before B. *! @item
e7634f2007-05-13Martin Stjernholm  *! If a cycle is resolved according to the rule above by ignoring a *! weaker reference, and there is another ambiguous cycle that *! would get resolved by ignoring the same reference, then the *! latter cycle will be resolved by ignoring that reference. *! @item *! Weak references (e.g. set with @[predef::set_weak_flag()]) are *! considered weaker than normal references, and both are *! considered weaker than strong references.
dfceb02003-11-10Martin Stjernholm  *! @item *! Strong references are those from objects to the objects of their *! lexically surrounding classes. There can never be a cycle *! consisting only of strong references. (This means the gc never *! destructs a parent object before all children have been *! destructed.) *! @endul *! *! An example with well defined destruct order due to strong *! references: *! *! @code *! class Super { *! class Sub {
9779872008-06-28Martin Stjernholm  *! protected void destroy() {
dfceb02003-11-10Martin Stjernholm  *! if (!Super::this) *! error ("My parent has been destructed!\n"); *! } *! } *! Sub sub = Sub();
9779872008-06-28Martin Stjernholm  *! protected void destroy() {
dfceb02003-11-10Martin Stjernholm  *! if (!sub) *! werror ("sub already destructed.\n"); *! } *! } *! @endcode *! *! The garbage collector ensures that these objects are destructed in *! an order so that @expr{werror@} in @expr{Super@} is called and not *! @expr{error@} in @expr{Sub@}. *! *! @note *! When the garbage collector calls @[lfun::destroy], all accessible *! non-objects and objects without @expr{destroy@} functions are *! still intact. They are not freed if the @expr{destroy@} function *! adds external references to them. However, all objects with *! @[lfun::destroy] in the cycle are already scheduled for
09f2882005-02-09Martin Stjernholm  *! destruction and will therefore be destroyed even if external *! references are added to them.
dfceb02003-11-10Martin Stjernholm  *!
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[lfun::create()], @[predef::destruct()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
f0ace32003-11-10Martin Stjernholm /*! @decl mixed lfun::`+(zero arg, zero ... rest)
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
dfceb02003-11-10Martin Stjernholm  *! Left side addition/concatenation callback. *! *! This is used by @[predef::`+]. It's called with any arguments *! that follow this object in the argument list of the call to *! @[predef::`+]. The returned value should be a new instance that *! represents the addition/concatenation between this object and *! the arguments in the order they are given. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
5d91362003-04-18Martin Stjernholm  *! @[lfun::``+()], @[lfun::`+=()], @[predef::`+()] */
f0ace32003-11-10Martin Stjernholm /*! @decl this_program lfun::`+=(zero arg, zero ... rest)
5d91362003-04-18Martin Stjernholm  *!
dfceb02003-11-10Martin Stjernholm  *! Destructive addition/concatenation callback. *! *! This is used by @[predef::`+]. It's called with any arguments *! that follow this object in the argument list of the call to *! @[predef::`+]. It should update this object to represent the *! addition/concatenation between it and the arguments in the order *! they are given. It should always return this object.
5d91362003-04-18Martin Stjernholm  *! *! @note *! This function should only be implemented if @[lfun::`+()] also *! is. It should only work as a more optimized alternative to that *! one, for the case when it's safe to change the object
dfceb02003-11-10Martin Stjernholm  *! destructively and use it directly as the result.
5d91362003-04-18Martin Stjernholm  *! *! @note *! This function is not an lfun for the @expr{+=@} operator. It's
dfceb02003-11-10Martin Stjernholm  *! only whether or not it's safe to do a destructive change that *! decides if this function or @[lfun::`+()] is called; both the
5d91362003-04-18Martin Stjernholm  *! @expr{+@} operator and the @expr{+=@} operator can call either *! one. *! *! @seealso *! @[lfun::`+()], @[predef::`+()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
f0ace32003-11-10Martin Stjernholm /*! @decl mixed lfun::``+(zero arg, zero ... rest)
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
dfceb02003-11-10Martin Stjernholm  *! Right side addition/concatenation callback. *! *! This is used by @[predef::`+]. It's called with any arguments
09f2882005-02-09Martin Stjernholm  *! that precede this object in the argument list of the call to
dfceb02003-11-10Martin Stjernholm  *! @[predef::`+]. The returned value should be a new instance that *! represents the addition/concatenation between the arguments in *! the order they are given and this object. *! *! @note *! It's assumed that this function is side-effect free. *! *! @seealso *! @[lfun::`+()], @[predef::`+()] */ /*! @decl mixed lfun::`-(void|zero arg) *! *! Negation and left side subtraction/set difference callback. *! *! This is used by @[predef::`-]. When called without an argument *! the result should be a new instance that represents the negation *! of this object, otherwise the result should be a new instance *! that represents the difference between this object and @[arg]. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[lfun::``-()], @[predef::`-()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
dfceb02003-11-10Martin Stjernholm /*! @decl mixed lfun::``-(zero arg) *! *! Right side subtraction/set difference callback. *! *! This is used by @[predef::`-]. The result should be a new *! instance that represents the difference between @[arg] and this *! object. *! *! @note *! It's assumed that this function is side-effect free. *! *! @seealso *! @[lfun::`-()], @[predef::`-()] */
1a5b2f2001-02-09Henrik Grubbström (Grubba) /*! @decl mixed lfun::`&(zero ... args) *!
dfceb02003-11-10Martin Stjernholm  *! Left side bitwise and/intersection callback. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[lfun::``&()], @[predef::`&()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
dfceb02003-11-10Martin Stjernholm /*! @decl mixed lfun::``&(zero ... args) *! *! Right side bitwise and/intersection callback. *! *! @note *! It's assumed that this function is side-effect free. *! *! @seealso *! @[lfun::`&()], @[predef::`&()] */
1a5b2f2001-02-09Henrik Grubbström (Grubba) /*! @decl mixed lfun::`|(zero ... args) *!
dfceb02003-11-10Martin Stjernholm  *! Left side bitwise or/union callback. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[lfun::``|()], @[predef::`|()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
dfceb02003-11-10Martin Stjernholm /*! @decl mixed lfun::``|(zero ... args) *! *! Right side bitwise or/union callback. *! *! @note *! It's assumed that this function is side-effect free. *! *! @seealso *! @[lfun::`|()], @[predef::`|()] */
1a5b2f2001-02-09Henrik Grubbström (Grubba) /*! @decl mixed lfun::`^(zero ... args) *!
dfceb02003-11-10Martin Stjernholm  *! Left side exclusive or callback. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[lfun::``^()], @[predef::`^()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
dfceb02003-11-10Martin Stjernholm /*! @decl mixed lfun::``^(zero ... args) *! *! Right side exclusive or callback. *! *! @note *! It's assumed that this function is side-effect free. *! *! @seealso *! @[lfun::`^()], @[predef::`^()] */
1a5b2f2001-02-09Henrik Grubbström (Grubba) /*! @decl mixed lfun::`<<(zero arg) *!
dfceb02003-11-10Martin Stjernholm  *! Left side left shift callback. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[lfun::``<<()], @[predef::`<<()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
dfceb02003-11-10Martin Stjernholm /*! @decl mixed lfun::``<<(zero arg) *! *! Right side left shift callback. *! *! @note *! It's assumed that this function is side-effect free. *! *! @seealso *! @[lfun::`<<()], @[predef::`<<()] */
1a5b2f2001-02-09Henrik Grubbström (Grubba) /*! @decl mixed lfun::`>>(zero arg) *!
dfceb02003-11-10Martin Stjernholm  *! Left side right shift callback. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[lfun::``>>()], @[predef::`>>()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
dfceb02003-11-10Martin Stjernholm /*! @decl mixed lfun::``>>(zero arg) *! *! Right side right shift callback. *! *! @note *! It's assumed that this function is side-effect free. *! *! @seealso *! @[lfun::`>>()], @[predef::`>>()] */
1a5b2f2001-02-09Henrik Grubbström (Grubba) /*! @decl mixed lfun::`*(zero ... args) *!
dfceb02003-11-10Martin Stjernholm  *! Left side multiplication/repetition/implosion callback. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[lfun::``*()], @[predef::`*()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
dfceb02003-11-10Martin Stjernholm /*! @decl mixed lfun::``*(zero ... args) *! *! Right side multiplication/repetition/implosion callback. *! *! @note *! It's assumed that this function is side-effect free. *! *! @seealso *! @[lfun::`*()], @[predef::`*()] */
1a5b2f2001-02-09Henrik Grubbström (Grubba) /*! @decl mixed lfun::`/(zero ... args) *!
dfceb02003-11-10Martin Stjernholm  *! Left side division/split callback. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[lfun::``/()], @[predef::`/()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
dfceb02003-11-10Martin Stjernholm /*! @decl mixed lfun::``/(zero ... args) *! *! Right side division/split callback. *! *! @note *! It's assumed that this function is side-effect free. *! *! @seealso *! @[lfun::`/()], @[predef::`/()] */
1a5b2f2001-02-09Henrik Grubbström (Grubba) /*! @decl mixed lfun::`%(zero ... args) *!
dfceb02003-11-10Martin Stjernholm  *! Left side modulo callback. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[lfun::``%()], @[predef::`%()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
dfceb02003-11-10Martin Stjernholm /*! @decl mixed lfun::``%(zero ... args) *! *! Right side modulo callback. *! *! @note *! It's assumed that this function is side-effect free. *! *! @seealso *! @[lfun::`%()], @[predef::`%()] */ /*! @decl int lfun::`!() *! *! Logical not callback. *! *! @returns *! Returns non-zero if the object should be evaluated as false, *! and @expr{0@} (zero) otherwise. *! *! @note *! It's assumed that this function is side-effect free. *! *! @seealso *! @[predef::`!()] */
1a5b2f2001-02-09Henrik Grubbström (Grubba) /*! @decl mixed lfun::`~() *!
dfceb02003-11-10Martin Stjernholm  *! Complement/inversion callback. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[predef::`~()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */ /*! @decl int(0..1) lfun::`==(mixed arg) *!
ebe4bc2015-03-13Henrik Grubbström (Grubba)  *! Equivalence test callback. *! *! @returns *! Is expected to return @expr{1@} if the current object is *! equivalent to @[arg] (ie may be replaced with @[arg], with *! no semantic differences (disregarding the effects of @[destruct()])), *! and @expr{0@} (zero) otherwise.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
779ae12003-04-28Martin Stjernholm  *! @note
ebe4bc2015-03-13Henrik Grubbström (Grubba)  *! If this is implemented it may be necessary to implement *! @[lfun::__hash] too. Otherwise mappings may hold several
779ae12003-04-28Martin Stjernholm  *! objects as indices which are duplicates according to this
ebe4bc2015-03-13Henrik Grubbström (Grubba)  *! function. This may also affect various other functions *! that use hashing internally, e.g. @[predef::Array.uniq].
779ae12003-04-28Martin Stjernholm  *!
dfceb02003-11-10Martin Stjernholm  *! @note *! It's assumed that this function is side-effect free. *!
ebe4bc2015-03-13Henrik Grubbström (Grubba)  *! @note *! It's recommended to only implement this function for *! immutable objects, as otherwise stuff may get confusing *! when things that once were equivalent no longer are so, *! or the reverse. *!
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! @seealso
779ae12003-04-28Martin Stjernholm  *! @[predef::`==()], @[lfun::__hash]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */ /*! @decl int(0..1) lfun::`<(mixed arg) *!
dfceb02003-11-10Martin Stjernholm  *! Less than test callback. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[predef::`<()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */ /*! @decl int(0..1) lfun::`>(mixed arg) *!
dfceb02003-11-10Martin Stjernholm  *! Greater than test callback. *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[predef::`>()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */ /*! @decl int lfun::__hash() *!
83c2612001-05-05Henrik Grubbström (Grubba)  *! Hashing callback.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
e751c42010-05-19Henrik Grubbström (Grubba)  *! The main caller of this function is @[predef::hash_value()] *! or the low-level equvivalent, which get called by various *! mapping operations when the object is used as index in a mapping. *! *! @returns *! It should return an integer that corresponds to the object *! in such a way that all values which @[lfun::`==] considers *! equal to the object get the same hash value.
779ae12003-04-28Martin Stjernholm  *! *! @note *! The function @[predef::hash] does not return hash values that *! are compatible with this one. *!
dfceb02003-11-10Martin Stjernholm  *! @note *! It's assumed that this function is side-effect free. *!
779ae12003-04-28Martin Stjernholm  *! @seealso
e751c42010-05-19Henrik Grubbström (Grubba)  *! @[lfun::`==], @[predef::hash_value()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */ /*! @decl mixed lfun::cast(string requested_type) *!
dfceb02003-11-10Martin Stjernholm  *! Value cast callback.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
f60f892001-12-20Henrik Grubbström (Grubba)  *! @param requested_type *! Type to cast to. *! *! @returns *! Expected to return the object value-casted (converted) to *! the type described by @[requested_type]. *!
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! @note
3173842001-12-20Martin Nilsson  *! The argument is currently a string with the name
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! of the type, but might in the future be a value of the type type.
f60f892001-12-20Henrik Grubbström (Grubba)  *! *! @note
3173842001-12-20Martin Nilsson  *! Currently casting between object types is a noop.
f60f892001-12-20Henrik Grubbström (Grubba)  *! *! @note *! If the returned value is not deemed to be of the requested type *! a runtime error may be thrown. *!
dfceb02003-11-10Martin Stjernholm  *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */ /*! @decl mixed lfun::`[](zero arg1, zero|void arg2) *!
408a1e2004-10-30Martin Stjernholm  *! Indexing callback. *! *! For compatibility, this is also called to do subranges unless *! there is a @[`[..]] in the class. See @[predef::`[..]] for *! details.
dfceb02003-11-10Martin Stjernholm  *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
408a1e2004-10-30Martin Stjernholm  *! @[predef::`[]()], @[predef::`[..]]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */ /*! @decl mixed lfun::`[]=(zero arg1, zero arg2) *!
dfceb02003-11-10Martin Stjernholm  *! Index assignment callback.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[predef::`[]=()], @[lfun::`->=()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
4df6202013-11-16Henrik Grubbström (Grubba) /*! @decl mixed lfun::`->(string index, object|void context, int|void access)
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
dfceb02003-11-10Martin Stjernholm  *! Arrow index callback. *!
4df6202013-11-16Henrik Grubbström (Grubba)  *! @param index *! Symbol in @[context] to access. *! *! @param context *! Context in the current object to start the search from. *! If @expr{UNDEFINED@} or left out, @expr{this_program::this@} *! is to be be used (ie start at the current context and ignore *! any overloaded symbols). *! *! @param access *! Access permission override. One of the following: *! @int *! @value 0 *! @value UNDEFINED *! See only public symbols. *! @value 1 *! See protected symbols as well. *! @endint *! *! @returns *! Returns the value at @[index] if it exists, and *! @expr{UNDEFINED@} otherwise. *!
dfceb02003-11-10Martin Stjernholm  *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
4bd5202012-04-29Henrik Grubbström (Grubba)  *! @[predef::`->()], @[::`->()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
4df6202013-11-16Henrik Grubbström (Grubba) /*! @decl mixed lfun::`->=(string index, zero value, @
4bd5202012-04-29Henrik Grubbström (Grubba)  *! object|void context, int|void access)
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
dfceb02003-11-10Martin Stjernholm  *! Arrow index assignment callback.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
4df6202013-11-16Henrik Grubbström (Grubba)  *! @param index *! Symbol in @[context] to change the value of. *! *! @param value *! The new value. *! *! @param context *! Context in the current object to start the search from. *! If @expr{UNDEFINED@} or left out, @expr{this_program::this@} *! is to be used (ie start at the current context and ignore *! any overloaded symbols). *! *! @param access *! Access permission override. One of the following: *! @int *! @value 0 *! @value UNDEFINED *! See only public symbols. *! @value 1 *! See protected symbols as well. *! @endint *! *! This function is to index the current object with the string @[index], *! and set it to @[value]. *! *! @returns *! Returns the set @[value]. *!
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! @seealso
4bd5202012-04-29Henrik Grubbström (Grubba)  *! @[predef::`->=()], @[::`->=()], @[lfun::`[]=()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
5d086e2001-05-05Henrik Grubbström (Grubba) /*! @decl int lfun::_sizeof()
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
dfceb02003-11-10Martin Stjernholm  *! Size query callback.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
eaf0892003-11-20Henrik Grubbström (Grubba)  *! Called by @[predef::sizeof()] to determine the number of elements
f60f892001-12-20Henrik Grubbström (Grubba)  *! in an object. If this function is not present, the number *! of public symbols in the object will be returned. *! *! @returns *! Expected to return the number of valid indices in the object. *!
dfceb02003-11-10Martin Stjernholm  *! @note *! It's assumed that this function is side-effect free. *!
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[predef::sizeof()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
4bd5202012-04-29Henrik Grubbström (Grubba) /*! @decl array lfun::_indices(object|void context, int|void access)
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
dfceb02003-11-10Martin Stjernholm  *! List indices callback.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
f60f892001-12-20Henrik Grubbström (Grubba)  *! @returns *! Expected to return an array with the valid indices in the object. *!
dfceb02003-11-10Martin Stjernholm  *! @note *! It's assumed that this function is side-effect free. *!
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! @seealso
7195af2011-01-15Henrik Grubbström (Grubba)  *! @[predef::indices()], @[lfun::_values()], @[lfun::_types()], *! @[::_indices()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
4bd5202012-04-29Henrik Grubbström (Grubba) /*! @decl array lfun::_values(object|void context, int|void access)
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
dfceb02003-11-10Martin Stjernholm  *! List values callback.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
f60f892001-12-20Henrik Grubbström (Grubba)  *! @returns *! Expected to return an array with the values corresponding to *! the indices returned by @[lfun::_indices()]. *!
dfceb02003-11-10Martin Stjernholm  *! @note *! It's assumed that this function is side-effect free. *!
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! @seealso
7195af2011-01-15Henrik Grubbström (Grubba)  *! @[predef::values()], @[lfun::_indices()], @[lfun::_types()], *! @[::_values()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
5d086e2001-05-05Henrik Grubbström (Grubba) /*! @decl mixed lfun::`()(zero ... args)
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
dfceb02003-11-10Martin Stjernholm  *! Apply callback.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[predef::`()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
f60f892001-12-20Henrik Grubbström (Grubba) /*! @decl int(0..1) lfun::_is_type(string basic_type)
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
83c2612001-05-05Henrik Grubbström (Grubba)  *! Type comparison callback.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
f60f892001-12-20Henrik Grubbström (Grubba)  *! Called by the cast operator to determine if an object *! simulates a basic type. *! *! @param basic_type *! One of: *! @string *! @value "array" *! @value "float" *! @value "function" *! @value "int" *! @value "mapping" *! @value "multiset" *! @value "object" *! @value "program" *! @value "string" *! @value "type" *! @value "void" *! @value "zero" *! @endstring *! *! The following five shouldn't occurr, but are here for completeness: *! @string *! @value "lvalue" *! @value "mapping_data" *! @value "object storage" *! @value "pike_frame" *! @value "unknown" *! @endstring *! *! @returns
cbe8c92003-04-07Martin Nilsson  *! Expected to return @expr{1@} if the object is to be regarded as a
3173842001-12-20Martin Nilsson  *! simulation of the type specified by @[basic_type].
f60f892001-12-20Henrik Grubbström (Grubba)  *!
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! @note
3173842001-12-20Martin Nilsson  *! The argument is currently a string with the name
f60f892001-12-20Henrik Grubbström (Grubba)  *! of the type, but might in the future be a value of the type type.
dfceb02003-11-10Martin Stjernholm  *! *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
8203d42001-02-09Henrik Grubbström (Grubba) /*! @decl string lfun::_sprintf(int conversion_type, @ *! mapping(string:int)|void params)
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
83c2612001-05-05Henrik Grubbström (Grubba)  *! Sprintf callback.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
14230c2003-01-03Henrik Grubbström (Grubba)  *! This method is called by @[predef::sprintf()] to print objects. If it is
302b712001-12-20Henrik Grubbström (Grubba)  *! not present, printing of the object will not be supported for any
b772752001-12-20Henrik Grubbström (Grubba)  *! conversion-type except for the @tt{%O@}-conversion-type, which
cbe8c92003-04-07Martin Nilsson  *! will output @expr{"object"@}.
b772752001-12-20Henrik Grubbström (Grubba)  *! *! @param conversion_type *! One of: *! @int *! @value 'b' *! Signed binary integer. *! @value 'd' *! Signed decimal integer. *! @value 'u' *! Unsigned decimal integer. *! @value 'o' *! Signed octal integer. *! @value 'x' *! Lowercase signed hexadecimal integer. *! @value 'X' *! Uppercase signed hexadecimal integer. *! @value 'c' *! Character. If a fieldsize has been specified this will output *! the low-order bytes of the integer in network byte order. *! @value 'f' *! Float. *! @value 'g' *! Heuristically chosen representation of float. *! @value 'G' *! Like @tt{%g@}, but uses uppercase @tt{E@} for exponent. *! @value 'e' *! Exponential notation float. *! @value 'E' *! Like @tt{%e@}, but uses uppercase @tt{E@} for exponent. *! @value 's' *! String. *! @value 'O' *! Any value (debug style). *! @value 't' *! Type of the argument. *! @endint *! *! @param params *! Conversion parameters. The following parameters may be supplied: *! @mapping *! @member int "precision" *! Precision. *! @member int "width" *! Field width. *! @member int(1..1) "flag_left" *! Indicates that the output should be left-aligned. *! @member int "indent" *! Indentation level in @tt{%O@}-mode. *! @endmapping *! *! @returns *! Is expected to return a string describing the object formatted *! according to @[conversion_type]. *! *! @note
3173842001-12-20Martin Nilsson  *! @[_sprintf()] is currently not called for the following
b772752001-12-20Henrik Grubbström (Grubba)  *! conversion-types: *! @int *! @value 'F' *! Binary IEEE representation of float (@tt{%4F@} gives *! single precision, @tt{%8F@} gives double precision.) *! @endint *!
dfceb02003-11-10Martin Stjernholm  *! @note *! This function might be called at odd times, e.g. before *! @[lfun::create] has been called or when an error has occurred. *! The reason is typically that it gets called when a backtrace is *! being formatted to report an error. It should therefore be very *! robust and not make any assumptions about its own internal *! state, at least not when @[conversion_type] is @expr{'O'@}. *! *! @note *! It's assumed that this function is side-effect free. *!
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[predef::sprintf()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
8203d42001-02-09Henrik Grubbström (Grubba) /*! @decl int lfun::_equal(mixed arg)
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
dfceb02003-11-10Martin Stjernholm  *! Recursive equality callback. *!
ebe4bc2015-03-13Henrik Grubbström (Grubba)  *! @returns *! Is expected to return @expr{1@} if the current object is *! equal to @[arg], and @expr{0@} (zero) otherwise. *!
dfceb02003-11-10Martin Stjernholm  *! @note *! It's assumed that this function is side-effect free.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
ebe4bc2015-03-13Henrik Grubbström (Grubba)  *! @note *! Note that this function may return different values at different *! times for the same argument due to the mutability of the object. *!
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[predef::equal()], @[lfun::`==()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
8203d42001-02-09Henrik Grubbström (Grubba) /*! @decl mixed lfun::_m_delete(mixed arg)
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *!
dfceb02003-11-10Martin Stjernholm  *! Delete index callback.
1a5b2f2001-02-09Henrik Grubbström (Grubba)  *! *! @seealso
dd2c602002-12-20Henrik Grubbström (Grubba)  *! @[predef::m_delete()]
1a5b2f2001-02-09Henrik Grubbström (Grubba)  */
eaf0892003-11-20Henrik Grubbström (Grubba) /*! @decl predef::Iterator lfun::_get_iterator()
226d642001-02-24Henrik Grubbström (Grubba)  *!
dfceb02003-11-10Martin Stjernholm  *! Iterator creation callback. *!
eaf0892003-11-20Henrik Grubbström (Grubba)  *! The returned @[predef::Iterator] instance works as a cursor that
dfceb02003-11-10Martin Stjernholm  *! references a specific item contained (in some arbitrary sense) *! in this one. *! *! @note *! It's assumed that this function is side-effect free.
83c2612001-05-05Henrik Grubbström (Grubba)  *!
c4131e2003-04-18Martin Stjernholm  *! @seealso
eaf0892003-11-20Henrik Grubbström (Grubba)  *! @[predef::Iterator], @[predef::get_iterator], @[predef::foreach()]
226d642001-02-24Henrik Grubbström (Grubba)  */
abb3e42013-11-18Henrik Grubbström (Grubba) /*! @decl mixed lfun::`[..](zero low, int low_bound_type, @ *! zero high, int high_bound_type) *! *! Subrange callback. *! *! @note *! It's assumed that this function is side-effect free. *! *! @seealso *! @[predef::`[..]] */ /**** END TRUE LFUNS ****/ /**** BEGIN FAKE LFUNS ****/
142c802003-09-04Henrik Grubbström (Grubba) /*! @decl mixed lfun::_search(mixed needle, mixed|void start) *! *! Search callback. *! *! @seealso *! @[predef::search()] */
4bd5202012-04-29Henrik Grubbström (Grubba) /*! @decl array lfun::_types(object|void context, int|void access)
7195af2011-01-15Henrik Grubbström (Grubba)  *! *! List types callback. *! *! This callback is typically called via @[predef::types()]. *! *! @returns *! Expected to return an array with the types corresponding to *! the indices returned by @[lfun::_indices()]. *! *! @note *! It's assumed that this function is side-effect free. *! *! @note *! @[predef::types()] was added in Pike 7.9. *! *! @seealso *! @[predef::types()], @[lfun::_indices()], @[lfun::_values()], *! @[::_types()] */
1031362011-01-21Henrik Grubbström (Grubba) /*! @decl void lfun::_serialize(object o, @
9cded82011-02-04Henrik Grubbström (Grubba)  *! function(mixed, string, type:void) serializer)
1031362011-01-21Henrik Grubbström (Grubba)  *! *! Dispatch function for @[Serializer.serialize()]. *! *! @param o *! Object to serialize. Always a context of the current object. *! *! @param serializer *! Function to be called once for every variable *! to serialize. *! *! The @[serializer] function expects to be called with three arguments: *! @dl *! @item
9cded82011-02-04Henrik Grubbström (Grubba)  *! @tt{value@} - The value of the symbol. *! @item
1031362011-01-21Henrik Grubbström (Grubba)  *! @tt{symbol@} - The symbol name. *! @item *! @tt{symbol_type@} - The type of the symbol. *! @enddl *! *! @note *! A default implementation of @[lfun::_serialize()] and *! @[lfun::_deserialize()] is available in @[Serializer.Serializable]. *! *! @seealso *! @[lfun::_deserialize()], @[Serializer.serialize()], *! @[Serializer.Serializable()->_serialize()] */ /*! @decl void lfun::_deserialize(object o, @
9cded82011-02-04Henrik Grubbström (Grubba)  *! function(function(mixed:void), @ *! string, type: mixed) deserializer)
1031362011-01-21Henrik Grubbström (Grubba)  *! *! Dispatch function for @[Serialization.deserialize()]. *! *! @param o *! Object to serialize. Always a context of the current object. *! *! @param deserializer *! Function to be called once for every variable *! to serialize. *! *! The @[deserializer] function expects to be called with three arguments: *! @dl *! @item
9cded82011-02-04Henrik Grubbström (Grubba)  *! @tt{setter@} - Function that sets the symbol value. *! @item
1031362011-01-21Henrik Grubbström (Grubba)  *! @tt{symbol@} - The symbol name. *! @item *! @tt{symbol_type@} - The type of the symbol. *! @enddl *! *! @note *! A default implementation of @[lfun::_serialize()] and *! @[lfun::_deserialize()] is available in @[Serializer.Serializable]. *! *! @seealso *! @[lfun::_serialize()], @[Serializer.deserialize()], *! @[Serializer.Serializable()->_deserialize()] */
f9aaee2013-11-18Henrik Grubbström (Grubba) /*! @decl int lfun::_size_object() *! *! @[Debug.size_object()] callback. *! *! @returns *! Returns an approximation of the memory use in bytes for the object. *! *! @seealso *! @[Debug.size_object()], @[lfun::_sizeof()] */
e24c3d2013-11-18Henrik Grubbström (Grubba) /*! @decl mixed lfun::_random() *! Called by @[random()]. Typical use is when the object implements *! a ADT, when a call to this lfun should return a random member of *! the ADT or range implied by the ADT. *! *! @seealso *! @[predef::random()] */
abb3e42013-11-18Henrik Grubbström (Grubba) /**** END FAKE LFUNS ****/ /**** BEGIN MAGIC LFUNS ****/
d25a892007-11-15Henrik Grubbström (Grubba) /*! @decl mixed lfun::`symbol() *! @decl mixed lfun::`->symbol()
6fa59e2006-10-27Henrik Grubbström (Grubba)  *! *! Variable retrieval callback (aka "getter"). *! *! @note *! Note that the @expr{symbol@} in the name can be any symbol. *! *! @note *! This is not a true LFUN, since it is even more low level! *! *! @note *! This function WILL be called even by inheriting programs *! when they attempt to access the variable named @expr{symbol@}. *! *! @seealso *! @[lfun::`->symbol=()], @[lfun::`->()] */
d25a892007-11-15Henrik Grubbström (Grubba) /*! @decl void lfun::`symbol=(zero value) *! @decl void lfun::`->symbol=(zero value)
6fa59e2006-10-27Henrik Grubbström (Grubba)  *! *! Variable assignment callback (aka "setter"). *! *! @note *! Note that the @expr{symbol@} in the name can be any symbol. *! *! @note *! This is not a true LFUN, since it is even more low level! *! *! @note *! This function WILL be called even by inheriting programs *! when they attempt to set the variable named @expr{symbol@}. *! *! @seealso *! @[lfun::`->symbol()], @[lfun::`->=()] */
47251d2002-12-11Henrik Grubbström (Grubba) /*! @endnamespace */
1937952002-12-08Henrik Grubbström (Grubba) /*! @class MasterObject */ /*! @decl void unregister(program p) *! *! Unregister a program that was only partially compiled. *! *! Called by @[compile()] to clean up references to partially compiled *! programs. *! *! @param p *! Partially compiled program that should no longer be referenced. *! *! @fixme *! Shouldn't this function be in the compilation handler? */ /*! @endclass */ /*! @class CompilationHandler */ /*! @decl mapping(string:mixed)|object get_default_module() *! *! Returns the default module from which global symbols will *! be fetched. *! *! @returns
cbe8c92003-04-07Martin Nilsson  *! Returns the default module, or @expr{0@} (zero).
1937952002-12-08Henrik Grubbström (Grubba)  *!
cbe8c92003-04-07Martin Nilsson  *! If @expr{0@} (zero) is returned the compiler use the mapping
1937952002-12-08Henrik Grubbström (Grubba)  *! returned by @[all_constants()] as fallback. *! *! @seealso *! @[get_predefines()] */ /*! @decl void compile_warning(string filename, int line, string msg) *! *! Called by @[compile()] to report warnings. *! *! @param filename *! File which triggered the warning. *! *! @param line *! Line which triggered the warning. *! *! @param msg *! Warning message. *! *! @seealso *! @[compile_error()] */ /*! @endclass */
5267b71995-08-09Fredrik Hübinette (Hubbe) struct program *first_program = 0;
f8d8f42001-07-01Henrik Grubbström (Grubba) static int current_program_id = PROG_DYNAMIC_ID_START;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
aa68b12001-03-19Fredrik Hübinette (Hubbe) struct program *null_program=0;
4932732011-12-09Henrik Grubbström (Grubba) static struct program *reporter_program = NULL;
5cd1572008-04-06Henrik Grubbström (Grubba) struct program *compilation_program = 0;
41c9152008-04-18Henrik Grubbström (Grubba) struct program *compilation_env_program = 0; struct object *compilation_environment = NULL;
5cd1572008-04-06Henrik Grubbström (Grubba) 
e2d9e62000-06-10Martin Stjernholm struct program *gc_internal_program = 0; static struct program *gc_mark_program_pos = 0;
547e582013-09-08Henrik Grubbström (Grubba) #define CHECK_FILE_ENTRY(PROG, STRNO) \
1415ff2003-03-19Martin Stjernholm  do { \
547e582013-09-08Henrik Grubbström (Grubba)  if ((STRNO < 0) || (STRNO >= PROG->num_strings)) \
1415ff2003-03-19Martin Stjernholm  Pike_fatal ("Invalid file entry in linenumber info.\n"); \ } while (0)
ef24a82012-01-12Henrik Grubbström (Grubba) INT_TYPE get_small_number(char **q);
1016021999-10-28Fredrik Hübinette (Hubbe) 
f13b952006-07-05Martin Stjernholm PMOD_EXPORT void do_free_program (struct program *p) { if (p) free_program(p); }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) /* So what if we don't have templates? / Hubbe */
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
1bc3192004-01-16Martin Nilsson #define CHECK_FOO(NUMTYPE,TYPE,NAME) \ if(Pike_compiler->malloc_size_program-> PIKE_CONCAT(num_,NAME) < \ Pike_compiler->new_program-> PIKE_CONCAT(num_,NAME)) \ Pike_fatal("Pike_compiler->new_program->num_" #NAME " is out of order\n");\ if(Pike_compiler->new_program->flags & PROGRAM_OPTIMIZED) \
5aad932002-08-15Marcus Comstedt  Pike_fatal("Tried to reallocate fixed program.\n")
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  #else #define CHECK_FOO(NUMTYPE,TYPE,NAME) #endif
0e0cd72001-07-20Henrik Grubbström (Grubba) #ifndef RELOCATE_program #define RELOCATE_program(ORIG, NEW) #endif /* !RELOCATE_program */
b61bd92009-03-04Henrik Grubbström (Grubba) #define RELOCATE_identifier_cache(ORIG,NEW)
302ede2001-07-19Henrik Grubbström (Grubba) #define RELOCATE_linenumbers(ORIG,NEW) #define RELOCATE_identifier_index(ORIG,NEW) #define RELOCATE_variable_index(ORIG,NEW) #define RELOCATE_identifier_references(ORIG,NEW) #define RELOCATE_strings(ORIG,NEW) #define RELOCATE_inherits(ORIG,NEW) #define RELOCATE_identifiers(ORIG,NEW) #define RELOCATE_constants(ORIG,NEW) #define RELOCATE_relocations(ORIG,NEW)
6c87492004-01-16Mirar (Pontus Hagland) #if SIZEOF_LONG_LONG == 8 /* we have 8 byte ints, hopefully this constant works on all these systems */ #define MAXVARS(NUMTYPE) \ (NUMTYPE)(sizeof(NUMTYPE)==1?254: \ (sizeof(NUMTYPE)==2?65534: \ (sizeof(NUMTYPE)==4?4294967294U:18446744073709551614ULL))) #else #define MAXVARS(NUMTYPE) \ (NUMTYPE)(sizeof(NUMTYPE)==1?254: (sizeof(NUMTYPE)==2?65534:4294967294U)) #endif
d717352005-05-25Henrik Grubbström (Grubba) #ifdef PIKE_USE_MACHINE_CODE /* Special cases for low_add_to_program and add_to_program since * many OSes require us to use mmap to allocate memory for our
e18a682009-08-17Henrik Grubbström (Grubba)  * machine code. For decoding efficiency we also want a multi copy * variant to be used by decode().
d717352005-05-25Henrik Grubbström (Grubba)  */ #define BAR(NUMTYPE,TYPE,ARGTYPE,NAME) \ void PIKE_CONCAT(low_add_to_,NAME) (struct program_state *state, \ TYPE ARG) { \ NUMTYPE m = state->malloc_size_program->PIKE_CONCAT(num_,NAME); \ CHECK_FOO(NUMTYPE,TYPE,NAME); \ if(m == state->new_program->PIKE_CONCAT(num_,NAME)) { \ TYPE *tmp; \ if(m==MAXVARS(NUMTYPE)) { \ yyerror("Too many " #NAME "."); \ return; \ } \ m = MINIMUM(m*2+1,MAXVARS(NUMTYPE)); \
5572422014-04-27Martin Nilsson  tmp = mexec_realloc(state->new_program->NAME, sizeof(TYPE) * m); \
d717352005-05-25Henrik Grubbström (Grubba)  if(!tmp) Pike_fatal("Out of memory.\n"); \ PIKE_CONCAT(RELOCATE_,NAME)(state->new_program, tmp); \ state->malloc_size_program->PIKE_CONCAT(num_,NAME)=m; \ state->new_program->NAME=tmp; \ } \ state->new_program-> \ NAME[state->new_program->PIKE_CONCAT(num_,NAME)++]=(ARG); \ } \
e18a682009-08-17Henrik Grubbström (Grubba) void PIKE_CONCAT(low_add_many_to_,NAME) (struct program_state *state, \ TYPE *ARG, NUMTYPE cnt) { \ NUMTYPE m = state->malloc_size_program->PIKE_CONCAT(num_,NAME); \ CHECK_FOO(NUMTYPE,TYPE,NAME); \ if((m + cnt) > state->new_program->PIKE_CONCAT(num_,NAME)) { \ TYPE *tmp; \ NUMTYPE n = m; \ do { \ if(n==MAXVARS(NUMTYPE)) { \ yyerror("Too many " #NAME "."); \ return; \ } \
b3d3262009-08-18Henrik Grubbström (Grubba)  n = MINIMUM(n*2+1,MAXVARS(NUMTYPE)); \
e18a682009-08-17Henrik Grubbström (Grubba)  } while (m + cnt > n); \ m = n; \
5572422014-04-27Martin Nilsson  tmp = mexec_realloc(state->new_program->NAME, sizeof(TYPE) * m); \
e18a682009-08-17Henrik Grubbström (Grubba)  if(!tmp) Pike_fatal("Out of memory.\n"); \ PIKE_CONCAT(RELOCATE_,NAME)(state->new_program, tmp); \ state->malloc_size_program->PIKE_CONCAT(num_,NAME)=m; \ state->new_program->NAME=tmp; \ } \
59fc9e2014-09-03Martin Nilsson  memcpy(state->new_program->NAME + \
e18a682009-08-17Henrik Grubbström (Grubba)  state->new_program->PIKE_CONCAT(num_,NAME), \ ARG, sizeof(TYPE) * cnt); \ state->new_program->PIKE_CONCAT(num_,NAME) += cnt; \ } \
d717352005-05-25Henrik Grubbström (Grubba) void PIKE_CONCAT(add_to_,NAME) (ARGTYPE ARG) { \ PIKE_CONCAT(low_add_to_,NAME) ( Pike_compiler, ARG ); \ }
e18a682009-08-17Henrik Grubbström (Grubba) #else /* !PIKE_USE_MACHINE_CODE */ #define BAR(NUMTYPE,TYPE,ARGTYPE,NAME) \ FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ void PIKE_CONCAT(low_add_many_to_,NAME) (struct program_state *state, \ TYPE *ARG, NUMTYPE cnt) { \ NUMTYPE m = state->malloc_size_program->PIKE_CONCAT(num_,NAME); \ CHECK_FOO(NUMTYPE,TYPE,NAME); \ if((m + cnt) > state->new_program->PIKE_CONCAT(num_,NAME)) { \ TYPE *tmp; \ NUMTYPE n = m; \ do { \ if(n==MAXVARS(NUMTYPE)) { \ yyerror("Too many " #NAME "."); \ return; \ } \
b3d3262009-08-18Henrik Grubbström (Grubba)  n = MINIMUM(n*2+1,MAXVARS(NUMTYPE)); \
e18a682009-08-17Henrik Grubbström (Grubba)  } while (m + cnt > n); \ m = n; \
5572422014-04-27Martin Nilsson  tmp = realloc(state->new_program->NAME, sizeof(TYPE) * m); \
e18a682009-08-17Henrik Grubbström (Grubba)  if(!tmp) Pike_fatal("Out of memory.\n"); \ PIKE_CONCAT(RELOCATE_,NAME)(state->new_program, tmp); \ state->malloc_size_program->PIKE_CONCAT(num_,NAME)=m; \ state->new_program->NAME=tmp; \ } \
59fc9e2014-09-03Martin Nilsson  memcpy(state->new_program->NAME + \
e18a682009-08-17Henrik Grubbström (Grubba)  state->new_program->PIKE_CONCAT(num_,NAME), \ ARG, sizeof(TYPE) * cnt); \ state->new_program->PIKE_CONCAT(num_,NAME) += cnt; \ }
d717352005-05-25Henrik Grubbström (Grubba) #endif /* PIKE_USE_MACHINE_CODE */
1bc3192004-01-16Martin Nilsson /* Funny guys use the uppermost value for nonexistant variables and the like. Hence -2 and not -1. Y2K. */
7e877a2003-04-02Martin Stjernholm #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \
bad5162000-06-23Fredrik Hübinette (Hubbe) void PIKE_CONCAT(low_add_to_,NAME) (struct program_state *state, \ TYPE ARG) { \
1bc3192004-01-16Martin Nilsson  NUMTYPE m = state->malloc_size_program->PIKE_CONCAT(num_,NAME); \ CHECK_FOO(NUMTYPE,TYPE,NAME); \ if(m == state->new_program->PIKE_CONCAT(num_,NAME)) { \
302ede2001-07-19Henrik Grubbström (Grubba)  TYPE *tmp; \
50a98f2004-01-19Henrik Grubbström (Grubba)  if(m==MAXVARS(NUMTYPE)) { \
a0b06e2004-01-19Henrik Grubbström (Grubba)  yyerror("Too many " #NAME "."); \
50a98f2004-01-19Henrik Grubbström (Grubba)  return; \ } \ m = MINIMUM(m*2+1,MAXVARS(NUMTYPE)); \
5572422014-04-27Martin Nilsson  tmp = realloc(state->new_program->NAME, sizeof(TYPE) * m); \
7ed4962002-11-19Henrik Grubbström (Grubba)  if(!tmp) Pike_fatal("Out of memory.\n"); \
84abc62007-10-13Henrik Grubbström (Grubba)  PIKE_CONCAT(RELOCATE_,NAME)(state->new_program, tmp); \ state->malloc_size_program->PIKE_CONCAT(num_,NAME)=m; \ state->new_program->NAME=tmp; \ } \ state->new_program-> \ NAME[state->new_program->PIKE_CONCAT(num_,NAME)++]=(ARG); \ } \ void PIKE_CONCAT(add_to_,NAME) (ARGTYPE ARG) { \ PIKE_CONCAT(low_add_to_,NAME) ( Pike_compiler, ARG ); \ } /* Funny guys use the uppermost value for nonexistant variables and the like. Hence -2 and not -1. Y2K. */ #define PASS1ONLY(NUMTYPE,TYPE,ARGTYPE,NAME) \ void PIKE_CONCAT(low_add_to_,NAME) (struct program_state *state, \ TYPE ARG) { \ NUMTYPE m = state->malloc_size_program->PIKE_CONCAT(num_,NAME); \ CHECK_FOO(NUMTYPE,TYPE,NAME); \ DO_IF_DEBUG(if (state->compiler_pass != 1) { \ Pike_fatal("Adding " TOSTR(NAME) " in pass %d.\n", \ state->compiler_pass); \ }); \ if(m == state->new_program->PIKE_CONCAT(num_,NAME)) { \ TYPE *tmp; \ if(m==MAXVARS(NUMTYPE)) { \ yyerror("Too many " #NAME "."); \ return; \ } \ m = MINIMUM(m*2+1,MAXVARS(NUMTYPE)); \
5572422014-04-27Martin Nilsson  tmp = realloc(state->new_program->NAME, sizeof(TYPE) * m); \
84abc62007-10-13Henrik Grubbström (Grubba)  if(!tmp) Pike_fatal("Out of memory.\n"); \
302ede2001-07-19Henrik Grubbström (Grubba)  PIKE_CONCAT(RELOCATE_,NAME)(state->new_program, tmp); \
1bc3192004-01-16Martin Nilsson  state->malloc_size_program->PIKE_CONCAT(num_,NAME)=m; \
bad5162000-06-23Fredrik Hübinette (Hubbe)  state->new_program->NAME=tmp; \
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  } \
bad5162000-06-23Fredrik Hübinette (Hubbe)  state->new_program-> \ NAME[state->new_program->PIKE_CONCAT(num_,NAME)++]=(ARG); \ } \
7e877a2003-04-02Martin Stjernholm void PIKE_CONCAT(add_to_,NAME) (ARGTYPE ARG) { \
bad5162000-06-23Fredrik Hübinette (Hubbe)  PIKE_CONCAT(low_add_to_,NAME) ( Pike_compiler, ARG ); \
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) }
d429a71998-02-24Fredrik Hübinette (Hubbe)  #include "program_areas.h"
7ed4962002-11-19Henrik Grubbström (Grubba) #define add_to_program(ARG) do { \ debug_malloc_touch(Pike_compiler->new_program->program); \ add_to_program(ARG); \ } while(0)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) void ins_int(INT32 i, void (*func)(char tmp)) { int e;
573ba42001-04-11Henrik Grubbström (Grubba)  unsigned char *p = (unsigned char *)&i; for(e=0;e<(long)sizeof(i);e++) { func(p[e]); }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) }
5f8eb71997-02-18Fredrik Hübinette (Hubbe) 
2449d22008-05-10Martin Stjernholm #if 0 /* This check is not possible to do since the identifier is added * before checking for duplicates in add_constant. */
5ec1062002-05-09Martin Stjernholm static void debug_add_to_identifiers (struct identifier id) { if (d_flag) { int i; for (i = 0; i < Pike_compiler->new_program->num_identifiers; i++) if (Pike_compiler->new_program->identifiers[i].name == id.name) { dump_program_tables (Pike_compiler->new_program, 0);
0ed9122008-05-16Henrik Grubbström (Grubba)  Pike_fatal ("Adding identifier twice, old at %s:%d #%d.\n", Pike_compiler->new_program->identifiers[i].filename? Pike_compiler->new_program->identifiers[i].filename:"-", Pike_compiler->new_program->identifiers[i].linenumber, i);
5ec1062002-05-09Martin Stjernholm  } } add_to_identifiers (id); } #else #define debug_add_to_identifiers(ARG) add_to_identifiers(ARG) #endif
2659cf2002-05-10Henrik Grubbström (Grubba) void add_relocated_int_to_program(INT32 i) { add_to_relocations(Pike_compiler->new_program->num_program); ins_int(i, (void (*)(char))add_to_program); }
5ec1062002-05-09Martin Stjernholm 
591c0c1997-01-19Fredrik Hübinette (Hubbe) void use_module(struct svalue *s)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
5b84a52008-04-26Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
017b572011-10-28Henrik Grubbström (Grubba)  if( (1<<TYPEOF(*s)) & (BIT_MAPPING | BIT_OBJECT | BIT_PROGRAM))
5c0a101997-02-06Fredrik Hübinette (Hubbe)  {
5b84a52008-04-26Henrik Grubbström (Grubba)  c->num_used_modules++;
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->num_used_modules++;
5c0a101997-02-06Fredrik Hübinette (Hubbe)  assign_svalue_no_free((struct svalue *) low_make_buf_space(sizeof(struct svalue),
5b84a52008-04-26Henrik Grubbström (Grubba)  &c->used_modules), s);
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->module_index_cache)
05590d1998-04-23Fredrik Hübinette (Hubbe)  {
bad5162000-06-23Fredrik Hübinette (Hubbe)  free_mapping(Pike_compiler->module_index_cache); Pike_compiler->module_index_cache=0;
05590d1998-04-23Fredrik Hübinette (Hubbe)  }
518b042011-11-20Henrik Grubbström (Grubba)  if(c->resolve_cache) { free_mapping(c->resolve_cache); c->resolve_cache=0; }
5c0a101997-02-06Fredrik Hübinette (Hubbe)  }else{ yyerror("Module is neither mapping nor object"); }
591c0c1997-01-19Fredrik Hübinette (Hubbe) }
05590d1998-04-23Fredrik Hübinette (Hubbe) void unuse_modules(INT32 howmany) {
5b84a52008-04-26Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
05590d1998-04-23Fredrik Hübinette (Hubbe)  if(!howmany) return;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5b84a52008-04-26Henrik Grubbström (Grubba)  if(howmany *sizeof(struct svalue) > c->used_modules.s.len)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Unusing too many modules.\n");
05590d1998-04-23Fredrik Hübinette (Hubbe) #endif
5b84a52008-04-26Henrik Grubbström (Grubba)  c->num_used_modules -= howmany;
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->num_used_modules-=howmany;
310dd52008-07-16Martin Stjernholm  low_make_buf_space((ptrdiff_t) sizeof(struct svalue) * -howmany, &c->used_modules);
5b84a52008-04-26Henrik Grubbström (Grubba)  free_svalues((struct svalue *)low_make_buf_space(0, &c->used_modules),
05590d1998-04-23Fredrik Hübinette (Hubbe)  howmany,
a1e8821998-11-05Fredrik Hübinette (Hubbe)  BIT_MAPPING | BIT_OBJECT | BIT_PROGRAM);
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->module_index_cache)
05590d1998-04-23Fredrik Hübinette (Hubbe)  {
bad5162000-06-23Fredrik Hübinette (Hubbe)  free_mapping(Pike_compiler->module_index_cache); Pike_compiler->module_index_cache=0;
05590d1998-04-23Fredrik Hübinette (Hubbe)  } }
b8cda21997-01-21Fredrik Hübinette (Hubbe) 
4d7b181999-12-07Fredrik Hübinette (Hubbe) static struct node_s *index_modules(struct pike_string *ident, struct mapping **module_index_cache,
52af792014-10-22Arne Goedeke  const int num_used_modules,
4d7b181999-12-07Fredrik Hübinette (Hubbe)  struct svalue *modules)
52af792014-10-22Arne Goedeke  /* num_used_modules is declared const here to convince the compiler that it is not * modified in between setjmp() and longjmp(). This prevents -Wglobbered warnings. */
591c0c1997-01-19Fredrik Hübinette (Hubbe) {
4d7b181999-12-07Fredrik Hübinette (Hubbe)  if(*module_index_cache)
05590d1998-04-23Fredrik Hübinette (Hubbe)  {
4d7b181999-12-07Fredrik Hübinette (Hubbe)  struct svalue *tmp=low_mapping_string_lookup(*module_index_cache,ident);
05590d1998-04-23Fredrik Hübinette (Hubbe)  if(tmp) {
017b572011-10-28Henrik Grubbström (Grubba)  if(!(SAFE_IS_ZERO(tmp) && SUBTYPEOF(*tmp)==1))
05590d1998-04-23Fredrik Hübinette (Hubbe)  return mksvaluenode(tmp); return 0; } }
8aae6d1999-08-19Fredrik Hübinette (Hubbe) /* fprintf(stderr,"index_module: %s\n",ident->str); */
591c0c1997-01-19Fredrik Hübinette (Hubbe)  {
8fa3102000-09-05Henrik Grubbström (Grubba)  JMP_BUF tmp; if(SETJMP(tmp))
910bd12008-05-30Martin Stjernholm  handle_compile_exception ("Couldn't index a module with %S.", ident); else {
8fa3102000-09-05Henrik Grubbström (Grubba)  int e = num_used_modules; struct svalue *m = modules - num_used_modules;
27ae842000-02-07Per Hedbor 
8fa3102000-09-05Henrik Grubbström (Grubba)  while(--e>=0)
591c0c1997-01-19Fredrik Hübinette (Hubbe)  {
8fa3102000-09-05Henrik Grubbström (Grubba)  push_svalue(m+e); ref_push_string(ident); f_index(2); if(!IS_UNDEFINED(Pike_sp-1)) { struct node_s *ret; UNSETJMP(tmp);
bd537b2002-12-10Martin Stjernholm  if (Pike_compiler->compiler_pass == 2 &&
017b572011-10-28Henrik Grubbström (Grubba)  ((TYPEOF(Pike_sp[-1]) == T_OBJECT &&
bd537b2002-12-10Martin Stjernholm  Pike_sp[-1].u.object == placeholder_object) ||
017b572011-10-28Henrik Grubbström (Grubba)  (TYPEOF(Pike_sp[-1]) == T_PROGRAM &&
bd537b2002-12-10Martin Stjernholm  Pike_sp[-1].u.program == placeholder_program))) {
ce060e2004-06-30Martin Nilsson  my_yyerror("Got placeholder %s (resolver problem) " "when indexing a module with %S.",
017b572011-10-28Henrik Grubbström (Grubba)  get_name_of_type (TYPEOF(Pike_sp[-1])), ident);
bd537b2002-12-10Martin Stjernholm  ret = 0; } else { if(!*module_index_cache) *module_index_cache = allocate_mapping(10); mapping_string_insert(*module_index_cache, ident, Pike_sp-1); ret = mksvaluenode(Pike_sp-1);
7b33712008-08-17Martin Stjernholm #if 0 && defined (COMPILER_DEBUG) safe_pike_fprintf (stderr, "Index %S: %O\n", ident, Pike_sp - 1); #endif
bd537b2002-12-10Martin Stjernholm  }
8fa3102000-09-05Henrik Grubbström (Grubba)  pop_stack(); return ret; }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  pop_stack();
591c0c1997-01-19Fredrik Hübinette (Hubbe)  } }
8fa3102000-09-05Henrik Grubbström (Grubba)  UNSETJMP(tmp);
591c0c1997-01-19Fredrik Hübinette (Hubbe)  }
b8cda21997-01-21Fredrik Hübinette (Hubbe) 
3152712008-08-17Martin Stjernholm #if 0 && defined (COMPILER_DEBUG) safe_pike_fprintf (stderr, "Index %S: undefined\n", ident); #endif
8aae6d1999-08-19Fredrik Hübinette (Hubbe) 
05590d1998-04-23Fredrik Hübinette (Hubbe)  return 0; }
f34f642002-05-05Martin Stjernholm struct node_s *resolve_identifier(struct pike_string *ident);
2816052000-03-30Fredrik Hübinette (Hubbe) struct node_s *find_module_identifier(struct pike_string *ident, int see_inherit)
05590d1998-04-23Fredrik Hübinette (Hubbe) {
5b84a52008-04-26Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
05590d1998-04-23Fredrik Hübinette (Hubbe)  struct node_s *ret;
4d7b181999-12-07Fredrik Hübinette (Hubbe)  struct svalue *modules=(struct svalue *)
5b84a52008-04-26Henrik Grubbström (Grubba)  (c->used_modules.s.str + c->used_modules.s.len);
05590d1998-04-23Fredrik Hübinette (Hubbe) 
b8cda21997-01-21Fredrik Hübinette (Hubbe)  {
4d51e02002-06-10Martin Stjernholm  struct program_state *p=Pike_compiler;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  int n;
8853882008-04-26Henrik Grubbström (Grubba)  for(n=0;n<=c->compilation_depth;n++,p=p->previous)
b8cda21997-01-21Fredrik Hübinette (Hubbe)  {
2816052000-03-30Fredrik Hübinette (Hubbe)  int i; if(see_inherit)
b8cda21997-01-21Fredrik Hübinette (Hubbe)  {
2816052000-03-30Fredrik Hübinette (Hubbe)  i=really_low_find_shared_string_identifier(ident, p->new_program,
6530932008-06-29Martin Nilsson  SEE_PROTECTED|SEE_PRIVATE);
2816052000-03-30Fredrik Hübinette (Hubbe)  if(i!=-1) {
d165152008-05-03Henrik Grubbström (Grubba)  if ((p->flags & COMPILATION_FORCE_RESOLVE) && (p->compiler_pass == 2) && ((p->num_inherits + 1) < p->new_program->num_inherits) && (PTR_FROM_INT(p->new_program, i)->inherit_offset > p->num_inherits)) {
3b15fb2008-05-03Henrik Grubbström (Grubba)  /* Don't look up symbols inherited later, since we need to get * the same symbol in both passes in the force_resolve mode.
d165152008-05-03Henrik Grubbström (Grubba)  */ continue; }
4d51e02002-06-10Martin Stjernholm  return p == Pike_compiler ? mkidentifiernode(i) : mkexternalnode(p->new_program, i);
2816052000-03-30Fredrik Hübinette (Hubbe)  }
05590d1998-04-23Fredrik Hübinette (Hubbe)  }
bad5162000-06-23Fredrik Hübinette (Hubbe) 
4d7b181999-12-07Fredrik Hübinette (Hubbe)  if((ret=index_modules(ident, &p->module_index_cache, p->num_used_modules, modules))) return ret; modules-=p->num_used_modules; #ifdef PIKE_DEBUG
5b84a52008-04-26Henrik Grubbström (Grubba)  if( ((char *)modules ) < c->used_modules.s.str)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Modules out of whack!\n");
4d7b181999-12-07Fredrik Hübinette (Hubbe) #endif
05590d1998-04-23Fredrik Hübinette (Hubbe)  } }
5be76b2005-08-10Henrik Grubbström (Grubba)  return resolve_identifier(ident); } /*! @decl constant UNDEFINED *! *! The undefined value; ie a zero for which @[zero_type()] returns 1. */ struct node_s *resolve_identifier(struct pike_string *ident) {
0ae4612008-04-14Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION; node *ret = NULL;
e8d37d2002-02-14Henrik Grubbström (Grubba)  /* Handle UNDEFINED */ if (ident == UNDEFINED_string) {
e448552008-07-09Martin Stjernholm  return mkconstantsvaluenode(&svalue_undefined);
e8d37d2002-02-14Henrik Grubbström (Grubba)  }
05590d1998-04-23Fredrik Hübinette (Hubbe) 
518b042011-11-20Henrik Grubbström (Grubba)  if(c->resolve_cache)
05590d1998-04-23Fredrik Hübinette (Hubbe)  {
518b042011-11-20Henrik Grubbström (Grubba)  struct svalue *tmp=low_mapping_string_lookup(c->resolve_cache,ident);
05590d1998-04-23Fredrik Hübinette (Hubbe)  if(tmp) {
4139a22008-01-28Martin Stjernholm  if(!IS_UNDEFINED (tmp))
05590d1998-04-23Fredrik Hübinette (Hubbe)  return mkconstantsvaluenode(tmp); return 0; } }
0ae4612008-04-14Henrik Grubbström (Grubba)  CHECK_COMPILER();
27ae842000-02-07Per Hedbor 
0ae4612008-04-14Henrik Grubbström (Grubba)  ref_push_string(ident); ref_push_string(c->lex.current_file); if (c->handler) { ref_push_object(c->handler); } else { push_int(0); }
e17a952008-05-30Martin Stjernholm  if (!safe_apply_current2(PC_RESOLV_FUN_NUM, 3, NULL))
3152712008-08-17Martin Stjernholm  handle_compile_exception ("Error resolving '%S'.", ident); if (Pike_compiler->compiler_pass != 2) { /* If we get a program that hasn't gone through pass 1 yet then we * have to register a dependency now in our pass 1 so that our * pass 2 gets delayed. Otherwise the other program might still be * just as unfinished when we come back here in pass 2. */ struct program *p = NULL;
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-1]) == T_PROGRAM)
3152712008-08-17Martin Stjernholm  p = Pike_sp[-1].u.program;
017b572011-10-28Henrik Grubbström (Grubba)  else if (TYPEOF(Pike_sp[-1]) == T_OBJECT || (TYPEOF(Pike_sp[-1]) == T_FUNCTION && SUBTYPEOF(Pike_sp[-1]) != FUNCTION_BUILTIN))
3152712008-08-17Martin Stjernholm  p = Pike_sp[-1].u.object->prog; if (p && !(p->flags & PROGRAM_PASS_1_DONE)) report_compiler_dependency (p); }
0ae4612008-04-14Henrik Grubbström (Grubba)  if (Pike_compiler->compiler_pass == 2 &&
017b572011-10-28Henrik Grubbström (Grubba)  ((TYPEOF(Pike_sp[-1]) == T_OBJECT &&
0ae4612008-04-14Henrik Grubbström (Grubba)  Pike_sp[-1].u.object == placeholder_object) ||
017b572011-10-28Henrik Grubbström (Grubba)  (TYPEOF(Pike_sp[-1]) == T_PROGRAM &&
0ae4612008-04-14Henrik Grubbström (Grubba)  Pike_sp[-1].u.program == placeholder_program))) { my_yyerror("Got placeholder %s (resolver problem) "
3152712008-08-17Martin Stjernholm  "when resolving '%S'.",
017b572011-10-28Henrik Grubbström (Grubba)  get_name_of_type (TYPEOF(Pike_sp[-1])), ident);
0ae4612008-04-14Henrik Grubbström (Grubba)  } else {
518b042011-11-20Henrik Grubbström (Grubba)  if(!c->resolve_cache) c->resolve_cache=dmalloc_touch(struct mapping *, allocate_mapping(10)); mapping_string_insert(c->resolve_cache,ident,Pike_sp-1);
8d697e2004-03-13Henrik Grubbström (Grubba) 
0ae4612008-04-14Henrik Grubbström (Grubba)  if(!IS_UNDEFINED (Pike_sp-1)) { ret=mkconstantsvaluenode(Pike_sp-1); }
b8cda21997-01-21Fredrik Hübinette (Hubbe)  }
0ae4612008-04-14Henrik Grubbström (Grubba)  pop_stack();
27ae842000-02-07Per Hedbor 
0ae4612008-04-14Henrik Grubbström (Grubba)  return ret;
b8cda21997-01-21Fredrik Hübinette (Hubbe) }
29615e2014-10-18Henrik Grubbström (Grubba) /** * This function is intended to simplify resolving of
ef2adb2013-04-21Henrik Grubbström (Grubba)  * program symbols during compile-time for C-modules. * * A typical use-case is for a C-module inheriting * code written in Pike. */ PMOD_EXPORT struct program *resolve_program(struct pike_string *ident) { struct program *ret = NULL; struct node_s *n = resolve_identifier(ident); if (n) { if ((n->token == F_CONSTANT) && (TYPEOF(n->u.sval) == T_PROGRAM) && (ret = n->u.sval.u.program)) { add_ref(ret); } else { my_yyerror("Invalid program identifier '%S'.", ident); } free_node(n); } else { my_yyerror("Unknown program identifier '%S'.", ident); } return ret; }
5614312002-11-17Henrik Grubbström (Grubba) /*! @decl constant this *!
88e9fb2003-08-03Martin Stjernholm  *! Builtin read only variable that evaluates to the current object.
5614312002-11-17Henrik Grubbström (Grubba)  *! *! @seealso *! @[this_program], @[this_object()] */ /*! @decl constant this_program *! *! Builtin constant that evaluates to the current program. *! *! @seealso *! @[this], @[this_object()] */
29615e2014-10-18Henrik Grubbström (Grubba) /** * If the identifier is recognized as one of the magic identifiers,
0ee38f2002-05-11Martin Stjernholm  * like "this", "this_program" or "`->" when preceded by ::, then a
388e5d2008-05-30Henrik Grubbström (Grubba)  * suitable node is returned, NULL otherwise. *
29615e2014-10-18Henrik Grubbström (Grubba)  * @param inherit_num * Inherit number in state->new_program that the identifier has been * qualified with. -1 when no specific inherit has been specified; ie * either when the identifier has no prefix (colon_colon_ref == 0) or * when the identifier has the prefix :: without any preceding identifier * (colon_colon_ref == 1).
4bd5202012-04-29Henrik Grubbström (Grubba)  * * New in Pike 7.9.5 and later: * * If colon_colon_ref is 1 and the selected inherit defines the * `->() lfun, code calling the lfun will be generated as follows: * * inh::`->(ident, inh::this, 1)
388e5d2008-05-30Henrik Grubbström (Grubba)  */
0ee38f2002-05-11Martin Stjernholm struct node_s *program_magic_identifier (struct program_state *state, int state_depth, int inherit_num, struct pike_string *ident, int colon_colon_ref) { #if 0 fprintf (stderr, "magic_identifier (state, %d, %d, %s, %d)\n", state_depth, inherit_num, ident->str, colon_colon_ref); #endif
3a30d72014-10-05Martin Nilsson  /* FIXME: Is this expression always true? */ if ((inherit_num == -1) || (inherit_num >= 0)) {
88e9fb2003-08-03Martin Stjernholm  if (ident == this_string) {
fa7a352004-12-18Henrik Grubbström (Grubba)  /* Handle this. */ return mkthisnode(state->new_program, inherit_num);
88e9fb2003-08-03Martin Stjernholm  }
0ee38f2002-05-11Martin Stjernholm  /* Handle this_program */
88e9fb2003-08-03Martin Stjernholm  if (ident == this_program_string) {
0f91072013-04-27Henrik Grubbström (Grubba)  node *n; if (!state_depth && (inherit_num == -1) && colon_colon_ref && !TEST_COMPAT(7,8) && state->previous && state->previous->new_program) { /* ::this_program * * This refers to the previous definition of the current class * in its parent, and is typically used with inherit like: * * inherit Foo; * * // Override the Bar inherited from Foo. * class Bar { * // Bar is based on the implementation from Foo. * inherit ::this_program; * * // ... * } */ struct program *parent; struct pike_string *name = NULL; int e; int i; /* Find the name of the current class. */ parent = state->previous->new_program; for (e = parent->num_identifier_references; e--;) { struct identifier *id = ID_FROM_INT(parent, e); struct svalue *s; if (!IDENTIFIER_IS_CONSTANT(id->identifier_flags) || (id->func.const_info.offset < 0)) { continue; } s = &PROG_FROM_INT(parent, e)-> constants[id->func.const_info.offset].sval; if ((TYPEOF(*s) != T_PROGRAM) || (s->u.program != state->new_program)) { continue; } /* Found! */ name = id->name; break; } if (!name) { yyerror("Failed to find current class in its parent."); return NULL; } /* Find ::name in the parent. */
6d0fdb2013-04-28Henrik Grubbström (Grubba)  i = reference_inherited_identifier(state->previous, NULL, name);
0f91072013-04-27Henrik Grubbström (Grubba)  if (i == -1) { my_yyerror("Failed to find previous inherited definition of %S " "in parent.", name); return NULL; } n = mkexternalnode(parent, i); } else { n = mkefuncallnode("object_program", mkthisnode(state->new_program, inherit_num)); }
88e9fb2003-08-03Martin Stjernholm  /* We know this expression is constant. */ n->node_info &= ~OPT_NOT_CONST; n->tree_info &= ~OPT_NOT_CONST; return n; }
0ed9122008-05-16Henrik Grubbström (Grubba)  /* Handle this_function */ if (ident == this_function_string) { int i; if ((i = Pike_compiler->compiler_frame->current_function_number) >= 0) { struct identifier *id; id = ID_FROM_INT(Pike_compiler->new_program, i); if (id->identifier_flags & IDENTIFIER_SCOPED) { return mktrampolinenode(i, Pike_compiler->compiler_frame->previous); } else { return mkidentifiernode(i); } } else { /* FIXME: Fall back to __INIT? */ } }
0ee38f2002-05-11Martin Stjernholm  } if (colon_colon_ref) {
4bd5202012-04-29Henrik Grubbström (Grubba)  int i = inherit_num;
0ee38f2002-05-11Martin Stjernholm  /* These are only recognized when prefixed with the :: operator. */
4bd5202012-04-29Henrik Grubbström (Grubba)  if (inherit_num < 0) i = 0;
0ee38f2002-05-11Martin Stjernholm  if(ident == lfun_strings[LFUN_ARROW] || ident == lfun_strings[LFUN_INDEX]) {
4bd5202012-04-29Henrik Grubbström (Grubba)  return mknode(F_MAGIC_INDEX, mknewintnode(i),
0ee38f2002-05-11Martin Stjernholm  mknewintnode(state_depth)); } else if(ident == lfun_strings[LFUN_ASSIGN_ARROW] || ident == lfun_strings[LFUN_ASSIGN_INDEX]) {
4bd5202012-04-29Henrik Grubbström (Grubba)  return mknode(F_MAGIC_SET_INDEX, mknewintnode(i),
0ee38f2002-05-11Martin Stjernholm  mknewintnode(state_depth)); } else if(ident == lfun_strings[LFUN__INDICES]) {
4bd5202012-04-29Henrik Grubbström (Grubba)  return mknode(F_MAGIC_INDICES, mknewintnode(i),
0ee38f2002-05-11Martin Stjernholm  mknewintnode(state_depth)); } else if(ident == lfun_strings[LFUN__VALUES]) {
4bd5202012-04-29Henrik Grubbström (Grubba)  return mknode(F_MAGIC_VALUES, mknewintnode(i),
0ee38f2002-05-11Martin Stjernholm  mknewintnode(state_depth));
7195af2011-01-15Henrik Grubbström (Grubba)  } else if(ident == lfun_strings[LFUN__TYPES]) {
4bd5202012-04-29Henrik Grubbström (Grubba)  return mknode(F_MAGIC_TYPES, mknewintnode(i),
7195af2011-01-15Henrik Grubbström (Grubba)  mknewintnode(state_depth));
0ee38f2002-05-11Martin Stjernholm  }
4bd5202012-04-29Henrik Grubbström (Grubba)  if (inherit_num && !TEST_COMPAT(7, 8) && (state->new_program->num_inherits > 1)) { /* Check if there's an inherited lfun::`->() that we can call. */ int id; struct program *prog = state->new_program->inherits[i].prog; if (((id = FIND_LFUN(prog, LFUN_ARROW)) == -1) && (prog == state->new_program)) { /* We are allowed to see private symbols in ourselves... */ id = really_low_find_shared_string_identifier(lfun_strings[LFUN_ARROW], prog, SEE_PROTECTED|SEE_PRIVATE); } else if ((id != -1) && (prog != state->new_program)) { id = really_low_reference_inherited_identifier(state, i, id); } if ((id != -1) && (state->compiler_pass == 2)) { if (inherit_num < 0) { /* Find the closest inherit containing the lfun::`->() * that is about to be called. * * In the single inherit case, this will always * result in inherit_num == 1. */ struct inherit *inherits = state->new_program->inherits; inherit_num = PTR_FROM_INT(state->new_program, id)->inherit_offset; while (inherits[inherit_num].inherit_level > 1) { inherit_num--; } } return mknode(F_APPLY, mkexternalnode(state->new_program, id), mknode(F_ARG_LIST, mkstrnode(ident), mknode(F_ARG_LIST, mkthisnode(state->new_program, inherit_num), mkintnode(1)))); } }
0ee38f2002-05-11Martin Stjernholm  } return NULL; }
bad5162000-06-23Fredrik Hübinette (Hubbe) /* Fixme: allow level=0 to return the current level */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) struct program *parent_compilation(int level) {
8853882008-04-26Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  int n;
bad5162000-06-23Fredrik Hübinette (Hubbe)  struct program_state *p=Pike_compiler->previous;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  for(n=0;n<level;n++) {
8853882008-04-26Henrik Grubbström (Grubba)  if(n>=c->compilation_depth) return 0;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  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];
b8cda21997-01-21Fredrik Hübinette (Hubbe) struct program *id_to_program(INT32 id) {
fa93a52008-02-28Henrik Grubbström (Grubba)  struct program_state *state;
b8cda21997-01-21Fredrik Hübinette (Hubbe)  struct program *p;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  INT32 h; if(!id) return 0;
f84d282004-12-08Henrik Grubbström (Grubba)  /* fprintf(stderr, "id_to_program(%d)... ", id); */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  h=id & (ID_TO_PROGRAM_CACHE_SIZE-1); if((p=id_to_program_cache[h]))
f84d282004-12-08Henrik Grubbström (Grubba)  if(p->id==id) { /* fprintf(stderr, "cached: %p\n", p); */
61e9a01998-01-25Fredrik Hübinette (Hubbe)  return p;
f84d282004-12-08Henrik Grubbström (Grubba)  }
27ae842000-02-07Per Hedbor 
a382372001-07-02Henrik Grubbström (Grubba)  for(p=first_program;p;p=p->next) { if(id==p->id)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  {
a382372001-07-02Henrik Grubbström (Grubba)  id_to_program_cache[h]=p;
f84d282004-12-08Henrik Grubbström (Grubba)  /* fprintf(stderr, "found: %p\n", p); */
a382372001-07-02Henrik Grubbström (Grubba)  return p; } }
fa93a52008-02-28Henrik Grubbström (Grubba)  /* Check if it is a program being compiled right now. */ for (state = Pike_compiler; state; state = state->previous) { if (state->new_program && state->new_program->id == id) { return state->new_program; } }
a382372001-07-02Henrik Grubbström (Grubba)  if ((id > 0) && (id < PROG_DYNAMIC_ID_START)) { /* Reserved id. Attempt to load the proper dynamic module * to resolv the id. */ char *module = NULL;
f84d282004-12-08Henrik Grubbström (Grubba)  /* fprintf(stderr, "reserved "); */
a382372001-07-02Henrik Grubbström (Grubba)  switch(id) { case PROG_PARSER_HTML_ID:
fd0fd72004-04-17Marcus Comstedt  module = "Parser._parser";
a382372001-07-02Henrik Grubbström (Grubba)  break; case PROG_GMP_MPZ_ID:
fd0fd72004-04-17Marcus Comstedt  module = "Gmp";
a382372001-07-02Henrik Grubbström (Grubba)  break; case PROG_MODULE_MIME_ID:
fd0fd72004-04-17Marcus Comstedt  module = "___MIME";
a382372001-07-02Henrik Grubbström (Grubba)  break; default:
62093a2013-11-08Henrik Grubbström (Grubba)  if ((id >= 100) && (id < 300)) {
fd0fd72004-04-17Marcus Comstedt  module = "Image";
62093a2013-11-08Henrik Grubbström (Grubba)  } else if ((id >= 300) && (id < 400)) { module = "Nettle";
b52ea32005-11-06Henrik Grubbström (Grubba)  } else if ((id >= 1000) && (id < 2000)) {
5c5d242004-03-02Henrik Grubbström (Grubba)  module = "___GTK";
b52ea32005-11-06Henrik Grubbström (Grubba)  } else if ((id >= 2000) && (id < 3000)) { module = "___GTK2";
a382372001-07-02Henrik Grubbström (Grubba)  } break; }
0e2c512009-08-18Henrik Grubbström (Grubba)  if (module && get_master()) {
f84d282004-12-08Henrik Grubbström (Grubba)  /* fprintf(stderr, "%s... ", module); */
a382372001-07-02Henrik Grubbström (Grubba)  push_text(module); SAFE_APPLY_MASTER("resolv", 1); pop_stack(); /* Try again... */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  for(p=first_program;p;p=p->next)
a382372001-07-02Henrik Grubbström (Grubba)  { if(id==p->id)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  {
a382372001-07-02Henrik Grubbström (Grubba)  id_to_program_cache[h]=p;
f84d282004-12-08Henrik Grubbström (Grubba)  /* fprintf(stderr, "found: %p\n", p); */
a382372001-07-02Henrik Grubbström (Grubba)  return p;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
a382372001-07-02Henrik Grubbström (Grubba)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
a382372001-07-02Henrik Grubbström (Grubba)  }
f84d282004-12-08Henrik Grubbström (Grubba)  /* fprintf(stderr, "not found\n"); */
591c0c1997-01-19Fredrik Hübinette (Hubbe)  return 0; }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) /* Here starts routines which are used to build new programs */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
6f96692009-09-12Henrik Grubbström (Grubba) /* * A typical program goes through the following steps: * * allocate_program ==> PROGRAM_VIRGIN * * start_program ==> !PROGRAM_VIRGIN * * end_first_pass ==> PROGRAM_PASS_1_DONE * * fixate_program ==> PROGRAM_FIXED * * optimize_program ==> PROGRAM_OPTIMIZED * * end_first_pass(1) ==> PROGRAM_FINISHED */
29615e2014-10-18Henrik Grubbström (Grubba) /** * Re-allocate all the memory in the program in one chunk. because: * @b 1) The individual blocks are much bigger than they need to be * @b 2) cuts down on malloc overhead (maybe) * @b 3) localizes memory access (decreases paging)
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) void optimize_program(struct program *p) {
080b1a2000-08-10Henrik Grubbström (Grubba)  size_t size=0;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  char *data; /* Already done (shouldn't happen, but who knows?) */ if(p->flags & PROGRAM_OPTIMIZED) return;
d717352005-05-25Henrik Grubbström (Grubba) #ifdef PIKE_USE_MACHINE_CODE /* Don't move our mexec-allocated memory into the malloc... */ #define BAR(NUMTYPE,TYPE,ARGTYPE,NAME) #endif /* PIKE_USE_MACHINE_CODE */
7e877a2003-04-02Martin Stjernholm #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \
1994981998-04-07Fredrik Hübinette (Hubbe)  size=DO_ALIGN(size, ALIGNOF(TYPE)); \ size+=p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0]);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #include "program_areas.h" data=malloc(size);
f822262001-07-16Fredrik Hübinette (Hubbe)  if(!data) { make_program_executable(p); return; /* We are out of memory, but we don't care! */ }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  size=0;
d717352005-05-25Henrik Grubbström (Grubba) #ifdef PIKE_USE_MACHINE_CODE /* As above. */ #define BAR(NUMTYPE,TYPE,ARGTYPE,NAME) #endif /* PIKE_USE_MACHINE_CODE */
7e877a2003-04-02Martin Stjernholm #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \
1994981998-04-07Fredrik Hübinette (Hubbe)  size=DO_ALIGN(size, ALIGNOF(TYPE)); \
37cd452003-06-09Martin Stjernholm  if (p->PIKE_CONCAT (num_, NAME)) \
59fc9e2014-09-03Martin Nilsson  memcpy(data+size,p->NAME,p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0])); \
302ede2001-07-19Henrik Grubbström (Grubba)  PIKE_CONCAT(RELOCATE_,NAME)(p, (TYPE *)(data+size)); \
1937952002-12-08Henrik Grubbström (Grubba)  dmfree(p->NAME); \
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  p->NAME=(TYPE *)(data+size); \
1994981998-04-07Fredrik Hübinette (Hubbe)  size+=p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0]);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #include "program_areas.h" p->total_size=size + sizeof(struct program); p->flags |= PROGRAM_OPTIMIZED;
f822262001-07-16Fredrik Hübinette (Hubbe)  make_program_executable(p);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) /* internal function to make the index-table */
8288152003-06-30Martin Stjernholm static int program_identifier_index_compare(int a, int b, const struct program *p)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) {
8288152003-06-30Martin Stjernholm  size_t val_a = PTR_TO_INT (ID_FROM_INT(p, a)->name); size_t val_b = PTR_TO_INT (ID_FROM_INT(p, b)->name);
2fb9862008-09-04Henrik Grubbström (Grubba)  return val_a < val_b ? -1 : (val_a == val_b ? (a < b? -1:(a != b)) : 1);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) }
ab9db52003-02-20Henrik Grubbström (Grubba) #define CMP(X,Y) program_identifier_index_compare(*(X), *(Y), prog) #define EXTRA_ARGS , struct program *prog #define XARGS , prog #define ID fsort_program_identifier_index #define TYPE unsigned short #include "fsort_template.h" #undef TYPE #undef ID #undef XARGS #undef EXTRA_ARGS #undef CMP
a4033e2000-04-14Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
ef24a82012-01-12Henrik Grubbström (Grubba) struct pike_string *find_program_name(struct program *p, INT_TYPE *line)
a4033e2000-04-14Fredrik Hübinette (Hubbe) {
ef24a82012-01-12Henrik Grubbström (Grubba)  INT_TYPE l;
cd86322000-07-06Fredrik Hübinette (Hubbe)  if(!line) line=&l;
a4033e2000-04-14Fredrik Hübinette (Hubbe)  #ifdef DEBUG_MALLOC
50edc82001-07-13Henrik Grubbström (Grubba)  {
ce3d2f2014-10-01Martin Nilsson  const char *tmp=dmalloc_find_name(p);
a275d22003-03-29Martin Stjernholm  if (tmp) {
5aa54c2014-09-03Martin Nilsson  char *p = strchr (tmp, ':');
a275d22003-03-29Martin Stjernholm  if (p) { char *pp;
5aa54c2014-09-03Martin Nilsson  while ((pp = strchr (p + 1, ':'))) p = pp;
a275d22003-03-29Martin Stjernholm  *line = atoi (p + 1); return make_shared_binary_string (tmp, p - tmp); } else { *line=0; return make_shared_string(tmp); } }
50edc82001-07-13Henrik Grubbström (Grubba)  }
a4033e2000-04-14Fredrik Hübinette (Hubbe) #endif
4f985f2001-06-30Martin Stjernholm  return get_program_line(p, line);
a4033e2000-04-14Fredrik Hübinette (Hubbe) } #endif
aaf40c2013-11-03Henrik Grubbström (Grubba) int override_identifier (struct reference *new_ref, struct pike_string *name, int required_flags)
5ec1062002-05-09Martin Stjernholm {
e021fe2008-04-14Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
1f7f172007-10-11Henrik Grubbström (Grubba)  int id = -1, cur_id = 0, is_used = 0;
c2060d2003-06-06Henrik Grubbström (Grubba)  int new_is_variable = IDENTIFIER_IS_VARIABLE(ID_FROM_PTR(Pike_compiler->new_program,
1f7f172007-10-11Henrik Grubbström (Grubba)  new_ref)->identifier_flags);
c2060d2003-06-06Henrik Grubbström (Grubba) 
5ec1062002-05-09Martin Stjernholm  /* This loop could possibly be optimized by looping over * each inherit and looking up 'name' in each inherit * and then see if should be overwritten * /Hubbe */
e021fe2008-04-14Henrik Grubbström (Grubba)  CHECK_COMPILER();
5ec1062002-05-09Martin Stjernholm  for(;cur_id<Pike_compiler->new_program->num_identifier_references;cur_id++) {
1f7f172007-10-11Henrik Grubbström (Grubba)  struct reference *ref = Pike_compiler->new_program->identifier_references + cur_id; struct identifier *i; /* No need to do anything for ourselves. */ if (ref == new_ref) continue;
5ec1062002-05-09Martin Stjernholm  /* Do not zapp hidden identifiers */
1f7f172007-10-11Henrik Grubbström (Grubba)  if(ref->id_flags & ID_HIDDEN) continue;
5ec1062002-05-09Martin Stjernholm 
2c740d2013-05-26Henrik Grubbström (Grubba)  if(ref->id_flags & ID_VARIANT) continue;
aaf40c2013-11-03Henrik Grubbström (Grubba)  if ((ref->id_flags & required_flags) != required_flags) continue;
5ec1062002-05-09Martin Stjernholm  /* Do not zapp functions with the wrong name... */
1f7f172007-10-11Henrik Grubbström (Grubba)  if((i = ID_FROM_PTR(Pike_compiler->new_program, ref))->name != name)
5ec1062002-05-09Martin Stjernholm  continue;
b3d3262009-08-18Henrik Grubbström (Grubba)  /* Do not zapp inherited inline ('local') identifiers, * or inherited externals with new externals, * since this makes it hard to identify in encode_value(). */ if((ref->id_flags & (ID_INLINE|ID_INHERITED)) == (ID_INLINE|ID_INHERITED) || (ref->id_flags & new_ref->id_flags & ID_EXTERN)) {
fcaec32008-09-14Henrik Grubbström (Grubba)  /* But we still need to hide them, since we shadow them... */ ref->id_flags |= ID_HIDDEN; continue; }
5ec1062002-05-09Martin Stjernholm #ifdef PROGRAM_BUILD_DEBUG fprintf(stderr, "%.*soverloaded reference %d (id_flags:0x%04x)\n",
8853882008-04-26Henrik Grubbström (Grubba)  c->compilation_depth, "", cur_id, ref->id_flags);
5ec1062002-05-09Martin Stjernholm #endif
1f7f172007-10-11Henrik Grubbström (Grubba)  if (!new_is_variable && IDENTIFIER_IS_VARIABLE(i->identifier_flags)) {
fa6afc2003-06-06Henrik Grubbström (Grubba)  /* Overloading a variable with a constant or a function. * This is generally a bad idea. */
1f7f172007-10-11Henrik Grubbström (Grubba)  ref->id_flags |= ID_INLINE|ID_HIDDEN;
ce060e2004-06-30Martin Nilsson  yywarning("Attempt to override a non local variable %S "
1f7f172007-10-11Henrik Grubbström (Grubba)  "with a non-variable.", name);
c2060d2003-06-06Henrik Grubbström (Grubba)  continue; }
1f7f172007-10-11Henrik Grubbström (Grubba)  if ((ref->id_flags & (ID_INHERITED|ID_USED)) == (ID_INHERITED|ID_USED)) { struct inherit *inh = INHERIT_FROM_PTR(Pike_compiler->new_program, ref); struct reference *sub_ref; /* Find the inherit one level away. */ while (inh->inherit_level > 1) inh--;
c2a9522013-06-08Henrik Grubbström (Grubba) #if 0
1f7f172007-10-11Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG if (!inh->inherit_level) {
c2a9522013-06-08Henrik Grubbström (Grubba)  /* FIXME: This is valid for references that are about to be * overridden by the variant dispatcher. */
1f7f172007-10-11Henrik Grubbström (Grubba)  Pike_fatal("Inherit without intermediate levels.\n"); }
c2a9522013-06-08Henrik Grubbström (Grubba) #endif
1f7f172007-10-11Henrik Grubbström (Grubba) #endif sub_ref = PTR_FROM_INT(inh->prog, cur_id - inh->identifier_level); /* Check if the symbol was used before it was inherited. */
e021fe2008-04-14Henrik Grubbström (Grubba)  if ((c->lex.pragmas & ID_STRICT_TYPES) &&
6f25b52007-10-12Henrik Grubbström (Grubba)  (sub_ref->id_flags & ID_USED)) {
30893e2007-10-12Henrik Grubbström (Grubba)  struct identifier *sub_id = ID_FROM_PTR(inh->prog, sub_ref); if (IDENTIFIER_IS_FUNCTION(sub_id->identifier_flags)) {
467e512007-11-15Henrik Grubbström (Grubba)  if ((Pike_compiler->compiler_pass == 2) && !pike_types_le(ID_FROM_PTR(Pike_compiler->new_program,
30893e2007-10-12Henrik Grubbström (Grubba)  new_ref)->type, sub_id->type)) {
94d66b2008-05-24Henrik Grubbström (Grubba)  yytype_report(REPORT_WARNING, NULL, 0, sub_id->type, NULL, 0, ID_FROM_PTR(Pike_compiler->new_program, new_ref)->type, 0, "Type mismatch when overloading function %S.", name);
30893e2007-10-12Henrik Grubbström (Grubba)  } } else {
01c4792008-02-03Henrik Grubbström (Grubba)  struct identifier *new_id; /* Variable or constant. *
8e488c2008-02-03Henrik Grubbström (Grubba)  * Note: Use weaker check for integers (especially for constants).
01c4792008-02-03Henrik Grubbström (Grubba)  */
30893e2007-10-12Henrik Grubbström (Grubba)  if (!pike_types_le(sub_id->type,
01c4792008-02-03Henrik Grubbström (Grubba)  (new_id = ID_FROM_PTR(Pike_compiler->new_program, new_ref))->type) && !((i->run_time_type == PIKE_T_INT) && (new_id->run_time_type == PIKE_T_INT) &&
8e488c2008-02-03Henrik Grubbström (Grubba)  (IDENTIFIER_IS_CONSTANT(sub_id->identifier_flags) || match_types(sub_id->type, new_id->type)))) {
94d66b2008-05-24Henrik Grubbström (Grubba)  yytype_report(REPORT_WARNING, NULL, 0, sub_id->type, NULL, 0, new_id->type, 0, "Type mismatch when overloading %S.", name);
30893e2007-10-12Henrik Grubbström (Grubba)  }
1f7f172007-10-11Henrik Grubbström (Grubba)  } } } is_used = ref->id_flags & ID_USED; *ref=*new_ref; ref->id_flags |= is_used;
5ec1062002-05-09Martin Stjernholm  id = cur_id; } return id; }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) void fixate_program(void) {
e021fe2008-04-14Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  INT32 i,e,t;
3b7d182001-09-26Fredrik Hübinette (Hubbe)  struct program *p=Pike_compiler->new_program;
e021fe2008-04-14Henrik Grubbström (Grubba)  CHECK_COMPILER();
3b7d182001-09-26Fredrik Hübinette (Hubbe)  if(p->flags & PROGRAM_FIXED) return;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
3b7d182001-09-26Fredrik Hübinette (Hubbe)  if(p->flags & PROGRAM_OPTIMIZED)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Cannot fixate optimized program\n");
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #endif
354bbe2007-09-24Henrik Grubbström (Grubba)  /* Fixup the runtime type for functions. * (T_MIXED is used as the tentative type marker in pass 1). */
da371d2003-11-18Henrik Grubbström (Grubba)  for (i=0; i < p->num_identifiers; i++) {
354bbe2007-09-24Henrik Grubbström (Grubba)  if (IDENTIFIER_IS_FUNCTION(p->identifiers[i].identifier_flags) && (p->identifiers[i].run_time_type == T_MIXED)) { /* Get rid of the remaining tentative type marker. */ /* FIXME: Should probably never be reachable.
0a74382009-06-21Henrik Grubbström (Grubba)  * Consider this a fatal?
354bbe2007-09-24Henrik Grubbström (Grubba)  */ p->identifiers[i].run_time_type = T_FUNCTION;
da371d2003-11-18Henrik Grubbström (Grubba)  } }
7571282003-06-03Martin Stjernholm  /* Fixup identifier overrides. */ for (i = 0; i < p->num_identifier_references; i++) { struct reference *ref = p->identifier_references + i; if (ref->id_flags & ID_HIDDEN) continue;
2c740d2013-05-26Henrik Grubbström (Grubba)  if (ref->id_flags & ID_VARIANT) continue;
7571282003-06-03Martin Stjernholm  if (ref->inherit_offset != 0) continue;
aaf40c2013-11-03Henrik Grubbström (Grubba)  override_identifier (ref, ID_FROM_PTR (p, ref)->name, 0);
7571282003-06-03Martin Stjernholm  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  /* Ok, sort for binsearch */
3b7d182001-09-26Fredrik Hübinette (Hubbe)  for(e=i=0;i<(int)p->num_identifier_references;i++)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  { struct reference *funp; struct identifier *fun;
3b7d182001-09-26Fredrik Hübinette (Hubbe)  funp=p->identifier_references+i;
7221342007-09-04Henrik Grubbström (Grubba)  if(funp->id_flags & ID_HIDDEN) continue;
2c740d2013-05-26Henrik Grubbström (Grubba)  if(funp->id_flags & ID_VARIANT) continue;
e18d902002-04-26Henrik Grubbström (Grubba)  fun=ID_FROM_PTR(p, funp);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(funp->id_flags & ID_INHERITED) {
3b7d182001-09-26Fredrik Hübinette (Hubbe)  int found_better=-1; int funa_is_prototype;
2e1a6a2008-05-29Henrik Grubbström (Grubba)  /* NOTE: Mixin is currently not supported for PRIVATE symbols. */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(funp->id_flags & ID_PRIVATE) continue;
3b7d182001-09-26Fredrik Hübinette (Hubbe)  funa_is_prototype = fun->func.offset == -1; /* if(fun->func.offset == -1) continue; * prototype */
27ae842000-02-07Per Hedbor 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  /* check for multiple definitions */
3b7d182001-09-26Fredrik Hübinette (Hubbe)  for(t=i+1;t<(int)p->num_identifier_references;t++)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  { struct reference *funpb; struct identifier *funb;
27ae842000-02-07Per Hedbor 
3b7d182001-09-26Fredrik Hübinette (Hubbe)  funpb=p->identifier_references+t;
7221342007-09-04Henrik Grubbström (Grubba)  if (funpb->id_flags & ID_HIDDEN) continue;
2c740d2013-05-26Henrik Grubbström (Grubba)  if (funpb->id_flags & ID_VARIANT) continue;
3b7d182001-09-26Fredrik Hübinette (Hubbe)  funb=ID_FROM_PTR(p,funpb);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  /* if(funb->func.offset == -1) continue; * prototype */
3b7d182001-09-26Fredrik Hübinette (Hubbe)  if(fun->name==funb->name) {
0a74382009-06-21Henrik Grubbström (Grubba)  if (!(funpb->id_flags & ID_PROTECTED)) { /* Only regard this symbol as better if it * will end up in the index further below. */ found_better=t; }
d89fa12002-04-26Henrik Grubbström (Grubba)  /* FIXME: Is this stuff needed? * It looks like it already is done by define_function().
7221342007-09-04Henrik Grubbström (Grubba)  * * Yes -- It's needed in case of mixin.
d89fa12002-04-26Henrik Grubbström (Grubba)  */ if(funa_is_prototype && (funb->func.offset != -1) && !(funp->id_flags & ID_INLINE))
3b7d182001-09-26Fredrik Hübinette (Hubbe)  {
e021fe2008-04-14Henrik Grubbström (Grubba)  if ((c->lex.pragmas & ID_STRICT_TYPES) &&
6f25b52007-10-12Henrik Grubbström (Grubba)  (funp->id_flags & ID_USED)) {
1f7f172007-10-11Henrik Grubbström (Grubba)  /* Verify that the types are compatible. */
30893e2007-10-12Henrik Grubbström (Grubba)  if (!pike_types_le(funb->type, fun->type)) {
94d66b2008-05-24Henrik Grubbström (Grubba)  yytype_report(REPORT_WARNING, NULL, 0, fun->type, NULL, 0, funb->type, 0, "Type mismatch when overloading %S.", fun->name);
1f7f172007-10-11Henrik Grubbström (Grubba)  } }
3b7d182001-09-26Fredrik Hübinette (Hubbe)  funp->inherit_offset = funpb->inherit_offset; funp->identifier_offset = funpb->identifier_offset; } if(!funa_is_prototype && funb->func.offset == -1) {
e021fe2008-04-14Henrik Grubbström (Grubba)  if ((c->lex.pragmas & ID_STRICT_TYPES) &&
6f25b52007-10-12Henrik Grubbström (Grubba)  (funpb->id_flags & ID_USED)) {
1f7f172007-10-11Henrik Grubbström (Grubba)  /* Verify that the types are compatible. */
30893e2007-10-12Henrik Grubbström (Grubba)  if (!pike_types_le(fun->type, funb->type)) {
94d66b2008-05-24Henrik Grubbström (Grubba)  yytype_report(REPORT_WARNING, NULL, 0, funb->type, NULL, 0, fun->type, 0, "Type mismatch when overloading %S.", fun->name);
1f7f172007-10-11Henrik Grubbström (Grubba)  } }
3b7d182001-09-26Fredrik Hübinette (Hubbe)  funpb->inherit_offset = funp->inherit_offset; funpb->identifier_offset = funp->identifier_offset; } }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
3b7d182001-09-26Fredrik Hübinette (Hubbe)  if(found_better!=-1) continue;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
a542da2008-01-24Martin Stjernholm  if (IDENTIFIER_IS_PIKE_FUNCTION(fun->identifier_flags) && (fun->func.offset == -1) && (funp->id_flags & ID_INLINE)) {
2c448d2004-11-05Henrik Grubbström (Grubba)  my_yyerror("Missing definition for local function %S.", fun->name);
e18d902002-04-26Henrik Grubbström (Grubba)  }
95489a2008-06-29Martin Nilsson  if (funp->id_flags & ID_PROTECTED) continue;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  add_to_identifier_index(i); }
ab9db52003-02-20Henrik Grubbström (Grubba)  fsort_program_identifier_index(p->identifier_index, p->identifier_index + p->num_identifier_index - 1, p);
27ae842000-02-07Per Hedbor 
2fb9862008-09-04Henrik Grubbström (Grubba)  /* Take care of duplicates in the identifier index table; * this can happen eg when the overloading definition is * before an inherit being overloaded. This happens for * eg the default master object. */ if (p->num_identifier_index) { struct identifier *id = ID_FROM_INT(p, p->identifier_index[0]); for (e = i = 1; e < p->num_identifier_index; e++) { struct identifier *probe = ID_FROM_INT(p, p->identifier_index[e]); if (probe == id) { /* Duplicate. */ continue; } p->identifier_index[i++] = p->identifier_index[e]; id = probe; } p->num_identifier_index = i; }
27ae842000-02-07Per Hedbor 
9a20092003-12-30Henrik Grubbström (Grubba)  p->flags |= PROGRAM_FIXED;
a5787d1999-03-03Fredrik Hübinette (Hubbe)  /* Yes, it is supposed to start at 1 /Hubbe */
87d5c52000-02-16Henrik Grubbström (Grubba)  for(i=1;i<NUM_LFUNS;i++) {
cb17be2007-10-24Henrik Grubbström (Grubba)  int id = p->lfuns[i] = low_find_lfun(p, i);
ca9e402012-10-09Henrik Grubbström (Grubba)  if (id >= 0) { // LFUNs are used. p->identifier_references[id].id_flags |= ID_USED; } } /* Complain about unused private symbols. */ for (i = 0; i < p->num_identifier_references; i++) { struct reference *ref = p->identifier_references + i; if (ref->id_flags & ID_HIDDEN) continue;
2c740d2013-05-26Henrik Grubbström (Grubba)  if (ref->id_flags & ID_VARIANT) continue;
ca9e402012-10-09Henrik Grubbström (Grubba)  if (ref->inherit_offset != 0) continue; if ((ref->id_flags & (ID_HIDDEN|ID_PRIVATE|ID_USED)) == ID_PRIVATE) { yywarning("%S is private but not used anywhere.", ID_FROM_PTR(p, ref)->name); }
2c17091999-06-22Fredrik Hübinette (Hubbe)  }
99cce52007-05-26Martin Stjernholm  /* Set the PROGRAM_LIVE_OBJ flag by looking for destroy() and * inherited PROGRAM_LIVE_OBJ flags. This is done at fixation time * to allow the user to set and clear that flag while the program is * being built. */ if (!(p->flags & PROGRAM_LIVE_OBJ)) { int e, destroy = p->lfuns[LFUN_DESTROY]; if (destroy > -1) { struct identifier *id = ID_FROM_INT (p, destroy); if (!IDENTIFIER_IS_PIKE_FUNCTION (id->identifier_flags) || id->func.offset != -1) { /* Got a destroy function that isn't a prototype. */ p->flags |= PROGRAM_LIVE_OBJ; goto program_live_obj_set; } } for (e = p->num_inherits - 1; e >= 0; e--) if (p->inherits[e].prog->flags & PROGRAM_LIVE_OBJ) { p->flags |= PROGRAM_LIVE_OBJ; break; } program_live_obj_set:; }
cd2be32004-03-13Henrik Grubbström (Grubba)  if(Pike_compiler->flags & COMPILATION_CHECK_FINAL)
3b7d182001-09-26Fredrik Hübinette (Hubbe)  { for(i=0;i<(int)p->num_identifier_references;i++) {
ab0d472007-12-28Martin Nilsson  if((p->identifier_references[i].id_flags & (ID_FINAL|ID_HIDDEN)) == ID_FINAL)
3b7d182001-09-26Fredrik Hübinette (Hubbe)  { struct pike_string *name=ID_FROM_INT(p, i)->name; e=find_shared_string_identifier(name,p);
5a071a2001-10-02Fredrik Hübinette (Hubbe)  if(e == -1)
e9900c2002-04-17Henrik Grubbström (Grubba)  e=really_low_find_shared_string_identifier(name, p,
6530932008-06-29Martin Nilsson  SEE_PROTECTED|SEE_PRIVATE);
5a071a2001-10-02Fredrik Hübinette (Hubbe) 
2659cf2002-05-10Henrik Grubbström (Grubba)  if((e != i) && (e != -1))
3b7d182001-09-26Fredrik Hübinette (Hubbe)  {
2c448d2004-11-05Henrik Grubbström (Grubba)  my_yyerror("Illegal to redefine final identifier %S", name);
3b7d182001-09-26Fredrik Hübinette (Hubbe)  } } } }
98bc6f2001-09-27Henrik Grubbström (Grubba) 
1e4e5f2000-04-07Fredrik Hübinette (Hubbe) #ifdef DEBUG_MALLOC { #define DBSTR(X) ((X)?(X)->str:"") int e,v;
ef24a82012-01-12Henrik Grubbström (Grubba)  INT_TYPE line;
50edc82001-07-13Henrik Grubbström (Grubba)  struct pike_string *tmp;
a4033e2000-04-14Fredrik Hübinette (Hubbe)  struct memory_map *m=0;;
e021fe2008-04-14Henrik Grubbström (Grubba)  if(c->lex.current_file && c->lex.current_file->str && c->lex.current_file->len && !strcmp(c->lex.current_file->str,"-"))
a4033e2000-04-14Fredrik Hübinette (Hubbe)  {
e021fe2008-04-14Henrik Grubbström (Grubba)  m=dmalloc_alloc_mmap( DBSTR(c->lex.current_file), c->lex.current_line);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  }
bad5162000-06-23Fredrik Hübinette (Hubbe)  else if( (tmp=find_program_name(Pike_compiler->new_program, &line)) )
a4033e2000-04-14Fredrik Hübinette (Hubbe)  {
50edc82001-07-13Henrik Grubbström (Grubba)  m=dmalloc_alloc_mmap( tmp->str, line); free_string(tmp);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  }else{
bad5162000-06-23Fredrik Hübinette (Hubbe)  m=dmalloc_alloc_mmap( "program id", Pike_compiler->new_program->id);
a4033e2000-04-14Fredrik Hübinette (Hubbe)  }
bad5162000-06-23Fredrik Hübinette (Hubbe)  for(e=0;e<Pike_compiler->new_program->num_inherits;e++)
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  {
bad5162000-06-23Fredrik Hübinette (Hubbe)  struct inherit *i=Pike_compiler->new_program->inherits+e;
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  char *tmp;
50edc82001-07-13Henrik Grubbström (Grubba)  struct pike_string *tmp2 = NULL;
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  char buffer[50]; for(v=0;v<i->prog->num_variable_index;v++) { int d=i->prog->variable_index[v]; struct identifier *id=i->prog->identifiers+d; dmalloc_add_mmap_entry(m, id->name->str,
648a1a2000-06-22Fredrik Hübinette (Hubbe)  /* OFFSETOF(object,storage) + */ i->storage_offset + id->func.offset,
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  sizeof_variable(id->run_time_type), 1, /* count */ 0,0); } if(i->name) { tmp=i->name->str;
a4033e2000-04-14Fredrik Hübinette (Hubbe)  }
50edc82001-07-13Henrik Grubbström (Grubba)  else if(!(tmp2 = find_program_name(i->prog, &line)))
a4033e2000-04-14Fredrik Hübinette (Hubbe)  { sprintf(buffer,"inherit[%d]",e); tmp=buffer;
50edc82001-07-13Henrik Grubbström (Grubba)  } else { tmp = tmp2->str;
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  } dmalloc_add_mmap_entry(m, tmp,
648a1a2000-06-22Fredrik Hübinette (Hubbe)  /* OFFSETOF(object, storage) + */ i->storage_offset,
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  i->prog->storage_needed - i->prog->inherits[0].storage_offset, 1, /* count */ 0,0);
50edc82001-07-13Henrik Grubbström (Grubba)  if (tmp2) { free_string(tmp2); }
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  }
bad5162000-06-23Fredrik Hübinette (Hubbe)  dmalloc_set_mmap_template(Pike_compiler->new_program, m);
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  } #endif
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
05590d1998-04-23Fredrik Hübinette (Hubbe) struct program *low_allocate_program(void) {
1c1c5e2001-04-08Fredrik Hübinette (Hubbe)  struct program *p=alloc_program();
21b12a2014-09-03Martin Nilsson  memset(p, 0, sizeof(struct program));
aa68b12001-03-19Fredrik Hübinette (Hubbe)  p->flags|=PROGRAM_VIRGIN;
90e9781999-01-31Fredrik Hübinette (Hubbe)  p->alignment_needed=1;
27ae842000-02-07Per Hedbor 
7bf6232000-04-23Martin Stjernholm  GC_ALLOC(p);
05590d1998-04-23Fredrik Hübinette (Hubbe)  p->id=++current_program_id;
9386322011-07-21Henrik Grubbström (Grubba)  INIT_PIKE_MEMOBJ(p, T_PROGRAM);
27ae842000-02-07Per Hedbor 
e2d9e62000-06-10Martin Stjernholm  DOUBLELINK(first_program, p);
f010202011-11-16Tobias S. Josefowitz  ACCURATE_GETTIMEOFDAY(& p->timestamp);
05590d1998-04-23Fredrik Hübinette (Hubbe)  return p; }
29615e2014-10-18Henrik Grubbström (Grubba) /**
5267b71995-08-09Fredrik Hübinette (Hubbe)  * Start building a new program */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) void low_start_new_program(struct program *p,
7571282003-06-03Martin Stjernholm  int pass,
993ba72000-02-15Fredrik Hübinette (Hubbe)  struct pike_string *name, int flags, int *idp)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
e021fe2008-04-14Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
7571282003-06-03Martin Stjernholm  int id=0;
993ba72000-02-15Fredrik Hübinette (Hubbe)  struct svalue tmp;
5c8e891995-10-29Fredrik Hübinette (Hubbe) 
e021fe2008-04-14Henrik Grubbström (Grubba)  CHECK_COMPILER();
8b5b3a2014-04-28Henrik Grubbström (Grubba)  /* We aren't thread safe, but we are reentrant. * * Lock out any other threads from the compiler until we are finished.
58544f1998-07-17Henrik Grubbström (Grubba)  */
8b5b3a2014-04-28Henrik Grubbström (Grubba)  lock_pike_compiler();
a91ca01998-07-10Henrik Grubbström (Grubba) 
8853882008-04-26Henrik Grubbström (Grubba)  c->compilation_depth++;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL_TYPE(tmp, T_PROGRAM);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(!p) {
05590d1998-04-23Fredrik Hübinette (Hubbe)  p=low_allocate_program();
993ba72000-02-15Fredrik Hübinette (Hubbe)  if(name) { tmp.u.program=p; id=add_constant(name, &tmp, flags & ~ID_EXTERN);
51717a2001-04-09Fredrik Hübinette (Hubbe) #if 0
8853882008-04-26Henrik Grubbström (Grubba)  fprintf(stderr,"Compiling class %s, depth=%d\n", name->str, c->compilation_depth);
51717a2001-04-09Fredrik Hübinette (Hubbe)  }else{ fprintf(stderr,"Compiling file %s, depth=%d\n",
e021fe2008-04-14Henrik Grubbström (Grubba)  c->lex.current_file ? c->lex.current_file->str : "-",
8853882008-04-26Henrik Grubbström (Grubba)  c->compilation_depth);
51717a2001-04-09Fredrik Hübinette (Hubbe) #endif
993ba72000-02-15Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }else{
993ba72000-02-15Fredrik Hübinette (Hubbe)  tmp.u.program=p;
8c83371998-04-16Fredrik Hübinette (Hubbe)  add_ref(p);
7d65752003-06-04Henrik Grubbström (Grubba)  if((pass == 2) && name)
993ba72000-02-15Fredrik Hübinette (Hubbe)  { struct identifier *i; id=isidentifier(name); if (id < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Program constant disappeared in second pass.\n");
bad5162000-06-23Fredrik Hübinette (Hubbe)  i=ID_FROM_INT(Pike_compiler->new_program, id);
d68a072001-02-20Henrik Grubbström (Grubba)  free_type(i->type);
993ba72000-02-15Fredrik Hübinette (Hubbe)  i->type=get_type_of_svalue(&tmp); }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
7d65752003-06-04Henrik Grubbström (Grubba)  if (pass == 1) {
3152712008-08-17Martin Stjernholm  if(c->compilation_depth >= 1) {
7d65752003-06-04Henrik Grubbström (Grubba)  add_ref(p->parent = Pike_compiler->new_program);
3152712008-08-17Martin Stjernholm  debug_malloc_touch (p); }
7d65752003-06-04Henrik Grubbström (Grubba)  }
aa68b12001-03-19Fredrik Hübinette (Hubbe)  p->flags &=~ PROGRAM_VIRGIN;
993ba72000-02-15Fredrik Hübinette (Hubbe)  if(idp) *idp=id;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
a359742001-12-16Martin Stjernholm  CDFPRINTF((stderr, "th(%ld) %p low_start_new_program() %s "
8b5b3a2014-04-28Henrik Grubbström (Grubba)  "pass=%d: lock_depth:%d, compilation_depth:%d\n",
a359742001-12-16Martin Stjernholm  (long)th_self(), p, name ? name->str : "-", Pike_compiler->compiler_pass,
8b5b3a2014-04-28Henrik Grubbström (Grubba)  lock_depth, c->compilation_depth));
cb67042001-12-12Martin Stjernholm 
fb2f661998-11-05Fredrik Hübinette (Hubbe)  init_type_stack();
5c8e891995-10-29Fredrik Hübinette (Hubbe) #define PUSH #include "compilation.h"
b8cda21997-01-21Fredrik Hübinette (Hubbe) 
44e3402013-10-09Arne Goedeke  ba_init(&Pike_compiler->node_allocator, sizeof(struct node_s), 512);
ddd9962008-04-06Henrik Grubbström (Grubba)  Pike_compiler->parent_identifier=id;
7571282003-06-03Martin Stjernholm  Pike_compiler->compiler_pass = pass;
e37a3e1999-10-09Fredrik Hübinette (Hubbe) 
5b84a52008-04-26Henrik Grubbström (Grubba)  Pike_compiler->num_used_modules=0; /* FIXME: Duplicate? */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
8f06122007-01-16Henrik Grubbström (Grubba)  if(p->flags & PROGRAM_FINISHED)
0683be1997-01-26Fredrik Hübinette (Hubbe)  {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  yyerror("Pass2: Program already done"); }
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->malloc_size_program = ALLOC_STRUCT(program); Pike_compiler->fake_object=alloc_object();
1937952002-12-08Henrik Grubbström (Grubba) 
379b682002-09-30Marcus Comstedt #ifdef PIKE_DEBUG
033d232007-01-16Henrik Grubbström (Grubba)  Pike_compiler->fake_object->storage=(char *)malloc(256 * sizeof(struct svalue)); if (Pike_compiler->fake_object->storage) { /* Stipple to find illegal accesses */
21b12a2014-09-03Martin Nilsson  memset(Pike_compiler->fake_object->storage,0x55,256*sizeof(struct svalue));
a161792010-04-10Martin Stjernholm  PIKE_MEM_WO_RANGE (Pike_compiler->fake_object->storage, 256 * sizeof (struct svalue));
033d232007-01-16Henrik Grubbström (Grubba)  }
6d22541998-01-28Fredrik Hübinette (Hubbe) #else
f3c7152001-04-14Fredrik Hübinette (Hubbe)  Pike_compiler->fake_object->storage=(char *)malloc(sizeof(struct parent_info));
6d22541998-01-28Fredrik Hübinette (Hubbe) #endif
033d232007-01-16Henrik Grubbström (Grubba)  if (!Pike_compiler->fake_object->storage) { yyerror("Out of memory when allocating object storage."); }
ddac672000-07-02Martin Stjernholm  /* Can't use GC_ALLOC on fake objects, but still it's good to know * that they never take over a stale gc marker. */ if (Pike_in_gc) remove_marker(Pike_compiler->fake_object);
6d22541998-01-28Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->fake_object->next=Pike_compiler->fake_object; Pike_compiler->fake_object->prev=Pike_compiler->fake_object;
50ea682003-03-14Henrik Grubbström (Grubba)  Pike_compiler->fake_object->refs=0; add_ref(Pike_compiler->fake_object); /* For DMALLOC... */
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->fake_object->prog=p;
3aa0db1999-10-22Henrik Grubbström (Grubba)  add_ref(p);
1e4e5f2000-04-07Fredrik Hübinette (Hubbe)  #ifdef PIKE_DEBUG
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->fake_object->program_id=p->id;
1e4e5f2000-04-07Fredrik Hübinette (Hubbe) #endif
bad5162000-06-23Fredrik Hübinette (Hubbe)  debug_malloc_touch(Pike_compiler->fake_object); debug_malloc_touch(Pike_compiler->fake_object->storage);
648a1a2000-06-22Fredrik Hübinette (Hubbe) 
033d232007-01-16Henrik Grubbström (Grubba)  if (Pike_compiler->fake_object->storage) { if(name) {
3152712008-08-17Martin Stjernholm  /* Fake objects have parents regardless of PROGRAM_USES_PARENT */
033d232007-01-16Henrik Grubbström (Grubba)  if((((struct parent_info *)Pike_compiler->fake_object->storage)->parent=Pike_compiler->previous->fake_object)) add_ref(Pike_compiler->previous->fake_object);
f3c7152001-04-14Fredrik Hübinette (Hubbe)  ((struct parent_info *)Pike_compiler->fake_object->storage)->parent_identifier=id;
033d232007-01-16Henrik Grubbström (Grubba)  }else{ ((struct parent_info *)Pike_compiler->fake_object->storage)->parent=0; ((struct parent_info *)Pike_compiler->fake_object->storage)->parent_identifier=0; }
6d22541998-01-28Fredrik Hübinette (Hubbe)  }
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->new_program=p;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
a786431999-11-18Martin Stjernholm #ifdef PROGRAM_BUILD_DEBUG if (name) { fprintf (stderr, "%.*sstarting program %d (pass=%d): ",
8853882008-04-26Henrik Grubbström (Grubba)  c->compilation_depth, "", Pike_compiler->new_program->id, Pike_compiler->compiler_pass);
a786431999-11-18Martin Stjernholm  push_string (name);
cd86322000-07-06Fredrik Hübinette (Hubbe)  print_svalue (stderr, --Pike_sp);
a786431999-11-18Martin Stjernholm  putc ('\n', stderr); } else fprintf (stderr, "%.*sstarting program %d (pass=%d)\n",
8853882008-04-26Henrik Grubbström (Grubba)  c->compilation_depth, "", Pike_compiler->new_program->id, Pike_compiler->compiler_pass);
a786431999-11-18Martin Stjernholm #endif
8853882008-04-26Henrik Grubbström (Grubba)  if (c->compilation_depth >= 1) {
ec80082014-08-24Martin Nilsson  if(c->lex.pragmas & ID_SAVE_PARENT)
2fbfc42002-06-11Martin Stjernholm  {
f397202002-06-12Martin Stjernholm  p->flags |= PROGRAM_USES_PARENT;
ec80082014-08-24Martin Nilsson  } else if (!(c->lex.pragmas & ID_DONT_SAVE_PARENT)) {
f397202002-06-12Martin Stjernholm  struct pike_string *tmp=findstring("__pragma_save_parent__"); if(tmp)
2fbfc42002-06-11Martin Stjernholm  {
f397202002-06-12Martin Stjernholm  struct node_s *n=find_module_identifier(tmp, 0); if(n) { int do_save_parent = !node_is_false(n); /* Default to true. */ free_node(n); if (do_save_parent) p->flags |= PROGRAM_USES_PARENT; }
2fbfc42002-06-11Martin Stjernholm  } } }
bad5162000-06-23Fredrik Hübinette (Hubbe)  debug_malloc_touch(Pike_compiler->fake_object); debug_malloc_touch(Pike_compiler->fake_object->storage);
648a1a2000-06-22Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->new_program->program)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  {
d717352005-05-25Henrik Grubbström (Grubba) #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ Pike_compiler->malloc_size_program->PIKE_CONCAT(num_,NAME) = \ Pike_compiler->new_program->PIKE_CONCAT(num_,NAME);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #include "program_areas.h"
1016021999-10-28Fredrik Hübinette (Hubbe)  {
ef24a82012-01-12Henrik Grubbström (Grubba)  INT_TYPE line = 0; INT32 off = 0;
50edc82001-07-13Henrik Grubbström (Grubba)  size_t len = 0; INT32 shift = 0;
547e582013-09-08Henrik Grubbström (Grubba)  struct pike_string *file=0;
bad5162000-06-23Fredrik Hübinette (Hubbe)  char *cnt=Pike_compiler->new_program->linenumbers;
27ae842000-02-07Per Hedbor 
50edc82001-07-13Henrik Grubbström (Grubba)  while(cnt < Pike_compiler->new_program->linenumbers + Pike_compiler->new_program->num_linenumbers)
1016021999-10-28Fredrik Hübinette (Hubbe)  { if(*cnt == 127) {
547e582013-09-08Henrik Grubbström (Grubba)  int strno;
50edc82001-07-13Henrik Grubbström (Grubba)  cnt++;
547e582013-09-08Henrik Grubbström (Grubba)  strno = get_small_number(&cnt); CHECK_FILE_ENTRY (Pike_compiler->new_program, strno); file = Pike_compiler->new_program->strings[strno];
1016021999-10-28Fredrik Hübinette (Hubbe)  } off+=get_small_number(&cnt); line+=get_small_number(&cnt); }
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->last_line=line; Pike_compiler->last_pc=off;
1016021999-10-28Fredrik Hübinette (Hubbe)  if(file) {
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->last_file) free_string(Pike_compiler->last_file);
547e582013-09-08Henrik Grubbström (Grubba)  copy_shared_string(Pike_compiler->last_file, file);
1016021999-10-28Fredrik Hübinette (Hubbe)  } }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }else{ static struct pike_string *s; struct inherit i;
547e582013-09-08Henrik Grubbström (Grubba)  if (Pike_compiler->new_program->strings) { struct pike_string **str = Pike_compiler->new_program->strings; int j = Pike_compiler->new_program->num_strings; while(j--) { free_string(*str); str++; } }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #define START_SIZE 64
d717352005-05-25Henrik Grubbström (Grubba) #ifdef PIKE_USE_MACHINE_CODE #define BAR(NUMTYPE,TYPE,ARGTYPE,NAME) \ if (Pike_compiler->new_program->NAME) { \ mexec_free(Pike_compiler->new_program->NAME); \ Pike_compiler->new_program->PIKE_CONCAT(num_,NAME) = 0; \ } \ Pike_compiler->malloc_size_program->PIKE_CONCAT(num_,NAME) = \ START_SIZE; \ Pike_compiler->new_program->NAME = \ (TYPE *)mexec_alloc(sizeof(TYPE) * START_SIZE); #endif /* PIKE_USE_MACHINE_CODE */
7e877a2003-04-02Martin Stjernholm #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \
7c7a3f2002-12-01Martin Stjernholm  if (Pike_compiler->new_program->NAME) { \ free (Pike_compiler->new_program->NAME); \ Pike_compiler->new_program->PIKE_CONCAT(num_,NAME) = 0; \ } \
d717352005-05-25Henrik Grubbström (Grubba)  Pike_compiler->malloc_size_program->PIKE_CONCAT(num_,NAME) = \ START_SIZE; \ Pike_compiler->new_program->NAME = \ (TYPE *)xalloc(sizeof(TYPE) * START_SIZE);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #include "program_areas.h"
bad5162000-06-23Fredrik Hübinette (Hubbe)  i.prog=Pike_compiler->new_program;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  i.identifier_level=0; i.storage_offset=0; i.inherit_level=0;
2659cf2002-05-10Henrik Grubbström (Grubba)  i.identifier_ref_offset=0;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  i.parent=0;
342fef2000-08-23Fredrik Hübinette (Hubbe)  i.parent_identifier=-1;
684bd22003-08-02Martin Stjernholm  i.parent_offset=OBJECT_PARENT;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  i.name=0; add_to_inherits(i);
0683be1997-01-26Fredrik Hübinette (Hubbe)  }
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->init_node=0; Pike_compiler->num_parse_error=0;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
4218011999-01-31Fredrik Hübinette (Hubbe)  push_compiler_frame(0);
be6fec2001-04-01Henrik Grubbström (Grubba)  copy_pike_type(Pike_compiler->compiler_frame->current_return_type, void_type_string);
648a1a2000-06-22Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  debug_malloc_touch(Pike_compiler->fake_object); debug_malloc_touch(Pike_compiler->fake_object->storage);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
ef24a82012-01-12Henrik Grubbström (Grubba) PMOD_EXPORT void debug_start_new_program(INT_TYPE line, const char *file)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) {
e021fe2008-04-14Henrik Grubbström (Grubba)  struct pike_string *save_file;
ef24a82012-01-12Henrik Grubbström (Grubba)  INT_TYPE save_line;
e021fe2008-04-14Henrik Grubbström (Grubba)  struct compilation *c; CHECK_COMPILER(); c = THIS_COMPILATION; save_file = dmalloc_touch(struct pike_string *, c->lex.current_file); save_line = c->lex.current_line;
cbb2be2003-02-04Martin Stjernholm  { /* Trim off the leading path of the compilation environment. */ const char *p = DEFINETOSTR(PIKE_SRC_ROOT), *f = file; while (*p && *p == *f) p++, f++; while (*f == '/' || *f == '\\') f++;
e021fe2008-04-14Henrik Grubbström (Grubba)  c->lex.current_file = make_shared_string(f); c->lex.current_line = line;
cbb2be2003-02-04Martin Stjernholm  }
2fbfc42002-06-11Martin Stjernholm 
b6f8c31999-07-01Henrik Grubbström (Grubba)  CDFPRINTF((stderr,
ef24a82012-01-12Henrik Grubbström (Grubba)  "th(%ld) start_new_program(%ld, %s): "
8b5b3a2014-04-28Henrik Grubbström (Grubba)  "lock_depth:%d, compilation_depth:%d\n",
ef24a82012-01-12Henrik Grubbström (Grubba)  (long)th_self(), (long)line, file,
8b5b3a2014-04-28Henrik Grubbström (Grubba)  lock_depth, c->compilation_depth));
b6f8c31999-07-01Henrik Grubbström (Grubba) 
7571282003-06-03Martin Stjernholm  low_start_new_program(0,1,0,0,0);
e021fe2008-04-14Henrik Grubbström (Grubba)  store_linenumber(line,c->lex.current_file);
2fbfc42002-06-11Martin Stjernholm  debug_malloc_name(Pike_compiler->new_program, file, line);
e021fe2008-04-14Henrik Grubbström (Grubba)  free_string(c->lex.current_file); c->lex.current_file = dmalloc_touch(struct pike_string *, save_file); c->lex.current_line = save_line;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) }
1c1c5e2001-04-08Fredrik Hübinette (Hubbe) static void exit_program_struct(struct program *p)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
7e877a2003-04-02Martin Stjernholm  unsigned e;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
d631b82002-12-01Martin Stjernholm #ifdef PIKE_DEBUG if (p->refs) { #ifdef DEBUG_MALLOC
4fab5f2004-04-18Martin Stjernholm  fprintf (stderr, "Program to be freed still got %d references:\n", p->refs);
d631b82002-12-01Martin Stjernholm  describe_something(p, T_PROGRAM, 0,2,0, NULL); #endif Pike_fatal("Program to be freed still got %d references.\n", p->refs); } #endif
1c1c5e2001-04-08Fredrik Hübinette (Hubbe)  if(p->parent) {
c82a992001-04-13Henrik Grubbström (Grubba)  /* Make sure to break the circularity... */ struct program *parent = p->parent; p->parent = NULL;
8444d32008-01-28Henrik Grubbström (Grubba) #ifdef PIKE_DEBUG
46b8762008-01-28Henrik Grubbström (Grubba)  if (!parent->refs) { dump_program_tables(p, 2);
cac6242008-02-12Henrik Grubbström (Grubba)  fprintf(stderr, "Dead parent:\n"); dump_program_tables(parent, 2);
46b8762008-01-28Henrik Grubbström (Grubba)  Pike_fatal("Program parent is dead.\n"); }
8444d32008-01-28Henrik Grubbström (Grubba) #endif
c82a992001-04-13Henrik Grubbström (Grubba)  free_program(parent);
1c1c5e2001-04-08Fredrik Hübinette (Hubbe)  }
29d1e62005-05-31Henrik Grubbström (Grubba)  /* fprintf(stderr, "Exiting program: %p, id:%d\n", p, p->id); */
1c1c5e2001-04-08Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  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;
05590d1998-04-23Fredrik Hübinette (Hubbe)  if(p->strings) for(e=0; e<p->num_strings; e++) if(p->strings[e]) free_string(p->strings[e]);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
05590d1998-04-23Fredrik Hübinette (Hubbe)  if(p->identifiers)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
05590d1998-04-23Fredrik Hübinette (Hubbe)  for(e=0; e<p->num_identifiers; e++) { if(p->identifiers[e].name) free_string(p->identifiers[e].name); if(p->identifiers[e].type)
d68a072001-02-20Henrik Grubbström (Grubba)  free_type(p->identifiers[e].type);
05590d1998-04-23Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
05590d1998-04-23Fredrik Hübinette (Hubbe)  if(p->constants)
43fc171999-09-19Fredrik Hübinette (Hubbe)  {
454d541999-09-18Fredrik Hübinette (Hubbe)  for(e=0;e<p->num_constants;e++)
43fc171999-09-19Fredrik Hübinette (Hubbe)  {
454d541999-09-18Fredrik Hübinette (Hubbe)  free_svalue(& p->constants[e].sval);
4ea54f2004-05-29Henrik Grubbström (Grubba) #if 0
43fc171999-09-19Fredrik Hübinette (Hubbe)  if(p->constants[e].name) free_string(p->constants[e].name);
4ea54f2004-05-29Henrik Grubbström (Grubba) #endif /* 0 */
43fc171999-09-19Fredrik Hübinette (Hubbe)  } }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
05590d1998-04-23Fredrik Hübinette (Hubbe)  if(p->inherits) for(e=0; e<p->num_inherits; e++)
3c0c281998-01-26Fredrik Hübinette (Hubbe)  {
05590d1998-04-23Fredrik Hübinette (Hubbe)  if(p->inherits[e].name) free_string(p->inherits[e].name); if(e) { if(p->inherits[e].prog) free_program(p->inherits[e].prog); } if(p->inherits[e].parent) free_object(p->inherits[e].parent);
3c0c281998-01-26Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
e2d9e62000-06-10Martin Stjernholm  DOUBLEUNLINK(first_program, p);
27ae842000-02-07Per Hedbor 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(p->flags & PROGRAM_OPTIMIZED)
05590d1998-04-23Fredrik Hübinette (Hubbe)  {
9173f72002-11-25Martin Stjernholm #ifdef PIKE_USE_MACHINE_CODE
e43a142005-06-09Henrik Grubbström (Grubba)  do { /* NOTE: Assumes all BAR's are before any FOO. */ #define BAR(NUMTYPE,TYPE,ARGTYPE,NAME) \ if (p->NAME) mexec_free(p->NAME); #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ if (p->NAME) { \ dmfree(p->NAME); \ break; \ } #include "program_areas.h" } while(0);
d717352005-05-25Henrik Grubbström (Grubba) #else /* PIKE_USE_MACHINE_CODE */
e43a142005-06-09Henrik Grubbström (Grubba)  if(p->program) {
424d9c1999-05-02Fredrik Hübinette (Hubbe)  dmfree(p->program);
9173f72002-11-25Martin Stjernholm  }
e43a142005-06-09Henrik Grubbström (Grubba) #endif /* PIKE_USE_MACHINE_CODE */
31906a2008-04-19Henrik Grubbström (Grubba) #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) do { \ p->NAME=0; \ } while(0);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #include "program_areas.h"
05590d1998-04-23Fredrik Hübinette (Hubbe)  }else{
d717352005-05-25Henrik Grubbström (Grubba) #ifdef PIKE_USE_MACHINE_CODE #define BAR(NUMTYPE,TYPE,ARGTYPE,NAME) \
31906a2008-04-19Henrik Grubbström (Grubba)  if(p->NAME) { \ mexec_free((char *)p->NAME); p->NAME=0; \ }
d717352005-05-25Henrik Grubbström (Grubba) #endif /* PIKE_USE_MACHINE_CODE */ #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \
31906a2008-04-19Henrik Grubbström (Grubba)  if(p->NAME) { \ dmfree((char *)p->NAME); p->NAME=0; \ }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #include "program_areas.h"
05590d1998-04-23Fredrik Hübinette (Hubbe)  }
27ae842000-02-07Per Hedbor 
45637c2001-04-07Fredrik Hübinette (Hubbe)  EXIT_PIKE_MEMOBJ(p);
27ae842000-02-07Per Hedbor 
553d232000-09-14Martin Stjernholm  GC_FREE(p);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
2acdd31995-10-29Fredrik Hübinette (Hubbe) void dump_program_desc(struct program *p) { int e,d,q; /* fprintf(stderr,"Program '%s':\n",p->name->str); */
a1f8522002-06-11Martin Stjernholm  fprintf(stderr,"$$$$$ dump_program_desc for %p\n", p);
2acdd31995-10-29Fredrik Hübinette (Hubbe)  fprintf(stderr,"All inherits:\n"); for(e=0;e<p->num_inherits;e++) { for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," ");
5f05c11999-12-27Fredrik Hübinette (Hubbe)  fprintf(stderr,"%3d:\n",e);
b8896b2000-02-10Fredrik Hübinette (Hubbe)  for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); fprintf(stderr,"inherited program: %d\n",p->inherits[e].prog->id);
5f05c11999-12-27Fredrik Hübinette (Hubbe)  if(p->inherits[e].name) { for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); fprintf(stderr,"name : %s\n",p->inherits[e].name->str); } for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); fprintf(stderr,"inherit_level: %d\n",p->inherits[e].inherit_level); for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); fprintf(stderr,"identifier_level: %d\n",p->inherits[e].identifier_level); for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); fprintf(stderr,"parent_identifier: %d\n",p->inherits[e].parent_identifier); for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); fprintf(stderr,"parent_offset: %d\n",p->inherits[e].parent_offset); for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," ");
63540d2000-08-15Henrik Grubbström (Grubba)  fprintf(stderr,"storage_offset: %ld\n", DO_NOT_WARN((long)p->inherits[e].storage_offset));
5f05c11999-12-27Fredrik Hübinette (Hubbe)  for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); fprintf(stderr,"parent: %p\n",p->inherits[e].parent); if(p->inherits[e].parent && p->inherits[e].parent->prog && p->inherits[e].parent->prog->num_linenumbers>1) { for(d=0;d<p->inherits[e].inherit_level;d++) fprintf(stderr," "); fprintf(stderr,"parent: %s\n",p->inherits[e].parent->prog->linenumbers+1); }
2acdd31995-10-29Fredrik Hübinette (Hubbe)  }
a1f8522002-06-11Martin Stjernholm  fprintf(stderr,"All identifier references:\n");
2acdd31995-10-29Fredrik Hübinette (Hubbe)  for(e=0;e<(int)p->num_identifier_references;e++) {
a1f8522002-06-11Martin Stjernholm  struct inherit *inh = INHERIT_FROM_INT(p,e); fprintf(stderr,"%3d: ",e); for(d=0;d<inh->inherit_level;d++) fprintf(stderr," "); fprintf(stderr,"%-40s flags 0x%x",ID_FROM_INT(p,e)->name->str, p->identifier_references[e].id_flags); for (q = 0; q < p->num_inherits; q++) if (p->inherits + q == inh) {
7221342007-09-04Henrik Grubbström (Grubba)  fprintf(stderr, " inherit %d\n" " type: ", q); simple_describe_type(ID_FROM_INT(p, e)->type); fprintf(stderr, "\n");
a1f8522002-06-11Martin Stjernholm  goto inherit_found; } fprintf (stderr, " inherit not found!\n"); inherit_found:;
2acdd31995-10-29Fredrik Hübinette (Hubbe)  } fprintf(stderr,"All sorted identifiers:\n");
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  for(q=0;q<(int)p->num_identifier_index;q++)
2acdd31995-10-29Fredrik Hübinette (Hubbe)  { 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," ");
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  fprintf(stderr,"%s;\n", ID_FROM_INT(p,e)->name->str);
2acdd31995-10-29Fredrik Hübinette (Hubbe)  }
a1f8522002-06-11Martin Stjernholm  fprintf(stderr,"$$$$$ dump_program_desc for %p done\n", p);
2acdd31995-10-29Fredrik Hübinette (Hubbe) } #endif
be478c1997-08-30Henrik Grubbström (Grubba) static void toss_compilation_resources(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->fake_object)
a3c6ad1998-01-29Fredrik Hübinette (Hubbe)  {
f3c7152001-04-14Fredrik Hübinette (Hubbe)  if( ((struct parent_info *)Pike_compiler->fake_object->storage)->parent ) { free_object(((struct parent_info *)Pike_compiler->fake_object->storage)->parent); ((struct parent_info *)Pike_compiler->fake_object->storage)->parent=0; }
bad5162000-06-23Fredrik Hübinette (Hubbe)  free_program(Pike_compiler->fake_object->prog); Pike_compiler->fake_object->prog=0; free_object(Pike_compiler->fake_object); Pike_compiler->fake_object=0;
a3c6ad1998-01-29Fredrik Hübinette (Hubbe)  }
bad5162000-06-23Fredrik Hübinette (Hubbe)  free_program(Pike_compiler->new_program); Pike_compiler->new_program=0;
591c0c1997-01-19Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->malloc_size_program)
591c0c1997-01-19Fredrik Hübinette (Hubbe)  {
bad5162000-06-23Fredrik Hübinette (Hubbe)  dmfree((char *)Pike_compiler->malloc_size_program); Pike_compiler->malloc_size_program=0;
591c0c1997-01-19Fredrik Hübinette (Hubbe)  }
05590d1998-04-23Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->module_index_cache)
05590d1998-04-23Fredrik Hübinette (Hubbe)  {
bad5162000-06-23Fredrik Hübinette (Hubbe)  free_mapping(Pike_compiler->module_index_cache); Pike_compiler->module_index_cache=0;
05590d1998-04-23Fredrik Hübinette (Hubbe)  }
27ae842000-02-07Per Hedbor 
bad5162000-06-23Fredrik Hübinette (Hubbe)  while(Pike_compiler->compiler_frame)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  pop_compiler_frame();
591c0c1997-01-19Fredrik Hübinette (Hubbe) 
de1d7d2000-07-10Henrik Grubbström (Grubba)  if(Pike_compiler->last_identifier) { free_string(Pike_compiler->last_identifier); Pike_compiler->last_identifier=0; }
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->last_file)
591c0c1997-01-19Fredrik Hübinette (Hubbe)  {
bad5162000-06-23Fredrik Hübinette (Hubbe)  free_string(Pike_compiler->last_file); Pike_compiler->last_file=0;
591c0c1997-01-19Fredrik Hübinette (Hubbe)  }
a2af982014-03-01Henrik Grubbström (Grubba)  if (Pike_compiler->current_attributes) { free_node(Pike_compiler->current_attributes); Pike_compiler->current_attributes = NULL; }
bad5162000-06-23Fredrik Hübinette (Hubbe)  unuse_modules(Pike_compiler->num_used_modules);
44e3402013-10-09Arne Goedeke  free_all_nodes(); ba_destroy(&Pike_compiler->node_allocator);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
e964ae1998-04-08Fredrik Hübinette (Hubbe) int sizeof_variable(int run_time_type)
1994981998-04-07Fredrik Hübinette (Hubbe) { switch(run_time_type) { case T_FUNCTION: case T_MIXED: return sizeof(struct svalue); case T_FLOAT: return sizeof(FLOAT_TYPE);
2ba9191999-10-23Fredrik Hübinette (Hubbe)  case T_INT: return sizeof(INT_TYPE);
2e1a6a2008-05-29Henrik Grubbström (Grubba)  case PIKE_T_FREE:
0fc3b92008-02-19Henrik Grubbström (Grubba)  case PIKE_T_GET_SET: return 0;
6ccad42002-04-25Henrik Grubbström (Grubba)  default: return sizeof(void *);
1994981998-04-07Fredrik Hübinette (Hubbe)  } }
d3b06f2000-08-10Henrik Grubbström (Grubba) static ptrdiff_t alignof_variable(int run_time_type)
1994981998-04-07Fredrik Hübinette (Hubbe) { switch(run_time_type) { case T_FUNCTION:
90e9781999-01-31Fredrik Hübinette (Hubbe)  case T_MIXED: return ALIGNOF(struct svalue);
1994981998-04-07Fredrik Hübinette (Hubbe)  case T_FLOAT: return ALIGNOF(FLOAT_TYPE);
2ba9191999-10-23Fredrik Hübinette (Hubbe)  case T_INT: return ALIGNOF(INT_TYPE);
2e1a6a2008-05-29Henrik Grubbström (Grubba)  case PIKE_T_FREE:
0fc3b92008-02-19Henrik Grubbström (Grubba)  case PIKE_T_GET_SET: return 1;
6ccad42002-04-25Henrik Grubbström (Grubba)  default: return ALIGNOF(void *);
1994981998-04-07Fredrik Hübinette (Hubbe)  } }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
e51d101999-09-15Fredrik Hübinette (Hubbe) 
aa04222013-02-25Arne Goedeke PMOD_EXPORT void dump_program_tables (const struct program *p, int indent)
5ec1062002-05-09Martin Stjernholm { int d;
7d65752003-06-04Henrik Grubbström (Grubba)  if (!p) { fprintf(stderr, "%*sProgram: NULL\n\n", indent, ""); return; }
5ec1062002-05-09Martin Stjernholm  fprintf(stderr, "%*sProgram flags: 0x%04x\n\n", indent, "", p->flags); fprintf(stderr, "%*sReference table:\n" "%*s ####: Flags Inherit Identifier\n", indent, "", indent, ""); for (d=0; d < p->num_identifier_references; d++) { struct reference *ref = p->identifier_references + d;
cac6242008-02-12Henrik Grubbström (Grubba)  struct identifier *id = ID_FROM_PTR(p, ref);
e5b7452013-11-03Henrik Grubbström (Grubba)  struct program *inh_p = INHERIT_FROM_PTR(p, ref)->prog;
5ec1062002-05-09Martin Stjernholm 
0ed9122008-05-16Henrik Grubbström (Grubba)  fprintf(stderr, "%*s %4d: %5x %7d %10d %s\n"
ef24a82012-01-12Henrik Grubbström (Grubba)  "%*s %s:%ld\n",
5ec1062002-05-09Martin Stjernholm  indent, "", d, ref->id_flags, ref->inherit_offset, ref->identifier_offset,
0ed9122008-05-16Henrik Grubbström (Grubba)  id->name->size_shift ? "(wide)" : id->name->str, indent, "",
e5b7452013-11-03Henrik Grubbström (Grubba)  inh_p->num_strings?inh_p->strings[id->filename_strno]->str:"-",
ef24a82012-01-12Henrik Grubbström (Grubba)  (long)id->linenumber);
cac6242008-02-12Henrik Grubbström (Grubba)  if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) { fprintf (stderr, "%*s Alias for %d:%d\n", indent, "", id->func.ext_ref.depth, id->func.ext_ref.id); } else if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) { fprintf (stderr, "%*s Constant #%ld\n",
89378b2010-11-23Henrik Grubbström (Grubba)  indent, "", (long)id->func.const_info.offset);
cac6242008-02-12Henrik Grubbström (Grubba)  } else if (IDENTIFIER_IS_VARIABLE(id->identifier_flags)) { fprintf (stderr, "%*s Offset: 0x%08lx\n", indent, "", (long)id->func.offset); } else if (IDENTIFIER_IS_PIKE_FUNCTION(id->identifier_flags)) {
ef24a82012-01-12Henrik Grubbström (Grubba)  INT_TYPE line;
89a2ad2002-05-09Martin Stjernholm  struct pike_string *file = get_line (ID_FROM_PTR(p,ref)->func.offset + inh_p->program, inh_p, &line); if (!file->size_shift)
ef24a82012-01-12Henrik Grubbström (Grubba)  fprintf (stderr, "%*s %s:%ld\n", indent, "", file->str, (long)line);
fcbde02003-08-20Martin Stjernholm  free_string (file);
cac6242008-02-12Henrik Grubbström (Grubba)  } else { fprintf (stderr, "%*s Cfun: %p\n", indent, "", id->func.c_fun);
5ec1062002-05-09Martin Stjernholm  } }
7571282003-06-03Martin Stjernholm  fprintf(stderr, "\n" "%*sIdentifier index table:\n"
2fb9862008-09-04Henrik Grubbström (Grubba)  "%*s ####: Index\tName\n",
7571282003-06-03Martin Stjernholm  indent, "", indent, ""); for (d = 0; d < p->num_identifier_index; d++) {
2fb9862008-09-04Henrik Grubbström (Grubba)  struct identifier *id = ID_FROM_INT(p, p->identifier_index[d]); fprintf(stderr, "%*s %4d: %5d\t%s\n",
7571282003-06-03Martin Stjernholm  indent, "",
2fb9862008-09-04Henrik Grubbström (Grubba)  d, p->identifier_index[d], id->name->size_shift ? "(wide)" : id->name->str);
7571282003-06-03Martin Stjernholm  }
5ec1062002-05-09Martin Stjernholm  fprintf(stderr, "\n" "%*sInherit table:\n"
684bd22003-08-02Martin Stjernholm  "%*s ####: Level prog_id id_level storage_offs " "par_id par_offs par_obj_id id_ref_offs\n",
5ec1062002-05-09Martin Stjernholm  indent, "", indent, ""); for (d=0; d < p->num_inherits; d++) { struct inherit *inh = p->inherits + d;
2d76f22005-05-20Martin Stjernholm  fprintf(stderr, "%*s %4d: %5d %7d %8d %12"PRINTPTRDIFFT"d %6d %8d %10d %11"PRINTSIZET"d\n",
5ec1062002-05-09Martin Stjernholm  indent, "",
684bd22003-08-02Martin Stjernholm  d, inh->inherit_level, inh->prog ? inh->prog->id : -1, inh->identifier_level, inh->storage_offset, inh->parent_identifier, inh->parent_offset, inh->parent ? inh->parent->program_id : -1, inh->identifier_ref_offset);
5ec1062002-05-09Martin Stjernholm  } fprintf(stderr, "\n" "%*sIdentifier table:\n" "%*s ####: Flags Offset Type Name\n", indent, "", indent, ""); for (d=0; d < p->num_identifiers; d++) { struct identifier *id = p->identifiers + d;
0ed9122008-05-16Henrik Grubbström (Grubba)  fprintf(stderr,
ddcc6d2008-05-22Martin Stjernholm  "%*s %4d: %5x %6"PRINTPTRDIFFT"d %4d \"%s\"\n"
ef24a82012-01-12Henrik Grubbström (Grubba)  "%*s %s:%ld\n",
5ec1062002-05-09Martin Stjernholm  indent, "", d, id->identifier_flags, id->func.offset,
0ed9122008-05-16Henrik Grubbström (Grubba)  id->run_time_type, id->name->str, indent, "",
ef24a82012-01-12Henrik Grubbström (Grubba)  p->num_strings?p->strings[id->filename_strno]->str:"-", (long)id->linenumber);
5ec1062002-05-09Martin Stjernholm  }
7571282003-06-03Martin Stjernholm 
5ec1062002-05-09Martin Stjernholm  fprintf(stderr, "\n" "%*sVariable table:\n" "%*s ####: Index\n", indent, "", indent, ""); for (d = 0; d < p->num_variable_index; d++) { fprintf(stderr, "%*s %4d: %5d\n", indent, "", d, p->variable_index[d]); } fprintf(stderr, "\n" "%*sConstant table:\n"
cac6242008-02-12Henrik Grubbström (Grubba)  "%*s ####: Type Raw\n",
5ec1062002-05-09Martin Stjernholm  indent, "", indent, ""); for (d = 0; d < p->num_constants; d++) { struct program_constant *c = p->constants + d;
cac6242008-02-12Henrik Grubbström (Grubba) #if 1 fprintf(stderr, "%*s %4d: %-15s %p\n",
5ec1062002-05-09Martin Stjernholm  indent, "",
017b572011-10-28Henrik Grubbström (Grubba)  d, get_name_of_type (TYPEOF(c->sval)),
cac6242008-02-12Henrik Grubbström (Grubba)  c->sval.u.ptr);
4ea54f2004-05-29Henrik Grubbström (Grubba) #else /* !0 */
2d76f22005-05-20Martin Stjernholm  fprintf(stderr, "%*s %4d: %-15s %"PRINTPTRDIFFT"d\n",
4ea54f2004-05-29Henrik Grubbström (Grubba)  indent, "",
017b572011-10-28Henrik Grubbström (Grubba)  d, get_name_of_type (TYPEOF(c->sval)),
4ea54f2004-05-29Henrik Grubbström (Grubba)  c->offset); #endif /* 0 */
5ec1062002-05-09Martin Stjernholm  }
9b78282002-11-07Henrik Grubbström (Grubba) 
17799f2008-04-24Henrik Grubbström (Grubba)  fprintf(stderr, "\n" "%*sString table:\n" "%*s ####: Value\n", indent, "", indent, ""); for (d = 0; d < p->num_strings; d++) {
194f072008-05-01Martin Stjernholm  fprintf(stderr, "%*s %4d: [%p]\"%s\"(%"PRINTPTRDIFFT"d characters)\n",
17799f2008-04-24Henrik Grubbström (Grubba)  indent, "", (int)d, p->strings[d], p->strings[d]->str, p->strings[d]->len); }
e021fe2008-04-14Henrik Grubbström (Grubba)  fprintf(stderr, "\n" "%*sLFUN table:\n" "%*s LFUN Ref# Name\n", indent, "", indent, ""); for (d = 0; d < NUM_LFUNS; d++) { if (p->lfuns[d] != -1) { fprintf(stderr, "%*s %4d: %04d %s\n", indent, "", d, p->lfuns[d], lfun_names[d]); } }
9b78282002-11-07Henrik Grubbström (Grubba)  fprintf(stderr, "\n" "%*sLinenumber table:\n", indent, ""); {
ef24a82012-01-12Henrik Grubbström (Grubba)  INT32 off = 0; INT_TYPE line = 0;
ad6a882002-11-07Henrik Grubbström (Grubba)  char *cnt = p->linenumbers;
9b78282002-11-07Henrik Grubbström (Grubba) 
ad6a882002-11-07Henrik Grubbström (Grubba)  while (cnt < p->linenumbers + p->num_linenumbers) {
9b78282002-11-07Henrik Grubbström (Grubba)  if (*cnt == 127) {
547e582013-09-08Henrik Grubbström (Grubba)  int strno;
9b78282002-11-07Henrik Grubbström (Grubba)  cnt++;
547e582013-09-08Henrik Grubbström (Grubba)  strno = get_small_number(&cnt); fprintf(stderr, "%*s Filename: String #%d\n", indent, "", strno);
9b78282002-11-07Henrik Grubbström (Grubba)  } off += get_small_number(&cnt); line += get_small_number(&cnt);
ef24a82012-01-12Henrik Grubbström (Grubba)  fprintf(stderr, "%*s %8d:%8ld\n", indent, "", off, (long)line);
9b78282002-11-07Henrik Grubbström (Grubba)  } }
7571282003-06-03Martin Stjernholm 
5ec1062002-05-09Martin Stjernholm  fprintf(stderr, "\n"); }
624d091996-02-24Fredrik Hübinette (Hubbe) void check_program(struct program *p)
0d202a1995-10-20Fredrik Hübinette (Hubbe) {
6ce7322008-07-16Martin Stjernholm  unsigned INT32 e;
68b6951999-09-15Fredrik Hübinette (Hubbe)  int variable_positions[1024];
8ba59a2000-03-26Fredrik Hübinette (Hubbe)  if(p->flags & PROGRAM_AVOID_CHECK) return;
68b6951999-09-15Fredrik Hübinette (Hubbe)  for(e=0;e<NELEM(variable_positions);e++) variable_positions[e]=-1;
0d202a1995-10-20Fredrik Hübinette (Hubbe) 
636e471998-04-15Fredrik Hübinette (Hubbe)  if(p->id > current_program_id)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Program id is out of sync! (p->id=%d, current_program_id=%d)\n",p->id,current_program_id);
636e471998-04-15Fredrik Hübinette (Hubbe) 
0d202a1995-10-20Fredrik Hübinette (Hubbe)  if(p->refs <=0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Program has zero refs.\n");
0d202a1995-10-20Fredrik Hübinette (Hubbe)  if(p->next && p->next->prev != p)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Program ->next->prev != program.\n");
0d202a1995-10-20Fredrik Hübinette (Hubbe)  if(p->prev) { if(p->prev->next != p)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Program ->prev->next != program.\n");
0d202a1995-10-20Fredrik Hübinette (Hubbe)  }else{ if(first_program != p)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Program ->prev == 0 but first_program != program.\n");
0d202a1995-10-20Fredrik Hübinette (Hubbe)  }
d2c6081996-11-07Fredrik Hübinette (Hubbe)  if(p->id > current_program_id || p->id <= 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Program id is wrong.\n");
0d202a1995-10-20Fredrik Hübinette (Hubbe)  if(p->storage_needed < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Program->storage_needed < 0.\n");
0d202a1995-10-20Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(p->num_identifier_index > p->num_identifier_references)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Too many identifier index entries in program!\n");
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
3c58e51999-09-22Henrik Grubbström (Grubba)  for(e=0;e<p->num_constants;e++)
454d541999-09-18Fredrik Hübinette (Hubbe)  {
aa771b2003-08-20Martin Stjernholm  struct svalue *s = & p->constants[e].sval; check_svalue(s);
017b572011-10-28Henrik Grubbström (Grubba)  if (p->flags & PROGRAM_FINISHED && TYPEOF(*s) == T_OBJECT &&
aa771b2003-08-20Martin Stjernholm  s->u.object->next == s->u.object) Pike_fatal ("Got fake object in constant in finished program.\n");
4ea54f2004-05-29Henrik Grubbström (Grubba) #if 0
454d541999-09-18Fredrik Hübinette (Hubbe)  if(p->constants[e].name) check_string(p->constants[e].name);
4ea54f2004-05-29Henrik Grubbström (Grubba) #else /* ! 0 */ if (p->constants[e].offset >= p->num_identifiers) { Pike_fatal("Constant initializer outside num_identifiers (%d >= %d).\n", p->constants[e].offset, p->num_identifiers); } #endif /* 0 */
454d541999-09-18Fredrik Hübinette (Hubbe)  }
0d202a1995-10-20Fredrik Hübinette (Hubbe) 
3c58e51999-09-22Henrik Grubbström (Grubba)  for(e=0;e<p->num_strings;e++)
0d202a1995-10-20Fredrik Hübinette (Hubbe)  check_string(p->strings[e]);
3c58e51999-09-22Henrik Grubbström (Grubba)  for(e=0;e<p->num_inherits;e++)
e51d101999-09-15Fredrik Hübinette (Hubbe)  {
ce277e2000-03-25Fredrik Hübinette (Hubbe)  if(!p->inherits[e].prog) {
e05acb2000-03-25Fredrik Hübinette (Hubbe)  /* This inherit is not yet initialized, ignore rest of tests.. */ return;
ce277e2000-03-25Fredrik Hübinette (Hubbe)  }
e51d101999-09-15Fredrik Hübinette (Hubbe)  if(p->inherits[e].storage_offset < 0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Inherit->storage_offset is wrong.\n");
e51d101999-09-15Fredrik Hübinette (Hubbe) 
1f5bfe1999-09-28Fredrik Hübinette (Hubbe)  if(p->inherits[e].prog && p->inherits[e].storage_offset + STORAGE_NEEDED(p->inherits[e].prog) > p->storage_needed)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Not enough room allocated by inherit!\n");
1f5bfe1999-09-28Fredrik Hübinette (Hubbe) 
684bd22003-08-02Martin Stjernholm  if (p->inherits[e].inherit_level == 1 &&
88e9fb2003-08-03Martin Stjernholm  p->inherits[e].identifier_level != (INT32) p->inherits[e].identifier_ref_offset) {
684bd22003-08-02Martin Stjernholm  dump_program_tables (p, 0); Pike_fatal ("Unexpected difference between identifier_level " "and identifier_ref_offset in inherit %d.\n", e); }
e51d101999-09-15Fredrik Hübinette (Hubbe)  if(e) {
27ae842000-02-07Per Hedbor  if(p->inherits[e-1].storage_offset >
e51d101999-09-15Fredrik Hübinette (Hubbe)  p->inherits[e].storage_offset)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Overlapping inherits! (1)\n");
27ae842000-02-07Per Hedbor 
e51d101999-09-15Fredrik Hübinette (Hubbe)  if(p->inherits[e-1].prog &&
27ae842000-02-07Per Hedbor  p->inherits[e-1].inherit_level >= p->inherits[e].inherit_level &&
1f5bfe1999-09-28Fredrik Hübinette (Hubbe)  ( p->inherits[e-1].storage_offset + STORAGE_NEEDED(p->inherits[e-1].prog)) > p->inherits[e].storage_offset)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Overlapping inherits! (3)\n");
e51d101999-09-15Fredrik Hübinette (Hubbe)  } }
29338d1999-09-29Henrik Grubbström (Grubba) 
7066e11999-09-14Fredrik Hübinette (Hubbe)  if(p->flags & PROGRAM_FINISHED)
3c58e51999-09-22Henrik Grubbström (Grubba)  for(e=0;e<p->num_identifiers;e++)
0d202a1995-10-20Fredrik Hübinette (Hubbe)  { check_string(p->identifiers[e].name);
88e9fb2003-08-03Martin Stjernholm  switch (p->identifiers[e].identifier_flags & IDENTIFIER_TYPE_MASK) { case IDENTIFIER_VARIABLE: case IDENTIFIER_PIKE_FUNCTION: case IDENTIFIER_C_FUNCTION: case IDENTIFIER_CONSTANT: break; default: Pike_fatal("Invalid identifier type.\n"); }
97f6282000-03-07Fredrik Hübinette (Hubbe)  if(p->identifiers[e].identifier_flags & ~IDENTIFIER_MASK)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Unknown flags in identifier flag field.\n");
0d202a1995-10-20Fredrik Hübinette (Hubbe) 
6fa59e2006-10-27Henrik Grubbström (Grubba)  if((p->identifiers[e].run_time_type!=T_MIXED) &&
2e1a6a2008-05-29Henrik Grubbström (Grubba)  (p->identifiers[e].run_time_type!=PIKE_T_FREE) &&
6fa59e2006-10-27Henrik Grubbström (Grubba)  (p->identifiers[e].run_time_type!=PIKE_T_GET_SET))
0d202a1995-10-20Fredrik Hübinette (Hubbe)  check_type(p->identifiers[e].run_time_type);
2f1b9e1998-04-06Fredrik Hübinette (Hubbe) 
64dd452007-09-29Henrik Grubbström (Grubba)  if (!IDENTIFIER_IS_ALIAS(p->identifiers[e].identifier_flags)) {
eb367a2007-09-25Henrik Grubbström (Grubba)  if(IDENTIFIER_IS_VARIABLE(p->identifiers[e].identifier_flags))
2f1b9e1998-04-06Fredrik Hübinette (Hubbe)  {
0fc3b92008-02-19Henrik Grubbström (Grubba)  if((p->identifiers[e].func.offset /* + OFFSETOF(object,storage)*/ ) &
eb367a2007-09-25Henrik Grubbström (Grubba)  (alignof_variable(p->identifiers[e].run_time_type)-1)) {
938ae42008-02-02Henrik Grubbström (Grubba)  dump_program_tables(p, 0);
eb367a2007-09-25Henrik Grubbström (Grubba)  Pike_fatal("Variable %s offset is not properly aligned (%ld).\n", p->identifiers[e].name->str, PTRDIFF_T_TO_LONG(p->identifiers[e].func.offset)); } } } else { /* FIXME: Check that ext_ref.depth and ext_ref.id are valid and * have matching identifier_flags. */
64dd452007-09-29Henrik Grubbström (Grubba)  if (p->identifiers[e].func.ext_ref.depth && !(p->flags & PROGRAM_USES_PARENT)) {
eb367a2007-09-25Henrik Grubbström (Grubba)  Pike_fatal("Identifier %d is an external reference, but " "PROGRAM_USES_PARENT hasn't been set.\n", e);
2f1b9e1998-04-06Fredrik Hübinette (Hubbe)  } }
0d202a1995-10-20Fredrik Hübinette (Hubbe)  }
3c58e51999-09-22Henrik Grubbström (Grubba)  for(e=0;e<p->num_identifier_references;e++)
0d202a1995-10-20Fredrik Hübinette (Hubbe)  {
68b6951999-09-15Fredrik Hübinette (Hubbe)  struct identifier *i;
0d202a1995-10-20Fredrik Hübinette (Hubbe)  if(p->identifier_references[e].inherit_offset > p->num_inherits)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Inherit offset is wrong!\n");
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
513ece1999-09-09Fredrik Hübinette (Hubbe)  if(!p->inherits[p->identifier_references[e].inherit_offset].prog) { if(!(p->flags & PROGRAM_FINISHED)) continue;
5aad932002-08-15Marcus Comstedt  Pike_fatal("p->inherit[%d].prog = NULL!\n",p->identifier_references[e].inherit_offset);
513ece1999-09-09Fredrik Hübinette (Hubbe)  }
0d202a1995-10-20Fredrik Hübinette (Hubbe)  if(p->identifier_references[e].identifier_offset > p->inherits[p->identifier_references[e].inherit_offset].prog->num_identifiers)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Identifier offset %d is wrong! %d > %d\n",
19be9f2001-07-02Fredrik Hübinette (Hubbe)  e, p->identifier_references[e].identifier_offset, p->inherits[p->identifier_references[e].inherit_offset].prog->num_identifiers);
68b6951999-09-15Fredrik Hübinette (Hubbe)  i=ID_FROM_INT(p, e);
2de6f72008-02-14Henrik Grubbström (Grubba)  if (IDENTIFIER_IS_ALIAS(i->identifier_flags)) { if ((!i->func.ext_ref.depth) && (i->func.ext_ref.id == e)) { dump_program_tables(p, 0); Pike_fatal("Circular alias for reference %d!\n", e); } } else if (IDENTIFIER_IS_VARIABLE(i->identifier_flags)) {
63540d2000-08-15Henrik Grubbström (Grubba)  size_t q, size;
68b6951999-09-15Fredrik Hübinette (Hubbe)  /* Variable */
63540d2000-08-15Henrik Grubbström (Grubba)  ptrdiff_t offset = INHERIT_FROM_INT(p, e)->storage_offset+i->func.offset;
6fa59e2006-10-27Henrik Grubbström (Grubba)  if (i->run_time_type == PIKE_T_GET_SET) { struct reference *ref = PTR_FROM_INT(p, e);
f590122007-09-14Henrik Grubbström (Grubba)  if (!ref->inherit_offset) {
85e4552008-05-13Henrik Grubbström (Grubba)  if (i->func.gs_info.getter >= p->num_identifier_references) {
6fa59e2006-10-27Henrik Grubbström (Grubba)  Pike_fatal("Getter outside references.\n"); }
85e4552008-05-13Henrik Grubbström (Grubba)  if (i->func.gs_info.setter >= p->num_identifier_references) {
6fa59e2006-10-27Henrik Grubbström (Grubba)  Pike_fatal("Setter outside references.\n"); } } continue; }
e51d101999-09-15Fredrik Hübinette (Hubbe)  size=sizeof_variable(i->run_time_type);
2e1a6a2008-05-29Henrik Grubbström (Grubba)  if(size && ((offset+size > (size_t)p->storage_needed) || offset<0))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Variable outside storage! (%s)\n",i->name->str);
e51d101999-09-15Fredrik Hübinette (Hubbe)  for(q=0;q<size;q++)
68b6951999-09-15Fredrik Hübinette (Hubbe)  { if(offset+q >= NELEM(variable_positions)) break; if(variable_positions[offset+q] != -1) { if(ID_FROM_INT(p,variable_positions[offset+q])->run_time_type != i->run_time_type) {
2d76f22005-05-20Martin Stjernholm  fprintf(stderr, "Storage offset: " "0x%08"PRINTPTRDIFFT"x vs 0x%08"PRINTPTRDIFFT"x\n" "Func offset: 0x%08"PRINTPTRDIFFT"x vs 0x%08"PRINTPTRDIFFT"x\n"
2509e92001-07-02Henrik Grubbström (Grubba)  "Type: %s vs %s\n", INHERIT_FROM_INT(p, variable_positions[offset+q])-> storage_offset, INHERIT_FROM_INT(p, e)->storage_offset, ID_FROM_INT(p, variable_positions[offset+q])->func.offset, i->func.offset, get_name_of_type(ID_FROM_INT(p,variable_positions[offset+q] )->run_time_type), get_name_of_type(i->run_time_type));
66e2cf2001-06-10Henrik Grubbström (Grubba)  if (i->name) {
5aad932002-08-15Marcus Comstedt  Pike_fatal("Variable '%s' and '%s' overlap\n"
2d76f22005-05-20Martin Stjernholm  "Offset 0x%08"PRINTPTRDIFFT"x - 0x%08"PRINTPTRDIFFT"x " "overlaps with " "0x%08"PRINTPTRDIFFT"x - 0x%08"PRINTPTRDIFFT"x\n",
66e2cf2001-06-10Henrik Grubbström (Grubba)  ID_FROM_INT(p, variable_positions[offset+q])->name->str,
0626282001-07-02Henrik Grubbström (Grubba)  i->name->str, INHERIT_FROM_INT(p, variable_positions[offset+q])-> storage_offset + ID_FROM_INT(p, variable_positions[offset+q])->func.offset, INHERIT_FROM_INT(p, variable_positions[offset+q])-> storage_offset + ID_FROM_INT(p, variable_positions[offset+q])->func.offset + sizeof_variable(ID_FROM_INT(p, variable_positions[offset+q]
2653e82001-07-02Henrik Grubbström (Grubba)  )->run_time_type)-1,
0626282001-07-02Henrik Grubbström (Grubba)  offset, offset+size-1);
66e2cf2001-06-10Henrik Grubbström (Grubba)  } else {
5aad932002-08-15Marcus Comstedt  Pike_fatal("Variable '%s' and anonymous variable (%d) overlap\n"
2d76f22005-05-20Martin Stjernholm  "Offset 0x%08"PRINTPTRDIFFT"x - 0x%08"PRINTPTRDIFFT"x " "overlaps with " "0x%08"PRINTPTRDIFFT"x - 0x%08"PRINTPTRDIFFT"x\n",
66e2cf2001-06-10Henrik Grubbström (Grubba)  ID_FROM_INT(p, variable_positions[offset+q])->name->str,
0626282001-07-02Henrik Grubbström (Grubba)  e, INHERIT_FROM_INT(p, variable_positions[offset+q])-> storage_offset + ID_FROM_INT(p, variable_positions[offset+q])->func.offset, INHERIT_FROM_INT(p, variable_positions[offset+q])-> storage_offset + ID_FROM_INT(p, variable_positions[offset+q])->func.offset + sizeof_variable(ID_FROM_INT(p, variable_positions[offset+q]
2653e82001-07-02Henrik Grubbström (Grubba)  )->run_time_type)-1,
0626282001-07-02Henrik Grubbström (Grubba)  offset, offset+size-1);
66e2cf2001-06-10Henrik Grubbström (Grubba)  }
68b6951999-09-15Fredrik Hübinette (Hubbe)  } } variable_positions[offset+q]=e; } }
0d202a1995-10-20Fredrik Hübinette (Hubbe)  }
3c58e51999-09-22Henrik Grubbström (Grubba)  for(e=0;e<p->num_identifier_index;e++)
0d202a1995-10-20Fredrik Hübinette (Hubbe)  { if(p->identifier_index[e] > p->num_identifier_references)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Program->identifier_indexes[%ld] is wrong\n",(long)e);
ab9db52003-02-20Henrik Grubbström (Grubba)  if (e && (program_identifier_index_compare(p->identifier_index[e-1], p->identifier_index[e], p) > 0)) { Pike_fatal("Program->identifier_index[%ld] > " "Program->identifier_index[%ld]\n", (long)(e-1), (long)e); }
0d202a1995-10-20Fredrik Hübinette (Hubbe)  } } #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b160c22013-05-26Henrik Grubbström (Grubba) static void f_dispatch_variant(INT32 args);
b706222014-08-20Henrik Grubbström (Grubba) int low_is_variant_dispatcher(struct identifier *id) { if (!id) return 0; return (IDENTIFIER_IS_C_FUNCTION(id->identifier_flags) && !IDENTIFIER_IS_ALIAS(id->identifier_flags) && (id->func.c_fun == f_dispatch_variant)); }
a0a83a2013-06-16Henrik Grubbström (Grubba) int is_variant_dispatcher(struct program *prog, int fun)
b3d2c22013-06-02Henrik Grubbström (Grubba) { struct reference *ref; struct identifier *id; if (fun < 0) return 0; ref = PTR_FROM_INT(prog, fun); id = ID_FROM_PTR(prog, ref);
b706222014-08-20Henrik Grubbström (Grubba)  return low_is_variant_dispatcher(id);
b3d2c22013-06-02Henrik Grubbström (Grubba) } static int add_variant_dispatcher(struct pike_string *name, struct pike_type *type, int id_flags) { union idptr dispatch_fun; dispatch_fun.c_fun = f_dispatch_variant; return define_function(name, type, id_flags & ~(ID_VARIANT|ID_LOCAL), IDENTIFIER_C_FUNCTION, &dispatch_fun, 0); }
29615e2014-10-18Henrik Grubbström (Grubba) /** * End the current compilation pass. * * @param finish * finish-state:
2659cf2002-05-10Henrik Grubbström (Grubba)  * * 0: First pass. * 1: Last pass. * 2: Called from decode_value().
29615e2014-10-18Henrik Grubbström (Grubba)  * * Note: This function is misnamed, since it's run after all passes.
2659cf2002-05-10Henrik Grubbström (Grubba)  */
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) struct program *end_first_pass(int finish)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
8853882008-04-26Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
0ffa001998-01-13Fredrik Hübinette (Hubbe)  int e;
b160c22013-05-26Henrik Grubbström (Grubba)  struct program *prog = Pike_compiler->new_program;
25b7812014-04-20Henrik Grubbström (Grubba)  struct pike_string *init_name;
b160c22013-05-26Henrik Grubbström (Grubba)  int num_refs = prog->num_identifier_references; union idptr dispatch_fun; dispatch_fun.c_fun = f_dispatch_variant; /* Collect variant functions that have been defined in this program, * and add the corresponding dispatchers. */ for (e = 0; e < num_refs; e++) { struct identifier *id; struct pike_string *name; struct pike_type *type; int id_flags;
2ad81f2013-12-12Henrik Grubbström (Grubba)  int opt_flags;
b160c22013-05-26Henrik Grubbström (Grubba)  int j; if (prog->identifier_references[e].inherit_offset) continue;
b3d2c22013-06-02Henrik Grubbström (Grubba)  if (!is_variant_dispatcher(prog, e)) continue; /* Found a dispatcher. */
b160c22013-05-26Henrik Grubbström (Grubba)  id = ID_FROM_INT(prog, e); name = id->name;
b3d2c22013-06-02Henrik Grubbström (Grubba)  type = NULL; id_flags = 0;
2ad81f2013-12-12Henrik Grubbström (Grubba)  opt_flags = 0;
b160c22013-05-26Henrik Grubbström (Grubba)  CDFPRINTF((stderr, "Collecting variants of \"%s\"...\n", name->str));
b3d2c22013-06-02Henrik Grubbström (Grubba)  /* Collect the variants of the function. */ j = prog->num_identifier_references; while ((j = really_low_find_variant_identifier(name, prog, NULL, j, SEE_PROTECTED|SEE_PRIVATE)) >= 0) { struct reference *ref = prog->identifier_references + j;
b160c22013-05-26Henrik Grubbström (Grubba)  id = ID_FROM_INT(prog, j);
b3d2c22013-06-02Henrik Grubbström (Grubba)  id_flags |= ref->id_flags;
2ad81f2013-12-12Henrik Grubbström (Grubba)  opt_flags |= id->opt_flags;
b3d2c22013-06-02Henrik Grubbström (Grubba)  /* NB: The dispatcher needs the variant references to * not get overloaded for the ::-operator to work. */
d6b3da2013-05-30Henrik Grubbström (Grubba)  prog->identifier_references[j].id_flags |= ID_LOCAL;
9b4f212013-06-17Arne Goedeke  { struct pike_type * temp = type; type = or_pike_types(type, id->type, 1); if (temp) free_type(temp); }
b160c22013-05-26Henrik Grubbström (Grubba) #ifdef COMPILER_DEBUG fprintf(stderr, "type: "); simple_describe_type(id->type); fprintf(stderr, "\n"); #endif } #ifdef COMPILER_DEBUG fprintf(stderr, "Dispatcher type: "); simple_describe_type(type); fprintf(stderr, "\n"); #endif
b3d2c22013-06-02Henrik Grubbström (Grubba)  /* Update the type of the dispatcher. */ id = ID_FROM_INT(prog, e); free_type(id->type); id->type = type;
2ad81f2013-12-12Henrik Grubbström (Grubba)  id->opt_flags = opt_flags;
25df692014-04-16Henrik Grubbström (Grubba)  prog->identifier_references[e].id_flags |= id_flags & ~(ID_VARIANT|ID_LOCAL);
b160c22013-05-26Henrik Grubbström (Grubba)  next_ref: ; }
0ffa001998-01-13Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  debug_malloc_touch(Pike_compiler->fake_object); debug_malloc_touch(Pike_compiler->fake_object->storage);
648a1a2000-06-22Fredrik Hübinette (Hubbe) 
25b7812014-04-20Henrik Grubbström (Grubba)  init_name = lfun_strings[LFUN___INIT];
0ffa001998-01-13Fredrik Hübinette (Hubbe)  /* Collect references to inherited __INIT functions */
2659cf2002-05-10Henrik Grubbström (Grubba)  if (!(Pike_compiler->new_program->flags & PROGRAM_AVOID_CHECK)) { for(e=Pike_compiler->new_program->num_inherits-1;e;e--)
0ffa001998-01-13Fredrik Hübinette (Hubbe)  {
2659cf2002-05-10Henrik Grubbström (Grubba)  int id; if(Pike_compiler->new_program->inherits[e].inherit_level!=1) continue;
f9843b2013-07-17Henrik Grubbström (Grubba)  id = Pike_compiler->new_program->inherits[e].prog->lfuns[LFUN___INIT]; id = really_low_reference_inherited_identifier(0, e, id);
2659cf2002-05-10Henrik Grubbström (Grubba)  if(id!=-1) { Pike_compiler->init_node=mknode(F_COMMA_EXPR, mkcastnode(void_type_string, mkapplynode(mkidentifiernode(id),0)), Pike_compiler->init_node); }
0ffa001998-01-13Fredrik Hübinette (Hubbe)  } }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
72a7dd2014-04-20Henrik Grubbström (Grubba)  if (finish == 1) { if (Pike_compiler->compiler_pass == 1) { /* Called from end_program(). */ if (Pike_compiler->init_node) { /* Make sure that the __INIT symbol exists, so that * we won't get a fatal when we add the actual code * further down when we have entered pass 2.
25b7812014-04-20Henrik Grubbström (Grubba)  * * Also make sure that it is marked as having side effects, * or it will be optimized away when inherited...
72a7dd2014-04-20Henrik Grubbström (Grubba)  */
25b7812014-04-20Henrik Grubbström (Grubba)  define_function(init_name, function_type_string, ID_PROTECTED, IDENTIFIER_PIKE_FUNCTION, NULL, OPT_SIDE_EFFECT|OPT_EXTERNAL_DEPEND);
72a7dd2014-04-20Henrik Grubbström (Grubba)  } } Pike_compiler->compiler_pass = 2; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  /* * Define the __INIT function, but only if there was any code * to initialize. */
0ffa001998-01-13Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->init_node)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
25b7812014-04-20Henrik Grubbström (Grubba)  /* Inhibit this_function. */
dc80622002-11-14Henrik Grubbström (Grubba)  Pike_compiler->compiler_frame->current_function_number = -2;
25b7812014-04-20Henrik Grubbström (Grubba)  e=dooptcode(init_name,
3d78821999-11-06Henrik Grubbström (Grubba)  mknode(F_COMMA_EXPR,
dc80622002-11-14Henrik Grubbström (Grubba)  Pike_compiler->init_node, mknode(F_RETURN,mkintnode(0),0)),
a5787d1999-03-03Fredrik Hübinette (Hubbe)  function_type_string,
95489a2008-06-29Martin Nilsson  ID_PROTECTED);
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->init_node=0;
2659cf2002-05-10Henrik Grubbström (Grubba)  } else if (finish == 2) { /* Called from decode_value(). */ e = low_find_lfun(Pike_compiler->new_program, LFUN___INIT);
b270252013-07-17Henrik Grubbström (Grubba)  if ((e != -1) && (ID_FROM_INT(Pike_compiler->new_program, e)->func.offset == -1)) {
f9843b2013-07-17Henrik Grubbström (Grubba)  /* Just a prototype. Make sure not to call it. */ e = -1; }
a5787d1999-03-03Fredrik Hübinette (Hubbe)  }else{
f9843b2013-07-17Henrik Grubbström (Grubba)  /* Note that we may zap an __INIT that existed in pass 1 here. * This is intentional to avoid having to keep track of whether * __INIT() is just a prototype or not. */
a5787d1999-03-03Fredrik Hübinette (Hubbe)  e=-1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->new_program->lfuns[LFUN___INIT]=e;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  pop_compiler_frame(); /* Pop __INIT local variables */
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->num_parse_error > 0)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
ec994b2008-08-13Martin Stjernholm  CDFPRINTF((stderr, "th(%ld) %p Compilation errors (%d).\n", (long)th_self(), Pike_compiler->new_program, Pike_compiler->num_parse_error));
5267b71995-08-09Fredrik Hübinette (Hubbe)  prog=0; }else{
bad5162000-06-23Fredrik Hübinette (Hubbe)  prog=Pike_compiler->new_program;
8c83371998-04-16Fredrik Hübinette (Hubbe)  add_ref(prog);
5580691996-06-21Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->new_program->flags |= PROGRAM_PASS_1_DONE;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(finish) {
f3c7152001-04-14Fredrik Hübinette (Hubbe)  if(Pike_compiler->new_program->flags & PROGRAM_USES_PARENT) { Pike_compiler->new_program->parent_info_storage = add_xstorage(sizeof(struct parent_info), ALIGNOF(struct parent_info), 0); }else{ /* Cause errors if used hopefully */ Pike_compiler->new_program->parent_info_storage=-1; }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  fixate_program();
3b7d182001-09-26Fredrik Hübinette (Hubbe)  if(Pike_compiler->num_parse_error) { free_program(prog); prog=0; }else{ optimize_program(Pike_compiler->new_program); Pike_compiler->new_program->flags |= PROGRAM_FINISHED; }
aaf40c2013-11-03Henrik Grubbström (Grubba)  } else { /* All references in prog are now known. * Fixup identifier overrides or external symbols, * so that inherit is safe. */ for (e = 0; e < prog->num_identifier_references; e++) { struct reference *ref = prog->identifier_references + e; if (ref->id_flags & ID_HIDDEN) continue; if (ref->inherit_offset != 0) continue; override_identifier (ref, ID_FROM_PTR (prog, ref)->name, ID_EXTERN); }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
aa771b2003-08-20Martin Stjernholm #ifdef PIKE_DEBUG
4c4f932005-05-26Martin Stjernholm  if (prog) { check_program(prog); if(l_flag) dump_program_desc(prog); }
aa771b2003-08-20Martin Stjernholm #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
a786431999-11-18Martin Stjernholm  #ifdef PROGRAM_BUILD_DEBUG fprintf (stderr, "%.*sfinishing program %d (pass=%d)\n",
8853882008-04-26Henrik Grubbström (Grubba)  c->compilation_depth, "", Pike_compiler->new_program->id, Pike_compiler->compiler_pass);
a786431999-11-18Martin Stjernholm #endif
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  toss_compilation_resources();
5267b71995-08-09Fredrik Hübinette (Hubbe) 
cb67042001-12-12Martin Stjernholm #if 0
aed42d1999-12-29Martin Stjernholm  CDFPRINTF((stderr,
cb67042001-12-12Martin Stjernholm  "th(%ld) end_first_pass(): "
ec994b2008-08-13Martin Stjernholm  "%p compilation_depth:%d, Pike_compiler->compiler_pass:%d\n", (long)th_self(), prog,
8853882008-04-26Henrik Grubbström (Grubba)  c->compilation_depth, Pike_compiler->compiler_pass));
cb67042001-12-12Martin Stjernholm #endif
aed42d1999-12-29Martin Stjernholm 
518b042011-11-20Henrik Grubbström (Grubba)  if(!Pike_compiler->compiler_frame && (Pike_compiler->compiler_pass==2 || !prog) && c->resolve_cache)
aed42d1999-12-29Martin Stjernholm  {
518b042011-11-20Henrik Grubbström (Grubba)  free_mapping(dmalloc_touch(struct mapping *, c->resolve_cache)); c->resolve_cache=0;
aed42d1999-12-29Martin Stjernholm  }
f807f01999-11-11Henrik Grubbström (Grubba) #ifdef SHARED_NODES /* free(node_hash.table); */ #endif /* SHARED_NODES */
5c8e891995-10-29Fredrik Hübinette (Hubbe) #define POP #include "compilation.h"
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
fb2f661998-11-05Fredrik Hübinette (Hubbe)  exit_type_stack();
05590d1998-04-23Fredrik Hübinette (Hubbe) 
61bd382004-09-27Henrik Grubbström (Grubba) 
b3cca72001-06-14Henrik Grubbström (Grubba)  CDFPRINTF((stderr,
cb67042001-12-12Martin Stjernholm  "th(%ld) %p end_first_pass(%d): "
8b5b3a2014-04-28Henrik Grubbström (Grubba)  "lock_depth:%d, compilation_depth:%d\n",
cb67042001-12-12Martin Stjernholm  (long)th_self(), prog, finish,
8b5b3a2014-04-28Henrik Grubbström (Grubba)  lock_depth, c->compilation_depth));
b3cca72001-06-14Henrik Grubbström (Grubba) 
8853882008-04-26Henrik Grubbström (Grubba)  c->compilation_depth--;
a91ca01998-07-10Henrik Grubbström (Grubba) 
8b5b3a2014-04-28Henrik Grubbström (Grubba)  unlock_pike_compiler();
ea32c11998-04-13Henrik Grubbström (Grubba) 
29d1e62005-05-31Henrik Grubbström (Grubba) #if 0 #ifdef PIKE_USE_MACHINE_CODE if (prog && (((unsigned long long *)prog->program)[-1] != 0xdeadfeedf00dfaddLL)) { Pike_fatal("Bad mexec magic!\n"); } #endif /* PIKE_USE_MACHINE_CODE */ #endif /* 0 */
5267b71995-08-09Fredrik Hübinette (Hubbe)  return prog; }
29615e2014-10-18Henrik Grubbström (Grubba) /**
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  * Finish this program, returning the newly built program */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT struct program *debug_end_program(void)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) { return end_first_pass(1); }
29615e2014-10-18Henrik Grubbström (Grubba) /**
6f96692009-09-12Henrik Grubbström (Grubba)  * Allocate space needed for this program in the object structure.
5267b71995-08-09Fredrik Hübinette (Hubbe)  * An offset to the data is returned. */
b819352000-08-14Henrik Grubbström (Grubba) PMOD_EXPORT size_t low_add_storage(size_t size, size_t alignment, ptrdiff_t modulo_orig)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
d3b06f2000-08-10Henrik Grubbström (Grubba)  ptrdiff_t offset; ptrdiff_t modulo;
2ad3c01999-09-16Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(!size) return Pike_compiler->new_program->storage_needed;
2ad3c01999-09-16Fredrik Hübinette (Hubbe) 
90e9781999-01-31Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG if(alignment <=0 || (alignment & (alignment-1)) || alignment > 256)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Alignment must be 1,2,4,8,16,32,64,128 or 256 not %ld\n",
69bb402000-08-17Henrik Grubbström (Grubba)  PTRDIFF_T_TO_LONG(alignment));
90e9781999-01-31Fredrik Hübinette (Hubbe) #endif
648a1a2000-06-22Fredrik Hübinette (Hubbe)  modulo=( modulo_orig /* +OFFSETOF(object,storage) */ ) % alignment;
b1c8031999-09-15Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  offset=DO_ALIGN(Pike_compiler->new_program->storage_needed-modulo,alignment)+modulo;
90e9781999-01-31Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(!Pike_compiler->new_program->storage_needed) { /* Shouldn't Pike_compiler->new_program->storage_needed be set here?
29338d1999-09-29Henrik Grubbström (Grubba)  * Otherwise the debug code below ought to be trigged. * But since it isn't, I guess this is dead code? * /grubba 1999-09-28
eb071e1999-09-28Fredrik Hübinette (Hubbe)  * * No, the below offset represents the storage in the beginning * of obj->storage which is not used because of alignment constraints. * However, for historical reasons, prog->storage_offset needs to * contain this unused space as well. This means that the real * space used by all variables in an object is really: * o->prog->storage_needed - o->prog->inherits[0].storage_offset, * This can also be written as STORAGE_NEEDED(o->prog) * STORAGE_NEEDED() is defined in program.h. * /Hubbe 1999-09-29
0ee2331999-09-29Henrik Grubbström (Grubba)  * * Oops, seems I read the test below the wrong way around. * /grubba 1999-09-29
29338d1999-09-29Henrik Grubbström (Grubba)  */
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->new_program->inherits[0].storage_offset=offset;
29338d1999-09-29Henrik Grubbström (Grubba)  }
90e9781999-01-31Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->new_program->alignment_needed<alignment)
b819352000-08-14Henrik Grubbström (Grubba)  Pike_compiler->new_program->alignment_needed = DO_NOT_WARN((unsigned INT8)alignment);
90e9781999-01-31Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(offset < Pike_compiler->new_program->storage_needed)
5aad932002-08-15Marcus Comstedt  Pike_fatal("add_storage failed horribly!\n");
b1c8031999-09-15Fredrik Hübinette (Hubbe) 
648a1a2000-06-22Fredrik Hübinette (Hubbe)  if( (offset /* + OFFSETOF(object,storage) */ - modulo_orig ) % alignment )
5aad932002-08-15Marcus Comstedt  Pike_fatal("add_storage failed horribly(2) %ld %ld %ld %ld!\n",
d3b06f2000-08-10Henrik Grubbström (Grubba)  DO_NOT_WARN((long)offset),
648a1a2000-06-22Fredrik Hübinette (Hubbe)  (long)0 /* + OFFSETOF(object,storage) */,
63540d2000-08-15Henrik Grubbström (Grubba)  DO_NOT_WARN((long)modulo_orig),
d3b06f2000-08-10Henrik Grubbström (Grubba)  DO_NOT_WARN((long)alignment));
27ae842000-02-07Per Hedbor 
1994981998-04-07Fredrik Hübinette (Hubbe) #endif
b1c8031999-09-15Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  Pike_compiler->new_program->storage_needed = offset + size;
b1c8031999-09-15Fredrik Hübinette (Hubbe) 
b819352000-08-14Henrik Grubbström (Grubba)  return (size_t) offset;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
f3c7152001-04-14Fredrik Hübinette (Hubbe) /* * Internal function. * Adds object storage that will *not* be inherited. */ static size_t add_xstorage(size_t size, size_t alignment, ptrdiff_t modulo_orig) { ptrdiff_t offset, modulo, available; int e; if(!size) return Pike_compiler->new_program->xstorage; modulo=( modulo_orig /* +OFFSETOF(object,storage) */ ) % alignment; offset=DO_ALIGN(Pike_compiler->new_program->xstorage-modulo,alignment)+modulo; Pike_compiler->new_program->xstorage = offset + size; /* Move all inherits to make room */ available = Pike_compiler->new_program->inherits[0].storage_offset;
21fdac2001-05-02Henrik Grubbström (Grubba)  if(available < (ptrdiff_t)(offset+size))
f3c7152001-04-14Fredrik Hübinette (Hubbe)  { available= DO_ALIGN( ((offset + size) - available), Pike_compiler->new_program->alignment_needed); for(e=0;e<Pike_compiler->new_program->num_inherits;e++) Pike_compiler->new_program->inherits[e].storage_offset+=available; Pike_compiler->new_program->storage_needed+=available; } return (size_t) offset; }
763f682001-03-12Fredrik Hübinette (Hubbe) typedef void (*oldhandlertype)(struct object *);
a547892007-05-13Martin Stjernholm 
99cce52007-05-26Martin Stjernholm static void compat_event_handler(int e)
763f682001-03-12Fredrik Hübinette (Hubbe) { oldhandlertype handler;
d0787c2001-09-20Fredrik Hübinette (Hubbe)  debug_malloc_touch(Pike_fp->current_object);
fa93a52008-02-28Henrik Grubbström (Grubba)  handler=((oldhandlertype *)Pike_fp->context->prog->program)[e];
763f682001-03-12Fredrik Hübinette (Hubbe)  if(handler) handler(Pike_fp->current_object);
d0787c2001-09-20Fredrik Hübinette (Hubbe)  debug_malloc_touch(Pike_fp->current_object);
763f682001-03-12Fredrik Hübinette (Hubbe) } static void add_compat_event_handler(void) { if(Pike_compiler->new_program->event_handler != compat_event_handler) { unsigned int e,d; unsigned char *tmp=(unsigned char *)&Pike_compiler->new_program->event_handler;
6d727b2001-07-08Henrik Grubbström (Grubba)  for(d=0;d<NUM_PROG_EVENTS;d++) { /* FIXME: This looks like it might be broken. */
b5dc812001-07-12Fredrik Hübinette (Hubbe)  /* Broken how? -Hubbe */
6d727b2001-07-08Henrik Grubbström (Grubba) #ifdef HAVE_COMPUTED_GOTO add_to_program(Pike_compiler->new_program->event_handler); #else /* !HAVE_COMPUTED_GOTO */
763f682001-03-12Fredrik Hübinette (Hubbe)  for(e=0;e<sizeof(Pike_compiler->new_program->event_handler);e++) add_to_program(tmp[e]);
6d727b2001-07-08Henrik Grubbström (Grubba) #endif /* HAVE_COMPUTED_GOTO */ }
763f682001-03-12Fredrik Hübinette (Hubbe)  Pike_compiler->new_program->event_handler=compat_event_handler; } }
1994981998-04-07Fredrik Hübinette (Hubbe) 
29615e2014-10-18Henrik Grubbström (Grubba) /**
a547892007-05-13Martin Stjernholm  * Set a callback to be called when this program is cloned. *
99cce52007-05-26Martin Stjernholm  * This function is obsolete; see pike_set_prog_event_callback for * details.
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void set_init_callback(void (*init)(struct object *))
5267b71995-08-09Fredrik Hübinette (Hubbe) {
763f682001-03-12Fredrik Hübinette (Hubbe)  add_compat_event_handler(); ((oldhandlertype *)Pike_compiler->new_program->program)[PROG_EVENT_INIT]=init;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
29615e2014-10-18Henrik Grubbström (Grubba) /**
a547892007-05-13Martin Stjernholm  * Set a callback to be called when clones of this program are * destructed. *
99cce52007-05-26Martin Stjernholm  * This function is obsolete; see pike_set_prog_event_callback for * details. * * Note: If the callback only does very trivial stuff, like freeing or * clearing a few pointers in the object storage, you can do * * Pike_compiler->new_program->flags &= ~PROGRAM_LIVE_OBJ; * * after the set_exit_callback call. That allows the gc to operate * more efficiently, but the effect is that the callback might be * called out of order for PROG_EVENT_EXIT events; see the docs for * PROGRAM_LIVE_OBJ in program.h for further details.
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void set_exit_callback(void (*exit)(struct object *))
5267b71995-08-09Fredrik Hübinette (Hubbe) {
763f682001-03-12Fredrik Hübinette (Hubbe)  add_compat_event_handler(); ((oldhandlertype *)Pike_compiler->new_program->program)[PROG_EVENT_EXIT]=exit;
99cce52007-05-26Martin Stjernholm  Pike_compiler->new_program->flags |= PROGRAM_LIVE_OBJ;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
29615e2014-10-18Henrik Grubbström (Grubba) /**
e2d9e62000-06-10Martin Stjernholm  * This callback is used by the gc to traverse all references to
ad8d052008-05-02Martin Stjernholm  * things in memory. It should call some gc_recurse_* function exactly * once for each reference that the pike internals doesn't know about.
e2d9e62000-06-10Martin Stjernholm  * * If a reference is shared between objects, it should be traversed * once for every instance sharing it. * * The callback might be called more than once for the same instance * during a gc pass. The gc assumes that the references are enumerated * in the same order in that case.
03bcb92001-03-12Fredrik Hübinette (Hubbe)  *
a9ae572004-04-04Martin Stjernholm  * The callback is called after any mapped variables on the object * have been recursed (and possibly freed). *
5e83442008-05-11Martin Stjernholm  * If there are pointers to allocated memory that you keep track of on * the C level then you should add something like this to the recurse * callback so that Pike.count_memory remains accurate:
ad8d052008-05-02Martin Stjernholm  *
9061492008-06-23Martin Stjernholm  * if (mc_count_bytes (Pike_fp->current_object))
5e83442008-05-11Martin Stjernholm  * mc_counted_bytes += <size of the allocated memory block(s)>
ad8d052008-05-02Martin Stjernholm  * * If the allocated memory is shared between objects then it gets more
5e83442008-05-11Martin Stjernholm  * complicated and you need to write visit_thing_fn callbacks. See * e.g. visit_mapping and visit_mapping_data for how to do that.
ad8d052008-05-02Martin Stjernholm  *
99cce52007-05-26Martin Stjernholm  * This function is obsolete; see pike_set_prog_event_callback for * details.
d4828c1997-07-17Fredrik Hübinette (Hubbe)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void set_gc_recurse_callback(void (*m)(struct object *))
d4828c1997-07-17Fredrik Hübinette (Hubbe) {
763f682001-03-12Fredrik Hübinette (Hubbe)  add_compat_event_handler(); ((oldhandlertype *)Pike_compiler->new_program->program)[PROG_EVENT_GC_RECURSE]=m;
d4828c1997-07-17Fredrik Hübinette (Hubbe) }
29615e2014-10-18Henrik Grubbström (Grubba) /**
ad8d052008-05-02Martin Stjernholm  * This callback is used by the gc to count all references to things * in memory. It should call gc_check, gc_check_(weak_)svalues or
e2d9e62000-06-10Martin Stjernholm  * gc_check_(weak_)short_svalue exactly once for each reference that
ad8d052008-05-02Martin Stjernholm  * the pike internals don't know about.
e2d9e62000-06-10Martin Stjernholm  * * If a reference is shared between objects, it should be counted once * for all shared instances. The return value from gc_check is useful * to ensure this; it's zero when called the first time for its
ad8d052008-05-02Martin Stjernholm  * argument (it is perfectly fine to use gc_check on things that the * pike core doesn't know about, but they must have an INT32 refcount * first).
03bcb92001-03-12Fredrik Hübinette (Hubbe)  *
99cce52007-05-26Martin Stjernholm  * This function is obsolete; see pike_set_prog_event_callback for * details.
f0c3d31998-04-05Fredrik Hübinette (Hubbe)  */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void set_gc_check_callback(void (*m)(struct object *))
f0c3d31998-04-05Fredrik Hübinette (Hubbe) {
763f682001-03-12Fredrik Hübinette (Hubbe)  add_compat_event_handler(); ((oldhandlertype *)Pike_compiler->new_program->program)[PROG_EVENT_GC_CHECK]=m;
f0c3d31998-04-05Fredrik Hübinette (Hubbe) }
29615e2014-10-18Henrik Grubbström (Grubba) /**
a547892007-05-13Martin Stjernholm  * Set a callback to be called when any of the special program events * occur. The event type is sent as an integer argument. The events * include, but might not be limited to, the following: * * PROG_EVENT_INIT * An object is being cloned from the program. See set_init_callback * for details. * PROG_EVENT_EXIT * An object is being destructed. See set_exit_callback for details. * PROG_EVENT_GC_RECURSE * An object is being recursed by the gc. See * set_gc_recurse_callback for details. * PROG_EVENT_GC_CHECK * An object is being checked by the gc. See set_gc_check_callback * for details. *
99cce52007-05-26Martin Stjernholm  * Note that installing an event callback will set the * PROGRAM_LIVE_OBJ flag since the callback might act on the * PROG_EVENT_EXIT event. If the callback won't do anything for that * event (or if it only does something very trivial for it), you * should do * * Pike_compiler->new_program->flags &= ~PROGRAM_LIVE_OBJ;
a547892007-05-13Martin Stjernholm  *
99cce52007-05-26Martin Stjernholm  * afterwards to clear it again. That allows the gc to operate more * efficiently, but the effect is that the callback might be called * out of order for PROG_EVENT_EXIT events; see the docs for * PROGRAM_LIVE_OBJ in program.h for further details.
a547892007-05-13Martin Stjernholm  */
f13b952006-07-05Martin Stjernholm PMOD_EXPORT void pike_set_prog_event_callback(void (*cb)(int))
03bcb92001-03-12Fredrik Hübinette (Hubbe) { #ifdef PIKE_DEBUG if(Pike_compiler->new_program->event_handler)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Program already has an event handler!\n");
03bcb92001-03-12Fredrik Hübinette (Hubbe) #endif Pike_compiler->new_program->event_handler=cb;
99cce52007-05-26Martin Stjernholm  Pike_compiler->new_program->flags |= PROGRAM_LIVE_OBJ;
03bcb92001-03-12Fredrik Hübinette (Hubbe) }
f13b952006-07-05Martin Stjernholm PMOD_EXPORT void pike_set_prog_optimize_callback(node *(*opt)(node *))
a5d45c2001-05-26Henrik Grubbström (Grubba) { #ifdef PIKE_DEBUG if(Pike_compiler->new_program->optimize)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Program already has an optimize handler!\n");
a5d45c2001-05-26Henrik Grubbström (Grubba) #endif Pike_compiler->new_program->optimize = opt; }
29615e2014-10-18Henrik Grubbström (Grubba) /** * Reference an inherited identifier. * * @param q * Program state for the program being compiled that will have * the reference added. May be NULL to indicate Pike_compiler. * * @param i * Inherit number in q->new_program. * * @param f * Reference number in q->new_program->inherit[i].prog. * * @return * Returns an equivalent reference that is INLINE|HIDDEN. */
b0c1a02013-10-28Henrik Grubbström (Grubba) PMOD_EXPORT int really_low_reference_inherited_identifier(struct program_state *q,
8029d72013-10-31Henrik Grubbström (Grubba)  int i, int f)
3a3eac2004-01-19Henrik Grubbström (Grubba) { struct program *np=(q?q:Pike_compiler)->new_program; struct reference funp; struct program *p; int d, num_id_refs;
8029d72013-10-31Henrik Grubbström (Grubba)  if(f==-1) return -1;
3a3eac2004-01-19Henrik Grubbström (Grubba) 
8029d72013-10-31Henrik Grubbström (Grubba)  p = np->inherits[i].prog;
3a3eac2004-01-19Henrik Grubbström (Grubba) 
8029d72013-10-31Henrik Grubbström (Grubba)  funp = p->identifier_references[f]; funp.inherit_offset += i;
3a3eac2004-01-19Henrik Grubbström (Grubba)  funp.id_flags = (funp.id_flags & ~ID_INHERITED) | ID_INLINE|ID_HIDDEN; num_id_refs = np->num_identifier_references; for(d = 0; d < num_id_refs; d++) { struct reference *refp; refp = np->identifier_references + d;
1f7f172007-10-11Henrik Grubbström (Grubba)  if ((refp->inherit_offset == funp.inherit_offset) && (refp->identifier_offset == funp.identifier_offset) &&
8029d72013-10-31Henrik Grubbström (Grubba)  ((refp->id_flags | ID_USED) == (funp.id_flags | ID_USED))) {
1f7f172007-10-11Henrik Grubbström (Grubba)  return d;
8029d72013-10-31Henrik Grubbström (Grubba)  }
3a3eac2004-01-19Henrik Grubbström (Grubba)  }
77fbd72010-11-25Henrik Grubbström (Grubba)  funp.run_time_type = PIKE_T_UNKNOWN;
3a3eac2004-01-19Henrik Grubbström (Grubba)  if(q) low_add_to_identifier_references(q,funp); else add_to_identifier_references(funp); /* NOTE: np->num_identifier_references has been increased by one by * {low_,}add_to_identifier_references(). */ #ifdef PIKE_DEBUG if (num_id_refs != np->num_identifier_references-1) { fatal("Unexpected number of identifier references: %d != %d\n", num_id_refs, np->num_identifier_references-1); } #endif /* PIKE_DEBUG */
8029d72013-10-31Henrik Grubbström (Grubba) 
3a3eac2004-01-19Henrik Grubbström (Grubba)  return num_id_refs; /* aka np->num_identifier_references - 1 */ }
b0c1a02013-10-28Henrik Grubbström (Grubba) PMOD_EXPORT int low_reference_inherited_identifier(struct program_state *q, int e, struct pike_string *name, int flags)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
bad5162000-06-23Fredrik Hübinette (Hubbe)  struct program *np=(q?q:Pike_compiler)->new_program;
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct program *p;
6ce7322008-07-16Martin Stjernholm  int i;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
d429a71998-02-24Fredrik Hübinette (Hubbe)  p=np->inherits[e].prog;
5267b71995-08-09Fredrik Hübinette (Hubbe)  i=find_shared_string_identifier(name,p);
c0e4461998-06-23Fredrik Hübinette (Hubbe)  if(i==-1) {
8aae6d1999-08-19Fredrik Hübinette (Hubbe)  i=really_low_find_shared_string_identifier(name,p, flags);
c0e4461998-06-23Fredrik Hübinette (Hubbe)  if(i==-1) return -1; }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
7fda7a1997-09-08Fredrik Hübinette (Hubbe)  if(p->identifier_references[i].id_flags & ID_HIDDEN)
5267b71995-08-09Fredrik Hübinette (Hubbe)  return -1;
8aae6d1999-08-19Fredrik Hübinette (Hubbe)  if(p->identifier_references[i].id_flags & ID_PRIVATE) if(!(flags & SEE_PRIVATE)) return -1;
3a3eac2004-01-19Henrik Grubbström (Grubba)  return really_low_reference_inherited_identifier(q, e, i);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
ba8c392000-06-26Henrik Grubbström (Grubba) int find_inherit(struct program *p, struct pike_string *name)
9a3e732000-06-26Henrik Grubbström (Grubba) { int e;
6716b82013-11-08Henrik Grubbström (Grubba)  int level = p->num_inherits; /* Larger than any inherit_level. */ int res = 0;
9a3e732000-06-26Henrik Grubbström (Grubba) 
ba8c392000-06-26Henrik Grubbström (Grubba) #if 0 fprintf(stderr, "find_inherit(0x%08lx, \"%s\")...\n", (unsigned long)p, name->str); #endif /* 0 */
6716b82013-11-08Henrik Grubbström (Grubba) 
ba8c392000-06-26Henrik Grubbström (Grubba)  for(e = p->num_inherits-1; e>0; e--) { #if 0 fprintf(stderr, " %04d: %04d %s\n", e, p->inherits[e].inherit_level, p->inherits[e].name?p->inherits[e].name->str:"NULL"); #endif /* 0 */
6716b82013-11-08Henrik Grubbström (Grubba)  if (p->inherits[e].inherit_level >= level) continue; if (name == p->inherits[e].name) { res = e; level = p->inherits[e].inherit_level; if (level == 1) break; }
9a3e732000-06-26Henrik Grubbström (Grubba)  }
6716b82013-11-08Henrik Grubbström (Grubba)  return res;
9a3e732000-06-26Henrik Grubbström (Grubba) }
29615e2014-10-18Henrik Grubbström (Grubba) /** * Reference the symbol inherit::name in the lexical context
6d0fdb2013-04-28Henrik Grubbström (Grubba)  * specified by state. *
29615e2014-10-18Henrik Grubbström (Grubba)  * @return Returns the reference in state->new_program if found.
6d0fdb2013-04-28Henrik Grubbström (Grubba)  */ PMOD_EXPORT int reference_inherited_identifier(struct program_state *state, struct pike_string *inherit, struct pike_string *name)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
6d0fdb2013-04-28Henrik Grubbström (Grubba)  int e, id;
a005eb1999-03-04Fredrik Hübinette (Hubbe)  struct program *p;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
6d0fdb2013-04-28Henrik Grubbström (Grubba)  if (name != debug_findstring(name)) Pike_fatal("reference_inherited_identifier on nonshared string.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
a005eb1999-03-04Fredrik Hübinette (Hubbe) 
6d0fdb2013-04-28Henrik Grubbström (Grubba)  if (!state) state = Pike_compiler;
4c083b2013-04-28Henrik Grubbström (Grubba)  p = state->new_program;
a005eb1999-03-04Fredrik Hübinette (Hubbe) 
6f96692009-09-12Henrik Grubbström (Grubba)  /* FIXME: This loop could be optimized by advancing by the number * of inherits in the inherit. But in that case the loop * would have to go the other way. */
6d0fdb2013-04-28Henrik Grubbström (Grubba)  for (e = p->num_inherits; e--;) { if (p->inherits[e].inherit_level != 1) continue; if (inherit && (inherit != p->inherits[e].name)) continue;
a005eb1999-03-04Fredrik Hübinette (Hubbe) 
6d0fdb2013-04-28Henrik Grubbström (Grubba)  id = low_reference_inherited_identifier(state, e, name, SEE_PROTECTED);
a005eb1999-03-04Fredrik Hübinette (Hubbe) 
6d0fdb2013-04-28Henrik Grubbström (Grubba)  if (id != -1) return id;
d429a71998-02-24Fredrik Hübinette (Hubbe)  }
6d0fdb2013-04-28Henrik Grubbström (Grubba)  return -1;
d429a71998-02-24Fredrik Hübinette (Hubbe) }
6f96692009-09-12Henrik Grubbström (Grubba) /* FIXME: This function probably doesn't do what it is intended to do * if the last inherit had inherits of its own. Consider removal. */
06983f1996-09-22Fredrik Hübinette (Hubbe) void rename_last_inherit(struct pike_string *n)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->new_program->inherits[Pike_compiler->new_program->num_inherits].name) free_string(Pike_compiler->new_program->inherits[Pike_compiler->new_program->num_inherits].name); copy_shared_string(Pike_compiler->new_program->inherits[Pike_compiler->new_program->num_inherits].name,
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  n);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
88e9fb2003-08-03Martin Stjernholm #if 0
342fef2000-08-23Fredrik Hübinette (Hubbe) static int locate_parent_state(struct program_state **state, struct inherit **i, int *parent_identifier, int depth) { int result=1; if(depth<=0) return depth; while(depth-->0) {
684bd22003-08-02Martin Stjernholm  if( (*i)->parent_offset != INHERIT_PARENT)
342fef2000-08-23Fredrik Hübinette (Hubbe)  { int tmp=(*i)->parent_identifier; if( (*i)->parent_offset > 0) { int po=(*i)->parent_offset; *parent_identifier = (*state)->parent_identifier; *state = (*state)->previous; result++; fprintf(stderr,"INHERIT: state=state->previous (po=%d)\n",po); if(po>1) { *i=INHERIT_FROM_INT( (*state)->new_program, *parent_identifier); result+=locate_parent_state(state,i,parent_identifier, po-1); } } if(tmp != -1) { if( *parent_identifier == -4711) { *parent_identifier = tmp; }else{ *parent_identifier = tmp + INHERIT_FROM_INT( (*state)->new_program, *parent_identifier)->identifier_level; } } }else{ fprintf(stderr,"INHERIT: Bailout!\n"); return result+depth+1; } *i = INHERIT_FROM_INT( (*state)->new_program, *parent_identifier); } return result; } static int find_depth(struct program_state *state, struct inherit *i, int parent_identifier, int depth) { #if 0 int e; struct inherit *oi; for(e=0;e<=parent_offset;e++) state=state->previous; oi=INHERIT_FROM_INT(state->new_program, parent_identifier); parent_offset+=i->parent_offset; #endif return locate_parent_state(&state, &i, &parent_identifier, depth); }
88e9fb2003-08-03Martin Stjernholm #endif
342fef2000-08-23Fredrik Hübinette (Hubbe) 
a0c9f62013-06-15Henrik Grubbström (Grubba) void lower_inherit(struct program *p, struct object *parent, int parent_identifier, int parent_offset, INT32 flags, struct pike_string *name)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
d3b06f2000-08-10Henrik Grubbström (Grubba)  int e; ptrdiff_t inherit_offset, storage_offset;
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct inherit inherit;
02a79a2000-09-04Fredrik Hübinette (Hubbe) #if 0
0f2b442001-12-14Martin Stjernholm  fprintf(stderr,"%p low_inherit(pid=%d, parent=%p, parid=%d, " "paroff=%d, flags=0x%x, name=%s);\n", Pike_compiler->new_program, p ? p->id : 0,
02a79a2000-09-04Fredrik Hübinette (Hubbe)  parent, parent_identifier, parent_offset, flags, name? name->str : ""); #endif
a359742001-12-16Martin Stjernholm  CDFPRINTF((stderr, "th(%ld) %p inherit %p\n", (long) th_self(), Pike_compiler->new_program, p));
02a79a2000-09-04Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(!p) { yyerror("Illegal program pointer."); return; }
5267b71995-08-09Fredrik Hübinette (Hubbe) 
d165152008-05-03Henrik Grubbström (Grubba)  if (Pike_compiler->compiler_pass == 2) { struct program *old_p = Pike_compiler->new_program->inherits[Pike_compiler->num_inherits+1].prog; Pike_compiler->num_inherits += old_p->num_inherits;
73a6852008-08-15Martin Stjernholm 
d165152008-05-03Henrik Grubbström (Grubba)  if (old_p != p) {
73a6852008-08-15Martin Stjernholm  yyerror("Got different program for inherit in second pass " "(resolver problem)."); } if (!(p->flags & PROGRAM_FINISHED)) { /* Require that the inherited program really is finished in pass * 2. Otherwise we might not have all definitions when we * fixate our program. * * FIXME: Maybe this can be relaxed by registering a dependency * and delaying compilation here? */ yyerror ("Cannot inherit program in pass 2 " "which is not fully compiled yet."); yyerror ("(You probably have a cyclic symbol dependency that the " "compiler cannot handle.)");
d165152008-05-03Henrik Grubbström (Grubba)  }
73a6852008-08-15Martin Stjernholm 
7c3fe02009-11-20Henrik Grubbström (Grubba)  if(p->flags & PROGRAM_NEEDS_PARENT) { struct program_state *state=Pike_compiler; if(!parent && !parent_offset) { yyerror("Parent pointer lost, cannot inherit!"); /* We've inherited it anyway, to avoid causing more errors */ } #if 0 /* FIXME: we don't really need to set this flag on ALL * previous compilations, but I'm too lazy to figure out * exactly how deep down we need to go... */ for(e=0;e<c->compilation_depth;e++,state=state->previous) state->new_program->flags |= PROGRAM_USES_PARENT; #endif }
73a6852008-08-15Martin Stjernholm  return; } if (!(p->flags & (PROGRAM_FINISHED | PROGRAM_PASS_1_DONE))) { yyerror ("Cannot inherit program in pass 1 " "which is only a placeholder."); yyerror ("(You probably have a cyclic symbol dependency that the " "compiler cannot handle.)");
d165152008-05-03Henrik Grubbström (Grubba)  return; }
bd537b2002-12-10Martin Stjernholm  if (p == placeholder_program) { yyerror("Trying to inherit placeholder program (resolver problem)."); return; }
0f2b442001-12-14Martin Stjernholm 
a947122014-06-16Henrik Grubbström (Grubba)  /* Propagate the HAS_C_METHODS and CLEAR_STORAGE flags. */ if (p->flags & (PROGRAM_HAS_C_METHODS|PROGRAM_CLEAR_STORAGE)) { Pike_compiler->new_program->flags |= (p->flags & (PROGRAM_HAS_C_METHODS|PROGRAM_CLEAR_STORAGE));
d8e7d82013-10-05Henrik Grubbström (Grubba)  }
342fef2000-08-23Fredrik Hübinette (Hubbe)  /* parent offset was increased by 42 for above test.. */
3139891999-09-06Henrik Grubbström (Grubba)  if(parent_offset)
342fef2000-08-23Fredrik Hübinette (Hubbe)  parent_offset-=42;
1994251999-09-06Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  inherit_offset = Pike_compiler->new_program->num_inherits;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
90e9781999-01-31Fredrik Hübinette (Hubbe)  /* alignment magic */
9386f71999-09-15Fredrik Hübinette (Hubbe)  storage_offset=p->inherits[0].storage_offset % p->alignment_needed;
1f5bfe1999-09-28Fredrik Hübinette (Hubbe)  storage_offset=low_add_storage(STORAGE_NEEDED(p),
90e9781999-01-31Fredrik Hübinette (Hubbe)  p->alignment_needed,
b1c8031999-09-15Fredrik Hübinette (Hubbe)  storage_offset);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
1f5bfe1999-09-28Fredrik Hübinette (Hubbe)  /* Without this, the inherit becomes skewed */
27ae842000-02-07Per Hedbor  storage_offset-=p->inherits[0].storage_offset;
1f5bfe1999-09-28Fredrik Hübinette (Hubbe) 
5c8e891995-10-29Fredrik Hübinette (Hubbe)  for(e=0; e<(int)p->num_inherits; e++)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { inherit=p->inherits[e];
8c83371998-04-16Fredrik Hübinette (Hubbe)  add_ref(inherit.prog);
bad5162000-06-23Fredrik Hübinette (Hubbe)  inherit.identifier_level += Pike_compiler->new_program->num_identifier_references;
5267b71995-08-09Fredrik Hübinette (Hubbe)  inherit.storage_offset += storage_offset; inherit.inherit_level ++;
342fef2000-08-23Fredrik Hübinette (Hubbe) 
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(!e) {
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(parent)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  {
9e52381998-03-01Fredrik Hübinette (Hubbe)  if(parent->next == parent) {
f3c7152001-04-14Fredrik Hübinette (Hubbe) #if 0
9e52381998-03-01Fredrik Hübinette (Hubbe)  struct object *o;
342fef2000-08-23Fredrik Hübinette (Hubbe)  inherit.parent_offset=0; for(o=Pike_compiler->fake_object;o!=parent;o=o->parent)
9e52381998-03-01Fredrik Hübinette (Hubbe)  {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5aad932002-08-15Marcus Comstedt  if(!o) Pike_fatal("low_inherit with odd Pike_compiler->fake_object as parent!\n");
9e52381998-03-01Fredrik Hübinette (Hubbe) #endif inherit.parent_offset++; }
f3c7152001-04-14Fredrik Hübinette (Hubbe) #else struct program_state *state=Pike_compiler; inherit.parent_offset=0; for(;state->fake_object!=parent;state=state->previous) { #ifdef PIKE_DEBUG if(!state->fake_object)
5aad932002-08-15Marcus Comstedt  Pike_fatal("low_inherit with odd Pike_compiler->fake_object as parent!\n");
f3c7152001-04-14Fredrik Hübinette (Hubbe) #endif inherit.parent_offset++; } #endif
9e52381998-03-01Fredrik Hübinette (Hubbe)  }else{ inherit.parent=parent; inherit.parent_identifier=parent_identifier;
684bd22003-08-02Martin Stjernholm  inherit.parent_offset=INHERIT_PARENT;
9e52381998-03-01Fredrik Hübinette (Hubbe)  }
61e9a01998-01-25Fredrik Hübinette (Hubbe)  }else{
342fef2000-08-23Fredrik Hübinette (Hubbe)  inherit.parent_offset=parent_offset;
bcd5741999-03-17Fredrik Hübinette (Hubbe)  inherit.parent_identifier=parent_identifier;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
1994981998-04-07Fredrik Hübinette (Hubbe)  }else{
5f05c11999-12-27Fredrik Hübinette (Hubbe)  if(!inherit.parent)
1994981998-04-07Fredrik Hübinette (Hubbe)  {
5f05c11999-12-27Fredrik Hübinette (Hubbe)  if(parent && parent->next != parent && inherit.parent_offset)
1994981998-04-07Fredrik Hübinette (Hubbe)  {
5f05c11999-12-27Fredrik Hübinette (Hubbe)  struct object *par=parent; int e,pid=parent_identifier;
342fef2000-08-23Fredrik Hübinette (Hubbe) 
5f05c11999-12-27Fredrik Hübinette (Hubbe)  for(e=1;e<inherit.parent_offset;e++)
1994981998-04-07Fredrik Hübinette (Hubbe)  {
5f05c11999-12-27Fredrik Hübinette (Hubbe)  struct inherit *in;
baed542008-01-13Henrik Grubbström (Grubba)  if(!par || !par->prog)
5f05c11999-12-27Fredrik Hübinette (Hubbe)  {
baed542008-01-13Henrik Grubbström (Grubba)  par = NULL; pid = -1;
5f05c11999-12-27Fredrik Hübinette (Hubbe)  break; }
27ae842000-02-07Per Hedbor 
5f05c11999-12-27Fredrik Hübinette (Hubbe)  in=INHERIT_FROM_INT(par->prog, pid);
342fef2000-08-23Fredrik Hübinette (Hubbe)  switch(in->parent_offset)
5f05c11999-12-27Fredrik Hübinette (Hubbe)  {
342fef2000-08-23Fredrik Hübinette (Hubbe)  default: { struct external_variable_context tmp; struct inherit *in2=in;
684bd22003-08-02Martin Stjernholm  while(in2->inherit_level >= in->inherit_level) in2--;
342fef2000-08-23Fredrik Hübinette (Hubbe)  tmp.o=par; tmp.inherit=in2; tmp.parent_identifier=pid; find_external_context(&tmp, in->parent_offset);
5222e92000-08-24Henrik Grubbström (Grubba)  par = tmp.o; pid = tmp.parent_identifier;
342fef2000-08-23Fredrik Hübinette (Hubbe)  } break;
684bd22003-08-02Martin Stjernholm  case INHERIT_PARENT:
5222e92000-08-24Henrik Grubbström (Grubba)  pid = in->parent_identifier; par = in->parent;
342fef2000-08-23Fredrik Hübinette (Hubbe)  break;
684bd22003-08-02Martin Stjernholm  case OBJECT_PARENT:
4d51e02002-06-10Martin Stjernholm  /* Ponder: Can we be sure that PROGRAM_USES_PARENT * doesn't get set later? /mast */
f3c7152001-04-14Fredrik Hübinette (Hubbe)  if(par->prog->flags & PROGRAM_USES_PARENT) { pid = PARENT_INFO(par)->parent_identifier; par = PARENT_INFO(par)->parent; }else{
baed542008-01-13Henrik Grubbström (Grubba)  pid = -1; par = NULL;
f3c7152001-04-14Fredrik Hübinette (Hubbe)  }
5f05c11999-12-27Fredrik Hübinette (Hubbe)  }
1994981998-04-07Fredrik Hübinette (Hubbe)  }
27ae842000-02-07Per Hedbor 
5f05c11999-12-27Fredrik Hübinette (Hubbe)  inherit.parent=par;
684bd22003-08-02Martin Stjernholm  inherit.parent_offset=INHERIT_PARENT;
1994981998-04-07Fredrik Hübinette (Hubbe)  } }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
8c83371998-04-16Fredrik Hübinette (Hubbe)  if(inherit.parent) add_ref(inherit.parent);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
d2c6081996-11-07Fredrik Hübinette (Hubbe)  if(name) {
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  if(e==0) {
3c0c281998-01-26Fredrik Hübinette (Hubbe)  copy_shared_string(inherit.name,name);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  } else if(inherit.name) {
14e43c2013-11-10Henrik Grubbström (Grubba)  add_ref(inherit.name);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  } }else{ inherit.name=0;
d2c6081996-11-07Fredrik Hübinette (Hubbe)  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  add_to_inherits(inherit);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
2659cf2002-05-10Henrik Grubbström (Grubba)  /* This value is used by encode_value() to reverse the inherit operation. */ Pike_compiler->new_program->inherits[inherit_offset].identifier_ref_offset = Pike_compiler->new_program->num_identifier_references;
5c8e891995-10-29Fredrik Hübinette (Hubbe)  for (e=0; e < (int)p->num_identifier_references; e++)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { struct reference fun; fun = p->identifier_references[e]; /* Make a copy */ fun.inherit_offset += inherit_offset;
6bec2f2010-11-26Henrik Grubbström (Grubba)  fun.run_time_type = PIKE_T_UNKNOWN; /* Invalidate the vtable cache. */
ab0d472007-12-28Martin Nilsson  if (fun.id_flags & ID_FINAL)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
cd2be32004-03-13Henrik Grubbström (Grubba)  Pike_compiler->flags |= COMPILATION_CHECK_FINAL;
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
9f1f302001-09-27Per Hedbor 
29615e2014-10-18Henrik Grubbström (Grubba)  if (flags & ID_PUBLIC) fun.id_flags &= ~(ID_PRIVATE|ID_PUBLIC);
7fda7a1997-09-08Fredrik Hübinette (Hubbe)  if(fun.id_flags & ID_PRIVATE) fun.id_flags|=ID_HIDDEN;
5580691996-06-21Fredrik Hübinette (Hubbe) 
29615e2014-10-18Henrik Grubbström (Grubba)  fun.id_flags |= flags & ~ID_PUBLIC;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
7fda7a1997-09-08Fredrik Hübinette (Hubbe)  fun.id_flags |= ID_INHERITED;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  add_to_identifier_references(fun);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
fb7ff52013-04-27Henrik Grubbström (Grubba) }
29615e2014-10-18Henrik Grubbström (Grubba) /** * Make the program being compiled inherit another program. * * @param p * Program to inherit. * * @param parent * Object containing p (if applicable). * * @param parent_identifier * Identifier reference in parent->prog that is p. * * @param parent_offset * Lexical scope to parent from the program being compiled * offsetted by 42, or OBJECT_PARENT or INHERIT_PARENT. * * @param flags * Modifier flags for the inherit. * * @param name * Optional rename of the inherit.
fb7ff52013-04-27Henrik Grubbström (Grubba)  */ PMOD_EXPORT void low_inherit(struct program *p, struct object *parent, int parent_identifier, int parent_offset, INT32 flags, struct pike_string *name) { lower_inherit(p, parent, parent_identifier, parent_offset, flags, name);
acab7b2013-04-20Henrik Grubbström (Grubba) 
ec38642013-05-17Henrik Grubbström (Grubba)  /* Don't do this for OBJECT_PARENT or INHERIT_PARENT inherits. * They may show up here from decode_value(). */ if (parent_offset >= 42) {
acab7b2013-04-20Henrik Grubbström (Grubba)  if (p->flags & (PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT)) { /* We'll need the parent pointer as well... */ struct program_state *state = Pike_compiler;
fb7ff52013-04-27Henrik Grubbström (Grubba)  /* parent offset was increased by 42 by the caller... */ parent_offset -= 42; while (state && state->new_program && parent_offset--) {
acab7b2013-04-20Henrik Grubbström (Grubba)  state->new_program->flags |= PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; state = state->previous; } } }
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void do_inherit(struct svalue *s,
ae62c02012-10-27Henrik Grubbström (Grubba)  INT32 flags, struct pike_string *name)
61e9a01998-01-25Fredrik Hübinette (Hubbe) {
ae62c02012-10-27Henrik Grubbström (Grubba)  struct object *parent_obj = NULL; int parent_id = -1; struct program *p = low_program_from_svalue(s, &parent_obj, &parent_id); low_inherit(p, parent_obj, parent_id, 0, flags, name);
61e9a01998-01-25Fredrik Hübinette (Hubbe) } void compiler_do_inherit(node *n, INT32 flags, struct pike_string *name) {
086acc1999-09-11Fredrik Hübinette (Hubbe)  struct program *p; struct identifier *i;
5582a82000-08-28Fredrik Hübinette (Hubbe)  INT32 numid=-1, offset=0;
27ae842000-02-07Per Hedbor 
2416d81998-01-27Fredrik Hübinette (Hubbe)  if(!n) { yyerror("Unable to inherit"); return; }
a31a102003-08-21Henrik Grubbström (Grubba) 
38f9312014-05-03Henrik Grubbström (Grubba)  fix_type_field(n); if (!pike_types_le(n->type, inheritable_type_string) && (THIS_COMPILATION->lex.pragmas & ID_STRICT_TYPES)) { yytype_report(REPORT_WARNING, n->current_file, n->line_number, inheritable_type_string, n->current_file, n->line_number, n->type, 0, "Program required for inherit.\n"); }
61e9a01998-01-25Fredrik Hübinette (Hubbe)  switch(n->token) { case F_EXTERNAL: {
342fef2000-08-23Fredrik Hübinette (Hubbe)  struct program_state *state = Pike_compiler;
ff88db2000-07-12Henrik Grubbström (Grubba) 
5582a82000-08-28Fredrik Hübinette (Hubbe)  offset = 0;
ff88db2000-07-12Henrik Grubbström (Grubba)  while (state && (state->new_program->id != n->u.integer.a)) { state = state->previous; offset++; } if (!state) { yyerror("Failed to resolv external constant.\n"); return; } p = state->new_program; numid = n->u.integer.b;
6014a22014-02-05Henrik Grubbström (Grubba)  if ((name == this_program_string) && (offset == 1)) { /* Klugde: Default to renaming ::this_program * to the name of the current class. * * Otherwise the this_program:-scope * will become confusing, as it will * refer to the inherit and not the * current class. */ name = ID_FROM_INT(p, numid)->name; }
61e9a01998-01-25Fredrik Hübinette (Hubbe)  }
086acc1999-09-11Fredrik Hübinette (Hubbe)  continue_inherit:
64dd452007-09-29Henrik Grubbström (Grubba)  /* FIXME: Support external constants. */
88e9fb2003-08-03Martin Stjernholm  if(numid != IDREF_MAGIC_THIS &&
4247e92003-08-20Henrik Grubbström (Grubba)  (IDENTIFIER_IS_CONSTANT((i=ID_FROM_INT(p, numid))-> identifier_flags)) &&
89378b2010-11-23Henrik Grubbström (Grubba)  (i->func.const_info.offset != -1))
61e9a01998-01-25Fredrik Hübinette (Hubbe)  {
454d541999-09-18Fredrik Hübinette (Hubbe)  struct svalue *s=&PROG_FROM_INT(p, numid)->
89378b2010-11-23Henrik Grubbström (Grubba)  constants[i->func.const_info.offset].sval;
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_PROGRAM)
61e9a01998-01-25Fredrik Hübinette (Hubbe)  {
2416d81998-01-27Fredrik Hübinette (Hubbe)  do_inherit(s,flags,name);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  return; }else{
684bd22003-08-02Martin Stjernholm  low_inherit(s->u.program, 0, numid, offset+42, flags, name);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  } }else{ yyerror("Inherit identifier is not a constant program"); return; } break; default:
086acc1999-09-11Fredrik Hübinette (Hubbe)  resolv_class(n);
cd86322000-07-06Fredrik Hübinette (Hubbe)  do_inherit(Pike_sp-1, flags, name);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  pop_stack(); } }
27ae842000-02-07Per Hedbor 
9036e82001-08-16Martin Stjernholm int call_handle_inherit(struct pike_string *s)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
e021fe2008-04-14Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
9036e82001-08-16Martin Stjernholm 
e021fe2008-04-14Henrik Grubbström (Grubba)  CHECK_COMPILER();
1f91c02008-05-02Henrik Grubbström (Grubba)  ref_push_string(s);
3a30d72014-10-05Martin Nilsson  f_string_to_utf8(1);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
1f91c02008-05-02Henrik Grubbström (Grubba)  if (safe_apply_current2(PC_HANDLE_INHERIT_FUN_NUM, 1, NULL))
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-1]) != T_INT)
9036e82001-08-16Martin Stjernholm  return 1; else {
ce060e2004-06-30Martin Nilsson  my_yyerror("Couldn't find program %S", s);
9036e82001-08-16Martin Stjernholm  } else {
4bb5d02003-11-14Martin Stjernholm  handle_compile_exception ("Error finding program");
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
6e22f02008-08-06Henrik Grubbström (Grubba)  pop_stack();
5267b71995-08-09Fredrik Hübinette (Hubbe) 
9036e82001-08-16Martin Stjernholm  return 0; } void simple_do_inherit(struct pike_string *s, INT32 flags, struct pike_string *name) { if (!call_handle_inherit(s)) return;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(name) { free_string(s); s=name; }
cd86322000-07-06Fredrik Hübinette (Hubbe)  do_inherit(Pike_sp-1, flags, s);
d2c6081996-11-07Fredrik Hübinette (Hubbe)  free_string(s);
5267b71995-08-09Fredrik Hübinette (Hubbe)  pop_stack(); }
29615e2014-10-18Henrik Grubbström (Grubba) /** * Find an identifier relative to the program being compiled. * * @return Return the index of the identifier found, otherwise -1.
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
06983f1996-09-22Fredrik Hübinette (Hubbe) int isidentifier(struct pike_string *s)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
ecd5bf2002-04-07Henrik Grubbström (Grubba)  return really_low_find_shared_string_identifier(s, Pike_compiler->new_program,
6530932008-06-29Martin Nilsson  SEE_PROTECTED|SEE_PRIVATE);
5267b71995-08-09Fredrik Hübinette (Hubbe) }
6f96692009-09-12Henrik Grubbström (Grubba) /* * Definition of identifiers. * * Pike has three plus one classes of identifiers: * * IDENTIFIER_VARIABLE - A value stored in object->storage * IDENTIFIER_CONSTANT - A value stored in program->constants * IDENTIFIER_FUNCTION - Either a C function or a Pike function * and * IDENTIFIER_ALIAS - An alias for a different identifier. * */
29615e2014-10-18Henrik Grubbström (Grubba) /** * Define an alias for a (possibly extern) identifier.
64dd452007-09-29Henrik Grubbström (Grubba)  * * Note that both type and name may be NULL. If they are NULL * they will be defaulted to the values from the aliased identifier. */ int low_define_alias(struct pike_string *name, struct pike_type *type, int flags, int depth, int refno) { int n; int e;
0ed9122008-05-16Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
64dd452007-09-29Henrik Grubbström (Grubba)  struct program_state *state = Pike_compiler; struct identifier dummy, *id; struct reference ref; #ifdef PIKE_DEBUG if(Pike_compiler->new_program->flags & (PROGRAM_FIXED | PROGRAM_OPTIMIZED)) Pike_fatal("Attempting to add variable to fixed program\n"); if(Pike_compiler->compiler_pass==2) Pike_fatal("Internal error: Not allowed to add more identifiers during second compiler pass.\n" "Added identifier: \"%s\"\n", name->str); #endif
c4191b2015-05-03Henrik Grubbström (Grubba)  for(e = 0; DO_IF_DEBUG_ELSE(state, 1) && (e < depth); e++) {
64dd452007-09-29Henrik Grubbström (Grubba)  state = state->previous; } #ifdef PIKE_DEBUG if (!state) { Pike_fatal("Internal error: External symbol buried too deep.\n"); } if (state->new_program->num_identifier_references <= refno) { Pike_fatal("Internal error: Reference out of bounds: %d (max: %d).\n", refno, state->new_program->num_identifier_references); } #endif id = ID_FROM_INT(state->new_program, refno); if (name) { copy_shared_string(dummy.name, name); } else { copy_shared_string(dummy.name, id->name); } if (type) { copy_pike_type(dummy.type, type); } else { copy_pike_type(dummy.type, id->type); }
865d652008-05-16Henrik Grubbström (Grubba)  dummy.filename_strno = store_prog_string(c->lex.current_file);
0ed9122008-05-16Henrik Grubbström (Grubba)  dummy.linenumber = c->lex.current_line;
64dd452007-09-29Henrik Grubbström (Grubba)  dummy.identifier_flags = id->identifier_flags | IDENTIFIER_ALIAS; dummy.run_time_type = id->run_time_type; /* Not actually used. */ dummy.func.ext_ref.depth = depth; dummy.func.ext_ref.id = refno;
670ba32008-01-13Henrik Grubbström (Grubba)  dummy.opt_flags = 0;
64dd452007-09-29Henrik Grubbström (Grubba) #ifdef PROFILING dummy.self_time=0; dummy.num_calls=0;
5ca7b52012-01-07Jonas Walldén  dummy.recur_depth=0;
64dd452007-09-29Henrik Grubbström (Grubba)  dummy.total_time=0; #endif
23a14a2008-07-14Henrik Grubbström (Grubba)  if (flags & ID_PRIVATE) flags |= ID_INLINE;
64dd452007-09-29Henrik Grubbström (Grubba)  ref.id_flags=flags; ref.identifier_offset=Pike_compiler->new_program->num_identifiers; ref.inherit_offset=0;
77fbd72010-11-25Henrik Grubbström (Grubba)  ref.run_time_type = PIKE_T_UNKNOWN;
64dd452007-09-29Henrik Grubbström (Grubba)  debug_add_to_identifiers(dummy); n = Pike_compiler->new_program->num_identifier_references; add_to_identifier_references(ref); return n; } PMOD_EXPORT int define_alias(struct pike_string *name, struct pike_type *type, int flags, int depth, int refno) { /* FIXME: Support NULL name and type. */ int n = isidentifier(name); if(Pike_compiler->new_program->flags & PROGRAM_PASS_1_DONE) { if(n==-1) yyerror("Pass2: Alias disappeared!"); else { struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, n); if (!IDENTIFIER_IS_ALIAS(id->identifier_flags)) { if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) { /* Convert a placeholder constant into an alias. */ struct program_state *state = Pike_compiler; int e; for(e = 0; state && (e < depth); e++) { state = state->previous; } #ifdef PIKE_DEBUG if (!state) { Pike_fatal("Internal error: External symbol buried too deep.\n"); } if (state->new_program->num_identifier_references <= refno) { Pike_fatal("Internal error: Reference out of bounds: %d (max: %d).\n", refno, state->new_program->num_identifier_references); } #endif id->identifier_flags = IDENTIFIER_ALIAS | ID_FROM_INT(state->new_program, refno)->identifier_flags; } else { Pike_fatal("Replacing non alias with an alias in second pass!\n"); } } free_type(id->type); copy_pike_type(id->type, type); id->func.ext_ref.depth = depth; id->func.ext_ref.id = refno; return n; } } #ifdef PIKE_DEBUG if(Pike_compiler->new_program->flags & (PROGRAM_FIXED | PROGRAM_OPTIMIZED)) Pike_fatal("Attempting to add variable to fixed program\n"); #endif if(n != -1) { /* not inherited */ if(Pike_compiler->new_program->identifier_references[n].inherit_offset == 0) { if (!((IDENTIFIERP(n)->id_flags | flags) & ID_EXTERN)) { my_yyerror("Identifier %S defined twice.",name); return n; } if (flags & ID_EXTERN) { /* FIXME: Check type */ return n; } } if (!(IDENTIFIERP(n)->id_flags & ID_EXTERN)) {
ab0d472007-12-28Martin Nilsson  if (IDENTIFIERP(n)->id_flags & ID_FINAL) my_yyerror("Illegal to redefine 'final' "
64dd452007-09-29Henrik Grubbström (Grubba)  "variable/functions %S", name); /* FIXME: More. */ } } return low_define_alias(name, type, flags, depth, refno); }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) /* argument must be a shared string */
d4828c1997-07-17Fredrik Hübinette (Hubbe) int low_define_variable(struct pike_string *name,
d68a072001-02-20Henrik Grubbström (Grubba)  struct pike_type *type,
d4828c1997-07-17Fredrik Hübinette (Hubbe)  INT32 flags,
de1d7d2000-07-10Henrik Grubbström (Grubba)  size_t offset,
d4828c1997-07-17Fredrik Hübinette (Hubbe)  INT32 run_time_type) { int n;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
0ed9122008-05-16Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
d4828c1997-07-17Fredrik Hübinette (Hubbe)  struct identifier dummy; struct reference ref;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->new_program->flags & (PROGRAM_FIXED | PROGRAM_OPTIMIZED))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Attempting to add variable to fixed program\n");
22edc21998-01-29Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->compiler_pass==2)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Internal error: Not allowed to add more identifiers during second compiler pass.\n"
05bfe21998-07-20Henrik Grubbström (Grubba)  "Added identifier: \"%s\"\n", name->str);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #endif
d4828c1997-07-17Fredrik Hübinette (Hubbe)  copy_shared_string(dummy.name, name);
be6fec2001-04-01Henrik Grubbström (Grubba)  copy_pike_type(dummy.type, type);
865d652008-05-16Henrik Grubbström (Grubba)  dummy.filename_strno = store_prog_string(c->lex.current_file);
0ed9122008-05-16Henrik Grubbström (Grubba)  dummy.linenumber = c->lex.current_line;
64dd452007-09-29Henrik Grubbström (Grubba)  dummy.identifier_flags = IDENTIFIER_VARIABLE;
d4828c1997-07-17Fredrik Hübinette (Hubbe)  dummy.run_time_type=run_time_type;
bad5162000-06-23Fredrik Hübinette (Hubbe)  dummy.func.offset=offset - Pike_compiler->new_program->inherits[0].storage_offset;
670ba32008-01-13Henrik Grubbström (Grubba)  dummy.opt_flags = 0;
be478c1997-08-30Henrik Grubbström (Grubba) #ifdef PROFILING
6189631998-11-12Fredrik Hübinette (Hubbe)  dummy.self_time=0;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  dummy.num_calls=0;
5ca7b52012-01-07Jonas Walldén  dummy.recur_depth=0;
a2a8801998-03-18Per Hedbor  dummy.total_time=0;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #endif
be478c1997-08-30Henrik Grubbström (Grubba) 
2e1a6a2008-05-29Henrik Grubbström (Grubba)  if (run_time_type == PIKE_T_FREE) dummy.func.offset = -1;
89d9762013-02-03Henrik Grubbström (Grubba)  if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;
23a14a2008-07-14Henrik Grubbström (Grubba) 
7fda7a1997-09-08Fredrik Hübinette (Hubbe)  ref.id_flags=flags;
bad5162000-06-23Fredrik Hübinette (Hubbe)  ref.identifier_offset=Pike_compiler->new_program->num_identifiers;
d4828c1997-07-17Fredrik Hübinette (Hubbe)  ref.inherit_offset=0;
77fbd72010-11-25Henrik Grubbström (Grubba)  ref.run_time_type = PIKE_T_UNKNOWN;
05590d1998-04-23Fredrik Hübinette (Hubbe)  add_to_variable_index(ref.identifier_offset);
27ae842000-02-07Per Hedbor 
5ec1062002-05-09Martin Stjernholm  debug_add_to_identifiers(dummy);
27ae842000-02-07Per Hedbor 
bad5162000-06-23Fredrik Hübinette (Hubbe)  n=Pike_compiler->new_program->num_identifier_references;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  add_to_identifier_references(ref);
05590d1998-04-23Fredrik Hübinette (Hubbe) 
d4828c1997-07-17Fredrik Hübinette (Hubbe)  return n; }
6f96692009-09-12Henrik Grubbström (Grubba) /* type is a textual type */
0929a02002-09-12Marcus Comstedt PMOD_EXPORT int map_variable(const char *name, const char *type,
d4828c1997-07-17Fredrik Hübinette (Hubbe)  INT32 flags,
de1d7d2000-07-10Henrik Grubbström (Grubba)  size_t offset,
d4828c1997-07-17Fredrik Hübinette (Hubbe)  INT32 run_time_type) { int ret;
d68a072001-02-20Henrik Grubbström (Grubba)  struct pike_string *n; struct pike_type *t;
a786431999-11-18Martin Stjernholm  #ifdef PROGRAM_BUILD_DEBUG
8853882008-04-26Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
a786431999-11-18Martin Stjernholm  fprintf (stderr, "%.*sdefining variable (pass=%d): %s %s\n",
8853882008-04-26Henrik Grubbström (Grubba)  c->compilation_depth, "", Pike_compiler->compiler_pass, type, name);
a786431999-11-18Martin Stjernholm #endif
d4828c1997-07-17Fredrik Hübinette (Hubbe)  n=make_shared_string(name); t=parse_type(type);
1f7f172007-10-11Henrik Grubbström (Grubba)  ret=low_define_variable(n,t,flags|ID_USED,offset,run_time_type);
d4828c1997-07-17Fredrik Hübinette (Hubbe)  free_string(n);
d68a072001-02-20Henrik Grubbström (Grubba)  free_type(t);
d4828c1997-07-17Fredrik Hübinette (Hubbe)  return ret; }
6f96692009-09-12Henrik Grubbström (Grubba) /* type is a serialized tokenized type. */
0929a02002-09-12Marcus Comstedt PMOD_EXPORT int quick_map_variable(const char *name,
e2d9e62000-06-10Martin Stjernholm  int name_length,
de1d7d2000-07-10Henrik Grubbström (Grubba)  size_t offset,
0929a02002-09-12Marcus Comstedt  const char *type,
74dfe82012-12-30Jonas Walldén  int UNUSED(type_length),
e2d9e62000-06-10Martin Stjernholm  INT32 run_time_type, INT32 flags) { int ret;
d68a072001-02-20Henrik Grubbström (Grubba)  struct pike_string *n; struct pike_type *t;
e2d9e62000-06-10Martin Stjernholm 
8a2a522001-03-03Henrik Grubbström (Grubba)  n = make_shared_binary_string(name, name_length); t = make_pike_type(type);
aed5202002-05-01Martin Stjernholm  #ifdef PROGRAM_BUILD_DEBUG {
8853882008-04-26Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
f34f642002-05-05Martin Stjernholm  struct pike_string *d = describe_type (t); fprintf (stderr, "%.*sdefining variable (pass=%d): %s ",
8853882008-04-26Henrik Grubbström (Grubba)  c->compilation_depth, "", Pike_compiler->compiler_pass, d->str);
f34f642002-05-05Martin Stjernholm  free_string (d);
aed5202002-05-01Martin Stjernholm  push_string (n); print_svalue (stderr, --Pike_sp); putc ('\n', stderr); } #endif
1f7f172007-10-11Henrik Grubbström (Grubba)  ret=low_define_variable(n,t,flags|ID_USED,offset,run_time_type);
e2d9e62000-06-10Martin Stjernholm  free_string(n);
d68a072001-02-20Henrik Grubbström (Grubba)  free_type(t);
e2d9e62000-06-10Martin Stjernholm  return ret; }
5267b71995-08-09Fredrik Hübinette (Hubbe) /* argument must be a shared string */
06983f1996-09-22Fredrik Hübinette (Hubbe) int define_variable(struct pike_string *name,
d68a072001-02-20Henrik Grubbström (Grubba)  struct pike_type *type,
5267b71995-08-09Fredrik Hübinette (Hubbe)  INT32 flags) {
61e9a01998-01-25Fredrik Hübinette (Hubbe)  int n, run_time_type;
b967972014-08-07Per Hedbor  int no_this = 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(name!=debug_findstring(name))
5aad932002-08-15Marcus Comstedt  Pike_fatal("define_variable on nonshared string.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
a786431999-11-18Martin Stjernholm #ifdef PROGRAM_BUILD_DEBUG {
8853882008-04-26Henrik Grubbström (Grubba)  struct compilation *c = THIS_COMPILATION;
f34f642002-05-05Martin Stjernholm  struct pike_string *d = describe_type (type); fprintf (stderr, "%.*sdefining variable (pass=%d): %s ",
8853882008-04-26Henrik Grubbström (Grubba)  c->compilation_depth, "", Pike_compiler->compiler_pass, d->str);
f34f642002-05-05Martin Stjernholm  free_string (d);
a786431999-11-18Martin Stjernholm  push_string (name);
cd86322000-07-06Fredrik Hübinette (Hubbe)  print_svalue (stderr, --Pike_sp);
a786431999-11-18Martin Stjernholm  putc ('\n', stderr); } #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(type == void_type_string)
94d66b2008-05-24Henrik Grubbström (Grubba)  yyerror("Variables can't be of type void.");
27ae842000-02-07Per Hedbor 
5267b71995-08-09Fredrik Hübinette (Hubbe)  n = isidentifier(name);
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->new_program->flags & PROGRAM_PASS_1_DONE)
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  { if(n==-1) yyerror("Pass2: Variable disappeared!");
a786431999-11-18Martin Stjernholm  else {
eff2b02001-07-03Henrik Grubbström (Grubba)  struct identifier *id=ID_FROM_INT(Pike_compiler->new_program,n);
d68a072001-02-20Henrik Grubbström (Grubba)  free_type(id->type);
be6fec2001-04-01Henrik Grubbström (Grubba)  copy_pike_type(id->type, type);
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  return n;
a786431999-11-18Martin Stjernholm  }
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  }
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->new_program->flags & (PROGRAM_FIXED | PROGRAM_OPTIMIZED))
5aad932002-08-15Marcus Comstedt  Pike_fatal("Attempting to add variable to fixed program\n");
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(n != -1) {
1994251999-09-06Fredrik Hübinette (Hubbe)  /* not inherited */
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(Pike_compiler->new_program->identifier_references[n].inherit_offset == 0)
1994251999-09-06Fredrik Hübinette (Hubbe)  {
e774391999-12-31Henrik Grubbström (Grubba)  if (!((IDENTIFIERP(n)->id_flags | flags) & ID_EXTERN)) {
ce060e2004-06-30Martin Nilsson  my_yyerror("Identifier %S defined twice.",name);
e774391999-12-31Henrik Grubbström (Grubba)  return n; } if (flags & ID_EXTERN) { /* FIXME: Check type */ return n; }
1994251999-09-06Fredrik Hübinette (Hubbe)  }
e774391999-12-31Henrik Grubbström (Grubba)  if (!(IDENTIFIERP(n)->id_flags & ID_EXTERN)) {
ab0d472007-12-28Martin Nilsson  if (IDENTIFIERP(n)->id_flags & ID_FINAL) my_yyerror("Illegal to redefine 'final' "
ce060e2004-06-30Martin Nilsson  "variable/functions %S", name);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
ce060e2004-06-30Martin Nilsson  if(!(IDENTIFIERP(n)->id_flags & ID_INLINE) || Pike_compiler->compiler_pass!=1)
8aae6d1999-08-19Fredrik Hübinette (Hubbe)  {
eff2b02001-07-03Henrik Grubbström (Grubba)  int n2; if(ID_FROM_INT(Pike_compiler->new_program, n)->type != type && !pike_types_le(type, ID_FROM_INT(Pike_compiler->new_program, n)->type)) {
94d66b2008-05-24Henrik Grubbström (Grubba)  int level = REPORT_WARNING;
eff2b02001-07-03Henrik Grubbström (Grubba)  if (!match_types(ID_FROM_INT(Pike_compiler->new_program, n)->type, type)) {
94d66b2008-05-24Henrik Grubbström (Grubba)  level = REPORT_ERROR;
eff2b02001-07-03Henrik Grubbström (Grubba)  }
94d66b2008-05-24Henrik Grubbström (Grubba)  yytype_report(level, NULL, 0, ID_FROM_INT(Pike_compiler->new_program, n)->type, NULL, 0, type, 0, "Illegal to redefine inherited variable %S " "with different type.", name);
eff2b02001-07-03Henrik Grubbström (Grubba)  }
9eaa6e2000-02-12Fredrik Hübinette (Hubbe) 
8aae6d1999-08-19Fredrik Hübinette (Hubbe) 
bad5162000-06-23Fredrik Hübinette (Hubbe)  if(!IDENTIFIER_IS_VARIABLE(ID_FROM_INT(Pike_compiler->new_program, n)->
e774391999-12-31Henrik Grubbström (Grubba)  identifier_flags)) {
3dfd262008-05-14Henrik