diff --git a/src/builtin_functions.c b/src/builtin_functions.c index de9c606378997a32f07efa274482658cd53f867c..816d4a82be3079a263fdd6806c05a18aaecdd57b 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: builtin_functions.c,v 1.199 1999/11/01 13:39:18 mirar Exp $"); +RCSID("$Id: builtin_functions.c,v 1.200 1999/11/04 15:42:51 grubba Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -1881,7 +1881,16 @@ void f_compile(INT32 args) if(sp[-args].type != T_STRING) SIMPLE_BAD_ARG_ERROR("compile", 1, "string"); - p=compile(sp[-args].u.string); + if ((args > 1) && (sp[1-args].type != T_OBJECT) && + (sp[1-args].type != T_INT)) { + SIMPLE_BAD_ARG_ERROR("compile", 2, "object"); + } + + if ((args > 1) && (sp[1-args].type == T_OBJECT)) { + p = compile(sp[-args].u.string, sp[1-args].u.object); + } else { + p = compile(sp[-args].u.string, master_object); + } pop_n_elems(args); push_program(p); } @@ -2453,6 +2462,131 @@ static void f_mktime (INT32 args) #endif +/* Parse a sprintf/sscanf-style format string */ +static int low_parse_format(p_wchar0 *s, int slen) +{ + int i; + int offset = 0; + int num_percent_percent = 0; + struct svalue *old_sp = sp; + + for (i=offset; i < slen; i++) { + if (s[i] == '%') { + int j; + if (i != offset) { + push_string(make_shared_binary_string0(s + offset, i)); + if ((sp != old_sp+1) && (sp[-2].type == T_STRING)) { + /* Concat. */ + f_add(2); + } + } + + for (j = i+1;j<slen;j++) { + int c = s[j]; + + switch(c) { + /* Flags */ + case '!': + case '#': + case '$': + case '-': + case '/': + case '0': + case '=': + case '>': + case '@': + case '^': + case '_': + case '|': + continue; + /* Padding */ + case ' ': + case '\'': + case '+': + case '~': + break; + /* Attributes */ + case '.': + case ':': + case ';': + continue; + /* Attribute value */ + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + continue; + /* Specials */ + case '%': + push_constant_text("%"); + if ((sp != old_sp+1) && (sp[-2].type == T_STRING)) { + /* Concat. */ + f_add(2); + } + break; + case '{': + i = j + 1 + low_parse_format(s + j + 1, slen - (j+1)); + f_aggregate(1); + if ((i + 2 >= slen) || (s[i] != '%') || (s[i+1] != '}')) { + error("parse_format(): Expected %%}.\n"); + } + i += 2; + break; + case '}': + f_aggregate(sp - old_sp); + return i; + /* Set */ + case '[': + + break; + /* Argument */ + default: + break; + } + break; + } + if (j == slen) { + error("parse_format(): Unterminated %%-expression.\n"); + } + offset = i = j; + } + } + + if (i != offset) { + push_string(make_shared_binary_string0(s + offset, i)); + if ((sp != old_sp+1) && (sp[-2].type == T_STRING)) { + /* Concat. */ + f_add(2); + } + } + + f_aggregate(sp - old_sp); + return i; +} + +static void f_parse_format(INT32 args) +{ + struct pike_string *s = NULL; + struct array *a; + int len; + + get_all_args("parse_format", args, "%W", &s); + + len = low_parse_format(STR0(s), s->len); + if (len != s->len) { + error("parse_format(): Unexpected %%} in format string at offset %d\n", + len); + } +#ifdef PIKE_DEBUG + if (sp[-1].type != T_ARRAY) { + fatal("parse_format(): Unexpected result from low_parse_format()\n"); + } +#endif /* PIKE_DEBUG */ + a = (--sp)->u.array; + debug_malloc_touch(a); + + pop_n_elems(args); + push_array(a); +} + /* Check if the string s[0..len[ matches the glob m[0..mlen[ */ static int does_match(struct pike_string *s,int j, @@ -5023,8 +5157,9 @@ void init_builtin_efuns(void) /* function(string...:string) */ ADD_EFUN("combine_path",f_combine_path,tFuncV(tNone,tStr,tStr),0); -/* function(string,mixed...:program) */ - ADD_EFUN("compile",f_compile,tFuncV(tStr,tMix,tPrg),OPT_EXTERNAL_DEPEND); +/* function(string,object|void,mixed...:program) */ + ADD_EFUN("compile", f_compile, tFuncV(tStr tOr(tObj, tVoid),tMix,tPrg), + OPT_EXTERNAL_DEPEND); /* function(1=mixed:1) */ ADD_EFUN("copy_value",f_copy_value,tFunc(tSetvar(1,tMix),tVar(1)),0);