From bb6a7cf9ecaec1dbd2837fdddc866be285ce053a Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Mon, 2 Apr 2018 11:05:33 +0200 Subject: [PATCH] Flip and switch parameters --- cmds.cc | 47 +++++++++++++++++++++++++++++++++ jam.h | 1 + parse.cc | 79 ++++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 99 insertions(+), 28 deletions(-) diff --git a/cmds.cc b/cmds.cc index 24fb0a4..ca3f81f 100644 --- a/cmds.cc +++ b/cmds.cc @@ -171,6 +171,52 @@ static cmd_exec *rotate_ctor(cmd *c) return r; } +/*** flip ***/ + +class flip_cmd : public cmd_exec { +public: + bool horizontal; + bool vertical; + vector process(vector &pages); +}; + +vector flip_cmd::process(vector &pages) +{ + vector out; + for (auto p: pages) + { + pdf_matrix m; + if (vertical) + { + m.scale(1, -1); + m.shift(0, p->height); + } + if (horizontal) + { + m.scale(-1, 1); + m.shift(p->width, 0); + } + out.push_back(new xform_page(p, m)); + } + return out; +} + +static const arg_def flip_args[] = { + { "h", AT_SWITCH }, + { "v", AT_SWITCH }, + { NULL, 0 } +}; + +static cmd_exec *flip_ctor(cmd *c) +{ + flip_cmd *f = new flip_cmd; + f->horizontal = c->args.at(0)->as_int(0); + f->vertical = c->args.at(1)->as_int(0); + if (!f->horizontal && !f->vertical) + die("Flip has no direction specified"); + return f; +} + /*** select ***/ class select_cmd : public cmd_exec { @@ -383,6 +429,7 @@ const cmd_def cmd_table[] = { { "move", move_args, 0, move_ctor }, { "scale", scale_args, 0, scale_ctor }, { "rotate", rotate_args, 0, rotate_ctor }, + { "flip", flip_args, 0, flip_ctor }, { "select", no_args, 1, select_ctor }, { "apply", no_args, 1, apply_ctor }, { "modulo", modulo_args, 1, modulo_ctor }, diff --git a/jam.h b/jam.h index a966cea..002ad04 100644 --- a/jam.h +++ b/jam.h @@ -18,6 +18,7 @@ enum arg_type { AT_INT, AT_DOUBLE, AT_DIMEN, + AT_SWITCH, AT_TYPE_MASK = 0xffff, AT_MANDATORY = 0x10000, AT_POSITIONAL = 0x20000, diff --git a/parse.cc b/parse.cc index 1869b3a..d3d92cd 100644 --- a/parse.cc +++ b/parse.cc @@ -295,7 +295,10 @@ static void parse_args(cmd *c) for (;;) { t = next_token(); + if (t == TOK_CLOSE_PAREN) + break; uint argi = 0; + bool has_value = false; if (t == TOK_IDENT) { while (adefs[argi].name && token != adefs[argi].name) @@ -305,8 +308,10 @@ static void parse_args(cmd *c) if (c->args.at(argi)->given()) parse_error("Parameter %s given multiple times", token.c_str()); t = next_token(); - if (t != TOK_EQUAL) - parse_error("Parameter name must be followed by '='"); + if (t == TOK_EQUAL) + has_value = true; + else + return_token(); saw_named = true; } else if (saw_named) @@ -319,35 +324,53 @@ static void parse_args(cmd *c) if (next_pos >= num_args) parse_error("Too many positional arguments for command %s", cdef->name); argi = next_pos++; + has_value = true; } const arg_def *adef = &adefs[argi]; + uint type = adef->type & AT_TYPE_MASK; arg_val *val = NULL; - switch (adef->type & AT_TYPE_MASK) - { - case AT_STRING: - t = next_token(); - if (t != TOK_STRING) - parse_error("Parameter %s must be a string", adef->name); - val = new arg_string(token); - break; - case AT_INT: - t = next_token(); - if (t != TOK_NUMBER || !token_is_int()) - parse_error("Parameter %s must be an integer", adef->name); - val = new arg_int((int) token_num); - break; - case AT_DOUBLE: - t = next_token(); - if (t != TOK_NUMBER) - parse_error("Parameter %s must be a number", adef->name); - val = new arg_double(token_num); - break; - case AT_DIMEN: - val = new arg_double(parse_dimen(adef)); - break; - default: - abort(); + if (has_value) + { + switch (type) + { + case AT_STRING: + t = next_token(); + if (t != TOK_STRING) + parse_error("Parameter %s must be a string", adef->name); + val = new arg_string(token); + break; + case AT_INT: + t = next_token(); + if (t != TOK_NUMBER || !token_is_int()) + parse_error("Parameter %s must be an integer", adef->name); + val = new arg_int((int) token_num); + break; + case AT_DOUBLE: + t = next_token(); + if (t != TOK_NUMBER) + parse_error("Parameter %s must be a number", adef->name); + val = new arg_double(token_num); + break; + case AT_DIMEN: + val = new arg_double(parse_dimen(adef)); + break; + case AT_SWITCH: + t = next_token(); + if (t != TOK_NUMBER || !token_is_int() || ((int) token_num != 0 && (int) token_num != 1)) + parse_error("Parameter %s must be a switch", adef->name); + val = new arg_int((int) token_num); + break; + default: + abort(); + } + } + else + { + if (type == AT_SWITCH) + val = new arg_int(1); + else + parse_error("Parameter %s must have a value", adef->name); } c->args.at(argi) = val; @@ -469,7 +492,7 @@ void help() const arg_def *arg = def->arg_defs; static const char * const type_names[] = { - "string", "int", "double", "dimen" + "string", "int", "double", "dimen", "switch" }; while (arg->name) { -- 2.39.5