20 action strstart { ts = p; }
22 action add_alternate {
23 std::string tmp (ts, p - ts); ts = 0;
24 alternates.push_back(tmp);
28 inapt_package *tmp_package = new inapt_package;
29 tmp_package->alternates.swap(alternates);
30 tmp_package->action = tmp_action->action;
31 tmp_package->linenum = curline;
32 tmp_package->filename = curfile;
33 tmp_package->predicates.swap(pkg_predicates);
34 tmp_action->packages.push_back(tmp_package);
37 action start_install {
38 tmp_action = new inapt_action;
39 tmp_action->action = inapt_action::INSTALL;
40 tmp_action->predicates.swap(cmd_predicates);
41 block_stack.back()->actions.push_back(tmp_action);
45 tmp_action = new inapt_action;
46 tmp_action->action = inapt_action::REMOVE;
47 tmp_action->predicates.swap(cmd_predicates);
48 block_stack.back()->actions.push_back(tmp_action);
52 inapt_profiles *tmp_profiles = new inapt_profiles;
53 tmp_profiles->profiles.swap(profiles);
54 tmp_profiles->predicates.swap(cmd_predicates);
55 block_stack.back()->profiles.push_back(tmp_profiles);
64 inapt_block *tmp_block = new inapt_block;
65 block_stack.push_back(tmp_block);
68 fatal("%s: %d: Syntax Error: Nesting Too Deep at '}'", curfile, curline);
76 fatal("%s: %d: Syntax Error: Unexpected '}'", curfile, curline);
80 action start_conditional {
81 inapt_conditional *cond = new inapt_conditional;
82 cond->condition = xstrndup(ts, p - ts); ts = 0;
83 conditional_stack.push_back(cond);
86 action full_conditional {
87 inapt_conditional *cond = conditional_stack.back(); conditional_stack.pop_back();
88 cond->else_block = block_stack.back(); block_stack.pop_back();
89 cond->then_block = block_stack.back(); block_stack.pop_back();
90 block_stack.back()->children.push_back(cond);
93 action half_conditional {
94 inapt_conditional *cond = conditional_stack.back(); conditional_stack.pop_back();
95 cond->else_block = NULL;
96 cond->then_block = block_stack.back(); block_stack.pop_back();
97 block_stack.back()->children.push_back(cond);
100 action pkg_predicate {
101 std::string tmp (ts, p - ts); ts = 0;
102 pkg_predicates.push_back(tmp);
105 action cmd_predicate {
106 std::string tmp (ts, p - ts); ts = 0;
107 cmd_predicates.push_back(tmp);
111 std::string tmp (ts, p - ts); ts = 0;
112 profiles.push_back(tmp);
115 newline = '\n' @newline;
116 comment = '#' (any - '\n')* newline;
117 whitespace = [\t\v\f\r ] | comment | newline;
118 profile = alpha (alpha | digit | '-' | '+' | '.')*;
119 package_name = ((lower | digit) (lower | digit | '+' | '-' | '.')+) >strstart;
120 pkg_predicate = '@' ('!'? profile) >strstart %pkg_predicate whitespace+;
121 cmd_predicate = '@' ('!'? profile) >strstart %cmd_predicate whitespace+;
122 package_alternates = package_name >strstart %add_alternate ('/' package_name >strstart %add_alternate)*;
123 package_list = ((whitespace+ pkg_predicate? package_alternates)+ %add_package whitespace*);
124 profile_list = (whitespace+ profile >strstart %profile)* whitespace*;
125 cmd_install = ('install' @start_install package_list ';');
126 cmd_remove = ('remove' @start_remove package_list ';');
127 cmd_profiles = ('profiles' profile_list ';' @add_profiles);
128 start_block = '{' @start_block;
129 end_block = '}' @end_block;
130 cmd_if = 'if' whitespace+ profile >strstart %start_conditional whitespace* start_block whitespace*
131 ('else' whitespace* start_block whitespace* ';' @full_conditional | ';' @half_conditional);
132 cmd = whitespace* (cmd_predicate? (cmd_install | cmd_remove | cmd_profiles) | cmd_if);
133 cmd_list = cmd* whitespace* end_block?;
139 void badsyntax(const char *filename, int lineno, char badchar, const char *message) {
142 message = "Unexpected newline";
143 else if (isspace(badchar))
144 message = "Unexpected whitespace";
146 message = "Syntax error";
149 if (isprint(badchar) && !isspace(badchar))
150 fatal("%s: %d: %s at '%c'", filename, lineno, message, badchar);
152 fatal("%s: %d: %s", filename, lineno, message);
155 void parser(const char *filename, inapt_block *top_block)
157 static char buf[BUFSIZE];
164 std::vector<inapt_block *> block_stack;
165 std::vector<inapt_conditional *> conditional_stack;
166 std::vector<std::string> alternates;
167 std::vector<std::string> cmd_predicates;
168 std::vector<std::string> pkg_predicates;
169 std::vector<std::string> profiles;
170 block_stack.push_back(top_block);
171 inapt_action *tmp_action = NULL;
176 const char *curfile = filename;
178 if (!filename || !strcmp(filename, "-")) {
182 fd = open(filename, O_RDONLY);
184 fatalpe("open: %s", filename);
190 char *p = buf + have, *pe, *eof = 0;
191 int len, space = BUFSIZE - have;
194 badsyntax(curfile, curline, 0, "Overlength token");
196 len = read(fd, p, space);
198 fatalpe("Unable to read spec");
208 if (cs == inapt_error)
209 badsyntax(curfile, curline, *p, NULL);
215 memmove(buf, ts, have);
220 if (cs < inapt_first_final)
221 badsyntax(curfile, curline, 0, "Unexpected EOF");
224 badsyntax(curfile, curline, 0, "Unclosed block at EOF");