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

  ViewVC Help
Powered by ViewVC 1.1.0 with CvsGraph 1.7.0