summaryrefslogtreecommitdiff
path: root/mimeview/grammar.y
diff options
context:
space:
mode:
Diffstat (limited to 'mimeview/grammar.y')
-rw-r--r--mimeview/grammar.y1111
1 files changed, 0 insertions, 1111 deletions
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;
-}

Return to:

Send suggestions and report system problems to the System administrator.