Merge-in fix for segfault from current github repository.
[AROS.git] / tools / flexcat / src / scancd.c
blobd0c84dd5b48864c7ffcdf65282120ff78681b539
1 /*
2 * $Id$
4 * Copyright (C) 1993-1999 by Jochen Wiedmann and Marcin Orlowski
5 * Copyright (C) 2002-2017 FlexCat Open Source Team
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 (at
10 * your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "flexcat.h"
24 #include "showfuncs.h"
25 #include "readprefs.h"
26 #include "globals.h"
27 #include "utils.h"
28 #include "createcat.h"
30 struct CDLine *FirstCDLine = NULL; /* First catalog description line. */
31 char *HeaderName = NULL;
33 /// ScanCDFile
35 /* This scans the catalog description file.
36 Inputs: cdfile - name of the catalog description file
37 Result: TRUE if successful, FALSE otherwise */
39 int ScanCDFile(char *cdfile)
41 FILE *fp;
42 struct CDLine *cdline, **cdptr = &FirstCDLine;
43 struct CatString *cs, **csptr = &FirstCatString;
44 char *line, *newline;
45 int NextID = 0;
46 int Result = TRUE;
47 int lenbytes = 0;
49 ScanFile = cdfile;
50 ScanLine = 0;
52 if((fp = fopen(cdfile, "r")) == NULL)
54 ShowErrorQuick(MSG_ERR_NOCATALOGDESCRIPTION, cdfile);
57 if(!NoBufferedIO)
58 setvbuf(fp, NULL, _IOFBF, buffer_size);
60 // initialize "line" ahead of the loop
61 // the loop will bail out early for empty files
62 line = NULL;
63 newline = NULL;
64 while(!feof(fp) && (line = newline = ReadLine(fp, TRUE)) != NULL)
66 if((cdline = malloc(sizeof(*cdline))) == NULL)
68 MemError();
71 *cdptr = cdline;
72 cdptr = &cdline->Next;
73 cdline->Next = NULL;
74 cdline->Line = line = AllocString(newline);
75 free(newline);
77 if(*line == ';')
79 continue;
81 else if(*line == '#')
83 int CheckExtra = TRUE;
85 /* '#' in the first column of a line is the command introducer --
86 any number of # symbols, blank spaces and tabs afterwards are
87 skipped for compatibility with CatComp */
89 while(*line == '#' || *line == ' ' || *line == '\t')
91 ++line;
94 if(Strnicmp(line, "language", 8) == 0)
96 char *ptr;
98 line += 9;
99 OverSpace(&line);
100 Language = AllocString(line);
101 if(LANGToLower)
103 for(ptr = Language; *ptr; ptr++)
105 *ptr = tolower((int)*ptr);
108 CheckExtra = FALSE;
110 else if(Strnicmp(line, "version", 7) == 0)
112 line += 8;
113 OverSpace(&line);
114 CatVersion = strtol(line, &line, 0);
115 CheckExtra = TRUE;
117 else if(Strnicmp(line, "basename", 8) == 0)
119 line += 9;
120 OverSpace(&line);
121 free(BaseName);
122 BaseName = AllocString(line);
123 CheckExtra = FALSE;
125 else if(Strnicmp(line, "ifdef", 5) == 0)
127 continue;
129 else if(Strnicmp(line, "endif", 5) == 0)
131 continue;
133 else if(Strnicmp(line, "array", 5) == 0)
135 continue;
137 else if(Strnicmp(line, "header", 6) == 0)
139 line += 7;
140 OverSpace(&line);
141 free(HeaderName);
142 HeaderName = AllocString(line);
143 CheckExtra = FALSE;
146 else if(Strnicmp(line, "lengthbytes", 11) == 0)
148 line += 12;
149 OverSpace(&line);
150 lenbytes = atoi(line);
151 CheckExtra = FALSE;
153 else if(Strnicmp(line, "printf_check_off", 16) == 0)
155 continue;
157 else if(Strnicmp(line, "printf_check_on", 15) == 0)
159 continue;
161 else
163 ShowWarn(MSG_ERR_UNKNOWNCDCOMMAND);
164 Result = FALSE;
165 CheckExtra = FALSE;
168 if(CheckExtra == TRUE)
170 OverSpace(&line);
171 if(*line != '\0')
173 ShowError(MSG_ERR_EXTRA_CHARACTERS);
174 Result = FALSE;
178 else
180 char *idstr;
182 /* Check for blanks at the start of line. */
184 if(*line == ' ' || *line == '\t')
186 ShowError(MSG_ERR_UNEXPECTEDBLANKS);
187 Result = FALSE;
188 OverSpace(&line);
191 idstr = line;
192 while((*line >= 'a' && *line <= 'z') ||
193 (*line >= 'A' && *line <= 'Z') ||
194 (*line >= '0' && *line <= '9') ||
195 (*line == '_'))
197 ++line;
200 if(idstr == line)
202 ShowError(MSG_ERR_NOIDENTIFIER);
203 Result = FALSE;
205 else
207 int found;
209 if((cs = malloc(sizeof(*cs))) == NULL)
211 MemError();
216 struct CatString *scs;
218 found = TRUE;
219 for(scs = FirstCatString; scs != NULL; scs = scs->Next)
221 if(scs->ID == NextID)
223 found = FALSE;
224 ++NextID;
225 break;
229 while(found == FALSE);
231 cs->Next = NULL;
232 cs->ID = NextID;
233 cs->MinLen = 0;
234 cs->MaxLen = -1;
235 cs->CD_Str = (char *)"";
236 cs->CT_Str = NULL;
237 cs->NotInCT = TRUE;
238 cs->POformat = FALSE;
240 if((cs->ID_Str = malloc((line - idstr) + 1)) == NULL)
242 MemError();
244 strncpy(cs->ID_Str, idstr, line - idstr);
245 cs->ID_Str[line - idstr] = '\0';
246 OverSpace(&line);
248 /* Check if next char in line is '('? (//) */
250 if(*line != '(')
252 ShowError(MSG_ERR_NO_LEADING_BRACKET, cs->ID_Str);
253 Result = FALSE;
255 else
257 char *oldstr;
258 struct CatString *scs;
259 char bytes[10];
260 int bytesread, reallen;
262 ++line;
263 OverSpace(&line);
265 /* Check for default config of line (//) */
267 if(*line != '/')
269 if(*line == '+')
271 NextID = cs->ID = NextID + strtol(line, &line, 0);
273 else if(*line == '$')
275 line++;
276 cs->ID = NextID = strtol(line, &line, 16);
278 else
280 cs->ID = NextID = strtol(line, &line, 0);
282 OverSpace(&line);
285 /* Check for already used identifier. */
287 for(scs = FirstCatString; scs != NULL; scs = scs->Next)
289 if(scs->ID == cs->ID)
291 ShowError(MSG_ERR_DOUBLE_ID, cs->ID_Str);
292 Result = FALSE;
294 if(strcmp(cs->ID_Str, scs->ID_Str) == 0)
296 ShowError(MSG_ERR_DOUBLE_IDENTIFIER, cs->ID_Str);
297 Result = FALSE;
301 /* Check for min/len values (//) */
303 if(*line != '/')
305 ShowWarn(MSG_ERR_NO_MIN_LEN, cs->ID_Str);
306 Result = FALSE;
308 else
310 ++line;
311 OverSpace(&line);
312 if(*line != '/')
314 cs->MinLen = strtol(line, &line, 0);
315 OverSpace(&line);
317 if(*line != '/')
319 ShowWarn(MSG_ERR_NO_MAX_LEN, cs->ID_Str);
320 Result = FALSE;
322 else
324 ++line;
325 OverSpace(&line);
326 if(*line != ')')
328 cs->MaxLen = strtol(line, &line, 0);
329 OverSpace(&line);
331 if(*line != ')')
333 ShowError(MSG_ERR_NO_TRAILING_BRACKET, cs->ID_Str);
334 Result = FALSE;
336 else
338 ++line;
339 OverSpace(&line);
340 if(*line)
342 ShowError(MSG_ERR_EXTRA_CHARACTERS_ID, cs->ID_Str);
348 /* Huh? There is no string for this definition? */
350 if((newline = ReadLine(fp, FALSE)) == FALSE)
352 ShowWarn(MSG_ERR_MISSINGSTRING);
353 Result = FALSE;
354 cs->CD_Str = (char *)"";
356 else
358 // Check if there are any non-ASCII characters contained in the line.
359 // This will cause a warning only, since non-ASCII characters in the
360 // default language are discouraged.
361 char *p = newline;
362 char c;
364 while((c = *p++) != '\0')
366 if(!isascii(c))
368 int v = (int)c;
370 ShowWarn(MSG_ERR_NON_ASCII_CHARACTER, v & 0xff, cs->ID_Str);
371 break;
375 cs->CD_Str = AllocString(newline);
376 free(newline);
379 /* Get string length. */
381 oldstr = cs->CD_Str;
382 reallen = 0;
383 while(*oldstr != '\0')
385 bytesread = ReadChar(&oldstr, bytes);
386 if(bytesread == 2)
388 bytesread--;
390 reallen += bytesread;
393 /* String too short. */
395 if(cs->MinLen > 0 && reallen < cs->MinLen)
397 ShowWarn(MSG_ERR_STRING_TOO_SHORT, cs->ID_Str);
400 /* String too long. */
402 if(cs->MaxLen > 0 && reallen > cs->MaxLen)
404 ShowWarn(MSG_ERR_STRING_TOO_LONG, cs->ID_Str);
407 cs->Nr = NumStrings;
408 cs->LenBytes = lenbytes;
409 *csptr = cs;
410 csptr = &cs->Next;
411 ++NumStrings;
417 fclose(fp);
419 return Result;