diff --git a/lib/modules/Program.pmod b/lib/modules/Program.pmod index 8661cc9f890bc77cc5a577a6c20f1bafcc4e31a8..d6bfb10e89608898f7403e1ffcd3876edbed6729 100644 --- a/lib/modules/Program.pmod +++ b/lib/modules/Program.pmod @@ -4,7 +4,15 @@ constant inherit_list = __builtin.inherit_list; constant inherits = __builtin.program_inherits; constant implements = __builtin.program_implements; -constant defined = __builtin.program_defined; + +// documented in the C-code. +string defined(program x,string|void y) +{ + if( !y ) + return __builtin.program_defined(x); + return __builtin.program_identifier_defined(x,y); +} + //! @fixme //! Document this function. diff --git a/src/builtin_functions.c b/src/builtin_functions.c index b7d893ee28d488ef853f42b1dd538902581d4886..05189fa8e723a8f982083bb1ba32ceace5707469 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -9287,6 +9287,89 @@ void f_enumerate(INT32 args) /*! @module Program */ + +/*! @decl string defined(program x, string identifier) + *! + *! Returns a string with filename and linenumber where @[idenfifier] + *! in @[x] was defined. + *! + *! Returns @expr{0@} (zero) when no line can be found, e.g. for + *! builtin functions. + *! + *! If @[idenfier] can not be found in @[x] this function returns + *! where the program is defined. + */ +PMOD_EXPORT void f_program_identifier_defined(INT32 args) +{ + struct program *p; + struct pike_string *ident; + struct program *id_prog, *p2; + struct identifier *id; + INT_TYPE line; + INT_TYPE offset; + struct pike_string *file = NULL; + + if( !(p = program_from_svalue(Pike_sp-args)) ) + Pike_error("Illegal argument 1 to defined(program,string)\n"); + + if( Pike_sp[-args+1].type != PIKE_T_STRING ) + Pike_error("Illegal argument 2 to defined(program,string)\n"); + else + ident = Pike_sp[-args+1].u.string; + + if( (offset = find_shared_string_identifier( ident, p )) == -1 ) + { + INT_TYPE line; + struct pike_string *tmp = low_get_program_line(p, &line); + + pop_n_elems(args); + + if (tmp) + { + push_string(tmp); + if(line >= 1) + { + push_constant_text(":"); + push_int(line); + f_add(3); + } + } + else + push_int(0); + return; + } + + id = ID_FROM_INT(p, offset); + id_prog = PROG_FROM_INT (p, offset); + + if(IDENTIFIER_IS_PIKE_FUNCTION( id->identifier_flags ) && + id->func.offset != -1) + file = low_get_line(id_prog->program + id->func.offset, id_prog, &line); + else if (IDENTIFIER_IS_CONSTANT (id->identifier_flags) && + id->func.const_info.offset >= 0 && + (p2 = program_from_svalue (&id_prog->constants[id->func.const_info.offset].sval))) + file = low_get_program_line (p2, &line); + else + /* The program line is better than nothing for C functions. */ + file = low_get_program_line (p, &line); + + if (file) + { + pop_n_elems(args); + if (line) { + push_string(file); + push_constant_text(":"); + push_int(line); + f_add(3); + } + else + push_string (file); + return; + } + pop_n_elems(args); + push_int(0); +} + /*! @decl array(program) inherit_list(program p) *! *! Returns an array with the programs that @[p] has inherited. @@ -10097,6 +10180,8 @@ void init_builtin_efuns(void) ADD_FUNCTION2("inherit_list", f_inherit_list, tFunc(tOr(tObj,tPrg(tObj)),tArr(tPrg(tObj))), 0, OPT_TRY_OPTIMIZE); + ADD_FUNCTION2("program_identifier_defined", f_program_identifier_defined, + tFunc(tOr(tObj,tPrg(tObj)) tString,tString), 0, OPT_TRY_OPTIMIZE); ADD_FUNCTION2("function_defined", f_function_defined, tFunc(tFunction,tString), 0, OPT_TRY_OPTIMIZE);