/[CvsGraph]/cvsgraph/rcsy.y
ViewVC logotype

Annotate of /cvsgraph/rcsy.y

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.11 - (show annotations)
Mon Jun 13 19:57:10 2005 UTC (12 years, 5 months ago) by bertho
Branch: MAIN
Changes since 1.10: +18 -2 lines
- Work around CVSNT problem with wrong keyword ordering
- Fix complaining about a new CVSNT keyword properties
1 /*
2 * CvsGraph graphical representation generator of brances and revisions
3 * of a file in cvs/rcs.
4 *
5 * Copyright (C) 2001 B. Stultiens
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 %{
23 #define YYERROR_VERBOSE 1
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29
30 #include <gd.h> /* For gdFontPtr in cvsgraph.h */
31 #include "cvsgraph.h"
32 #include "utils.h"
33 #include "rcs.h"
34
35 rcsfile_t *rcsfile;
36
37 static tag_t *new_tag(char *s, char *r);
38 static tags_t *new_tags(tag_t *s);
39 static tags_t *add_tags(tags_t *s, tag_t *t);
40 static idrev_t *new_idrev(char *s, char *r);
41 static idrevs_t *new_idrevs(idrev_t *s);
42 static idrevs_t *add_idrevs(idrevs_t *s, idrev_t *t);
43 static ids_t *new_ids(char *s);
44 static ids_t *add_ids(ids_t *s, char *t);
45 static revs_t *new_revs(char *s);
46 static revs_t *add_revs(revs_t *s, char *t);
47 static dtext_t *new_dtext(char *n, char *l, char *t);
48 static dtexts_t *add_dtexts(dtexts_t *s, dtext_t *t);
49 static phrase_t *new_phrase(phrase_type_e pt, char *t);
50 static phrases_t *add_phrases(phrases_t *s, phrase_t *t);
51 static phrases_t *merge_phrases(phrases_t *s, phrases_t *t);
52 static delta_t *new_delta(char *rev, char *date, char *author, char *state, revs_t *branches, char *next, phrases_t *phrases);
53 static deltas_t *add_deltas(deltas_t *s, delta_t *t);
54 static rcsfile_t *new_rcsfile(char *head, char *branch, ids_t *access, tags_t *tags,
55 idrevs_t *locks, int strict, char *comment, char *expand);
56
57 %}
58
59 %union{
60 int i;
61 char *str;
62 tag_t *tag;
63 tags_t *tags;
64 idrev_t *idrev;
65 idrevs_t *idrevs;
66 ids_t *ids;
67 revs_t *revs;
68 dtext_t *dtext;
69 dtexts_t *dtexts;
70 delta_t *delta;
71 deltas_t *deltas;
72 rcsfile_t *rcsfile;
73 phrases_t *phrases;
74 phrase_t *phrase;
75 }
76
77 %token tHEAD tBRANCH tACCESS tSYMBOLS tLOCKS tSTRICT tCOMMENT
78 %token tEXPAND tDATE tAUTHOR tSTATE tBRANCHES tNEXT
79 %token tDESC tLOG tTEXT
80 %token tOWNER tGROUP tPERMISSIONS tSPECIAL tSYMLINK tHARDLINKS
81 %token tNAMESPACE tDEAD tMERGEPOINT
82 %token tDELTATYPE tCOMMITID tKOPT tFILENAME tPROPERTIES
83 %token <str> tNEWPHRASE
84 %token <str> tSTRING tREV tID tSYM
85
86
87 %type <str> ostr orev oid obranch ocomment oexpand desc idorstr
88 %type <tag> tag
89 %type <tags> tags otags
90 %type <idrev> idrev
91 %type <idrevs> idrevs oidrevs
92 %type <ids> ids oids
93 %type <revs> revs orevs
94 %type <i> ostrict
95 %type <dtext> dtext
96 %type <dtexts> dtexts
97 %type <delta> delta
98 %type <deltas> deltas
99 %type <rcsfile> admin
100 %type <phrases> ophrases
101 %type <phrase> phrase
102
103 %%
104 rcsfile : admin deltas desc {
105 rcsfile = $1;
106 rcsfile->deltas = $2;
107 rcsfile->desc = $3;
108 rcsfile->dtexts = NULL;
109 if(rcsfile->head)
110 {
111 char *h = xstrdup("HEAD");
112 char *r = xstrdup(rcsfile->head->rev);
113 tag_t *t = new_tag(h, r);
114 t->ignore = -1; /* Make sure it doesn't get zapped */
115 rcsfile->tags = add_tags(rcsfile->tags, t);
116 }
117 if(rcsfile->branch)
118 {
119 char *h = xstrdup("MAIN");
120 char *r = xstrdup(rcsfile->branch->rev);
121 tag_t *t = new_tag(h, r);
122 t->rev->isbranch = 1;
123 rcsfile->tags = add_tags(rcsfile->tags, t);
124 }
125 /* Else we need to add the main tag later because the
126 * trunk is reversed in order and the primary revision
127 * numbers can vary.
128 */
129 if(!conf.parse_logs)
130 {
131 /* Return from the yyparse() call early to avoid parsing
132 * of the possibly extremely large deltatext. This speeds
133 * up parsing of binary files by a very large factor.
134 */
135 return 0;
136 }
137 }
138
139 /* This is trailing deltatext context and possibly ignored */
140 dtexts { rcsfile->dtexts = $5; }
141 ;
142
143 admin : tHEAD orev ';'
144 obranch
145 tACCESS { set_id(); } oids ';'
146 tSYMBOLS { set_sym(); } otags ';'
147 tLOCKS { set_id(); } oidrevs ';' ostrict
148 ocomment
149 oexpand
150 ophrases { $$ = new_rcsfile($2, $4, $7, $11, $15, $17, $18, $19); }
151 ;
152
153 ostrict : /* Empty */ { $$ = 0; }
154 | tSTRICT ';' { $$ = 1; }
155 ;
156
157 obranch : /* Empty */ { $$ = NULL; }
158 | tBRANCH orev ';' { $$ = $2; }
159 ;
160
161 ocomment: /* Empty */ { $$ = NULL; }
162 | tCOMMENT ostr ';' { $$ = $2; }
163 ;
164
165 oexpand : /* Empty */ { $$ = NULL; }
166 | tEXPAND ostr ';' { $$ = $2; }
167 ;
168
169 deltas : /* Empty */ { $$ = NULL; }
170 | deltas delta { $$ = add_deltas($1, $2); }
171 ;
172
173 delta : tREV
174 tDATE tREV ';'
175 tAUTHOR { set_author(); } idorstr ';'
176 tSTATE { set_id(); } oid ';'
177 tBRANCHES orevs ';'
178 ophrases
179 tNEXT orev ';'
180 ophrases { $$ = new_delta($1, $3, $7, $11, $14, $18, merge_phrases($16, $20)); }
181 ;
182
183 idorstr : tID { $$ = $1; }
184 | tSTRING { $$ = $1; }
185 ;
186
187 desc : tDESC tSTRING { $$ = $2; }
188 ;
189
190 dtexts : /* Empty */ { $$ = NULL; }
191 | dtexts dtext { $$ = add_dtexts($1, $2); }
192 ;
193
194 dtext : tREV
195 tLOG tSTRING
196 ophrases
197 tTEXT { set_skipstr(); } tSTRING { $$ = new_dtext($1, $3, $7); }
198 ;
199
200 ophrases: /* Empty */ { $$ = NULL; }
201 | ophrases phrase { $$ = add_phrases($1, $2); }
202 ;
203
204 phrase : tNEWPHRASE { set_skip(); } ';' {
205 yywarning("Unrecognised `newphrase´ keyword '%s' skipped", $1);
206 xfree($1);
207 $$ = NULL;
208 }
209 | cvskw { set_skip(); } ';' { $$ = NULL; /* yywarning("CVS extended keyword skipped"); */ }
210 | otherkw { set_skip(); } ';' { $$ = NULL; /* yywarning("Other extended keyword"); */ }
211 | tMERGEPOINT tSTRING ';' { $$ = new_phrase(PT_MERGEPOINT, $2); }
212 ;
213
214 cvskw : tOWNER
215 | tGROUP
216 | tPERMISSIONS
217 | tSPECIAL
218 | tSYMLINK
219 | tHARDLINKS
220 ;
221
222 otherkw : tNAMESPACE
223 | tDEAD
224 | tDELTATYPE
225 | tCOMMITID
226 | tKOPT
227 | tFILENAME
228 | tPROPERTIES
229 ;
230
231 ostr : /* Empty */ { $$ = NULL; }
232 | tSTRING { $$ = $1; }
233 ;
234
235 orev : /* Empty */ { $$ = NULL; }
236 | tREV { $$ = $1; }
237 ;
238
239 orevs : /* Empty */ { $$ = NULL; }
240 | revs { $$ = $1; }
241 ;
242
243 revs : tREV { $$ = new_revs($1); }
244 | revs tREV { $$ = add_revs($1, $2); }
245 ;
246
247 oid : /* Empty */ { $$ = NULL; }
248 | tID { $$ = $1; }
249 ;
250
251 oids : /* Empty */ { $$ = NULL; }
252 | ids { $$ = $1; }
253 ;
254
255 ids : tID { $$ = new_ids($1); }
256 | ids tID { set_id(); $$ = add_ids($1, $2); }
257 ;
258
259 oidrevs : /* Empty */ { $$ = NULL; }
260 | idrevs { $$ = $1; }
261 ;
262
263 idrevs : idrev { $$ = new_idrevs($1); }
264 | idrevs idrev { $$ = add_idrevs($1, $2); }
265 ;
266
267 idrev : tID ':' tREV { set_id(); $$ = new_idrev($1, $3); }
268 ;
269
270 otags : /* Empty */ { $$ = NULL; }
271 | tags { $$ = $1; }
272 ;
273
274 tags : tag { if($1) $$ = new_tags($1); else $$ = NULL; }
275 | tags tag { if($1 && $2) $$ = add_tags($1, $2); else if($2) $$ = new_tags($2); else $$ = $1; }
276 ;
277
278 tag : tSYM ':' tREV { set_sym(); $$ = new_tag($1, $3); }
279 /* Zap the additional tag-info from CVSNT */
280 /* This is a bit of a hack, but it is necessary to do like this */
281 /* because the parser is not allowed to do any look-ahead on ':'. */
282 /* Otherwise, we would have a tNEWPHRASE hit because we cannot set */
283 /* set_sym() before the lexer gets the next token. */
284 | ':' tREV ':' tSTRING { set_sym(); $$ = NULL; }
285 ;
286
287 %%
288 static rev_t *make_rev(char *s, int isrev)
289 {
290 char *cptr;
291 int dots = 0;
292 rev_t *r;
293
294 if(!s)
295 return NULL;
296
297 r = xmalloc(sizeof(*r));
298
299 for(cptr = s; *cptr; cptr++)
300 {
301 if(*cptr == '.')
302 dots++;
303 }
304 if(!dots)
305 {
306 r->rev = xstrdup("");
307 r->branch = xstrdup(s);
308 r->isbranch = 1;
309 }
310 else if(!*s)
311 {
312 r->rev = xstrdup("?.?");
313 r->branch = xstrdup("?");
314 }
315 else if(dots & 1)
316 {
317 char *t;
318 r->rev = s;
319 r->branch = xstrdup(s);
320 cptr = strrchr(r->branch, '.');
321 assert(cptr != NULL);
322 *cptr = '\0';
323 t = strrchr(r->branch, '.');
324 if(!isrev && ((t && !strcmp(t+1, "0")) || (!t && !strcmp(r->branch, "0"))))
325 {
326 /* Magic branch numbers "x.x.0.x" */
327 r->isbranch = 1;
328 if(t)
329 strcpy(t+1, cptr+1);
330 else
331 strcpy(r->branch, cptr+1);
332 }
333 }
334 else
335 {
336 r->isbranch = 1;
337 r->branch = s;
338 r->rev = xmalloc(strlen(s) + 3);
339 strcpy(r->rev, s);
340 strcat(r->rev, ".?");
341 }
342 return r;
343 }
344
345
346 static tag_t *new_tag(char *s, char *r)
347 {
348 tag_t *t = xmalloc(sizeof(*t));
349 t->tag = s;
350 t->rev = make_rev(r, 0);
351 return t;
352 }
353
354 static tags_t *new_tags(tag_t *s)
355 {
356 tags_t *t = xmalloc(sizeof(*t));
357 t->ntags = 1;
358 t->tags = xmalloc(sizeof(t->tags[0]));
359 t->tags[0] = s;
360 return t;
361 }
362
363 static tags_t *add_tags(tags_t *s, tag_t *t)
364 {
365 if(!s)
366 return new_tags(t);
367 s->tags = xrealloc(s->tags, (s->ntags+1) * sizeof(s->tags[0]));
368 s->tags[s->ntags] = t;
369 s->ntags++;
370 return s;
371 }
372
373 static idrev_t *new_idrev(char *s, char *r)
374 {
375 idrev_t *t = xmalloc(sizeof(*t));
376 t->id = s;
377 t->rev = make_rev(r, 1);
378 return t;
379 }
380
381 static idrevs_t *new_idrevs(idrev_t *s)
382 {
383 idrevs_t *t = xmalloc(sizeof(*t));
384 t->nidrevs = 1;
385 t->idrevs = xmalloc(sizeof(t->idrevs[0]));
386 t->idrevs[0] = s;
387 return t;
388 }
389
390 static idrevs_t *add_idrevs(idrevs_t *s, idrev_t *t)
391 {
392 if(!s)
393 return new_idrevs(t);
394 s->idrevs = xrealloc(s->idrevs, (s->nidrevs+1) * sizeof(s->idrevs[0]));
395 s->idrevs[s->nidrevs] = t;
396 s->nidrevs++;
397 return s;
398 }
399
400 static ids_t *new_ids(char *s)
401 {
402 ids_t *t = xmalloc(sizeof(*t));
403 t->nids = 1;
404 t->ids = xmalloc(sizeof(t->ids[0]));
405 t->ids[0] = s;
406 return t;
407 }
408
409 static ids_t *add_ids(ids_t *s, char *t)
410 {
411 s->ids = xrealloc(s->ids, (s->nids+1) * sizeof(s->ids[0]));
412 s->ids[s->nids] = t;
413 s->nids++;
414 return s;
415 }
416
417 static revs_t *new_revs(char *s)
418 {
419 revs_t *t = xmalloc(sizeof(*t));
420 t->nrevs = 1;
421 t->revs = xmalloc(sizeof(t->revs[0]));
422 t->revs[0] = make_rev(s, 1);
423 return t;
424 }
425
426 static revs_t *add_revs(revs_t *s, char *t)
427 {
428 s->revs = xrealloc(s->revs, (s->nrevs+1) * sizeof(s->revs[0]));
429 s->revs[s->nrevs] = make_rev(t, 1);
430 s->nrevs++;
431 return s;
432 }
433
434 static dtext_t *new_dtext(char *n, char *l, char *t)
435 {
436 dtext_t *d = xmalloc(sizeof(*d));
437 d->rev = make_rev(n, 1);
438 d->log = l;
439 d->text = t;
440 return d;
441 }
442
443 static dtexts_t *add_dtexts(dtexts_t *s, dtext_t *t)
444 {
445 if(!s)
446 s = xmalloc(sizeof(*s));
447 s->dtexts = xrealloc(s->dtexts, (s->ndtexts+1) * sizeof(s->dtexts[0]));
448 s->dtexts[s->ndtexts] = t;
449 s->ndtexts++;
450 return s;
451 }
452
453 static phrase_t *new_phrase(phrase_type_e pt, char *t)
454 {
455 phrase_t *d = xmalloc(sizeof(*d));
456 d->type = pt;
457 d->rev = make_rev(t, 1);
458 return d;
459 }
460
461 static phrases_t *add_phrases(phrases_t *s, phrase_t *t)
462 {
463 if(!t)
464 return s;
465 if(!s)
466 s = xmalloc(sizeof(*s));
467 if(t)
468 {
469 s->phrases = xrealloc(s->phrases, (s->nphrases + 1) * sizeof(s->phrases[0]));
470 s->phrases[s->nphrases] = t;
471 s->nphrases++;
472 }
473 return s;
474 }
475
476 static phrases_t *merge_phrases(phrases_t *s, phrases_t *t)
477 {
478 if(!t)
479 return s;
480 if(!s)
481 return t;
482 s->phrases = xrealloc(s->phrases, (s->nphrases + t->nphrases) * sizeof(s->phrases[0]));
483 memcpy(&s->phrases[s->nphrases], &t->phrases[0], t->nphrases * sizeof(t->phrases[0]));
484 s->nphrases += t->nphrases;
485 /* FIXME: Free t and content; hm, who cares... */
486 return s;
487 }
488
489 static phrase_t *find_mergepoint(phrases_t *p)
490 {
491 int i;
492
493 if(!p)
494 return NULL;
495
496 for(i = 0; i < p->nphrases; i++)
497 {
498 if(p->phrases[i]->type == PT_MERGEPOINT)
499 return p->phrases[i];
500 }
501 return NULL;
502 }
503
504 static delta_t *new_delta(char *rev, char *date, char *author, char *state, revs_t *branches, char *next, phrases_t *phrases)
505 {
506 delta_t *d = xmalloc(sizeof(*d));
507 d->rev = make_rev(rev, 1);
508 d->date = date;
509 d->author = author;
510 d->state = state;
511 d->branches = branches;
512 d->next = make_rev(next, 1);
513 d->phrases = phrases;
514 d->mergepoint = find_mergepoint(phrases);
515 return d;
516 }
517
518 static deltas_t *add_deltas(deltas_t *s, delta_t *t)
519 {
520 if(!s)
521 s = xmalloc(sizeof(*s));
522 s->deltas = xrealloc(s->deltas, (s->ndeltas+1) * sizeof(s->deltas[0]));
523 s->deltas[s->ndeltas] = t;
524 s->ndeltas++;
525 return s;
526 }
527
528 static rcsfile_t *new_rcsfile(char *head, char *branch, ids_t *access, tags_t *tags,
529 idrevs_t *locks, int strict, char *comment, char *expand)
530 {
531 rcsfile_t *r = xmalloc(sizeof(*r));
532 r->head = make_rev(head, 1);
533 r->branch = make_rev(branch, 0);
534 r->access = access;
535 r->tags = tags;
536 r->locks = locks;
537 r->strict = strict;
538 r->comment = comment;
539 r->expand = expand;
540 return r;
541 }
542

  ViewVC Help
Powered by ViewVC 1.1.0 with CvsGraph 1.7.0