]> git.ipfire.org Git - pakfire.git/blame - src/libpakfire/parser/grammar.y
libpakfire: parser: assignments and block assigments are the same thing
[pakfire.git] / src / libpakfire / parser / grammar.y
CommitLineData
f9a691ef
MT
1/*#############################################################################
2# #
3# Pakfire - The IPFire package management system #
4# Copyright (C) 2019 Pakfire development team #
5# #
6# This program is free software: you can redistribute it and/or modify #
7# it under the terms of the GNU General Public License as published by #
8# the Free Software Foundation, either version 3 of the License, or #
9# (at your option) any later version. #
10# #
11# This program is distributed in the hope that it will be useful, #
12# but WITHOUT ANY WARRANTY; without even the implied warranty of #
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14# GNU General Public License for more details. #
15# #
16# You should have received a copy of the GNU General Public License #
17# along with this program. If not, see <http://www.gnu.org/licenses/>. #
18# #
19#############################################################################*/
20
21%{
4f2a7bce
MT
22#include <stdio.h>
23
a0258b56 24#include <pakfire/logging.h>
23188111 25#include <pakfire/parser.h>
35ebb186 26#include <pakfire/types.h>
23188111 27#include <pakfire/util.h>
35ebb186 28
f9a691ef
MT
29#define YYERROR_VERBOSE 1
30
31typedef struct yy_buffer_state* YY_BUFFER_STATE;
32extern YY_BUFFER_STATE yy_scan_bytes(const char* buffer, size_t len);
33extern void yy_delete_buffer(YY_BUFFER_STATE buffer);
34
35extern int yylex();
36extern int yyparse();
6ab14b96
MT
37
38extern int num_lines;
e98f46a7
MT
39static Pakfire pakfire;
40static void yyerror(const char* s);
6b03e625 41
4f2a7bce
MT
42static void cleanup(void);
43#define ABORT do { cleanup(); YYABORT; } while (0);
44
23188111
MT
45#define NUM_DECLARATIONS 128
46static int pakfire_parser_add_declaration(const char* name, const char* value);
47static struct pakfire_parser_declaration* declarations[NUM_DECLARATIONS];
3b1b9cbd
MT
48
49char* current_block = NULL;
f9a691ef
MT
50%}
51
52%token APPEND
53%token ASSIGN
54%token DEFINE
55%token END
56%token NEWLINE
57%token TAB
f9a691ef 58%token WHITESPACE
6b03e625 59%token <string> WORD
f9a691ef 60
68f7a6f7
MT
61%type <string> line;
62%type <string> text;
28afa9c2
MT
63%type <string> variable;
64%type <string> value;
6b03e625 65%type <string> words;
28afa9c2
MT
66
67%union {
68 char* string;
69}
f9a691ef 70
28afa9c2 71%%
70425a92 72
59f7b7f0
MT
73top : top thing
74 | thing
75 ;
76
77thing : block
28afa9c2 78 | empty
28afa9c2
MT
79 ;
80
81empty : WHITESPACE NEWLINE
82 | NEWLINE
83 ;
84
85// Optional whitespace
86whitespace : WHITESPACE
87 | /* empty */
88 ;
89
6b03e625 90variable : WORD
28afa9c2
MT
91 {
92 $$ = $1;
93 };
94
6b03e625 95value : words
28afa9c2
MT
96 {
97 $$ = $1;
98 }
99 | /* empty */
100 {
101 $$ = NULL;
102 };
103
6b03e625
MT
104words : WORD
105 {
106 $$ = $1;
107 }
68f7a6f7 108 | words WHITESPACE WORD
4f2a7bce
MT
109 {
110 int r = asprintf(&$$, "%s %s", $1, $3);
111 if (r < 0) {
112 ERROR(pakfire, "Could not allocate memory");
113 ABORT;
114 }
115 }
de528421
MT
116 | /* empty */
117 {
118 $$ = NULL;
119 };
68f7a6f7
MT
120
121line : whitespace words NEWLINE
122 {
4f2a7bce
MT
123 // Only forward words
124 $$ = $2;
68f7a6f7
MT
125 };
126
127text : text line
4f2a7bce
MT
128 {
129 int r = asprintf(&$$, "%s\n%s", $1, $2);
130 if (r < 0) {
131 ERROR(pakfire, "Could not allocate memory");
132 ABORT;
133 }
134 }
68f7a6f7 135 | line
de528421
MT
136 | /* empty */
137 {
138 $$ = NULL;
139 };
6b03e625 140
28afa9c2
MT
141block_opening : variable NEWLINE
142 {
3b1b9cbd 143 current_block = pakfire_strdup($1);
28afa9c2
MT
144 };
145
146block_closing : END NEWLINE
147 {
3b1b9cbd
MT
148 pakfire_free(current_block);
149 current_block = NULL;
28afa9c2
MT
150 }
151
3b1b9cbd 152block : block_opening assignments block_closing;
28afa9c2
MT
153
154assignments : assignments assignment
155 | assignments empty
156 | /* empty */
157 ;
158
159assignment : whitespace variable whitespace ASSIGN whitespace value whitespace NEWLINE
160 {
23188111
MT
161 int r = pakfire_parser_add_declaration($2, $6);
162 if (r < 0)
163 ABORT;
eb8fb9a6
MT
164 }
165 | whitespace DEFINE WHITESPACE variable NEWLINE text whitespace END NEWLINE
68f7a6f7 166 {
23188111
MT
167 int r = pakfire_parser_add_declaration($4, $6);
168 if (r < 0)
169 ABORT;
68f7a6f7
MT
170 }
171
f9a691ef
MT
172%%
173
4f2a7bce
MT
174static void cleanup(void) {
175 // Reset Pakfire pointer
176 pakfire = NULL;
23188111
MT
177
178 // Free all declarations
179 for (unsigned int i = 0; i < NUM_DECLARATIONS; i++) {
180 pakfire_free(declarations[i]);
181 }
3b1b9cbd
MT
182
183 // Reset current_block
184 if (current_block) {
185 pakfire_free(current_block);
186 current_block = NULL;
187 }
23188111
MT
188}
189
190static int pakfire_parser_add_declaration(const char* name, const char* value) {
191 struct pakfire_parser_declaration* d;
192 unsigned int i = 0;
193
194 while (i++ < NUM_DECLARATIONS && declarations[i])
195 i++;
196
197 if (i == NUM_DECLARATIONS) {
198 ERROR(pakfire, "No free declarations left\n");
199 return -1;
200 }
201
202 // Allocate a new declaration
203 declarations[i] = d = pakfire_calloc(1, sizeof(*d));
204 if (!d)
205 return -1;
206
3b1b9cbd
MT
207 // Import name
208 if (current_block) {
209 int r = asprintf(&d->name, "%s.%s", current_block, name);
210 if (r < 0)
211 return r;
212 } else {
213 d->name = pakfire_strdup(name);
214 }
215
216 // Import value
23188111
MT
217 d->value = pakfire_strdup(value);
218
219 DEBUG(pakfire, "New declaration: %s = %s\n", d->name, d->value);
220
221 return 0;
4f2a7bce
MT
222}
223
e98f46a7
MT
224int pakfire_parser_parse_metadata(Pakfire _pakfire, const char* data, size_t len) {
225 pakfire = _pakfire;
226
a0258b56
MT
227 DEBUG(pakfire, "Parsing the following data:\n%s\n", data);
228
6ab14b96
MT
229 num_lines = 1;
230
f9a691ef
MT
231 YY_BUFFER_STATE buffer = yy_scan_bytes(data, len);
232 int r = yyparse();
233 yy_delete_buffer(buffer);
234
235 return r;
236}
237
238void yyerror(const char* s) {
e98f46a7 239 ERROR(pakfire, "Error (line %d): %s\n", num_lines, s);
f9a691ef 240}