20 action strstart { ts = p; }
23 inapt_action *tmp_action = new inapt_action;
24 tmp_action->package = xstrndup(ts, p - ts); ts = 0;
25 tmp_action->action = curaction;
26 tmp_action->linenum = curline;
27 tmp_action->filename = curfile;
29 tmp_action->predicates.push_back(cmd_predicate);
31 tmp_action->predicates.push_back(pkg_predicate);
34 block_stack.back()->actions.push_back(tmp_action);
38 curaction = inapt_action::INSTALL;
42 curaction = inapt_action::REMOVE;
51 inapt_block *tmp_block = new inapt_block;
52 block_stack.push_back(tmp_block);
55 fatal("%s: %d: Syntax Error: Nesting Too Deep at '}'", curfile, curline);
63 fatal("%s: %d: Syntax Error: Unexpected '}'", curfile, curline);
67 action start_conditional {
68 inapt_conditional *cond = new inapt_conditional;
69 cond->condition = xstrndup(ts, p - ts); ts = 0;
70 conditional_stack.push_back(cond);
73 action full_conditional {
74 inapt_conditional *cond = conditional_stack.back(); conditional_stack.pop_back();
75 cond->else_block = block_stack.back(); block_stack.pop_back();
76 cond->then_block = block_stack.back(); block_stack.pop_back();
77 block_stack.back()->children.push_back(cond);
80 action half_conditional {
81 inapt_conditional *cond = conditional_stack.back(); conditional_stack.pop_back();
82 cond->else_block = NULL;
83 cond->then_block = block_stack.back(); block_stack.pop_back();
84 block_stack.back()->children.push_back(cond);
87 action pkg_predicate {
89 fatal("pkg_predicate already set");
90 pkg_predicate = xstrndup(ts, p - ts); ts = 0;
93 action cmd_predicate {
95 fatal("cmd_predicate already set");
96 cmd_predicate = xstrndup(ts, p - ts); ts = 0;
99 action clear_cmd_predicate {
100 cmd_predicate = NULL;
103 newline = '\n' @newline;
104 comment = '#' (any - '\n')* newline;
105 whitespace = [\t\v\f\r ] | comment | newline;
106 macro = '!'? alpha (alpha | digit | '-' | '+' | '.')*;
107 package_name = ((lower | digit) (lower | digit | '+' | '-' | '.')+) >strstart;
108 pkg_predicate = '@' macro >strstart %pkg_predicate whitespace+;
109 cmd_predicate = '@' macro >strstart %cmd_predicate whitespace+;
110 package_list = ((whitespace+ pkg_predicate? package_name)+ %add_list whitespace*);
111 cmd_install = ('install' @install package_list ';' @clear_cmd_predicate);
112 cmd_remove = ('remove' @remove package_list ';' @clear_cmd_predicate);
113 start_block = '{' @start_block;
114 end_block = '}' @end_block;
115 cmd_if = 'if' whitespace+ macro >strstart %start_conditional whitespace* start_block whitespace*
116 ('else' whitespace* start_block whitespace* ';' @full_conditional | ';' @half_conditional);
117 cmd = whitespace* (cmd_predicate? (cmd_install | cmd_remove) | cmd_if);
118 cmd_list = cmd* whitespace* end_block?;
124 void badsyntax(const char *filename, int lineno, char badchar, const char *message) {
127 message = "Unexpected newline";
128 else if (isspace(badchar))
129 message = "Unexpected whitespace";
131 message = "Syntax error";
134 if (isprint(badchar) && !isspace(badchar))
135 fatal("%s: %d: %s at '%c'", filename, lineno, message, badchar);
137 fatal("%s: %d: %s", filename, lineno, message);
140 void parser(const char *filename, inapt_block *top_block)
142 static char buf[BUFSIZE];
148 char *cmd_predicate = NULL, *pkg_predicate = NULL;
150 std::vector<inapt_block *> block_stack;
151 std::vector<inapt_conditional *> conditional_stack;
152 block_stack.push_back(top_block);
157 const char *curfile = filename;
158 enum inapt_action::action_t curaction = inapt_action::UNSET;
161 fd = open(filename, O_RDONLY);
163 fatalpe("open: %s", filename);
172 char *p = buf + have, *pe, *eof = 0;
173 int len, space = BUFSIZE - have;
176 badsyntax(curfile, curline, 0, "Overlength token");
178 len = read(fd, p, space);
180 fatalpe("Unable to read spec");
190 if (cs == inapt_error)
191 badsyntax(curfile, curline, *p, NULL);
197 memmove(buf, ts, have);
202 if (cs < inapt_first_final)
203 badsyntax(curfile, curline, 0, "Unexpected EOF");
206 badsyntax(curfile, curline, 0, "Unclosed block at EOF");