]> mj.ucw.cz Git - paperjam.git/commitdiff
Better error messages from instantiating and running of commands
authorMartin Mares <mj@ucw.cz>
Fri, 6 Apr 2018 22:07:42 +0000 (00:07 +0200)
committerMartin Mares <mj@ucw.cz>
Fri, 6 Apr 2018 22:07:42 +0000 (00:07 +0200)
TODO
cmds.cc
jam.h
paperjam.cc
parse.cc
pdf.cc

diff --git a/TODO b/TODO
index 2463ead6980f9c23815066a41fdb7624740996ea..6583cfca65c9bb45ff6f42410d0a46954ab8ae83 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,8 +1,8 @@
 - Integrate pdf-tools.cc with the rest of the code
 - What if an input page specifies /Rotate?
-- Better error messages from instantiation
 - "-f" switch
 - Help
+- Clean up debugging messages, use more levels
 
 | # Position bbox on a new paper
 | paper("a4")
diff --git a/cmds.cc b/cmds.cc
index f86424461f5c3798babe65f34265f031bf62035c..c809884027c02b8e78ab7b6e0be30efcf3c1c3d3 100644 (file)
--- a/cmds.cc
+++ b/cmds.cc
@@ -86,13 +86,13 @@ public:
          return;
        }
       if (aw->given() != ah->given() || aname->given() == aw->given())
-       die("Either paper format name or width and height must be given");
+       err("Either paper format name or width and height must be given");
       if (aname->given())
        {
          const char *name = aname->as_string("").c_str();
          const paper *pap = paperinfo(name);
          if (!pap)
-           die("No paper called %s is known", name);
+           err("No paper called \"%s\" is known", name);
          w = paperpswidth(pap);
          h = paperpsheight(pap);
        }
@@ -118,7 +118,7 @@ public:
   pos_spec(string s)
     {
       if (s.size() != 2)
-        die("Value of pos must have two characters");
+        err("Value of pos must have two characters");
       if (s[0] == 't')
        v = 1;
       else if (s[0] == 'c')
@@ -126,7 +126,7 @@ public:
       else if (s[0] == 'b')
        v = -1;
       else
-       die("First character of pos must be t/c/b");
+       err("First character of pos must be t/c/b");
       if (s[1] == 'l')
        h = -1;
       else if (s[1] == 'c')
@@ -134,7 +134,7 @@ public:
       else if (s[1] == 'r')
        h = 1;
       else
-       die("Second character of pos must be l/c/r");
+       err("Second character of pos must be l/c/r");
     }
   pos_spec(cmd *c) : pos_spec(c->arg("pos")->as_string("cc")) { }
   pdf_matrix place(BBox &inner, BBox &outer)
@@ -202,7 +202,7 @@ public:
       bb->y_min += b;
       bb->y_max -= t;
       if (bb->x_min >= bb->x_max || bb->y_min >= bb->y_max)
-       die("Margins cannot be larger than the whole page");
+       err("Margins cannot be larger than the whole page");
     }
   void expand_box(BBox *bb)
     {
@@ -239,7 +239,7 @@ public:
   color_spec(string s)
     {
       if (s.length() != 6)
-       die("Invalid color specification \"%s\": expecting 6 hex digits", s.c_str());
+       err("Invalid color specification \"%s\": expecting 6 hex digits", s.c_str());
       for (int i=0; i<3; i++)
        {
          int x = 0;
@@ -302,7 +302,7 @@ public:
       else if (t == "bg")
        type = MARK_BG;
       else
-       die("Invalid cropmark type %s", t.c_str());
+       err("Invalid cropmark type %s", t.c_str());
 
       pen_width = c->arg(prefix + "pen")->as_double(0.2);
       arm_length = c->arg(prefix + "len")->as_double(5*mm);
@@ -474,7 +474,7 @@ public:
       if (deg < 0)
        deg += 360;
       if (deg % 90)
-       die("Rotate requires a multiple of 90 degrees");
+       err("The angle must be a multiple of 90 degrees");
     }
   page *process_page(page *p) override
     {
@@ -518,7 +518,7 @@ public:
       horizontal = c->arg("h")->as_int(0);
       vertical = c->arg("v")->as_int(0);
       if (!horizontal && !vertical)
-       die("Flip has no direction specified");
+       err("No direction specified");
     }
   page *process_page(page *p) override
     {
@@ -561,7 +561,7 @@ static int validate_page_index(vector<page *> &pages, int idx)
     return idx - 1;
   if (idx <= -1 && idx >= (int) -pages.size())
     return idx + pages.size();
-  die("Page index %d out of range", idx);
+  err("Page index %d out of range", idx);
 }
 
 vector<page *> select_cmd::process(vector<page *> &pages)
@@ -645,7 +645,7 @@ public:
     {
       n = c->arg("n")->as_int(0);
       if (n <= 0)
-       die("Modulo must have n > 0");
+       err("Modulo must have n > 0");
       half = c->arg("half")->as_int(0);
       pipe = c->pipe;
     }
@@ -678,7 +678,7 @@ vector<page *> modulo_cmd::process(vector<page *> &pages)
                  else if (i < 0 && i >= -n)
                    j = (tuples-1-tuple)*n + (-i) - 1;
                  else
-                   die("Modulo: invalid index %d", i);
+                   err("Invalid index %d", i);
                  if (j < (int) pages.size())
                    tmp.push_back(pages[j]);
                  else
@@ -768,7 +768,7 @@ public:
          else
            {
              if (!is_equal(width, p->width) || !is_equal(height, p->height))
-               die("All pages participating in a merge must have the same dimensions");
+               err("All pages must have the same dimensions");
              image_box.join(p->image_box);
            }
        }
@@ -901,7 +901,7 @@ public:
       q->width = p->width + marg.l + marg.r;
       q->height = p->height + marg.t + marg.b;
       if (q->width < 0.001 || q->height < 0.001)
-       die("Expansion must result in positive page dimensions");
+       err("Expansion must result in positive page dimensions");
       return q;
     }
 };
