pike.git/src/program.c:19:
#include "interpret.h"
#include "main.h"
#include "pike_memory.h"
#include "gc.h"
#include "threads.h"
#include "constants.h"
#include "operators.h"
#include "builtin_functions.h"
#include "mapping.h"
#include "cyclic.h"
- #include "pike_types.h"
+
#include "opcodes.h"
#include "version.h"
#include "block_allocator.h"
#include "block_alloc.h"
#include "pikecode.h"
#include "pike_compiler.h"
#include "module_support.h"
#include "bitvector.h"
#include "sprintf.h"
#include <errno.h>
#include <fcntl.h>
- #define sp Pike_sp
-
-
+
static void exit_program_struct(struct program *);
static size_t add_xstorage(size_t size,
size_t alignment,
ptrdiff_t modulo_orig);
/* mapping(int:string) */
static struct mapping *reverse_symbol_table = NULL;
static struct block_allocator program_allocator = BA_INIT_PAGES(sizeof(struct program), 4);
pike.git/src/program.c:118:
#include "compilation.h"
struct pike_string *this_program_string, *this_string, *args_string;
static struct pike_string *this_function_string;
static struct pike_string *UNDEFINED_string;
/* Common compiler subsystems */
struct pike_string *parser_system_string;
struct pike_string *type_check_system_string;
+ struct pike_string *compat_lfun_destroy_string;
+
/* 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.
*/
const char *const lfun_names[] = {
"__INIT",
"create",
- "destroy",
+ "_destruct",
"`+",
"`-",
"`&",
"`|",
"`^",
"`<<",
"`>>",
"`*",
"`/",
"`%",
pike.git/src/program.c:192:
struct pike_string *lfun_strings[NELEM(lfun_names)];
static struct mapping *lfun_ids;
/* mapping(string:type) */
static struct mapping *lfun_types;
static const char *const raw_lfun_types[] = {
tFuncV(tNone,tVoid,tVoid), /* "__INIT", */
tFuncV(tNone,tZero,tVoid), /* "create", */
- tFuncV(tOr(tVoid,tInt),tVoid,tVoid), /* "destroy", */
+ tFuncV(tOr(tVoid,tInt),tVoid,tVoid), /* "_destruct", */
tFuncV(tZero,tZero,tMix), /* "`+", */
tFunc(tOr(tVoid,tZero),tMix), /* "`-", */
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), /* "`%", */
pike.git/src/program.c:240:
tFuncV(tInt tOr(tMap(tStr,tInt),tVoid),tVoid,tStr), /* "_sprintf", */
tFuncV(tMix,tVoid,tInt), /* "_equal", */
tFuncV(tZero,tVoid,tMix), /* "_m_delete", */
tFuncV(tNone,tVoid,tObj), /* "_get_iterator", */
tFuncV(tZero tRangeBound tZero tRangeBound, tVoid, tMix), /* "`[..]" */
/* NOTE: After this point there are only fake lfuns. */
tFuncV(tZero tOr(tZero, tVoid), tZero, tMix), /* "_search", */
tFuncV(tNone,tVoid,tArray), /* "_types", */
tFuncV(tObj tZero, tVoid, tVoid), /* "_serialize", */
tFuncV(tObj tZero, tVoid, tVoid), /* "_deserialize", */
- tFuncV(tZero, tVoid, tInt), /* "_size_object", */
+ tFuncV(tNone, tVoid, tInt), /* "_size_object", */
tFuncV(tFunction tFunction, tVoid, tMix), /* "_random", */
tFuncV(tOr3(tInt,tFloat,tObj),tVoid,tOr3(tObj,tInt,tFloat)), /* "pow", */
tFuncV(tOr3(tInt,tFloat,tObj),tVoid,tOr3(tObj,tInt,tFloat)), /* "rpow", */
tFunc(tVoid,tMix),/* "_sqrt* */
};
/* These two are not true LFUNs! */
static struct pike_type *lfun_getter_type_string = NULL;
static struct pike_type *lfun_setter_type_string = NULL;
/*! @namespace lfun::
*!
*! 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()]
+ *! @[__INIT()], @[create()], @[_destruct()]
*!
*! @item
*! Unary operator overloading.
*!
*! @[`~()], @[`!()],
*! @[_values()], @[cast()],
*! @[_sizeof()], @[_indices()],
*! @[__hash()]
*!
*! @item
pike.git/src/program.c:354:
*!
*! @note
*! This function can be created implicitly
*! by the compiler using the syntax:
*! @code
*! class Foo(int foo) {
*! int bar;
*! }
*! @endcode
*! In the above case an implicit @[lfun::create()] is created, and
- *! it's equvivalent to:
+ *! it's equivalent to:
*! @code
*! class Foo {
*! int foo;
*! int bar;
*! protected void create(int foo)
*! {
*! this::foo = foo;
*! }
*! }
*! @endcode
*!
*! @seealso
- *! @[lfun::__INIT()], @[lfun::destroy()]
+ *! @[lfun::__INIT()], @[lfun::_destruct()]
*/
- /*! @decl void lfun::destroy (void|int reason)
+ /*! @decl void lfun::_destruct (void|int reason)
*!
*! Object destruction callback.
*!
*! 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
pike.git/src/program.c:399:
*! Destructed by the garbage collector.
*! @value Object.DESTRUCT_CLEANUP
*! 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.
*! @endint
*!
*! @note
*! Objects are normally not destructed when a process exits, so
- *! @expr{destroy@} functions aren't called then. Use @[atexit] to get
+ *! @expr{_destruct@} functions aren't called then. Use @[atexit] to get
*! called when the process exits.
*!
*! @note
*! 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@}
+ *! references. If there are other objects with @expr{_destruct@}
*! 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
+ *! If an object A contains an @[lfun::_destruct] 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
*! If a cycle is resolved according to the rule above by ignoring a
*! weaker reference, and there is another ambiguous cycle that
pike.git/src/program.c:452:
*! 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 {
- *! protected void destroy() {
+ *! protected void _destruct() {
*! if (!Super::this)
*! error ("My parent has been destructed!\n");
*! }
*! }
*! Sub sub = Sub();
- *! protected void destroy() {
+ *! protected void _destruct() {
*! 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
+ *! When the garbage collector calls @[lfun::_destruct], all accessible
+ *! non-objects and objects without @expr{_destruct@} functions are
+ *! still intact. They are not freed if the @expr{_destruct@} function
*! adds external references to them. However, all objects with
- *! @[lfun::destroy] in the cycle are already scheduled for
+ *! @[lfun::_destruct] in the cycle are already scheduled for
*! destruction and will therefore be destroyed even if external
*! references are added to them.
*!
*! @seealso
*! @[lfun::create()], @[predef::destruct()]
*/
/*! @decl mixed lfun::`+(zero arg, zero ... rest)
*!
*! Left side addition/concatenation callback.
pike.git/src/program.c:833:
*!
*! @seealso
*! @[predef::`>()]
*/
/*! @decl int lfun::__hash()
*!
*! Hashing callback.
*!
*! The main caller of this function is @[predef::hash_value()]
- *! or the low-level equvivalent, which get called by various
+ *! or the low-level equivalent, 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.
*!
*! @note
*! The function @[predef::hash] does not return hash values that
*! are compatible with this one.
pike.git/src/program.c:1658:
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) { \
+ DO_IF_DEBUG(if (state->compiler_pass != COMPILER_PASS_FIRST) { \
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)); \
pike.git/src/program.c:1724: Inside #if 0
Pike_compiler->new_program->identifiers[i].linenumber,
i);
}
}
add_to_identifiers (id);
}
#else
#define debug_add_to_identifiers(ARG) add_to_identifiers(ARG)
#endif
- static void add_identifier(struct compilation *c,
+ static int low_add_identifier(struct compilation *c,
struct pike_type *type,
struct pike_string *name,
unsigned int identifier_flags,
unsigned int opt_flags,
union idptr func,
int run_time_type)
{
struct identifier dummy;
-
+ int n = Pike_compiler->new_program->num_identifiers;
+
copy_shared_string(dummy.name, name);
copy_pike_type(dummy.type, type);
dummy.filename_strno = store_prog_string(c->lex.current_file);
dummy.linenumber = c->lex.current_line;
dummy.identifier_flags = identifier_flags;
dummy.run_time_type = run_time_type;
dummy.func = func;
dummy.opt_flags = opt_flags;
#ifdef PROFILING
dummy.self_time=0;
dummy.num_calls=0;
dummy.recur_depth=0;
dummy.total_time=0;
#endif
debug_add_to_identifiers(dummy);
-
+
+ return n;
}
-
+ static int add_identifier(struct compilation *c,
+ struct pike_type *type,
+ struct pike_string *name,
+ unsigned int modifier_flags,
+ unsigned int identifier_flags,
+ unsigned int opt_flags,
+ union idptr func,
+ int run_time_type)
+ {
+ struct reference ref;
+ struct identifier dummy;
+ int n;
+
+ if (modifier_flags & ID_PRIVATE) modifier_flags |= ID_LOCAL|ID_PROTECTED;
+
+ if (((identifier_flags & (IDENTIFIER_VARIABLE|IDENTIFIER_ALIAS)) ==
+ IDENTIFIER_VARIABLE) &&
+ (modifier_flags & ID_WEAK)) {
+ identifier_flags |= IDENTIFIER_WEAK;
+ }
+
+ ref.id_flags = modifier_flags;
+ ref.identifier_offset =
+ low_add_identifier(c, type, name,
+ identifier_flags, opt_flags,
+ func, run_time_type);
+ ref.inherit_offset = 0;
+ ref.run_time_type = PIKE_T_UNKNOWN;
+
+ if ((identifier_flags & (IDENTIFIER_VARIABLE|IDENTIFIER_ALIAS)) ==
+ IDENTIFIER_VARIABLE) {
+ add_to_variable_index(ref.identifier_offset);
+ }
+
+ n = Pike_compiler->new_program->num_identifier_references;
+ add_to_identifier_references(ref);
+
+ return n;
+ }
+
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);
}
void use_module(struct svalue *s)
{
struct compilation *c = THIS_COMPILATION;
if( (1<<TYPEOF(*s)) & (BIT_MAPPING | BIT_OBJECT | BIT_PROGRAM))
pike.git/src/program.c:1846:
{
push_svalue(m+e);
ref_push_string(ident);
f_index(2);
if(!IS_UNDEFINED(Pike_sp-1))
{
struct node_s *ret;
UNSETJMP(tmp);
- if (Pike_compiler->compiler_pass == 2 &&
+ if (Pike_compiler->compiler_pass == COMPILER_PASS_LAST &&
((TYPEOF(Pike_sp[-1]) == T_OBJECT &&
Pike_sp[-1].u.object == placeholder_object) ||
(TYPEOF(Pike_sp[-1]) == T_PROGRAM &&
Pike_sp[-1].u.program == placeholder_program))) {
my_yyerror("Got placeholder %s (resolver problem) "
"when indexing a module with %S.",
get_name_of_type (TYPEOF(Pike_sp[-1])), ident);
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);
- #if 0 && defined (COMPILER_DEBUG)
- safe_pike_fprintf (stderr, "Index %S: %O\n", ident, Pike_sp - 1);
- #endif
+
}
pop_stack();
return ret;
}
pop_stack();
}
}
UNSETJMP(tmp);
}
- #if 0 && defined (COMPILER_DEBUG)
- safe_pike_fprintf (stderr, "Index %S: undefined\n", ident);
- #endif
+
return 0;
}
struct node_s *resolve_identifier(struct pike_string *ident);
struct node_s *find_module_identifier(struct pike_string *ident,
int see_inherit)
{
struct compilation *c = THIS_COMPILATION;
pike.git/src/program.c:1905:
{
int i;
if(see_inherit)
{
i=really_low_find_shared_string_identifier(ident,
p->new_program,
SEE_PROTECTED|SEE_PRIVATE);
if(i!=-1)
{
if ((p->flags & COMPILATION_FORCE_RESOLVE) &&
- (p->compiler_pass == 2) &&
+ (p->compiler_pass == COMPILER_PASS_LAST) &&
((p->num_inherits + 1) < p->new_program->num_inherits) &&
(PTR_FROM_INT(p->new_program, i)->inherit_offset >
p->num_inherits)) {
/* Don't look up symbols inherited later, since we need to get
* the same symbol in both passes in the force_resolve mode.
*/
continue;
}
return p == Pike_compiler ?
mkidentifiernode(i) :
pike.git/src/program.c:1952:
add_ref(ret->name = ident);
free_node(tmp);
return ret;
}
/*! @decl constant UNDEFINED
*!
*! The undefined value; ie a zero for which @[zero_type()] returns 1.
*/
- struct node_s *resolve_identifier(struct pike_string *ident)
+ int low_resolve_identifier(struct pike_string *ident)
{
struct compilation *c = THIS_COMPILATION;
node *ret = NULL;
/* Handle UNDEFINED */
if (ident == UNDEFINED_string) {
- return mkconstantsvaluenode(&svalue_undefined);
+ push_undefined();
+ return 1;
}
if(c->resolve_cache)
{
struct svalue *tmp=low_mapping_string_lookup(c->resolve_cache,ident);
if(tmp)
{
- if(!IS_UNDEFINED (tmp))
- return mkconstantsvaluenode(tmp);
-
+ if(IS_UNDEFINED (tmp)) {
return 0;
}
-
+
+ push_svalue(tmp);
+ return 1;
}
-
+ }
CHECK_COMPILER();
ref_push_string(ident);
- ref_push_string(c->lex.current_file);
- if (c->handler) {
- ref_push_object(c->handler);
- } else {
- push_int(0);
- }
- if (!safe_apply_current2(PC_RESOLV_FUN_NUM, 3, NULL))
+ if (!safe_apply_current2(PC_RESOLV_FUN_NUM, 1, NULL))
handle_compile_exception ("Error resolving '%S'.", ident);
- if (Pike_compiler->compiler_pass != 2) {
+ if (Pike_compiler->compiler_pass != COMPILER_PASS_LAST) {
/* 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;
if (TYPEOF(Pike_sp[-1]) == T_PROGRAM)
p = Pike_sp[-1].u.program;
else if (TYPEOF(Pike_sp[-1]) == T_OBJECT ||
(TYPEOF(Pike_sp[-1]) == T_FUNCTION &&
SUBTYPEOF(Pike_sp[-1]) != FUNCTION_BUILTIN))
p = Pike_sp[-1].u.object->prog;
if (p && !(p->flags & PROGRAM_PASS_1_DONE))
report_compiler_dependency (p);
}
- if (Pike_compiler->compiler_pass == 2 &&
+ if (Pike_compiler->compiler_pass == COMPILER_PASS_LAST &&
((TYPEOF(Pike_sp[-1]) == T_OBJECT &&
Pike_sp[-1].u.object == placeholder_object) ||
(TYPEOF(Pike_sp[-1]) == T_PROGRAM &&
Pike_sp[-1].u.program == placeholder_program))) {
my_yyerror("Got placeholder %s (resolver problem) "
"when resolving '%S'.",
get_name_of_type (TYPEOF(Pike_sp[-1])), ident);
} else {
if(!c->resolve_cache)
c->resolve_cache=dmalloc_touch(struct mapping *, allocate_mapping(10));
mapping_string_insert(c->resolve_cache,ident,Pike_sp-1);
if(!IS_UNDEFINED (Pike_sp-1))
{
- ret=mkconstantsvaluenode(Pike_sp-1);
+ return 1;
}
}
pop_stack();
-
+ return 0;
+ }
+
+ struct node_s *resolve_identifier(struct pike_string *ident)
+ {
+ node *ret = NULL;
+
+ if (low_resolve_identifier(ident)) {
+ ret = mkconstantsvaluenode(Pike_sp-1);
+ pop_stack();
+ }
return ret;
}
/**
* This function is intended to simplify resolving of
* 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)) {
+ if (low_resolve_identifier(ident)) {
+ if ((ret = program_from_svalue(Pike_sp-1))) {
add_ref(ret);
- } else {
- my_yyerror("Invalid program identifier '%S'.", ident);
+
}
- free_node(n);
- } else {
- my_yyerror("Unknown program identifier '%S'.", ident);
+ pop_stack();
}
-
+ if (!ret) {
+ my_yyerror("Invalid program identifier '%S'.", ident);
+ }
return ret;
}
/**
* Find the identifier named ident in inherit #inh in the lexical scope
* given by inherit_state and inherit_depth.
*
* @param inherit_state
* The program state for the program where the inherit is found.
*
pike.git/src/program.c:2379:
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 ((id != -1) && (state->compiler_pass == COMPILER_PASS_LAST)) {
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) {
pike.git/src/program.c:2729:
#endif
#endif
sub_ref = PTR_FROM_INT(inh->prog, cur_id - inh->identifier_level);
/* Check if the symbol was used before it was inherited. */
if ((c->lex.pragmas & ID_STRICT_TYPES) &&
(sub_ref->id_flags & ID_USED)) {
struct identifier *sub_id = ID_FROM_PTR(inh->prog, sub_ref);
if (IDENTIFIER_IS_FUNCTION(sub_id->identifier_flags)) {
- if ((Pike_compiler->compiler_pass == 2) &&
+ if ((Pike_compiler->compiler_pass == COMPILER_PASS_LAST) &&
!pike_types_le(ID_FROM_PTR(Pike_compiler->new_program,
new_ref)->type, sub_id->type)) {
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);
}
} else {
pike.git/src/program.c:2944:
if (ref->id_flags & ID_HIDDEN) continue;
if (ref->id_flags & ID_VARIANT) continue;
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);
}
}
- /* Set the PROGRAM_LIVE_OBJ flag by looking for destroy() and
+ /* Set the PROGRAM_LIVE_OBJ flag by looking for _destruct() 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);
+ int e, destruct = p->lfuns[LFUN__DESTRUCT];
+ if (destruct > -1) {
+ struct identifier *id = ID_FROM_INT (p, destruct);
if (!IDENTIFIER_IS_PIKE_FUNCTION (id->identifier_flags) ||
id->func.offset != -1) {
- /* Got a destroy function that isn't a prototype. */
+ /* Got a _destruct 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;
}
pike.git/src/program.c:3063:
}
dmalloc_set_mmap_template(Pike_compiler->new_program, m);
}
#endif
}
struct program *low_allocate_program(void)
{
struct program *p=alloc_program();
memset(p, 0, sizeof(struct program));
+ gc_init_marker(p);
p->flags|=PROGRAM_VIRGIN;
p->alignment_needed=1;
GC_ALLOC(p);
p->id=++current_program_id;
INIT_PIKE_MEMOBJ(p, T_PROGRAM);
DOUBLELINK(first_program, p);
ACCURATE_GETTIMEOFDAY(& p->timestamp);
return p;
pike.git/src/program.c:3118: Inside #if 0
name->str, c->compilation_depth);
}else{
fprintf(stderr,"Compiling file %s, depth=%d\n",
c->lex.current_file ? c->lex.current_file->str : "-",
c->compilation_depth);
#endif
}
}else{
tmp.u.program=p;
add_ref(p);
- if((pass == 2) && name)
+ if((pass != COMPILER_PASS_FIRST) && name)
{
struct identifier *i;
id=isidentifier(name);
if (id < 0)
Pike_fatal("Program constant disappeared in second pass.\n");
i=ID_FROM_INT(Pike_compiler->new_program, id);
free_type(i->type);
i->type=get_type_of_svalue(&tmp);
}
}
- if (pass == 1) {
+ if (pass == COMPILER_PASS_FIRST) {
if(c->compilation_depth >= 1) {
add_ref(p->parent = Pike_compiler->new_program);
debug_malloc_touch (p);
}
}
p->flags &=~ PROGRAM_VIRGIN;
if(idp) *idp=id;
CDFPRINTF("th(%ld) %p low_start_new_program() %s "
"pass=%d: lock_depth:%d, compilation_depth:%d\n",
pike.git/src/program.c:3371:
c->lex.current_file = make_shared_string(f);
c->lex.current_line = line;
}
CDFPRINTF("th(%ld) start_new_program(%ld, %s): "
"lock_depth:%d, compilation_depth:%d\n",
(long)th_self(), (long)line, file,
lock_depth, c->compilation_depth);
- low_start_new_program(0,1,0,0,0);
+ low_start_new_program(0, COMPILER_PASS_FIRST, 0, 0, 0);
store_linenumber(line,c->lex.current_file);
debug_malloc_name(Pike_compiler->new_program, file, line);
free_string(c->lex.current_file);
c->lex.current_file = dmalloc_touch(struct pike_string *, save_file);
c->lex.current_line = save_line;
}
static void exit_program_struct(struct program *p)
pike.git/src/program.c:4211:
id = ID_FROM_INT(prog, j);
id_flags |= ref->id_flags;
opt_flags |= id->opt_flags;
/* NB: The dispatcher needs the variant references to
* not get overloaded for the ::-operator to work.
*/
ref->id_flags |= ID_LOCAL;
if (type)
{
struct pike_type * temp = type;
- if ((Pike_compiler->compiler_pass == 2) && !ref->inherit_offset &&
+ if ((Pike_compiler->compiler_pass == COMPILER_PASS_LAST) &&
+ !ref->inherit_offset &&
!check_variant_overload(id->type, type)) {
/* This symbol is shadowed by later variants. */
yytype_report(REPORT_WARNING,
NULL, 0, NULL,
Pike_compiler->new_program->strings[id->filename_strno],
id->linenumber, id->type,
0, "Function %S() masked by later variant.",
name);
ref_push_type_value(type);
low_yyreport(REPORT_WARNING,
pike.git/src/program.c:4277:
{
Pike_compiler->init_node=mknode(F_COMMA_EXPR,
mkcastnode(void_type_string,
mkapplynode(mkidentifiernode(id),0)),
Pike_compiler->init_node);
}
}
}
if (finish == 1) {
- if (Pike_compiler->compiler_pass == 1) {
+ if (Pike_compiler->compiler_pass == COMPILER_PASS_FIRST) {
/* 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.
*
* Also make sure that it is marked as having side effects,
* or it will be optimized away when inherited...
*/
define_function(init_name, function_type_string, ID_PROTECTED,
IDENTIFIER_PIKE_FUNCTION, NULL,
OPT_SIDE_EFFECT|OPT_EXTERNAL_DEPEND);
}
}
- Pike_compiler->compiler_pass = 2;
+ Pike_compiler->compiler_pass = COMPILER_PASS_LAST;
}
/*
* Define the __INIT function, but only if there was any code
* to initialize.
*/
if(Pike_compiler->init_node)
{
/* Inhibit this_function. */
pike.git/src/program.c:4403:
toss_compilation_resources();
#if 0
CDFPRINTF("th(%ld) end_first_pass(): "
"%p compilation_depth:%d, Pike_compiler->compiler_pass:%d\n",
(long)th_self(), prog,
c->compilation_depth, Pike_compiler->compiler_pass);
#endif
- if(!Pike_compiler->compiler_frame && (Pike_compiler->compiler_pass==2 || !prog) && c->resolve_cache)
+ if(!Pike_compiler->compiler_frame &&
+ (Pike_compiler->compiler_pass == COMPILER_PASS_LAST || !prog) &&
+ c->resolve_cache)
{
free_mapping(dmalloc_touch(struct mapping *, c->resolve_cache));
c->resolve_cache=0;
}
- #ifdef SHARED_NODES
- /* free(node_hash.table); */
- #endif /* SHARED_NODES */
-
+
#define POP
#include "compilation.h"
exit_type_stack();
CDFPRINTF("th(%ld) %p end_first_pass(%d): "
"lock_depth:%d, compilation_depth:%d\n",
(long)th_self(), prog, finish,
lock_depth, c->compilation_depth);
pike.git/src/program.c:4569:
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;
for(d=0;d<NUM_PROG_EVENTS;d++) {
/* FIXME: This looks like it might be broken. */
/* Broken how? -Hubbe */
- #ifdef HAVE_COMPUTED_GOTO
- add_to_program(Pike_compiler->new_program->event_handler);
- #else /* !HAVE_COMPUTED_GOTO */
+
for(e=0;e<sizeof(Pike_compiler->new_program->event_handler);e++)
add_to_program(tmp[e]);
- #endif /* HAVE_COMPUTED_GOTO */
+
}
Pike_compiler->new_program->event_handler=compat_event_handler;
}
}
/**
* Set a callback to be called when this program is cloned.
*
* This function is obsolete; see pike_set_prog_event_callback for
* details.
pike.git/src/program.c:4753:
{
struct program *np=(q?q:Pike_compiler)->new_program;
struct reference funp;
struct program *p;
int d, num_id_refs;
if(f==-1) return -1;
p = np->inherits[i].prog;
- if ((q?q:Pike_compiler)->compiler_pass == 2) {
+ if ((q?q:Pike_compiler)->compiler_pass == COMPILER_PASS_LAST) {
struct identifier *id = ID_FROM_INT(p, f);
if (((id->identifier_flags & IDENTIFIER_TYPE_MASK) ==
IDENTIFIER_PIKE_FUNCTION) && (id->func.offset == -1)) {
/* Prototype. */
return -1;
}
}
funp = p->identifier_references[f];
funp.inherit_offset += i;
pike.git/src/program.c:4826:
if(p->identifier_references[i].id_flags & ID_HIDDEN)
return -1;
if(p->identifier_references[i].id_flags & ID_PRIVATE)
if(!(flags & SEE_PRIVATE))
return -1;
return really_low_reference_inherited_identifier(q, e, i);
}
- int find_inherit(struct program *p, struct pike_string *name)
+ int find_inherit(const struct program *p, const struct pike_string *name)
{
int e;
int level = p->num_inherits; /* Larger than any inherit_level. */
int res = 0;
#if 0
fprintf(stderr, "find_inherit(0x%08lx, \"%s\")...\n",
(unsigned long)p, name->str);
#endif /* 0 */
pike.git/src/program.c:5003:
#endif
CDFPRINTF("th(%ld) %p inherit %p\n",
(long) th_self(), Pike_compiler->new_program, p);
if(!p)
{
yyerror("Illegal program pointer.");
return;
}
- if (Pike_compiler->compiler_pass == 2) {
+ if (Pike_compiler->compiler_pass == COMPILER_PASS_EXTRA) {
struct program *old_p =
- Pike_compiler->new_program->inherits[Pike_compiler->num_inherits+1].prog;
+ Pike_compiler->new_program->
+ inherits[Pike_compiler->num_inherits+1].prog;
Pike_compiler->num_inherits += old_p->num_inherits;
if (old_p != p) {
yyerror("Got different program for inherit in second pass "
"(resolver problem).");
}
-
+ return;
+ }
+ if (Pike_compiler->compiler_pass == COMPILER_PASS_LAST) {
+ struct program *old_p =
+ Pike_compiler->new_program->
+ inherits[Pike_compiler->num_inherits+1].prog;
+ Pike_compiler->num_inherits += old_p->num_inherits;
-
+ if (old_p != p) {
+ 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.");
pike.git/src/program.c:5064:
yyerror ("(You probably have a cyclic symbol dependency that the "
"compiler cannot handle.)");
return;
}
if (p == placeholder_program) {
yyerror("Trying to inherit placeholder program (resolver problem).");
return;
}
- /* Propagate the HAS_C_METHODS and CLEAR_STORAGE flags. */
- if (p->flags & (PROGRAM_HAS_C_METHODS|PROGRAM_CLEAR_STORAGE)) {
+ /* Propagate the HAS_C_METHODS, CLEAR_STORAGE and DESTRUCT_IMMEDIATE flags. */
+ if (p->flags & (PROGRAM_HAS_C_METHODS|PROGRAM_CLEAR_STORAGE|PROGRAM_DESTRUCT_IMMEDIATE)) {
Pike_compiler->new_program->flags |=
- (p->flags & (PROGRAM_HAS_C_METHODS|PROGRAM_CLEAR_STORAGE));
+ (p->flags & (PROGRAM_HAS_C_METHODS|PROGRAM_CLEAR_STORAGE|PROGRAM_DESTRUCT_IMMEDIATE));
}
/* parent offset was increased by 42 for above test.. */
if(parent_offset)
parent_offset-=42;
inherit_offset = Pike_compiler->new_program->num_inherits;
/* alignment magic */
storage_offset=p->inherits[0].storage_offset % p->alignment_needed;
pike.git/src/program.c:5289:
parent_offset -= 42;
while (state && state->new_program && parent_offset--) {
state->new_program->flags |= PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT;
state = state->previous;
}
}
}
}
+ /**
+ * Inherit a class from a lexically scoped identifier.
+ *
+ * @param scope_depth
+ * Scope at which the identifier is expected to be found.
+ *
+ * @param symbol
+ * Name of symbol to inherit from the specified scope.
+ *
+ * @param flags
+ * Modifier flags for the inherit.
+ *
+ * @param failure_severity_level
+ * Severity level to yyreport() failures to perform the inherit.
+ * Typically REPORT_ERROR, but eg REPORT_NOTICE and REPORT_WARNING
+ * are useful if the sybol is expected to sometimes be missing.
+ *
+ * @returns
+ * Returns NULL on failure and the inherited program on success.
+ */
+ PMOD_EXPORT struct program *lexical_inherit(int scope_depth,
+ struct pike_string *symbol,
+ INT32 flags,
+ int failure_severity_level)
+ {
+ struct program_state *state = Pike_compiler;
+ int e;
+ int class_fun_num;
+ struct program *prog;
+
+ for (e = 0; e < scope_depth; e++) {
+ state = state->previous;
+ if (!state) {
+ my_yyerror("Invalid lexical inherit of symbol %S at depth %d (max_depth: %d).",
+ symbol, scope_depth, e+1);
+ return NULL;
+ }
+ }
+
+ class_fun_num =
+ really_low_find_shared_string_identifier(symbol, state->new_program,
+ SEE_PROTECTED|SEE_PRIVATE);
+ if (class_fun_num < 0) {
+ yyreport(failure_severity_level, parser_system_string, 0,
+ "Symbol to inherit (%S) not found in parent scope #%d.",
+ symbol, scope_depth);
+ return NULL;
+ }
+
+ prog = low_program_from_function(state->fake_object, class_fun_num);
+ if (!prog) {
+ yyreport(failure_severity_level, parser_system_string, 0,
+ "Symbol %S in parent scope #%d is not a program.",
+ symbol, scope_depth);
+ return NULL;
+ }
+
+ if (scope_depth) {
+ /* Add a reference to the identifier. */
+ class_fun_num =
+ really_low_reference_inherited_identifier(state, 0, class_fun_num);
+ }
+ low_inherit(prog, 0, class_fun_num, 42 + scope_depth, flags, symbol);
+
+ return prog;
+ }
+
PMOD_EXPORT void do_inherit(struct svalue *s,
INT32 flags,
struct pike_string *name)
{
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);
}
pike.git/src/program.c:5416:
}
break;
default:
resolv_class(n);
do_inherit(Pike_sp-1, flags, name);
pop_stack();
}
}
+ void compiler_do_implement(node *n)
+ {
+ if (!n) {
+ yyerror("Invalid implement directive.");
+ return;
+ }
+ /* FIXME: Implement. */
+ }
+
int call_handle_inherit(struct pike_string *s)
{
struct compilation *c = THIS_COMPILATION;
CHECK_COMPILER();
ref_push_string(s);
f_string_to_utf8(1);
if (safe_apply_current2(PC_HANDLE_INHERIT_FUN_NUM, 1, NULL))
pike.git/src/program.c:5460:
do_inherit(Pike_sp-1, flags, s);
free_string(s);
pop_stack();
}
/**
* Find an identifier relative to the program being compiled.
*
* @return Return the index of the identifier found, otherwise -1.
*/
- int isidentifier(struct pike_string *s)
+ int isidentifier(const struct pike_string *s)
{
return really_low_find_shared_string_identifier(s,
Pike_compiler->new_program,
SEE_PROTECTED|SEE_PRIVATE);
}
/*
* Definition of identifiers.
*
* Pike has three plus one classes of identifiers:
pike.git/src/program.c:5496:
*/
int low_define_alias(struct pike_string *name, struct pike_type *type,
int flags, int depth, int refno)
{
int n;
int e;
struct compilation *c = THIS_COMPILATION;
struct program_state *state = Pike_compiler;
struct identifier *id;
- struct reference ref;
+
union idptr func;
#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)
+ if(Pike_compiler->compiler_pass == COMPILER_PASS_LAST)
Pike_fatal("Internal error: Not allowed to add more identifiers during second compiler pass.\n"
"Added identifier: \"%s\"\n", name->str);
#endif
for(e = 0; DO_IF_DEBUG_ELSE(state, 1) && (e < depth); e++) {
state = state->previous;
}
#ifdef PIKE_DEBUG
if (!state) {
pike.git/src/program.c:5529:
}
#endif
id = ID_FROM_INT(state->new_program, refno);
func.ext_ref.depth = depth;
func.ext_ref.id = refno;
if (flags & ID_PRIVATE) flags |= ID_INLINE;
- ref.id_flags=flags;
- ref.identifier_offset=Pike_compiler->new_program->num_identifiers;
- ref.inherit_offset=0;
- ref.run_time_type = PIKE_T_UNKNOWN;
-
- add_identifier(c, type ? type : id->type, name ? name : id->name,
- id->identifier_flags | IDENTIFIER_ALIAS, 0,
+ return add_identifier(c, type ? type : id->type, name ? name : id->name,
+ flags, id->identifier_flags | IDENTIFIER_ALIAS, 0,
func, id->run_time_type);
-
- 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)
{
pike.git/src/program.c:5630:
return low_define_alias(name, type, flags, depth, refno);
}
/* argument must be a shared string */
int low_define_variable(struct pike_string *name,
struct pike_type *type,
INT32 flags,
size_t offset,
INT32 run_time_type)
{
- int n;
-
+
struct compilation *c = THIS_COMPILATION;
- struct identifier dummy;
- struct reference ref;
+ unsigned int identifier_flags = IDENTIFIER_VARIABLE;
union idptr func;
#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)
+ if(Pike_compiler->compiler_pass == COMPILER_PASS_LAST)
Pike_fatal("Internal error: Not allowed to add more identifiers during second compiler pass.\n"
"Added identifier: \"%s\"\n", name->str);
#endif
func.offset = offset - Pike_compiler->new_program->inherits[0].storage_offset;
if (run_time_type == PIKE_T_FREE) func.offset = -1;
-
+ if (run_time_type & PIKE_T_NO_REF_FLAG) {
+ run_time_type &= ~PIKE_T_NO_REF_FLAG;
+ identifier_flags |= IDENTIFIER_NO_THIS_REF;
+ }
+
if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;
- ref.id_flags=flags;
- ref.identifier_offset=Pike_compiler->new_program->num_identifiers;
- ref.inherit_offset=0;
- ref.run_time_type = PIKE_T_UNKNOWN;
-
- add_to_variable_index(ref.identifier_offset);
-
- if (flags & ID_WEAK) {
+ return
add_identifier(c, type, name,
- IDENTIFIER_VARIABLE|IDENTIFIER_WEAK, 0,
+ flags, identifier_flags, 0,
func,
run_time_type);
- } else {
- add_identifier(c, type, name,
- IDENTIFIER_VARIABLE, 0,
- func,
- run_time_type);
+
}
- n=Pike_compiler->new_program->num_identifier_references;
- add_to_identifier_references(ref);
-
- return n;
- }
-
+
/* type is a serialized tokenized type. */
PMOD_EXPORT int quick_map_variable(const char *name,
int name_length,
size_t offset,
const char *type,
int UNUSED(type_length),
INT32 run_time_type,
INT32 flags)
{
int ret;
pike.git/src/program.c:5801:
return n;
}
}
if (!(IDENTIFIERP(n)->id_flags & ID_EXTERN)) {
if (IDENTIFIERP(n)->id_flags & ID_FINAL)
my_yyerror("Illegal to redefine 'final' "
"variable/functions %S", name);
if(!(IDENTIFIERP(n)->id_flags & ID_INLINE) ||
- Pike_compiler->compiler_pass!=1)
+ Pike_compiler->compiler_pass != COMPILER_PASS_FIRST)
{
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)) {
int level = REPORT_WARNING;
if (!match_types(ID_FROM_INT(Pike_compiler->new_program, n)->type,
type)) {
level = REPORT_ERROR;
pike.git/src/program.c:5857:
ID_HIDDEN;
return n2;
} else if ((IDENTIFIERP(n)->id_flags & (ID_INLINE|ID_INHERITED)) ==
(ID_INLINE|ID_INHERITED)) {
/* Hide the overloaded inherited symbol. */
IDENTIFIERP(n)->id_flags |= ID_HIDDEN;
}
} else if ((IDENTIFIERP(n)->id_flags & (ID_EXTERN|ID_INHERITED)) ==
(ID_EXTERN|ID_INHERITED)) {
/* Hide the overloaded inherited symbol. */
- IDENTIFIERP(n)->id_flags |= ID_STATIC|ID_PRIVATE|ID_USED;
+ IDENTIFIERP(n)->id_flags |= ID_PROTECTED|ID_PRIVATE|ID_USED;
}
}
if (flags & ID_EXTERN) {
run_time_type = PIKE_T_FREE;
} else {
run_time_type=compile_type_to_runtime_type(type);
/* FIXME: Shouldn't these special cases be
* in compile_type_to_runtime_type()?
*/
switch(run_time_type)
{
case T_OBJECT:
/* Make place for the object subtype. */
case T_MIXED:
case T_FUNCTION:
no_this = 1;
- /* FALL_THROUGH */
+ /* FALLTHRU */
case T_PROGRAM:
run_time_type = T_MIXED;
break;
case T_INT:
{
INT_TYPE int_range[] = { MAX_INT32, MIN_INT32 };
run_time_type = T_MIXED;
if (get_int_type_range(type, int_range) &&
(int_range[0] > MIN_INT32) && (int_range[1] < MAX_INT32) ) {
run_time_type = T_INT;
pike.git/src/program.c:6052:
n, id->func.const_info.offset);
#endif
}
return n;
}
#ifdef PIKE_DEBUG
if(Pike_compiler->new_program->flags & (PROGRAM_FIXED | PROGRAM_OPTIMIZED))
Pike_fatal("Attempting to add constant to fixed program\n");
- if(Pike_compiler->compiler_pass==2) {
+ if(Pike_compiler->compiler_pass == COMPILER_PASS_LAST) {
dump_program_tables(Pike_compiler->new_program, 2);
Pike_fatal("Internal error: Not allowed to add more identifiers during second compiler pass.\n"
" Attempted to add the identifier \"%s\"\n",
name->str);
}
#endif
#if 1
if (c) {
#endif
pike.git/src/program.c:6083: Inside #if 1
else {
copy_pike_type(type, mixed_type_string);
func.const_info.offset = -1;
opt_flags = 0;
}
#endif
if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;
ref.id_flags=flags;
- ref.identifier_offset=Pike_compiler->new_program->num_identifiers;
+ ref.identifier_offset =
+ low_add_identifier(cc, type, name,
+ IDENTIFIER_CONSTANT, opt_flags,
+ func, c ? TYPEOF(*c) : T_MIXED);
ref.inherit_offset=0;
ref.run_time_type = PIKE_T_UNKNOWN;
- add_identifier(cc, type, name,
- IDENTIFIER_CONSTANT, opt_flags,
- func, c ? TYPEOF(*c) : T_MIXED);
+
free_pike_type(type);
if(n != -1)
{
int overridden;
if(IDENTIFIERP(n)->id_flags & ID_FINAL)
my_yyerror("Illegal to redefine 'final' identifier %S", name);
if(IDENTIFIER_IS_VARIABLE(ID_FROM_INT(Pike_compiler->new_program,
pike.git/src/program.c:6326:
#endif
/* If this is an lfun, match against the predefined type. */
if ((lfun_type = low_mapping_string_lookup(lfun_types, name))) {
int orig_pragmas = c->lex.pragmas;
#ifdef PIKE_DEBUG
if (TYPEOF(*lfun_type) != T_TYPE) {
Pike_fatal("Bad entry in lfun_types for key \"%s\"\n", name->str);
}
#endif /* PIKE_DEBUG */
+ if (Pike_compiler->compiler_pass == COMPILER_PASS_LAST) {
/* Inhibit deprecation warnings during the comparison. */
c->lex.pragmas |= ID_NO_DEPRECATION_WARNINGS;
if (!pike_types_le(type, lfun_type->u.type)) {
int level = REPORT_NOTICE;
if (!match_types(type, lfun_type->u.type)) {
level = REPORT_ERROR;
} else if (c->lex.pragmas & ID_STRICT_TYPES) {
level = REPORT_WARNING;
}
if (level != REPORT_NOTICE) {
yytype_report(level, NULL, 0, lfun_type->u.type,
NULL, 0, type, 0,
"Type mismatch for callback function %S:", name);
}
}
c->lex.pragmas = orig_pragmas;
-
+ }
} else if (((name->len > 3) &&
(index_shared_string(name, 0) == '`') &&
(index_shared_string(name, 1) == '-') &&
(index_shared_string(name, 2) == '>')) ||
((name->len > 1) &&
(index_shared_string(name, 0) == '`') &&
wide_isidchar(index_shared_string(name, 1)))) {
/* Getter setter. */
struct pike_string *symbol = NULL;
struct pike_type *symbol_type = NULL;
pike.git/src/program.c:6404:
if ((i >= 0) &&
!((ref = PTR_FROM_INT(prog, i))->id_flags & ID_INHERITED)) {
/* Not an inherited symbol. */
struct identifier *id = ID_FROM_INT(prog, i);
if (!IDENTIFIER_IS_VARIABLE(id->identifier_flags)) {
my_yyerror("Illegal to redefine function %S with variable.", symbol);
} else if (id->run_time_type != PIKE_T_GET_SET) {
my_yyerror("Illegal to redefine a current variable with a getter/setter: %S.", symbol);
} else {
if ((ref->id_flags | ID_USED) != (flags | ID_USED)) {
- if (Pike_compiler->compiler_pass == 1) {
+ if (Pike_compiler->compiler_pass == COMPILER_PASS_FIRST) {
yywarning("Modifier mismatch for variable %S.", symbol);
}
ref->id_flags &= flags | ID_USED;
}
getter_setter = i;
}
/* FIXME: Update id->type here. */
} else {
struct identifier *id;
i = low_define_variable(symbol, symbol_type, flags,
pike.git/src/program.c:6439:
*/
flags |= ID_PROTECTED /* | ID_PRIVATE | ID_INLINE | ID_USED */;
free_type(symbol_type);
free_string(symbol);
}
}
if(IDENTIFIER_IS_C_FUNCTION(function_flags))
prog->flags |= PROGRAM_HAS_C_METHODS;
- if (Pike_compiler->compiler_pass == 1) {
+ if (Pike_compiler->compiler_pass == COMPILER_PASS_FIRST) {
/* Mark the type as tentative by setting the runtime-type
* to T_MIXED.
*
* NOTE: This should be reset to T_FUNCTION in pass 2.
*/
run_time_type = T_MIXED;
}
i = isidentifier(name);
- if (Pike_compiler->compiler_pass == 1) {
+ if (Pike_compiler->compiler_pass == COMPILER_PASS_FIRST) {
if (flags & ID_VARIANT) {
if (i >= 0) {
if (!is_variant_dispatcher(prog, i)) {
/* This function will be the termination function for
* our variant dispatcher.
*/
struct reference ref = prog->identifier_references[i];
/* Make sure to not get complaints about multiple
* definitions when adding the variant dispatcher.
*/
pike.git/src/program.c:6554:
struct identifier *id = ID_FROM_INT(prog, getter_setter);
(&id->func.gs_info.getter)[is_setter] = i;
}
return i;
}
/* Note: The type from pass 1 may be incompatible with the one from
* pass 2. Only do this in pass 2, and only if the previous
* type isn't from pass 1.
*/
- if ((Pike_compiler->compiler_pass == 2) &&
+ if ((Pike_compiler->compiler_pass == COMPILER_PASS_LAST) &&
(funp->run_time_type == T_FUNCTION)) {
/* match types against earlier prototype or vice versa */
if(!match_types(type, funp->type))
{
yytype_report(REPORT_ERROR, NULL, 0,
funp->type,
NULL, 0, type, 0,
"Prototype doesn't match for function %S.", name);
}
}
pike.git/src/program.c:6595:
if((ref.id_flags & ID_FINAL)
#if 0
&& !(funp->func.offset == -1)
#endif
)
{
my_yyerror("Illegal to redefine 'final' function %S.", name);
}
- if (!(flags & ID_VARIANT) && (Pike_compiler->compiler_pass == 1) &&
+ if (!(flags & ID_VARIANT) &&
+ (Pike_compiler->compiler_pass == COMPILER_PASS_FIRST) &&
(funp->func.c_fun == f_dispatch_variant) &&
(!func || (func->c_fun != f_dispatch_variant) ||
!IDENTIFIER_IS_C_FUNCTION(function_flags)) &&
IDENTIFIER_IS_C_FUNCTION(funp->identifier_flags)) {
/* Overriding a variant function dispatcher with
* a non-variant function in pass 1.
*
* Hide the corresponding variant functions.
*/
int j = prog->num_identifier_references;
pike.git/src/program.c:6641: Inside #if defined(PROGRAM_BUILD_DEBUG)
#ifdef PROGRAM_BUILD_DEBUG
fprintf(stderr, "%*saltering the existing definition\n",
c->compilation_depth, "");
#endif
if(func)
idptr = *func;
else
idptr.offset = -1;
- ref.identifier_offset = prog->num_identifiers;
-
- add_identifier(c, type, name,
+ ref.identifier_offset =
+ low_add_identifier(c, type, name,
function_flags, opt_flags,
idptr, run_time_type);
}
if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;
ref.inherit_offset = 0;
ref.id_flags = flags;
if (flags & ID_VARIANT) {
ref.id_flags |= ID_USED;
pike.git/src/program.c:6695:
}
return overridden;
}
/* NOTE: At this point we already have the identifier in the
* new program, and just need to add the reference.
*/
} else {
make_a_new_def:
#ifdef PIKE_DEBUG
- if(Pike_compiler->compiler_pass==2)
+ if(Pike_compiler->compiler_pass == COMPILER_PASS_LAST)
Pike_fatal("Internal error: Not allowed to add more identifiers during second compiler pass.\n"
"Added identifier: \"%s\"\n", name->str);
#endif
/* Define a new function */
if(func)
idptr = *func;
else
idptr.offset = -1;
pike.git/src/program.c:6718: Inside #if defined(PIKE_DEBUG)
if (a_flag > 5) {
fprintf(stderr,
"Adding new function #%d: '%s'\n"
" identifier_flags:0x%02x opt_flags:0x%04x\n",
prog->num_identifiers,
name->str,
function_flags, opt_flags);
}
#endif /* PIKE_DEBUG */
- i = prog->num_identifiers;
-
- add_identifier(c, type, name,
+ i = low_add_identifier(c, type, name,
function_flags, opt_flags,
idptr, run_time_type);
if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;
ref.id_flags = flags;
ref.identifier_offset = i;
ref.inherit_offset = 0;
}
pike.git/src/program.c:6858:
* B-+-foo All versions of Pike
* |
* +-A---foo
*
* External lookup of identifier "foo" in F():
*
* F-+-A---foo --- Pike 7.7.33
* |
* +-E---foo Pike 7.7.34 ---
*/
- PMOD_EXPORT int really_low_find_shared_string_identifier(struct pike_string *name,
+ PMOD_EXPORT int really_low_find_shared_string_identifier(const struct pike_string *name,
const struct program *prog,
int flags)
{
struct reference *funp;
struct identifier *fun;
int id, i, depth, last_inh;
#if 0
CDFPRINTF("th(%ld) %p Trying to find %s flags=%d\n",
(long)th_self(), prog, name->str, flags);
pike.git/src/program.c:6936:
int really_low_find_variant_identifier(struct pike_string *name,
struct program *prog,
struct pike_type *type,
int start_pos,
int flags)
{
struct reference *funp;
struct identifier *fun;
int id, i, depth, last_inh;
+ int tentative = -1;
#if 1
#ifdef COMPILER_DEBUG
fprintf(stderr,"th(%ld) %p Trying to find variant \"%s\" start=%d flags=%d\n"
" type: ",
(long)th_self(), prog, name->str, start_pos, flags);
simple_describe_type(type);
fprintf(stderr, "\n");
#endif
#endif
pike.git/src/program.c:6977:
{
funp = prog->identifier_references + i;
if(funp->id_flags & ID_HIDDEN) continue;
if(!(funp->id_flags & ID_VARIANT)) continue;
if(funp->id_flags & ID_PROTECTED)
if(!(flags & SEE_PROTECTED))
continue;
fun = ID_FROM_PTR(prog, funp);
/* if(fun->func.offset == -1) continue; * Prototype */
if(!is_same_string(fun->name,name)) continue;
- if(type && (fun->type != type)) continue;
+ if(type && (fun->type != type)) {
+ if ((Pike_compiler->compiler_pass != COMPILER_PASS_FIRST) &&
+ !(funp->id_flags & ID_INHERITED) &&
+ match_types(fun->type, type)) {
+ tentative = i;
+ }
+ continue;
+ }
if(funp->id_flags & ID_INHERITED)
{
struct inherit *inh = INHERIT_FROM_PTR(prog, funp);
if ((funp->id_flags & ID_PRIVATE) && !(flags & SEE_PRIVATE)) continue;
if (!depth || (depth > inh->inherit_level)) {
if (id != -1) {
int j;
int min_level = depth;
for (j=last_inh-1; j > funp->inherit_offset; j--) {
struct inherit *inh2 = prog->inherits + j;
pike.git/src/program.c:7010:
}
last_inh = funp->inherit_offset;
depth = inh->inherit_level;
id = i;
}
} else {
CDFPRINTF("Found %d\n", i);
return i;
}
}
+ if ((id < 0) && (tentative >= 0)) {
+ if (Pike_compiler->compiler_pass == COMPILER_PASS_LAST) {
+ // Usually due to forward-referring types. The tentative match
+ // is often correct, but may in some cases be wrong eg due to
+ // having fall back implementations that use the mixed type.
+ yytype_report(REPORT_WARNING,
+ NULL, 0, ID_FROM_INT(prog, tentative)->type,
+ NULL, 0, type,
+ 0, "Variant type mismatch in second pass for %S.",
+ name);
+ }
+ id = tentative;
+ }
CDFPRINTF("Found %d\n", id);
return id;
}
/**
* This is the dispatcher function for variant functions.
*
* cf end_first_pass().
*/
static void f_dispatch_variant(INT32 args)
pike.git/src/program.c:7118:
Pike_error("Too few arguments to %S(). Expected %O.\n",
name, Pike_sp-1);
}
} else {
Pike_error("Too many arguments to %S().\n", name);
}
}
PMOD_EXPORT int low_find_lfun(struct program *p, enum LFUN lfun)
{
- struct pike_string *lfun_name;
+ const struct pike_string *lfun_name;
unsigned int flags = 0;
int i;
struct identifier *id;
#ifdef PIKE_DEBUG
if ((size_t)lfun >= NELEM(lfun_strings)) {
return find_lfun_fatal(p, lfun);
}
#endif
lfun_name = lfun_strings[lfun];
i = really_low_find_shared_string_identifier(lfun_name,
dmalloc_touch(struct program *,
p),
SEE_PROTECTED);
- if (i < 0 || !(p->flags & PROGRAM_FIXED)) return i;
+
+ if ((i < 0) && (lfun == LFUN__DESTRUCT)) {
+ /* Try the Pike 8.0 compatibility name. */
+ i = really_low_find_shared_string_identifier(compat_lfun_destroy_string,
+ dmalloc_touch(struct program *,
+ p),
+ SEE_PROTECTED);
+ if ((i >= 0) && !(p->flags & PROGRAM_FINISHED) && !TEST_COMPAT(8,0)) {
+ struct compilation *c = MAYBE_THIS_COMPILATION;
+ if (c && !(c->lex.pragmas & ID_NO_DEPRECATION_WARNINGS)) {
+ yywarning("Compat: Substituting destroy() for _destruct().");
+ }
+ }
+ }
+
+ if (i < 0 || !(p->flags & PROGRAM_FIXED)) {
+ return i;
+ }
id = ID_FROM_INT(p, i);
if (IDENTIFIER_IS_PIKE_FUNCTION(id->identifier_flags) &&
(id->func.offset == -1)) {
/* Function prototype. */
return -1;
}
return i;
}
#ifdef PIKE_DEBUG
PMOD_EXPORT int find_lfun_fatal(struct program *UNUSED(p), enum LFUN lfun)
pike.git/src/program.c:7163:
if (!id) return -1;
if (TYPEOF(*id) == T_INT) return id->u.integer;
my_yyerror("Bad entry in lfun lookup table for %S.", lfun_name);
return -1;
}
/**
* Lookup the number of a function in a program given the name in
* a shared_string
*/
- int low_find_shared_string_identifier(struct pike_string *name,
+ int low_find_shared_string_identifier(const struct pike_string *name,
const struct program *prog)
{
int max,min,tst;
struct identifier *fun;
if(prog->flags & PROGRAM_FIXED)
{
unsigned short *funindex = prog->identifier_index;
size_t val_n = PTR_TO_INT (name);
pike.git/src/program.c:7356:
return e;
}
/*
* program examination functions available from Pike.
*/
struct array *program_indices(struct program *p)
{
- int e;
+ int i;
int n = 0;
struct array *res;
- for (e = p->num_identifier_references; e--; ) {
+ for (i = p->num_identifier_index; i--; ) {
struct identifier *id;
-
+ int e = p->identifier_index[i];
if (p->identifier_references[e].id_flags &
(ID_HIDDEN|ID_VARIANT|ID_PROTECTED|ID_PRIVATE)) {
continue;
}
id = ID_FROM_INT(p, e);
if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) {
/* FIXME!
*/
continue;
} else if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) {
pike.git/src/program.c:7395:
}
f_aggregate(n);
res = Pike_sp[-1].u.array;
add_ref(res);
pop_stack();
return(res);
}
struct array *program_values(struct program *p)
{
- int e;
+ int i;
int n = 0;
struct array *res;
- for(e = p->num_identifier_references; e--; ) {
+ for(i = p->num_identifier_index; i--; ) {
struct identifier *id;
-
+ int e = p->identifier_index[i];
if (p->identifier_references[e].id_flags &
(ID_HIDDEN|ID_VARIANT|ID_PROTECTED|ID_PRIVATE)) {
continue;
}
id = ID_FROM_INT(p, e);
if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) {
/* FIXME!
*/
continue;
} else if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) {
pike.git/src/program.c:7434:
}
f_aggregate(n);
res = Pike_sp[-1].u.array;
add_ref(res);
pop_stack();
return(res);
}
struct array *program_types(struct program *p)
{
- int e;
+ int i;
int n = 0;
struct array *res;
- for (e = p->num_identifier_references; e--; ) {
+ for (i = p->num_identifier_index; i--; ) {
struct identifier *id;
-
+ int e = p->identifier_index[i];
if (p->identifier_references[e].id_flags &
(ID_HIDDEN|ID_VARIANT|ID_PROTECTED|ID_PRIVATE)) {
continue;
}
id = ID_FROM_INT(p, e);
if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) {
/* FIXME!
*/
continue;
} else if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) {
pike.git/src/program.c:7512:
id = ID_FROM_INT(loc.o->prog, refid);
} while (IDENTIFIER_IS_ALIAS(id->identifier_flags));
if (fake_object.refs != 1) {
Pike_fatal("Lost track of fake object! refs: %d\n",
fake_object.refs);
}
if (loc.o != &fake_object) {
low_object_index_no_free(to, loc.o, refid);
- #if 0 && defined (COMPILER_DEBUG)
- safe_pike_fprintf (stderr, "low_program_index_no_free1 %O->%S: %O\n",
- what, s, to);
- #endif
+
return 1;
}
}
if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) {
if (id->func.const_info.offset >= 0) {
struct program *p2 = PROG_FROM_INT(p, e);
struct svalue *val = &p2->constants[id->func.const_info.offset].sval;
assign_svalue_no_free(to, val);
} else {
/* Prototype constant. */
SET_SVAL(*to, T_INT, NUMBER_NUMBER, integer, 0);
}
- #if 0 && defined (COMPILER_DEBUG)
- safe_pike_fprintf (stderr, "low_program_index_no_free2 %O->%S: %O\n",
- what, s, to);
- #endif
+
return 1;
}
return 0;
}
int program_index_no_free(struct svalue *to, struct svalue *what,
struct svalue *ind)
{
int e;
struct object *parent = NULL;
pike.git/src/program.c:8298:
MAKE_CONST_STRING(this_function_string,"this_function");
MAKE_CONST_STRING(this_program_string,"this_program");
MAKE_CONST_STRING(this_string,"this");
MAKE_CONST_STRING(UNDEFINED_string,"UNDEFINED");
MAKE_CONST_STRING(args_string, "__args__");
MAKE_CONST_STRING(parser_system_string, "parser");
MAKE_CONST_STRING(type_check_system_string, "type_check");
+ MAKE_CONST_STRING(compat_lfun_destroy_string, "destroy");
+
lfun_ids = allocate_mapping(NUM_LFUNS);
lfun_types = allocate_mapping(NUM_LFUNS);
for (i=0; i < NELEM(lfun_names); i++) {
lfun_strings[i] = make_shared_static_string(lfun_names[i], strlen(lfun_names[i]), eightbit);
SET_SVAL(id, T_INT, NUMBER_NUMBER, integer, i);
SET_SVAL(key, T_STRING, 0, string, lfun_strings[i]);
mapping_insert(lfun_ids, &key, &id);
SET_SVAL(val, T_TYPE, 0, type, make_pike_type(raw_lfun_types[i]));
pike.git/src/program.c:8823:
return NULL;
case T_TUPLE:
case T_OR:
case T_AND:
case PIKE_T_RING:
{
struct program *res;
res = program_from_type(t->car);
if (res) return res;
}
- /* FALL_THROUGH */
+ /* FALLTHRU */
case T_SCOPE:
case T_ASSIGN:
case PIKE_T_ATTRIBUTE:
case PIKE_T_NAME:
return program_from_type(t->cdr);
break;
default:
return NULL;
}
pike.git/src/program.c:9520:
const char **params,
const char *comment)
{
while ((start < end) || opcode || (params && params[0]) ||
(comment && comment[0])) {
ptrdiff_t field_width = sizeof(PIKE_OPCODE_T) * 2;
ptrdiff_t i;
int skip_params = 0;
int skip_comment = 0;
- if (start < end) {
+ if (end) {
/* Address */
string_builder_sprintf(s, "0x%016lx ", start);
-
+ if (start < end) {
/* Memory dump */
for (i = 0; i < 8; i += field_width) {
if (start < end) {
string_builder_sprintf(s, "%0*x ", field_width, start[0]);
start++;
-
+ if (start == end) {
+ end = NULL;
+ }
} else {
string_builder_sprintf(s, "%*s ", field_width, "");
}
}
} else {
-
+ end = NULL;
+ string_builder_sprintf(s, "%*s ", 8 + 8/field_width, "");
+ }
+ } else {
string_builder_sprintf(s, "%*s ", 18 + 8 + 8/field_width, "");
}
/* Opcode */
if (opcode) {
if (strlen(opcode) < 8) {
string_builder_sprintf(s, " %-8s ", opcode);
} else if (strlen(opcode) < 32) {
string_builder_sprintf(s, " %-28s ", opcode);
skip_params = 1;
pike.git/src/program.c:9595:
} else {
string_builder_sprintf(s, " # %s\n", comment);
comment = NULL;
}
} else {
string_builder_sprintf(s, "\n");
}
}
}
+ PMOD_EXPORT void string_builder_append_pike_opcode(struct string_builder *s,
+ const PIKE_OPCODE_T *addr,
+ enum Pike_opcodes op,
+ int arg1,
+ int arg2)
+ {
+ char buf[3][32];
+ const char *params[3] = { NULL, NULL, NULL };
+ const struct instr *instr = &instrs[op - F_OFFSET];
+ sprintf(buf[0], "%d", arg1);
+ sprintf(buf[1], "%d", arg2);
+ if (instr->flags & I_HASARG) {
+ params[0] = buf[0];
+ }
+ if (instr->flags & I_HASARG2) {
+ params[1] = buf[1];
+ }
+ sprintf(buf[2], "# %s", instr->name);
+ string_builder_append_disassembly(s, addr, addr, buf[2], params, NULL);
+ }
+
PMOD_EXPORT void add_reverse_symbol(struct pike_string *sym, void *addr)
{
struct svalue key;
struct svalue val;
SET_SVAL(key, PIKE_T_INT, NUMBER_NUMBER, integer, (ptrdiff_t)addr);
SET_SVAL(val, PIKE_T_STRING, 0, string, sym);
low_mapping_insert(reverse_symbol_table, &key, &val, 1);
}
PMOD_EXPORT void simple_add_reverse_symbol(const char *sym, void *addr)
pike.git/src/program.c:9620:
PMOD_EXPORT void init_reverse_symbol_table()
{
int op;
if (reverse_symbol_table) return;
reverse_symbol_table = allocate_mapping(256);
/* Initialize with the most popular symbols. */
#define ADD_SYMBOL(SYM) simple_add_reverse_symbol(#SYM "()", (void *)(SYM))
- #ifdef PIKE_DEBUG
+ #if defined(PIKE_DEBUG) && defined(PIKE_USE_MACHINE_CODE)
ADD_SYMBOL(simple_debug_instr_prologue_0);
ADD_SYMBOL(simple_debug_instr_prologue_1);
ADD_SYMBOL(simple_debug_instr_prologue_2);
#endif
ADD_SYMBOL(low_return);
ADD_SYMBOL(low_return_pop);
ADD_SYMBOL(really_free_svalue);
ADD_SYMBOL(lvalue_to_svalue_no_free);
ADD_SYMBOL(f_add);
ADD_SYMBOL(really_free_string);
pike.git/src/program.c:9643:
ADD_SYMBOL(svalue_is_true);
ADD_SYMBOL(assign_lvalue);
ADD_SYMBOL(really_free_array);
ADD_SYMBOL(object_low_set_index);
ADD_SYMBOL(low_object_index_no_free);
ADD_SYMBOL(assign_to_short_svalue);
ADD_SYMBOL(really_free_short_svalue_ptr);
ADD_SYMBOL(mega_apply);
simple_add_reverse_symbol("Pike_interpreter_pointer",
- &Pike_interpreter_pointer);
+ (void *)&Pike_interpreter_pointer);
#ifdef PIKE_USE_MACHINE_CODE
/* Add the opcodes as well. */
for (op = 1; op < (F_MAX_INSTR - F_OFFSET); op++) {
if (!instrs[op].address) continue;
simple_add_reverse_symbol(instrs[op].name, instrs[op].address);
}
#endif /* PIKE_USE_MACHINE_CODE */
}