1 /*
2 * aegis - project change supervisor
3 * Copyright (C) 2001-2006, 2008, 2012 Peter Miller
4 * Copyright (C) 2020 Aryeh M. Friedman
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
18 * <http://www.gnu.org/licenses/>.
19 */
20
21 %define api.prefix {format_rcs_gram_}
22 %{
23
24 #include <common/ac/assert.h>
25 #include <common/ac/stdlib.h>
26
27 #include <common/gettime.h>
28 #include <common/str_list.h>
29 #include <common/symtab.h>
30 #include <libaegis/help.h>
31
32 #include <aeimport/format/rcs/gram.h>
33 #include <aeimport/format/rcs/lex.h>
34 #include <aeimport/format/version_list.h>
35
36 %}
37
38 %token ACCESS
39 %token AUTHOR
40 %token BRANCH
41 %token COLON
42 %token COMMENT
43 %token DATE
44 %token DESC
45 %token EXPAND
46 %token HEAD
47 %token IDENTIFIER
48 %token JUNK
49 %token LOCKS
50 %token LOG
51 %token NEXT
52 %token NUMBER
53 %token SEMI
54 %token STATE
55 %token STRICT
56 %token STRING
57 %token SUFFIX
58 %token SYMBOLS
59 %token TEXT
60
61 %union
62 {
63 string_ty *lv_string;
64 string_list_ty *lv_string_list;
65 }
66
67 %type <lv_string> NUMBER STRING IDENTIFIER date author next log state
68 %type <lv_string_list> strings_opt branch branch_opt identifiers_opt numbers_opt
69
70 %{
71
72 static symtab_ty *stp;
73 static format_version_ty *head;
74 static string_ty *pfn;
75 static string_ty *lfn;
76
77
78 static format_version_ty *
ancestor(format_version_ty * fvp)79 ancestor(format_version_ty *fvp)
80 {
81 while (fvp->before)
82 fvp = fvp->before;
83 return fvp;
84 }
85
86
87 format_version_ty *
rcs_parse(string_ty * physical,string_ty * logical)88 rcs_parse(string_ty *physical, string_ty *logical)
89 {
90 extern int yyparse(void);
91
92 head = 0;
93
94 stp = new symtab_ty(5);
95 pfn = physical;
96 lfn = logical;
97
98 rcs_lex_open(physical);
99 yyparse();
100 rcs_lex_close();
101
102 delete stp;
103 stp = 0;
104 return ancestor(head);
105 }
106
107
108 static time_t
str2date(string_ty * s)109 str2date(string_ty *s)
110 {
111 string_list_ty sl;
112 sl.split(s, ".");
113 if (sl.nstrings != 6)
114 {
115 fatal_date_unknown(s->str_text);
116 }
117
118 /*
119 * Turn it into a format that scan_date understands.
120 * (Probably not the fastest way to get is converted into a date.)
121 */
122 string_ty *s2 =
123 str_format
124 (
125 "%s/%s/%s %s:%s:%s GMT",
126 sl.string[1]->str_text,
127 sl.string[2]->str_text,
128 sl.string[0]->str_text,
129 sl.string[3]->str_text,
130 sl.string[4]->str_text,
131 sl.string[5]->str_text
132 );
133 time_t t = date_scan(s2->str_text);
134 str_free(s2);
135 if (t == (time_t)-1)
136 {
137 fatal_date_unknown(s->str_text);
138 }
139 return t;
140 }
141
142
143 static format_version_ty *
find(string_ty * edit)144 find(string_ty *edit)
145 {
146 format_version_ty *rp;
147
148 assert(stp);
149 rp = (format_version_ty *)stp->query(edit);
150 if (!rp)
151 {
152 rp = new format_version_ty();
153 stp->assign(edit, rp);
154 rp->edit = str_copy(edit);
155 rp->filename_physical = str_copy(pfn);
156 rp->filename_logical = str_copy(lfn);
157 }
158 return rp;
159 }
160
161
162 static int
is_a_branch_version_number(string_ty * s)163 is_a_branch_version_number(string_ty *s)
164 {
165 const char *cp;
166 int count_the_dots;
167
168 count_the_dots = 0;
169 for (cp = s->str_text; *cp; ++cp)
170 {
171 if (*cp == '.')
172 {
173 ++count_the_dots;
174 if (count_the_dots >= 2)
175 return 1;
176 }
177 }
178 return 0;
179 }
180
181
182 %}
183
184 %%
185
186 file
187 : admin tree desc edits
188 ;
189
190 admin
191 : head branch_opt suffix_opt access symbols locks strict_opt
192 comment_opt expand_opt
193 {
194 delete $2;
195 }
196 ;
197
198 head
199 : HEAD NUMBER SEMI
200 {
201 head = find($2);
202 str_free($2);
203 }
204 ;
205
206 branch
207 : BRANCH numbers_opt SEMI
208 { $$ = $2; }
209 ;
210
211 branch_opt
212 : /* empty */
213 { $$ = new string_list_ty(); }
214 | branch
215 { $$ = $1; }
216 ;
217
218 suffix
219 : SUFFIX IDENTIFIER SEMI
220 { str_free($2); }
221 | SUFFIX STRING SEMI
222 { str_free($2); }
223 ;
224
225 suffix_opt
226 : /* empty */
227 | suffix
228 ;
229
230 access
231 : ACCESS identifiers_opt SEMI
232 { delete $2; }
233 ;
234
235 symbols
236 : SYMBOLS symbol_list SEMI
237 ;
238
239 symbol_list
240 : /* empty */
241 | symbol_list symbol
242 ;
243
244 symbol
245 : IDENTIFIER COLON NUMBER
246 {
247 format_version_ty *rp;
248
249 rp = find($3);
250 rp->tag.push_back($1);
251
252 str_free($1);
253 str_free($3);
254 }
255 ;
256
257 locks
258 : LOCKS lock_list SEMI
259 ;
260
261 lock_list
262 : /* empty */
263 | lock_list lock
264 ;
265
266 lock
267 : IDENTIFIER COLON NUMBER
268 {
269 str_free($1);
270 str_free($3);
271 }
272 ;
273
274 strict
275 : STRICT SEMI
276 ;
277
278 strict_opt
279 : /* empty */
280 | strict
281 ;
282
283 comment
284 : COMMENT STRING SEMI
285 { str_free($2); }
286 ;
287
288 comment_opt
289 : /* empty */
290 | comment
291 ;
292
293 expand
294 : EXPAND strings_opt SEMI
295 { delete $2; }
296 ;
297
298 expand_opt
299 : /* empty */
300 | expand
301 ;
302
303 identifiers_opt
304 : /* empty */
305 {
306 $$ = new string_list_ty();
307 }
308 | identifiers_opt IDENTIFIER
309 {
310 $$ = $1;
311 $$->push_back($2);
312 str_free($2);
313 }
314 ;
315
316 strings_opt
317 : /* empty */
318 {
319 $$ = new string_list_ty();
320 }
321 | strings_opt STRING
322 {
323 $$ = $1;
324 $$->push_back($2);
325 str_free($2);
326 }
327 ;
328
329 tree
330 : /* empty */
331 | tree delta
332 ;
333
334 delta
335 : NUMBER date author state branch next
336 {
337 size_t j;
338 format_version_ty *rp;
339 static string_ty *dead;
340
341 rp = find($1);
342
343 rp->when = str2date($2);
344 str_free($2);
345 rp->who = $3;
346
347 /*
348 * The RCS manual says that
349 * "Exp" means experimental
350 * "Stab" means stable
351 * "Rel" means released
352 *
353 * CVS uses "dead" to indicate a file which has
354 * been deleted, and should not be checked out.
355 */
356 if (!dead)
357 dead = str_from_c("dead");
358 rp->dead = str_equal($4, dead);
359 str_free($4);
360
361 if ($5->nstrings && !rp->after_branch)
362 rp->after_branch = format_version_list_new();
363 for (j = 0; j < $5->nstrings; ++j)
364 {
365 format_version_ty *other;
366
367 other = find($5->string[j]);
368 other->before = rp;
369 format_version_list_append
370 (
371 rp->after_branch,
372 other
373 );
374 }
375 delete $5;
376
377 if ($6)
378 {
379 /*
380 * The trunk is a roll-back lists, but
381 * the branches are roll-forward lists.
382 * (Sheesh!)
383 */
384 if (is_a_branch_version_number($1))
385 {
386 rp->after = find($6);
387 rp->after->before = rp;
388 }
389 else
390 {
391 rp->before = find($6);
392 rp->before->after = rp;
393 }
394 str_free($6);
395 }
396 }
397 ;
398
399 date
400 : DATE NUMBER SEMI
401 { $$ = $2; }
402 ;
403
404 author
405 : AUTHOR IDENTIFIER SEMI
406 { $$ = $2; }
407 ;
408
409 state
410 : STATE IDENTIFIER SEMI
411 { $$ = $2; }
412 ;
413
414 numbers_opt
415 : /* empty */
416 {
417 $$ = new string_list_ty();
418 }
419 | numbers_opt NUMBER
420 {
421 $$ = $1;
422 $$->push_back($2);
423 str_free($2);
424 }
425 ;
426
427 next
428 : NEXT NUMBER SEMI
429 { $$ = $2; }
430 | NEXT SEMI
431 { $$ = 0; }
432 ;
433
434 desc
435 : DESC STRING nosemi
436 { str_free($2); }
437 ;
438
439 edits
440 : edit
441 | edits edit
442 ;
443
444 edit
445 : NUMBER log text
446 {
447 format_version_ty *rp;
448
449 rp = find($1);
450 rp->description = $2;
451 }
452 ;
453
454 log
455 : LOG STRING nosemi
456 { $$ = $2; }
457 ;
458
459 text
460 : TEXT STRING nosemi
461 { str_free($2); }
462 ;
463
464 nosemi
465 : /* empty */
466 { rcs_lex_keyword_expected(); }
467 ;
468
469
470 /* vim: set ts=8 sw=4 et : */
471