home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ftes46b5.zip / ftes46b5 / src / cfte.cpp < prev    next >
C/C++ Source or Header  |  1998-01-31  |  59KB  |  1,687 lines

  1. /*    cfte.cpp
  2.  *
  3.  *    Copyright (c) 1994-1997, Marko Macek
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <errno.h>
  14. #include <stdarg.h>
  15. #include <ctype.h>
  16. #include <fcntl.h>
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19.  
  20. #include "ftever.h"
  21. #include "sysdep.h"
  22. #include "feature.h"
  23. #include "c_fconfig.h"
  24. #include "s_files.h"
  25. #include "c_mode.h"
  26.  
  27. #define slen(s) ((s) ? (strlen(s) + 1) : 0)
  28.  
  29. typedef struct {
  30.     char *Name;
  31. } ExMacro;
  32.  
  33. int CMacros = 0;
  34. ExMacro *Macros = 0;
  35.  
  36. FILE *output = 0;
  37. int lntotal = 0;
  38. long offset = -1;
  39. long pos = 0;
  40. char XTarget[256] = "";
  41.  
  42.  
  43. #include "c_commands.h"
  44. #include "c_cmdtab.h"
  45.  
  46. typedef struct _CurPos {
  47.     int sz;
  48.     char *a;
  49.     char *c;
  50.     char *z;
  51.     int line;
  52.     char *name; // filename
  53. } CurPos;
  54.  
  55. void cleanup(int xerrno) {
  56.     if (output)
  57.         fclose(output);
  58.     if (XTarget[0] != 0)
  59.         unlink(XTarget);
  60.     exit (xerrno);
  61. }
  62.  
  63. void Fail(CurPos &cp, char *s, ...) {
  64.     va_list ap;
  65.     char msgbuf[1024];
  66.     
  67.     va_start(ap, s);
  68.     vsprintf(msgbuf, s, ap);
  69.     va_end(ap);
  70.     
  71.     fprintf(stderr, "%s:%d: Error: %s\n", cp.name, cp.line, msgbuf);
  72.     cleanup(1);
  73. }
  74.  
  75. int LoadFile(char *WhereName, char *CfgName, int Level);
  76. void DefineWord(char *w);
  77. void PutObj(CurPos &cp, int xtag, int xlen, void *obj);
  78.  
  79. int main(int argc, char **argv) {
  80.     char Cur[MAXPATH];
  81.     char Source[MAXPATH];
  82.     char Target[MAXPATH];
  83.     char *p = argv[1];
  84.     long null = 0;
  85.     int n = 1;
  86.     
  87.     fprintf(stderr, PROG_CFTE " " VERSION " " COPYRIGHT "\n");
  88.     if (argc < 2 || argc > 4) {
  89.         fprintf(stderr, "Usage: " PROG_CFTE " [-o<offset>] config/main.fte [fte-new.cnf]\n");
  90.         exit(1);
  91.     }
  92.  
  93.     DefineWord("OS_"
  94. #if defined(OS2)
  95.                "OS2"
  96. #elif defined(UNIX)
  97.                "UNIX"
  98. #elif defined(NT)
  99.                "NT"
  100. #elif defined(DOSP32)
  101.                "DOS32"
  102. #endif
  103.               );
  104.  
  105.     if (strncmp(p, "-o", 2) == 0) {
  106.         p += 2;
  107.         offset = atol(p);
  108.         n++;
  109.     }
  110.     if (n == 1 && argc == 4) {
  111.         fprintf(stderr, "Invalid option '%s'\n", argv[1]);
  112.         exit(1);
  113.     }
  114.     strcpy(Source, argv[n++]);
  115.     strcpy(Target, "fte-new.cnf");
  116.     if (n < argc)
  117.         strcpy(Target, argv[n++]);
  118.  
  119.     JustDirectory(Target, XTarget);
  120.     Slash(XTarget, 1);
  121.     sprintf(XTarget + strlen(XTarget), "cfte%ld.tmp", (long)getpid());
  122.     output = fopen(XTarget, "wb");
  123.     if (output == 0) {
  124.         fprintf(stderr, "Cannot create '%s', errno=%d!\n", XTarget, errno);
  125.         cleanup(1);
  126.     }
  127.     
  128.     if (fwrite(&null, sizeof(long), 1, output) != 1) {
  129.         fprintf(stderr, "Disk full!");
  130.         cleanup(1);
  131.     }
  132.     null = VERNUM;
  133.     if (fwrite(&null, sizeof(long), 1, output) != 1) {
  134.         fprintf(stderr, "Disk full!");
  135.         cleanup(1);
  136.     }
  137.     pos = 2 * sizeof(long);
  138.     
  139.     fprintf(stderr, "Compiling to '%s'\n", Target);
  140.     ExpandPath(".", Cur);
  141.     Slash(Cur, 1);
  142.  
  143.     {
  144.         CurPos cp;
  145.         char FSource[MAXPATH];
  146.  
  147.         if (ExpandPath(Source, FSource) != 0) {
  148.             fprintf(stderr, "Could not expand path %s\n", Source);
  149.             exit(1);
  150.         }
  151.         
  152.         cp.sz = 0;
  153.         cp.c = 0;
  154.         cp.a = cp.c = 0;
  155.         cp.z = cp.a + cp.sz;
  156.         cp.line = 0;
  157.         cp.name = "<cfte-start>";
  158.         
  159.         PutObj(cp, CF_STRING, slen(FSource), FSource);
  160.     }
  161.     
  162.     if (LoadFile(Cur, Source, 0) != 0) {
  163.         fprintf(stderr, "\nCompile failed\n");
  164.         cleanup(1);
  165.     }
  166.     
  167.     null = CONFIG_ID;
  168.     fseek(output, 0, SEEK_SET);
  169.     fwrite(&null, sizeof(long), 1, output);
  170.     fclose(output);
  171.  
  172.     if (unlink(Target) != 0 && errno != ENOENT) {
  173.         fprintf(stderr, "Remove of '%s' failed, result left in %s, errno=%d\n",
  174.                 Target, XTarget, errno);
  175.         exit(1);
  176.     }
  177.         
  178.     if (rename(XTarget, Target) != 0) {
  179.         fprintf(stderr, "Rename of '%s' to '%s' failed, errno=%d\n",
  180.                 XTarget, Target, errno);
  181.         exit(1);
  182.     }
  183.     
  184.     fprintf(stderr, "\nDone.\n");
  185.     return 0;
  186. }
  187.  
  188. #define MODE_BFI(x) { #x, BFI_##x }
  189. #define MODE_BFS(x) { #x, BFS_##x }
  190. #define MODE_FLG(x) { #x, FLAG_##x }
  191. #define EVENT_FLG(x) { #x, EM_##x }
  192. #define COLORIZE_FLG(x) { #x, COL_##x }
  193. #define HILIT_CLR(x) { #x, CLR_##x }
  194.  
  195. typedef struct _OrdLookup {
  196.     char *Name;
  197.     int num;
  198. } OrdLookup;
  199.  
  200. OrdLookup mode_num[] = {
  201. MODE_BFI(AutoIndent),
  202. MODE_BFI(Insert),
  203. MODE_BFI(DrawOn),
  204. MODE_BFI(HilitOn),
  205. MODE_BFI(ExpandTabs),
  206. MODE_BFI(Trim),
  207. MODE_BFI(TabSize),
  208. MODE_BFI(ShowTabs),
  209. MODE_BFI(LineChar),
  210. MODE_BFI(StripChar),
  211. MODE_BFI(AddLF),
  212. MODE_BFI(AddCR),
  213. MODE_BFI(ForceNewLine),
  214. MODE_BFI(HardMode),
  215. MODE_BFI(Undo),
  216. MODE_BFI(ReadOnly),
  217. MODE_BFI(AutoSave),
  218. MODE_BFI(KeepBackups),
  219. MODE_BFI(LoadMargin),
  220. MODE_BFI(UndoLimit),
  221. MODE_BFI(MatchCase),
  222. MODE_BFI(BackSpKillTab),
  223. MODE_BFI(DeleteKillTab),
  224. MODE_BFI(BackSpUnindents),
  225. MODE_BFI(SpaceTabs),
  226. MODE_BFI(IndentWithTabs),
  227. MODE_BFI(LeftMargin),
  228. MODE_BFI(RightMargin),
  229. MODE_BFI(SeeThruSel),
  230. MODE_BFI(WordWrap),
  231. MODE_BFI(ShowMarkers),
  232. MODE_BFI(CursorThroughTabs),
  233. MODE_BFI(SaveFolds),
  234. MODE_BFI(MultiLineHilit),
  235. MODE_BFI(AutoHilitParen),
  236. MODE_BFI(Abbreviations),
  237. MODE_BFI(BackSpKillBlock),
  238. MODE_BFI(DeleteKillBlock),
  239. MODE_BFI(PersistentBlocks),
  240. MODE_BFI(InsertKillBlock),
  241. MODE_BFI(UndoMoves),
  242. MODE_BFI(DetectLineSep),
  243. MODE_BFI(TrimOnSave),
  244. { 0, 0 },
  245. };
  246.  
  247. OrdLookup mode_string[] = {
  248. MODE_BFI(Colorizer),
  249. MODE_BFI(IndentMode),
  250. MODE_BFS(RoutineRegexp),
  251. MODE_BFS(DefFindOpt),
  252. MODE_BFS(DefFindReplaceOpt),
  253. MODE_BFS(CommentStart),
  254. MODE_BFS(CommentEnd),
  255. MODE_BFS(WordChars),
  256. MODE_BFS(FileNameRx),
  257. MODE_BFS(FirstLineRx),
  258. MODE_BFS(CompileCommand),
  259. MODE_BFI(EventMap),
  260. { 0, 0 },
  261. };
  262.  
  263. OrdLookup global_num[] = {
  264. #ifdef CONFIG_INDENT_C
  265. MODE_FLG(C_Indent),
  266. MODE_FLG(C_BraceOfs),
  267. MODE_FLG(C_CaseOfs),
  268. MODE_FLG(C_CaseDelta),
  269. MODE_FLG(C_ClassOfs),
  270. MODE_FLG(C_ClassDelta),
  271. MODE_FLG(C_ColonOfs),
  272. MODE_FLG(C_CommentOfs),
  273. MODE_FLG(C_CommentDelta),
  274. MODE_FLG(C_FirstLevelWidth),
  275. MODE_FLG(C_FirstLevelIndent),
  276. MODE_FLG(C_Continuation),
  277. MODE_FLG(C_ParenDelta),
  278. #endif
  279. #ifdef CONFIG_INDENT_REXX
  280. MODE_FLG(REXX_Indent),
  281. MODE_FLG(REXX_Do_Offset),
  282. #endif
  283. MODE_FLG(ScreenSizeX),
  284. MODE_FLG(ScreenSizeY),
  285. MODE_FLG(CursorInsertStart),
  286. MODE_FLG(CursorInsertEnd),
  287. MODE_FLG(CursorOverStart),
  288. MODE_FLG(CursorOverEnd),
  289. MODE_FLG(SysClipboard),
  290. MODE_FLG(OpenAfterClose),
  291. MODE_FLG(ShowVScroll),
  292. MODE_FLG(ShowHScroll),
  293. MODE_FLG(ScrollBarWidth),
  294. MODE_FLG(SelectPathname),
  295. MODE_FLG(ShowToolBar),
  296. MODE_FLG(ShowMenuBar),
  297. MODE_FLG(KeepHistory),
  298. MODE_FLG(LoadDesktopOnEntry),
  299. MODE_FLG(SaveDesktopOnExit),
  300. MODE_FLG(KeepMessages),
  301. MODE_FLG(ScrollBorderX),
  302. MODE_FLG(ScrollBorderY),
  303. MODE_FLG(ScrollJumpX),
  304. MODE_FLG(ScrollJumpY),
  305. MODE_FLG(GUIDialogs),
  306. MODE_FLG(PMDisableAccel),
  307. MODE_FLG(SevenBit),
  308. MODE_FLG(WeirdScroll),
  309. MODE_FLG(LoadDesktopMode),
  310. { 0, 0 },
  311. };
  312.  
  313. OrdLookup global_string[] = {
  314. MODE_FLG(DefaultModeName),
  315. MODE_FLG(CompletionFilter),
  316. MODE_FLG(PrintDevice),
  317. MODE_FLG(CompileCommand),
  318. MODE_FLG(WindowFont),
  319. MODE_FLG(HelpCommand),
  320. { 0, 0 },
  321. };
  322.  
  323. OrdLookup event_string[] = {
  324. EVENT_FLG(MainMenu),
  325. EVENT_FLG(LocalMenu),
  326. { 0, 0 },
  327. };
  328.  
  329. OrdLookup colorize_string[] = {
  330. COLORIZE_FLG(SyntaxParser),
  331. { 0, 0 },
  332. };
  333.  
  334. OrdLookup hilit_colors[] = {
  335. HILIT_CLR(Normal),
  336. HILIT_CLR(Keyword),
  337. HILIT_CLR(String),
  338. HILIT_CLR(Comment),
  339. HILIT_CLR(CPreprocessor),
  340. HILIT_CLR(Regexp),
  341. HILIT_CLR(Header),
  342. HILIT_CLR(Quotes),
  343. HILIT_CLR(Number),
  344. HILIT_CLR(HexNumber),
  345. HILIT_CLR(OctalNumber),
  346. HILIT_CLR(FloatNumber),
  347. HILIT_CLR(Function),
  348. HILIT_CLR(Command),
  349. HILIT_CLR(Tag),
  350. HILIT_CLR(Punctuation),
  351. HILIT_CLR(New),
  352. HILIT_CLR(Old),
  353. HILIT_CLR(Changed),
  354. HILIT_CLR(Control),
  355. HILIT_CLR(Separator),
  356. HILIT_CLR(Variable),
  357. HILIT_CLR(Symbol),
  358. HILIT_CLR(Directive),
  359. HILIT_CLR(Label),
  360. HILIT_CLR(Special),
  361. HILIT_CLR(QuoteDelim),
  362. HILIT_CLR(RegexpDelim),
  363. { 0, 0 },
  364. };
  365.  
  366. int Lookup(OrdLookup *where, char *what) {
  367.     int i;
  368.     
  369.     for (i = 0; where[i].Name != 0; i++) {
  370.         if (strcmp(what, where[i].Name) == 0)
  371.             return where[i].num;
  372.     }
  373. //    fprintf(stderr, "\nBad name: %s (i = %d)\n", what, i);
  374.     return -1;
  375. }
  376.  
  377. void PutObj(CurPos &cp, int xtag, int xlen, void *obj) {
  378.     unsigned char tag = (unsigned char)xtag;
  379.     unsigned short len = (unsigned short)xlen;
  380.     
  381.     if (fwrite(&tag, sizeof(unsigned char), 1, output) != 1 ||
  382.         fwrite(&len, sizeof(unsigned short), 1, output) != 1 ||
  383.         fwrite(obj, 1, len, output) != len)
  384.     {
  385.         Fail(cp, "Disk full!");
  386.     }
  387.     pos += sizeof(unsigned char) + sizeof(unsigned short) + len;
  388.     if (offset != -1 && pos >= offset) {
  389.         Fail(cp, "Error location found at %ld", pos);
  390.     }
  391. }
  392.  
  393. int LoadFile(char *WhereName, char *CfgName, int Level = 1);
  394.  
  395. #define P_EOF         0  // end of file
  396. #define P_SYNTAX      1  // unknown
  397. #define P_WORD        2  // a-zA-Z_
  398. #define P_NUMBER      3  // 0-9
  399. #define P_STRING      4  // "'`
  400. #define P_ASSIGN      5  // =
  401. #define P_EOS         6  // ;
  402. #define P_KEYSPEC     7  // []
  403. #define P_OPENBRACE   8  // {
  404. #define P_CLOSEBRACE  9  // }
  405. #define P_COLON      10  // :
  406. #define P_COMMA      11  // ,
  407. #define P_QUEST      12
  408. #define P_VARIABLE   13  // $
  409. #define P_DOT        14  // . (concat)
  410.  
  411. #define K_UNKNOWN     0
  412. #define K_MODE        1
  413. #define K_KEY         2
  414. #define K_COLOR       3
  415. #define K_KEYWORD     4
  416. #define K_OBJECT      5
  417. #define K_MENU        6
  418. #define K_ITEM        7
  419. #define K_SUBMENU     8
  420. #define K_COMPILERX   9
  421. #define K_EXTERN     10
  422. #define K_INCLUDE    11
  423. #define K_SUB        12
  424. #define K_EVENTMAP   13
  425. #define K_COLORIZE   14
  426. #define K_ABBREV     15
  427. #define K_HSTATE     16
  428. #define K_HTRANS     17
  429. #define K_HWORDS     18
  430. #define K_SUBMENUCOND 19
  431. #define K_HWTYPE     20
  432. #define K_COLPALETTE 21
  433.  
  434. typedef char Word[64];
  435.  
  436. OrdLookup CfgKW[] = {
  437. { "mode", K_MODE },
  438. { "eventmap", K_EVENTMAP },
  439. { "key", K_KEY },
  440. { "color", K_COLOR },
  441. { "color_palette", K_COLPALETTE },
  442. { "keyword", K_KEYWORD },
  443. { "object", K_OBJECT },
  444. { "menu", K_MENU },
  445. { "item", K_ITEM },
  446. { "submenu", K_SUBMENU },
  447. { "CompileRx", K_COMPILERX },
  448. { "extern", K_EXTERN },
  449. { "include", K_INCLUDE },
  450. { "sub", K_SUB },
  451. { "colorize", K_COLORIZE },
  452. { "abbrev", K_ABBREV },
  453. { "h_state", K_HSTATE },
  454. { "h_trans", K_HTRANS },
  455. { "h_words", K_HWORDS },
  456. { "h_wtype", K_HWTYPE },
  457. { "submenucond", K_SUBMENUCOND },
  458. { 0, 0 },
  459. };
  460.  
  461. OrdLookup CfgVar[] = {
  462.     { "FilePath", mvFilePath },
  463.     { "FileName", mvFileName },
  464.     { "CurDirectory", mvCurDirectory },
  465.     { "CurRow", mvCurRow, },
  466.     { "CurCol", mvCurCol },
  467.     { "Char", mvChar },
  468.     { "Word", mvWord },
  469.     { "Line", mvLine },
  470.     { 0, 0 },
  471. };
  472.  
  473. char **words = 0;
  474. int wordCount = 0;
  475.  
  476. int DefinedWord(char *w) {
  477.     if (words == 0 || wordCount == 0)
  478.         return 0;
  479.     for (int i = 0; i < wordCount; i++)
  480.         if (strcmp(w, words[i]) == 0)
  481.             return 1;
  482.     return 0;
  483. }
  484.  
  485. void DefineWord(char *w) {
  486.     if (!w || !w[0])
  487.         return ;
  488.     if (!DefinedWord(w)) {
  489.         words = (char **)realloc(words, sizeof (char *) * (wordCount + 1));
  490.         assert(words != 0);
  491.         words[wordCount] = strdup(w);
  492.         assert(words[wordCount] != 0);
  493.         wordCount++;
  494.     }
  495. }
  496.  
  497. int colorCount;
  498. struct _color {
  499.     char *colorName;
  500.     char *colorValue;
  501. } *colors;
  502.  
  503. int DefineColor(char *name, char *value) {
  504.     if (!name || !value)
  505.         return 0;
  506.     colors = (struct _color *)realloc(colors, sizeof (struct _color) * (colorCount + 1));
  507.     assert(colors != 0);
  508.     colors[colorCount].colorName = strdup(name);
  509.     colors[colorCount].colorValue = strdup(value);
  510.     assert(colors != NULL);
  511.     assert(colors[colorCount].colorName != 0);
  512.     assert(colors[colorCount].colorValue != 0);
  513.     colorCount++;
  514.     return 1;
  515. }
  516.  
  517. char *DefinedColor(char *name) {
  518.     if (colors == 0 || colorCount == 0)
  519.         return 0;
  520.     for (int i = 0; i < colorCount; i++)
  521.         if (strcmp(name, colors[i].colorName) == 0)
  522.             return colors[i].colorValue;
  523.     return 0;
  524. }
  525.  
  526. char *GetColor(CurPos &cp, char *name) {
  527.     char *c;
  528.     static char color[4];
  529.     
  530.     // add support for fore:back and remove it from fte itself
  531.     if ((c = strchr(name, ' ')) != NULL) {
  532.     } else if ((c = strchr(name, ':')) != NULL) {
  533.         char clr[4];
  534.         *c++ = 0;
  535.         clr[0] = GetColor(cp, name)[0];
  536.         clr[1] = ' ';
  537.         clr[2] = GetColor(cp, c)[2];
  538.         clr[3] = 0;
  539.  
  540.         memcpy((void *)color, (void *)clr, sizeof(color));
  541.         name = (char *)color;
  542.     } else {
  543.         char *p = DefinedColor(name);
  544.         if (!p)
  545.             Fail(cp, "Unknown symbolic color %s", name);
  546.         name = p;
  547.     }
  548.     if (!isxdigit(name[0]) &&
  549.         name[1] != ' ' &&
  550.         !isxdigit(name[2]) &&
  551.         name[3] != 0)
  552.     {
  553.         Fail(cp, "malformed color specification: %s", name);
  554.     }
  555.     return name;
  556. }
  557.  
  558. int GetWord(CurPos &cp, char *w) {
  559.     char *p = w;
  560.     int len = 0;
  561.     
  562.     while (len < int(sizeof(Word)) && cp.c < cp.z &&
  563.            ((*cp.c >= 'a' && *cp.c <= 'z') ||
  564.             (*cp.c >= 'A' && *cp.c <= 'Z') ||
  565.             (*cp.c >= '0' && *cp.c <= '9') ||
  566.             (*cp.c == '_')))
  567.     {
  568.         *p++ = *cp.c++;
  569.         len++;
  570.     }
  571.     if (len == sizeof(Word)) return -1;
  572.     *p = 0;
  573.     return 0;
  574. }
  575.  
  576.  
  577. int Parse(CurPos &cp) {
  578.     while (cp.c < cp.z) {
  579.         switch (*cp.c) {
  580. #ifndef UNIX
  581.         case '\x1A': /* ^Z :-* */ return P_EOF;
  582. #endif
  583.         case '#':
  584.             while (cp.c < cp.z && *cp.c != '\n') cp.c++;
  585.             break;
  586.         case '%':
  587.             cp.c++;
  588.             if (cp.c + 7 < cp.z && strncmp(cp.c, "define(", 7) == 0) {
  589.                 Word w;
  590.                 cp.c += 7;
  591.  
  592.                 while (cp.c < cp.z && *cp.c != ')') {
  593.                     GetWord(cp, w);
  594.                     //printf("define '%s'\n", w);
  595.                     DefineWord(w);
  596.                     if (cp.c < cp.z && *cp.c != ',' && *cp.c != ')' )
  597.                         Fail(cp, "unexpected: %c", cp.c[0]);
  598.                     if (cp.c < cp.z && *cp.c == ',')
  599.                         cp.c++;
  600.                 }
  601.                 cp.c++;
  602. /*            } else if (cp.c + 6 && strcmp(cp.c, "undef(", 6) == 0) {
  603.                 Word w;
  604.                 cp.c += 6;
  605.  
  606.                 while (cp.c < cp.z && *cp.c != ')') {
  607.                     GetWord(cp, w);
  608.                     UndefWord(w);
  609.                 }*/
  610.             } else if (cp.c + 3 < cp.z && strncmp(cp.c, "if(", 3) == 0) {
  611.                 Word w;
  612.                 int wasWord = 0;
  613.                 cp.c += 3;
  614.  
  615.                 while (cp.c < cp.z && *cp.c != ')') {
  616.                     int neg = 0;
  617.                     if (*cp.c == '!') {
  618.                         cp.c++;
  619.                         neg = 1;
  620.                     }
  621.                     GetWord(cp, w);
  622.                     if (DefinedWord(w))
  623.                         wasWord = 1;
  624.                     if (neg)
  625.                         wasWord = wasWord ? 0 : 1;
  626.                     /*if (wasWord)
  627.                         printf("yes '%s'\n", w);
  628.                     else
  629.                         printf("not '%s'\n", w);*/
  630.                         
  631.                     if (cp.c < cp.z && *cp.c != ',' && *cp.c != ')' )
  632.                         Fail(cp, "unexpected: %c", cp.c[0]);
  633.                     if (cp.c < cp.z && *cp.c == ',')
  634.                         cp.c++;
  635.                 }
  636.                 cp.c++;
  637.                 if (!wasWord) {
  638.                     int nest = 1;
  639.                     while (cp.c < cp.z) {
  640.                         if (*cp.c == '\n') {
  641.                             cp.line++;
  642.                             lntotal++;
  643.                         } else if (*cp.c == '%') {
  644.                             if (cp.c + 6 < cp.z &&
  645.                                 strncmp(cp.c, "%endif", 6) == 0)
  646.                             {
  647.                                 cp.c += 6;
  648.                                 if (--nest == 0)
  649.                                     break;
  650.                             }
  651.                             if (cp.c + 4 < cp.z &&
  652.                                 strncmp(cp.c, "%if", 4) == 0)
  653.                             {
  654.                                 cp.c += 4;
  655.                                 ++nest;
  656.                             }
  657.                         }
  658.                         cp.c++;
  659.                     }
  660.                 }
  661.             } else if (cp.c + 5 < cp.z && strncmp(cp.c, "endif", 5) == 0) {
  662.                 cp.c += 5;
  663.             }
  664.             if (cp.c < cp.z && *cp.c != '\n' && *cp.c != '\r')
  665.                 Fail(cp, "syntax error %30.30s", cp.c);
  666.             break;
  667.     case '\n':
  668.             cp.line++;
  669.             lntotal++;
  670.     case ' ': 
  671.     case '\t': 
  672.     case '\r': 
  673.         cp.c++;
  674.         break;
  675.         case '=': return P_ASSIGN;
  676.         case ';': return P_EOS;
  677.     case ',': return P_COMMA;
  678.         case ':': return P_COLON;
  679.         case '.': return P_DOT;
  680.         case '\'': 
  681.         case '"': 
  682.         case '`': 
  683.         case '/': return P_STRING;
  684.         case '[': return P_KEYSPEC;
  685.         case '{': return P_OPENBRACE;
  686.         case '}': return P_CLOSEBRACE;
  687.         case '?': return P_QUEST;
  688.         case '$': return P_VARIABLE;
  689.         case '-': case '+':
  690.         case '0': case '1': case '2': case '3': case '4':
  691.         case '5': case '6': case '7': case '8': case '9': return P_NUMBER;
  692.         default:
  693.             if ((*cp.c >= 'a' && *cp.c <= 'z') ||
  694.                 (*cp.c >= 'A' && *cp.c <= 'Z') ||
  695.                 (*cp.c == '_'))
  696.                 return P_WORD;
  697.             else
  698.                 return P_SYNTAX;
  699.         }
  700.     }
  701.     return P_EOF;
  702. }
  703.  
  704. void GetOp(CurPos &cp, int what) {
  705.     switch (what) {
  706.     case P_COMMA:
  707.     case P_OPENBRACE:
  708.     case P_CLOSEBRACE:
  709.     case P_ASSIGN:
  710.     case P_EOS:
  711.     case P_COLON:
  712.     case P_QUEST:
  713.     case P_VARIABLE:
  714.     case P_DOT:
  715.         cp.c++;
  716.         break;
  717.     }
  718. }
  719.  
  720. char *GetString(CurPos &cp) {
  721.     char c = *cp.c;
  722.     char *p = cp.c;
  723.     char *d = cp.c;
  724.     
  725.     if (c == '[') c = ']';
  726.     
  727.     cp.c++; // skip '"`
  728.     while (cp.c < cp.z) {
  729.         if (*cp.c == '\\') {
  730.             if (c == '/')
  731.                 *p++ = *cp.c;
  732.             cp.c++;
  733.         if (cp.c == cp.z) return 0;
  734.             if (c == '"') {
  735.                 switch (*cp.c) {
  736.                 case 'e': *cp.c = '\x1B'; break;
  737.                 case 't': *cp.c = '\t'; break;
  738.                 case 'r': *cp.c = '\r'; break;
  739.                 case 'n': *cp.c = '\n'; break;
  740.                 case 'b': *cp.c = '\b'; break;
  741.                 case 'v': *cp.c = '\v'; break;
  742.                 case 'a': *cp.c = '\a'; break;
  743.                 }
  744.             }
  745.     } else if (*cp.c == c) {
  746.         cp.c++;
  747.         *p = 0;
  748.         return d;
  749.     } else if (*cp.c == '\n') return 0;
  750.     if (*cp.c == '\n') cp.line++;
  751.     if (*cp.c == '\r') {
  752.         cp.c++;
  753.         if (cp.c == cp.z) return 0;
  754.     }
  755.     *p++ = *cp.c++;
  756.     }
  757.     return 0;
  758. }
  759.  
  760. int GetNumber(CurPos &cp) {
  761.     int value = 0;
  762.     int neg = 0;
  763.     
  764.     if (cp.c < cp.z && *cp.c == '-' || *cp.c == '+') {
  765.     if (*cp.c == '-') neg = 1;
  766.     cp.c++;
  767.     }
  768.     while (cp.c < cp.z && (*cp.c >= '0' && *cp.c <= '9')) {
  769.     value = value * 10 + (*cp.c - '0');
  770.     cp.c++;
  771.     }
  772.     return neg ? -value : value;
  773. }
  774.  
  775. int CmdNum(char *Cmd) {
  776.     int i;
  777.     
  778.     for (i = 0; 
  779.      i < int(sizeof(Command_Table) / sizeof(Command_Table[0]));
  780.      i++)
  781.     if (strcmp(Cmd, Command_Table[i].Name) == 0)
  782.         return Command_Table[i].CmdId;
  783.     for (i = 0; i < CMacros; i++)
  784.         if (Macros[i].Name && (strcmp(Cmd, Macros[i].Name)) == 0)
  785.             return i | CMD_EXT;
  786.     return 0; // Nop
  787. }
  788.  
  789. int NewCommand(char *Name) {
  790.     if (Name == 0)
  791.         Name = "";
  792.     Macros = (ExMacro *) realloc(Macros, sizeof(ExMacro) * (1 + CMacros));
  793.     Macros[CMacros].Name = strdup(Name);
  794.     CMacros++;
  795.     return CMacros - 1;
  796. }
  797.  
  798. int ParseCommands(CurPos &cp, char *Name) {
  799.     //if (!Name)
  800.     //    return 0;
  801.     Word cmd;
  802.     int p;
  803.     long Cmd = NewCommand(Name) | CMD_EXT;
  804.  
  805.     long cnt;
  806.     long ign = 0;
  807.     
  808.     PutObj(cp, CF_INT, sizeof(long), &Cmd);
  809.     GetOp(cp, P_OPENBRACE);
  810.     cnt = 1;
  811.     while (1) {
  812.         p = Parse(cp);
  813.         if (p == P_CLOSEBRACE) break;
  814.         if (p == P_EOF) Fail(cp, "Unexpected EOF");
  815.  
  816.         if (p == P_DOT) {
  817.             GetOp(cp, P_DOT);
  818.             PutObj(cp, CF_CONCAT, 0, 0);
  819.         } else if (p == P_NUMBER) {
  820.             long num = GetNumber(cp);
  821.             if (Parse(cp) != P_COLON) {
  822.                 PutObj(cp, CF_INT, sizeof(long), &num);
  823.             } else {
  824.                 cnt = num;
  825.                 GetOp(cp, P_COLON);
  826.             }
  827.         } else if (p == P_WORD) {
  828.             long Command;
  829.             
  830.             if (GetWord(cp, cmd) == -1) Fail(cp, "Syntax error");
  831.             Command = CmdNum(cmd);
  832.             if (Command == 0)
  833.                 Fail(cp, "Unrecognised command: %s", cmd);
  834.             PutObj(cp, CF_COMMAND, sizeof(long), &Command);
  835.             PutObj(cp, CF_INT, sizeof(long), &cnt);
  836.             PutObj(cp, CF_INT, sizeof(long), &ign);
  837.             ign = 0;
  838.             cnt = 1;
  839.         } else if (p == P_STRING) {
  840.             char *s = GetString(cp);
  841.             PutObj(cp, CF_STRING, slen(s), s);
  842.         } else if (p == P_QUEST) {
  843.             ign = 1;
  844.             GetOp(cp, P_QUEST);
  845.         } else if (p == P_VARIABLE) {
  846.             GetOp(cp, P_VARIABLE);
  847.             if (Parse(cp) != P_WORD) Fail(cp, "Syntax error (variable name expected)");
  848.             Word w;
  849.             if (GetWord(cp, w) != 0) Fail(cp, "Syntax error (bad variable name)");
  850.             long var = Lookup(CfgVar, w);
  851.             if (var == -1) Fail(cp, "Unrecognised variable");
  852.             PutObj(cp, CF_VARIABLE, sizeof(long), &var);
  853.         } else if (p == P_EOS) {
  854.             GetOp(cp, P_EOS);
  855.             cnt = 1;
  856.         } else
  857.             Fail(cp, "Syntax error");
  858.     }
  859.     GetOp(cp, P_CLOSEBRACE);
  860.     return 0;
  861. }
  862.  
  863. int ParseConfigFile(CurPos &cp) {
  864.     Word w = "";
  865.     char *s = 0;
  866.     int p = 0;
  867.     
  868.     Word ObjName = "", UpMode = "";
  869.     
  870.     while (1) {
  871.         p = Parse(cp);
  872.         
  873.         switch (p) {
  874.         case P_WORD:
  875.             if (GetWord(cp, w) != 0) Fail(cp, "Syntax error");
  876.             switch (Lookup(CfgKW, w)) {
  877.             case K_SUB:
  878.                 {
  879.                     Word Name;
  880.                     
  881.                     if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
  882.                     if (GetWord(cp, Name) != 0) Fail(cp, "Syntax error");
  883.                     PutObj(cp, CF_SUB, slen(Name), Name);
  884.                     if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  885.                     GetOp(cp, P_OPENBRACE);
  886.                     if (ParseCommands(cp, strdup(Name ? Name : "")) == -1) 
  887.                         Fail(cp, "Parse failed");
  888.                     PutObj(cp, CF_END, 0, 0);
  889.                 }
  890.                 break;
  891.             case K_MENU:
  892.                     
  893.                 {
  894.                     Word MenuName;
  895.                     //int menu = -1, item = -1;
  896.                     
  897.                     if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");;
  898.             if (GetWord(cp, MenuName) != 0) Fail(cp, "Syntax error");;
  899.                     if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  900.                     GetOp(cp, P_OPENBRACE);
  901.                     
  902.                     PutObj(cp, CF_MENU, slen(MenuName), MenuName);
  903.                     
  904.                     while (1) {
  905.                         p = Parse(cp);
  906.                         if (p == P_CLOSEBRACE) break;
  907.                         if (p == P_EOF) Fail(cp, "Unexpected EOF");
  908.                         if (p != P_WORD) Fail(cp, "Syntax error");
  909.                         
  910.                         if (GetWord(cp, w) != 0) Fail(cp, "Parse failed");
  911.                         switch (Lookup(CfgKW, w)) {
  912.                         case K_ITEM: // menu::item
  913.                             switch (Parse(cp)) {
  914.                             case P_EOS:
  915.                                 PutObj(cp, CF_ITEM, 0, 0);
  916.                                 break;
  917.                             case P_STRING:
  918.                                 s = GetString(cp);
  919.                                 PutObj(cp, CF_ITEM, slen(s), s);
  920.                                 break;
  921.                             default:
  922.                                 Fail(cp, "Syntax error");;
  923.                             }
  924.                             if (Parse(cp) == P_EOS) {
  925.                                 GetOp(cp, P_EOS);
  926.                                 break;
  927.                             }
  928.                             if (Parse(cp) != P_OPENBRACE) 
  929.                                 Fail(cp, "'{' expected");
  930.                             
  931.                             PutObj(cp, CF_MENUSUB, 0, 0);
  932.                             if (ParseCommands(cp, 0) == -1) 
  933.                                 Fail(cp, "Parse failed");
  934.                             PutObj(cp, CF_END, 0, 0);
  935.                             break;
  936.                         case K_SUBMENU: // menu::submenu
  937.                             if (Parse(cp) != P_STRING) 
  938.                                 Fail(cp, "String expected");
  939.                             s = GetString(cp);
  940.                             if (Parse(cp) != P_COMMA) 
  941.                                 Fail(cp, "',' expected");
  942.                             GetOp(cp, P_COMMA);
  943.                             if (Parse(cp) != P_WORD) 
  944.                                 Fail(cp, "Syntax error");
  945.                             if (GetWord(cp, w) == -1) 
  946.                                 Fail(cp, "Parse failed");
  947.                             
  948.                             PutObj(cp, CF_SUBMENU, slen(s), s);
  949.                             PutObj(cp, CF_STRING, slen(w), w);
  950.                             if (Parse(cp) != P_EOS) 
  951.                                 Fail(cp, "';' expected");
  952.                 GetOp(cp, P_EOS);
  953.                             break;
  954.  
  955.                         case K_SUBMENUCOND: // menu::submenu
  956.                             if (Parse(cp) != P_STRING) 
  957.                                 Fail(cp, "String expected");
  958.                             s = GetString(cp);
  959.                             if (Parse(cp) != P_COMMA) 
  960.                                 Fail(cp, "',' expected");
  961.                             GetOp(cp, P_COMMA);
  962.                             if (Parse(cp) != P_WORD) 
  963.                                 Fail(cp, "Syntax error");
  964.                             if (GetWord(cp, w) == -1) 
  965.                                 Fail(cp, "Parse failed");
  966.                             
  967.                             PutObj(cp, CF_SUBMENUCOND, slen(s), s);
  968.                             PutObj(cp, CF_STRING, slen(w), w);
  969.                             if (Parse(cp) != P_EOS) 
  970.                                 Fail(cp, "';' expected");
  971.                             GetOp(cp, P_EOS);
  972.                             break;
  973.                         default:  // menu::
  974.                             Fail(cp, "Syntax error");
  975.                         }
  976.                     }
  977.                     GetOp(cp, P_CLOSEBRACE);
  978.                     PutObj(cp, CF_END, 0, 0);
  979.                 }
  980.                 break;
  981.             case K_EVENTMAP:
  982.                 {
  983.                     if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
  984.                     if (GetWord(cp, ObjName) != 0) Fail(cp, "Parse failed");
  985.                     PutObj(cp, CF_EVENTMAP, slen(ObjName), ObjName);
  986.  
  987.                     UpMode[0] = 0;
  988.             if (Parse(cp) == P_COLON) {
  989.             GetOp(cp, P_COLON);
  990.             if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
  991.                         if (GetWord(cp, UpMode) != 0) Fail(cp, "Parse failed");
  992.             }
  993.                     PutObj(cp, CF_PARENT, slen(UpMode), UpMode);
  994.                     if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  995.                     GetOp(cp, P_OPENBRACE);
  996.                     
  997.                     while (1) {
  998.                         p = Parse(cp);
  999.                         if (p == P_CLOSEBRACE) break;
  1000.                         if (p == P_EOF) Fail(cp, "Unexpected EOF");
  1001.                         if (p != P_WORD) Fail(cp, "Syntax error");
  1002.                         
  1003.                         if (GetWord(cp, w) != 0) Fail(cp, "Parse failed");
  1004.                         switch (Lookup(CfgKW, w)) {
  1005.             case K_KEY: // mode::key
  1006.                 if (Parse(cp) != P_KEYSPEC) Fail(cp, "'[' expected");
  1007.                             s = GetString(cp);
  1008.                             PutObj(cp, CF_KEY, slen(s), s);
  1009.                             if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1010.                             PutObj(cp, CF_KEYSUB, 0, 0);
  1011.                             if (ParseCommands(cp, 0) == -1) Fail(cp, "Parse failed");
  1012.                             PutObj(cp, CF_END, 0, 0);
  1013.                             break;
  1014.                         
  1015.                         case K_ABBREV:
  1016.                             if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1017.                             s = GetString(cp);
  1018.                             PutObj(cp, CF_ABBREV, slen(s), s);
  1019.                             switch (Parse(cp)) {
  1020.                             case P_OPENBRACE:
  1021.                                 PutObj(cp, CF_KEYSUB, 0, 0);
  1022.                                 if (ParseCommands(cp, 0) == -1) Fail(cp, "Parse failed");
  1023.                                 PutObj(cp, CF_END, 0, 0);
  1024.                                 break;
  1025.                             case P_STRING:
  1026.                                 s = GetString(cp);
  1027.                                 PutObj(cp, CF_STRING, slen(s), s);
  1028.                                 if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
  1029.                                 GetOp(cp, P_EOS);
  1030.                                 break;
  1031.                             default:
  1032.                                 Fail(cp, "Syntax error");
  1033.                             }
  1034.                             break;
  1035.  
  1036.             default:  // mode::
  1037.                 if (Parse(cp) != P_ASSIGN) Fail(cp, "'=' expected");
  1038.                 GetOp(cp, P_ASSIGN);
  1039.                 
  1040.                 switch (Parse(cp)) {
  1041.                                 /*                case P_NUMBER:
  1042.                                  {
  1043.                                  long var;
  1044.                                  long num;
  1045.                                  
  1046.                                  num = GetNumber(cp);
  1047.                                  var = LookupEventNumber(w);
  1048.                                  if (var == -1) return -1;
  1049.                                  PutObj(cp, CF_SETVAR, sizeof(long), &var);
  1050.                                  PutObj(cp, CF_INT, sizeof(long), &num);
  1051.                                  }
  1052.                                  break;*/
  1053.                             case P_STRING:
  1054.                 {
  1055.                                     long var;
  1056.                                     
  1057.                     s = GetString(cp);
  1058.                                     if (s == 0) Fail(cp, "String expected");
  1059.                                     var = Lookup(event_string, w);
  1060.                                     if (var == -1) Fail(cp, "Lookup of '%s' failed", w);
  1061.                                     PutObj(cp, CF_SETVAR, sizeof(long), &var);
  1062.                                     PutObj(cp, CF_STRING, slen(s), s);
  1063.                 }
  1064.                 break;
  1065.                 default:
  1066.                 return -1;
  1067.                 }
  1068.                 if (Parse(cp) != P_EOS) return -1;
  1069.                 GetOp(cp, P_EOS);
  1070.                             break;
  1071.                         }
  1072.                     }
  1073.                     GetOp(cp, P_CLOSEBRACE);
  1074.                     PutObj(cp, CF_END, 0, 0);
  1075.                 }
  1076.                 break;
  1077.                 
  1078.             case K_COLORIZE:
  1079.                 {
  1080.                     long LastState = -1;
  1081.                     
  1082.                     if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
  1083.                     if (GetWord(cp, ObjName) != 0) Fail(cp, "Parse failed");
  1084.                     PutObj(cp, CF_COLORIZE, slen(ObjName), ObjName);
  1085.  
  1086.                     UpMode[0] = 0;
  1087.             if (Parse(cp) == P_COLON) {
  1088.             GetOp(cp, P_COLON);
  1089.             if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
  1090.                         if (GetWord(cp, UpMode) != 0) Fail(cp, "Parse failed");
  1091.             }
  1092.                     PutObj(cp, CF_PARENT, slen(UpMode), UpMode);
  1093.                     if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1094.                     GetOp(cp, P_OPENBRACE);
  1095.                     
  1096.                     while (1) {
  1097.                         p = Parse(cp);
  1098.                         if (p == P_CLOSEBRACE) break;
  1099.                         if (p == P_EOF) Fail(cp, "Unexpected EOF");
  1100.                         if (p != P_WORD) Fail(cp, "Syntax error");
  1101.                         
  1102.                         if (GetWord(cp, w) != 0) Fail(cp, "Parse failed");
  1103.                         switch (Lookup(CfgKW, w)) {
  1104.                         case K_COLOR: // mode::color
  1105.                             if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1106.                 GetOp(cp, P_OPENBRACE);
  1107.                             PutObj(cp, CF_COLOR, 0, 0);
  1108.                                 
  1109.                 while (1) {
  1110.                                 char *sname, *svalue;
  1111.                                 long cidx;
  1112.                                 
  1113.                 if (Parse(cp) == P_CLOSEBRACE) break;
  1114.                                 if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1115.                 GetOp(cp, P_OPENBRACE);
  1116.                 if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1117.                                 sname = GetString(cp);
  1118.                                 if ((cidx = Lookup(hilit_colors, sname)) == -1)
  1119.                                     Fail(cp, "Lookup of '%s' failed", sname);
  1120.                                 PutObj(cp, CF_INT, sizeof(long), &cidx);
  1121.                                 if (Parse(cp) != P_COMMA) 
  1122.                                     Fail(cp, "',' expected");
  1123.                 GetOp(cp, P_COMMA);
  1124.                 if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1125.                                 svalue = GetString(cp);
  1126.                                 svalue = GetColor(cp, svalue);
  1127.                                 PutObj(cp, CF_STRING, slen(svalue), svalue);
  1128.                                 if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
  1129.                 GetOp(cp, P_CLOSEBRACE);
  1130.                 if (Parse(cp) != P_COMMA)
  1131.                     break;
  1132.                 else
  1133.                     GetOp(cp, P_COMMA);
  1134.                 }
  1135.                             if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
  1136.                 GetOp(cp, P_CLOSEBRACE);
  1137.                 if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
  1138.                             GetOp(cp, P_EOS);
  1139.                             PutObj(cp, CF_END, 0, 0);
  1140.                 break;
  1141.                           
  1142.                         case K_KEYWORD: // mode::keyword
  1143.                 {
  1144.                 char *colorstr, *kname;
  1145.                 //int color;
  1146.                 
  1147.                 if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1148.                                 colorstr = GetString(cp);
  1149.                                 colorstr = GetColor(cp, colorstr);
  1150.                                 if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1151.                                 GetOp(cp, P_OPENBRACE);
  1152.                                 
  1153.                                 PutObj(cp, CF_KEYWORD, slen(colorstr), colorstr);
  1154.  
  1155.                 while (1) {
  1156.                     if (Parse(cp) == P_CLOSEBRACE) break;
  1157.                     if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1158.                                     kname = GetString(cp);
  1159.                                     PutObj(cp, CF_STRING, slen(kname), kname);
  1160.                     
  1161.                     if (Parse(cp) != P_COMMA)
  1162.                     break;
  1163.                     else
  1164.                     GetOp(cp, P_COMMA);
  1165.                                 }
  1166.                 }
  1167.                             if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
  1168.                             GetOp(cp, P_CLOSEBRACE);
  1169.                 if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
  1170.                             GetOp(cp, P_EOS);
  1171.                             PutObj(cp, CF_END, 0, 0);
  1172.                             break;
  1173.  
  1174.                         case K_HSTATE:
  1175.                             {
  1176.                                 long stateno;
  1177.                                 char *cname;
  1178.                                 long cidx;
  1179.  
  1180.                                 if (Parse(cp) != P_NUMBER) Fail(cp, "state index expected");
  1181.                                 stateno = GetNumber(cp);
  1182.                                 if (stateno != LastState + 1) Fail(cp, "invalid state index");
  1183.  
  1184.                                 if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1185.                                 GetOp(cp, P_OPENBRACE);
  1186.                                 PutObj(cp, CF_HSTATE, sizeof(long), &stateno);
  1187.  
  1188.                                 if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1189.                                 cname = GetString(cp);
  1190.                                 if ((cidx = Lookup(hilit_colors, cname)) == -1)
  1191.                                     Fail(cp, "Lookup of '%s' failed", cname);
  1192.                                 PutObj(cp, CF_INT, sizeof(long), &cidx);
  1193.                                 if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
  1194.                                 GetOp(cp, P_CLOSEBRACE);
  1195.                                 LastState = stateno;
  1196.                             }
  1197.                             break;
  1198.  
  1199.                         case K_HTRANS:
  1200.                             {
  1201.                                 long next_state;
  1202.                                 char *opts, *match;
  1203.                                 long match_opts;
  1204.                                 char *cname;
  1205.                                 long cidx;
  1206.                                 
  1207.                                 if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1208.                                 GetOp(cp, P_OPENBRACE);
  1209.  
  1210.                                 if (Parse(cp) != P_NUMBER) Fail(cp, "next_state index expected");
  1211.                                 next_state = GetNumber(cp);
  1212.                                 if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
  1213.                                 GetOp(cp, P_COMMA);
  1214.                                 if (Parse(cp) != P_STRING) Fail(cp, "match options expected");
  1215.                                 opts = GetString(cp);
  1216.                                 if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
  1217.                                 GetOp(cp, P_COMMA);
  1218.                                 if (Parse(cp) != P_STRING) Fail(cp, "match string expected");
  1219.                                 match = GetString(cp);
  1220.                                 PutObj(cp, CF_HTRANS, sizeof(long), &next_state);
  1221.                                 match_opts = 0;
  1222.                                 if (strchr(opts, '^')) match_opts |= MATCH_MUST_BOL;
  1223.                                 if (strchr(opts, '$')) match_opts |= MATCH_MUST_EOL;
  1224.                                 //if (strchr(opts, 'b')) match_opts |= MATCH_MUST_BOLW;
  1225.                                 //if (strchr(opts, 'e')) match_opts |= MATCH_MUST_EOLW;
  1226.                                 if (strchr(opts, 'i')) match_opts |= MATCH_NO_CASE;
  1227.                                 if (strchr(opts, 's')) match_opts |= MATCH_SET;
  1228.                                 if (strchr(opts, 'S')) match_opts |= MATCH_NOTSET;
  1229.                                 if (strchr(opts, '-')) match_opts |= MATCH_NOGRAB;
  1230.                                 if (strchr(opts, '<')) match_opts |= MATCH_TAGASNEXT;
  1231.                                 if (strchr(opts, '>')) match_opts &= ~MATCH_TAGASNEXT;
  1232.                                 //if (strchr(opts, '!')) match_opts |= MATCH_NEGATE;
  1233.                                 if (strchr(opts, 'q')) match_opts |= MATCH_QUOTECH;
  1234.                                 if (strchr(opts, 'Q')) match_opts |= MATCH_QUOTEEOL;
  1235.  
  1236.                                 if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
  1237.                                 GetOp(cp, P_COMMA);
  1238.                                 if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1239.                                 cname = GetString(cp);
  1240.                                 if ((cidx = Lookup(hilit_colors, cname)) == -1)
  1241.                                     Fail(cp, "Lookup of '%s' failed", cname);
  1242.  
  1243.                                 PutObj(cp, CF_INT, sizeof(long), &match_opts);
  1244.                                 PutObj(cp, CF_INT, sizeof(long), &cidx);
  1245.                                 PutObj(cp, CF_STRING, slen(match), match);
  1246.                                 
  1247.                                 if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
  1248.                                 GetOp(cp, P_CLOSEBRACE);
  1249.                             }
  1250.                             break;
  1251.  
  1252.                         case K_HWTYPE:
  1253.                             if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1254.                             GetOp(cp, P_OPENBRACE);
  1255.                             
  1256.                             {
  1257.                                 long options = 0;
  1258.                                 long nextKwdMatchedState;
  1259.                                 long nextKwdNotMatchedState;
  1260.                                 long nextKwdNoCharState;
  1261.                                 char *opts;
  1262.                                 char *wordChars;
  1263.  
  1264.  
  1265.                                 if (Parse(cp) != P_NUMBER) Fail(cp, "next_state index expected");
  1266.                                 nextKwdMatchedState = GetNumber(cp);
  1267.                                 
  1268.                                 if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
  1269.                                 GetOp(cp, P_COMMA);
  1270.  
  1271.                                 if (Parse(cp) != P_NUMBER) Fail(cp, "next_state index expected");
  1272.                                 nextKwdNotMatchedState = GetNumber(cp);
  1273.                                 
  1274.                                 if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
  1275.                                 GetOp(cp, P_COMMA);
  1276.  
  1277.                                 if (Parse(cp) != P_NUMBER) Fail(cp, "next_state index expected");
  1278.                                 nextKwdNoCharState = GetNumber(cp);
  1279.                                 
  1280.                                 if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
  1281.                                 GetOp(cp, P_COMMA);
  1282.                                 
  1283.                                 if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1284.                                 opts = GetString(cp);
  1285.                                 if (strchr(opts, 'i')) options |= STATE_NOCASE;
  1286.                                 if (strchr(opts, '<')) options |= STATE_TAGASNEXT;
  1287.                                 if (strchr(opts, '>')) options &= ~STATE_TAGASNEXT;
  1288.                                 if (strchr(opts, '-')) options |= STATE_NOGRAB;
  1289.  
  1290.                                 if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
  1291.                                 GetOp(cp, P_COMMA);
  1292.                                 
  1293.                                 if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1294.                                 wordChars = GetString(cp);
  1295.  
  1296.                                 PutObj(cp, CF_HWTYPE, 0, 0);
  1297.                                 PutObj(cp, CF_INT, sizeof(long), &nextKwdMatchedState);
  1298.                                 PutObj(cp, CF_INT, sizeof(long), &nextKwdNotMatchedState);
  1299.                                 PutObj(cp, CF_INT, sizeof(long), &nextKwdNoCharState);
  1300.                                 PutObj(cp, CF_INT, sizeof(long), &options);
  1301.                                 PutObj(cp, CF_STRING, slen(wordChars), wordChars);
  1302.                             }
  1303.                             if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
  1304.                             GetOp(cp, P_CLOSEBRACE);
  1305.                             break;
  1306.                             
  1307.                         case K_HWORDS:
  1308.                             {
  1309.                                 char *colorstr, *kname;
  1310.                                 //int color;
  1311.  
  1312.                                 if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1313.                                 colorstr = GetString(cp);
  1314.                                 colorstr = GetColor(cp, colorstr);
  1315.  
  1316.                                 if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1317.                                 GetOp(cp, P_OPENBRACE);
  1318.                                 
  1319.                                 PutObj(cp, CF_HWORDS, slen(colorstr), colorstr);
  1320.                                 
  1321.                                 while (1) {
  1322.                                     if (Parse(cp) == P_CLOSEBRACE) break;
  1323.                                     if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1324.                                     kname = GetString(cp);
  1325.                                     PutObj(cp, CF_STRING, slen(kname), kname);
  1326.                                     
  1327.                                     if (Parse(cp) != P_COMMA)
  1328.                                         break;
  1329.                                     else
  1330.                                         GetOp(cp, P_COMMA);
  1331.                                 }
  1332.                             }
  1333.                             if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
  1334.                             GetOp(cp, P_CLOSEBRACE);
  1335.                             
  1336.                             PutObj(cp, CF_END, 0, 0);
  1337.                             break;
  1338.  
  1339.                         default:
  1340.                             if (Parse(cp) != P_ASSIGN) Fail(cp, "'=' expected");
  1341.                             GetOp(cp, P_ASSIGN);
  1342.                 switch (Parse(cp)) {
  1343.                                 /*                case P_NUMBER:
  1344.                                  {
  1345.                                  long var;
  1346.                                  long num;
  1347.                                  
  1348.                                  num = GetNumber(cp);
  1349.                                  var = LookupColorizeNumber(w);
  1350.                                  if (var == -1) return -1;
  1351.                                  PutObj(cp, CF_SETVAR, sizeof(long), &var);
  1352.                                  PutObj(cp, CF_INT, sizeof(long), &num);
  1353.                                  }
  1354.                                  break;*/
  1355.                             case P_STRING:
  1356.                 {
  1357.                                     long var;
  1358.                                     
  1359.                     s = GetString(cp);
  1360.                                     if (s == 0) Fail(cp, "Parse failed");
  1361.                                     var = Lookup(colorize_string, w);
  1362.                                     if (var == -1) 
  1363.                                         Fail(cp, "Lookup of '%s' failed", w);
  1364.                                     PutObj(cp, CF_SETVAR, sizeof(long), &var);
  1365.                                     PutObj(cp, CF_STRING, slen(s), s);
  1366.                 }
  1367.                 break;
  1368.                 default:
  1369.                 return -1;
  1370.                 }
  1371.                 if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
  1372.                 GetOp(cp, P_EOS);
  1373.                             break;
  1374.                         }
  1375.                     }
  1376.                     GetOp(cp, P_CLOSEBRACE);
  1377.                     PutObj(cp, CF_END, 0, 0);
  1378.                 }
  1379.                 break;
  1380.                 
  1381.         case K_MODE: // mode::
  1382.                 {
  1383.                     if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
  1384.                     if (GetWord(cp, ObjName) != 0) Fail(cp, "Parse failed");
  1385.                     PutObj(cp, CF_MODE, slen(ObjName), ObjName);
  1386.  
  1387.                     UpMode[0] = 0;
  1388.             if (Parse(cp) == P_COLON) {
  1389.             GetOp(cp, P_COLON);
  1390.             if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
  1391.                         if (GetWord(cp, UpMode) != 0) Fail(cp, "Parse failed");
  1392.             }
  1393.                     PutObj(cp, CF_PARENT, slen(UpMode), UpMode);
  1394.                     if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1395.                     GetOp(cp, P_OPENBRACE);
  1396.                     
  1397.                     while (1) {
  1398.                         p = Parse(cp);
  1399.                         if (p == P_CLOSEBRACE) break;
  1400.                         if (p == P_EOF) Fail(cp, "Unexpected EOF");
  1401.                         if (p != P_WORD) Fail(cp, "Syntax error");
  1402.                         
  1403.                         if (GetWord(cp, w) != 0) Fail(cp, "Parse failed");
  1404.                         //switch (Lookup(CfgKW, w)) {
  1405.             //default:  // mode::
  1406.                 if (Parse(cp) != P_ASSIGN) Fail(cp, "'=' expected");
  1407.                 GetOp(cp, P_ASSIGN);
  1408.                 switch (Parse(cp)) {
  1409.                 case P_NUMBER:
  1410.                                 {
  1411.                                     long var;
  1412.                     long num;
  1413.                     
  1414.                                     num = GetNumber(cp);
  1415.                                     var = Lookup(mode_num, w);
  1416.                                     if (var == -1)
  1417.                                         Fail(cp, "Lookup of '%s' failed", w);
  1418.                                     PutObj(cp, CF_SETVAR, sizeof(long), &var);
  1419.                                     PutObj(cp, CF_INT, sizeof(long), &num);
  1420.                 }
  1421.                 break;
  1422.                 case P_STRING:
  1423.                 {
  1424.                                     long var;
  1425.                                     
  1426.                     s = GetString(cp);
  1427.                                     if (s == 0) Fail(cp, "Parse failed");
  1428.                                     var = Lookup(mode_string, w);
  1429.                                     if (var == -1)
  1430.                                         Fail(cp, "Lookup of '%s' filed", w);
  1431.                                     PutObj(cp, CF_SETVAR, sizeof(long), &var);
  1432.                                     PutObj(cp, CF_STRING, slen(s), s);
  1433.                 }
  1434.                 break;
  1435.                 default:
  1436.                 return -1;
  1437.                 }
  1438.                             if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
  1439.                 GetOp(cp, P_EOS);
  1440.                         //    break;
  1441.                         //}
  1442.                     }
  1443.                     GetOp(cp, P_CLOSEBRACE);
  1444.                     PutObj(cp, CF_END, 0, 0);
  1445.                 }
  1446.                 break;
  1447.             case K_OBJECT:
  1448.         {
  1449.             if (Parse(cp) != P_WORD) Fail(cp, "Syntax error");
  1450.             if (GetWord(cp, ObjName) != 0) Fail(cp, "Parse failed");
  1451.                     if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1452.                     GetOp(cp, P_OPENBRACE);
  1453.                     
  1454.                     PutObj(cp, CF_OBJECT, slen(ObjName), ObjName);
  1455.                     
  1456.                     while (1) {
  1457.                         p = Parse(cp);
  1458.                         if (p == P_CLOSEBRACE) break;
  1459.                         if (p == P_EOF) Fail(cp, "Unexpected EOF");
  1460.                         if (p != P_WORD) Fail(cp, "Syntax error");
  1461.                         
  1462.                         if (GetWord(cp, w) != 0) Fail(cp, "Parse failed");
  1463.                         switch (Lookup(CfgKW, w)) {
  1464.                         case K_COLOR: // mode::color
  1465.                             if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1466.                 GetOp(cp, P_OPENBRACE);
  1467.                             PutObj(cp, CF_COLOR, 0, 0);
  1468.                                 
  1469.                 while (1) {
  1470.                 char *sname, *svalue;
  1471.                                 
  1472.                 if (Parse(cp) == P_CLOSEBRACE) break;
  1473.                                 if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1474.                 GetOp(cp, P_OPENBRACE);
  1475.                 if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1476.                                 sname = GetString(cp);
  1477.                                 PutObj(cp, CF_STRING, slen(sname), sname);
  1478.                 if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
  1479.                 GetOp(cp, P_COMMA);
  1480.                 if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1481.                                 svalue = GetString(cp);
  1482.                                 svalue = GetColor(cp, svalue);
  1483.                                 PutObj(cp, CF_STRING, slen(svalue), svalue);
  1484.                                 if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
  1485.                 GetOp(cp, P_CLOSEBRACE);
  1486.                 if (Parse(cp) != P_COMMA)
  1487.                     break;
  1488.                 else
  1489.                     GetOp(cp, P_COMMA);
  1490.                 }
  1491.                             if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
  1492.                 GetOp(cp, P_CLOSEBRACE);
  1493.                             if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
  1494.                             GetOp(cp, P_EOS);
  1495.                             PutObj(cp, CF_END, 0, 0);
  1496.                 break;
  1497.                           
  1498.                         case K_COMPILERX:
  1499.                             {
  1500.                                 long file, line, msg;
  1501.                                 char *regexp;
  1502.                                 
  1503.                                 if (Parse(cp) != P_ASSIGN) Fail(cp, "'=' expected");
  1504.                                 GetOp(cp, P_ASSIGN);
  1505.                                 if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1506.                                 GetOp(cp, P_OPENBRACE);
  1507.                                 if (Parse(cp) != P_NUMBER) Fail(cp, "Number expected");
  1508.                                 file = GetNumber(cp);
  1509.                                 if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
  1510.                                 GetOp(cp, P_COMMA);
  1511.                                 if (Parse(cp) != P_NUMBER) Fail(cp, "Number expected");
  1512.                                 line = GetNumber(cp);
  1513.                                 if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
  1514.                                 GetOp(cp, P_COMMA);
  1515.                                 if (Parse(cp) != P_NUMBER) Fail(cp, "Number expected");
  1516.                                 msg = GetNumber(cp);
  1517.                                 if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
  1518.                                 GetOp(cp, P_COMMA);
  1519.                                 if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1520.                 regexp = GetString(cp);
  1521.                                 if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
  1522.                                 GetOp(cp, P_CLOSEBRACE);
  1523.                                 PutObj(cp, CF_COMPRX, 0, 0);
  1524.                                 PutObj(cp, CF_INT, sizeof(long), &file);
  1525.                                 PutObj(cp, CF_INT, sizeof(long), &line);
  1526.                                 PutObj(cp, CF_INT, sizeof(long), &msg);
  1527.                                 PutObj(cp, CF_REGEXP, slen(regexp), regexp);
  1528.                                 if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
  1529.                                 GetOp(cp, P_EOS);
  1530.                             }
  1531.                             break;
  1532.                           default:  // mode::
  1533.                             if (Parse(cp) != P_ASSIGN) Fail(cp, "'=' expected");
  1534.                 GetOp(cp, P_ASSIGN);
  1535.                 
  1536.                 switch (Parse(cp)) {
  1537.                 case P_NUMBER:
  1538.                                 {
  1539.                                     long var;
  1540.                     long num;
  1541.                     
  1542.                                     num = GetNumber(cp);
  1543.                                     var = Lookup(global_num, w);
  1544.                                     if (var == -1) 
  1545.                                         Fail(cp, "Lookup of '%s' failed", w);
  1546.                                     PutObj(cp, CF_SETVAR, sizeof(long), &var);
  1547.                                     PutObj(cp, CF_INT, sizeof(long), &num);
  1548.                 }
  1549.                 break;
  1550.                 case P_STRING:
  1551.                                 {
  1552.                                     long var;
  1553.                                     
  1554.                     s = GetString(cp);
  1555.                                     if (s == 0) Fail(cp, "Parse failed");
  1556.                                     var = Lookup(global_string, w);
  1557.                                     if (var == -1) Fail(cp, "Lookup of '%s' failed");
  1558.                                     PutObj(cp, CF_SETVAR, sizeof(long), &var);
  1559.                                     PutObj(cp, CF_STRING, slen(s), s);
  1560.                 }
  1561.                 break;
  1562.                 default:
  1563.                 Fail(cp, "Syntax error");
  1564.                 }
  1565.                 if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
  1566.                 GetOp(cp, P_EOS);
  1567.                             break;
  1568.                         }
  1569.                     }
  1570.                     GetOp(cp, P_CLOSEBRACE);
  1571.                     PutObj(cp, CF_END, 0, 0);
  1572.                 }
  1573.                 break;
  1574.  
  1575.             case K_COLPALETTE:
  1576.                 {
  1577.                     if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1578.                     GetOp(cp, P_OPENBRACE);
  1579.                     
  1580.                     while (1) {
  1581.                         char *sname, *svalue;
  1582.                         
  1583.                         if (Parse(cp) == P_CLOSEBRACE) break;
  1584.                         if (Parse(cp) != P_OPENBRACE) Fail(cp, "'{' expected");
  1585.                         GetOp(cp, P_OPENBRACE);
  1586.                         if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1587.                         sname = GetString(cp);
  1588.                         if (Parse(cp) != P_COMMA) Fail(cp, "',' expected");
  1589.                         GetOp(cp, P_COMMA);
  1590.                         if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1591.                         svalue = GetString(cp);
  1592.                         svalue = GetColor(cp, svalue);
  1593.                         assert(DefineColor(sname, svalue) == 1);
  1594.                         if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
  1595.                         GetOp(cp, P_CLOSEBRACE);
  1596.                         if (Parse(cp) != P_COMMA)
  1597.                             break;
  1598.                         else
  1599.                             GetOp(cp, P_COMMA);
  1600.                     }
  1601.                     if (Parse(cp) != P_CLOSEBRACE) Fail(cp, "'}' expected");
  1602.                     GetOp(cp, P_CLOSEBRACE);
  1603.                     break;
  1604.                 }
  1605.                 break;
  1606.             case K_INCLUDE:
  1607.                 {
  1608.                     char *fn;
  1609.  
  1610.                     if (Parse(cp) != P_STRING) Fail(cp, "String expected");
  1611.                     fn = GetString(cp);
  1612.  
  1613.                     if (LoadFile(cp.name, fn) != 0) Fail(cp, "Include of file '%s' failed", fn);
  1614.                     if (Parse(cp) != P_EOS) Fail(cp, "';' expected");
  1615.                     GetOp(cp, P_EOS);
  1616.                 }
  1617.                 break;
  1618.         default: 
  1619.         Fail(cp, "Syntax error");
  1620.             }
  1621.             break;
  1622.         case P_EOF: return 0;
  1623.         default:    Fail(cp, "Syntax error");
  1624.         }
  1625.     }
  1626. }
  1627.     
  1628. int LoadFile(char *WhereName, char *CfgName, int Level) {
  1629.     int fd, rc;
  1630.     char *buffer = 0;
  1631.     struct stat statbuf;
  1632.     CurPos cp;
  1633.     char last[256];
  1634.     char Cfg[256];
  1635.     
  1636.     //fprintf(stderr, "Loading file %s %s\n", WhereName, CfgName);
  1637.     
  1638.     JustDirectory(WhereName, last);
  1639.     
  1640.     if (IsFullPath(CfgName)) {
  1641.         strcpy(Cfg, CfgName);
  1642.     } else {
  1643.         SlashDir(last);
  1644.         strcat(last, CfgName);
  1645.         ExpandPath(last, Cfg);
  1646.     }
  1647.     // puts(Cfg);
  1648.     
  1649.     //fprintf(stderr, "Loading file %s\n", Cfg);
  1650.     if ((fd = open(Cfg, O_RDONLY | O_BINARY)) == -1) {
  1651.         fprintf(stderr, "Cannot open '%s', errno=%d\n", Cfg, errno);
  1652.         return -1;
  1653.     }
  1654.     if (fstat(fd, &statbuf) != 0) {
  1655.         close(fd);
  1656.         fprintf(stderr, "Cannot stat '%s', errno=%d\n", Cfg, errno);
  1657.         return -1;
  1658.     }
  1659.     buffer = (char *) malloc(statbuf.st_size);
  1660.     if (buffer == 0) {
  1661.         close(fd);
  1662.         return -1;
  1663.     }
  1664.     if (read(fd, buffer, statbuf.st_size) != statbuf.st_size) {
  1665.         close(fd);
  1666.         return -1;
  1667.     }
  1668.     close(fd);
  1669.     
  1670.     cp.sz = statbuf.st_size;
  1671.     cp.a = cp.c = buffer;
  1672.     cp.z = cp.a + cp.sz;
  1673.     cp.line = 1;
  1674.     cp.name = Cfg;
  1675.     
  1676.     rc = ParseConfigFile(cp);
  1677.     // puts("End Loading file");
  1678.     if (Level == 0) 
  1679.         PutObj(cp, CF_EOF, 0, 0);
  1680.  
  1681.     if (rc == -1) {
  1682.         Fail(cp, "Parse failed");
  1683.     }
  1684.     free(buffer);
  1685.     return rc;
  1686. }
  1687.