aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-05-21 22:01:29 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-05-21 22:01:29 +0000
commit2c28da5e5902dde2a7f7dcb04c69d5eff088b2fe (patch)
tree4e3e9fad417b4864dfeac4613a677a98681cb572 /src
parent48c99630a93560a4c40efdbe955e9a1e395a6162 (diff)
downloadmailfromd-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
Diffstat (limited to 'src')
-rw-r--r--src/bi_string.m42
-rw-r--r--src/drivers.c16
-rw-r--r--src/gram.y18
-rw-r--r--src/mailfromd.h2
-rw-r--r--src/main.c6
-rw-r--r--src/snarf.m4156
6 files changed, 127 insertions, 73 deletions
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
diff --git a/src/gram.y b/src/gram.y
index 8a02e038..e6dbbb79 100644
--- a/src/gram.y
+++ b/src/gram.y
@@ -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
diff --git a/src/main.c b/src/main.c
index aa0c69a8..e5d5a7f0 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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)>])>])

Return to:

Send suggestions and report system problems to the System administrator.