amath/build/flexcat/scancd.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;
}
///