/* * $Id$ * * Copyright (C) 1993-1999 by Jochen Wiedmann and Marcin Orlowski * Copyright (C) 2002-2015 FlexCat Open Source Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "flexcat.h" #include "showfuncs.h" #include "readprefs.h" #include "globals.h" #include "utils.h" #include "createcat.h" struct CDLine *FirstCDLine = NULL; /* First catalog description line. */ char *HeaderName = NULL; /// ScanCDFile /* This scans the catalog description file. Inputs: cdfile - name of the catalog description file Result: TRUE if successful, FALSE otherwise */ int ScanCDFile(char *cdfile) { FILE *fp; struct CDLine *cdline, **cdptr = &FirstCDLine; struct CatString *cs, **csptr = &FirstCatString; char *line, *newline; int NextID = 0; int Result = TRUE; int lenbytes = 0; ScanFile = cdfile; ScanLine = 0; if((fp = fopen(cdfile, "r")) == NULL) { ShowErrorQuick(MSG_ERR_NOCATALOGDESCRIPTION, cdfile); } if(!NoBufferedIO) setvbuf(fp, NULL, _IOFBF, buffer_size); while(!feof(fp) && (line = newline = ReadLine(fp, TRUE)) != NULL) { if((cdline = malloc(sizeof(*cdline))) == NULL) { MemError(); } *cdptr = cdline; cdptr = &cdline->Next; cdline->Next = NULL; cdline->Line = line = AllocString(newline); free(newline); if(*line == ';') { continue; } else if(*line == '#') { int CheckExtra = TRUE; /* '#' in the first column of a line is the command introducer -- any number of # symbols, blank spaces and tabs afterwards are skipped for compatibility with CatComp */ while(*line == '#' || *line == ' ' || *line == '\t') { ++line; } if(Strnicmp(line, "language", 8) == 0) { char *ptr; line += 9; OverSpace(&line); Language = AllocString(line); if(LANGToLower) { for(ptr = Language; *ptr; ptr++) { *ptr = tolower((int)*ptr); } } CheckExtra = FALSE; } else if(Strnicmp(line, "version", 7) == 0) { line += 8; OverSpace(&line); CatVersion = strtol(line, &line, 0); CheckExtra = TRUE; } else if(Strnicmp(line, "basename", 8) == 0) { line += 9; OverSpace(&line); free(BaseName); BaseName = AllocString(line); CheckExtra = FALSE; } else if(Strnicmp(line, "ifdef", 5) == 0) { continue; } else if(Strnicmp(line, "endif", 5) == 0) { continue; } else if(Strnicmp(line, "array", 5) == 0) { continue; } else if(Strnicmp(line, "header", 6) == 0) { line += 7; OverSpace(&line); free(HeaderName); HeaderName = AllocString(line); CheckExtra = FALSE; } else if(Strnicmp(line, "lengthbytes", 11) == 0) { line += 12; OverSpace(&line); lenbytes = atoi(line); CheckExtra = FALSE; } else if(Strnicmp(line, "printf_check_off", 16) == 0) { continue; } else if(Strnicmp(line, "printf_check_on", 15) == 0) { continue; } else { ShowWarn(MSG_ERR_UNKNOWNCDCOMMAND); Result = FALSE; CheckExtra = FALSE; } if(CheckExtra == TRUE) { OverSpace(&line); if(*line != '\0') { ShowError(MSG_ERR_EXTRA_CHARACTERS); Result = FALSE; } } } else { char *idstr; /* Check for blanks at the start of line. */ if(*line == ' ' || *line == '\t') { ShowError(MSG_ERR_UNEXPECTEDBLANKS); Result = FALSE; OverSpace(&line); } idstr = line; while((*line >= 'a' && *line <= 'z') || (*line >= 'A' && *line <= 'Z') || (*line >= '0' && *line <= '9') || (*line == '_')) { ++line; } if(idstr == line) { ShowError(MSG_ERR_NOIDENTIFIER); Result = FALSE; } else { int found; if((cs = malloc(sizeof(*cs))) == NULL) { MemError(); } do { struct CatString *scs; found = TRUE; for(scs = FirstCatString; scs != NULL; scs = scs->Next) { if(scs->ID == NextID) { found = FALSE; ++NextID; break; } } } while(found == FALSE); cs->Next = NULL; cs->ID = NextID; cs->MinLen = 0; cs->MaxLen = -1; cs->CD_Str = (char *)""; cs->CT_Str = NULL; cs->NotInCT = TRUE; cs->POformat = FALSE; if((cs->ID_Str = malloc((line - idstr) + 1)) == NULL) { MemError(); } strncpy(cs->ID_Str, idstr, line - idstr); cs->ID_Str[line - idstr] = '\0'; OverSpace(&line); /* Check if next char in line is '('? (//) */ if(*line != '(') { ShowError(MSG_ERR_NO_LEADING_BRACKET, cs->ID_Str); Result = FALSE; } else { char *oldstr; struct CatString *scs; char bytes[10]; int bytesread, reallen; ++line; OverSpace(&line); /* Check for default config of line (//) */ if(*line != '/') { if(*line == '+') { NextID = cs->ID = NextID + strtol(line, &line, 0); } else if(*line == '$') { line++; cs->ID = NextID = strtol(line, &line, 16); } else { cs->ID = NextID = strtol(line, &line, 0); } OverSpace(&line); } /* Check for already used identifier. */ for(scs = FirstCatString; scs != NULL; scs = scs->Next) { if(scs->ID == cs->ID) { ShowError(MSG_ERR_DOUBLE_ID, cs->ID_Str); Result = FALSE; } if(strcmp(cs->ID_Str, scs->ID_Str) == 0) { ShowError(MSG_ERR_DOUBLE_IDENTIFIER, cs->ID_Str); Result = FALSE; } } /* Check for min/len values (//) */ if(*line != '/') { ShowWarn(MSG_ERR_NO_MIN_LEN, cs->ID_Str); Result = FALSE; } else { ++line; OverSpace(&line); if(*line != '/') { cs->MinLen = strtol(line, &line, 0); OverSpace(&line); } if(*line != '/') { ShowWarn(MSG_ERR_NO_MAX_LEN, cs->ID_Str); Result = FALSE; } else { ++line; OverSpace(&line); if(*line != ')') { cs->MaxLen = strtol(line, &line, 0); OverSpace(&line); } if(*line != ')') { ShowError(MSG_ERR_NO_TRAILING_BRACKET, cs->ID_Str); Result = FALSE; } else { ++line; OverSpace(&line); if(*line) { ShowError(MSG_ERR_EXTRA_CHARACTERS_ID, cs->ID_Str); } } } } /* Huh? There is no string for this definition? */ if((newline = ReadLine(fp, FALSE)) == FALSE) { ShowWarn(MSG_ERR_MISSINGSTRING); Result = FALSE; cs->CD_Str = (char *)""; } else { // Check if there are any non-ASCII characters contained in the line. // This will cause a warning only, since non-ASCII characters in the // default language are discouraged. char *p = newline; char c; while((c = *p++) != '\0') { if(!isascii(c)) { int v = (int)c; ShowWarn(MSG_ERR_NON_ASCII_CHARACTER, v & 0xff, cs->ID_Str); break; } } cs->CD_Str = AllocString(newline); free(newline); } /* Get string length. */ oldstr = cs->CD_Str; reallen = 0; while(*oldstr != '\0') { bytesread = ReadChar(&oldstr, bytes); if(bytesread == 2) { bytesread--; } reallen += bytesread; } /* String too short. */ if(cs->MinLen > 0 && reallen < cs->MinLen) { ShowWarn(MSG_ERR_STRING_TOO_SHORT, cs->ID_Str); } /* String too long. */ if(cs->MaxLen > 0 && reallen > cs->MaxLen) { ShowWarn(MSG_ERR_STRING_TOO_LONG, cs->ID_Str); } cs->Nr = NumStrings; cs->LenBytes = lenbytes; *csptr = cs; csptr = &cs->Next; ++NumStrings; } } } } fclose(fp); return Result; } ///