1 | /*************************************************************************/ |
---|
2 | /* */ |
---|
3 | /* Get names of classes, attributes and attribute values */ |
---|
4 | /* ----------------------------------------------------- */ |
---|
5 | /* */ |
---|
6 | /*************************************************************************/ |
---|
7 | |
---|
8 | |
---|
9 | #include "defns.i" |
---|
10 | #include "types.i" |
---|
11 | #include "extern.i" |
---|
12 | |
---|
13 | #include <sys/types.h> |
---|
14 | #include <sys/stat.h> |
---|
15 | |
---|
16 | |
---|
17 | #define Space(s) (s == ' ' || s == '\n' || s == '\t') |
---|
18 | #define SkipComment while ( ( c = getc(f) ) != '\n' ) |
---|
19 | |
---|
20 | char Delimiter; |
---|
21 | String CopyString(); |
---|
22 | |
---|
23 | |
---|
24 | |
---|
25 | /*************************************************************************/ |
---|
26 | /* */ |
---|
27 | /* Read a name from file f into string s, setting Delimiter. */ |
---|
28 | /* */ |
---|
29 | /* - Embedded periods are permitted, but periods followed by space */ |
---|
30 | /* characters act as delimiters. */ |
---|
31 | /* - Embedded spaces are permitted, but multiple spaces are replaced */ |
---|
32 | /* by a single space. */ |
---|
33 | /* - Any character can be escaped by '\'. */ |
---|
34 | /* - The remainder of a line following '|' is ignored. */ |
---|
35 | /* */ |
---|
36 | /*************************************************************************/ |
---|
37 | |
---|
38 | |
---|
39 | Boolean ReadName(f, s) |
---|
40 | /* --------- */ |
---|
41 | FILE *f; |
---|
42 | String s; |
---|
43 | { |
---|
44 | register char *Sp=s; |
---|
45 | register int c; |
---|
46 | |
---|
47 | /* Skip to first non-space character */ |
---|
48 | |
---|
49 | while ( ( c = getc(f) ) == '|' || Space(c) ) |
---|
50 | { |
---|
51 | if ( c == '|' ) SkipComment; |
---|
52 | } |
---|
53 | |
---|
54 | /* Return false if no names to read */ |
---|
55 | |
---|
56 | if ( c == EOF ) |
---|
57 | { |
---|
58 | Delimiter = EOF; |
---|
59 | return false; |
---|
60 | } |
---|
61 | |
---|
62 | /* Read in characters up to the next delimiter */ |
---|
63 | |
---|
64 | while ( c != ':' && c != ',' && c != '\n' && c != '\r' && c != '|' && c != EOF ) |
---|
65 | { |
---|
66 | if ( c == '.' ) |
---|
67 | { |
---|
68 | if ( ( c = getc(f) ) == '|' || Space(c) ) break; |
---|
69 | *Sp++ = '.'; |
---|
70 | } |
---|
71 | |
---|
72 | if ( c == '\\' ) |
---|
73 | { |
---|
74 | c = getc(f); |
---|
75 | } |
---|
76 | |
---|
77 | *Sp++ = c; |
---|
78 | |
---|
79 | if ( c == ' ' ) |
---|
80 | { |
---|
81 | while ( ( c = getc(f) ) == ' ' ) |
---|
82 | ; |
---|
83 | } |
---|
84 | else |
---|
85 | { |
---|
86 | c = getc(f); |
---|
87 | } |
---|
88 | } |
---|
89 | |
---|
90 | if ( c == '|' ) SkipComment; |
---|
91 | Delimiter = c; |
---|
92 | |
---|
93 | /* Strip trailing spaces */ |
---|
94 | |
---|
95 | while ( Space(*(Sp-1)) ) Sp--; |
---|
96 | |
---|
97 | *Sp++ = '\0'; |
---|
98 | return true; |
---|
99 | } |
---|
100 | |
---|
101 | |
---|
102 | |
---|
103 | /*************************************************************************/ |
---|
104 | /* */ |
---|
105 | /* Read the names of classes, attributes and legal attribute values. */ |
---|
106 | /* On completion, these names are stored in: */ |
---|
107 | /* ClassName - class names */ |
---|
108 | /* AttName - attribute names */ |
---|
109 | /* AttValName - attribute value names */ |
---|
110 | /* with: */ |
---|
111 | /* MaxAttVal - number of values for each attribute */ |
---|
112 | /* */ |
---|
113 | /* Other global variables set are: */ |
---|
114 | /* MaxAtt - maximum attribute number */ |
---|
115 | /* MaxClass - maximum class number */ |
---|
116 | /* MaxDiscrVal - maximum discrete values for any attribute */ |
---|
117 | /* */ |
---|
118 | /* Note: until the number of attributes is known, the name */ |
---|
119 | /* information is assembled in local arrays */ |
---|
120 | /* */ |
---|
121 | /*************************************************************************/ |
---|
122 | |
---|
123 | |
---|
124 | GetNames() |
---|
125 | /* --------- */ |
---|
126 | { |
---|
127 | FILE *Nf, *fopen(); |
---|
128 | char Fn[100], Buffer[1000]; |
---|
129 | DiscrValue v; |
---|
130 | int AttCeiling=100, ClassCeiling=100, ValCeiling; |
---|
131 | |
---|
132 | /* Open names file */ |
---|
133 | |
---|
134 | strcpy(Fn, FileName); |
---|
135 | strcat(Fn, ".names"); |
---|
136 | if ( ! ( Nf = fopen(Fn, "r") ) ) Error(0, Fn, ""); |
---|
137 | |
---|
138 | /* Get class names from names file */ |
---|
139 | |
---|
140 | ClassName = (String *) calloc(ClassCeiling, sizeof(String)); |
---|
141 | MaxClass = -1; |
---|
142 | do |
---|
143 | { |
---|
144 | ReadName(Nf, Buffer); |
---|
145 | |
---|
146 | if ( ++MaxClass >= ClassCeiling) |
---|
147 | { |
---|
148 | ClassCeiling += 100; |
---|
149 | ClassName = (String *) realloc(ClassName, ClassCeiling*sizeof(String)); |
---|
150 | } |
---|
151 | ClassName[MaxClass] = CopyString(Buffer); |
---|
152 | } |
---|
153 | while ( Delimiter == ',' ); |
---|
154 | |
---|
155 | /* Get attribute and attribute value names from names file */ |
---|
156 | |
---|
157 | AttName = (String *) calloc(AttCeiling, sizeof(String)); |
---|
158 | MaxAttVal = (DiscrValue *) calloc(AttCeiling, sizeof(DiscrValue)); |
---|
159 | AttValName = (String **) calloc(AttCeiling, sizeof(String *)); |
---|
160 | SpecialStatus = (char *) malloc(AttCeiling); |
---|
161 | |
---|
162 | MaxAtt = -1; |
---|
163 | while ( ReadName(Nf, Buffer) ) |
---|
164 | { |
---|
165 | if ( Delimiter != ':' ) Error(1, Buffer, ""); |
---|
166 | |
---|
167 | if ( ++MaxAtt >= AttCeiling ) |
---|
168 | { |
---|
169 | AttCeiling += 100; |
---|
170 | AttName = (String *) realloc(AttName, AttCeiling*sizeof(String)); |
---|
171 | MaxAttVal = (DiscrValue *) realloc(MaxAttVal, AttCeiling*sizeof(DiscrValue)); |
---|
172 | AttValName = (String **) realloc(AttValName, AttCeiling*sizeof(String *)); |
---|
173 | SpecialStatus = (char *) realloc(SpecialStatus, AttCeiling); |
---|
174 | } |
---|
175 | |
---|
176 | AttName[MaxAtt] = CopyString(Buffer); |
---|
177 | SpecialStatus[MaxAtt] = Nil; |
---|
178 | MaxAttVal[MaxAtt] = 0; |
---|
179 | ValCeiling = 100; |
---|
180 | AttValName[MaxAtt] = (String *) calloc(ValCeiling, sizeof(String)); |
---|
181 | |
---|
182 | do |
---|
183 | { |
---|
184 | if ( ! ( ReadName(Nf, Buffer) ) ) Error(2, AttName[MaxAtt], ""); |
---|
185 | |
---|
186 | if ( ++MaxAttVal[MaxAtt] >= ValCeiling ) |
---|
187 | { |
---|
188 | ValCeiling += 100; |
---|
189 | AttValName[MaxAtt] = |
---|
190 | (String *) realloc(AttValName[MaxAtt], ValCeiling*sizeof(String)); |
---|
191 | } |
---|
192 | |
---|
193 | AttValName[MaxAtt][MaxAttVal[MaxAtt]] = CopyString(Buffer); |
---|
194 | } |
---|
195 | while ( Delimiter == ',' ); |
---|
196 | |
---|
197 | if ( MaxAttVal[MaxAtt] == 1 ) |
---|
198 | { |
---|
199 | /* Check for special treatment */ |
---|
200 | |
---|
201 | if ( ! strcmp(Buffer, "continuous") ) |
---|
202 | {} |
---|
203 | else |
---|
204 | if ( ! memcmp(Buffer, "discrete", 8) ) |
---|
205 | { |
---|
206 | SpecialStatus[MaxAtt] = DISCRETE; |
---|
207 | |
---|
208 | /* Read max values, reserve space and check MaxDiscrVal */ |
---|
209 | |
---|
210 | v = atoi(&Buffer[8]); |
---|
211 | if ( v < 2 ) |
---|
212 | { |
---|
213 | printf("** %s: illegal number of discrete values\n", |
---|
214 | AttName[MaxAtt]); |
---|
215 | exit(1); |
---|
216 | } |
---|
217 | |
---|
218 | AttValName[MaxAtt] = |
---|
219 | (String *) realloc(AttValName[MaxAtt], (v+2)*sizeof(String)); |
---|
220 | AttValName[MaxAtt][0] = (char *) v; |
---|
221 | if ( v > MaxDiscrVal ) MaxDiscrVal = v; |
---|
222 | } |
---|
223 | else |
---|
224 | if ( ! strcmp(Buffer, "ignore") ) |
---|
225 | { |
---|
226 | SpecialStatus[MaxAtt] = IGNORE; |
---|
227 | } |
---|
228 | else |
---|
229 | { |
---|
230 | /* Cannot have only one discrete value for an attribute */ |
---|
231 | |
---|
232 | Error(3, AttName[MaxAtt], ""); |
---|
233 | } |
---|
234 | |
---|
235 | MaxAttVal[MaxAtt] = 0; |
---|
236 | } |
---|
237 | else |
---|
238 | if ( MaxAttVal[MaxAtt] > MaxDiscrVal ) MaxDiscrVal = MaxAttVal[MaxAtt]; |
---|
239 | } |
---|
240 | |
---|
241 | fclose(Nf); |
---|
242 | } |
---|
243 | |
---|
244 | |
---|
245 | |
---|
246 | /*************************************************************************/ |
---|
247 | /* */ |
---|
248 | /* Locate value Val in List[First] to List[Last] */ |
---|
249 | /* */ |
---|
250 | /*************************************************************************/ |
---|
251 | |
---|
252 | |
---|
253 | int Which(Val, List, First, Last) |
---|
254 | /* ----- */ |
---|
255 | String Val, List[]; |
---|
256 | short First, Last; |
---|
257 | { |
---|
258 | short n=First; |
---|
259 | |
---|
260 | while ( n <= Last && strcmp(Val, List[n]) ) n++; |
---|
261 | |
---|
262 | return ( n <= Last ? n : First-1 ); |
---|
263 | } |
---|
264 | |
---|
265 | |
---|
266 | |
---|
267 | /*************************************************************************/ |
---|
268 | /* */ |
---|
269 | /* Allocate space then copy string into it */ |
---|
270 | /* */ |
---|
271 | /*************************************************************************/ |
---|
272 | |
---|
273 | String CopyString(x) |
---|
274 | /* ----------- */ |
---|
275 | String x; |
---|
276 | { |
---|
277 | char *s; |
---|
278 | |
---|
279 | s = (char *) calloc(strlen(x)+1, sizeof(char)); |
---|
280 | strcpy(s, x); |
---|
281 | return s; |
---|
282 | } |
---|
283 | |
---|
284 | |
---|
285 | |
---|
286 | /*************************************************************************/ |
---|
287 | /* */ |
---|
288 | /* Error messages */ |
---|
289 | /* */ |
---|
290 | /*************************************************************************/ |
---|
291 | |
---|
292 | Error(n, s1, s2) |
---|
293 | /* ----- */ |
---|
294 | short n; |
---|
295 | String s1, s2; |
---|
296 | { |
---|
297 | static char Messages=0; |
---|
298 | |
---|
299 | printf("\nERROR: "); |
---|
300 | switch(n) |
---|
301 | { |
---|
302 | case 0: printf("cannot open file %s%s\n", s1, s2); |
---|
303 | exit(1); |
---|
304 | |
---|
305 | case 1: printf("colon expected after attribute name %s\n", s1); |
---|
306 | break; |
---|
307 | |
---|
308 | case 2: printf("unexpected eof while reading attribute %s\n", s1); |
---|
309 | break; |
---|
310 | |
---|
311 | case 3: printf("attribute %s has only one value\n", s1); |
---|
312 | break; |
---|
313 | |
---|
314 | case 4: printf("case %d's value of '%s' for attribute %s is illegal\n", |
---|
315 | MaxItem+1, s2, s1); |
---|
316 | break; |
---|
317 | |
---|
318 | case 5: printf("case %d's class of '%s' is illegal\n", MaxItem+1, s2); |
---|
319 | } |
---|
320 | |
---|
321 | if ( ++Messages > 10 ) |
---|
322 | { |
---|
323 | printf("Error limit exceeded\n"); |
---|
324 | exit(1); |
---|
325 | } |
---|
326 | } |
---|