]> mj.ucw.cz Git - paperjam.git/blobdiff - parse.cc
Better error messages from instantiating and running of commands
[paperjam.git] / parse.cc
index d3d92cd083df81a98bef9f263b85869bcb46b992..8e7de38b3aec6a52f57a3f72bb23a98158f3aee4 100644 (file)
--- a/parse.cc
+++ b/parse.cc
@@ -1,3 +1,9 @@
+/*
+ *     PaperJam -- Command parser
+ *
+ *     (c) 2018 Martin Mares <mj@ucw.cz>
+ */
+
 #include <cassert>
 #include <cstdarg>
 #include <cstdlib>
@@ -72,7 +78,8 @@ static token_type get_next_token()
       while (*in_pos >= 'A' && *in_pos <= 'Z' ||
             *in_pos >= 'a' && *in_pos <= 'z' ||
             *in_pos >= '0' && *in_pos <= '9' ||
-            *in_pos == '_')
+            *in_pos == '_' ||
+            *in_pos == '-')
        token += *in_pos++;
       return TOK_IDENT;
     }
@@ -182,7 +189,7 @@ public:
   string dump() { return "<string> \"" + val + '"'; }
 };
 
-static arg_val null_arg;
+arg_val null_arg;
 
 /*** Parser ***/
 
@@ -212,7 +219,14 @@ static double parse_dimen(const arg_def *adef)
 
   t = next_token();
   if (t != TOK_IDENT)
-    parse_error("Parameter %s must have a unit", adef->name);
+    {
+      if (is_zero(tmp))
+       {
+         return_token();
+         return 0;
+       }
+      parse_error("Parameter %s must have a unit", adef->name);
+    }
   for (uint i=0; units[i].name; i++)
     if (token == units[i].name)
       return tmp * units[i].multiplier;
@@ -281,8 +295,6 @@ static void parse_args(cmd *c)
   while (adefs[num_args].name)
     num_args++;
 
-  c->args.resize(num_args, &null_arg);
-
   token_type t = next_token();
   if (t != TOK_OPEN_PAREN)
     {
@@ -305,7 +317,7 @@ static void parse_args(cmd *c)
            argi++;
          if (!adefs[argi].name)
            parse_error("Command %s has no parameter %s", cdef->name, token.c_str());
-         if (c->args.at(argi)->given())
+         if (c->args.count(token))
            parse_error("Parameter %s given multiple times", token.c_str());
          t = next_token();
          if (t == TOK_EQUAL)
@@ -373,7 +385,7 @@ static void parse_args(cmd *c)
            parse_error("Parameter %s must have a value", adef->name);
        }
 
-      c->args.at(argi) = val;
+      c->args[adef->name] = val;
 
       t = next_token();
       if (t == TOK_CLOSE_PAREN)
@@ -383,17 +395,17 @@ static void parse_args(cmd *c)
     }
 
   for (uint i=0; i<num_args; i++)
-    if ((adefs[i].type & AT_MANDATORY) && !c->args.at(i)->given())
+    if ((adefs[i].type & AT_MANDATORY) && !c->args.count(adefs[i].name))
       parse_error("Command %s is missing a parameter %s", cdef->name, adefs[i].name);
 }
 
 static void debug_cmd(cmd *c, uint indent=0)
 {
   printf("%*sCommand %s\n", indent, "", c->def->name);
-  for (size_t i=0; i < c->args.size(); i++)
+  for (uint i=0; c->def->arg_defs[i].name; i++)
     {
       const arg_def *adef = &c->def->arg_defs[i];
-      string dump = c->args.at(i)->dump();
+      string dump = c->arg(adef->name)->dump();
       printf("%*sArg #%d: %s = %s\n", indent+4, "", (int) i, adef->name, dump.c_str());
     }
   if (c->pipe)
@@ -463,7 +475,14 @@ static void instantiate(list<cmd *> &cmds)
 {
   for (auto c: cmds)
     {
-      c->exec = c->def->constructor(c);
+      try
+       {
+         c->exec = c->def->constructor(c);
+       }
+      catch (exception &e)
+       {
+         die("Error in %s: %s", c->def->name, e.what());
+       }
       if (c->pipe)
        {
          for (auto pb: c->pipe->branches)
@@ -483,7 +502,7 @@ void parse(const char *in, list<cmd *> &cmds)
   instantiate(cmds);
 }
 
-void help()
+void parser_help()
 {
   for (int i=0; cmd_table[i].name; i++)
     {