This repository has been archived on 2023-07-11. You can view files and clone it, but cannot push or open issues or pull requests.
fte/cfte.cpp

1790 lines
62 KiB
C++

/* cfte.cpp
*
* Copyright (c) 1994-1997, Marko Macek
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "ftever.h"
#include "sysdep.h"
#include "feature.h"
#include "c_fcon~1.h"
#include "s_files.h"
#include "c_mode.h"
#define slen(s) ((s) ? (strlen(s) + 1) : 0)
typedef struct {
char *Name;
} ExMacro;
unsigned int CMacros = 0;
ExMacro *Macros = 0;
FILE *output = 0;
int lntotal = 0;
long offset = -1;
long pos = 0;
char XTarget[MAXPATH] = "";
char StartDir[MAXPATH] = "";
#include "c_comm~1.h"
#include "c_cmdtab.h"
typedef struct _CurPos {
int sz;
char *a;
char *c;
char *z;
int line;
const char *name; // filename
} CurPos;
void cleanup(int xerrno) {
if (output)
fclose(output);
if (XTarget[0] != 0)
unlink(XTarget);
exit (xerrno);
}
void Fail(CurPos &cp, const char *s, ...) {
va_list ap;
char msgbuf[1024];
va_start(ap, s);
vsprintf(msgbuf, s, ap);
va_end(ap);
fprintf(stderr, "%s:%d: Error: %s\n", cp.name, cp.line, msgbuf);
cleanup(1);
}
int LoadFile(const char *WhereName, const char *CfgName, int Level = 1);
void DefineWord(const char *w);
void PutObject(CurPos &cp, int xtag, int xlen, void *obj) {
unsigned char tag = (unsigned char)xtag;
unsigned short len = (unsigned short)xlen;
unsigned char l[2];
l[0] = len & 0xFF;
l[1] = (len >> 8) & 0xFF;
if (fwrite(&tag, 1, 1, output) != 1 ||
fwrite(l, 2, 1, output) != 1 ||
fwrite(obj, 1, len, output) != len)
{
Fail(cp, "Disk full!");
}
pos += 1 + 2 + len;
if (offset != -1 && pos >= offset) {
Fail(cp, "Error location found at %ld", pos);
}
}
void PutNull(CurPos &cp, int xtag) {
PutObject(cp, xtag, 0, 0);
}
void PutString(CurPos &cp, int xtag, char *str) {
PutObject(cp, xtag, slen(str), str);
}
void PutNumber(CurPos &cp, int xtag, long num) {
unsigned long l = num;
unsigned char b[4];
b[0] = (unsigned char)(l & 0xFF);
b[1] = (unsigned char)((l >> 8) & 0xFF);
b[2] = (unsigned char)((l >> 16) & 0xFF);
b[3] = (unsigned char)((l >> 24) & 0xFF);
PutObject(cp, xtag, 4, &b);
}
int main(int argc, char **argv) {
char Source[MAXPATH];
char Target[MAXPATH];
char *p = argv[1];
int n = 1;
fprintf(stderr, PROG_CFTE " " VERSION "\n" COPYRIGHT "\n");
if (argc < 2 || argc > 4) {
fprintf(stderr, "Usage: " PROG_CFTE " [-o<offset>] "
#ifndef UNIX
"config/"
#endif
"main.fte [fte-new.cnf]\n");
exit(1);
}
DefineWord("OS_"
#if defined(OS2)
"OS2"
#elif defined(UNIX)
"UNIX"
#elif defined(NT)
"NT"
#elif defined(DOSP32)
"DOS32"
#endif
);
if (strncmp(p, "-o", 2) == 0) {
p += 2;
offset = atol(p);
n++;
}
if (n == 1 && argc == 4) {
fprintf(stderr, "Invalid option '%s'\n", argv[1]);
exit(1);
}
strcpy(Source, argv[n++]);
strcpy(Target, "fte-new.cnf");
if (n < argc)
strcpy(Target, argv[n++]);
JustDirectory(Target, XTarget);
Slash(XTarget, 1);
sprintf(XTarget + strlen(XTarget), "cfte%ld.tmp", (long)getpid());
output = fopen(XTarget, "wb");
if (output == 0) {
fprintf(stderr, "Cannot create '%s', errno=%d!\n", XTarget, errno);
cleanup(1);
}
unsigned char b[4];
b[0] = b[1] = b[2] = b[3] = 0;
if (fwrite(b, sizeof(b), 1, output) != 1) {
fprintf(stderr, "Disk full!");
cleanup(1);
}
unsigned long l = VERNUM;
b[0] = (unsigned char)(l & 0xFF);
b[1] = (unsigned char)((l >> 8) & 0xFF);
b[2] = (unsigned char)((l >> 16) & 0xFF);
b[3] = (unsigned char)((l >> 24) & 0xFF);
if (fwrite(b, 4, 1, output) != 1) {
fprintf(stderr, "Disk full!");
cleanup(1);
}
pos = 2 * 4;
fprintf(stderr, "Compiling to '%s'\n", Target);
/*{
char PrevDir[MAXPATH];
sprintf(PrevDir, "%s/..", Target);
ExpandPath(PrevDir, StartDir);
Slash(StartDir, 1);
}*/
ExpandPath("."
#ifdef UNIX
"."
#endif
, StartDir);
Slash(StartDir, 1);
{
CurPos cp;
char FSource[MAXPATH];
if (ExpandPath(Source, FSource) != 0) {
fprintf(stderr, "Could not expand path %s\n", Source);
exit(1);
}
cp.sz = 0;
cp.c = 0;
cp.a = cp.c = 0;
cp.z = cp.a + cp.sz;
cp.line = 0;
cp.name = "<cfte-start>";
PutString(cp, CF_STRING, FSource);
}
if (LoadFile(StartDir, Source, 0) != 0) {
fprintf(stderr, "\nCompile failed\n");
cleanup(1);
}
l = CONFIG_ID;
b[0] = (unsigned char)(l & 0xFF);
b[1] = (unsigned char)((l >> 8) & 0xFF);
b[2] = (unsigned char)((l >> 16) & 0xFF);
b[3] = (unsigned char)((l >> 24) & 0xFF);
fseek(output, 0, SEEK_SET);
fwrite(b, 4, 1, output);
fclose(output);
if (unlink(Target) != 0 && errno != ENOENT) {
fprintf(stderr, "Remove of '%s' failed, result left in %s, errno=%d\n",
Target, XTarget, errno);
exit(1);
}
if (rename(XTarget, Target) != 0) {
fprintf(stderr, "Rename of '%s' to '%s' failed, errno=%d\n",
XTarget, Target, errno);
exit(1);
}
fprintf(stderr, "\nDone.\n");
return 0;
}
#define MODE_BFI(x) { #x, BFI_##x }
#define MODE_BFS(x) { #x, BFS_##x }
#define MODE_FLG(x) { #x, FLAG_##x }
#define EVENT_FLG(x) { #x, EM_##x }
#define COLORIZE_FLG(x) { #x, COL_##x }
#define HILIT_CLR(x) { #x, CLR_##x }
typedef struct _OrdLookup {
const char *Name;
int num;
} OrdLookup;
OrdLookup mode_num[] = {
MODE_BFI(AutoIndent),
MODE_BFI(Insert),
MODE_BFI(DrawOn),
MODE_BFI(HilitOn),
MODE_BFI(ExpandTabs),
MODE_BFI(Trim),
MODE_BFI(TabSize),
MODE_BFI(ShowTabs),
MODE_BFI(LineChar),
MODE_BFI(StripChar),
MODE_BFI(AddLF),
MODE_BFI(AddCR),
MODE_BFI(ForceNewLine),
MODE_BFI(HardMode),
MODE_BFI(Undo),
MODE_BFI(ReadOnly),
MODE_BFI(AutoSave),
MODE_BFI(KeepBackups),
MODE_BFI(LoadMargin),
MODE_BFI(UndoLimit),
MODE_BFI(MatchCase),
MODE_BFI(BackSpKillTab),
MODE_BFI(DeleteKillTab),
MODE_BFI(BackSpUnindents),
MODE_BFI(SpaceTabs),
MODE_BFI(IndentWithTabs),
MODE_BFI(LeftMargin),
MODE_BFI(RightMargin),
MODE_BFI(SeeThruSel),
MODE_BFI(WordWrap),
MODE_BFI(ShowMarkers),
MODE_BFI(CursorThroughTabs),
MODE_BFI(SaveFolds),
MODE_BFI(MultiLineHilit),
MODE_BFI(AutoHilitParen),
MODE_BFI(Abbreviations),
MODE_BFI(BackSpKillBlock),
MODE_BFI(DeleteKillBlock),
MODE_BFI(PersistentBlocks),
MODE_BFI(InsertKillBlock),
MODE_BFI(UndoMoves),
MODE_BFI(DetectLineSep),
MODE_BFI(TrimOnSave),
{ 0, 0 },
};
OrdLookup mode_string[] = {
MODE_BFI(Colorizer),
MODE_BFI(IndentMode),
MODE_BFS(RoutineRegexp),
MODE_BFS(DefFindOpt),
MODE_BFS(DefFindReplaceOpt),
MODE_BFS(CommentStart),
MODE_BFS(CommentEnd),
MODE_BFS(WordChars),
MODE_BFS(CapitalChars),
MODE_BFS(FileNameRx),
MODE_BFS(FirstLineRx),
MODE_BFS(CompileCommand),
MODE_BFI(EventMap),
{ 0, 0 },
};
OrdLookup global_num[] = {
#ifdef CONFIG_INDENT_C
MODE_FLG(C_Indent),
MODE_FLG(C_BraceOfs),
MODE_FLG(C_CaseOfs),
MODE_FLG(C_CaseDelta),
MODE_FLG(C_ClassOfs),
MODE_FLG(C_ClassDelta),
MODE_FLG(C_ColonOfs),
MODE_FLG(C_CommentOfs),
MODE_FLG(C_CommentDelta),
MODE_FLG(C_FirstLevelWidth),
MODE_FLG(C_FirstLevelIndent),
MODE_FLG(C_Continuation),
MODE_FLG(C_ParenDelta),
#endif
#ifdef CONFIG_INDENT_REXX
MODE_FLG(REXX_Indent),
MODE_FLG(REXX_Do_Offset),
#endif
MODE_FLG(ScreenSizeX),
MODE_FLG(ScreenSizeY),
MODE_FLG(CursorInsertStart),
MODE_FLG(CursorInsertEnd),
MODE_FLG(CursorOverStart),
MODE_FLG(CursorOverEnd),
MODE_FLG(SysClipboard),
MODE_FLG(OpenAfterClose),
MODE_FLG(ShowVScroll),
MODE_FLG(ShowHScroll),
MODE_FLG(ScrollBarWidth),
MODE_FLG(SelectPathname),
MODE_FLG(ShowToolBar),
MODE_FLG(ShowMenuBar),
MODE_FLG(KeepHistory),
MODE_FLG(LoadDesktopOnEntry),
MODE_FLG(SaveDesktopOnExit),
MODE_FLG(KeepMessages),
MODE_FLG(ScrollBorderX),
MODE_FLG(ScrollBorderY),
MODE_FLG(ScrollJumpX),
MODE_FLG(ScrollJumpY),
MODE_FLG(GUIDialogs),
MODE_FLG(PMDisableAccel),
MODE_FLG(SevenBit),
MODE_FLG(WeirdScroll),
MODE_FLG(LoadDesktopMode),
{ 0, 0 },
};
OrdLookup global_string[] = {
MODE_FLG(DefaultModeName),
MODE_FLG(CompletionFilter),
MODE_FLG(PrintDevice),
MODE_FLG(CompileCommand),
MODE_FLG(WindowFont),
MODE_FLG(HelpCommand),
{ 0, 0 },
};
OrdLookup event_string[] = {
EVENT_FLG(MainMenu),
EVENT_FLG(LocalMenu),
{ 0, 0 },
};
OrdLookup colorize_string[] = {
COLORIZE_FLG(SyntaxParser),
{ 0, 0 },
};
OrdLookup hilit_colors[] = {
HILIT_CLR(Normal),
HILIT_CLR(Keyword),
HILIT_CLR(String),
HILIT_CLR(Comment),
HILIT_CLR(CPreprocessor),
HILIT_CLR(Regexp),
HILIT_CLR(Header),
HILIT_CLR(Quotes),
HILIT_CLR(Number),
HILIT_CLR(HexNumber),
HILIT_CLR(OctalNumber),
HILIT_CLR(FloatNumber),
HILIT_CLR(Function),
HILIT_CLR(Command),
HILIT_CLR(Tag),
HILIT_CLR(Punctuation),
HILIT_CLR(New),
HILIT_CLR(Old),
HILIT_CLR(Changed),
HILIT_CLR(Control),
HILIT_CLR(Separator),
HILIT_CLR(Variable),
HILIT_CLR(Symbol),
HILIT_CLR(Directive),
HILIT_CLR(Label),
HILIT_CLR(Special),
HILIT_CLR(QuoteDelim),
HILIT_CLR(RegexpDelim),
{ 0, 0 },
};
int Lookup(OrdLookup *where, char *what) {
int i;
for (i = 0; where[i].Name != 0; i++) {
if (strcmp(what, where[i].Name) == 0)
return where[i].num;
}
// fprintf(stderr, "\nBad name: %s (i = %d)\n", what, i);
return -1;
}
#define P_EOF 0 // end of file
#define P_SYNTAX 1 // unknown
#define P_WORD 2 // a-zA-Z_
#define P_NUMBER 3 // 0-9
#define P_STRING 4 // "'`
#define P_ASSIGN 5 // =
#define P_EOS 6 // ;
#define P_KEYSPEC 7 // []
#define P_OPENBRACE 8 // {
#define P_CLOSEBRACE 9 // }
#define P_COLON 10 // :
#define P_COMMA 11 // ,
#define P_QUEST 12
#define P_VARIABLE 13 // $
#define P_DOT 14 // . (concat)
#define K_UNKNOWN 0
#define K_MODE 1
#define K_KEY 2
#define K_COLOR 3
#define K_KEYWORD 4
#define K_OBJECT 5
#define K_MENU 6
#define K_ITEM 7
#define K_SUBMENU 8
#define K_COMPILERX 9
#define K_EXTERN 10
#define K_INCLUDE 11
#define K_SUB 12
#define K_EVENTMAP 13
#define K_COLORIZE 14
#define K_ABBREV 15
#define K_HSTATE 16
#define K_HTRANS 17
#define K_HWORDS 18
#define K_SUBMENUCOND 19
#define K_HWTYPE 20
#define K_COLPALETTE 21
typedef char Word[64];
OrdLookup CfgKW[] = {
{ "mode", K_MODE },
{ "eventmap", K_EVENTMAP },
{ "key", K_KEY },
{ "color", K_COLOR },
{ "color_palette", K_COLPALETTE },
{ "keyword", K_KEYWORD },
{ "object", K_OBJECT },
{ "menu", K_MENU },
{ "item", K_ITEM },
{ "submenu", K_SUBMENU },
{ "CompileRx", K_COMPILERX },
{ "extern", K_EXTERN },
{ "include", K_INCLUDE },
{ "sub", K_SUB },
{ "colorize", K_COLORIZE },
{ "abbrev", K_ABBREV },
{ "h_state", K_HSTATE },
{ "h_trans", K_HTRANS },
{ "h_words", K_HWORDS },
{ "h_wtype", K_HWTYPE },
{ "submenucond", K_SUBMENUCOND },
{ 0, 0 },
};
OrdLookup CfgVar[] = {
{ "FilePath", mvFilePath },
{ "FileName", mvFileName },
{ "FileDirectory", mvFileDirectory },
{ "FileBaseName", mvFileBaseName },
{ "FileExtension", mvFileExtension },
{ "CurDirectory", mvCurDirectory },
{ "CurRow", mvCurRow, },
{ "CurCol", mvCurCol },
{ "Char", mvChar },
{ "Word", mvWord },
{ "Line", mvLine },
{ 0, 0 },
};
char **words = 0;
unsigned int wordCount = 0;
int DefinedWord(const char *w) {
if (words == 0 || wordCount == 0)
return 0;
for (unsigned int i = 0; i < wordCount; i++)
if (strcmp(w, words[i]) == 0)
return 1;
return 0;
}
void DefineWord(const char *w) {
if (!w || !w[0])
return ;
if (!DefinedWord(w)) {
words = (char **)realloc(words, sizeof (char *) * (wordCount + 1));
assert(words != 0);
words[wordCount] = strdup(w);
assert(words[wordCount] != 0);
wordCount++;
}
}
int colorCount;
struct _color {
char *colorName;
char *colorValue;
} *colors;
int DefineColor(char *name, char *value) {
if (!name || !value)
return 0;
colors = (struct _color *)realloc(colors, sizeof (struct _color) * (colorCount + 1));
assert(colors != 0);
colors[colorCount].colorName = strdup(name);
colors[colorCount].colorValue = strdup(value);
assert(colors != NULL);
assert(colors[colorCount].colorName != 0);
assert(colors[colorCount].colorValue != 0);
colorCount++;
return 1;
}
char *DefinedColor(char *name) {
if (colors == 0 || colorCount == 0)
return 0;
for (int i = 0; i < colorCount; i++)
if (strcmp(name, colors[i].colorName) == 0)
return colors[i].colorValue;
return 0;
}
char *GetColor(CurPos &cp, char *name) {
char *c;
static char color[4];
// add support for fore:back and remove it from fte itself
if ((c = strchr(name, ' ')) != NULL) {
} else if ((c = strchr(name, ':')) != NULL) {
char clr[4];
*c++ = 0;
clr[0] = GetColor(cp, name)[0];
clr[1] = ' ';
clr[2] = GetColor(cp, c)[2];
clr[3] = 0;
memcpy((void *)color, (void *)clr, sizeof(color));
name = (char *)color;
} else {
char *p = DefinedColor(name);
if (!p)
Fail(cp, "Unknown symbolic color %s", name);
name = p;
}
if (!isxdigit(name[0]) &&
name[1] != ' ' &&
!isxdigit(name[2]) &&
name[3] != 0)
{
Fail(cp, "malformed color specification: %s", name);
}
return name;
}
int GetWord(CurPos &cp, char *w) {
char *p = w;
int len = 0;
while (len < int(sizeof(Word)) && cp.c < cp.z &&
((*cp.c >= 'a' && *cp.c <= 'z') ||
(*cp.c >= 'A' && *cp.c <= 'Z') ||
(*cp.c >= '0' && *cp.c <= '9') ||
(*cp.c == '_')))
{
*p++ = *cp.c++;
len++;
}
if (len == sizeof(Word)) return -1;
*p = 0;
return 0;
}
int Parse(CurPos &cp) {
while (cp.c < cp.z) {
switch (*cp.c) {
#ifndef UNIX
case '\x1A': /* ^Z :-* */ return P_EOF;
#endif
case '#':
while (cp.c < cp.z && *cp.c != '\n') cp.c++;
break;
case '%':
cp.c++;
if (cp.c + 7 < cp.z && strncmp(cp.c, "define(", 7) == 0) {
Word w;
cp.c += 7;
while (cp.c < cp.z && *cp.c != ')') {
GetWord(cp, w);
//printf("define '%s'\n", w);
DefineWord(w);
if (cp.c < cp.z && *cp.c != ',' && *cp.c != ')' )
Fail(cp, "unexpected: %c", cp.c[0]);
if (cp.c < cp.z && *cp.c == ',')
cp.c++;
}
cp.c++;
/* } else if (cp.c + 6 && strcmp(cp.c, "undef(", 6) == 0) {
Word w;
cp.c += 6;
while (cp.c < cp.z && *cp.c != ')') {
GetWord(cp, w);
UndefWord(w);
}*/
} else if (cp.c + 3 < cp.z && strncmp(cp.c, "if(", 3) == 0) {
Word w;
int wasWord = 0;
cp.c += 3;
while (cp.c < cp.z && *cp.c != ')') {
int neg = 0;
if (*cp.c == '!') {
cp.c++;
neg = 1;
}
GetWord(cp, w);
if (DefinedWord(w))
wasWord = 1;
if (neg)
wasWord = wasWord ? 0 : 1;
/*if (wasWord)
printf("yes '%s'\n", w);
else
printf("not '%s'\n", w);*/
if (cp.c < cp.z && *cp.c != ',' && *cp.c != ')' )
Fail(cp, "unexpected: %c", cp.c[0]);
if (cp.c < cp.z && *cp.c == ',')
cp.c++;
}
cp.c++;
if (!wasWord) {
int nest = 1;
while (cp.c < cp.z) {
if (*cp.c == '\n') {
cp.line++;
lntotal++;
} else if (*cp.c == '%') {
if (cp.c + 6 < cp.z &&
strncmp(cp.c, "%endif", 6) == 0)
{
cp.c += 6;
if (--nest == 0)
break;
}
if (cp.c + 3 < cp.z &&
strncmp(cp.c, "%if", 3) == 0)
{
cp.c += 3;
++nest;
}
} else if (*cp.c == '#') {
// we really shouldn't process hashed % directives
while( cp.c < cp.z && *cp.c != '\n' ) cp.c++;
// workaround to make line numbering correct
cp.line++;
lntotal++;
}
cp.c++;
}
}
} else if (cp.c + 5 < cp.z && strncmp(cp.c, "endif", 5) == 0) {
cp.c += 5;
}
if (cp.c < cp.z && *cp.c != '\n' && *cp.c != '\r')
Fail(cp, "syntax error %30.30s", cp.c);
break;
case '\n':
cp.line++;
lntotal++;
case ' ':
case '\t':
case '\r':
cp.c++;
break;
case '=': return P_ASSIGN;
case ';': return P_EOS;
case ',': return P_COMMA;
case ':': return P_COLON;
case '.': return P_DOT;
case '\'':
case '"':
case '`':
case '/': return P_STRING;
case '[': return P_KEYSPEC;
case '{': return P_OPENBRACE;
case '}': return P_CLOSEBRACE;
case '?': return P_QUEST;
case '$': return P_VARIABLE;
case '-': case '+':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': return P_NUMBER;
default:
if ((*cp.c >= 'a' && *cp.c <= 'z') ||
(*cp.c >= 'A' && *cp.c <= 'Z') ||
(*cp.c == '_'))
return P_WORD;
else
return P_SYNTAX;
}
}
return P_EOF;
}
void GetOp(CurPos &cp, int what) {
switch (what) {
case P_COMMA:
case P_OPENBRACE:
case P_CLOSEBRACE:
case P_ASSIGN:
case P_EOS:
case P_COLON:
case P_QUEST:
case P_VARIABLE:
case P_DOT:
cp.c++;
break;
}
}
char *GetString(CurPos &cp) {
char c = *cp.c;
char *p = cp.c;
char *d = cp.c;
if (c == '[') c = ']';
cp.c++; // skip '"`
while (cp.c < cp.z) {
if (*cp.c == '\\') {
if (c == '/')
*p++ = *cp.c;
cp.c++;
if (cp.c == cp.z) return 0;
if (c == '"') {
switch (*cp.c) {
case 'e': *cp.c = '\x1B'; break;
case 't': *cp.c = '\t'; break;
case 'r': *cp.c = '\r'; break;
case 'n': *cp.c = '\n'; break;
case 'b': *cp.c = '\b'; break;
case 'v': *cp.c = '\v'; break;
case 'a': *cp.c = '\a'; break;
}
}
} else if (*cp.c == c) {
cp.c++;
*p = 0;
return d;
} else if (*cp.c == '\n') return 0;
if (*cp.c == '\n') cp.line++;
if (*cp.c == '\r') {
cp.c++;
if (cp.c == cp.z) return 0;
}
*p++ = *cp.c++;
}
return 0;
}
int GetNumber(CurPos &cp) {
int value = 0;
int neg = 0;
if (cp.c < cp.z && *cp.c == '-' || *cp.c == '+') {
if (*cp.c == '-') neg = 1;
cp.c++;
}
while (cp.c < cp.z && (*cp.c >= '0' && *cp.c <= '9')) {
value = value * 10 + (*cp.c - '0');
cp.c++;
}
return neg ? -value : value;
}
int CmdNum(const char *Cmd) {
unsigned int i;
for (i = 0;
i < sizeof(Command_Table) / sizeof(Command_Table[0]);
i++)
if (strcmp(Cmd, Command_Table[i].Name) == 0)
return Command_Table[i].CmdId;
for (i = 0; i < CMacros; i++)
if (Macros[i].Name && (strcmp(Cmd, Macros[i].Name)) == 0)
return i | CMD_EXT;
return 0; // Nop
}
int NewCommand(const char *Name) {
if (Name == 0)
Name = "";
Macros = (ExMacro *) realloc(Macros, sizeof(ExMacro) * (1 + CMacros));
Macros[CMacros].Name = strdup(Name);
CMacros++;
return CMacros - 1;
}
int ParseCommands(CurPos &cp, char *Name) {
//if (!Name)
// return 0;
Word cmd;
int p;
long Cmd = NewCommand(Name) | CMD_EXT;
long cnt;
long ign = 0;
PutNumber(cp, CF_INT, Cmd);
GetOp(cp, P_OPENBRACE);
cnt = 1;
while (1) {
p = Parse(cp);
if (p == P_CLOSEBRACE) break;
if (p == P_EOF) Fail(cp, "Unexpected EOF");
if (p == P_DOT) {
GetOp(cp, P_DOT);
PutNull(cp, CF_CONCAT);
} else if (p == P_NUMBER) {
long num = GetNumber(cp);
if (Parse(cp) != P_COLON) {
PutNumber(cp, CF_INT, num);
} else {
cnt = num;
GetOp(cp, P_COLON);
}
} else if (p == P_WORD) {
long Command;
if (GetWord(cp, cmd) == -1) Fail(cp, "Syntax error");
Command = CmdNum(cmd);
if (Command == 0)
Fail(cp, "Unrecognised command: %s", cmd);
PutNumber(cp, CF_COMMAND, Command);
PutNumber(cp, CF_INT, cnt);
PutNumber(cp, CF_INT, ign);
ign = 0;
cnt = 1;
} else if (p == P_STRING) {
char *s = GetString(cp);
PutString(cp, CF_STRING, s);
} else if (p == P_QUEST) {
ign = 1;
GetOp(cp, P_QUEST);
} else if (p == P_VARIABLE) {
GetOp(cp, P_VARIABLE);
if (Parse(cp) != P_WORD) Fail(cp, "Syntax error (variable name expected)");
Word w;
if (GetWord(cp, w) != 0) Fail(cp, "Syntax error (bad variable name)");
long var = Lookup(CfgVar, w);
if (var == -1) Fail(cp, "Unrecognised variable");
PutNumber(cp, CF_VARIABLE, var);
} else if (p == P_EOS) {
GetOp(cp, P_EOS);
cnt = 1;
} else
Fail(cp, "Syntax error");
}
GetOp(cp, P_CLOSEBRACE);
return 0;
}
int ParseConfigFile(CurPos &cp) {
Word w = "";
char *s = 0;
int p = 0;
Word ObjName = "", UpMode = "";
while (1) {
p = Parse(cp);
switch (p) {
case P_WORD:
if (GetWord(cp, w) != 0) Fail(cp, "Syntax error");
switch (Lookup(CfgKW, w)) {
case K_SUB:
{
Word Name;
if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, Name) != 0) Fail(cp, "Syntax error");
PutString(cp, CF_SUB, Name);
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
if (ParseCommands(cp, strdup(Name ? Name : "")) == -1)
Fail(cp, "Parse failed");
PutNull(cp, CF_END);
}
break;
case K_MENU:
{
Word MenuName;
//int menu = -1, item = -1;
if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");;
if (GetWord(cp, MenuName) != 0) Fail(cp, "Syntax error");;
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
PutString(cp, CF_MENU, MenuName);
while (1) {
p = Parse(cp);
if (p == P_CLOSEBRACE) break;
if (p == P_EOF) Fail(cp, "Unexpected EOF");
if (p != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, w) != 0) Fail(cp, "Parse failed");
switch (Lookup(CfgKW, w)) {
case K_ITEM: // menu::item
switch (Parse(cp)) {
case P_EOS:
PutNull(cp, CF_ITEM);
break;
case P_STRING:
s = GetString(cp);
PutString(cp, CF_ITEM, s);
break;
default:
Fail(cp, "Syntax error");;
}
if (Parse(cp) == P_EOS) {
GetOp(cp, P_EOS);
break;
}
if (Parse(cp) != P_OPENBRACE)
Fail(cp, "'{' expected");
PutNull(cp, CF_MENUSUB);
if (ParseCommands(cp, 0) == -1)
Fail(cp, "Parse failed");
PutNull(cp, CF_END);
break;
case K_SUBMENU: // menu::submenu
if (Parse(cp) != P_STRING)
Fail(cp, "String expected");
s = GetString(cp);
if (Parse(cp) != P_COMMA)
Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_WORD)
Fail(cp, "Syntax error");
if (GetWord(cp, w) == -1)
Fail(cp, "Parse failed");
PutString(cp, CF_SUBMENU, s);
PutString(cp, CF_STRING, w);
if (Parse(cp) != P_EOS)
Fail(cp, "';' expected");
GetOp(cp, P_EOS);
break;
case K_SUBMENUCOND: // menu::submenu
if (Parse(cp) != P_STRING)
Fail(cp, "String expected");
s = GetString(cp);
if (Parse(cp) != P_COMMA)
Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_WORD)
Fail(cp, "Syntax error");
if (GetWord(cp, w) == -1)
Fail(cp, "Parse failed");
PutString(cp, CF_SUBMENUCOND, s);
PutString(cp, CF_STRING, w);
if (Parse(cp) != P_EOS)
Fail(cp, "';' expected");
GetOp(cp, P_EOS);
break;
default: // menu::
Fail(cp, "Syntax error");
}
}
GetOp(cp, P_CLOSEBRACE);
PutNull(cp, CF_END);
}
break;
case K_EVENTMAP:
{
if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, ObjName) != 0) Fail(cp, "Parse failed");
PutString(cp, CF_EVENTMAP, ObjName);
UpMode[0] = 0;
if (Parse(cp) == P_COLON) {
GetOp(cp, P_COLON);
if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, UpMode) != 0) Fail(cp, "Parse failed");
}
PutString(cp, CF_PARENT, UpMode);
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
while (1) {
p = Parse(cp);
if (p == P_CLOSEBRACE) break;
if (p == P_EOF) Fail(cp, "Unexpected EOF");
if (p != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, w) != 0) Fail(cp, "Parse failed");
switch (Lookup(CfgKW, w)) {
case K_KEY: // mode::key
if (Parse(cp) != P_KEYSPEC) Fail(cp, "'[' expected");
s = GetString(cp);
PutString(cp, CF_KEY, s);
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
PutNull(cp, CF_KEYSUB);
if (ParseCommands(cp, 0) == -1) Fail(cp, "Parse failed");
PutNull(cp, CF_END);
break;
case K_ABBREV:
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
s = GetString(cp);
PutString(cp, CF_ABBREV, s);
switch (Parse(cp)) {
case P_OPENBRACE:
PutNull(cp, CF_KEYSUB);
if (ParseCommands(cp, 0) == -1) Fail(cp, "Parse failed");
PutNull(cp, CF_END);
break;
case P_STRING:
s = GetString(cp);
PutString(cp, CF_STRING, s);
if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
GetOp(cp, P_EOS);
break;
default:
Fail(cp, "Syntax error");
}
break;
default: // mode::
if (Parse(cp) != P_ASSIGN) Fail(cp, "'=' expected");
GetOp(cp, P_ASSIGN);
switch (Parse(cp)) {
/* case P_NUMBER:
{
long var;
long num;
num = GetNumber(cp);
var = LookupEventNumber(w);
if (var == -1) return -1;
PutObj(cp, CF_SETVAR, sizeof(long), &var);
PutObj(cp, CF_INT, sizeof(long), &num);
}
break;*/
case P_STRING:
{
long var;
s = GetString(cp);
if (s == 0) Fail(cp, "String expected");
var = Lookup(event_string, w);
if (var == -1) Fail(cp, "Lookup of '%s' failed", w);
PutNumber(cp, CF_SETVAR, var);
PutString(cp, CF_STRING, s);
}
break;
default:
return -1;
}
if (Parse(cp) != P_EOS) return -1;
GetOp(cp, P_EOS);
break;
}
}
GetOp(cp, P_CLOSEBRACE);
PutNull(cp, CF_END);
}
break;
case K_COLORIZE:
{
long LastState = -1;
if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, ObjName) != 0) Fail(cp, "Parse failed");
PutString(cp, CF_COLORIZE, ObjName);
UpMode[0] = 0;
if (Parse(cp) == P_COLON) {
GetOp(cp, P_COLON);
if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, UpMode) != 0) Fail(cp, "Parse failed");
}
PutString(cp, CF_PARENT, UpMode);
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
while (1) {
p = Parse(cp);
if (p == P_CLOSEBRACE) break;
if (p == P_EOF) Fail(cp, "Unexpected EOF");
if (p != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, w) != 0) Fail(cp, "Parse failed");
switch (Lookup(CfgKW, w)) {
case K_COLOR: // mode::color
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
PutNull(cp, CF_COLOR);
while (1) {
char *sname, *svalue;
long cidx;
if (Parse(cp) == P_CLOSEBRACE) break;
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
sname = GetString(cp);
if ((cidx = Lookup(hilit_colors, sname)) == -1)
Fail(cp, "Lookup of '%s' failed", sname);
PutNumber(cp, CF_INT, cidx);
if (Parse(cp) != P_COMMA)
Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
svalue = GetString(cp);
svalue = GetColor(cp, svalue);
PutString(cp, CF_STRING, svalue);
if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
GetOp(cp, P_CLOSEBRACE);
if (Parse(cp) != P_COMMA)
break;
else
GetOp(cp, P_COMMA);
}
if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
GetOp(cp, P_CLOSEBRACE);
if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
GetOp(cp, P_EOS);
PutNull(cp, CF_END);
break;
case K_KEYWORD: // mode::keyword
{
char *colorstr, *kname;
//int color;
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
colorstr = GetString(cp);
colorstr = GetColor(cp, colorstr);
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
PutString(cp, CF_KEYWORD, colorstr);
while (1) {
if (Parse(cp) == P_CLOSEBRACE) break;
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
kname = GetString(cp);
PutString(cp, CF_STRING, kname);
if (Parse(cp) != P_COMMA)
break;
else
GetOp(cp, P_COMMA);
}
}
if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
GetOp(cp, P_CLOSEBRACE);
if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
GetOp(cp, P_EOS);
PutNull(cp, CF_END);
break;
case K_HSTATE:
{
long stateno;
char *cname;
long cidx;
if (Parse(cp) != P_NUMBER) Fail(cp, "state index expected");
stateno = GetNumber(cp);
if (stateno != LastState + 1) Fail(cp, "invalid state index");
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
PutNumber(cp, CF_HSTATE, stateno);
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
cname = GetString(cp);
if ((cidx = Lookup(hilit_colors, cname)) == -1)
Fail(cp, "Lookup of '%s' failed", cname);
PutNumber(cp, CF_INT, cidx);
if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
GetOp(cp, P_CLOSEBRACE);
LastState = stateno;
}
break;
case K_HTRANS:
{
long next_state;
char *opts, *match;
long match_opts;
char *cname;
long cidx;
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
if (Parse(cp) != P_NUMBER) Fail(cp, "next_state index expected");
next_state = GetNumber(cp);
if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_STRING) Fail(cp, "match options expected");
opts = GetString(cp);
if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_STRING) Fail(cp, "match string expected");
match = GetString(cp);
PutNumber(cp, CF_HTRANS, next_state);
match_opts = 0;
if (strchr(opts, '^')) match_opts |= MATCH_MUST_BOL;
if (strchr(opts, '$')) match_opts |= MATCH_MUST_EOL;
//if (strchr(opts, 'b')) match_opts |= MATCH_MUST_BOLW;
//if (strchr(opts, 'e')) match_opts |= MATCH_MUST_EOLW;
if (strchr(opts, 'i')) match_opts |= MATCH_NO_CASE;
if (strchr(opts, 's')) match_opts |= MATCH_SET;
if (strchr(opts, 'S')) match_opts |= MATCH_NOTSET;
if (strchr(opts, '-')) match_opts |= MATCH_NOGRAB;
if (strchr(opts, '<')) match_opts |= MATCH_TAGASNEXT;
if (strchr(opts, '>')) match_opts &= ~MATCH_TAGASNEXT;
//if (strchr(opts, '!')) match_opts |= MATCH_NEGATE;
if (strchr(opts, 'q')) match_opts |= MATCH_QUOTECH;
if (strchr(opts, 'Q')) match_opts |= MATCH_QUOTEEOL;
if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
cname = GetString(cp);
if ((cidx = Lookup(hilit_colors, cname)) == -1)
Fail(cp, "Lookup of '%s' failed", cname);
PutNumber(cp, CF_INT, match_opts);
PutNumber(cp, CF_INT, cidx);
PutString(cp, CF_STRING, match);
if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
GetOp(cp, P_CLOSEBRACE);
}
break;
case K_HWTYPE:
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
{
long options = 0;
long nextKwdMatchedState;
long nextKwdNotMatchedState;
long nextKwdNoCharState;
char *opts;
char *wordChars;
if (Parse(cp) != P_NUMBER) Fail(cp, "next_state index expected");
nextKwdMatchedState = GetNumber(cp);
if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_NUMBER) Fail(cp, "next_state index expected");
nextKwdNotMatchedState = GetNumber(cp);
if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_NUMBER) Fail(cp, "next_state index expected");
nextKwdNoCharState = GetNumber(cp);
if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
opts = GetString(cp);
if (strchr(opts, 'i')) options |= STATE_NOCASE;
if (strchr(opts, '<')) options |= STATE_TAGASNEXT;
if (strchr(opts, '>')) options &= ~STATE_TAGASNEXT;
if (strchr(opts, '-')) options |= STATE_NOGRAB;
if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
wordChars = GetString(cp);
PutNull(cp, CF_HWTYPE);
PutNumber(cp, CF_INT, nextKwdMatchedState);
PutNumber(cp, CF_INT, nextKwdNotMatchedState);
PutNumber(cp, CF_INT, nextKwdNoCharState);
PutNumber(cp, CF_INT, options);
PutString(cp, CF_STRING, wordChars);
}
if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
GetOp(cp, P_CLOSEBRACE);
break;
case K_HWORDS:
{
char *colorstr, *kname;
//int color;
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
colorstr = GetString(cp);
colorstr = GetColor(cp, colorstr);
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
PutString(cp, CF_HWORDS, colorstr);
while (1) {
if (Parse(cp) == P_CLOSEBRACE) break;
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
kname = GetString(cp);
PutString(cp, CF_STRING, kname);
if (Parse(cp) != P_COMMA)
break;
else
GetOp(cp, P_COMMA);
}
}
if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
GetOp(cp, P_CLOSEBRACE);
PutNull(cp, CF_END);
break;
default:
if (Parse(cp) != P_ASSIGN) Fail(cp, "'=' expected");
GetOp(cp, P_ASSIGN);
switch (Parse(cp)) {
/*case P_NUMBER:
{
long var;
long num;
num = GetNumber(cp);
var = LookupColorizeNumber(w);
if (var == -1) return -1;
PutObj(cp, CF_SETVAR, sizeof(long), &var);
PutObj(cp, CF_INT, sizeof(long), &num);
}
break;*/
case P_STRING:
{
long var;
s = GetString(cp);
if (s == 0) Fail(cp, "Parse failed");
var = Lookup(colorize_string, w);
if (var == -1)
Fail(cp, "Lookup of '%s' failed", w);
PutNumber(cp, CF_SETVAR, var);
PutString(cp, CF_STRING, s);
}
break;
default:
return -1;
}
if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
GetOp(cp, P_EOS);
break;
}
}
GetOp(cp, P_CLOSEBRACE);
PutNull(cp, CF_END);
}
break;
case K_MODE: // mode::
{
if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, ObjName) != 0) Fail(cp, "Parse failed");
PutString(cp, CF_MODE, ObjName);
UpMode[0] = 0;
if (Parse(cp) == P_COLON) {
GetOp(cp, P_COLON);
if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, UpMode) != 0) Fail(cp, "Parse failed");
}
PutString(cp, CF_PARENT, UpMode);
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
while (1) {
p = Parse(cp);
if (p == P_CLOSEBRACE) break;
if (p == P_EOF) Fail(cp, "Unexpected EOF");
if (p != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, w) != 0) Fail(cp, "Parse failed");
//switch (Lookup(CfgKW, w)) {
//default: // mode::
if (Parse(cp) != P_ASSIGN) Fail(cp, "'=' expected");
GetOp(cp, P_ASSIGN);
switch (Parse(cp)) {
case P_NUMBER:
{
long var;
long num;
num = GetNumber(cp);
var = Lookup(mode_num, w);
if (var == -1)
Fail(cp, "Lookup of '%s' failed", w);
PutNumber(cp, CF_SETVAR, var);
PutNumber(cp, CF_INT, num);
}
break;
case P_STRING:
{
long var;
s = GetString(cp);
if (s == 0) Fail(cp, "Parse failed");
var = Lookup(mode_string, w);
if (var == -1)
Fail(cp, "Lookup of '%s' filed", w);
PutNumber(cp, CF_SETVAR, var);
PutString(cp, CF_STRING, s);
}
break;
default:
return -1;
}
if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
GetOp(cp, P_EOS);
// break;
//}
}
GetOp(cp, P_CLOSEBRACE);
PutNull(cp, CF_END);
}
break;
case K_OBJECT:
{
if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, ObjName) != 0) Fail(cp, "Parse failed");
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
PutString(cp, CF_OBJECT, ObjName);
while (1) {
p = Parse(cp);
if (p == P_CLOSEBRACE) break;
if (p == P_EOF) Fail(cp, "Unexpected EOF");
if (p != P_WORD) Fail(cp, "Syntax error");
if (GetWord(cp, w) != 0) Fail(cp, "Parse failed");
switch (Lookup(CfgKW, w)) {
case K_COLOR: // mode::color
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
PutNull(cp, CF_COLOR);
while (1) {
char *sname, *svalue;
if (Parse(cp) == P_CLOSEBRACE) break;
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
sname = GetString(cp);
PutString(cp, CF_STRING, sname);
if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
svalue = GetString(cp);
svalue = GetColor(cp, svalue);
PutString(cp, CF_STRING, svalue);
if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
GetOp(cp, P_CLOSEBRACE);
if (Parse(cp) != P_COMMA)
break;
else
GetOp(cp, P_COMMA);
}
if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
GetOp(cp, P_CLOSEBRACE);
if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
GetOp(cp, P_EOS);
PutNull(cp, CF_END);
break;
case K_COMPILERX:
{
long file, line, msg;
char *regexp;
if (Parse(cp) != P_ASSIGN) Fail(cp, "'=' expected");
GetOp(cp, P_ASSIGN);
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
if (Parse(cp) != P_NUMBER) Fail(cp, "Number expected");
file = GetNumber(cp);
if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_NUMBER) Fail(cp, "Number expected");
line = GetNumber(cp);
if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_NUMBER) Fail(cp, "Number expected");
msg = GetNumber(cp);
if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
regexp = GetString(cp);
if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
GetOp(cp, P_CLOSEBRACE);
PutNull(cp, CF_COMPRX);
PutNumber(cp, CF_INT, file);
PutNumber(cp, CF_INT, line);
PutNumber(cp, CF_INT, msg);
PutString(cp, CF_REGEXP, regexp);
if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
GetOp(cp, P_EOS);
}
break;
default: // mode::
if (Parse(cp) != P_ASSIGN) Fail(cp, "'=' expected");
GetOp(cp, P_ASSIGN);
switch (Parse(cp)) {
case P_NUMBER:
{
long var;
long num;
num = GetNumber(cp);
var = Lookup(global_num, w);
if (var == -1)
Fail(cp, "Lookup of '%s' failed", w);
PutNumber(cp, CF_SETVAR, var);
PutNumber(cp, CF_INT, num);
}
break;
case P_STRING:
{
long var;
s = GetString(cp);
if (s == 0) Fail(cp, "Parse failed");
var = Lookup(global_string, w);
if (var == -1) Fail(cp, "Lookup of '%s' failed");
PutNumber(cp, CF_SETVAR, var);
PutString(cp, CF_STRING, s);
}
break;
default:
Fail(cp, "Syntax error");
}
if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
GetOp(cp, P_EOS);
break;
}
}
GetOp(cp, P_CLOSEBRACE);
PutNull(cp, CF_END);
}
break;
case K_COLPALETTE:
{
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
while (1) {
char *sname, *svalue;
if (Parse(cp) == P_CLOSEBRACE) break;
if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
GetOp(cp, P_OPENBRACE);
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
sname = GetString(cp);
if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
GetOp(cp, P_COMMA);
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
svalue = GetString(cp);
svalue = GetColor(cp, svalue);
assert(DefineColor(sname, svalue) == 1);
if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
GetOp(cp, P_CLOSEBRACE);
if (Parse(cp) != P_COMMA)
break;
else
GetOp(cp, P_COMMA);
}
if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
GetOp(cp, P_CLOSEBRACE);
}
break;
case K_INCLUDE:
{
char *fn;
if (Parse(cp) != P_STRING) Fail(cp, "String expected");
fn = GetString(cp);
if (LoadFile(cp.name, fn) != 0) Fail(cp, "Include of file '%s' failed", fn);
if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
GetOp(cp, P_EOS);
}
break;
default:
Fail(cp, "Syntax error");
}
break;
case P_EOF: return 0;
default: Fail(cp, "Syntax error");
}
}
}
int LoadFile(const char *WhereName, const char *CfgName, int Level) {
int fd, rc;
char *buffer = 0;
struct stat statbuf;
CurPos cp;
char last[MAXPATH];
char Cfg[MAXPATH];
//fprintf(stderr, "Loading file %s %s\n", WhereName, CfgName);
JustDirectory(WhereName, last);
if (IsFullPath(CfgName)) {
strcpy(Cfg, CfgName);
} else {
// here we will try relative to a number of places.
// 1. User's .fte directory.
// 2. System's "local config" directory.
// 3. Initial file's directory.
// 4. Current directory.
// This means that a user's directory will always win out,
// allowing a given user to always be able to override everything,
// followed by a system standard to override anything.
// #'s 1 and 2 are unix-only.
#ifdef UNIX
// 1. User's .fte directory.
char tmp[MAXPATH];
sprintf(tmp, "~/.fte/%s", CfgName);
ExpandPath(tmp, Cfg);
//fprintf(stderr, "Looking for %s\n", Cfg);
if (!FileExists(Cfg))
{
// Okay, now try "local config".
sprintf(tmp, "%slocalconfig/%s", StartDir, CfgName);
ExpandPath(tmp, Cfg);
//fprintf(stderr, "Looking for %s\n", Cfg);
if (!FileExists(Cfg))
{
sprintf(tmp, "%sconfig/%s", StartDir, CfgName);
ExpandPath(tmp, Cfg);
//fprintf(stderr, "Looking for %s\n", Cfg);
if (!FileExists(Cfg))
{
sprintf(tmp, "./%s", CfgName);
ExpandPath(tmp, Cfg);
//fprintf(stderr, "Looking for %s\n", Cfg);
if (!FileExists(Cfg))
{
fprintf(stderr, "Cannot find '%s' in:\n"
"\t~/.fte,\n""\t%slocalconfig,\n"
"\t%sconfig, or\n"
"\t.",
CfgName, StartDir, StartDir);
}
}
}
}
#else // UNIX
SlashDir(last);
strcat(last, CfgName);
ExpandPath(last, Cfg);
#endif // UNIX
}
// puts(Cfg);
//fprintf(stderr, "Loading file %s\n", Cfg);
if ((fd = open(Cfg, O_RDONLY | O_BINARY)) == -1) {
fprintf(stderr, "Cannot open '%s', errno=%d\n", Cfg, errno);
return -1;
}
if (fstat(fd, &statbuf) != 0) {
close(fd);
fprintf(stderr, "Cannot stat '%s', errno=%d\n", Cfg, errno);
return -1;
}
buffer = (char *) malloc(statbuf.st_size);
if (buffer == 0) {
close(fd);
return -1;
}
if (read(fd, buffer, statbuf.st_size) != statbuf.st_size) {
close(fd);
free(buffer);
return -1;
}
close(fd);
cp.sz = statbuf.st_size;
cp.a = cp.c = buffer;
cp.z = cp.a + cp.sz;
cp.line = 1;
cp.name = Cfg;
rc = ParseConfigFile(cp);
// puts("End Loading file");
if (Level == 0)
PutNull(cp, CF_EOF);
if (rc == -1) {
Fail(cp, "Parse failed");
}
free(buffer);
return rc;
}