From a4b921dcbcc63c6ac28949d16be531f2f4465eab Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sat, 7 Apr 2018 00:07:42 +0200 Subject: [PATCH] Better error messages from instantiating and running of commands --- TODO | 2 +- cmds.cc | 74 ++++++++++++++++++++++++++--------------------------- jam.h | 10 ++++++++ paperjam.cc | 10 ++++++++ parse.cc | 9 ++++++- pdf.cc | 9 ++++++- 6 files changed, 74 insertions(+), 40 deletions(-) diff --git a/TODO b/TODO index 2463ead..6583cfc 100644 --- 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 f864244..c809884 100644 --- 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 &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 select_cmd::process(vector &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 modulo_cmd::process(vector &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 process(vector &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 process(vector &pages) override; @@ -1250,7 +1250,7 @@ void nup_cmd::find_config(vector &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 cmd_exec *ctor(cmd *c) { return new T(c); } const cmd_def cmd_table[] = { - { "null", no_args, 0, &ctor }, - { "move", move_args, 0, &ctor }, - { "scale", scale_args, 0, &ctor }, - { "rotate", rotate_args, 0, &ctor }, - { "flip", flip_args, 0, &ctor }, - { "select", no_args, 1, &ctor }, + { "add-blank",add_blank_args, 0, &ctor }, { "apply", no_args, 1, &ctor }, - { "modulo", modulo_args, 1, &ctor }, + { "book", book_args, 0, &ctor }, + { "clip", clip_args, 0, &ctor }, + { "cropmarks",cropmarks_args, 0, &ctor }, { "debug", no_args, 0, &ctor }, - { "merge", no_args, 0, &ctor }, - { "paper", paper_args, 0, &ctor }, - { "scaleto", scaleto_args, 0, &ctor }, - { "fit", fit_args, 0, &ctor }, { "expand", expand_args, 0, &ctor }, + { "fit", fit_args, 0, &ctor }, + { "flip", flip_args, 0, &ctor }, { "margins", margins_args, 0, &ctor }, - { "add-blank",add_blank_args, 0, &ctor }, - { "book", book_args, 0, &ctor }, + { "merge", no_args, 0, &ctor }, + { "modulo", modulo_args, 1, &ctor }, + { "move", move_args, 0, &ctor }, + { "null", no_args, 0, &ctor }, { "nup", nup_args, 0, &ctor }, - { "cropmarks",cropmarks_args, 0, &ctor }, - { "clip", clip_args, 0, &ctor }, + { "paper", paper_args, 0, &ctor }, + { "rotate", rotate_args, 0, &ctor }, + { "scale", scale_args, 0, &ctor }, + { "scaleto", scaleto_args, 0, &ctor }, + { "select", no_args, 1, &ctor }, { NULL, NULL, 0, NULL } }; diff --git a/jam.h b/jam.h index 10f547a..b70041b 100644 --- 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 &cmds); diff --git a/paperjam.cc b/paperjam.cc index 5aa4c61..f5a08f9 100644 --- a/paperjam.cc +++ b/paperjam.cc @@ -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 { diff --git a/parse.cc b/parse.cc index b48b2f4..8e7de38 100644 --- a/parse.cc +++ b/parse.cc @@ -475,7 +475,14 @@ static void instantiate(list &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 0c9b27b..f262f5b 100644 --- a/pdf.cc +++ b/pdf.cc @@ -94,7 +94,14 @@ vector run_command_list(list &cmds, vector &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); } -- 2.39.2