summaryrefslogtreecommitdiff
path: root/mimetypes/grammar.y
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-01-03 12:23:44 +0200
committerSergey Poznyakoff <gray@gnu.org>2018-01-03 12:23:52 +0200
commit80ed5e611de0e31eed65ee207f1fd64ad097e6d1 (patch)
tree40979fe5ecadaa3d1351c645ff7988a87218e142 /mimetypes/grammar.y
parenta4edd153e4cdf703c98008313743b112274e760f (diff)
downloadfileserv-80ed5e611de0e31eed65ee207f1fd64ad097e6d1.tar.gz
fileserv-80ed5e611de0e31eed65ee207f1fd64ad097e6d1.tar.bz2
Add mimetypes library.
Ported from GNU Mailutils.
Diffstat (limited to 'mimetypes/grammar.y')
-rw-r--r--mimetypes/grammar.y397
1 files changed, 397 insertions, 0 deletions
diff --git a/mimetypes/grammar.y b/mimetypes/grammar.y
new file mode 100644
index 0000000..2ae1997
--- /dev/null
+++ b/mimetypes/grammar.y
@@ -0,0 +1,397 @@
+%{
+/* This file is part of fileserv.
+ Copyright (C) 2017, 2018 Sergey Poznyakoff
+
+ Fileserv 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.
+
+ Fileserv 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 fileserv. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <ctype.h>
+#include "mtint.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 (isprint (toknum))
+ fprintf (output, "'%c'", toknum);
+ else
+ fprintf (output, "tok(%d)", toknum);
+ break;
+ }
+}
+
+#define YYPRINT yyprint
+
+
+static void
+arg_list_append (struct arg_list *al, struct mimetypes_string const *str)
+{
+ struct arg_elt *elt;
+ elt = malloc (sizeof *elt);
+ elt->string.ptr = str->ptr;
+ elt->string.len = str->len;
+ LLE_APPEND (al, elt, link);
+}
+
+static void
+arg_list_destroy (struct arg_list *al)
+{
+ struct arg_elt *elt;
+ while ((elt = LL_FIRST (al)) != NULL)
+ {
+ /* FIXME: free? */
+ LLE_UNLINK (al, elt, link);
+ }
+}
+
+//FIXME
+struct rule_list rule_list = LL_HEAD_INITIALIZER;
+
+static struct node *make_node (enum node_type type,
+ struct locus_range const *loc);
+static struct node *make_binary_node (int op,
+ struct node *left, struct node *rigth,
+ struct locus_range const *loc);
+static struct node *make_negation_node (struct node *p,
+ struct locus_range const *loc);
+
+static struct node *make_suffix_node (struct mimetypes_string *suffix,
+ struct locus_range const *loc);
+static struct node *make_functional_node (char *ident, struct arg_list *list,
+ struct locus_range const *loc);
+
+static size_t errors;
+%}
+
+%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;
+ struct arg_list 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 *p = malloc (sizeof (*p));
+ LLE_APPEND (&rule_list, p, link);
+ p->type = $1.ptr;
+ p->node = $2;
+ p->priority = $3;
+ locus_point_copy (&p->loc.beg, &@1.beg);
+ locus_point_copy (&p->loc.end, &@3.end);
+#if 0
+ YY_LOCATION_PRINT (stderr, p->loc);
+ fprintf (stderr, ": rule %s\n", p->type);
+#endif
+ }
+ | BOGUS
+ {
+ YYERROR;
+ }
+ | error
+ {
+ errors++;
+ // arg_list_destroy (); //FIXME
+ lex_next_rule ();
+ yyerrok;
+ yyclearin;
+ }
+ ;
+
+maybe_rule: /* empty */
+ {
+ $$ = make_node (true_node, &yylloc);
+ }
+ | rule
+ ;
+
+rule : stmt
+ | rule rule %prec ','
+ {
+ struct locus_range lr;
+ lr.beg = @1.beg;
+ lr.end = @2.end;
+ $$ = make_binary_node (L_OR, $1, $2, &lr);
+ }
+ | rule ',' rule
+ {
+ struct locus_range lr;
+ lr.beg = @1.beg;
+ lr.end = @3.end;
+ $$ = make_binary_node (L_OR, $1, $3, &lr);
+ }
+ | rule '+' rule
+ {
+ struct locus_range lr;
+ lr.beg = @1.beg;
+ lr.end = @3.end;
+ $$ = make_binary_node (L_AND, $1, $3, &lr);
+ }
+ ;
+
+stmt : '!' stmt
+ {
+ $$ = make_negation_node ($2, &@2);
+ }
+ | '(' rule ')'
+ {
+ $$ = $2;
+ }
+ | STRING
+ {
+ $$ = make_suffix_node (&$1, &@1);
+ }
+ | function
+ | BOGUS
+ {
+ YYERROR;
+ }
+ ;
+
+priority : PRIORITY '(' arglist ')'
+ {
+ if (LL_COUNT (&$3) != 1)
+ {
+ mimetypes_error_at (&@1, "priority takes single numberic argument");
+ YYERROR;
+ }
+ $$ = atoi (LL_FIRST (&$3)->string.ptr);
+ arg_list_destroy (&$3);
+ }
+ ;
+
+maybe_priority: /* empty */
+ {
+ $$ = 100;
+ }
+ | priority
+ ;
+
+function : IDENT '(' arglist ')'
+ {
+ struct locus_range lr;
+ lr.beg = @1.beg;
+ lr.end = @4.end;
+
+ $$ = make_functional_node ($1.ptr, &$3, &lr);
+ if (!$$)
+ YYERROR;
+ }
+ ;
+
+arglist : arg
+ {
+ LL_HEAD_INIT (&$$);
+ arg_list_append (&$$, &$1);
+ }
+ | arglist ',' arg
+ {
+ arg_list_append (&$1, &$3);
+ $$ = $1;
+ }
+ ;
+
+arg : STRING
+ | BOGUS
+ {
+ YYERROR;
+ }
+ ;
+
+%%
+
+int
+mimetypes_parse (const char *name)
+{
+ int rc;
+ char *p;
+ if (mimetypes_open (name))
+ return 1;
+ p = getenv ("MIMETYPE_DEBUG_GRAM");
+ yydebug = p ? (*p - '0') : 0;
+ rc = yyparse ();
+ mimetypes_close ();
+ return rc || errors;
+}
+
+static struct node *
+make_node (enum node_type type, struct locus_range const *loc)
+{
+ struct node *p = malloc (sizeof *p);
+ p->type = type;
+ locus_range_init (&p->loc);
+ locus_range_copy (&p->loc, loc);
+ return p;
+}
+
+static struct node *
+make_binary_node (int op, struct node *left, struct node *right,
+ struct locus_range const *loc)
+{
+ struct node *node = make_node (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 (struct node *p, struct locus_range const *loc)
+{
+ struct node *node = make_node (negation_node, loc);
+ node->v.arg = p;
+ return node;
+}
+
+struct node *
+make_suffix_node (struct mimetypes_string *suffix,
+ struct locus_range const *loc)
+{
+ struct node *node = make_node (suffix_node, loc);
+ node->v.suffix = *suffix;
+ return node;
+}
+
+
+struct node *
+make_functional_node (char *ident, struct arg_list *list,
+ struct locus_range const *loc)
+{
+ size_t count, i;
+ struct builtin_tab const *p;
+ struct node *node;
+ union argument *args;
+ struct arg_elt *elt;
+
+ p = find_builtin (ident);
+ if (!p)
+ {
+ mimetypes_error_at (loc, "unknown builtin: %s", ident);
+ return NULL;
+ }
+
+ count = LL_COUNT (list);
+ i = strlen (p->args);
+
+ if (count < i)
+ {
+ mimetypes_error_at (loc, "too few arguments in call to %s", ident);
+ return NULL;
+ }
+ else if (count > i)
+ {
+ mimetypes_error_at (loc, "too many arguments in call to %s", ident);
+ return NULL;
+ }
+
+ args = calloc (count, sizeof *args);
+ i = 0;
+ LL_FOREACH (list, elt, link)
+ {
+ char *tmp;
+
+ switch (p->args[i])
+ {
+ case 'd':
+ args[i].number = strtoul (elt->string.ptr, &tmp, 0);
+ if (*tmp)
+ goto err;
+ break;
+
+ case 's':
+ args[i].string = elt->string;
+ break;
+
+ case 'x':
+ {
+ int rc = regcomp (&args[i].rx, elt->string.ptr,
+ REG_EXTENDED|REG_NOSUB);
+ if (rc)
+ {
+ char errbuf[512];
+ regerror (rc, &args[i].rx, errbuf, sizeof errbuf);
+ mimetypes_error_at (loc, "%s", errbuf);
+ return NULL;
+ }
+ }
+ break;
+
+ case 'c':
+ args[i].c = strtoul (elt->string.ptr, &tmp, 0);
+ if (*tmp)
+ goto err;
+ break;
+
+ default:
+ abort ();
+ }
+ i++;
+ }
+
+ node = make_node (functional_node, loc);
+ node->v.function.fun = p->handler;
+ node->v.function.args = args;
+ return node;
+
+ err:
+ mimetypes_error_at (loc, "argument %lu has wrong type in call to %s",
+ (unsigned long) i, ident);
+ return NULL;
+}
+
+
+

Return to:

Send suggestions and report system problems to the System administrator.