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 %x xSTR
23 %x xID
24 %x xSYM
25 %x xSKIP
26 %x xSKIPSTR
27 %x xAUTHOR
28 
29 %option nounput
30 %option noinput
31 
32 %{
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 
38 #include <gd.h>
39 
40 #include "utils.h"
41 #include "cvsgraph.h"
42 #include "readconf.h"
43 #include "rcs.h"
44 #include "rcsy.h"
45 
46 #define SKIP_DELTATEXT	1
47 
48 static void reset_str(void);
49 static void add_str(const char *s, int l);
50 static char *get_str(void);
51 
52 static int skip_string = 0;
53 
54 #define YY_NO_UNPUT 1
55 
56 %}
57 
58 ws		[\b\t\v\f\r ]
59 num		[0-9.]+
60 digit		[0-9]
61 idchar		[!-#%-+\-/<-?A-~\240-\377]
62 special		[$,.:;@]
63 
64 %%
65 	/* RCS keywords */
66 head			return tHEAD;
67 branch			return tBRANCH;
68 access			return tACCESS;
69 symbols			return tSYMBOLS;
70 locks			return tLOCKS;
71 strict			return tSTRICT;
72 comment			return tCOMMENT;
73 expand			return tEXPAND;
74 date			return tDATE;
75 author			return tAUTHOR;
76 state			return tSTATE;
77 branches		return tBRANCHES;
78 next			return tNEXT;
79 desc			return tDESC;
80 log			return tLOG;
81 text			return tTEXT;
82 	/* CVS extensions */
83 owner			return tOWNER;
84 group			return tGROUP;
85 permissions		return tPERMISSIONS;
86 special			return tSPECIAL;
87 symlnk			return tSYMLINK;
88 hardlinks		return tHARDLINKS;
89 	/* Other known extensions */
90 namespace		return tNAMESPACE;
91 dead			return tDEAD;
92 	/* CVSNT extensions */
93 mergepoint1		return tMERGEPOINT;
94 deltatype		return tDELTATYPE;
95 commitid		return tCOMMITID;
96 kopt			return tKOPT;
97 filename		return tFILENAME;
98 properties		return tPROPERTIES;
99 
100 	/* Here come any other 'newphrase' constructs */
101 {num}?{idchar}({idchar}|{num})*		{
102 		yylval.str = xstrdup(yytext);
103 		return tNEWPHRASE;
104 	}
105 
106 	/* Special rules for skipping everything after a 'newphrase' part */
107 <xSKIP>[^;@\n]+		;
108 <xSKIP>\n		line_number++;
109 <xSKIP>@		BEGIN(xSKIPSTR);
110 <xSKIP>;		BEGIN(INITIAL); return *yytext;
111 
112 <xSKIPSTR>[^\n@]+	;
113 <xSKIPSTR>\n		line_number++;
114 <xSKIPSTR>@@		;
115 <xSKIPSTR>@		BEGIN(xSKIP);
116 
117 {num}			yylval.str = xstrdup(yytext); return tREV;
118 [:;$]			return *yytext;
119 
120 <xID>{ws}+	;
121 <xID>\n		line_number++;
122 <xID>{special}	BEGIN(INITIAL); return *yytext;
123 <xID>{num}?{idchar}({idchar}|{num})*		{
124 		yylval.str = xstrdup(yytext);
125 		BEGIN(INITIAL);
126 		return tID;
127 	}
128 <xID>{num}?.	rcserror("Invalid character in ID '%s' (0x%02x)", yytext, yytext[yyleng-1]);
129 
130 <xSYM>{ws}+	;
131 <xSYM>\n	line_number++;
132 <xSYM>{special}	BEGIN(INITIAL); return *yytext;
133 <xSYM>{digit}*{idchar}({idchar}|{digit})*	{
134 		yylval.str = xstrdup(yytext);
135 		BEGIN(INITIAL);
136 		return tSYM;
137 	}
138 <xSYM>{digit}*.	rcserror("Invalid character in SYMBOL '%s' (0x%02x)", yytext, yytext[yyleng-1]);
139 
140 @		reset_str(); BEGIN(xSTR);
141 <xSTR>[^@\n]+	add_str(yytext, yyleng);
142 <xSTR>\n	line_number++; add_str(yytext, yyleng);
143 <xSTR>@@	add_str(yytext, 1);
144 <xSTR>@		yylval.str = get_str(); BEGIN(INITIAL); skip_string = 0; return tSTRING;
145 
146 <xAUTHOR>@	reset_str(); BEGIN(xSTR);
147 <xAUTHOR>{ws}+	;
148 <xAUTHOR>\n	line_number++;
149 <xAUTHOR>{special}	BEGIN(INITIAL); return *yytext;
150 <xAUTHOR>({idchar}|{num}|{ws})+		{
151 		yylval.str = xstrdup(yytext);
152 		BEGIN(INITIAL);
153 		return tID;
154 	}
155 <xAUTHOR>.	rcserror("Invalid character in AUTHOR '%s' (0x%02x)", yytext, yytext[yyleng-1]);
156 
157 {ws}+		; /* Ignore whitespace */
158 \n		line_number++;
159 
160 .		rcserror("Unknown char/unmatched text '%c' (0x%02x)", isprint((int)((unsigned char)*yytext)) ? *yytext : ' ', *yytext);
161 
162 %%
163 
164 int yywrap(void)
165 {
166 	return 1;
167 }
168 
set_id(void)169 void set_id(void)
170 {
171 	BEGIN(xID);
172 }
173 
set_author(void)174 void set_author(void)
175 {
176 	BEGIN(xAUTHOR);
177 }
178 
set_sym(void)179 void set_sym(void)
180 {
181 	BEGIN(xSYM);
182 }
183 
set_skip(void)184 void set_skip(void)
185 {
186 	BEGIN(xSKIP);
187 }
188 
set_skipstr(void)189 void set_skipstr(void)
190 {
191 	skip_string = 1;
192 }
193 
194 #define STRALLOCSIZE	256
195 static char *str;
196 static int nstr;
197 static int nastr;
198 
reset_str(void)199 static void reset_str(void)
200 {
201 	nstr = 0;
202 }
203 
add_str(const char * s,int l)204 static void add_str(const char *s, int l)
205 {
206 #ifdef SKIP_DELTATEXT
207 	if(skip_string)
208 		return;
209 #endif
210 	if(nstr + l + 1 > nastr)
211 	{
212 		str = xrealloc(str, nastr+STRALLOCSIZE);
213 		nastr += STRALLOCSIZE;
214 	}
215 	memcpy(str+nstr, s, l);
216 	nstr += l;
217 }
218 
get_str(void)219 static char *get_str(void)
220 {
221 #ifdef SKIP_DELTATEXT
222 	if(skip_string)
223 		return xstrdup("");
224 #endif
225 	if(str)
226 	{
227 		str[nstr] = '\0';
228 		return xstrdup(str);
229 	}
230 	else
231 		return xstrdup("");
232 }
233 
234