]> git.ipfire.org Git - pakfire.git/blame - src/libpakfire/parser/grammar.y
libpakfire: parser: Store declared variables in a long list
[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];
f9a691ef
MT
48%}
49
50%token APPEND
51%token ASSIGN
52%token DEFINE
53%token END
54%token NEWLINE
55%token TAB
f9a691ef 56%token WHITESPACE
6b03e625 57%token <string> WORD
f9a691ef 58
68f7a6f7
MT
59%type <string> line;
60%type <string> text;
28afa9c2
MT
61%type <string> variable;
62%type <string> value;
6b03e625 63%type <string> words;
28afa9c2
MT
64
65%union {
66 char* string;
67}
f9a691ef 68
28afa9c2 69%%
70425a92 70
28afa9c2
MT
71top : top empty
72 | top block
73 | empty
74 | block
75 ;
76
77empty : WHITESPACE NEWLINE
78 | NEWLINE
79 ;
80
81// Optional whitespace
82whitespace : WHITESPACE
83 | /* empty */
84 ;
85
6b03e625 86variable : WORD
28afa9c2
MT
87 {
88 $$ = $1;
89 };
90
6b03e625 91value : words
28afa9c2
MT
92 {
93 $$ = $1;
94 }
95 | /* empty */
96 {
97 $$ = NULL;
98 };
99
6b03e625
MT
100words : WORD
101 {
102 $$ = $1;
103 }
68f7a6f7 104 | words WHITESPACE WORD
4f2a7bce
MT
105 {
106 int r = asprintf(&$$, "%s %s", $1, $3);
107 if (r < 0) {
108 ERROR(pakfire, "Could not allocate memory");
109 ABORT;
110 }
111 }
de528421
MT
112 | /* empty */
113 {
114 $$ = NULL;
115 };
68f7a6f7
MT
116
117line : whitespace words NEWLINE
118 {
4f2a7bce
MT
119 // Only forward words
120 $$ = $2;
68f7a6f7
MT
121 };
122
123text : text line
4f2a7bce
MT
124 {
125 int r = asprintf(&$$, "%s\n%s", $1, $2);
126 if (r < 0) {
127 ERROR(pakfire, "Could not allocate memory");
128 ABORT;
129 }
130 }
68f7a6f7 131 | line
de528421
MT
132 | /* empty */
133 {
134 $$ = NULL;
135 };
6b03e625 136
28afa9c2
MT
137block_opening : variable NEWLINE
138 {
139 printf("BLOCK OPEN: %s\n", $1);
140 };
141
142block_closing : END NEWLINE
143 {
144 printf("BLOCK CLOSED\n");
145 }
146
147block : block_opening assignments block_closing
148 {
149 printf("BLOCK FOUND\n");
150 };
151
152assignments : assignments assignment
153 | assignments empty
68f7a6f7 154 | assignments block_assignment
28afa9c2
MT
155 | /* empty */
156 ;
157
158assignment : whitespace variable whitespace ASSIGN whitespace value whitespace NEWLINE
159 {
23188111
MT
160 int r = pakfire_parser_add_declaration($2, $6);
161 if (r < 0)
162 ABORT;
28afa9c2 163 };
f9a691ef 164
68f7a6f7
MT
165block_assignment : whitespace DEFINE WHITESPACE variable NEWLINE text whitespace END NEWLINE
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 }
182}
183
184static int pakfire_parser_add_declaration(const char* name, const char* value) {
185 struct pakfire_parser_declaration* d;
186 unsigned int i = 0;
187
188 while (i++ < NUM_DECLARATIONS && declarations[i])
189 i++;
190
191 if (i == NUM_DECLARATIONS) {
192 ERROR(pakfire, "No free declarations left\n");
193 return -1;
194 }
195
196 // Allocate a new declaration
197 declarations[i] = d = pakfire_calloc(1, sizeof(*d));
198 if (!d)
199 return -1;
200
201 // Import name & value
202 d->name = pakfire_strdup(name);
203 d->value = pakfire_strdup(value);
204
205 DEBUG(pakfire, "New declaration: %s = %s\n", d->name, d->value);
206
207 return 0;
4f2a7bce
MT
208}
209
e98f46a7
MT
210int pakfire_parser_parse_metadata(Pakfire _pakfire, const char* data, size_t len) {
211 pakfire = _pakfire;
212
a0258b56
MT
213 DEBUG(pakfire, "Parsing the following data:\n%s\n", data);
214
6ab14b96
MT
215 num_lines = 1;
216
f9a691ef
MT
217 YY_BUFFER_STATE buffer = yy_scan_bytes(data, len);
218 int r = yyparse();
219 yy_delete_buffer(buffer);
220
221 return r;
222}
223
224void yyerror(const char* s) {
e98f46a7 225 ERROR(pakfire, "Error (line %d): %s\n", num_lines, s);
f9a691ef 226}