@@ -927,7 +927,7 @@ public:
       q->width = p->image_box.width() + marg.l + marg.r;
       q->height = p->image_box.height() + marg.t + marg.b;
       if (q->width < 0.001 || q->height < 0.001)
-       die("Margins must result in positive page dimensions");
+       err("Margins must result in positive page dimensions");
       return q;
     }
 };
@@ -985,7 +985,7 @@ public:
     {
       n = c->arg("n")->as_int(0);
       if (n % 4)
-        die("Number of pages per signature must be divisible by 4");
+        err("Number of pages per signature must be divisible by 4");
     }
   vector<page *> process(vector<page *> &pages) override;
 };
@@ -1069,7 +1069,7 @@ public:
       else if (grid_n > 0 && !grid_m)
        num_tiles = grid_n;
       else
-       die("Grid size must be at least 1x1");
+       err("Grid size must be at least 1x1");
 
       const string by = c->arg("by")->as_string("rows");
       if (by == "rows" || by == "row" || by == "r")
@@ -1079,7 +1079,7 @@ public:
       else if (by == "tile" || by == "t")
        fill_by = BY_TILE;
       else
-       die("Parameter \"by\" must be rows/cols/tile");
+       err("Parameter \"by\" must be rows/cols/tile");
 
       crop = c->arg("crop")->as_int(0);
       mixed = c->arg("mixed")->as_int(0);
@@ -1091,9 +1091,9 @@ public:
       vspace = c->arg("vspace")->as_double(space);
 
       if (!is_zero(scale) && (!is_zero(paper.w) || rotate >= 0))
-       die("When nup is used with explicit scaling, paper size nor rotation may be given");
+       err("When used with explicit scaling, paper size nor rotation may be given");
       if (!is_zero(scale) && !grid_m)
-       die("When nup is used with explicit scaling, both grid sizes must be given");
+       err("When used with explicit scaling, both grid sizes must be given");
     }
 
   vector<page *> process(vector<page *> &pages) override;
@@ -1250,7 +1250,7 @@ void nup_cmd::find_config(vector<page *> &in, BBox *page_boxes)
     }
 
   if (!found_solution)
-    die("Nup did not find a feasible solution");
+    err("No feasible solution found");
   debug("Best: %dx%d on %.3f x %.3f", best.cols, best.rows, best.paper_w, best.paper_h);
   debug_indent -= 4;
 }
