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