diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-05-21 22:01:29 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-05-21 22:01:29 +0000 |
commit | 2c28da5e5902dde2a7f7dcb04c69d5eff088b2fe (patch) | |
tree | 4e3e9fad417b4864dfeac4613a677a98681cb572 | |
parent | 48c99630a93560a4c40efdbe955e9a1e395a6162 (diff) | |
download | mailfromd-2c28da5e5902dde2a7f7dcb04c69d5eff088b2fe.tar.gz mailfromd-2c28da5e5902dde2a7f7dcb04c69d5eff088b2fe.tar.bz2 |
Arguments are passed in the same order for both built-in and MFL-level
functions.
If a builtin takes optional arguments, the actual number of arguments is
passed in a hidden first argument. This allows to discern between zero
arguments (emtpy strings) and absent arguments.
git-svn-id: file:///svnroot/mailfromd/trunk@1461 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r-- | ChangeLog | 20 | ||||
-rw-r--r-- | TODO | 29 | ||||
-rw-r--r-- | src/bi_string.m4 | 2 | ||||
-rw-r--r-- | src/drivers.c | 16 | ||||
-rw-r--r-- | src/gram.y | 18 | ||||
-rw-r--r-- | src/mailfromd.h | 2 | ||||
-rw-r--r-- | src/main.c | 6 | ||||
-rw-r--r-- | src/snarf.m4 | 156 |
8 files changed, 173 insertions, 76 deletions
@@ -1,3 +1,23 @@ +2007-05-22 Sergey Poznyakoff <gray@gnu.org.ua> + + * src/snarf.m4 (__mf_has_optarg): New macro + (__mf_defined_argname,__mf_defined_argnames) + (mf_defined_argnames,mf_argpos): New macro + (__mf_optarg_defined,__mf_defined,MF_DEFINED,MF_OPTVAL) + (__mf_c_arglist,mf_c_arglist) + Fix typo (m4_errprint) + * src/gram.y: Arguments are passed the in the same order for both + built-in and MFL-level functions. + (print_node_list_reverse): New function + * src/bi_string.m4 (substr): Bugfix: Use MF_DEFINED + * src/drivers.c (print_type_builtin): Use print_node_list_reverse + (code_type_builtin): Pass total number of arguments in a hidden + argument if the built-in takes optional parameters. + * src/mailfromd.h: Fix typo + * src/main.c: Make sure logging goes to stderr for --dump-* + options. + * TODO: Update + 2007-05-20 Sergey Poznyakoff <gray@gnu.org.ua> * src/lex.l: Fix input file location tracing @@ -10,9 +10,6 @@ Mailfromd TODO list. ** Implement still more string functions -* If an optional numeric argument to a built-in function has value 0 it is -impossible to tell whether it was given explicitely or omitted. - * Provide a library facility: 1. Compile mailfromd source into a position-independent code: @@ -29,6 +26,32 @@ impossible to tell whether it was given explicitely or omitted. mailfromd -lfile +* Convert database support to MFL + +* Implement a separate configuration file, to get rid of `#pragma option' in +filter sources. + +* Provide a mechanism to catch exceptions for a given compound statement or +expression. + +* Implement nested functions and lambdas: + + set var lambda(string x) returns string + do + ... + done + apply(%var, "foo") + +or: + + apply(lambda(string x) returns string + do + ... + done, + "foo") + +This can then be used to implement the previous topic. + Local variables: mode: outline diff --git a/src/bi_string.m4 b/src/bi_string.m4 index 91f4fb83..8906d083 100644 --- a/src/bi_string.m4 +++ b/src/bi_string.m4 @@ -78,7 +78,7 @@ MF_DEFUN(substr, STRING, STRING string, NUMBER start, OPTIONAL, NUMBER nbytes) MF_ASSERT(start >= 0, mf_range, _("Argument out of range: start=%ld"), start); - if (nbytes == 0) + if (!MF_DEFINED(nbytes)) nbytes = len - start; MF_ASSERT(nbytes >= 0, mf_range, _("Argument out of range: start=%ld, len=%ld"), start, len); diff --git a/src/drivers.c b/src/drivers.c index 54d4225e..89fbd826 100644 --- a/src/drivers.c +++ b/src/drivers.c @@ -994,7 +994,7 @@ print_type_builtin(NODE *node, int level) { print_level(level); printf("BUILTIN %s\n", node->v.builtin.builtin->name); - print_node_list(node->v.builtin.args, level+1); + print_node_list_reverse(node->v.builtin.args, level+1); } void @@ -1044,14 +1044,16 @@ code_type_builtin(NODE *node, struct locus **old_locus) int i; const struct builtin *bp = node->v.builtin.builtin; struct literal *s; - - for (p = node->v.builtin.args, i = 0; p; p = p->next, i++) + + /* Pass arguments */ + for (p = node->v.builtin.args, i = 0; p; p = p->next, i++) code_node(p); - for (; i < bp->parmcount; i++) { + if (bp->optcount) { + /* Pass the number of actual arguments in a hidden arg */ code_op(opcode_push); - code_immediate(0); + code_immediate(i); } - + MARK_LOCUS(); code_op(opcode_builtin); s = literal_lookup(node->v.builtin.builtin->name); @@ -1492,7 +1494,7 @@ print_type_call(NODE *node, int level) { print_level(level); printf("CALL %s\n", node->v.call.func->name); - print_node_list(node->v.call.args, level+1); + print_node_list_reverse(node->v.call.args, level+1); } void @@ -1458,8 +1458,9 @@ funcall : BUILTIN '(' arglist ')' } else { $$ = alloc_node(node_type_builtin, get_locus()); $$->v.builtin.builtin = $1; - $$->v.builtin.args = cast_arg_list($3.head, - $1->parmtype); + $$->v.builtin.args = + reverse(cast_arg_list($3.head, + $1->parmtype)); } } | BUILTIN '(' ')' @@ -2123,6 +2124,15 @@ print_node_list(NODE *node, int level) print_node(node, level); } +static void +print_node_list_reverse(NODE *node, int level) +{ + if (node) { + print_node_list_reverse(node->next, level); + print_node(node, level); + } +} + int function_enumerator(void *sym, void *data) { @@ -3120,7 +3130,7 @@ create_on_node(NODE *sel, struct case_stmt *cases) case node_type_builtin: base_name = sel->v.builtin.builtin->name; argc = sel->v.builtin.builtin->parmcount; - args = reverse(sel->v.builtin.args); + args = sel->v.builtin.args; ptypes = sel->v.builtin.builtin->parmtype; rettype = sel->v.builtin.builtin->rettype; break; @@ -3195,7 +3205,7 @@ create_on_node(NODE *sel, struct case_stmt *cases) np->v.node = sel; /* FIXME: create a copy */ switch (np->v.node->type) { case node_type_builtin: - np->v.node->v.builtin.args = head; + np->v.node->v.builtin.args = reverse(head); break; case node_type_call: np->v.node->v.call.args = reverse(head); diff --git a/src/mailfromd.h b/src/mailfromd.h index 0693f818..f48cb660 100644 --- a/src/mailfromd.h +++ b/src/mailfromd.h @@ -358,7 +358,7 @@ struct concat_node { /* Concatenation of arg[0] and arg[1] */ NODE *arg[2]; }; -struct asgn_node { /* Assignement */ +struct asgn_node { /* Assignment */ struct variable *var; /* Variable */ size_t nframes; /* Number of frames to skip */ NODE *node; /* Expression to be evaluated and assigned @@ -1209,26 +1209,32 @@ parse_opt (int key, char *arg, struct argp_state *state) case OPTION_DUMP_CODE: script_dump_code = 1; + log_to_stderr = 1; break; case OPTION_DUMP_GRAMMAR_TRACE: script_ydebug = 1; + log_to_stderr = 1; break; case OPTION_DUMP_LEX_TRACE: yy_flex_debug = 1; + log_to_stderr = 1; break; case OPTION_DUMP_MACROS: script_dump_macros = 1; + log_to_stderr = 1; break; case OPTION_DUMP_TREE: script_dump_tree = 1; + log_to_stderr = 1; break; case OPTION_DUMP_XREF: script_dump_xref = 1; + log_to_stderr = 1; break; case OPTION_EXPIRE: diff --git a/src/snarf.m4 b/src/snarf.m4 index 896ccbcf..1586999c 100644 --- a/src/snarf.m4 +++ b/src/snarf.m4 @@ -62,50 +62,12 @@ $1, [<OPTIONAL>], [<mf_typelist(m4_shift($@))>], [<mf_argtype($1), >]m4_dnl [<mf_typelist(m4_shift($@))>])>]) -/* __mf_optarg_defined_p(TYPE,NAME) -- Return a C conditional expression - * that yields true if the built-in function parameter NAME of type TYPE - * is defined. +/* __mf_has_optarg(ARGS..) -- return 1 if ARGS contain OPTIONAL keyword, and + * 0 otherwise */ -m4_define([<__mf_optarg_defined_p>], -[<m4_ifelse($1,STRING,$2 && $2[0],$1,NUMBER,$2,m4_dnl -$2)>]) - -/* __mf_optarg_defined(NAME, ARGLIST...) -- Scan ARGLIST for the definition - * of the built-in function parameter NAME, and return a C conditional - * expression that yields true if it is defined. - * ARGLIST is the list of parameter declarations in the form: - * TYPE1,NAME1,TYPE2,NAME2... - */ -m4_define([<__mf_optarg_defined>], -[<m4_ifelse($2,, [<m4_errpirnt(m4___file__:m4___line__: [<$1: no such argument ->])>],m4_dnl -$2, [<OPTIONAL>], [<__mf_optarg_defined($1, m4_shift(m4_shift($@)))>],m4_dnl -$1,$3,[<__mf_optarg_defined_p($2,$3)>],m4_dnl -[<__mf_optarg_defined($1, m4_shift(m4_shift(m4_shift($@))))>])>]) - -/* __mf_defined(NAME, ARGS...) -- Scan ARGS... for the definition - * of the built-in function parameter NAME, and return a C conditional - * expression that yields true if it is defined. - * ARGS are parameter declarations in the form: - * TYPE NAME - */ -m4_define([<__mf_defined>], -[<__mf_optarg_defined(m4_patsubst([<$*>], [<[ ][ ]*>], [<,>]))>]) - -/* MF_DEFINED(NAME) -- Return a C conditional expression - * that yields true if the parameter NAME is defined. - */ -m4_define([<MF_DEFINED>], -[<m4_ifdef([<__MF_ARGLIST__>],([<__mf_defined($1, __MF_ARGLIST__)>]),m4_dnl -[<m4_errpirnt(m4___file__:m4___line__: [<MF_DEFINED used out of functional context>])>])>]) - -/* MF_OPTVAL(NAME[, DEFVAL]) -- If the parameter NAME is defined, return - * its value, otherwise return DEFVAL or 0 - */ -m4_define([<MF_OPTVAL>], -[<m4_ifdef([<__MF_ARGLIST__>],m4_dnl -[<m4_ifelse([<$2>],,$1,(MF_DEFINED($1) ? $1 : $2))>],m4_dnl -[<m4_errpirnt(m4___file__:m4___line__: [<MF_OPTVAL used out of functional context>])>])>]) +m4_define([<__mf_has_optarg>],m4_dnl +[<m4_ifelse($1, , 0,$1,[<OPTIONAL>], 1,[<m4_dnl +__mf_has_optarg(m4_shift($@))>])>]) /* __mf_c_type(TYPE) -- return a C type corresponding to the Mailfromd one */ @@ -127,18 +89,17 @@ m4_define([<__mf_c_getarg>],m4_dnl m4_define([<mf_c_argdcl>],m4_dnl [<m4_regexp([<$1>],[<\(\w+\)\W+\(\w+\)>],[<__mf_c_type(\1)>] \2 = ([<__mf_c_type(\1)>]) [<__mf_c_getarg(\1)>])>]) -/* __mf_c_arglist(ARGC, NARG, LIST) -- translate Mailfromd declaration list +/* __mf_c_arglist(NARG, LIST) -- translate Mailfromd declaration list * into a set of corresponding C variable declarations with initializations. * Arguments: - * ARGC -- number of arguments in LIST * NARG -- ordinal number of the first variable in LIST * LIST -- comma-separated list of Mailfromd declarations */ m4_define([<__mf_c_arglist>],m4_dnl -[<m4_ifelse($3, , ,$3,[<OPTIONAL>],[<m4_dnl -__mf_c_arglist($1, $2, m4_shift(m4_shift(m4_shift($@))))>], -[<mf_c_argdcl($3)(env, m4_eval($1 - $2)); - __mf_c_arglist($1, m4_incr($2), m4_shift(m4_shift(m4_shift($@))))>])>]) +[<m4_ifelse($2, , ,$2,[<OPTIONAL>],[<m4_dnl +__mf_c_arglist($1, m4_shift(m4_shift($@)))>], +[<mf_c_argdcl($2)(env, m4_eval($1)); + __mf_c_arglist(m4_incr($1), m4_shift(m4_shift($@)))>])>]) /* mf_c_arglist(LIST) -- translate Mailfromd declaration list * into a set of corresponding C variable declarations with initializations. @@ -146,16 +107,25 @@ __mf_c_arglist($1, $2, m4_shift(m4_shift(m4_shift($@))))>], * variables. * E.g.: * mf_c_arglist(STRING a, NUMBER n) => - * char *a = (char*)get_string_arg(env, 1); - * long n = (long)get_numeric_arg(env, 0); + * char *a = (char*)get_string_arg(env, 0); + * long n = (long)get_numeric_arg(env, 1); * adjust_stack(env, 2); + * + * Or, if the builtin takes optional parameters: + * + * mf_c_arglist(STRING a, NUMBER n) => + * long __bi_argcnt = (long)get_numeric_arg(env, 0); + * char *a = (char*)get_string_arg(env, 1); + * long n = (long)get_numeric_arg(env, 2); + * adjust_stack(env, __bi_argcnt); */ m4_define([<mf_c_arglist>],m4_dnl [< -m4_pushdef([<__ARGC__>], mf_argcount($@))m4_dnl -__mf_c_arglist(__ARGC__, 1, $@) - adjust_stack(env, __ARGC__); -m4_popdef([<__ARGC__>])m4_dnl +m4_pushdef([<__ARG1__>], [<__mf_has_optarg($@)>]) +m4_ifelse(__ARG1__,0,,[<long __bi_argcnt = (long)get_numeric_arg(env, 0);>]) +__mf_c_arglist(__ARG1__, $@) + adjust_stack(env, m4_ifelse(__ARG1__,0,mf_argcount($@),__bi_argcnt)); +m4_popdef([<__ARG1__>])m4_dnl >]) /* __mf_printf_type(TYPE) -- translate the Mailfromd data type TYPE into the @@ -192,12 +162,78 @@ m4_define([<mf_argnames>],m4_dnl $1,[<OPTIONAL>],[<mf_argnames(m4_shift($@))>],m4_dnl [<__mf_argname($1), mf_argnames(m4_shift($@))>])>]) +m4_define([<__mf_defined_argname>],m4_dnl +[<m4_ifelse($1,1,[<m4_dnl +MF_OPTVAL(__mf_argname($2),m4_ifelse(mf_argtype($2),[<STRING>],"",0))>],m4_dnl +[<__mf_argname($2)>])>]) + +m4_define([<__mf_defined_argnames>],m4_dnl +[<m4_ifelse($#,2, [<__mf_defined_argname($1,$2)>],m4_dnl +$2,[<OPTIONAL>],[<__mf_defined_argnames(1,m4_shift(m4_shift($@)))>],m4_dnl +[<__mf_defined_argname($1,$2), m4_dnl +__mf_defined_argnames($1,m4_shift(m4_shift($@)))>])>]) + +m4_define([<mf_defined_argnames>],m4_dnl +[<__mf_defined_argnames(0,$@)>]) + +/* __mf_argpos(POS,NEEDLE,STACK...) - Return position at which NEEDLE occurs in + * STACK + * Arguments: + * POS - Current position + * NEEDLE - String to find + * STACK - Argument list + * Example: + * __mf_argpos(0, x, a, b, x) => 2 + */ +m4_define([<__mf_argpos>],m4_dnl +[<m4_ifelse($2,$3,$1,$3,,[<m4_errprint(m4___file__:m4___line__: No such variable >]$2[< +)>],[<__mf_argpos(m4_incr($1), $2, m4_shift(m4_shift(m4_shift($@))))>])>]) + +/* mf_argpos(ARG, TYPE1 ARG1, TYPE2 ARG2 ...) - Return (zero-based) position + * of ARG in the argument list: + * + * mf_argpos(x, STRING a, NUMBER b, OPTIONAL, STRING x) => 3 + */ +m4_define([<mf_argpos>],m4_dnl +[<__mf_argpos(0, $1, mf_argnames(m4_shift($@)))>]) + +/* __mf_defined(NAME, ARGS...) -- Scan ARGS... for the definition + * of the built-in function parameter NAME, and return a C conditional + * expression that yields true if it is defined. + * ARGS are parameter declarations in the form: + * TYPE NAME + */ +m4_define([<__mf_defined>], +[<m4_ifelse(__mf_has_optarg($@),0,1,m4_dnl +[<__bi_argcnt > mf_argpos($1,__MF_ARGLIST__)>])>]) + +/* MF_DEFINED(NAME) -- Return a C conditional expression + * that yields true if the parameter NAME is defined. + * + * __MF_ARGLIST__ => STRING a, NUMBER b, OPTIONAL, STRING x + * MF_DEFINED(x) => (__bi_argcnt >= 2) + * + * __MF_ARGLIST__ => STRING a, NUMBER b, STRING x + * MF_DEFINED(x) => (1) + */ +m4_define([<MF_DEFINED>], +[<m4_ifdef([<__MF_ARGLIST__>],([<__mf_defined($1, __MF_ARGLIST__)>]),m4_dnl +[<m4_errprint(m4___file__:m4___line__: [<MF_DEFINED used out of functional context>])>])>]) + +/* MF_OPTVAL(NAME[, DEFVAL]) -- If the parameter NAME is defined, return + * its value, otherwise return DEFVAL or 0 + */ +m4_define([<MF_OPTVAL>], +[<m4_ifdef([<__MF_ARGLIST__>],m4_dnl +[<m4_ifelse([<$2>],,$1,(MF_DEFINED($1) ? $1 : $2))>],m4_dnl +[<m4_errprint(m4___file__:m4___line__: [<MF_OPTVAL used out of functional context>])>])>]) + /* __mf_check_end() -- signal error if the previous MF_DEFUN statement was * not properly closed with END */ m4_define([<__mf_check_end>],m4_dnl [<m4_ifdef([<__MF_FUNCTION__>],m4_dnl -[<m4_errpirnt(m4___file__:m4___line__: Function '>]__MF_FUNCTION__[<' was not closed +[<m4_errprint(m4___file__:m4___line__: Function '>]__MF_FUNCTION__[<' was not closed ) m4_popdef([<__MF_FUNCTION__>]) m4_define([<__mf_error_code>],1)>])>]) @@ -226,7 +262,7 @@ m4_define([<MF_CAPTURE>], m4_define([<env_get_stream>],m4_dnl [<m4_ifdef([<__MF_FUNCTION__>],m4_dnl [<m4_ifdef([<__MF_CAPTURE__>],[<[<env_get_stream>]($@)>],m4_dnl -[<m4_errpirnt(m4___file__:m4___line__: [<env_get_stream is illegal here, the function `>]__MF_FUNCTION__[<' is not declared with MF_CAPTURE>] +[<m4_errprint(m4___file__:m4___line__: [<env_get_stream is illegal here, the function `>]__MF_FUNCTION__[<' is not declared with MF_CAPTURE>] ) m4_define([<__mf_error_code>],1)>])>],m4_dnl [<env_get_stream>])>]) @@ -254,7 +290,7 @@ m4_ifelse($1,,0,__mf_argcount(1,$@))>]) */ m4_define([<mf_prog_trace>],[<m4_dnl prog_trace(env, "$1[<>]mf_printf_list(m4_shift($@))"m4_dnl -m4_ifelse($2,,,[<,mf_argnames(m4_shift($@))>]));>]) +m4_ifelse($2,,,[<,mf_defined_argnames(m4_shift($@))>]));>]) /* MF_DEFUN(NAME, RETTYPE, ARGS...) -- Begin a built-in function declaration */ @@ -382,7 +418,7 @@ m4_divert(0)m4_dnl m4_define([<MF_GET_DATA>],[<m4_dnl m4_ifdef([<__MF_PRIV_ID__>],[<m4_dnl env_get_builtin_priv(m4_ifelse($1,,env,$1),__MF_PRIV_ID__)>],m4_dnl -[<m4_errpirnt(m4___file__:m4___line__: private data not declared (call [<MF_DECLARE_DATA>] first) +[<m4_errprint(m4___file__:m4___line__: private data not declared (call [<MF_DECLARE_DATA>] first) ) m4_define([<__mf_error_code>],1) >])>]) @@ -425,7 +461,7 @@ MF_MODULE_NAME()_init_builtin() }>]) m4wrap([<__mf_check_end -m4_ifdef([<__MF_INIT__>],,[<m4_errpirnt([<MF_INIT>] not defined +m4_ifdef([<__MF_INIT__>],,[<m4_errprint([<MF_INIT>] not defined ) m4_define([<__mf_error_code>],1)>]) m4_ifdef([<__mf_error_code>],[<m4exit(__mf_error_code)>])>]) |