diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-11-02 21:44:22 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-11-02 22:14:25 +0200 |
commit | fdf8ac1081ce47783f053d93a150f8ffe9cc2320 (patch) | |
tree | e276f686bedba238d4d9ee7873e13484af816659 /src | |
parent | 424b234cf37355421cdd58e144e64c3a1e7cc249 (diff) | |
download | mailfromd-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.m4 | 55 | ||||
-rw-r--r-- | src/builtin/string.bi | 39 | ||||
-rw-r--r-- | src/gram.y | 9 | ||||
-rw-r--r-- | src/mailfromd.h | 3 |
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(); @@ -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); |