mirror of https://gitlab.com/rnger/amath
419 lines
9.8 KiB
C
419 lines
9.8 KiB
C
/*
|
|
* $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;
|
|
}
|
|
|
|
///
|