@@ -1417,25 +1417,25 @@ static const arg_def clip_args[] = {
 template<typename T> cmd_exec *ctor(cmd *c) { return new T(c); }
 
 const cmd_def cmd_table[] = {
-  { "null",    no_args,        0,      &ctor<null_cmd>         },
-  { "move",    move_args,      0,      &ctor<move_cmd>         },
-  { "scale",   scale_args,     0,      &ctor<scale_cmd>        },
-  { "rotate",  rotate_args,    0,      &ctor<rotate_cmd>       },
-  { "flip",    flip_args,      0,      &ctor<flip_cmd>         },
-  { "select",  no_args,        1,      &ctor<select_cmd>       },
+  { "add-blank",add_blank_args,        0,      &ctor<add_blank_cmd>    },
   { "apply",   no_args,        1,      &ctor<apply_cmd>        },
-  { "modulo",  modulo_args,    1,      &ctor<modulo_cmd>       },
+  { "book",    book_args,      0,      &ctor<book_cmd>         },
+  { "clip",    clip_args,      0,      &ctor<clip_cmd>         },
+  { "cropmarks",cropmarks_args,        0,      &ctor<cropmarks_cmd>    },
   { "debug",   no_args,        0,      &ctor<debug_cmd>        },
-  { "merge",   no_args,        0,      &ctor<merge_cmd>        },
-  { "paper",   paper_args,     0,      &ctor<paper_cmd>        },
-  { "scaleto", scaleto_args,   0,      &ctor<scaleto_cmd>      },
-  { "fit",     fit_args,       0,      &ctor<fit_cmd>          },
   { "expand",  expand_args,    0,      &ctor<expand_cmd>       },
+  { "fit",     fit_args,       0,      &ctor<fit_cmd>          },
+  { "flip",    flip_args,      0,      &ctor<flip_cmd>         },
   { "margins", margins_args,   0,      &ctor<margins_cmd>      },
-  { "add-blank",add_blank_args,        0,      &ctor<add_blank_cmd>    },
-  { "book",    book_args,      0,      &ctor<book_cmd>         },
+  { "merge",   no_args,        0,      &ctor<merge_cmd>        },
+  { "modulo",  modulo_args,    1,      &ctor<modulo_cmd>       },
+  { "move",    move_args,      0,      &ctor<move_cmd>         },
+  { "null",    no_args,        0,      &ctor<null_cmd>         },
   { "nup",     nup_args,       0,      &ctor<nup_cmd>          },
-  { "cropmarks",cropmarks_args,        0,      &ctor<cropmarks_cmd>    },
-  { "clip",    clip_args,      0,      &ctor<clip_cmd>         },
+  { "paper",   paper_args,     0,      &ctor<paper_cmd>        },
+  { "rotate",  rotate_args,    0,      &ctor<rotate_cmd>       },
+  { "scale",   scale_args,     0,      &ctor<scale_cmd>        },
+  { "scaleto", scaleto_args,   0,      &ctor<scaleto_cmd>      },
+  { "select",  no_args,        1,      &ctor<select_cmd>       },
   { NULL,      NULL,           0,      NULL    }
 };
diff --git a/jam.h b/jam.h
index 10f547ac55ad7dfe9c58575204a04e9818446328..b70041b4e2e9a11cab68108532c9aba5cbf1b609 100644 (file)
--- a/jam.h
+++ b/jam.h
@@ -146,6 +146,16 @@ void debug(const char *msg, ...) FORMAT_CHECK(printf, 1, 2);
 void warn(const char *msg, ...) FORMAT_CHECK(printf, 1, 2);
 void die(const char *msg, ...) FORMAT_CHECK(printf, 1, 2) NONRET;
 
+// This one is called during execution of commands and propagated as an exception
+void err(const char *msg, ...) FORMAT_CHECK(printf, 1, 2) NONRET;
+
+class paperjam_error : public exception {
+  string message;
+public:
+  paperjam_error(string m) : message(m) { }
+  const char *what() const noexcept override { return message.c_str(); }
+};
+
 // parse.cc
 
 void parse(const char *in, list<cmd *> &cmds);
index 5aa4c6139fd76814a3d6297ced7a339ebd1201eb..f5a08f97da4a4ccd762ca3ea21207d7bd9abfa52 100644 (file)
@@ -54,6 +54,16 @@ void die(const char *msg, ...)
   exit(1);
 }
 
+void err(const char *msg, ...)
+{
+  va_list args;
+  va_start(args, msg);
+  char buf[1024];
+  vsnprintf(buf, sizeof(buf), msg, args);
+  va_end(args);
+  throw paperjam_error(buf);
+}
+
 /*** Arguments ***/
 
 enum opt {
index b48b2f44c0fc1a4520cb8f82b42a1907d9fc12c0..8e7de38b3aec6a52f57a3f72bb23a98158f3aee4 100644 (file)
--- a/parse.cc
+++ b/parse.cc
@@ -475,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)
diff --git a/pdf.cc b/pdf.cc
index 0c9b27b491be88b3b248d4901b692e2820bfd2a9..f262f5ba6952554dde4444fbd572aaab2d4c547f 100644 (file)
--- a/pdf.cc
+++ b/pdf.cc
@@ -94,7 +94,14 @@ vector<page *> run_command_list(list<cmd *> &cmds, vector<page *> &pages)
     {
       debug("# Executing %s", c->def->name);
       debug_indent += 4;
-      pages = c->exec->process(pages);
+      try
+       {
+         pages = c->exec->process(pages);
+       }
+      catch (exception &e)
+       {
+         die("Error in %s: %s", c->def->name, e.what());
+       }
       debug_indent -= 4;
       debug_pages(pages);
     }