1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
/*
* Copyright (c) 1992, Brian Berliner and Jeff Polk
* Copyright (c) 1989-1992, Brian Berliner
*
* You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.4 kit.
*/
#include "cvs.h"
#include "getline.h"
/*
* Parse the INFOFILE file for the specified REPOSITORY. Invoke CALLPROC for
* the first line in the file that matches the REPOSITORY, or if ALL != 0, any lines
* matching "ALL", or if no lines match, the last line matching "DEFAULT".
*
* Return 0 for success, -1 if there was not an INFOFILE, and >0 for failure.
*/
int
Parse_Info (infofile, repository, callproc, all)
char *infofile;
char *repository;
CALLPROC callproc;
int all;
{
int err = 0;
FILE *fp_info;
char *infopath;
char *line = NULL;
size_t line_allocated = 0;
char *default_value = NULL;
char *expanded_value= NULL;
int callback_done, line_number;
char *cp, *exp, *value, *srepos;
const char *regex_err;
if (CVSroot_original == NULL)
{
/* XXX - should be error maybe? */
error (0, 0, "CVSROOT variable not set");
return (1);
}
/* find the info file and open it */
infopath = xmalloc (strlen (CVSroot_directory)
+ strlen (infofile)
+ sizeof (CVSROOTADM)
+ 10);
(void) sprintf (infopath, "%s/%s/%s", CVSroot_directory,
CVSROOTADM, infofile);
fp_info = CVS_FOPEN (infopath, "r");
if (fp_info == NULL)
{
/* If no file, don't do anything special. */
if (!existence_error (errno))
error (0, errno, "cannot open %s", infopath);
free (infopath);
return 0;
}
/* strip off the CVSROOT if repository was absolute */
srepos = Short_Repository (repository);
if (trace)
(void) fprintf (stderr, "-> ParseInfo(%s, %s, %s)\n",
infopath, srepos, all ? "ALL" : "not ALL");
/* search the info file for lines that match */
callback_done = line_number = 0;
while (getline (&line, &line_allocated, fp_info) >= 0)
{
line_number++;
/* skip lines starting with # */
if (line[0] == '#')
continue;
/* skip whitespace at beginning of line */
for (cp = line; *cp && isspace (*cp); cp++)
;
/* if *cp is null, the whole line was blank */
if (*cp == '\0')
continue;
/* the regular expression is everything up to the first space */
for (exp = cp; *cp && !isspace (*cp); cp++)
;
if (*cp != '\0')
*cp++ = '\0';
/* skip whitespace up to the start of the matching value */
while (*cp && isspace (*cp))
cp++;
/* no value to match with the regular expression is an error */
if (*cp == '\0')
{
error (0, 0, "syntax error at line %d file %s; ignored",
line_number, infofile);
continue;
}
value = cp;
/* strip the newline off the end of the value */
if ((cp = strrchr (value, '\n')) != NULL)
*cp = '\0';
if (expanded_value != NULL)
free (expanded_value);
expanded_value = expand_path (value, infofile, line_number);
if (!expanded_value)
{
continue;
}
/*
* At this point, exp points to the regular expression, and value
* points to the value to call the callback routine with. Evaluate
* the regular expression against srepos and callback with the value
* if it matches.
*/
/* save the default value so we have it later if we need it */
if (strcmp (exp, "DEFAULT") == 0)
{
/* Is it OK to silently ignore all but the last DEFAULT
expression? */
if (default_value != NULL)
free (default_value);
default_value = xstrdup (expanded_value);
continue;
}
/*
* For a regular expression of "ALL", do the callback always We may
* execute lots of ALL callbacks in addition to *one* regular matching
* callback or default
*/
if (strcmp (exp, "ALL") == 0)
{
if (all)
err += callproc (repository, expanded_value);
else
error(0, 0, "Keyword `ALL' is ignored at line %d in %s file",
line_number, infofile);
continue;
}
if (callback_done)
/* only first matching, plus "ALL"'s */
continue;
/* see if the repository matched this regular expression */
if ((regex_err = re_comp (exp)) != NULL)
{
error (0, 0, "bad regular expression at line %d file %s: %s",
line_number, infofile, regex_err);
continue;
}
if (re_exec (srepos) == 0)
continue; /* no match */
/* it did, so do the callback and note that we did one */
err += callproc (repository, expanded_value);
callback_done = 1;
}
if (ferror (fp_info))
error (0, errno, "cannot read %s", infopath);
if (fclose (fp_info) < 0)
error (0, errno, "cannot close %s", infopath);
/* if we fell through and didn't callback at all, do the default */
if (callback_done == 0 && default_value != NULL)
err += callproc (repository, default_value);
/* free up space if necessary */
if (default_value != NULL)
free (default_value);
if (expanded_value != NULL)
free (expanded_value);
free (infopath);
if (line != NULL)
free (line);
return (err);
}
|