pike.git/src/program.c:25:
#include "constants.h"
#include "operators.h"
#include "builtin_functions.h"
#include "stuff.h"
#include "mapping.h"
#include "cyclic.h"
#include "pike_security.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 <errno.h>
#include <fcntl.h>
#define sp Pike_sp
#undef ATTRIBUTE
#define ATTRIBUTE(X)
static void low_enter_compiler(struct object *ce, int inherit);
static void exit_program_struct(struct program *);
static size_t add_xstorage(size_t size,
size_t alignment,
ptrdiff_t modulo_orig);
- #undef EXIT_BLOCK
- #define EXIT_BLOCK(P) exit_program_struct( (P) )
+ static struct block_allocator program_allocator = BA_INIT_PAGES(sizeof(struct program), 4);
- #undef COUNT_OTHER
- #define COUNT_OTHER() do{ \
- struct program *p; \
- for(p=first_program;p;p=p->next) \
- { \
- size+=p->total_size - sizeof (struct program); \
- } \
- }while(0)
+ ATTRIBUTE((malloc))
+ struct program * alloc_program() {
+ return ba_alloc(&program_allocator);
+ }
- BLOCK_ALLOC_FILL_PAGES(program, 4)
+ void really_free_program(struct program * p) {
+ exit_program_struct(p);
+ ba_free(&program_allocator, p);
+ }
-
+ 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);
+ }
+ *_size = size;
+ }
-
+ void free_all_program_blocks() {
+ ba_destroy(&program_allocator);
+ }
+
/* #define COMPILER_DEBUG */
/* #define PROGRAM_BUILD_DEBUG */
#ifdef COMPILER_DEBUG
#define CDFPRINTF(X) fprintf X
-
+ #ifndef PIKE_THREADS
+ /* The CDFPRINTF lines wants to print threads_disabled, so fake on of those */
+ static const int threads_disabled = 1;
+ #endif
#else /* !COMPILER_DEBUG */
#define CDFPRINTF(X)
#endif /* COMPILER_DEBUG */
/*
* 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
pike.git/src/program.c:89:
* For normal applications, the hitrate is most likely well over 90%,
* but that should be verified.
* - Holistiska Centralbyrån (Hubbe)
*/
/* Define the size of the cache that is used for method lookup. */
/* A value of zero disables this cache */
#define FIND_FUNCTION_HASHSIZE 16384
/* Programs with less methods will not use the cache for method lookups.. */
- #define FIND_FUNCTION_HASH_TRESHOLD 9
+ #define FIND_FUNCTION_HASH_TRESHOLD 0
#define DECLARE
#include "compilation.h"
struct pike_string *this_program_string;
static struct pike_string *this_string, *this_function_string;
static struct pike_string *UNDEFINED_string;
/* Common compiler subsystems */
pike.git/src/program.c:154:
"_sprintf",
"_equal",
"_m_delete",
"_get_iterator",
"`[..]",
/* NOTE: After this point there are only fake lfuns. */
"_search",
"_types",
"_serialize",
"_deserialize",
+ "_size_object",
+ "_random",
};
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[] = {
pike.git/src/program.c:214:
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), tVoid, 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, tMix), /* "_random", */
};
/* 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.
*!
pike.git/src/program.c:839:
*! Currently casting between object types is a noop.
*!
*! @note
*! If the returned value is not deemed to be of the requested type
*! a runtime error may be thrown.
*!
*! @note
*! It's assumed that this function is side-effect free.
*/
- /*! @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::`[..]]
- */
-
+
/*! @decl mixed lfun::`[](zero arg1, zero|void arg2)
*!
*! Indexing callback.
*!
*! For compatibility, this is also called to do subranges unless
*! there is a @[`[..]] in the class. See @[predef::`[..]] for
*! details.
*!
*! @note
*! It's assumed that this function is side-effect free.
pike.git/src/program.c:874:
*/
/*! @decl mixed lfun::`[]=(zero arg1, zero arg2)
*!
*! Index assignment callback.
*!
*! @seealso
*! @[predef::`[]=()], @[lfun::`->=()]
*/
- /*! @decl mixed lfun::`->(string arg, object|void context, int|void access)
+ /*! @decl mixed lfun::`->(string index, object|void context, int|void access)
*!
*! Arrow index callback.
*!
-
+ *! @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.
+ *!
*! @note
*! It's assumed that this function is side-effect free.
*!
*! @seealso
*! @[predef::`->()], @[::`->()]
*/
- /*! @decl mixed lfun::`->=(string arg, zero value, @
+ /*! @decl mixed lfun::`->=(string index, zero value, @
*! object|void context, int|void access)
*!
*! Arrow index assignment callback.
*!
-
+ *! @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].
+ *!
*! @seealso
*! @[predef::`->=()], @[::`->=()], @[lfun::`[]=()]
*/
/*! @decl int lfun::_sizeof()
*!
*! Size query callback.
*!
*! Called by @[predef::sizeof()] to determine the number of elements
*! in an object. If this function is not present, the number
pike.git/src/program.c:1117:
*! references a specific item contained (in some arbitrary sense)
*! in this one.
*!
*! @note
*! It's assumed that this function is side-effect free.
*!
*! @seealso
*! @[predef::Iterator], @[predef::get_iterator], @[predef::foreach()]
*/
+ /*! @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 ****/
+
/*! @decl mixed lfun::_search(mixed needle, mixed|void start)
*!
*! Search callback.
*!
*! @seealso
*! @[predef::search()]
*/
/*! @decl array lfun::_types(object|void context, int|void access)
*!
pike.git/src/program.c:1209:
*!
*! @note
*! A default implementation of @[lfun::_serialize()] and
*! @[lfun::_deserialize()] is available in @[Serializer.Serializable].
*!
*! @seealso
*! @[lfun::_serialize()], @[Serializer.deserialize()],
*! @[Serializer.Serializable()->_deserialize()]
*/
+ /*! @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()]
+ */
+
+ /*! @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()]
+ */
+
+ /**** END FAKE LFUNS ****/
+ /**** BEGIN MAGIC LFUNS ****/
+
/*! @decl mixed lfun::`symbol()
*! @decl mixed lfun::`->symbol()
*!
*! 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!
pike.git/src/program.c:1322:
static struct program *reporter_program = NULL;
struct program *compilation_program = 0;
struct program *compilation_env_program = 0;
struct object *compilation_environment = NULL;
struct program *gc_internal_program = 0;
static struct program *gc_mark_program_pos = 0;
#ifdef PIKE_DEBUG
- #define CHECK_FILE_ENTRY(PROG, POS, LEN, SHIFT) \
+ #define CHECK_FILE_ENTRY(PROG, STRNO) \
do { \
- if (SHIFT < 0 || SHIFT > 2 || \
- POS + (LEN << SHIFT) > PROG->linenumbers + PROG->num_linenumbers) \
+ if ((STRNO < 0) || (STRNO >= PROG->num_strings)) \
Pike_fatal ("Invalid file entry in linenumber info.\n"); \
} while (0)
#else
- #define CHECK_FILE_ENTRY(PROG, POS, LEN, SHIFT) do {} while (0)
+ #define CHECK_FILE_ENTRY(PROG, STRNO) do {} while (0)
#endif
INT_TYPE get_small_number(char **q);
PMOD_EXPORT void do_free_program (struct program *p)
{
if (p)
free_program(p);
}
pike.git/src/program.c:1843:
if(!IS_UNDEFINED (Pike_sp-1))
{
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)) {
+ add_ref(ret);
+ } else {
+ my_yyerror("Invalid program identifier '%S'.", ident);
+ }
+ free_node(n);
+ } else {
+ my_yyerror("Unknown program identifier '%S'.", ident);
+ }
+ return ret;
+ }
+
/*! @decl constant this
*!
*! Builtin read only variable that evaluates to the current object.
*!
*! @seealso
*! @[this_program], @[this_object()]
*/
/*! @decl constant this_program
*!
pike.git/src/program.c:1898:
}
if ((inherit_num == -1) || (!TEST_COMPAT(7,6) && (inherit_num >= 0))) {
if (ident == this_string) {
/* Handle this. */
return mkthisnode(state->new_program, inherit_num);
}
/* Handle this_program */
if (ident == this_program_string) {
- node *n = mkefuncallnode("object_program",
+ 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. */
+ i = reference_inherited_identifier(state->previous, NULL, name);
+ 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));
-
+ }
/* We know this expression is constant. */
n->node_info &= ~OPT_NOT_CONST;
n->tree_info &= ~OPT_NOT_CONST;
return n;
}
/* Handle this_function */
if (ident == this_function_string) {
int i;
if ((i = Pike_compiler->compiler_frame->current_function_number) >= 0) {
pike.git/src/program.c:2060:
case PROG_PARSER_HTML_ID:
module = "Parser._parser";
break;
case PROG_GMP_MPZ_ID:
module = "Gmp";
break;
case PROG_MODULE_MIME_ID:
module = "___MIME";
break;
default:
- if ((id >= 100) && (id <= 300)) {
+ if ((id >= 100) && (id < 300)) {
module = "Image";
-
+ } else if ((id >= 300) && (id < 400)) {
+ module = "Nettle";
} else if ((id >= 1000) && (id < 2000)) {
module = "___GTK";
} else if ((id >= 2000) && (id < 3000)) {
module = "___GTK2";
}
break;
}
if (module && get_master()) {
/* fprintf(stderr, "%s... ", module); */
push_text(module);
pike.git/src/program.c:2212: Inside #if defined(PIKE_DEBUG) and #if defined(DEBUG_MALLOC)
return make_shared_string(tmp);
}
}
}
#endif
return get_program_line(p, line);
}
#endif
- int override_identifier (struct reference *new_ref, struct pike_string *name)
+ int override_identifier (struct reference *new_ref, struct pike_string *name,
+ int required_flags)
{
struct compilation *c = THIS_COMPILATION;
int id = -1, cur_id = 0, is_used = 0;
int new_is_variable =
IDENTIFIER_IS_VARIABLE(ID_FROM_PTR(Pike_compiler->new_program,
new_ref)->identifier_flags);
/* This loop could possibly be optimized by looping over
* each inherit and looking up 'name' in each inherit
pike.git/src/program.c:2241:
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;
/* Do not zapp hidden identifiers */
if(ref->id_flags & ID_HIDDEN) continue;
+ if(ref->id_flags & ID_VARIANT) continue;
+
+ if ((ref->id_flags & required_flags) != required_flags) continue;
+
/* Do not zapp functions with the wrong name... */
if((i = ID_FROM_PTR(Pike_compiler->new_program, ref))->name != name)
continue;
/* 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)) {
pike.git/src/program.c:2278:
continue;
}
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--;
+ #if 0
#ifdef PIKE_DEBUG
if (!inh->inherit_level) {
-
+ /* FIXME: This is valid for references that are about to be
+ * overridden by the variant dispatcher.
+ */
Pike_fatal("Inherit without intermediate levels.\n");
}
#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) &&
!pike_types_le(ID_FROM_PTR(Pike_compiler->new_program,
pike.git/src/program.c:2364:
* Consider this a fatal?
*/
p->identifiers[i].run_time_type = T_FUNCTION;
}
}
/* 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;
+ if (ref->id_flags & ID_VARIANT) continue;
if (ref->inherit_offset != 0) continue;
- override_identifier (ref, ID_FROM_PTR (p, ref)->name);
+ override_identifier (ref, ID_FROM_PTR (p, ref)->name, 0);
}
/* Ok, sort for binsearch */
for(e=i=0;i<(int)p->num_identifier_references;i++)
{
struct reference *funp;
struct identifier *fun;
funp=p->identifier_references+i;
if(funp->id_flags & ID_HIDDEN) continue;
-
+ if(funp->id_flags & ID_VARIANT) continue;
fun=ID_FROM_PTR(p, funp);
if(funp->id_flags & ID_INHERITED)
{
int found_better=-1;
int funa_is_prototype;
/* NOTE: Mixin is currently not supported for PRIVATE symbols. */
if(funp->id_flags & ID_PRIVATE) continue;
funa_is_prototype = fun->func.offset == -1;
/* if(fun->func.offset == -1) continue; * prototype */
/* check for multiple definitions */
for(t=i+1;t<(int)p->num_identifier_references;t++)
{
struct reference *funpb;
struct identifier *funb;
funpb=p->identifier_references+t;
if (funpb->id_flags & ID_HIDDEN) continue;
-
+ if (funpb->id_flags & ID_VARIANT) continue;
funb=ID_FROM_PTR(p,funpb);
/* if(funb->func.offset == -1) continue; * prototype */
if(fun->name==funb->name)
{
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;
pike.git/src/program.c:2494:
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;
+ 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
* inherited PROGRAM_LIVE_OBJ flags. This is done at fixation time
pike.git/src/program.c:2648:
struct pike_string *name,
int flags,
int *idp)
{
struct compilation *c = THIS_COMPILATION;
int id=0;
struct svalue tmp;
CHECK_COMPILER();
- #ifdef WITH_FACETS
- if(Pike_compiler->compiler_pass == 1 && p) {
- p->facet_index = -1;
- p->facet_group = NULL;
- }
- #endif
-
+
/* We don't want to change thread, but we don't want to
* wait for the other threads to complete either.
*/
low_init_threads_disable();
c->compilation_depth++;
- if (!Pike_compiler->compiler_frame) {
- new_node_s_context();
- }
-
+
SET_SVAL_TYPE(tmp, T_PROGRAM);
if(!p)
{
p=low_allocate_program();
if(name)
{
tmp.u.program=p;
id=add_constant(name, &tmp, flags & ~ID_EXTERN);
#if 0
fprintf(stderr,"Compiling class %s, depth=%d\n",
pike.git/src/program.c:2717:
"pass=%d: threads_disabled:%d, compilation_depth:%d\n",
(long)th_self(), p, name ? name->str : "-",
Pike_compiler->compiler_pass,
threads_disabled, c->compilation_depth));
init_type_stack();
#define PUSH
#include "compilation.h"
+ ba_init(&Pike_compiler->node_allocator, sizeof(struct node_s), 512);
+
Pike_compiler->parent_identifier=id;
Pike_compiler->compiler_pass = pass;
Pike_compiler->num_used_modules=0; /* FIXME: Duplicate? */
if(p->flags & PROGRAM_FINISHED)
{
yyerror("Pass2: Program already done");
}
pike.git/src/program.c:2830:
#define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \
Pike_compiler->malloc_size_program->PIKE_CONCAT(num_,NAME) = \
Pike_compiler->new_program->PIKE_CONCAT(num_,NAME);
#include "program_areas.h"
{
INT_TYPE line = 0;
INT32 off = 0;
size_t len = 0;
INT32 shift = 0;
- char *file=0;
+ struct pike_string *file=0;
char *cnt=Pike_compiler->new_program->linenumbers;
while(cnt < Pike_compiler->new_program->linenumbers +
Pike_compiler->new_program->num_linenumbers)
{
if(*cnt == 127)
{
-
+ int strno;
cnt++;
- len = get_small_number(&cnt);
- shift = *cnt;
- file = ++cnt;
- CHECK_FILE_ENTRY (Pike_compiler->new_program, cnt, len, shift);
- cnt += len<<shift;
+ strno = get_small_number(&cnt);
+ CHECK_FILE_ENTRY (Pike_compiler->new_program, strno);
+ file = Pike_compiler->new_program->strings[strno];
}
off+=get_small_number(&cnt);
line+=get_small_number(&cnt);
}
Pike_compiler->last_line=line;
Pike_compiler->last_pc=off;
if(file)
{
- struct pike_string *str = begin_wide_shared_string(len, shift);
+
if(Pike_compiler->last_file) free_string(Pike_compiler->last_file);
- memcpy(str->str, file, len<<shift);
- Pike_compiler->last_file = end_shared_string(str);
+ copy_shared_string(Pike_compiler->last_file, file);
}
}
}else{
static struct pike_string *s;
struct inherit i;
-
+ 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++;
+ }
+ }
+
#define START_SIZE 64
#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 = \
pike.git/src/program.c:3024:
{
if(p->inherits[e].prog)
free_program(p->inherits[e].prog);
}
if(p->inherits[e].parent)
free_object(p->inherits[e].parent);
}
DOUBLEUNLINK(first_program, p);
- #ifdef WITH_FACETS
- if(p->facet_group)
- {
- free_object(p->facet_group);
- }
- #endif
-
+
if(p->flags & PROGRAM_OPTIMIZED)
{
#ifdef PIKE_USE_MACHINE_CODE
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); \
pike.git/src/program.c:3207:
Pike_compiler->last_identifier=0;
}
if(Pike_compiler->last_file)
{
free_string(Pike_compiler->last_file);
Pike_compiler->last_file=0;
}
unuse_modules(Pike_compiler->num_used_modules);
+
+ free_all_nodes();
+
+ ba_destroy(&Pike_compiler->node_allocator);
}
int sizeof_variable(int run_time_type)
{
switch(run_time_type)
{
case T_FUNCTION:
case T_MIXED: return sizeof(struct svalue);
case T_FLOAT: return sizeof(FLOAT_TYPE);
case T_INT: return sizeof(INT_TYPE);
pike.git/src/program.c:3239:
case T_FLOAT: return ALIGNOF(FLOAT_TYPE);
case T_INT: return ALIGNOF(INT_TYPE);
case PIKE_T_FREE:
case PIKE_T_GET_SET: return 1;
default: return ALIGNOF(void *);
}
}
#ifdef PIKE_DEBUG
- void dump_program_tables (const struct program *p, int indent)
+ PMOD_EXPORT void dump_program_tables (const struct program *p, int indent)
{
int d;
if (!p) {
fprintf(stderr, "%*sProgram: NULL\n\n", indent, "");
return;
}
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;
struct identifier *id = ID_FROM_PTR(p, ref);
-
+ struct program *inh_p = INHERIT_FROM_PTR(p, ref)->prog;
fprintf(stderr,
"%*s %4d: %5x %7d %10d %s\n"
"%*s %s:%ld\n",
indent, "",
d, ref->id_flags, ref->inherit_offset,
ref->identifier_offset,
id->name->size_shift ? "(wide)" : id->name->str,
indent, "",
- p->num_strings?p->strings[id->filename_strno]->str:"-",
+ inh_p->num_strings?inh_p->strings[id->filename_strno]->str:"-",
(long)id->linenumber);
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",
indent, "", (long)id->func.const_info.offset);
} 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)) {
INT_TYPE line;
- struct program *inh_p = INHERIT_FROM_PTR(p,ref)->prog;
+
struct pike_string *file =
get_line (ID_FROM_PTR(p,ref)->func.offset + inh_p->program, inh_p, &line);
if (!file->size_shift)
fprintf (stderr, "%*s %s:%ld\n",
indent, "", file->str, (long)line);
free_string (file);
} else {
fprintf (stderr, "%*s Cfun: %p\n",
indent, "", id->func.c_fun);
}
pike.git/src/program.c:3399:
fprintf(stderr, "\n"
"%*sLinenumber table:\n",
indent, "");
{
INT32 off = 0;
INT_TYPE line = 0;
char *cnt = p->linenumbers;
while (cnt < p->linenumbers + p->num_linenumbers) {
if (*cnt == 127) {
- int len, shift;
- char *file;
+ int strno;
cnt++;
- len = get_small_number(&cnt);
- shift = *cnt;
- file = ++cnt;
- CHECK_FILE_ENTRY (p, cnt, len, shift);
- cnt += len << shift;
- if (!shift) {
- fprintf(stderr, "%*s Filename: \"%s\"\n", indent, "", file);
- } else {
- fprintf(stderr, "%*s Filename: len:%d, shift:%d\n", indent, "", len, shift);
+ strno = get_small_number(&cnt);
+ fprintf(stderr, "%*s Filename: String #%d\n", indent, "", strno);
}
- }
+
off += get_small_number(&cnt);
line += get_small_number(&cnt);
fprintf(stderr, "%*s %8d:%8ld\n", indent, "", off, (long)line);
}
}
fprintf(stderr, "\n");
}
void check_program(struct program *p)
pike.git/src/program.c:3694:
p) > 0)) {
Pike_fatal("Program->identifier_index[%ld] > "
"Program->identifier_index[%ld]\n",
(long)(e-1), (long)e);
}
}
}
#endif
+ static void f_dispatch_variant(INT32 args);
+
+ int is_variant_dispatcher(struct program *prog, int fun)
+ {
+ struct reference *ref;
+ struct identifier *id;
+ if (fun < 0) return 0;
+ ref = PTR_FROM_INT(prog, fun);
+ id = ID_FROM_PTR(prog, ref);
+ return (IDENTIFIER_IS_C_FUNCTION(id->identifier_flags) &&
+ !IDENTIFIER_IS_ALIAS(id->identifier_flags) &&
+ (id->func.c_fun == f_dispatch_variant));
+ }
+
+ 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);
+ }
+
/* Note: This function is misnamed, since it's run after both passes. /mast */
/* finish-states:
*
* 0: First pass.
* 1: Last pass.
* 2: Called from decode_value().
*/
struct program *end_first_pass(int finish)
{
struct compilation *c = THIS_COMPILATION;
int e;
- struct program *prog;
+ struct program *prog = Pike_compiler->new_program;
struct pike_string *s;
-
+ 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;
+ int opt_flags;
+ int j;
+ if (prog->identifier_references[e].inherit_offset) continue;
+ if (!is_variant_dispatcher(prog, e)) continue;
+ /* Found a dispatcher. */
+
+ id = ID_FROM_INT(prog, e);
+ name = id->name;
+ type = NULL;
+ id_flags = 0;
+ opt_flags = 0;
+
+ CDFPRINTF((stderr, "Collecting variants of \"%s\"...\n", name->str));
+
+ /* 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;
+ 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.
+ */
+ prog->identifier_references[j].id_flags |= ID_LOCAL;
+ {
+ struct pike_type * temp = type;
+ type = or_pike_types(type, id->type, 1);
+ if (temp) free_type(temp);
+ }
+ #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
+ /* Update the type of the dispatcher. */
+ id = ID_FROM_INT(prog, e);
+ free_type(id->type);
+ id->type = type;
+ id->opt_flags = opt_flags;
+ prog->identifier_references->id_flags |= id_flags & ~(ID_VARIANT|ID_LOCAL);
+ next_ref:
+ ;
+ }
+
debug_malloc_touch(Pike_compiler->fake_object);
debug_malloc_touch(Pike_compiler->fake_object->storage);
MAKE_CONST_STRING(s,"__INIT");
/* Collect references to inherited __INIT functions */
if (!(Pike_compiler->new_program->flags & PROGRAM_AVOID_CHECK)) {
for(e=Pike_compiler->new_program->num_inherits-1;e;e--)
{
int id;
if(Pike_compiler->new_program->inherits[e].inherit_level!=1) continue;
- id=low_reference_inherited_identifier(0, e, s, SEE_PROTECTED);
+ id = Pike_compiler->new_program->inherits[e].prog->lfuns[LFUN___INIT];
+ id = really_low_reference_inherited_identifier(0, e, id);
if(id!=-1)
{
Pike_compiler->init_node=mknode(F_COMMA_EXPR,
mkcastnode(void_type_string,
mkapplynode(mkidentifiernode(id),0)),
Pike_compiler->init_node);
}
}
}
pike.git/src/program.c:3749:
e=dooptcode(s,
mknode(F_COMMA_EXPR,
Pike_compiler->init_node,
mknode(F_RETURN,mkintnode(0),0)),
function_type_string,
ID_PROTECTED);
Pike_compiler->init_node=0;
} else if (finish == 2) {
/* Called from decode_value(). */
e = low_find_lfun(Pike_compiler->new_program, LFUN___INIT);
+ if ((e != -1) &&
+ (ID_FROM_INT(Pike_compiler->new_program, e)->func.offset == -1)) {
+ /* Just a prototype. Make sure not to call it. */
+ e = -1;
+ }
}else{
-
+ /* 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.
+ */
e=-1;
}
Pike_compiler->new_program->lfuns[LFUN___INIT]=e;
pop_compiler_frame(); /* Pop __INIT local variables */
if(Pike_compiler->num_parse_error > 0)
{
CDFPRINTF((stderr, "th(%ld) %p Compilation errors (%d).\n",
(long)th_self(), Pike_compiler->new_program,
pike.git/src/program.c:3790:
fixate_program();
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;
}
+ } 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);
}
-
+ }
#ifdef PIKE_DEBUG
if (prog) {
check_program(prog);
if(l_flag)
dump_program_desc(prog);
}
#endif
}
pike.git/src/program.c:3832: Inside #if defined(SHARED_NODES)
#ifdef SHARED_NODES
/* free(node_hash.table); */
#endif /* SHARED_NODES */
#define POP
#include "compilation.h"
exit_type_stack();
- free_all_nodes();
+
CDFPRINTF((stderr,
"th(%ld) %p end_first_pass(%d): "
"threads_disabled:%d, compilation_depth:%d\n",
(long)th_self(), prog, finish,
threads_disabled, c->compilation_depth));
c->compilation_depth--;
exit_threads_disable(NULL);
pike.git/src/program.c:4140:
PMOD_EXPORT void pike_set_prog_optimize_callback(node *(*opt)(node *))
{
#ifdef PIKE_DEBUG
if(Pike_compiler->new_program->optimize)
Pike_fatal("Program already has an optimize handler!\n");
#endif
Pike_compiler->new_program->optimize = opt;
}
- int really_low_reference_inherited_identifier(struct program_state *q,
- int e,
- int i)
+ PMOD_EXPORT int really_low_reference_inherited_identifier(struct program_state *q,
+ int i,
+ int f)
{
struct program *np=(q?q:Pike_compiler)->new_program;
struct reference funp;
struct program *p;
int d, num_id_refs;
- if(i==-1) return -1;
+ if(f==-1) return -1;
- p = np->inherits[e].prog;
+ p = np->inherits[i].prog;
- funp = p->identifier_references[i];
- funp.inherit_offset += e;
+ funp = p->identifier_references[f];
+ funp.inherit_offset += i;
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;
if ((refp->inherit_offset == funp.inherit_offset) &&
(refp->identifier_offset == funp.identifier_offset) &&
- ((refp->id_flags | ID_USED) == (funp.id_flags | ID_USED)))
+ ((refp->id_flags | ID_USED) == (funp.id_flags | ID_USED))) {
return d;
}
-
+ }
funp.run_time_type = PIKE_T_UNKNOWN;
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 */
-
+
return num_id_refs; /* aka np->num_identifier_references - 1 */
}
- int low_reference_inherited_identifier(struct program_state *q,
+ PMOD_EXPORT int low_reference_inherited_identifier(struct program_state *q,
int e,
struct pike_string *name,
int flags)
{
struct program *np=(q?q:Pike_compiler)->new_program;
struct program *p;
int i;
p=np->inherits[e].prog;
i=find_shared_string_identifier(name,p);
pike.git/src/program.c:4218:
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 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 */
- /* 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.
- */
+
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 */
- if (p->inherits[e].inherit_level > 1) continue;
- if (name == p->inherits[e].name) return e;
+ 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;
}
- return 0;
+
}
-
+ return res;
+ }
- /* Reference the symbol super_name::function_name */
- node *reference_inherited_identifier(struct pike_string *super_name,
- struct pike_string *function_name)
+ /* Reference the symbol inherit::name in the lexical context
+ * specified by state.
+ *
+ * Returns the reference in state->new_program if found.
+ */
+ PMOD_EXPORT int reference_inherited_identifier(struct program_state *state,
+ struct pike_string *inherit,
+ struct pike_string *name)
{
- int n,e,id;
- struct compilation *c = THIS_COMPILATION;
- struct program_state *state=Pike_compiler->previous;
-
+ int e, id;
struct program *p;
-
+
#ifdef PIKE_DEBUG
- if(function_name!=debug_findstring(function_name))
- Pike_fatal("reference_inherited_function on nonshared string.\n");
+ if (name != debug_findstring(name))
+ Pike_fatal("reference_inherited_identifier on nonshared string.\n");
#endif
- p=Pike_compiler->new_program;
+ if (!state) state = Pike_compiler;
- /* 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.
- */
- for(e=p->num_inherits-1;e>0;e--)
- {
- if(p->inherits[e].inherit_level!=1) continue;
- if(!p->inherits[e].name) continue;
+ p = state->new_program;
- if(super_name)
- if(super_name != p->inherits[e].name)
- continue;
-
- id=low_reference_inherited_identifier(0,
- e,
- function_name,
- SEE_PROTECTED);
-
- if(id!=-1)
- return mkidentifiernode(id);
-
- if(ISCONSTSTR(function_name,"`->") ||
- ISCONSTSTR(function_name,"`[]"))
- {
- return mknode(F_MAGIC_INDEX,mknewintnode(e),mknewintnode(0));
- }
-
- if(ISCONSTSTR(function_name,"`->=") ||
- ISCONSTSTR(function_name,"`[]="))
- {
- return mknode(F_MAGIC_SET_INDEX,mknewintnode(e),mknewintnode(0));
- }
-
- if(ISCONSTSTR(function_name,"_indices"))
- {
- return mknode(F_MAGIC_INDICES,mknewintnode(e),mknewintnode(0));
- }
-
- if(ISCONSTSTR(function_name,"_values"))
- {
- return mknode(F_MAGIC_VALUES,mknewintnode(e),mknewintnode(0));
- }
- }
-
-
- for(n=0;n<c->compilation_depth;n++,state=state->previous)
- {
- struct program *p=state->new_program;
-
+
/* 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.
*/
- for(e=p->num_inherits-1;e>0;e--)
- {
- if(p->inherits[e].inherit_level!=1) continue;
- if(!p->inherits[e].name) continue;
+ for (e = p->num_inherits; e--;) {
+ if (p->inherits[e].inherit_level != 1) continue;
+ if (inherit && (inherit != p->inherits[e].name)) continue;
- if(super_name)
- if(super_name != p->inherits[e].name)
- continue;
+ id = low_reference_inherited_identifier(state, e, name, SEE_PROTECTED);
- id=low_reference_inherited_identifier(state,e,function_name,SEE_PROTECTED);
-
- if(id!=-1)
- return mkexternalnode(p, id);
-
- if(ISCONSTSTR(function_name,"`->") ||
- ISCONSTSTR(function_name,"`[]"))
- {
- return mknode(F_MAGIC_INDEX,
- mknewintnode(e),mknewintnode(n+1));
+ if (id != -1) return id;
}
- if(ISCONSTSTR(function_name,"`->=") ||
- ISCONSTSTR(function_name,"`[]="))
- {
- return mknode(F_MAGIC_SET_INDEX,
- mknewintnode(e),mknewintnode(n+1));
+ return -1;
}
- if(ISCONSTSTR(function_name,"_indices"))
- {
- return mknode(F_MAGIC_INDICES,
- mknewintnode(e),mknewintnode(n+1));
- }
-
- if(ISCONSTSTR(function_name,"_values"))
- {
- return mknode(F_MAGIC_VALUES,
- mknewintnode(e),mknewintnode(n+1));
- }
- }
- }
-
- return 0;
- }
-
+
/* FIXME: This function probably doesn't do what it is intended to do
* if the last inherit had inherits of its own. Consider removal.
*/
void rename_last_inherit(struct pike_string *n)
{
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,
n);
}
pike.git/src/program.c:4436: Inside #if 0
parent_offset+=i->parent_offset;
#endif
return locate_parent_state(&state,
&i,
&parent_identifier,
depth);
}
#endif
- #ifdef WITH_FACETS
- void check_for_facet_inherit(struct program *p)
- {
- /* If the inherit statement comes before the facet keyword in the
- * class declaration the class will be temporarily marked as a
- * product-class, but this will be taken care of when the facet
- * keyword is found. */
- if (!p) return;
- if (Pike_compiler->new_program->facet_group &&
- p->facet_group != Pike_compiler->new_program->facet_group)
- yyerror("A class can not belong to two facet-groups.");
- if (p->flags & PROGRAM_IS_FACET) {
- if (Pike_compiler->new_program->flags & PROGRAM_IS_FACET) {
- if(Pike_compiler->new_program->facet_index != p->facet_index)
- yyerror("Facet class can't inherit from class in different facet.");
- }
- /* Otherwise this is a product class */
- else {
- if( !Pike_compiler->new_program->facet_group ) {
- Pike_compiler->new_program->flags |= PROGRAM_IS_PRODUCT;
- add_ref(p->facet_group);
- Pike_compiler->new_program->facet_group = p->facet_group;
- }
- push_int(Pike_compiler->new_program->id);
- push_int(p->facet_index);
- push_int(p->id);
- safe_apply(p->facet_group, "add_product_class", 3);
- pop_stack();
- }
- }
- /* The inherited class is not a facet class */
- else if (p->flags & PROGRAM_IS_PRODUCT) {
- if (Pike_compiler->new_program->flags & PROGRAM_IS_FACET) {
- yyerror("Facet class can't inherit from product class.");
- }
- else if(Pike_compiler->new_program->flags & PROGRAM_IS_PRODUCT){
- yyerror("Product class can't inherit from other product class.");
- }
- /* A class that inherits from a product class is also a product class */
- else {
- Pike_compiler->new_program->flags |= PROGRAM_IS_PRODUCT;
- add_ref(p->facet_group);
- Pike_compiler->new_program->facet_group = p->facet_group;
- }
- }
- }
- #endif
-
-
- /*
- * make this program inherit another program
- */
- PMOD_EXPORT void low_inherit(struct program *p,
+ void lower_inherit(struct program *p,
struct object *parent,
int parent_identifier,
int parent_offset,
INT32 flags,
struct pike_string *name)
{
int e;
ptrdiff_t inherit_offset, storage_offset;
struct inherit inherit;
pike.git/src/program.c:4575:
}
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.)");
return;
}
- #ifdef WITH_FACETS
- /* Check if inherit is a facet inherit. */
- check_for_facet_inherit(p);
- #endif
-
+
if (p == placeholder_program) {
yyerror("Trying to inherit placeholder program (resolver problem).");
return;
}
-
+ if (p->flags & PROGRAM_HAS_C_METHODS) {
+ Pike_compiler->new_program->flags |= PROGRAM_HAS_C_METHODS;
+ }
+
/* 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;
storage_offset=low_add_storage(STORAGE_NEEDED(p),
p->alignment_needed,
pike.git/src/program.c:4715:
if(inherit.parent) add_ref(inherit.parent);
if(name)
{
if(e==0)
{
copy_shared_string(inherit.name,name);
}
else if(inherit.name)
{
- /* FIXME: Wide string handling. */
- struct pike_string *s;
- s=begin_shared_string(inherit.name->len + name->len + 2);
- MEMCPY(s->str,name->str,name->len);
- MEMCPY(s->str+name->len,"::",2);
- MEMCPY(s->str+name->len+2,inherit.name->str,inherit.name->len);
- inherit.name=end_shared_string(s);
+ add_ref(inherit.name);
}
- else
- {
- inherit.name=0;
- }
+
}else{
inherit.name=0;
}
add_to_inherits(inherit);
}
/* 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;
pike.git/src/program.c:4764:
if (fun.id_flags & ID_PUBLIC)
fun.id_flags |= flags & ~ID_PRIVATE;
else
fun.id_flags |= flags;
fun.id_flags |= ID_INHERITED;
add_to_identifier_references(fun);
}
}
+ /*
+ * make this program inherit another program
+ */
+ 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);
+
+ /* Don't do this for OBJECT_PARENT or INHERIT_PARENT inherits.
+ * They may show up here from decode_value().
+ */
+ if (parent_offset >= 42) {
+ if (p->flags & (PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT)) {
+ /* We'll need the parent pointer as well... */
+ struct program_state *state = Pike_compiler;
+
+ /* parent offset was increased by 42 by the caller... */
+ parent_offset -= 42;
+
+ while (state && state->new_program && parent_offset--) {
+ state->new_program->flags |= PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT;
+ state = state->previous;
+ }
+ }
+ }
+ }
+
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:4835:
do_inherit(s,flags,name);
return;
}else{
low_inherit(s->u.program,
0,
numid,
offset+42,
flags,
name);
}
- if (n->token == F_EXTERNAL) {
- struct program *p=program_from_svalue(s);
- if (p->flags & (PROGRAM_NEEDS_PARENT|PROGRAM_NEEDS_PARENT)) {
- /* We'll need the parent pointer as well... */
- struct program_state *state = Pike_compiler;
-
- while (state && (state->new_program->id != n->u.integer.a)) {
- state->new_program->flags |= PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT;
- state = state->previous;
- }
- }
- }
+
}else{
yyerror("Inherit identifier is not a constant program");
return;
}
break;
default:
resolv_class(n);
do_inherit(Pike_sp-1, flags, name);
pop_stack();
pike.git/src/program.c:5126: Inside #if defined(PROFILING)
dummy.opt_flags = 0;
#ifdef PROFILING
dummy.self_time=0;
dummy.num_calls=0;
dummy.recur_depth=0;
dummy.total_time=0;
#endif
if (run_time_type == PIKE_T_FREE) dummy.func.offset = -1;
- if (flags & ID_PRIVATE) flags |= ID_INLINE;
+ 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);
debug_add_to_identifiers(dummy);
pike.git/src/program.c:5174:
free_string(n);
free_type(t);
return ret;
}
/* 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 type_length,
+ int UNUSED(type_length),
INT32 run_time_type,
INT32 flags)
{
int ret;
struct pike_string *n;
struct pike_type *t;
n = make_shared_binary_string(name, name_length);
t = make_pike_type(type);
pike.git/src/program.c:5339:
}
}
if (flags & ID_EXTERN) {
run_time_type = PIKE_T_FREE;
} else {
run_time_type=compile_type_to_runtime_type(type);
switch(run_time_type)
{
- #ifdef AUTO_BIGNUM
+
case T_INT:
- #endif
+
case T_OBJECT:
/* Make place for the object subtype. */
case T_FUNCTION:
case T_PROGRAM:
run_time_type = T_MIXED;
}
}
n=low_define_variable(name,type,flags,
low_add_storage(sizeof_variable(run_time_type),
pike.git/src/program.c:5502:
id=ID_FROM_INT(Pike_compiler->new_program,n);
if(id->func.const_info.offset>=0) {
/* Update the stored constant. */
assign_svalue (&PROG_FROM_INT(Pike_compiler->new_program,n)->
constants[id->func.const_info.offset].sval, c);
} else {
id->run_time_type = (unsigned char) TYPEOF(*c);
id->func.const_info.offset = store_constant(c, 0, 0);
}
free_type(id->type);
- if ((TYPEOF(*c) == T_INT) && !(flags & ID_INLINE)) {
- if (c->u.integer) {
- copy_pike_type(id->type, int_type_string);
- } else {
- copy_pike_type(id->type, zero_type_string);
- }
- } else {
- id->type = get_type_of_svalue(c);
- }
+ if( !(flags & ID_INLINE) )
+ id->type = get_lax_type_of_svalue( c );
+ else
+ id->type = get_type_of_svalue( c );
#ifdef PROGRAM_BUILD_DEBUG
fprintf (stderr, "%.*sstored constant #%d at %d\n",
cc->compilation_depth, "",
n, id->func.const_info.offset);
#endif
}
return n;
}
#ifdef PIKE_DEBUG
pike.git/src/program.c:5540:
#endif
copy_shared_string(dummy.name, name);
dummy.identifier_flags = IDENTIFIER_CONSTANT;
dummy.filename_strno = store_prog_string(cc->lex.current_file);
dummy.linenumber = cc->lex.current_line;
#if 1
if (c) {
#endif
- if ((TYPEOF(*c) == T_INT) && !(flags & ID_INLINE)) {
- if (c->u.integer) {
- copy_pike_type(dummy.type, int_type_string);
- } else {
- copy_pike_type(dummy.type, zero_type_string);
- }
- } else {
- dummy.type = get_type_of_svalue(c);
- }
+ if( !(flags & ID_INLINE) )
+ dummy.type = get_lax_type_of_svalue( c );
+ else
+ dummy.type = get_type_of_svalue( c );
dummy.run_time_type = (unsigned char) TYPEOF(*c);
dummy.func.const_info.offset = store_constant(c, 0, 0);
dummy.opt_flags=OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND;
if(TYPEOF(*c) == PIKE_T_PROGRAM && (c->u.program->flags & PROGRAM_CONSTANT))
dummy.opt_flags=0;
#if 1
}
else {
copy_pike_type(dummy.type, mixed_type_string);
dummy.run_time_type=T_MIXED;
dummy.func.const_info.offset = -1;
dummy.opt_flags=0;
}
#endif
- if (flags & ID_PRIVATE) flags |= ID_INLINE;
+ 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;
#ifdef PROFILING
dummy.self_time=0;
dummy.num_calls=0;
dummy.recur_depth=0;
pike.git/src/program.c:5602:
}
/* not inherited */
if(Pike_compiler->new_program->identifier_references[n].inherit_offset == 0)
{
my_yyerror("Identifier %S defined twice.", name);
return n;
}
/* override */
- if ((overridden = override_identifier (&ref, name)) >= 0) {
+ if ((overridden = override_identifier (&ref, name, 0)) >= 0) {
#ifdef PIKE_DEBUG
struct reference *oref =
Pike_compiler->new_program->identifier_references+overridden;
if((oref->inherit_offset != ref.inherit_offset) ||
(oref->identifier_offset != ref.identifier_offset) ||
((oref->id_flags | ID_USED) != (ref.id_flags | ID_USED))) {
Pike_fatal("New constant overriding algorithm failed!\n");
}
#endif
return overridden;
pike.git/src/program.c:5774:
* if func isn't given, it is supposed to be a prototype.
*/
INT32 define_function(struct pike_string *name,
struct pike_type *type,
unsigned flags,
unsigned function_flags,
union idptr *func,
unsigned opt_flags)
{
struct compilation *c = THIS_COMPILATION;
+ struct program *prog = Pike_compiler->new_program;
struct identifier *funp,fun;
struct reference ref;
struct svalue *lfun_type;
int run_time_type = T_FUNCTION;
INT32 i;
int getter_setter = -1;
int is_setter = 0;
CHECK_COMPILER();
pike.git/src/program.c:5805: Inside #if defined(PROFILING)
#ifdef PROFILING
fun.self_time=0;
fun.num_calls=0;
fun.recur_depth=0;
fun.total_time=0;
#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 */
-
+ /* 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) == '`') &&
((index_shared_string(name, 1) >= 256) ||
isidchar(index_shared_string(name, 1))))) {
/* Getter setter. */
struct pike_string *symbol = NULL;
pike.git/src/program.c:5856:
/* fprintf(stderr, "Got setter: %s\n", name->str); */
gs_type = lfun_setter_type_string;
is_setter = 1;
symbol = string_slice(name, delta, name->len-(delta+1));
symbol_type = get_argument_type(type, 0);
}
if (symbol) {
/* We got a getter or a setter. */
struct reference *ref;
+ int orig_pragmas = c->lex.pragmas;
+ /* Inhibit deprecation warnings during the comparison. */
+ c->lex.pragmas |= ID_NO_DEPRECATION_WARNINGS;
if (!pike_types_le(type, gs_type)) {
int level = REPORT_NOTICE;
if (!match_types(type, gs_type)) {
level = REPORT_ERROR;
} else if (c->lex.pragmas & ID_STRICT_TYPES) {
level = REPORT_WARNING;
}
yytype_report(level, NULL, 0, gs_type,
NULL, 0, type, 0,
"Type mismatch for callback function %S:", name);
}
-
+ c->lex.pragmas = orig_pragmas;
+ if (flags & ID_VARIANT) {
+ my_yyerror("Variants not supported for getter/setters: %S", name);
+ flags &= ~ID_VARIANT;
+ }
i = isidentifier(symbol);
if ((i >= 0) &&
- !((ref = PTR_FROM_INT(Pike_compiler->new_program, i))->
- id_flags & ID_INHERITED)) {
+ !((ref = PTR_FROM_INT(prog, i))->id_flags & ID_INHERITED)) {
/* Not an inherited symbol. */
- struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, i);
+ 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) {
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,
~0, PIKE_T_GET_SET);
- id = ID_FROM_INT(Pike_compiler->new_program, i);
+ id = ID_FROM_INT(prog, i);
/* Paranoia. */
id->func.gs_info.getter = -1;
id->func.gs_info.setter = -1;
getter_setter = i;
}
/* NOTE: The function needs to have the same PRIVATE/INLINE
* behaviour as the variable for overloading to behave
* as expected.
*
* FIXME: Force PRIVATE?
*/
flags |= ID_PROTECTED /* | ID_PRIVATE | ID_INLINE | ID_USED */;
free_type(symbol_type);
free_string(symbol);
}
}
if(IDENTIFIER_IS_C_FUNCTION(function_flags))
- Pike_compiler->new_program->flags |= PROGRAM_HAS_C_METHODS;
+ prog->flags |= PROGRAM_HAS_C_METHODS;
if (Pike_compiler->compiler_pass == 1) {
/* 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);
+ i = isidentifier(name);
+ if (Pike_compiler->compiler_pass == 1) {
+ 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.
+ */
+ prog->identifier_references[i].id_flags |= ID_INHERITED;
+ add_variant_dispatcher(name, type, flags);
+ /* Restore the termination function as a variant. */
+ ref.id_flags |= ID_VARIANT;
+ if (is_variant_dispatcher(prog, i)) {
+ /* The termination function got replaced with
+ * the variant dispatcher.
+ */
+ add_to_identifier_references(ref);
+ } else {
+ /* The termination function is still in the same place. */
+ prog->identifier_references[i].id_flags = ref.id_flags;
+ }
+ } else if (prog->identifier_references[i].inherit_offset) {
+ /* NB: If we are overriding an inherited dispatcher, there's
+ * no need to go via it, since our new dispatcher can
+ * just continue on with the old ones variant functions.
+ */
+ add_variant_dispatcher(name, type, flags);
+ }
+ } else {
+ add_variant_dispatcher(name, type, flags);
+ }
+ i = really_low_find_variant_identifier(name, prog, type,
+ prog->num_identifier_references,
+ SEE_PROTECTED|SEE_PRIVATE);
+ } else if (is_variant_dispatcher(prog, i) &&
+ !prog->identifier_references[i].inherit_offset) {
+ if (!func || (func->c_fun != f_dispatch_variant) ||
+ !IDENTIFIER_IS_C_FUNCTION(function_flags)) {
+ /* FIXME: What about the case
+ *
+ * non-variant prototype;
+ *
+ * variant;
+ *
+ * non-variant definition.
+ */
+ my_yyerror("Overriding variant function %S() with "
+ "non-variant in the same class.",
+ name);
+ }
+ }
+ } else if (i >= 0) {
+ /* Pass 2 */
+ if (is_variant_dispatcher(prog, i)) {
+ if (!func || (func->c_fun != f_dispatch_variant) ||
+ !IDENTIFIER_IS_C_FUNCTION(function_flags)) {
+ /* Variant or variant termination function in second pass. */
+ flags |= ID_VARIANT;
+ i = really_low_find_variant_identifier(name, prog, type,
+ prog->num_identifier_references,
+ SEE_PROTECTED|SEE_PRIVATE);
+ }
+ }
+ }
if(i >= 0)
{
int overridden;
/* already defined */
#ifdef PROGRAM_BUILD_DEBUG
fprintf(stderr, "%.*sexisted as identifier #%d\n",
c->compilation_depth, "", i);
#endif
- funp=ID_FROM_INT(Pike_compiler->new_program, i);
- ref=Pike_compiler->new_program->identifier_references[i];
+ funp = ID_FROM_INT(prog, i);
+ ref = prog->identifier_references[i];
if (funp->identifier_flags & IDENTIFIER_HAS_BODY)
/* Keep this flag. */
function_flags |= IDENTIFIER_HAS_BODY;
if(!(ref.id_flags & ID_INHERITED)) /* not inherited */
{
if( !( IDENTIFIER_IS_FUNCTION(funp->identifier_flags) &&
( (!func || func->offset == -1) || (funp->func.offset == -1))))
{
my_yyerror("Identifier %S defined twice.", name);
if (getter_setter != -1) {
- struct identifier *id = ID_FROM_INT(Pike_compiler->new_program,
- getter_setter);
+ 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) &&
(funp->run_time_type == T_FUNCTION)) {
/* match types against earlier prototype or vice versa */
if(!match_types(type, funp->type))
{
- if (!(flags & ID_VARIANT)) {
+
yytype_report(REPORT_ERROR, NULL, 0,
funp->type,
NULL, 0, type, 0,
"Prototype doesn't match for function %S.", name);
}
}
- }
+
if(func)
funp->func = *func;
#if 0 /* prototypes does not override non-prototypes, ok? */
else
funp->func.offset = -1;
#endif
funp->identifier_flags=function_flags;
funp->run_time_type = run_time_type;
pike.git/src/program.c:6006:
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) &&
+ (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;
+ while ((j = really_low_find_variant_identifier(name, prog, NULL, j,
+ SEE_PROTECTED|SEE_PRIVATE)) != -1) {
+ if (!prog->identifier_references[j].inherit_offset) {
+ /* FIXME: This doesn't catch all cases, and should probably
+ * be moved to a place where it does.
+ */
+ my_yyerror("Overloading variant function %S with non-variant in same class.",
+ name);
+ }
+ prog->identifier_references[j].id_flags |= ID_HIDDEN;
+ }
+ }
if(ref.id_flags & ID_INLINE)
{
#ifdef PROGRAM_BUILD_DEBUG
fprintf(stderr, "%.*sidentifier is local\n",
c->compilation_depth, "");
#endif
/* Hide the previous definition, and make a new definition. */
- Pike_compiler->new_program->identifier_references[i].id_flags |=
- ID_PROTECTED;
+ prog->identifier_references[i].id_flags |= ID_PROTECTED;
goto make_a_new_def;
}
/* Otherwise we alter the existing definition */
#ifdef PROGRAM_BUILD_DEBUG
fprintf(stderr, "%.*saltering the existing definition\n",
c->compilation_depth, "");
#endif
copy_shared_string(fun.name, name);
pike.git/src/program.c:6041:
fun.identifier_flags=function_flags;
if(func)
fun.func = *func;
else
fun.func.offset = -1;
fun.opt_flags = opt_flags;
- ref.identifier_offset=Pike_compiler->new_program->num_identifiers;
+ ref.identifier_offset = prog->num_identifiers;
debug_add_to_identifiers(fun);
}
- if (flags & ID_PRIVATE) flags |= ID_INLINE;
+ if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;
ref.inherit_offset = 0;
ref.id_flags = flags;
- if ((overridden = override_identifier (&ref, name)) >= 0) {
+ if (flags & ID_VARIANT) {
+ ref.id_flags |= ID_USED;
+ prog->identifier_references[i] = ref;
+ overridden = i;
+ } else {
+ overridden = override_identifier(&ref, name, 0);
+ }
+ if (overridden >= 0) {
#ifdef PIKE_DEBUG
- struct reference *oref =
- Pike_compiler->new_program->identifier_references+overridden;
+ struct reference *oref = prog->identifier_references+overridden;
if((oref->inherit_offset != ref.inherit_offset) ||
(oref->identifier_offset != ref.identifier_offset) ||
((oref->id_flags | ID_USED) != (ref.id_flags | ID_USED))) {
fprintf(stderr,
"ref: %d:%d 0x%04x\n"
"got: %d:%d 0x%04x (%d)\n",
ref.inherit_offset, ref.identifier_offset,
ref.id_flags,
oref->inherit_offset,
oref->identifier_offset,
oref->id_flags,
overridden);
Pike_fatal("New function overloading algorithm failed!\n");
}
#endif
if (getter_setter != -1) {
- struct identifier *id = ID_FROM_INT(Pike_compiler->new_program,
- getter_setter);
+ struct identifier *id = ID_FROM_INT(prog, getter_setter);
INT32 old_i = (&id->func.gs_info.getter)[is_setter];
if ((old_i >= 0) && (old_i != overridden)) {
my_yyerror("Multiple definitions for %S.", name);
}
(&id->func.gs_info.getter)[is_setter] = overridden;
}
return overridden;
}
/* NOTE: At this point we already have the identifier in the
* new program, and just need to add the reference.
pike.git/src/program.c:6113:
else
fun.func.offset = -1;
fun.opt_flags = opt_flags;
#ifdef PIKE_DEBUG
if (a_flag > 5) {
fprintf(stderr,
"Adding new function #%d: '%s'\n"
" identifier_flags:0x%02x opt_flags:0x%04x\n",
- Pike_compiler->new_program->num_identifiers,
+ prog->num_identifiers,
fun.name->str,
fun.identifier_flags, fun.opt_flags);
}
#endif /* PIKE_DEBUG */
- i=Pike_compiler->new_program->num_identifiers;
+ i = prog->num_identifiers;
debug_add_to_identifiers(fun);
- if (flags & ID_PRIVATE) flags |= ID_INLINE;
+ if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;
ref.id_flags = flags;
ref.identifier_offset = i;
ref.inherit_offset = 0;
}
ref.run_time_type = PIKE_T_UNKNOWN;
/* Add the reference. */
- i=Pike_compiler->new_program->num_identifier_references;
+ i = prog->num_identifier_references;
add_to_identifier_references(ref);
#ifdef PROGRAM_BUILD_DEBUG
fprintf(stderr, "%.*sadded new definition #%d\n",
c->compilation_depth, "", i);
#endif
if (getter_setter != -1) {
- struct identifier *id = ID_FROM_INT(Pike_compiler->new_program,
- getter_setter);
+ struct identifier *id = ID_FROM_INT(prog, getter_setter);
INT32 old_i = (&id->func.gs_info.getter)[is_setter];
if (old_i >= 0) {
my_yyerror("Multiple definitions for %S.", name);
}
(&id->func.gs_info.getter)[is_setter] = i;
}
return i;
}
pike.git/src/program.c:6257:
* B-+-foo All versions of Pike
* |
* +-A---foo
*
* External lookup of identifier "foo" in E():
*
* F-+-A---foo --- Pike 7.7.33
* |
* +-E---foo Pike 7.7.34 ---
*/
- int really_low_find_shared_string_identifier(struct pike_string *name,
+ PMOD_EXPORT int really_low_find_shared_string_identifier(struct pike_string *name,
struct program *prog,
int flags)
{
struct reference *funp;
struct identifier *fun;
int id, i, depth, last_inh;
#if 0
CDFPRINTF((stderr,"th(%ld) %p Trying to find %s flags=%d\n",
(long)th_self(), prog, name->str, flags));
pike.git/src/program.c:6285:
#endif /* PIKE_DEBUG */
id = -1;
depth = 0;
last_inh = prog->num_inherits;
i = (int)prog->num_identifier_references;
while(i--)
{
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(funp->id_flags & ID_INHERITED)
{
struct inherit *inh = INHERIT_FROM_PTR(prog, funp);
if ((funp->id_flags & ID_PRIVATE) && !(flags & SEE_PRIVATE)) continue;
pike.git/src/program.c:6325:
depth = inh->inherit_level;
id = i;
}
} else {
return i;
}
}
return id;
}
+ 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;
+
+ #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
+
+ #ifdef PIKE_DEBUG
+ if (!prog) {
+ Pike_fatal("really_low_find_variant_identifier(\"%s\", NULL, %p, %d, %d)\n"
+ "prog is NULL!\n", name->str, type, start_pos, flags);
+ }
+ #endif /* PIKE_DEBUG */
+
+ id = -1;
+ depth = 0;
+ last_inh = prog->num_inherits;
+ i = start_pos;
+ #ifdef PIKE_DEBUG
+ if (i > (int)prog->num_identifier_references) {
+ Pike_fatal("really_low_find_variant_identifier(\"%s\", %p, %p, %d, %d):\n"
+ "Start position is past max: %d\n",
+ name->str, prog, type, start_pos, flags,
+ prog->num_identifier_references);
+ }
+ #endif /* PIKE_DEBUG */
+ while(i--)
+ {
+ 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(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;
+ if (inh2->inherit_level >= min_level) {
+ /* Got deeper in the inherit graph */
+ continue;
+ }
+ min_level = inh2->inherit_level;
+ }
+ if (!(inh->inherit_level < min_level)) {
+ continue;
+ }
+ /* Found new identifier on the path from the old identifier to
+ * the root.
+ */
+ }
+ last_inh = funp->inherit_offset;
+ depth = inh->inherit_level;
+ id = i;
+ }
+ } else {
+ CDFPRINTF((stderr, "Found %d\n", i));
+ return i;
+ }
+ }
+ CDFPRINTF((stderr, "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)
+ {
+ struct pike_frame *fp = Pike_fp;
+ struct program *prog = fp->context->prog;
+ struct reference *funp = PTR_FROM_INT(fp->current_program, fp->fun);
+ struct identifier *id = ID_FROM_PTR(fp->current_program, funp);
+ struct pike_string *name = id->name;
+ int fun_num = prog->num_identifier_references;
+ int flags = 0;
+
+ /* NB: The following is mostly to support a potential future
+ * case where a mixed set of protections would cause
+ * multiple dispatchers with the same name to be added
+ * (but different protection (and types)).
+ */
+ if (funp->id_flags & ID_PRIVATE) {
+ flags = SEE_PRIVATE|SEE_PROTECTED;
+ } else if (funp->id_flags & ID_PROTECTED) {
+ flags = SEE_PROTECTED;
+ }
+
+ while ((fun_num = really_low_find_variant_identifier(name, prog, NULL,
+ fun_num, flags)) != -1) {
+ int i;
+ struct pike_type *t;
+ struct pike_type *ret;
+
+ id = ID_FROM_INT(prog, fun_num);
+ add_ref(t = id->type);
+
+ /* Check whether the type is compatible with our arguments. */
+ for (i = 0; i < args; i++) {
+ struct pike_type *cont = check_call_svalue(t, 0, Pike_sp+i - args);
+ free_type(t);
+ if (!(t = cont)) break;
+ }
+ if (!t) continue;
+ ret = new_get_return_type(t, 0);
+ free_type(t);
+ if (!ret) continue;
+ free_type(ret);
+
+ /* Found a function to call! */
+ apply_current(fun_num, args);
+ return;
+ }
+ Pike_error("Invalid arguments to %S()!\n", name);
+ }
+
PMOD_EXPORT int low_find_lfun(struct program *p, ptrdiff_t lfun)
{
struct pike_string *lfun_name = lfun_strings[lfun];
unsigned int flags = 0;
#if 0
struct identifier *id;
#endif
int i =
really_low_find_shared_string_identifier(lfun_name,
dmalloc_touch(struct program *,
pike.git/src/program.c:6483:
return i;
reference_shared_string(str);
add_to_strings(str);
return i;
}
/* NOTE: O(n²)! */
int store_constant(const struct svalue *foo,
int equal,
- struct pike_string *constant_name)
+ struct pike_string *UNUSED(constant_name))
{
struct program_constant tmp;
volatile unsigned int e;
JMP_BUF jmp;
if (SETJMP(jmp)) {
handle_compile_exception ("Error comparing constants.");
/* Assume that if `==() throws an error, the svalues aren't equal. */
e = Pike_compiler->new_program->num_constants;
} else {
pike.git/src/program.c:6548:
*/
struct array *program_indices(struct program *p)
{
int e;
int n = 0;
struct array *res;
for (e = p->num_identifier_references; e--; ) {
struct identifier *id;
if (p->identifier_references[e].id_flags &
- (ID_HIDDEN|ID_PROTECTED|ID_PRIVATE)) {
+ (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)) {
if (id->func.const_info.offset >= 0) {
struct program *p2 = PROG_FROM_INT(p, e);
pike.git/src/program.c:6587:
}
struct array *program_values(struct program *p)
{
int e;
int n = 0;
struct array *res;
for(e = p->num_identifier_references; e--; ) {
struct identifier *id;
if (p->identifier_references[e].id_flags &
- (ID_HIDDEN|ID_PROTECTED|ID_PRIVATE)) {
+ (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)) {
if (id->func.const_info.offset >= 0) {
struct program *p2 = PROG_FROM_INT(p, e);
pike.git/src/program.c:6626:
}
struct array *program_types(struct program *p)
{
int e;
int n = 0;
struct array *res;
for (e = p->num_identifier_references; e--; ) {
struct identifier *id;
if (p->identifier_references[e].id_flags &
- (ID_HIDDEN|ID_PROTECTED|ID_PRIVATE)) {
+ (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)) {
if (id->func.const_info.offset >= 0) {
struct program *p2 = PROG_FROM_INT(p, e);
pike.git/src/program.c:6769:
if (low_program_index_no_free(to, p, e, parent, parent_identifier))
return 1;
}
SET_SVAL(*to, T_INT, NUMBER_UNDEFINED, integer, 0);
return 1;
}
/*
* Line number support routines, now also tells what file we are in.
- *
- * FIXME: Consider storing the filenames in strings (like what is now done
- * for identifiers).
+
*/
/* program.linenumbers format:
*
* Filename entry:
* 1. char 127 (marker).
- * 2. small number Filename string length.
- * 3. char Filename string size shift.
- * 4. string data (Possibly wide) filename string without null
- * termination.
- * Each character is stored in native byte order.
+ * 2. small number Filename entry number in string table.
*
* Line number entry:
* 1. small number Index in program.program (pc).
* Stored as the difference from the pc in the
* closest previous line number entry. The first
* stored entry is absolute.
* 2. small number Line number. Stored in the same way as the pc.
*
* Small number:
* If -127 < n < 127:
pike.git/src/program.c:6958:
*(*ptr)++ = a>>8;
*(*ptr)++ = a;
}
}
void ext_store_program_line (struct program *prog, INT_TYPE line, struct pike_string *file)
{
char *ptr;
#ifdef PIKE_DEBUG
- if (prog->linenumbers)
+ if (prog->linenumbers || prog->strings)
Pike_fatal ("Program already got linenumber info.\n");
if (Pike_compiler->new_program == prog)
Pike_fatal ("Use store_linenumber instead when the program is compiled.\n");
#endif
- ptr = prog->linenumbers = xalloc (1 + 5 + 1 + (file->len << file->size_shift) + 1 + 11);
+ add_ref((prog->strings = xalloc(sizeof(struct pike_string *)))[0] = file);
+ prog->num_strings = 1;
+
+ ptr = prog->linenumbers = xalloc (1 + 1 + 1 + 11);
*ptr++ = 127; /* 1 */
- ext_insert_small_number (&ptr, file->len); /* 5 */
- *ptr++ = (char) file->size_shift; /* 1 */
- MEMCPY (ptr, file->str, file->len << file->size_shift); /* - */
- ptr += file->len << file->size_shift;
+ *ptr++ = 0; /* String #0 */ /* 1 */
*ptr++ = 0; /* PC */ /* 1 */
ext_insert_small_number (&ptr, line); /* 11 */
prog->num_linenumbers = ptr - prog->linenumbers;
}
void store_linenumber(INT_TYPE current_line, struct pike_string *current_file)
{
/* if(!store_linenumbers) Pike_fatal("Fnord.\n"); */
#ifdef PIKE_DEBUG
if(a_flag)
{
INT_TYPE line=0;
INT32 off=0;
- size_t len = 0;
- INT32 shift = 0;
- char *file=0;
+
char *cnt=Pike_compiler->new_program->linenumbers;
-
+ struct pike_string *file = NULL;
if (a_flag > 50) {
fprintf(stderr, "store_linenumber(%ld, \"%s\") at pc %d\n",
(long)current_line, current_file->str,
(INT32) PIKE_PC);
fprintf(stderr, " last_line:%ld last_file:\"%s\"\n",
(long)Pike_compiler->last_line,
Pike_compiler->last_file?Pike_compiler->last_file->str:"");
}
while(cnt < Pike_compiler->new_program->linenumbers +
Pike_compiler->new_program->num_linenumbers)
{
char *start = cnt;
if(*cnt == 127)
{
-
+ int strno;
cnt++;
- len = get_small_number(&cnt);
- shift = *cnt;
- file = ++cnt;
- CHECK_FILE_ENTRY (Pike_compiler->new_program, cnt, len, shift);
- cnt += len<<shift;
+ strno = get_small_number(&cnt);
+ CHECK_FILE_ENTRY (Pike_compiler->new_program, strno);
if (a_flag > 100) {
-
+ file = Pike_compiler->new_program->strings[strno];
fprintf(stderr, "Filename entry:\n"
" len: %"PRINTSIZET"d, shift: %d\n",
- len, shift);
+ file->len, file->size_shift);
}
}
off+=get_small_number(&cnt);
line+=get_small_number(&cnt);
if (a_flag > 100) {
fprintf(stderr, " off: %d, line: %ld\n"
" raw: ",
off, (long)line);
for (;start < cnt; start++) {
fprintf(stderr, "%02x ", *((unsigned char *)start));
}
fprintf(stderr, "\n");
}
}
if(Pike_compiler->last_line != line ||
Pike_compiler->last_pc != off ||
- (Pike_compiler->last_file && file &&
- MEMCMP(Pike_compiler->last_file->str, file, len<<shift)))
+ (file && (Pike_compiler->last_file != file)))
{
Pike_fatal("Line numbering out of whack\n"
" (line : %ld ?= %ld)!\n"
" ( pc : %d ?= %d)!\n"
" (shift: %d ?= %d)!\n"
" (len : %"PRINTSIZET"d ?= %"PRINTSIZET"d)!\n"
" (file : %s ?= %s)!\n",
(long)Pike_compiler->last_line, (long)line,
Pike_compiler->last_pc, off,
Pike_compiler->last_file?Pike_compiler->last_file->size_shift:0,
- shift,
- Pike_compiler->last_file?Pike_compiler->last_file->len:0, len,
+ file?file->size_shift:0,
+ Pike_compiler->last_file?Pike_compiler->last_file->len:0,
+ file?file->len:0,
Pike_compiler->last_file?Pike_compiler->last_file->str:"N/A",
- file?file:"N/A");
+ file?file->str:"N/A");
}
}
#endif
if(Pike_compiler->last_line != current_line ||
Pike_compiler->last_file != current_file)
{
if(Pike_compiler->last_file != current_file)
{
- char *tmp;
- INT32 remain = DO_NOT_WARN((INT32)current_file->len)<<
- current_file->size_shift;
-
+
if(Pike_compiler->last_file) free_string(Pike_compiler->last_file);
add_to_linenumbers(127);
- insert_small_number(DO_NOT_WARN((INT32)current_file->len));
- add_to_linenumbers(current_file->size_shift);
- for(tmp=current_file->str; remain-- > 0; tmp++)
- add_to_linenumbers(*tmp);
+ insert_small_number(store_prog_string(current_file));
copy_shared_string(Pike_compiler->last_file, current_file);
}
insert_small_number(DO_NOT_WARN((INT32)(PIKE_PC-Pike_compiler->last_pc)));
insert_small_number(current_line-Pike_compiler->last_line);
Pike_compiler->last_line = current_line;
Pike_compiler->last_pc = DO_NOT_WARN((INT32)PIKE_PC);
}
}
- #define FIND_PROGRAM_LINE(prog, file, len, shift, line) do { \
+ #define FIND_PROGRAM_LINE(prog, file, line) do { \
char *pos = prog->linenumbers; \
- len = 0; \
- shift = 0; \
+
file = NULL; \
\
if (pos < prog->linenumbers + prog->num_linenumbers) { \
if (*pos == 127) { \
-
+ int strno; \
pos++; \
- len = get_small_number(&pos); \
- shift = *pos; \
- file = ++pos; \
- CHECK_FILE_ENTRY (prog, pos, len, shift); \
- pos += len<<shift; \
+ strno = get_small_number(&pos); \
+ CHECK_FILE_ENTRY (prog, strno); \
+ file = prog->strings[strno]; \
} \
get_small_number(&pos); /* Ignore the offset */ \
line = get_small_number(&pos); \
} \
} while (0)
PMOD_EXPORT struct pike_string *low_get_program_line (struct program *prog,
INT_TYPE *linep)
{
*linep = 0;
if (prog->linenumbers) {
- size_t len;
- INT32 shift;
- char *file;
+ struct pike_string *file;
- FIND_PROGRAM_LINE (prog, file, len, shift, (*linep));
+ FIND_PROGRAM_LINE (prog, file, (*linep));
if (file) {
- struct pike_string *str = begin_wide_shared_string(len, shift);
- memcpy(str->str, file, len<<shift);
- return end_shared_string(str);
+ add_ref(file);
+ return file;
}
}
return NULL;
}
- static char *make_plain_file (char *file, size_t len, INT32 shift, int malloced)
+ static char *make_plain_file (struct pike_string *filename, int malloced)
{
static char buf[1000];
-
+ char *file = filename->str;
+ size_t len = filename->len;
+ INT32 shift = filename->size_shift;
+
if(shift)
{
size_t bufsize;
char *buffer;
PCHARP from=MKPCHARP(file, shift);
size_t ptr=0;
if (malloced) {
- bufsize = len + 1;
+ bufsize = len + 21;
buffer = malloc (bufsize);
}
else {
bufsize = NELEM(buf) - 1;
buffer = buf;
}
for (; len--; INC_PCHARP(from, 1))
{
size_t space;
pike.git/src/program.c:7193:
* can't be touched. It also converts wide strings to ordinary ones
* with escaping.
*/
PMOD_EXPORT char *low_get_program_line_plain(struct program *prog,
INT_TYPE *linep,
int malloced)
{
*linep = 0;
if (prog->linenumbers) {
- char *file;
- size_t len;
- INT32 shift;
- FIND_PROGRAM_LINE (prog, file, len, shift, (*linep));
- if (file) return make_plain_file (file, len, shift, malloced);
+ struct pike_string *file;
+ FIND_PROGRAM_LINE (prog, file, (*linep));
+ if (file)
+ return make_plain_file(file, malloced);
}
return NULL;
}
/* Returns the file where the program is defined. The line of the
* class start is written to linep, or 0 if the program is the top
* level of the file. */
PMOD_EXPORT struct pike_string *get_program_line(struct program *prog,
INT_TYPE *linep)
pike.git/src/program.c:7227:
PMOD_EXPORT struct pike_string *low_get_line (PIKE_OPCODE_T *pc,
struct program *prog,
INT_TYPE *linep)
{
linep[0] = 0;
if (prog->program && prog->linenumbers) {
ptrdiff_t offset = pc - prog->program;
if ((offset < (ptrdiff_t)prog->num_program) && (offset >= 0)) {
- static char *file = NULL;
+ static struct pike_string *file = NULL;
static char *base, *cnt;
static ptrdiff_t off;
static INT32 pid;
static INT_TYPE line;
- static size_t len;
- static INT32 shift;
+
if(prog->linenumbers == base && prog->id == pid && offset > off &&
cnt < prog->linenumbers + prog->num_linenumbers)
goto fromold;
base = cnt = prog->linenumbers;
off=line=0;
pid=prog->id;
file = 0;
while(cnt < prog->linenumbers + prog->num_linenumbers)
{
if(*cnt == 127)
{
-
+ int strno;
cnt++;
- len = get_small_number(&cnt);
- shift = *cnt;
- file = ++cnt;
- CHECK_FILE_ENTRY (prog, cnt, len, shift);
- cnt += len<<shift;
+ strno = get_small_number(&cnt);
+ CHECK_FILE_ENTRY (prog, strno);
+ file = prog->strings[strno];
continue;
}
off+=get_small_number(&cnt);
fromold:
if(off > offset) break;
line+=get_small_number(&cnt);
}
if (cnt >= prog->linenumbers + prog->num_linenumbers) {
/* We reached the end of the table. Make sure
* we get in sync again next time we're called.
*/
base = NULL;
}
linep[0]=line;
if (file) {
- struct pike_string *res = begin_wide_shared_string(len, shift);
- memcpy(res->str, file, len<<shift);
- return end_shared_string(res);
+ add_ref(file);
+ return file;
}
} else {
fprintf(stderr, "Bad offset: pc:%p program:%p (%p)\n",
pc, prog->program, (void *)prog->num_program);
}
} else {
fprintf(stderr, "No program of linenumbers program:%p linenumbers:%p\n",
prog->program, prog->linenumbers);
}
pike.git/src/program.c:7299:
{
linep[0] = 0;
if (prog->program && prog->linenumbers) {
ptrdiff_t offset = pc - prog->program;
if ((offset < (ptrdiff_t)prog->num_program) && (offset >= 0)) {
char *cnt = prog->linenumbers;
INT32 off = 0;
INT_TYPE line = 0;
- char *file = NULL;
- size_t len = 0;
- INT32 shift = 0;
+ struct pike_string *file = NULL;
while(cnt < prog->linenumbers + prog->num_linenumbers)
{
if(*cnt == 127)
{
-
+ int strno;
cnt++;
- len = get_small_number(&cnt);
- shift = *cnt;
- file = ++cnt;
- CHECK_FILE_ENTRY (prog, cnt, len, shift);
- cnt += len<<shift;
+ strno = get_small_number(&cnt);
+ CHECK_FILE_ENTRY (prog, strno);
+ file = prog->strings[strno];
}
off+=get_small_number(&cnt);
if(off > offset) break;
line+=get_small_number(&cnt);
}
linep[0]=line;
- if (file) return make_plain_file (file, len, shift, malloced);
+ if (file)
+ return make_plain_file(file, malloced);
}
}
return NULL;
}
#ifdef PIKE_DEBUG
/* Variants for convenient use from a debugger. */
void gdb_program_line (struct program *prog)
pike.git/src/program.c:7669:
if (s) {
push_string(s);
yyreport(REPORT_ERROR, parser_system_string, 1, "%s");
}
}
pop_stack();
free_svalue(&thrown);
}
- extern void yyparse(void);
+ extern int yyparse(void);
#ifdef PIKE_DEBUG
#define do_yyparse() do { \
struct svalue *save_sp=Pike_sp; \
yyparse(); /* Parse da program */ \
if(save_sp != Pike_sp) { \
Pike_fatal("yyparse() left %"PRINTPTRDIFFT"d droppings on the stack!\n", \
Pike_sp - save_sp); \
} \
}while(0)
pike.git/src/program.c:7696: Inside #if defined(PIKE_DEBUG)
#ifdef PIKE_DEBUG
struct supporter_marker
{
struct supporter_marker *next;
void *data;
int level, verified;
};
- #undef EXIT_BLOCK
- #define EXIT_BLOCK(P)
- #undef COUNT_OTHER
- #define COUNT_OTHER()
-
+
#undef INIT_BLOCK
#define INIT_BLOCK(X) do { (X)->level = (X)->verified = 0; }while(0)
PTR_HASH_ALLOC(supporter_marker, 128);
static int supnum;
#define SNUM(X) (get_supporter_marker((X))->level)
static void mark_supporters(struct Supporter *s)
{
pike.git/src/program.c:8152:
args = 1;
if (TYPEOF(Pike_sp[-1]) != T_OBJECT) {
Pike_error("Bad return value from PikeCompiler().\n");
}
apply(Pike_sp[-1].u.object, "compile", 0);
stack_pop_n_elems_keep_top(args);
}
/*! @decl mixed resolv(string identifier, string filename, @
*! object|void handler)
+ *!
+ *! Look up @[identifier] in the current context.
+ *!
+ *! The default implementation calls the corresponding
+ *! function in the master object.
*/
static void f_compilation_env_resolv(INT32 args)
{
struct pike_string *ident;
struct pike_string *filename;
struct object *handler = NULL;
get_all_args("resolv", args, "%W%W.%O",
&ident, &filename, &handler);
pike.git/src/program.c:8625:
c->p=debug_malloc_pass(end_program());
run_exit(c);
}
static void run_cleanup(struct compilation *c, int delayed)
{
debug_malloc_touch(c);
debug_malloc_touch(c->placeholder);
#if 0 /* FIXME */
+ #ifdef PIKE_THREADS
if (threads_disabled != c->saved_threads_disabled) {
Pike_fatal("compile(): threads_disabled:%d saved_threads_disabled:%d\n",
threads_disabled, c->saved_threads_disabled);
}
-
+ #endif
#endif /* PIKE_DEBUG */
exit_threads_disable(NULL);
CDFPRINTF((stderr,
"th(%ld) %p run_cleanup(): "
"threads_disabled:%d, compilation_depth:%d\n",
(long)th_self(), c->target,
threads_disabled, c->compilation_depth));
if (!c->p)
pike.git/src/program.c:9089:
return;
}
#ifdef PIKE_DEBUG
SET_ONERROR(tmp, fatal_on_error,"Compiler exited with longjump!\n");
#endif
c->flags |= COMPILER_BUSY;
low_init_threads_disable();
+ #ifdef PIKE_THREADS
c->saved_threads_disabled = threads_disabled;
-
+ #endif
init_supporter(& c->supporter,
(supporter_callback *) call_delayed_pass2,
(void *)c);
delay=run_pass1(c);
dependants_ok = call_dependants(& c->supporter, !!c->p );
#ifdef PIKE_DEBUG
/* FIXME */
UNSET_ONERROR(tmp);
pike.git/src/program.c:9666: Inside #if defined(PIKE_DEBUG)
new_frame->context->prog, compilation_program);
}
#endif /* PIKE_DEBUG */
new_frame->fun = new_frame->context->identifier_level + PC_COMPILE_FUN_NUM;
new_frame->expendible = Pike_sp;
new_frame->locals = Pike_sp;
new_frame->save_sp = Pike_sp;
new_frame->save_mark_sp = Pike_mark_sp;
new_frame->mark_sp_base = Pike_mark_sp;
new_frame->args = 0;
+ new_frame->num_args = 0;
new_frame->num_locals = 0;
new_frame->pc = 0;
new_frame->return_addr = 0;
new_frame->scope = 0;
new_frame->save_sp = Pike_sp;
Pike_fp = new_frame;
}
PMOD_EXPORT void enter_compiler(struct pike_string *filename,
INT_TYPE linenumber)
pike.git/src/program.c:9717:
/*! @class CompilerState
*!
*! Keeps the state of a single program/class during compilation.
*!
*! @note
*! Not in use yet!
*/
#define THIS_PROGRAM_STATE ((struct program_state *)(Pike_fp->current_storage))
- static void program_state_event_handler(int event)
+ static void program_state_event_handler(int UNUSED(event))
{
#if 0
struct program_state *c = THIS_PROGRAM_STATE;
switch (event) {
case PROG_EVENT_INIT:
#define INIT
#include "compilation.h"
break;
case PROG_EVENT_EXIT:
#define EXIT
pike.git/src/program.c:10046:
ref_push_mapping(get_builtin_constants());
}
free_svalue(& c->default_module);
move_svalue (&c->default_module, --Pike_sp);
#ifdef PIKE_DEBUG
SET_ONERROR(tmp, fatal_on_error,"Compiler exited with longjump!\n");
#endif
low_init_threads_disable();
+ #ifdef PIKE_THREADS
c->saved_threads_disabled = threads_disabled;
-
+ #endif
init_supporter(& c->supporter,
(supporter_callback *) call_delayed_pass2,
(void *)c);
delay=run_pass1(c);
dependants_ok = call_dependants(& c->supporter, !!c->p );
#ifdef PIKE_DEBUG
/* FIXME */
UNSET_ONERROR(tmp);
pike.git/src/program.c:10145:
}
free_string(name_tmp);
free_type(type_tmp);
return ret;
}
PMOD_EXPORT int quick_add_function(const char *name,
int name_length,
void (*cfun)(INT32),
const char *type,
- int type_length,
+ int UNUSED(type_length),
unsigned flags,
unsigned opt_flags)
{
int ret;
struct pike_string *name_tmp;
struct pike_type *type_tmp;
union idptr tmp;
/* fprintf(stderr,"ADD_FUNC: %s\n",name); */
name_tmp = make_shared_binary_string(name, name_length);
type_tmp = make_pike_type(type);
pike.git/src/program.c:10211: Inside #if defined(PIKE_DEBUG)
}
#endif
}
#endif
#undef THIS
#define THIS ((struct pike_trampoline *)(CURRENT_STORAGE))
struct program *pike_trampoline_program=0;
- static void apply_trampoline(INT32 args)
+ static void apply_trampoline(INT32 UNUSED(args))
{
Pike_error("Internal error: Trampoline magic failed!\n");
}
static void not_trampoline(INT32 args)
{
pop_n_elems(args);
if (!THIS->frame || !THIS->frame->current_object ||
!THIS->frame->current_object->prog) {
push_int(1);
pike.git/src/program.c:10249:
ref_push_function (THIS->frame->current_object, THIS->func);
init_buf(&save_buf);
describe_svalue (sp - 1, 0, 0);
str = complex_free_buf(&save_buf);
pop_stack();
push_string (make_shared_binary_string (str.str, str.len));
free (str.str);
}
- static void init_trampoline(struct object *o)
+ static void init_trampoline(struct object *UNUSED(o))
{
THIS->frame=0;
}
- static void exit_trampoline(struct object *o)
+ static void exit_trampoline(struct object *UNUSED(o))
{
if(THIS->frame)
{
free_pike_scope(THIS->frame);
THIS->frame=0;
}
}
static void gc_check_frame(struct pike_frame *f)
{
pike.git/src/program.c:10277:
if(f->current_object)
debug_gc_check (f->current_object, " as current_object in trampoline frame");
if(f->current_program)
debug_gc_check (f->current_program, " as current_program in trampoline frame");
debug_gc_check_svalues (f->locals, f->num_locals, " in locals of trampoline frame");
if(f->scope && !debug_gc_check (f->scope, " as scope frame of trampoline frame"))
gc_check_frame(f->scope);
}
}
- static void gc_check_trampoline(struct object *o)
+ static void gc_check_trampoline(struct object *UNUSED(o))
{
if (THIS->frame &&
!debug_gc_check (THIS->frame, " as trampoline frame"))
gc_check_frame(THIS->frame);
}
static void gc_recurse_frame(struct pike_frame *f)
{
if(f->current_object) gc_recurse_object(f->current_object);
if(f->current_program) gc_recurse_program(f->current_program);
if(f->flags & PIKE_FRAME_MALLOCED_LOCALS)
gc_recurse_svalues(f->locals,f->num_locals);
if(f->scope) gc_recurse_frame(f->scope);
}
- static void gc_recurse_trampoline(struct object *o)
+ static void gc_recurse_trampoline(struct object *UNUSED(o))
{
if (THIS->frame) gc_recurse_frame(THIS->frame);
}
/* This placeholder should be used
* in the first compiler pass to take the place
* of unknown things
*/
struct program *placeholder_program;
pike.git/src/program.c:10333:
MAKE_CONST_STRING (s, "__placeholder_object");
ref_push_string (s);
}
void init_program(void)
{
size_t i;
struct svalue key;
struct svalue val;
struct svalue id;
- init_program_blocks();
+
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(parser_system_string, "parser");
MAKE_CONST_STRING(type_check_system_string, "type_check");
lfun_ids = allocate_mapping(NUM_LFUNS);
pike.git/src/program.c:10925:
free_type(f->current_type);
if(f->current_return_type)
free_type(f->current_return_type);
Pike_compiler->compiler_frame=f->previous;
dmfree((char *)f);
}
+ PMOD_EXPORT char *get_inherit_storage(struct object *o, int inherit)
+ {
+ if (!o || !o->prog) return NULL;
+ #ifdef PIKE_DEBUG
+ if ((inherit < 0) || (inherit >= o->prog->num_inherits))
+ Pike_fatal("Inherit #%d out of range [0..%d]\n",
+ inherit, o->prog->num_inherits-1);
+ #endif
+ return o->storage + o->prog->inherits[inherit].storage_offset;
+ }
+
#define GET_STORAGE_CACHE_SIZE 1024
static struct get_storage_cache
{
INT32 oid, pid;
ptrdiff_t offset;
} get_storage_cache[GET_STORAGE_CACHE_SIZE];
PMOD_EXPORT ptrdiff_t low_get_storage(struct program *o, struct program *p)
{
INT32 oid, pid;
pike.git/src/program.c:10984: Inside #if defined(_REENTRANT)
#ifdef _REENTRANT
if(d_flag) CHECK_INTERPRETER_LOCK();
#endif
offset= low_get_storage(o->prog, p);
if(offset == -1) return 0;
return o->storage + offset;
}
- struct program *low_program_from_function(struct object *o, INT32 i)
+ PMOD_EXPORT struct program *low_program_from_function(struct object *o, INT32 i)
{
struct svalue *f;
struct program *p;
struct identifier *id;
while(1) {
struct external_variable_context loc;
p = o->prog;
if(!p) return 0;
pike.git/src/program.c:11121:
/* returns 1 if a implements b */
static int low_implements(struct program *a, struct program *b)
{
int e;
struct pike_string *s=findstring("__INIT");
for(e=0;e<b->num_identifier_references;e++)
{
struct identifier *bid;
int i;
- if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN))
+ if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))
continue; /* Skip protected & hidden */
bid = ID_FROM_INT(b,e);
if(s == bid->name) continue; /* Skip __INIT */
i = find_shared_string_identifier(bid->name,a);
if (i == -1) {
if (b->identifier_references[e].id_flags & (ID_OPTIONAL))
continue; /* It's ok... */
#if 0
fprintf(stderr, "Missing identifier \"%s\"\n", bid->name->str);
#endif /* 0 */
pike.git/src/program.c:11202:
if (a->num_identifier_references < b->num_identifier_references) {
struct program *tmp = a;
a = b;
b = tmp;
}
for(e=0;e<b->num_identifier_references;e++)
{
struct identifier *bid;
int i;
- if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN))
+ if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))
continue; /* Skip protected & hidden */
/* FIXME: What if they aren't protected & hidden in a? */
bid = ID_FROM_INT(b,e);
if(s == bid->name) continue; /* Skip __INIT */
i = find_shared_string_identifier(bid->name,a);
if (i == -1) {
continue; /* It's ok... */
}
pike.git/src/program.c:11324:
}
SET_CYCLIC_RET(1);
a_file = get_program_line(a, &a_line);
b_file = get_program_line(b, &b_line);
for(e=0;e<b->num_identifier_references;e++)
{
struct identifier *bid;
int i;
- if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN))
+ if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))
continue; /* Skip protected & hidden */
/* FIXME: What if they aren't protected & hidden in a? */
bid = ID_FROM_INT(b,e);
if(s == bid->name) continue; /* Skip __INIT */
i = find_shared_string_identifier(bid->name,a);
if (i == -1) {
continue; /* It's ok... */
}
pike.git/src/program.c:11386:
}
SET_CYCLIC_RET(1);
a_file = get_program_line(a, &a_line);
b_file = get_program_line(b, &b_line);
for(e=0;e<b->num_identifier_references;e++)
{
struct identifier *bid;
int i;
- if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN))
+ if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))
continue; /* Skip protected & hidden */
bid = ID_FROM_INT(b,e);
if(s == bid->name) continue; /* Skip __INIT */
i = find_shared_string_identifier(bid->name,a);
if (i == -1) {
INT_TYPE bid_line = b_line;
struct pike_string *bid_file;
if (b->identifier_references[e].id_flags & (ID_OPTIONAL))
continue; /* It's ok... */
bid_file = get_identifier_line(b, e, &bid_line);
pike.git/src/program.c:11433:
bid->name);
}
continue;
}
}
free_string(b_file);
free_string(a_file);
END_CYCLIC();
}
+ /* FIXME: Code duplication of yyexplain_not_compatible() above! */
+ /* Explains why a is not compatible with b */
+ void string_builder_explain_not_compatible(struct string_builder *s,
+ struct program *a,
+ struct program *b)
+ {
+ int e;
+ struct pike_string *init_string = findstring("__INIT");
+ int res = 1;
+ DECLARE_CYCLIC();
+
+ /* Optimize the loop somewhat */
+ if (a->num_identifier_references < b->num_identifier_references) {
+ struct program *tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ if (BEGIN_CYCLIC(a, b)) {
+ END_CYCLIC();
+ return;
+ }
+ SET_CYCLIC_RET(1);
+
+ for(e=0;e<b->num_identifier_references;e++)
+ {
+ struct identifier *bid;
+ int i;
+ if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))
+ continue; /* Skip protected & hidden */
+
+ /* FIXME: What if they aren't protected & hidden in a? */
+
+ bid = ID_FROM_INT(b,e);
+ if(init_string == bid->name) continue; /* Skip __INIT */
+ i = find_shared_string_identifier(bid->name,a);
+ if (i == -1) {
+ continue; /* It's ok... */
+ }
+
+ /* Note: Uses weaker check for constant integers. */
+ if(((bid->run_time_type != PIKE_T_INT) ||
+ (ID_FROM_INT(a, i)->run_time_type != PIKE_T_INT)) &&
+ !match_types(ID_FROM_INT(a,i)->type, bid->type)) {
+ ref_push_program(a);
+ ref_push_program(b);
+ ref_push_type_value(ID_FROM_INT(a, i)->type);
+ ref_push_type_value(bid->type);
+ string_builder_sprintf(s,
+ "Identifier %S in %O is incompatible with "
+ "the same in %O.\n"
+ "Expected: %O\n"
+ "Got : %O\n",
+ bid->name, Pike_sp-4,
+ Pike_sp-3,
+ Pike_sp-2,
+ Pike_sp-1);
+ pop_n_elems(4);
+ }
+ }
+ END_CYCLIC();
+ return;
+ }
+
+ /* FIXME: code duplication of yyexplain_not_implements() above! */
+ /* Explains why a does not implement b */
+ void string_builder_explain_not_implements(struct string_builder *s,
+ struct program *a,
+ struct program *b)
+ {
+ int e;
+ struct pike_string *init_string = findstring("__INIT");
+ DECLARE_CYCLIC();
+
+ if (BEGIN_CYCLIC(a, b)) {
+ END_CYCLIC();
+ return;
+ }
+ SET_CYCLIC_RET(1);
+
+ for(e=0;e<b->num_identifier_references;e++)
+ {
+ struct identifier *bid;
+ int i;
+ if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))
+ continue; /* Skip protected & hidden */
+ bid = ID_FROM_INT(b,e);
+ if(init_string == bid->name) continue; /* Skip __INIT */
+ i = find_shared_string_identifier(bid->name,a);
+ if (i == -1) {
+ if (b->identifier_references[e].id_flags & (ID_OPTIONAL))
+ continue; /* It's ok... */
+ ref_push_type_value(bid->type);
+ string_builder_sprintf(s,
+ "Missing identifier %O %S.\n",
+ Pike_sp-1, bid->name);
+ pop_stack();
+ continue;
+ }
+
+ if (!pike_types_le(bid->type, ID_FROM_INT(a, i)->type)) {
+ ref_push_type_value(bid->type);
+ ref_push_type_value(ID_FROM_INT(a, i)->type);
+ if(!match_types(ID_FROM_INT(a,i)->type, bid->type)) {
+ string_builder_sprintf(s,
+ "Type of identifier %S does not match.\n"
+ "Expected: %O.\n"
+ "Got : %O.\n",
+ bid->name,
+ Pike_sp-2,
+ Pike_sp-1);
+ } else {
+ string_builder_sprintf(s,
+ "Type of identifier %S is not strictly compatible.",
+ "Expected: %O.\n"
+ "Got : %O.\n",
+ bid->name,
+ Pike_sp-2,
+ Pike_sp-1);
+ }
+ pop_n_elems(2);
+ continue;
+ }
+ }
+ END_CYCLIC();
+ }
+
PMOD_EXPORT void *parent_storage(int depth)
{
struct external_variable_context loc;
loc.o = Pike_fp->current_object;
loc.parent_identifier = 0;
loc.inherit = Pike_fp->context;
find_external_context(&loc, depth);