summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-11-03 16:11:57 +0200
committerSergey Poznyakoff <gray@gnu.org>2021-11-03 17:59:16 +0200
commit22ceaddfb850e3b9692fe2a75a83ec0156345ac8 (patch)
treebc82c45c377d02b2798a5fc714e93b18ec285159
parent1b2b389c2a563b90a74abc9cdb058ab5e12ab1f0 (diff)
downloadmailutils-22ceaddfb850e3b9692fe2a75a83ec0156345ac8.tar.gz
mailutils-22ceaddfb850e3b9692fe2a75a83ec0156345ac8.tar.bz2
Move mimetypes support into the library
* configure.ac: Build libmailutils/mimetypes/Makefile * include/mailutils/Makefile.am: New header mimetypes.h * mimeview/mimeview.h: moved from include/mailutils/mimetypes.h * include/mailutils/sys/Makefile.am: Add mimetypes.h * include/mailutils/sys/mimetypes.h: New file. * include/mailutils.h: Include mailutils/mimetypes.h * libmailutils/Makefile.am: Build mimetypes. * libmailutils/mimetypes/.gitignore: New file. * libmailutils/mimetypes/eval.c: New file. * libmailutils/mimetypes/grammar.y: Moved from mimeview/grammar.y * libmailutils/mimetypes/lexer.l: Moved from mimeview/lexer.l. * libmailutils/diag/debcat: Add mimetypes. * mimeview/Makefile.am: Update. * mimeview/tests/testsuite.at: Change debug level. * include/mailutils/stream.h (mu_fd_stream_create): filename is const. * libmailutils/stream/file_stream.c: Likewise.
-rw-r--r--configure.ac1
-rw-r--r--include/mailutils/Makefile.am1
-rw-r--r--include/mailutils/mailutils.h1
-rw-r--r--include/mailutils/mimetypes.h (renamed from mimeview/mimeview.h)24
-rw-r--r--include/mailutils/stream.h2
-rw-r--r--include/mailutils/sys/Makefile.am1
-rw-r--r--include/mailutils/sys/mimetypes.h102
-rw-r--r--libmailutils/Makefile.am2
-rw-r--r--libmailutils/diag/debcat1
-rw-r--r--libmailutils/locus/linetrack.c2
-rw-r--r--libmailutils/mimetypes/.gitignore9
-rw-r--r--libmailutils/mimetypes/eval.c551
-rw-r--r--libmailutils/mimetypes/grammar.y627
-rw-r--r--libmailutils/mimetypes/lexer.l (renamed from mimeview/lexer.l)33
-rw-r--r--libmailutils/stream/file_stream.c2
-rw-r--r--mimeview/Makefile.am25
-rw-r--r--mimeview/grammar.y1111
-rw-r--r--mimeview/mimeview.c34
-rw-r--r--mimeview/tests/testsuite.at2
-rw-r--r--po/POTFILES.in6
20 files changed, 1357 insertions, 1180 deletions
diff --git a/configure.ac b/configure.ac
index 452b611cc..4fa4ab65a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1568,6 +1568,7 @@ AC_CONFIG_FILES([
libmailutils/mailcap/Makefile
libmailutils/mailer/Makefile
libmailutils/mime/Makefile
+ libmailutils/mimetypes/Makefile
libmailutils/msgset/Makefile
libmailutils/opt/Makefile
libmailutils/property/Makefile
diff --git a/include/mailutils/Makefile.am b/include/mailutils/Makefile.am
index cbbbfbf35..7d4f00400 100644
--- a/include/mailutils/Makefile.am
+++ b/include/mailutils/Makefile.am
@@ -77,6 +77,7 @@ pkginclude_HEADERS = \
message.h\
mh.h\
mime.h\
+ mimetypes.h\
monitor.h\
msgset.h\
mu_auth.h\
diff --git a/include/mailutils/mailutils.h b/include/mailutils/mailutils.h
index 32cb36e84..d53e1d0de 100644
--- a/include/mailutils/mailutils.h
+++ b/include/mailutils/mailutils.h
@@ -72,5 +72,6 @@
#include <mailutils/sockaddr.h>
#include <mailutils/cidr.h>
#include <mailutils/msgset.h>
+#include <mailutils/mimetypes.h>
/* EOF */
diff --git a/mimeview/mimeview.h b/include/mailutils/mimetypes.h
index 867de1b20..1e75e81d0 100644
--- a/mimeview/mimeview.h
+++ b/include/mailutils/mimetypes.h
@@ -1,34 +1,32 @@
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2005-2021 Free Software Foundation, Inc.
- GNU Mailutils is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
- GNU Mailutils is distributed in the hope that it will be useful,
+ This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <mailutils/mailutils.h>
-#include <mailutils/locus.h>
-#include <mailutils/yyloc.h>
-#include <fnmatch.h>
+#ifndef _MAILUTILS_MIMETYPES_H
+#define _MAILUTILS_MIMETYPES_H
+
+#include <mailutils/types.h>
typedef struct mu_mimetypes *mu_mimetypes_t;
-mu_mimetypes_t mimetypes_open (const char *name);
+mu_mimetypes_t mu_mimetypes_open (const char *name);
void mu_mimetypes_close (mu_mimetypes_t mt);
const char *mu_mimetypes_stream_type (mu_mimetypes_t mt,
char const *name, mu_stream_t str);
const char *mu_mimetypes_file_type (mu_mimetypes_t mt, const char *file);
const char *mu_mimetypes_fd_type (mu_mimetypes_t mt, const char *file, int fd);
+#endif
diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h
index f5c8a673e..608a355dd 100644
--- a/include/mailutils/stream.h
+++ b/include/mailutils/stream.h
@@ -431,7 +431,7 @@ int mu_file_stream_create (mu_stream_t *pstream, const char *filename, int flags
struct mu_tempfile_hints;
int mu_temp_file_stream_create (mu_stream_t *pstream,
struct mu_tempfile_hints *hints, int flags);
-int mu_fd_stream_create (mu_stream_t *pstream, char *filename, int fd,
+int mu_fd_stream_create (mu_stream_t *pstream, char const *filename, int fd,
int flags);
#define MU_STDIN_FD 0
diff --git a/include/mailutils/sys/Makefile.am b/include/mailutils/sys/Makefile.am
index f5db48ffc..b5f68e15a 100644
--- a/include/mailutils/sys/Makefile.am
+++ b/include/mailutils/sys/Makefile.am
@@ -45,6 +45,7 @@ sysinclude_HEADERS = \
message_stream.h\
message.h\
mime.h\
+ mimetypes.h\
monitor.h\
msgset.h\
nullstream.h\
diff --git a/include/mailutils/sys/mimetypes.h b/include/mailutils/sys/mimetypes.h
new file mode 100644
index 000000000..254d8167b
--- /dev/null
+++ b/include/mailutils/sys/mimetypes.h
@@ -0,0 +1,102 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2009-2021 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _MAILUTILS_SYS_MIMETYPES_H
+#define _MAILUTILS_SYS_MIMETYPES_H
+
+#include <regex.h>
+#include <mailutils/locus.h>
+
+#define L_OR 0
+#define L_AND 1
+
+enum node_type
+ {
+ true_node,
+ functional_node,
+ binary_node,
+ negation_node,
+ suffix_node
+ };
+
+struct mimetypes_string
+{
+ char *ptr;
+ size_t len;
+};
+
+union argument
+{
+ struct mimetypes_string *string;
+ unsigned number;
+ int c;
+ regex_t rx;
+};
+
+struct input_file
+{
+ char const *name;
+ mu_stream_t stream;
+};
+
+typedef int (*builtin_t) (union argument *args, struct input_file *input);
+
+struct builtin_tab
+{
+ char *name;
+ char *args;
+ builtin_t handler;
+};
+
+struct node
+{
+ enum node_type type;
+ struct mu_locus_range loc;
+ union
+ {
+ struct
+ {
+ struct builtin_tab const *builtin;
+ union argument *args;
+ } function;
+ struct node *arg;
+ struct
+ {
+ int op;
+ struct node *arg1;
+ struct node *arg2;
+ } bin;
+ struct mimetypes_string suffix;
+ } v;
+};
+
+struct rule_tab
+{
+ char *type;
+ int priority;
+ struct mu_locus_range loc;
+ struct node *node;
+};
+
+struct mu_mimetypes
+{
+ mu_list_t rule_list;
+ mu_opool_t pool;
+};
+
+struct builtin_tab const *mu_mimetypes_builtin (char const *ident);
+
+#endif
diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am
index 6e7fb09f6..501f2bba9 100644
--- a/libmailutils/Makefile.am
+++ b/libmailutils/Makefile.am
@@ -31,6 +31,7 @@ SUBDIRS = \
mailcap\
mailer\
mime\
+ mimetypes\
msgset\
opt\
server\
@@ -68,6 +69,7 @@ libmailutils_la_LIBADD = \
mailcap/libmailcap.la\
mailer/libmailer.la\
mime/libmime.la\
+ mimetypes/libmimetypes.la\
msgset/libmsgset.la\
opt/libopt.la\
property/libproperty.la\
diff --git a/libmailutils/diag/debcat b/libmailutils/diag/debcat
index 600668085..6666222bc 100644
--- a/libmailutils/diag/debcat
+++ b/libmailutils/diag/debcat
@@ -31,6 +31,7 @@ mailbox
mailer
message
mime
+mimetypes
mailcap
property
remote
diff --git a/libmailutils/locus/linetrack.c b/libmailutils/locus/linetrack.c
index 3cd5be6e0..88141574f 100644
--- a/libmailutils/locus/linetrack.c
+++ b/libmailutils/locus/linetrack.c
@@ -238,7 +238,7 @@ mu_linetrack_create (mu_linetrack_t *ret,
free (trk);
return rc;
}
-
+
*ret = trk;
return 0;
}
diff --git a/libmailutils/mimetypes/.gitignore b/libmailutils/mimetypes/.gitignore
new file mode 100644
index 000000000..4a207381a
--- /dev/null
+++ b/libmailutils/mimetypes/.gitignore
@@ -0,0 +1,9 @@
+.deps
+.gdbinit
+.libs
+Makefile
+Makefile.in
+grammar.c
+grammar.h
+grammar.output
+lexer.c
diff --git a/libmailutils/mimetypes/eval.c b/libmailutils/mimetypes/eval.c
new file mode 100644
index 000000000..4babff4ef
--- /dev/null
+++ b/libmailutils/mimetypes/eval.c
@@ -0,0 +1,551 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2009-2021 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fnmatch.h>
+#include <regex.h>
+#include <inttypes.h>
+#include <mailutils/stream.h>
+#include <mailutils/locus.h>
+#include <mailutils/diag.h>
+#include <mailutils/cctype.h>
+#include <mailutils/cstr.h>
+#include <mailutils/stdstream.h>
+#include <mailutils/list.h>
+#include <mailutils/nls.h>
+#include <mailutils/errno.h>
+#include <mailutils/sys/mimetypes.h>
+#include <mailutils/mimetypes.h>
+
+/*
+ * match("pattern")
+ * Pattern match on filename
+ */
+static int
+b_match (union argument *args, struct input_file *input)
+{
+ return fnmatch (args[0].string->ptr, input->name, 0) == 0;
+}
+
+/*
+ * ascii(offset,length)
+ * True if bytes are valid printable ASCII (CR, NL, TAB,
+ * BS, 32-126)
+ */
+#define ISASCII(c) ((c) &&\
+ (strchr ("\n\r\t\b",c) \
+ || (32<=((unsigned) c) && ((unsigned) c)<=126)))
+static int
+b_ascii (union argument *args, struct input_file *input)
+{
+ int i;
+ int rc;
+
+ rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("mu_stream_seek: %s", mu_strerror (rc)));
+ return 0;
+ }
+
+ for (i = 0; i < args[1].number; i++)
+ {
+ unsigned char c;
+ size_t n;
+
+ rc = mu_stream_read (input->stream, &c, 1, &n);
+ if (rc || n == 0)
+ break;
+ if (!ISASCII (c))
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * printable(offset,length)
+ * True if bytes are printable 8-bit chars (CR, NL, TAB,
+ * BS, 32-126, 128-254)
+ */
+#define ISPRINT(c) (ISASCII (c) \
+ || (128<=((unsigned) c) && ((unsigned) c)<=254))
+static int
+b_printable (union argument *args, struct input_file *input)
+{
+ int i;
+ int rc;
+
+ rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("mu_stream_seek: %s", mu_strerror (rc)));
+ return 0;
+ }
+
+ for (i = 0; i < args[1].number; i++)
+ {
+ unsigned char c;
+ size_t n;
+
+ rc = mu_stream_read (input->stream, &c, 1, &n);
+ if (rc || n == 0)
+ break;
+ if (!ISPRINT (c))
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * string(offset,"string")
+ * True if bytes are identical to string
+ */
+static int
+b_string (union argument *args, struct input_file *input)
+{
+ struct mimetypes_string *str = args[1].string;
+ int i;
+ int rc;
+
+ rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("mu_stream_seek: %s", mu_strerror (rc)));
+ return 0;
+ }
+
+ for (i = 0; i < str->len; i++)
+ {
+ char c;
+ size_t n;
+
+ rc = mu_stream_read (input->stream, &c, 1, &n);
+ if (rc || n == 0 || c != str->ptr[i])
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * istring(offset,"string")
+ * True if a case-insensitive comparison of the bytes is
+ * identical
+ */
+static int
+b_istring (union argument *args, struct input_file *input)
+{
+ int i;
+ struct mimetypes_string *str = args[1].string;
+
+ int rc;
+
+ rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("mu_stream_seek: %s", mu_strerror (rc)));
+ return 0;
+ }
+
+ for (i = 0; i < str->len; i++)
+ {
+ char c;
+ size_t n;
+
+ rc = mu_stream_read (input->stream, &c, 1, &n);
+ if (rc || n == 0 || mu_tolower (c) != mu_tolower (str->ptr[i]))
+ return 0;
+ }
+ return 1;
+}
+
+int
+compare_bytes (union argument *args, struct input_file *input,
+ void *sample, void *buf, size_t size)
+{
+ int rc;
+ size_t n;
+
+ rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("mu_stream_seek: %s", mu_strerror (rc)));
+ return 0;
+ }
+
+ rc = mu_stream_read (input->stream, buf, size, &n);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("mu_stream_read: %s", mu_strerror (rc)));
+ return 0;
+ }
+ else if (n != size)
+ return 0;
+ return memcmp (sample, buf, size) == 0;
+}
+
+/*
+ * char(offset,value)
+ * True if byte is identical
+ */
+static int
+b_char (union argument *args, struct input_file *input)
+{
+ char val = args[1].number;
+ char buf;
+ return compare_bytes (args, input, &val, &buf, sizeof (buf));
+}
+
+/*
+ * short(offset,value)
+ * True if 16-bit integer is identical
+ * FIXME: Byte order
+ */
+static int
+b_short (union argument *args, struct input_file *input)
+{
+ uint16_t val = args[1].number;
+ uint16_t buf;
+ return compare_bytes (args, input, &val, &buf, sizeof (buf));
+}
+
+/*
+ * int(offset,value)
+ * True if 32-bit integer is identical
+ * FIXME: Byte order
+ */
+static int
+b_int (union argument *args, struct input_file *input)
+{
+ uint32_t val = args[1].number;
+ uint32_t buf;
+ return compare_bytes (args, input, &val, &buf, sizeof (buf));
+}
+
+/*
+ * locale("string")
+ * True if current locale matches string
+ */
+static int
+b_locale (union argument *args, struct input_file *input)
+{
+ abort (); /* FIXME */
+ return 0;
+}
+
+/*
+ * contains(offset,range,"string")
+ * True if the range contains the string
+ */
+static int
+b_contains (union argument *args, struct input_file *input)
+{
+ size_t i, count;
+ char *buf;
+ struct mimetypes_string *str = args[2].string;
+ int rc;
+
+ rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("mu_stream_seek: %s", mu_strerror (rc)));
+ return 0;
+ }
+
+ if ((buf = malloc (args[1].number)) == NULL)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("malloc: %s", mu_strerror (rc)));
+ return 0;
+ }
+
+ rc = mu_stream_read (input->stream, buf, args[1].number, &count);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("mu_stream_read: %s", mu_strerror (rc)));
+ }
+ else if (count > str->len)
+ for (i = 0; i <= count - str->len; i++)
+ if (buf[i] == str->ptr[0] && memcmp (buf + i, str->ptr, str->len) == 0)
+ {
+ free (buf);
+ return 1;
+ }
+ free (buf);
+ return 0;
+}
+
+#define MIME_MAX_BUFFER 4096
+
+/*
+ * regex(offset,"regex")
+ * True if bytes match regular expression
+ */
+static int
+b_regex (union argument *args, struct input_file *input)
+{
+ size_t count;
+ int rc;
+ char buf[MIME_MAX_BUFFER];
+
+ rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("mu_stream_seek: %s", mu_strerror (rc)));
+ return 0;
+ }
+
+ rc = mu_stream_read (input->stream, buf, sizeof buf - 1, &count);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("mu_stream_read: %s", mu_strerror (rc)));
+ return 0;
+ }
+ buf[count] = 0;
+
+ return regexec (&args[1].rx, buf, 0, NULL, 0) == 0;
+}
+
+
+static struct builtin_tab builtin_tab[] = {
+ { "match", "s", b_match },
+ { "ascii", "dd", b_ascii },
+ { "printable", "dd", b_printable },
+ { "regex", "dx", b_regex },
+ { "string", "ds", b_string },
+ { "istring", "ds", b_istring },
+ { "char", "dc", b_char },
+ { "short", "dd", b_short },
+ { "int", "dd", b_int },
+ { "locale", "s", b_locale },
+ { "contains", "dds", b_contains },
+ { NULL }
+};
+
+struct builtin_tab const *
+mu_mimetypes_builtin (char const *ident)
+{
+ struct builtin_tab *p;
+ for (p = builtin_tab; p->name; p++)
+ if (strcmp (ident, p->name) == 0)
+ return p;
+ return NULL;
+}
+
+static int
+check_suffix (char *suf, struct input_file *input)
+{
+ char *p = strrchr (input->name, '.');
+ if (!p)
+ return 0;
+ return strcmp (p+1, suf) == 0;
+}
+
+void
+mime_debug (int lev, struct mu_locus_range const *loc, char const *fmt, ...)
+{
+ if (mu_debug_level_p (MU_DEBCAT_MIMETYPES, lev))
+ {
+ va_list ap;
+
+ if (loc->beg.mu_col == 0)
+ mu_debug_log_begin ("%s:%u", loc->beg.mu_file, loc->beg.mu_line);
+ else if (strcmp(loc->beg.mu_file, loc->end.mu_file))
+ mu_debug_log_begin ("%s:%u.%u-%s:%u.%u",
+ loc->beg.mu_file,
+ loc->beg.mu_line, loc->beg.mu_col,
+ loc->end.mu_file,
+ loc->end.mu_line, loc->end.mu_col);
+ else if (loc->beg.mu_line != loc->end.mu_line)
+ mu_debug_log_begin ("%s:%u.%u-%u.%u",
+ loc->beg.mu_file,
+ loc->beg.mu_line, loc->beg.mu_col,
+ loc->end.mu_line, loc->end.mu_col);
+ else if (loc->beg.mu_col != loc->end.mu_col)
+ mu_debug_log_begin ("%s:%u.%u-%u",
+ loc->beg.mu_file,
+ loc->beg.mu_line, loc->beg.mu_col,
+ loc->end.mu_col);
+ else
+ mu_debug_log_begin ("%s:%u.%u",
+ loc->beg.mu_file,
+ loc->beg.mu_line, loc->beg.mu_col);
+
+ mu_stream_write (mu_strerr, ": ", 2, NULL);
+
+ va_start (ap, fmt);
+ mu_stream_vprintf (mu_strerr, fmt, ap);
+ va_end (ap);
+ mu_debug_log_nl ();
+ }
+}
+
+static int
+eval_rule (struct node *root, struct input_file *input)
+{
+ int result;
+
+ switch (root->type)
+ {
+ case true_node:
+ result = 1;
+ break;
+
+ case functional_node:
+ result = root->v.function.builtin->handler (root->v.function.args, input);
+ break;
+
+ case binary_node:
+ result = eval_rule (root->v.bin.arg1, input);
+ switch (root->v.bin.op)
+ {
+ case L_OR:
+ if (!result)
+ result |= eval_rule (root->v.bin.arg2, input);
+ break;
+
+ case L_AND:
+ if (result)
+ result &= eval_rule (root->v.bin.arg2, input);
+ break;
+
+ default:
+ abort ();
+ }
+ break;
+
+ case negation_node:
+ result = !eval_rule (root->v.arg, input);
+ break;
+
+ case suffix_node:
+ result = check_suffix (root->v.suffix.ptr, input);
+ break;
+
+ default:
+ abort ();
+ }
+ mime_debug (MU_DEBUG_TRACE2, &root->loc, "result %s", result ? "true" : "false");
+ return result;
+}
+
+static int
+evaluate (void **itmv, size_t itmc, void *call_data)
+{
+ struct rule_tab *p = itmv[0];
+ if (eval_rule (p->node, call_data))
+ {
+ itmv[0] = p;
+ mime_debug (MU_DEBUG_TRACE1, &p->loc, "rule %s matches", p->type);
+ return MU_LIST_MAP_OK;
+ }
+ return MU_LIST_MAP_SKIP;
+}
+
+static int
+rule_cmp (const void *a, const void *b)
+{
+ struct rule_tab const *arule = a;
+ struct rule_tab const *brule = b;
+
+ if (arule->priority == brule->priority)
+ {
+ if (arule->node->type == true_node
+ && brule->node->type != true_node)
+ return 1;
+ else if (brule->node->type == true_node
+ && arule->node->type != true_node)
+ return -1;
+ else
+ return mu_c_strcasecmp (arule->type, brule->type);
+ }
+ return arule->priority - brule->priority;
+}
+
+const char *
+mu_mimetypes_stream_type (mu_mimetypes_t mt, char const *name, mu_stream_t str)
+{
+ mu_list_t res = NULL;
+ const char *type = NULL;
+ struct input_file input;
+
+ input.name = name;
+ input.stream = str;
+
+ mu_stream_seek (str, 0, MU_SEEK_SET, NULL);
+ mu_list_map (mt->rule_list, evaluate, &input, 1, &res);
+ if (!mu_list_is_empty (res))
+ {
+ struct rule_tab *rule;
+ mu_list_sort (res, rule_cmp);
+ mu_list_head (res, (void**) &rule);
+ mime_debug (MU_DEBUG_TRACE0, &rule->loc, "selected rule %s", rule->type);
+ type = rule->type;
+ }
+ mu_list_destroy (&res);
+ return type;
+}
+
+const char *
+mu_mimetypes_file_type (mu_mimetypes_t mt, const char *file)
+{
+ int rc;
+ mu_stream_t str;
+ const char *res;
+
+ rc = mu_file_stream_create (&str, file, MU_STREAM_READ);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("cannot open %s: %s", file, mu_strerror (rc)));
+ return NULL;
+ }
+ res = mu_mimetypes_stream_type (mt, file, str);
+ mu_stream_destroy (&str);
+ return res;
+}
+
+const char *
+mu_mimetypes_fd_type (mu_mimetypes_t mt, const char *file, int fd)
+{
+ int rc;
+ mu_stream_t str;
+ const char *res;
+
+ rc = mu_fd_stream_create (&str, file, fd, MU_STREAM_READ);
+ if (rc)
+ {
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_ERROR,
+ ("cannot open %s: %s", file, mu_strerror (rc)));
+ return NULL;
+ }
+ res = mu_mimetypes_stream_type (mt, file, str);
+ mu_stream_destroy (&str);
+ return res;
+}
diff --git a/libmailutils/mimetypes/grammar.y b/libmailutils/mimetypes/grammar.y
new file mode 100644
index 000000000..31979002b
--- /dev/null
+++ b/libmailutils/mimetypes/grammar.y
@@ -0,0 +1,627 @@
+%{
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2005-2021 Free Software Foundation, Inc.
+
+ GNU Mailutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Mailutils is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <mailutils/mimetypes.h>
+#include <grammar.h>
+
+static void
+yyprint (FILE *output, unsigned short toknum, YYSTYPE val)
+{
+ switch (toknum)
+ {
+ case TYPE:
+ case IDENT:
+ case STRING:
+ fprintf (output, "[%lu] %s", (unsigned long) val.string.len,
+ val.string.ptr);
+ break;
+
+ case EOL:
+ fprintf (output, "\\n");
+ break;
+
+ default:
+ if (mu_isprint (toknum))
+ fprintf (output, "'%c'", toknum);
+ else
+ fprintf (output, "tok(%d)", toknum);
+ break;
+ }
+}
+
+#define YYPRINT yyprint
+
+static struct node *make_node (mu_mimetypes_t mth,
+ enum node_type type,
+ struct mu_locus_range const *loc);
+static struct node *make_binary_node (mu_mimetypes_t mth,
+ int op,
+ struct node *left, struct node *rigth,
+ struct mu_locus_range const *loc);
+static struct node *make_negation_node (mu_mimetypes_t mth,
+ struct node *p,
+ struct mu_locus_range const *loc);
+
+static struct node *make_suffix_node (mu_mimetypes_t mth,
+ struct mimetypes_string *suffix,
+ struct mu_locus_range const *loc);
+static struct node *make_functional_node (mu_mimetypes_t mth,
+ char *ident, mu_list_t list,
+ struct mu_locus_range const *loc);
+
+static void *
+mimetypes_malloc (mu_mimetypes_t mth, size_t size)
+{
+ mu_opool_alloc (mth->pool, size);
+ return mu_opool_finish (mth->pool, NULL);
+}
+
+static struct mimetypes_string *
+mimetypes_string_dup (mu_mimetypes_t mth, struct mimetypes_string *s)
+{
+ mu_opool_append (mth->pool, s, sizeof *s);
+ return mu_opool_finish (mth->pool, NULL);
+}
+
+static void rule_destroy_item (void *ptr);
+
+%}
+
+%define api.pure full
+%define api.prefix {mimetypes_yy}
+
+%code requires {
+#include <stdio.h>
+#include <regex.h>
+#include <mailutils/stream.h>
+#include <mailutils/cctype.h>
+#include <mailutils/cstr.h>
+#include <mailutils/locus.h>
+#include <mailutils/yyloc.h>
+#include <mailutils/opool.h>
+#include <mailutils/list.h>
+#include <mailutils/nls.h>
+#include <mailutils/diag.h>
+#include <mailutils/stdstream.h>
+#include <mailutils/iterator.h>
+#include <mailutils/util.h>
+#include <mailutils/mimetypes.h>
+#include <mailutils/sys/mimetypes.h>
+
+#define MIMETYPES_YYLTYPE struct mu_locus_range
+
+typedef void *yyscan_t;
+
+struct parser_control
+{
+ mu_linetrack_t trk;
+ struct mu_locus_point string_beg;
+ size_t errors;
+ mu_mimetypes_t mth;
+};
+
+}
+
+%code provides {
+int mimetypes_yylex (MIMETYPES_YYSTYPE *lvalp, MIMETYPES_YYLTYPE *llocp,
+ yyscan_t yyscanner);
+int mimetypes_yylex_init_extra (struct parser_control *, yyscan_t *);
+int mimetypes_yylex_destroy (yyscan_t);
+void mimetypes_yyerror (MIMETYPES_YYLTYPE const *llocp,
+ struct parser_control *pctl, yyscan_t scanner,
+ char const *fmt, ...)
+ MU_PRINTFLIKE(4,5);
+int mimetypes_scanner_open (yyscan_t scanner, const char *name);
+
+void lex_next_rule (MIMETYPES_YYLTYPE *llocp, yyscan_t scanner);
+}
+
+%parse-param { struct parser_control *pctl } { void *yyscanner }
+%lex-param { yyscan_t yyscanner }
+%initial-action {
+ /*
+ * yylloc is a local variable of yyparse. It is maintained in sync with
+ * the trk member of struct parser_control, and need to be deallocated
+ * before returning from yyparse. Since Bison does not provide any
+ * %final-action, the variable is deinited in the <<EOF>> scanner rule.
+ */
+ mu_locus_range_init (&yylloc);
+}
+%locations
+%expect 15
+
+%token <string> TYPE IDENT
+%token <string> STRING
+%token EOL BOGUS PRIORITY
+
+%left ','
+%left '+'
+
+%type <string> arg
+%type <list> arglist
+%type <node> function stmt rule maybe_rule
+%type <result> priority maybe_priority
+
+%union {
+ struct mimetypes_string string;
+ char *s;
+ mu_list_t list;
+ int result;
+ struct node *node;
+}
+
+%destructor { mu_list_destroy (&$$); } <list>
+
+%%
+
+input : list
+ ;
+
+list : rule_line
+ | list EOL rule_line
+ ;
+
+rule_line: /* empty */
+ | TYPE maybe_rule maybe_priority
+ {
+ struct rule_tab *p = mimetypes_malloc (pctl->mth, sizeof (*p));
+ p->type = $1.ptr;
+ p->node = $2;
+ p->priority = $3;
+ mu_locus_range_init (&p->loc);
+ mu_locus_point_copy (&p->loc.beg, &@1.beg);
+ mu_locus_point_copy (&p->loc.end, &@3.end);
+#if 0
+ YY_LOCATION_PRINT (stderr, p->loc);
+ fprintf (stderr, ": rule %s\n", p->type);
+#endif
+ mu_list_append (pctl->mth->rule_list, p);
+ }
+ | BOGUS
+ {
+ YYERROR;
+ }
+ | error
+ {
+ pctl->errors++;
+ lex_next_rule (&@1, yyscanner);
+ yyerrok;
+ yyclearin;
+ }
+ ;
+
+maybe_rule: /* empty */
+ {
+ $$ = make_node (pctl->mth, true_node, &yylloc);
+ }
+ | rule
+ ;
+
+rule : stmt
+ | rule rule %prec ','
+ {
+ struct mu_locus_range lr;
+ lr.beg = @1.beg;
+ lr.end = @2.end;
+ $$ = make_binary_node (pctl->mth, L_OR, $1, $2, &lr);
+ }
+ | rule ',' rule
+ {
+ struct mu_locus_range lr;
+ lr.beg = @1.beg;
+ lr.end = @3.end;
+ $$ = make_binary_node (pctl->mth, L_OR, $1, $3, &lr);
+ }
+ | rule '+' rule
+ {
+ struct mu_locus_range lr;
+ lr.beg = @1.beg;
+ lr.end = @3.end;
+ $$ = make_binary_node (pctl->mth, L_AND, $1, $3, &lr);
+ }
+ ;
+
+stmt : '!' stmt
+ {
+ $$ = make_negation_node (pctl->mth, $2, &@2);
+ }
+ | '(' rule ')'
+ {
+ $$ = $2;
+ }
+ | STRING
+ {
+ $$ = make_suffix_node (pctl->mth, &$1, &@1);
+ }
+ | function
+ | BOGUS
+ {
+ YYERROR;
+ }
+ ;
+
+priority : PRIORITY '(' arglist ')'
+ {
+ size_t count = 0;
+ struct mimetypes_string *arg;
+
+ mu_list_count ($3, &count);
+ if (count != 1)
+ {
+ yyerror (&@3, pctl, yyscanner,
+ "%s", _("priority takes single numberic argument"));
+ YYERROR;
+ }
+ mu_list_head ($3, (void**) &arg);
+ $$ = atoi (arg->ptr);
+ mu_list_destroy (&$3);
+ }
+ ;
+
+maybe_priority: /* empty */
+ {
+ $$ = 100;
+ }
+ | priority
+ ;
+
+function : IDENT '(' arglist ')'
+ {
+ struct mu_locus_range lr;
+ lr.beg = @1.beg;
+ lr.end = @4.end;
+
+ $$ = make_functional_node (pctl->mth, $1.ptr, $3, &lr);
+ if (!$$)
+ YYERROR;
+ mu_list_destroy (&$3);
+ }
+ ;
+
+arglist : arg
+ {
+ mu_list_create (&$$);
+ mu_list_append ($$, mimetypes_string_dup (pctl->mth, &$1));
+ }
+ | arglist ',' arg
+ {
+ mu_list_append ($1, mimetypes_string_dup (pctl->mth, &$3));
+ $$ = $1;
+ }
+ ;
+
+arg : STRING
+ | BOGUS
+ {
+ YYERROR;
+ }
+ ;
+
+%%
+
+void
+yyerror (MIMETYPES_YYLTYPE const *loc, struct parser_control *pctl,
+ yyscan_t scanner, char const *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ mu_vdiag_at_locus_range (MU_DIAG_ERROR, loc, fmt, ap);
+ va_end (ap);
+}
+
+static void
+parser_control_init (struct parser_control *ctl,
+ char const *filename, struct mu_mimetypes *mth)
+{
+ memset (ctl, 0, sizeof *ctl);
+ mu_linetrack_create (&ctl->trk, filename, 3);
+ ctl->mth = mth;
+}
+
+static void
+parser_control_destroy (struct parser_control *ctl)
+{
+ mu_linetrack_destroy (&ctl->trk);
+ mu_locus_point_deinit (&ctl->string_beg);
+}
+
+static void
+locus_on (void)
+{
+ int mode;
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_GET_MODE, &mode);
+ mode |= MU_LOGMODE_LOCUS;
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+}
+
+static void
+locus_off (void)
+{
+ int mode;
+
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_GET_MODE, &mode);
+ mode &= ~MU_LOGMODE_LOCUS;
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
+ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
+ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, NULL);
+}
+
+mu_mimetypes_t
+mu_mimetypes_open (const char *name)
+{
+ int rc;
+ struct mu_mimetypes *mtp;
+ struct parser_control ctl;
+ void *scanner;
+
+ mtp = calloc (1, sizeof *mtp);
+ if (!mtp)
+ return NULL;
+
+ //FIXME: install destroy_item ?
+ if (mu_list_create (&mtp->rule_list)
+ || mu_opool_create (&mtp->pool, MU_OPOOL_DEFAULT))
+ rc = 1;
+ else
+ {
+ mu_list_set_destroy_item (mtp->rule_list, rule_destroy_item);
+ parser_control_init (&ctl, name, mtp);
+
+ mimetypes_yylex_init_extra (&ctl, &scanner);
+ if (mimetypes_scanner_open (scanner, name))
+ rc = 1;
+ else
+ {
+ yydebug = mu_debug_level_p (MU_DEBCAT_MIMETYPES, MU_DEBUG_TRACE3);
+ locus_on ();
+ rc = yyparse (&ctl, scanner);
+ locus_off ();
+ }
+ mimetypes_yylex_destroy (scanner);
+ }
+
+ if (rc || ctl.errors)
+ {
+ mu_mimetypes_close (mtp);
+ mtp = NULL;
+ }
+ parser_control_destroy (&ctl);
+
+ return mtp;
+}
+
+void
+mu_mimetypes_close (mu_mimetypes_t mt)
+{
+ if (mt)
+ {
+ mu_list_destroy (&mt->rule_list);
+ mu_opool_destroy (&mt->pool);
+ free (mt);
+ }
+}
+
+static struct node *
+make_node (mu_mimetypes_t mth,
+ enum node_type type, struct mu_locus_range const *loc)
+{
+ struct node *p = mimetypes_malloc (mth, sizeof *p);
+ p->type = type;
+ mu_locus_range_init (&p->loc);
+ mu_locus_range_copy (&p->loc, loc);
+ return p;
+}
+
+static struct node *
+make_binary_node (mu_mimetypes_t mth,
+ int op, struct node *left, struct node *right,
+ struct mu_locus_range const *loc)
+{
+ struct node *node = make_node (mth, binary_node, loc);
+
+ node->v.bin.op = op;
+ node->v.bin.arg1 = left;
+ node->v.bin.arg2 = right;
+ return node;
+}
+
+static struct node *
+make_negation_node (mu_mimetypes_t mth,
+ struct node *p, struct mu_locus_range const *loc)
+{
+ struct node *node = make_node (mth, negation_node, loc);
+ node->v.arg = p;
+ return node;
+}
+
+static struct node *
+make_suffix_node (mu_mimetypes_t mth,
+ struct mimetypes_string *suffix,
+ struct mu_locus_range const *loc)
+{
+ struct node *node = make_node (mth, suffix_node, loc);
+ node->v.suffix = *suffix;
+ return node;
+}
+
+static struct node *
+make_functional_node (mu_mimetypes_t mth,
+ char *ident, mu_list_t list,
+ struct mu_locus_range const *loc)
+{
+ size_t count, i;
+ struct builtin_tab const *p;
+ struct node *node;
+ union argument *args;
+ mu_iterator_t itr;
+ int rc;
+
+ p = mu_mimetypes_builtin (ident);
+ if (!p)
+ {
+ yyerror (loc, NULL, NULL, _("unknown builtin: %s"), ident);
+ return NULL;
+ }
+
+ mu_list_count (list, &count);
+ i = strlen (p->args);
+
+ if (count < i)
+ {
+ yyerror (loc, NULL, NULL, _("too few arguments in call to `%s'"), ident);
+ return NULL;
+ }
+ else if (count > i)
+ {
+ yyerror (loc, NULL, NULL, _("too many arguments in call to `%s'"), ident);
+ return NULL;
+ }
+
+ args = mimetypes_malloc (mth, count * sizeof *args);
+
+ mu_list_get_iterator (list, &itr);
+ for (i = 0, mu_iterator_first (itr); !mu_iterator_is_done (itr);
+ mu_iterator_next (itr), i++)
+ {
+ struct mimetypes_string *data;
+ char *tmp;
+
+ mu_iterator_current (itr, (void **)&data);
+ switch (p->args[i])
+ {
+ case 'd':
+ args[i].number = strtoul (data->ptr, &tmp, 0);
+ if (*tmp)
+ goto err;
+ break;
+
+ case 's':
+ args[i].string = data;
+ break;
+
+ case 'x':
+ {
+ char *s;
+
+ rc = mu_c_str_unescape_trans (data->ptr,
+ "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v", &s);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_c_str_unescape_trans",
+ data->ptr, rc);
+ return NULL;
+ }
+ rc = regcomp (&args[i].rx, s, REG_EXTENDED|REG_NOSUB);
+ free (s);
+ if (rc)
+ {
+ char errbuf[512];
+ regerror (rc, &args[i].rx, errbuf, sizeof errbuf);
+ yyerror (loc, NULL, NULL, "%s", errbuf);
+ return NULL;
+ }
+ }
+ break;
+
+ case 'c':
+ args[i].c = strtoul (data->ptr, &tmp, 0);
+ if (*tmp)
+ goto err;
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ mu_iterator_destroy (&itr);
+ node = make_node (mth, functional_node, loc);
+ node->v.function.builtin = p;
+ node->v.function.args = args;
+ return node;
+
+ err:
+ {
+ yyerror (loc, NULL, NULL,
+ _("argument %lu has wrong type in call to `%s'"),
+ (unsigned long) i, ident);
+ return NULL;
+ }
+}
+
+static void
+free_node (struct node *node)
+{
+ switch (node->type)
+ {
+ case functional_node:
+ {
+ char const *p;
+
+ for (p = node->v.function.builtin->args; *p; p++)
+ {
+ switch (*p)
+ {
+ case 'd':
+ break;
+
+ case 'x':
+ regfree (&node->v.function.args[0].rx);
+ break;
+
+ case 's':
+ break;
+ }
+ }
+ // free (node->v.function.args);
+ }
+ break;
+
+ case binary_node:
+ free_node (node->v.bin.arg1);
+ free_node (node->v.bin.arg2);
+ break;
+
+ case negation_node:
+ free_node (node->v.arg);
+ break;
+
+ default:
+ break;
+ }
+
+ mu_locus_range_deinit (&node->loc);
+}
+
+static void
+rule_destroy_item (void *ptr)
+{
+ struct rule_tab *rt = ptr;
+ mu_locus_range_deinit (&rt->loc);
+ free_node (rt->node);
+}
+
+
+
diff --git a/mimeview/lexer.l b/libmailutils/mimetypes/lexer.l
index a8baf5493..ba19abcb7 100644
--- a/mimeview/lexer.l
+++ b/libmailutils/mimetypes/lexer.l
@@ -24,10 +24,15 @@
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
-#include <mimeview.h>
#include <grammar.h>
#include <mailutils/io.h>
-
+#include <mailutils/stream.h>
+#include <mailutils/stdstream.h>
+#include <mailutils/opool.h>
+#include <mailutils/errno.h>
+#include <mailutils/nls.h>
+#include <mailutils/diag.h>
+
static unsigned
digit_to_number (char c)
{
@@ -185,23 +190,24 @@ WS [ \t][ \t]*
finish_string (yylval, yylloc, yyscanner);
return STRING;
}
+}
<<EOF>> {
mu_locus_range_deinit (yylloc);
+ fclose (yyin);
yypop_buffer_state (yyscanner);
yyterminate ();
}
-}
%%
int
mimetypes_scanner_open (yyscan_t scanner, const char *name)
{
struct stat st;
- char *filename;
+ char *filename = NULL;
FILE *fp;
- yyset_debug (mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE4), scanner);
+ yyset_debug (mu_debug_level_p (MU_DEBCAT_MIMETYPES, MU_DEBUG_TRACE4), scanner);
if (stat (name, &st))
{
@@ -210,14 +216,17 @@ mimetypes_scanner_open (yyscan_t scanner, const char *name)
}
if (S_ISDIR (st.st_mode))
- filename = mu_make_file_name (name, "mime.types");
- else
- filename = mu_strdup (name);
+ {
+ filename = mu_make_file_name (name, "mime.types");
+ if (!filename)
+ return -1;
+ name = filename;
+ }
- fp = fopen (filename, "r");
+ fp = fopen (name, "r");
if (!fp)
{
- mu_error (_("cannot open `%s': %s"), filename, mu_strerror (errno));
+ mu_error (_("cannot open `%s': %s"), name, mu_strerror (errno));
free (filename);
return -1;
}
@@ -243,7 +252,7 @@ lex_next_rule (MIMETYPES_YYLTYPE *llocp, yyscan_t yyscanner)
mu_linetrack_t trk = yyget_extra (yyscanner)->trk;
int c;
int dbg = yyget_debug (yyscanner)
- || mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE6);
+ || mu_debug_level_p (MU_DEBCAT_MIMETYPES, MU_DEBUG_TRACE6);
if (dbg)
{
@@ -289,7 +298,7 @@ finish_string (MIMETYPES_YYSTYPE *lvalp, MIMETYPES_YYLTYPE *llocp,
mu_locus_point_copy (&llocp->beg, &pctl->string_beg);
mu_locus_point_deinit (&pctl->string_beg);
- if (mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE5))
+ if (mu_debug_level_p (MU_DEBCAT_MIMETYPES, MU_DEBUG_TRACE5))
{
size_t i;
mu_debug_log_begin ("string %zu: ", lvalp->string.len);
diff --git a/libmailutils/stream/file_stream.c b/libmailutils/stream/file_stream.c
index 1e5b97ff1..ab4dc87bf 100644
--- a/libmailutils/stream/file_stream.c
+++ b/libmailutils/stream/file_stream.c
@@ -479,7 +479,7 @@ mu_file_stream_create (mu_stream_t *pstream, const char *filename, int flags)
}
int
-mu_fd_stream_create (mu_stream_t *pstream, char *filename, int fd, int flags)
+mu_fd_stream_create (mu_stream_t *pstream, char const *filename, int fd, int flags)
{
struct _mu_file_stream *fstr;
int rc;
diff --git a/mimeview/Makefile.am b/mimeview/Makefile.am
index f1d80babd..5b536f443 100644
--- a/mimeview/Makefile.am
+++ b/mimeview/Makefile.am
@@ -18,33 +18,10 @@ SUBDIRS = . tests
AM_CPPFLAGS = \
$(MU_APP_COMMON_INCLUDES)\
- -D_GNU_SOURCE=1\
-DDEFAULT_CUPS_CONFDIR=\"@DEFAULT_CUPS_CONFDIR@\"
bin_PROGRAMS = mimeview
-mimeview_SOURCES = \
- mimeview.c \
- grammar.c \
- lexer.c \
- mimeview.h\
- grammar.h
-
-AM_YFLAGS=-vtd
-AM_LFLAGS=-d
-
-grammar.c grammar.h: grammar.y
-lexer.c: lexer.l
-
-BUILT_SOURCES = \
- grammar.c grammar.h \
- lexer.c
-
-EXTRA_DIST = grammar.y lexer.l
-
-.l.c:
- $(FLEX) -o $@ $(AM_LFLAGS) $<
-.y.c:
- $(BISON) -o $@ $(AM_YFLAGS) $<
+mimeview_SOURCES = mimeview.c
mimeview_LDADD = \
$(MU_APP_LIBRARIES)\
diff --git a/mimeview/grammar.y b/mimeview/grammar.y
deleted file mode 100644
index ee42c7866..000000000
--- a/mimeview/grammar.y
+++ /dev/null
@@ -1,1111 +0,0 @@
-%{
-/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 2005-2021 Free Software Foundation, Inc.
-
- GNU Mailutils is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
-
- GNU Mailutils is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <mailutils/cctype.h>
-#include <mimeview.h>
-#include <grammar.h>
-#include <regex.h>
-
-static void
-yyprint (FILE *output, unsigned short toknum, YYSTYPE val)
-{
- switch (toknum)
- {
- case TYPE:
- case IDENT:
- case STRING:
- fprintf (output, "[%lu] %s", (unsigned long) val.string.len,
- val.string.ptr);
- break;
-
- case EOL:
- fprintf (output, "\\n");
- break;
-
- default:
- if (mu_isprint (toknum))
- fprintf (output, "'%c'", toknum);
- else
- fprintf (output, "tok(%d)", toknum);
- break;
- }
-}
-
-#define YYPRINT yyprint
-
-#define L_OR 0
-#define L_AND 1
-
-enum node_type
- {
- true_node,
- functional_node,
- binary_node,
- negation_node,
- suffix_node
- };
-
-union argument
-{
- struct mimetypes_string *string;
- unsigned number;
- int c;
- regex_t rx;
-};
-
-struct input_file
-{
- char const *name;
- mu_stream_t stream;
-};
-
-typedef int (*builtin_t) (union argument *args, struct input_file *input);
-
-struct node
-{
- enum node_type type;
- struct mu_locus_range loc;
- union
- {
- struct
- {
- builtin_t fun;
- union argument *args;
- } function;
- struct node *arg;
- struct
- {
- int op;
- struct node *arg1;
- struct node *arg2;
- } bin;
- struct mimetypes_string suffix;
- } v;
-};
-
-static struct node *make_node (mu_mimetypes_t mth,
- enum node_type type,
- struct mu_locus_range const *loc);
-static struct node *make_binary_node (mu_mimetypes_t mth,
- int op,
- struct node *left, struct node *rigth,
- struct mu_locus_range const *loc);
-static struct node *make_negation_node (mu_mimetypes_t mth,
- struct node *p,
- struct mu_locus_range const *loc);
-
-static struct node *make_suffix_node (mu_mimetypes_t mth,
- struct mimetypes_string *suffix,
- struct mu_locus_range const *loc);
-static struct node *make_functional_node (mu_mimetypes_t mth,
- char *ident, mu_list_t list,
- struct mu_locus_range const *loc);
-
-static int eval_rule (struct node *root, struct input_file *input);
-
-static void *
-mimetypes_malloc (mu_mimetypes_t mth, size_t size)
-{
- mu_opool_alloc (mth->pool, size);
- return mu_opool_finish (mth->pool, NULL);
-}
-
-struct mimetypes_string *
-mimetypes_string_dup (mu_mimetypes_t mth, struct mimetypes_string *s)
-{
- mu_opool_append (mth->pool, s, sizeof *s);
- return mu_opool_finish (mth->pool, NULL);
-}
-
-%}
-
-%define api.pure full
-%define api.prefix {mimetypes_yy}
-
-%code requires {
-#define MIMETYPES_YYLTYPE struct mu_locus_range
-
-struct rule_tab
-{
- char *type;
- int priority;
- struct mu_locus_range loc;
- struct node *node;
-};
-
-struct mu_mimetypes
-{
- mu_list_t rule_list;
- mu_opool_t pool;
-};
-
-typedef void *yyscan_t;
-
-struct parser_control
-{
- mu_linetrack_t trk;
- struct mu_locus_point string_beg;
- size_t errors;
- mu_list_t arg_list;
- mu_mimetypes_t mth;
-};
-
-struct mimetypes_string
-{
- char *ptr;
- size_t len;
-};
-}
-
-%code provides {
-int mimetypes_yylex (MIMETYPES_YYSTYPE *lvalp, MIMETYPES_YYLTYPE *llocp,
- yyscan_t yyscanner);
-int mimetypes_yylex_init_extra (struct parser_control *, yyscan_t *);
-int mimetypes_yylex_destroy (yyscan_t);
-void mimetypes_yyerror (MIMETYPES_YYLTYPE const *llocp,
- struct parser_control *pctl, yyscan_t scanner,
- char const *fmt, ...)
- MU_PRINTFLIKE(4,5);
-int mimetypes_scanner_open (yyscan_t scanner, const char *name);
-
-void lex_next_rule (MIMETYPES_YYLTYPE *llocp, yyscan_t scanner);
-}
-
-%parse-param { struct parser_control *pctl } { void *yyscanner }
-%lex-param { yyscan_t yyscanner }
-%initial-action {
- /*
- * yylloc is a local variable of yyparse. It is maintained in sync with
- * the trk member of struct parser_control, and need to be deallocated
- * before returning from yyparse. Since Bison does not provide any
- * %final-action, the variable is deinited in the <<EOF>> scanner rule.
- */
- mu_locus_range_init (&yylloc);
-}
-%locations
-%expect 15
-
-%token <string> TYPE IDENT
-%token <string> STRING
-%token EOL BOGUS PRIORITY
-
-%left ','
-%left '+'
-
-%type <string> arg
-%type <list> arglist
-%type <node> function stmt rule maybe_rule
-%type <result> priority maybe_priority
-
-%union {
- struct mimetypes_string string;
- char *s;
- mu_list_t list;
- int result;
- struct node *node;
-}
-
-%%
-
-input : list
- ;
-
-list : rule_line
- | list EOL rule_line
- ;
-
-rule_line: /* empty */
- | TYPE maybe_rule maybe_priority
- {
- struct rule_tab *p = mimetypes_malloc (pctl->mth, sizeof (*p));
- p->type = $1.ptr;
- p->node = $2;
- p->priority = $3;
- mu_locus_range_init (&p->loc);
- mu_locus_point_copy (&p->loc.beg, &@1.beg);
- mu_locus_point_copy (&p->loc.end, &@3.end);
-#if 0
- YY_LOCATION_PRINT (stderr, p->loc);
- fprintf (stderr, ": rule %s\n", p->type);
-#endif
- mu_list_append (pctl->mth->rule_list, p);
- }
- | BOGUS
- {
- YYERROR;
- }
- | error
- {
- pctl->errors++;
- if (pctl->arg_list)
- mu_list_destroy (&pctl->arg_list);
- lex_next_rule (&@1, yyscanner);
- yyerrok;
- yyclearin;
- }
- ;
-
-maybe_rule: /* empty */
- {
- $$ = make_node (pctl->mth, true_node, &yylloc);
- }
- | rule
- ;
-
-rule : stmt
- | rule rule %prec ','
- {
- struct mu_locus_range lr;
- lr.beg = @1.beg;
- lr.end = @2.end;
- $$ = make_binary_node (pctl->mth, L_OR, $1, $2, &lr);
- }
- | rule ',' rule
- {
- struct mu_locus_range lr;
- lr.beg = @1.beg;
- lr.end = @3.end;
- $$ = make_binary_node (pctl->mth, L_OR, $1, $3, &lr);
- }
- | rule '+' rule
- {
- struct mu_locus_range lr;
- lr.beg = @1.beg;
- lr.end = @3.end;
- $$ = make_binary_node (pctl->mth, L_AND, $1, $3, &lr);
- }
- ;
-
-stmt : '!' stmt
- {
- $$ = make_negation_node (pctl->mth, $2, &@2);
- }
- | '(' rule ')'
- {
- $$ = $2;
- }
- | STRING
- {
- $$ = make_suffix_node (pctl->mth, &$1, &@1);
- }
- | function
- | BOGUS
- {
- YYERROR;
- }
- ;
-
-priority : PRIORITY '(' arglist ')'
- {
- size_t count = 0;
- struct mimetypes_string *arg;
-
- mu_list_count ($3, &count);
- if (count != 1)
- {
- yyerror (&@3, pctl, yyscanner,
- "%s", _("priority takes single numberic argument"));
- YYERROR;
- }
- mu_list_head ($3, (void**) &arg);
- $$ = atoi (arg->ptr);
- mu_list_destroy (&$3);
- }
- ;
-
-maybe_priority: /* empty */
- {
- $$ = 100;
- }
- | priority
- ;
-
-function : IDENT '(' arglist ')'
- {
- struct mu_locus_range lr;
- lr.beg = @1.beg;
- lr.end = @4.end;
-
- $$ = make_functional_node (pctl->mth, $1.ptr, $3, &lr);
- if (!$$)
- YYERROR;
- }
- ;
-
-arglist : arg
- {
- mu_list_create (&pctl->arg_list);
- $$ = pctl->arg_list;
- mu_list_append ($$, mimetypes_string_dup (pctl->mth, &$1));
- }
- | arglist ',' arg
- {
- mu_list_append ($1, mimetypes_string_dup (pctl->mth, &$3));
- $$ = $1;
- }
- ;
-
-arg : STRING
- | BOGUS
- {
- YYERROR;
- }
- ;
-
-%%
-
-void
-yyerror (MIMETYPES_YYLTYPE const *loc, struct parser_control *pctl,
- yyscan_t scanner, char const *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- mu_vdiag_at_locus_range (MU_DIAG_ERROR, loc, fmt, ap);
- va_end (ap);
-}
-
-static void
-parser_control_init (struct parser_control *ctl,
- char const *filename, struct mu_mimetypes *mth)
-{
- memset (ctl, 0, sizeof *ctl);
- mu_linetrack_create (&ctl->trk, filename, 3);
- ctl->mth = mth;
-}
-
-static void
-parser_control_destroy (struct parser_control *ctl)
-{
- mu_linetrack_destroy (&ctl->trk);
- mu_locus_point_deinit (&ctl->string_beg);
- mu_list_destroy (&ctl->arg_list);
-}
-
-static void
-locus_on (void)
-{
- int mode;
- mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_GET_MODE, &mode);
- mode |= MU_LOGMODE_LOCUS;
- mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
-}
-
-static void
-locus_off (void)
-{
- int mode;
-
- mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_GET_MODE, &mode);
- mode &= ~MU_LOGMODE_LOCUS;
- mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
- mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
- MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, NULL);
-}
-
-mu_mimetypes_t
-mimetypes_open (const char *name)
-{
- int rc;
- struct mu_mimetypes *mtp;
- struct parser_control ctl;
- void *scanner;
-
- mtp = mu_alloc (sizeof *mtp);
- //FIXME: install destroy_item ?
- mu_list_create (&mtp->rule_list);
- mu_opool_create (&mtp->pool, MU_OPOOL_ENOMEMABRT);
-
- parser_control_init (&ctl, name, mtp);
-
- mimetypes_yylex_init_extra (&ctl, &scanner);
- if (mimetypes_scanner_open (scanner, name))
- rc = 1;
- else
- {
- yydebug = mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE3);
- locus_on ();
- rc = yyparse (&ctl, scanner);
- locus_off ();
- }
- mimetypes_yylex_destroy (scanner);
-
- if (rc || ctl.errors)
- {
- mu_mimetypes_close (mtp);
- mtp = NULL;
- }
- parser_control_destroy (&ctl);
-
- return mtp;
-}
-
-void
-mu_mimetypes_close (mu_mimetypes_t mt)
-{
- if (mt)
- {
- mu_list_destroy (&mt->rule_list);
- mu_opool_destroy (&mt->pool);
- free (mt);
- }
-}
-
-static struct node *
-make_node (mu_mimetypes_t mth,
- enum node_type type, struct mu_locus_range const *loc)
-{
- struct node *p = mimetypes_malloc (mth, sizeof *p);
- p->type = type;
- mu_locus_range_init (&p->loc);
- mu_locus_range_copy (&p->loc, loc);
- return p;
-}
-
-static struct node *
-make_binary_node (mu_mimetypes_t mth,
- int op, struct node *left, struct node *right,
- struct mu_locus_range const *loc)
-{
- struct node *node = make_node (mth, binary_node, loc);
-
- node->v.bin.op = op;
- node->v.bin.arg1 = left;
- node->v.bin.arg2 = right;
- return node;
-}
-
-struct node *
-make_negation_node (mu_mimetypes_t mth,
- struct node *p, struct mu_locus_range const *loc)
-{
- struct node *node = make_node (mth, negation_node, loc);
- node->v.arg = p;
- return node;
-}
-
-struct node *
-make_suffix_node (mu_mimetypes_t mth,
- struct mimetypes_string *suffix,
- struct mu_locus_range const *loc)
-{
- struct node *node = make_node (mth, suffix_node, loc);
- node->v.suffix = *suffix;
- return node;
-}
-
-struct builtin_tab
-{
- char *name;
- char *args;
- builtin_t handler;
-};
-
-/* match("pattern")
- Pattern match on filename
-*/
-static int
-b_match (union argument *args, struct input_file *input)
-{
- return fnmatch (args[0].string->ptr, input->name, 0) == 0;
-}
-
-/* ascii(offset,length)
- True if bytes are valid printable ASCII (CR, NL, TAB,
- BS, 32-126)
-*/
-#define ISASCII(c) ((c) &&\
- (strchr ("\n\r\t\b",c) \
- || (32<=((unsigned) c) && ((unsigned) c)<=126)))
-static int
-b_ascii (union argument *args, struct input_file *input)
-{
- int i;
- int rc;
-
- rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
- if (rc)
- {
- mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_seek", NULL, rc);
- return 0;
- }
-
- for (i = 0; i < args[1].number; i++)
- {
- unsigned char c;
- size_t n;
-
- rc = mu_stream_read (input->stream, &c, 1, &n);
- if (rc || n == 0)
- break;
- if (!ISASCII (c))
- return 0;
- }
-
- return 1;
-}
-
-/* printable(offset,length)
- True if bytes are printable 8-bit chars (CR, NL, TAB,
- BS, 32-126, 128-254)
-*/
-#define ISPRINT(c) (ISASCII (c) \
- || (128<=((unsigned) c) && ((unsigned) c)<=254))
-static int
-b_printable (union argument *args, struct input_file *input)
-{
- int i;
- int rc;
-
- rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
- if (rc)
- {
- mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_seek", NULL, rc);
- return 0;
- }
-
- for (i = 0; i < args[1].number; i++)
- {
- unsigned char c;
- size_t n;
-
- rc = mu_stream_read (input->stream, &c, 1, &n);
- if (rc || n == 0)
- break;
- if (!ISPRINT (c))
- return 0;
- }
- return 1;
-}
-
-/* string(offset,"string")
- True if bytes are identical to string
-*/
-static int
-b_string (union argument *args, struct input_file *input)
-{
- struct mimetypes_string *str = args[1].string;
- int i;
- int rc;
-
- rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
- if (rc)
- {
- mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_seek", NULL, rc);
- return 0;
- }
-
- for (i = 0; i < str->len; i++)
- {
- char c;
- size_t n;
-
- rc = mu_stream_read (input->stream, &c, 1, &n);
- if (rc || n == 0 || c != str->ptr[i])
- return 0;
- }
- return 1;
-}
-
-/* istring(offset,"string")
- True if a case-insensitive comparison of the bytes is
- identical
-*/
-static int
-b_istring (union argument *args, struct input_file *input)
-{
- int i;
- struct mimetypes_string *str = args[1].string;
-
- int rc;
-
- rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
- if (rc)
- {
- mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_seek", NULL, rc);
- return 0;
- }
-
- for (i = 0; i < str->len; i++)
- {
- char c;
- size_t n;
-
- rc = mu_stream_read (input->stream, &c, 1, &n);
- if (rc || n == 0 || mu_tolower (c) != mu_tolower (str->ptr[i]))
- return 0;
- }
- return 1;
-}
-
-int
-compare_bytes (union argument *args, struct input_file *input,
- void *sample, void *buf, size_t size)
-{
- int rc;
- size_t n;
-
- rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
- if (rc)
- {
- mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_seek", NULL, rc);
- return 0;
- }
-
- rc = mu_stream_read (input->stream, buf, size, &n);
- if (rc)
- {
- mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_read", NULL, rc);
- return 0;
- }
- else if (n != size)
- return 0;
- return memcmp (sample, buf, size) == 0;
-}
-
-/* char(offset,value)
- True if byte is identical
-*/
-static int
-b_char (union argument *args, struct input_file *input)
-{
- char val = args[1].number;
- char buf;
- return compare_bytes (args, input, &val, &buf, sizeof (buf));
-}
-
-/* short(offset,value)
- True if 16-bit integer is identical
- FIXME: Byte order
-*/
-static int
-b_short (union argument *args, struct input_file *input)
-{
- uint16_t val = args[1].number;
- uint16_t buf;
- return compare_bytes (args, input, &val, &buf, sizeof (buf));
-}
-
-/* int(offset,value)
- True if 32-bit integer is identical
- FIXME: Byte order
-*/
-static int
-b_int (union argument *args, struct input_file *input)
-{
- uint32_t val = args[1].number;
- uint32_t buf;
- return compare_bytes (args, input, &val, &buf, sizeof (buf));
-}
-
-/* locale("string")
- True if current locale matches string
-*/
-static int
-b_locale (union argument *args, struct input_file *input)
-{
- abort (); /* FIXME */
- return 0;
-}
-
-/* contains(offset,range,"string")
- True if the range contains the string
-*/
-static int
-b_contains (union argument *args, struct input_file *input)
-{
- size_t i, count;
- char *buf;
- struct mimetypes_string *str = args[2].string;
- int rc;
-
- rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
- if (rc)
- {
- mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_seek", NULL, rc);
- return 0;
- }
-
- buf = mu_alloc (args[1].number);
- rc = mu_stream_read (input->stream, buf, args[1].number, &count);
- if (rc)
- {
- mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_read", NULL, rc);
- }
- else if (count > str->len)
- for (i = 0; i <= count - str->len; i++)
- if (buf[i] == str->ptr[0] && memcmp (buf + i, str->ptr, str->len) == 0)
- {
- free (buf);
- return 1;
- }
- free (buf);
- return 0;
-}
-
-#define MIME_MAX_BUFFER 4096
-
-/* regex(offset,"regex") True if bytes match regular expression
- */
-static int
-b_regex (union argument *args, struct input_file *input)
-{
- size_t count;
- int rc;
- char buf[MIME_MAX_BUFFER];
-
- rc = mu_stream_seek (input->stream, args[0].number, MU_SEEK_SET, NULL);
- if (rc)
- {
- mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_seek", NULL, rc);
- return 0;
- }
-
- rc = mu_stream_read (input->stream, buf, sizeof buf - 1, &count);
- if (rc)
- {
- mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_read", NULL, rc);
- return 0;
- }
- buf[count] = 0;
-
- return regexec (&args[1].rx, buf, 0, NULL, 0) == 0;
-}
-
-
-static struct builtin_tab builtin_tab[] = {
- { "match", "s", b_match },
- { "ascii", "dd", b_ascii },
- { "printable", "dd", b_printable },
- { "regex", "dx", b_regex },
- { "string", "ds", b_string },
- { "istring", "ds", b_istring },
- { "char", "dc", b_char },
- { "short", "dd", b_short },
- { "int", "dd", b_int },
- { "locale", "s", b_locale },
- { "contains", "dds", b_contains },
- { NULL }
-};
-
-struct node *
-make_functional_node (mu_mimetypes_t mth,
- char *ident, mu_list_t list,
- struct mu_locus_range const *loc)
-{
- size_t count, i;
- struct builtin_tab *p;
- struct node *node;
- union argument *args;
- mu_iterator_t itr;
- int rc;
-
- for (p = builtin_tab; ; p++)
- {
- if (!p->name)
- {
- yyerror (loc, NULL, NULL, _("%s: unknown function"), ident);
- return NULL;
- }
-
- if (strcmp (ident, p->name) == 0)
- break;
- }
-
- mu_list_count (list, &count);
- i = strlen (p->args);
-
- if (count < i)
- {
- yyerror (loc, NULL, NULL, _("too few arguments in call to `%s'"), ident);
- return NULL;
- }
- else if (count > i)
- {
- yyerror (loc, NULL, NULL, _("too many arguments in call to `%s'"), ident);
- return NULL;
- }
-
- args = mimetypes_malloc (mth, count * sizeof *args);
-
- mu_list_get_iterator (list, &itr);
- for (i = 0, mu_iterator_first (itr); !mu_iterator_is_done (itr);
- mu_iterator_next (itr), i++)
- {
- struct mimetypes_string *data;
- char *tmp;
-
- mu_iterator_current (itr, (void **)&data);
- switch (p->args[i])
- {
- case 'd':
- args[i].number = strtoul (data->ptr, &tmp, 0);
- if (*tmp)
- goto err;
- break;
-
- case 's':
- args[i].string = data;
- break;
-
- case 'x':
- {
- char *s;
-
- rc = mu_c_str_unescape_trans (data->ptr,
- "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v", &s);
- if (rc)
- {
- mu_diag_funcall (MU_DIAG_ERROR, "mu_c_str_unescape_trans",
- data->ptr, rc);
- return NULL;
- }
- rc = regcomp (&args[i].rx, s, REG_EXTENDED|REG_NOSUB);
- free (s);
- if (rc)
- {
- char errbuf[512];
- regerror (rc, &args[i].rx, errbuf, sizeof errbuf);
- yyerror (loc, NULL, NULL, "%s", errbuf);
- return NULL;
- }
- }
- break;
-
- case 'c':
- args[i].c = strtoul (data->ptr, &tmp, 0);
- if (*tmp)
- goto err;
- break;
-
- default:
- abort ();
- }
- }
-
- node = make_node (mth, functional_node, loc);
- node->v.function.fun = p->handler;
- node->v.function.args = args;
- return node;
-
- err:
- {
- yyerror (loc, NULL, NULL,
- _("argument %lu has wrong type in call to `%s'"),
- (unsigned long) i, ident);
- return NULL;
- }
-}
-
-static int
-check_suffix (char *suf, struct input_file *input)
-{
- char *p = strrchr (input->name, '.');
- if (!p)
- return 0;
- return strcmp (p+1, suf) == 0;
-}
-
-void
-mime_debug (int lev, struct mu_locus_range const *loc, char const *fmt, ...)
-{
- if (mu_debug_level_p (MU_DEBCAT_APP, lev))
- {
- va_list ap;
-
- if (loc->beg.mu_col == 0)
- mu_debug_log_begin ("%s:%u", loc->beg.mu_file, loc->beg.mu_line);
- else if (strcmp(loc->beg.mu_file, loc->end.mu_file))
- mu_debug_log_begin ("%s:%u.%u-%s:%u.%u",
- loc->beg.mu_file,
- loc->beg.mu_line, loc->beg.mu_col,
- loc->end.mu_file,
- loc->end.mu_line, loc->end.mu_col);
- else if (loc->beg.mu_line != loc->end.mu_line)
- mu_debug_log_begin ("%s:%u.%u-%u.%u",
- loc->beg.mu_file,
- loc->beg.mu_line, loc->beg.mu_col,
- loc->end.mu_line, loc->end.mu_col);
- else if (loc->beg.mu_col != loc->end.mu_col)
- mu_debug_log_begin ("%s:%u.%u-%u",
- loc->beg.mu_file,
- loc->beg.mu_line, loc->beg.mu_col,
- loc->end.mu_col);
- else
- mu_debug_log_begin ("%s:%u.%u",
- loc->beg.mu_file,
- loc->beg.mu_line, loc->beg.mu_col);
-
- mu_stream_write (mu_strerr, ": ", 2, NULL);
-
- va_start (ap, fmt);
- mu_stream_vprintf (mu_strerr, fmt, ap);
- va_end (ap);
- mu_debug_log_nl ();
- }
-}
-
-static int
-eval_rule (struct node *root, struct input_file *input)
-{
- int result;
-
- switch (root->type)
- {
- case true_node:
- result = 1;
- break;
-
- case functional_node:
- result = root->v.function.fun (root->v.function.args, input);
- break;
-
- case binary_node:
- result = eval_rule (root->v.bin.arg1, input);
- switch (root->v.bin.op)
- {
- case L_OR:
- if (!result)
- result |= eval_rule (root->v.bin.arg2, input);
- break;
-
- case L_AND:
- if (result)
- result &= eval_rule (root->v.bin.arg2, input);
- break;
-
- default:
- abort ();
- }
- break;
-
- case negation_node:
- result = !eval_rule (root->v.arg, input);
- break;
-
- case suffix_node:
- result = check_suffix (root->v.suffix.ptr, input);
- break;
-
- default:
- abort ();
- }
- mime_debug (MU_DEBUG_TRACE2, &root->loc, "result %s", result ? "true" : "false");
- return result;
-}
-
-static int
-evaluate (void **itmv, size_t itmc, void *call_data)
-{
- struct rule_tab *p = itmv[0];
- if (eval_rule (p->node, call_data))
- {
- itmv[0] = p;
- mime_debug (MU_DEBUG_TRACE1, &p->loc, "rule %s matches", p->type);
- return MU_LIST_MAP_OK;
- }
- return MU_LIST_MAP_SKIP;
-}
-
-static int
-rule_cmp (const void *a, const void *b)
-{
- struct rule_tab const *arule = a;
- struct rule_tab const *brule = b;
-
- if (arule->priority == brule->priority)
- {
- if (arule->node->type == true_node
- && brule->node->type != true_node)
- return 1;
- else if (brule->node->type == true_node
- && arule->node->type != true_node)
- return -1;
- else
- return mu_c_strcasecmp (arule->type, brule->type);
- }
- return arule->priority - brule->priority;
-}
-
-const char *
-mu_mimetypes_stream_type (mu_mimetypes_t mt, char const *name, mu_stream_t str)
-{
- mu_list_t res = NULL;
- const char *type = NULL;
- struct input_file input;
-
- input.name = name;
- input.stream = str;
-
- mu_stream_seek (str, 0, MU_SEEK_SET, NULL);
- mu_list_map (mt->rule_list, evaluate, &input, 1, &res);
- if (!mu_list_is_empty (res))
- {
- struct rule_tab *rule;
- mu_list_sort (res, rule_cmp);
- mu_list_head (res, (void**) &rule);
- mime_debug (MU_DEBUG_TRACE0, &rule->loc, "selected rule %s", rule->type);
- type = rule->type;
- }
- mu_list_destroy (&res);
- return type;
-}
-
-const char *
-mu_mimetypes_file_type (mu_mimetypes_t mt, const char *file)
-{
- int rc;
- mu_stream_t str;
- const char *res;
-
- rc = mu_file_stream_create (&str, file, MU_STREAM_READ);
- if (rc)
- {
- mu_error (_("Cannot open `%s': %s"), file, mu_strerror (rc));
- return NULL;
- }
- res = mu_mimetypes_stream_type (mt, file, str);
- mu_stream_destroy (&str);
- return res;
-}
-
-const char *
-mu_mimetypes_fd_type (mu_mimetypes_t mt, const char *file, int fd)
-{
- int rc;
- mu_stream_t str;
- const char *res;
-
- //FIXME: Fix 2nd argument in mu_fd_stream_create prototype
- rc = mu_fd_stream_create (&str, (char*) file, fd, MU_STREAM_READ);
- if (rc)
- {
- mu_error (_("Cannot open `%s': %s"), file, mu_strerror (rc));
- return NULL;
- }
- res = mu_mimetypes_stream_type (mt, file, str);
- mu_stream_destroy (&str);
- return res;
-}
diff --git a/mimeview/mimeview.c b/mimeview/mimeview.c
index acb719ddb..37cd3dc53 100644
--- a/mimeview/mimeview.c
+++ b/mimeview/mimeview.c
@@ -18,16 +18,22 @@
# include <config.h>
#endif
-#include <mimeview.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
-#include "mailutils/cli.h"
-#include "mailutils/argcv.h"
-
+#include <mailutils/alloc.h>
+#include <mailutils/cli.h>
+#include <mailutils/argcv.h>
+#include <mailutils/nls.h>
+#include <mailutils/io.h>
+#include <mailutils/header.h>
+#include <mailutils/errno.h>
+#include <mailutils/stream.h>
+#include <mailutils/stdstream.h>
+#include <mailutils/mimetypes.h>
#include "mailcap.h"
static int dry_run; /* Dry run mode */
@@ -63,7 +69,7 @@ cli_debug (struct mu_parseopt *po, struct mu_option *opt,
lev = MU_DEBUG_LEVEL_UPTO (MU_DEBUG_TRACE2);
else
{
- mu_debug_get_category_level (MU_DEBCAT_APP, &lev);
+ mu_debug_get_category_level (MU_DEBCAT_MIMETYPES, &lev);
for (; *arg; arg++)
{
switch (*arg)
@@ -85,7 +91,7 @@ cli_debug (struct mu_parseopt *po, struct mu_option *opt,
}
}
}
- mu_debug_set_category_level (MU_DEBCAT_APP, lev);
+ mu_debug_set_category_level (MU_DEBCAT_MIMETYPES, lev);
}
static void
@@ -186,11 +192,11 @@ display_file (const char *file, const char *type)
argv[5] = (char*) file;
argv[6] = NULL;
- if (mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE0))
+ if (mu_debug_level_p (MU_DEBCAT_MIMETYPES, MU_DEBUG_TRACE0))
{
char *string;
mu_argcv_string (6, argv, &string);
- mu_debug (MU_DEBCAT_APP, MU_DEBUG_TRACE0,
+ mu_debug (MU_DEBCAT_MIMETYPES, MU_DEBUG_TRACE0,
(_("executing %s...\n"), string));
free (string);
}
@@ -220,7 +226,7 @@ display_file (const char *file, const char *type)
{
display_stream_mailcap (file, str, hdr,
no_ask_types, interactive, dry_run,
- MU_DEBCAT_APP);
+ MU_DEBCAT_MIMETYPES);
mu_stream_destroy (&str);
}
mu_header_destroy (&hdr);
@@ -241,18 +247,18 @@ main (int argc, char **argv)
if (dry_run)
{
mu_debug_level_t lev;
- mu_debug_get_category_level (MU_DEBCAT_APP, &lev);
+ mu_debug_get_category_level (MU_DEBCAT_MIMETYPES, &lev);
lev |= MU_DEBUG_LEVEL_UPTO (MU_DEBUG_TRACE2);
- mu_debug_set_category_level (MU_DEBCAT_APP, lev);
+ mu_debug_set_category_level (MU_DEBCAT_MIMETYPES, lev);
}
if (argc == 0 && !lint)
{
- mu_error (_("no files given"));
+ mu_error ("%s", _("no files given"));
return 1;
}
- if ((mt = mimetypes_open (mimetypes_config)) == NULL)
+ if ((mt = mu_mimetypes_open (mimetypes_config)) == NULL)
return 1;
if (!lint)
{
@@ -264,6 +270,6 @@ main (int argc, char **argv)
}
}
mu_mimetypes_close (mt);
-
+
return 0;
}
diff --git a/mimeview/tests/testsuite.at b/mimeview/tests/testsuite.at
index cb60e782d..3959ce8e4 100644
--- a/mimeview/tests/testsuite.at
+++ b/mimeview/tests/testsuite.at
@@ -61,7 +61,7 @@ AT_KEYWORDS([mimeview])
AT_CHECK([
AT_DATA([mime.types],[$2
])
-mimeview MIMEVIEW_OPTIONS --debug-level=app.=trace6 -t -f mime.types
+mimeview MIMEVIEW_OPTIONS --debug-level=mimetypes.=trace6 -t -f mime.types
],
m4_shift(m4_shift($@)))
AT_CLEANUP
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 53a3680b3..04be5327d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -122,6 +122,10 @@ libmailutils/server/msrv.c
libmailutils/mailbox/mbx_default.c
libmailutils/mailer/mailer.c
+libmailutils/mimetypes/lexer.l
+libmailutils/mimetypes/grammar.y
+libmailutils/mimetypes/eval.c
+
libproto/mailer/smtp.c
libproto/mailer/smtp_gsasl.c
@@ -174,8 +178,6 @@ mh/send.c
mh/whatnow.c
mh/whom.c
-mimeview/lexer.l
-mimeview/grammar.y
mimeview/mimeview.c
movemail/movemail.c

Return to:

Send suggestions and report system problems to the System administrator.