aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-11-02 21:44:22 +0200
committerSergey Poznyakoff <gray@gnu.org>2020-11-02 22:14:25 +0200
commitfdf8ac1081ce47783f053d93a150f8ffe9cc2320 (patch)
treee276f686bedba238d4d9ee7873e13484af816659 /src
parent424b234cf37355421cdd58e144e64c3a1e7cc249 (diff)
downloadmailfromd-fdf8ac1081ce47783f053d93a150f8ffe9cc2320.tar.gz
mailfromd-fdf8ac1081ce47783f053d93a150f8ffe9cc2320.tar.bz2
Document the sed construct. Implement the qr() builtin.
* doc/Makefile.am: Remove sexp.texi. * doc/sexp.texi: Remove. * doc/functions.texi: Document the sed function. * doc/mailfromd.texi: Update. * src/builtin/snarf.m4 (__MF_DEFUN_FLAGS__): New macro. (__mf_add_defun_flag) (__mf_mfl_type,__mf_arglist_init): New macros. (__mf_defun): Use __mf_arglist_init to initialize __MF_ARGLIST__ and the defun flags. (__MF_NEEDS_CAPTURE__): Remove. (MF_CAPTURE): Set MFD_BUILTIN_CAPTURE directly, instead of setting __MF_NEEDS_CAPTURE__. * src/builtin/string.bi (qr): New function. * src/gram.y (funcall: T_BUILTIN): Special handling for builtins with MFD_BUILTIN_REGEX_FLAGS flag set. * src/mailfromd.h (MFD_BUILTIN_REGEX_FLAGS): New flag. * tests/sed.at: Rename qr to myqr to avoid name clash with the builtin. * configure.ac: Version 8.8.90 * NEWS: Document the sed and qr functions.
Diffstat (limited to 'src')
-rw-r--r--src/builtin/snarf.m455
-rw-r--r--src/builtin/string.bi39
-rw-r--r--src/gram.y9
-rw-r--r--src/mailfromd.h3
4 files changed, 96 insertions, 10 deletions
diff --git a/src/builtin/snarf.m4 b/src/builtin/snarf.m4
index 58fa8f3d..e669283d 100644
--- a/src/builtin/snarf.m4
+++ b/src/builtin/snarf.m4
@@ -31,6 +31,16 @@ m4_define([<__mf_dataseg>])
*/
m4_define([<MF_DSEXP>],[<m4_define([<__mf_dataseg>],[<MFL_DATASEG>])>])
+/* Flags that will be passed to va_builtin_install_ex. */
+m4_define([<__MF_DEFUN_FLAGS__>],0)
+
+/* __mf_add_defun_flag(F)
+ * ----------------------
+ * Add F to the current value of __MF_DEFUN_FLAGS__ via logical OR.
+ */
+m4_define([<__mf_add_defun_flag>],m4_dnl
+[<m4_define([<__MF_DEFUN_FLAGS__>],m4_ifelse(__MF_DEFUN_FLAGS__,0,$1,[<__MF_DEFUN_FLAGS__>]|$1))>])
+
/* __MF_DSEXP_REQ - an auxiliary macro which checks, whether __mf_dataseg
* is empty. If so, it issues a diagnostic message.
*
@@ -144,7 +154,7 @@ __mf_has_optarg(m4_shift($@))>])>])
* Expand to a C type corresponding to the Mailfromd TYPE
*/
m4_define([<__mf_c_type>],m4_dnl
-[<m4_ifelse($1,STRING,char * __mf_dataseg,$1,NUMBER,long ,$1,POINTER,void * __mf_dataseg, ERROR )>])
+[<m4_ifelse($1,STRING,char * __mf_dataseg,$1,NUMBER,long ,$1,POINTER,void * __mf_dataseg, [<UNKNOWN TYPE $1>])>])
/* __mf_c_getarg(TYPE)
* -------------------
@@ -411,7 +421,7 @@ m4_define([<MF_STATE>],
* case a reference to the capture stream is stored in STR.
*/
m4_define([<MF_CAPTURE>],m4_dnl
-[<m4_define([<__MF_NEEDS_CAPTURE__>],1)m4_dnl
+[<__mf_add_defun_flag([<MFD_BUILTIN_CAPTURE>])[<>]m4_dnl
m4_ifelse([<$1>],,,[<m4_define([<__MF_CAPTURE__>],[<$1>])>])>])
/* env_get_stream()
@@ -460,6 +470,31 @@ m4_define([<mf_prog_trace>],[<m4_dnl
prog_trace(env, "$1[<>]mf_printf_list(m4_shift($@))"m4_dnl
m4_ifelse($2,,,[<,mf_defined_argnames(m4_shift($@))>]));>])
+/* __mf_mfl_type(TYPE)
+ * -------------------
+ * If TYPE is REGFLAGS, add MFD_BUILTIN_REGEX_FLAGS to the value of
+ * __MF_DEFUN_FLAGS__ and expand to NUMBER. Otherwise, expand to
+ * TYPE.
+ */
+m4_define([<__mf_mfl_type>],
+[<m4_ifelse($1,REGFLAGS,[<m4_dnl
+__mf_add_defun_flag([<MFD_BUILTIN_REGEX_FLAGS>])m4_dnl
+NUMBER>],[<$1>])>])
+
+/* __mf_arglist_init(ARGS)
+ * -----------------------
+ * ARGS is the argument declaration list from MF_DEFUN. The macro
+ * expands to the ARGS list with the type of its first element fixed,
+ * if necessary. That is, if the first argument ha type designator
+ * REGFLAGS, it is changed to NUMBER and MFD_BUILTIN_REGEX_FLAGS is
+ * set in __MF_DEFUN_FLAGS__. Otherwise, themacro expands to ARGS
+ * unchanged.
+ */
+m4_define([<__mf_arglist_init>],m4_dnl
+[<m4_ifelse([<$1>],OPTIONAL,[<$@>],[<m4_dnl
+m4_regexp([<$1>],[<\(\w+\)\W+\(\w+\)>],[<__mf_mfl_type(\1) \2>]) m4_dnl
+m4_ifelse([<$2>],,,[<, m4_shift($@)>])>])>])
+
/* __mf_defun(VARARG, NAME, RETTYPE, ARGS...)
* ------------------------------------------
* Begin a built-in function declaration.
@@ -481,21 +516,21 @@ void
bi_$2(eval_environ_t env)
m4_pushdef([<__MF_FUNCTION__>], $2)m4_dnl
m4_pushdef([<__MF_RETTYPE__>], $3)m4_dnl
-m4_pushdef([<__MF_ARGLIST__>], [<m4_shift(m4_shift(m4_shift($*)))>])
+m4_pushdef([<__MF_ARGLIST__>], [<__mf_arglist_init(m4_shift(m4_shift(m4_shift($*))))>])
m4_ifelse($3,STRING,[<MF_DSEXP>])
m4_divert(1)m4_dnl
va_builtin_install_ex("$2", bi_$2,m4_dnl
m4_ifdef([<__MF_STATE__>],__MF_STATE__,0),m4_dnl
__mf_argtype($3),m4_dnl
- mf_argcount(m4_shift(m4_shift(m4_shift($@)))),m4_dnl
- mf_optcount(m4_shift(m4_shift(m4_shift($@)))),m4_dnl
- m4_ifdef([<__MF_NEEDS_CAPTURE__>],[<MFD_BUILTIN_CAPTURE>],0)|$1,m4_dnl
- mf_typelist(m4_shift(m4_shift(m4_shift($@)))));
+ mf_argcount(__MF_ARGLIST__),m4_dnl
+ mf_optcount(__MF_ARGLIST__),m4_dnl
+ __MF_DEFUN_FLAGS__|$1,m4_dnl
+ mf_typelist(__MF_ARGLIST__));
m4_divert(2)m4_dnl
{m4_ifdef([<__MF_CAPTURE__>],[<
mu_stream_t __MF_CAPTURE__;
>])
- mf_c_arglist(m4_shift(m4_shift(m4_shift($@))))
+ mf_c_arglist(__MF_ARGLIST__)
m4_ifdef([<__MF_CAPTURE__>],[<{
int rc = env_get_stream(env, &__MF_CAPTURE__);
MF_ASSERT(rc == 0, mfe_failure,
@@ -504,7 +539,7 @@ m4_ifdef([<__MF_CAPTURE__>],[<{
m4_define([<__MF_ENV_GET_STREAM_PROHIBIT>])m4_dnl
}>])
if (builtin_module_trace(MF_MODULE_IDX))
- mf_prog_trace($2,m4_shift(m4_shift(m4_shift($@))));
+ mf_prog_trace($2,__MF_ARGLIST__);
>])
/* MF_DEFUN(NAME, RETTYPE, ARGS...)
@@ -845,9 +880,9 @@ m4_popdef([<__MF_RETTYPE__>])m4_dnl
m4_popdef([<__MF_ARGLIST__>])m4_dnl
m4_popdef([<__MF_VARARGS__>])m4_dnl
m4_undefine([<__MF_CAPTURE__>])m4_dnl
-m4_undefine([<__MF_NEEDS_CAPTURE__>])m4_dnl
m4_undefine([<__MF_STATE__>])m4_dnl
m4_undefine([<__MF_ENDLAB__>])m4_dnl
+m4_define([<__MF_DEFUN_FLAGS__>],0)m4_dnl
m4_define([<__mf_dataseg>])m4_dnl
env_function_cleanup_flush(env, NULL);
return;
diff --git a/src/builtin/string.bi b/src/builtin/string.bi
index 9a74659f..5a163078 100644
--- a/src/builtin/string.bi
+++ b/src/builtin/string.bi
@@ -242,6 +242,45 @@ MF_DEFUN(escape, STRING, STRING text, OPTIONAL, STRING chars)
}
END
+MF_DEFUN(qr, STRING, REGFLAGS regex_flags, STRING text, OPTIONAL, STRING delim)
+{
+ static char *qc[] = {
+ /* Basic regular expressions */
+ "\\+*?[]",
+ /* Extended regular expressions */
+ "\\+*?[](){}"
+ };
+ char charmap[13];
+
+ strcpy(charmap, qc[!!(regex_flags & REG_EXTENDED)]);
+
+ if (MF_DEFINED(delim)) {
+ char *p = charmap + strlen(charmap);
+ *p++ = *delim++;
+ if (*delim)
+ *p++ = *delim;
+ *p = 0;
+ }
+
+ if (text[strcspn(text, charmap)] == 0)
+ MF_RETURN(text);
+ MF_OBSTACK_BEGIN();
+ for (;;) {
+ size_t len = strcspn(text, charmap);
+ if (len)
+ MF_OBSTACK_GROW(text, len);
+ if (text[len]) {
+ MF_OBSTACK_1GROW('\\');
+ MF_OBSTACK_1GROW(text[len]);
+ text += len + 1;
+ } else
+ break;
+ }
+ MF_OBSTACK_1GROW(0);
+ MF_RETURN_OBSTACK();
+}
+END
+
MF_DEFUN(unescape, STRING, STRING text)
{
MF_OBSTACK_BEGIN();
diff --git a/src/gram.y b/src/gram.y
index 52be4db0..5194afc5 100644
--- a/src/gram.y
+++ b/src/gram.y
@@ -2005,6 +2005,15 @@ funcall : T_BUILTIN '(' arglist ')'
{
if (check_builtin_usage($1, &@1))
YYERROR;
+
+ if ($1->flags & MFD_BUILTIN_REGEX_FLAGS) {
+ NODE *p = alloc_node(node_type_number, &@1);
+ p->v.number = regex_flags;
+ p->next = $3.head;
+ $3.head = p;
+ $3.count++;
+ }
+
if ($3.count < $1->parmcount - $1->optcount) {
parse_error_locus(&@1,
_("too few arguments in call to `%s'"),
diff --git a/src/mailfromd.h b/src/mailfromd.h
index f35ef990..cffaece4 100644
--- a/src/mailfromd.h
+++ b/src/mailfromd.h
@@ -454,6 +454,9 @@ struct mf_symbol {
#define MFD_BUILTIN_VARIADIC 0x02 /* Builtin is variadic */
#define MFD_BUILTIN_NO_PROMOTE 0x04 /* For variadic functions:
do not promote varargs to string */
+#define MFD_BUILTIN_REGEX_FLAGS 0x08 /* The built-in takes the value of the
+ regex_flags as the first (implicit)
+ argument. */
struct builtin {
SYMENT_STRUCT(name);

Return to:

Send suggestions and report system problems to the System administrator.