3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
8 * See LICENSING which should be included
9 * along with this file for more details
18 #include <sys/types.h>
28 ////////////////////////////////////////////////////////////////////////////////
29 struct InputFileSaved
{
42 InputFileSaved (TextInput
*aifile
) : ifile(aifile
), svbuf(nullptr) {
44 memcpy(mCharBuf
, aifile
->mCharBuf
, sizeof(mCharBuf
));
45 mCharBufPos
= aifile
->mCharBufPos
;
46 mCurrentLine
= aifile
->mCurrentLine
;
47 mTokenLine
= aifile
->mTokenLine
;
48 mRealPos
= aifile
->realGetPos();
55 memcpy(ifile
->mCharBuf
, mCharBuf
, sizeof(ifile
->mCharBuf
));
56 ifile
->mCharBufPos
= mCharBufPos
;
57 ifile
->mCurrentLine
= mCurrentLine
;
58 ifile
->mTokenLine
= mTokenLine
;
59 ifile
->realSetPos(mRealPos
);
65 ////////////////////////////////////////////////////////////////////////////////
66 TextInput::TextInput (const valuemap
*aValueMap
) {
71 TextInput::~TextInput () {
72 //fprintf(stderr, "TI:~this();\n");
74 //fprintf(stderr, "TI:~this(); -- exit\n");
78 void TextInput::setup (const valuemap
*aValueMap
) {
81 lastWordWasString
= false;
86 mCollectingNumStr
= false;
90 void TextInput::Close () {
91 //fprintf(stderr, "TI:Close();\n");
93 while (!mIfStack
.empty()) mIfStack
.pop();
98 mCollectingNumStr
= false;
99 //fprintf(stderr, "TI:Close(); -- exit\n");
103 int TextInput::GetChar () {
104 if (mCharBufPos
> 0) {
105 return mCharBuf
[--mCharBufPos
];
107 if (lastWasNL
) { ++mCurrentLine
; lastWasNL
= false; }
108 int ch
= realGetChar();
109 if (ch
== 0) ch
= ' ';
110 lastWasNL
= (ch
== '\n');
111 return (ch
< 0 ? EOF
: ch
);
116 void TextInput::UngetChar (int ch
) {
118 if (mCharBufPos
> MaxUngetChars
) die("too many unread chars");
119 mCharBuf
[mCharBufPos
++] = ch
;
124 truth
TextInput::Eof () {
125 if (mCharBufPos
> 0) return false;
130 void TextInput::skipBlanks () {
133 if (ch
== EOF
) return;
136 if (Eof()) { UngetChar(ch
); return; }
138 // multiline comment? (possibly nested)
140 int prevch
= ' ', level
= 1;
144 if (prevch
== '*' && ch
== '/') {
145 if (--level
== 0) break;
147 } else if (prevch
== '/' && ch
== '*') {
158 while (!Eof()) { ch
= GetChar(); if (ch
== '\n') break; }
165 if (ch
>= 0 && ch
<= ' ') continue;
173 #define StackDepth (256)
174 int TextInput::countArrayItems (char echar
) {
175 auto savedPos
= InputFileSaved(this);
176 char stack
[StackDepth
]; // end chars
181 if (ch
== EOF
) return -1; // oops
182 if (ch
== ',' || ch
== ';') return -1;
183 //fprintf(stderr, "COUNT: ch='%c'\n", ch);
184 if (ch
== echar
) return 0;
190 if (ch
== EOF
) return -1; // oops
192 if (ch
== '"' || ch
== '\'') {
198 if (ch
== EOF
) return -1; // oops
199 } else if (ch
== echar
) {
205 if (sp
== 0 && (ch
== ',' || ch
== ';')) {
208 if (ch
== EOF
) return -1;
209 if (ch
== ',' || ch
== ';') return -1;
210 //fprintf(stderr, " oldcount=%d; ch='%c'; sp=%d\n", count, ch, sp);
211 if (sp
== 0 && ch
== stack
[0]) {} else ++count
;
212 //fprintf(stderr, " newcount=%d; ch='%c'; sp=%d\n", count, ch, sp);
213 //if (ch != ')' && ch != ']' && ch != '}') ++count;
216 if (ch
== stack
[sp
]) {
217 //fprintf(stderr, " *close; ch='%c'; sp=%d\n", ch, sp);
221 // check for openings
223 case '(': echar
= ')'; break;
224 case '[': echar
= ']'; break;
225 case '{': echar
= '}'; break;
226 case ')': case ']': case '}': return -1; // oops
227 default: echar
= 0; break;
230 if (sp
>= StackDepth
-1) return -1; // oops
231 //fprintf(stderr, " *open; ch='%c'; echar='%c'; sp=%d\n", ch, echar, sp);
240 // ////////////////////////////////////////////////////////////////////////// //
241 festring
TextInput::findVar (cfestring
&name
, truth
*found
) const {
242 VarMap::const_iterator i
= mVars
.find(name
);
243 if (i
!= mVars
.end()) {
244 if (found
) *found
= true;
247 if (found
) *found
= false;
252 festring
TextInput::getVar (cfestring
&name
) {
254 festring res
= findVar(name
, &found
);
258 res
= mGetVar(this, name
);
260 festring s
= "unknown variable: "+name
;
268 void TextInput::setVar (cfestring
&name
, cfestring
&value
) {
273 //TODO: invoke callback
274 truth
TextInput::delVar (cfestring
&name
) {
275 VarMap::iterator i
= mVars
.find(name
);
276 if (i
!= mVars
.end()) {
284 // ////////////////////////////////////////////////////////////////////////// //
285 void TextInput::die (cfestring
&msg
) {
286 ABORT("ERROR in file %s, line %d: %s", GetFileName().CStr(), mTokenLine
, msg
.CStr());
290 // ////////////////////////////////////////////////////////////////////////// //
296 static const int maxCPrio
= 4;
297 static const char *opers
[5][7] = {
300 {"<", ">", "<=", ">=", "==", "!=", NULL
},
305 festring
TextInput::readCondition (festring
&token
, int prio
, truth skipIt
) {
306 festring res
, op1
, opc
;
307 //fprintf(stderr, "IN: prio: %d; skip: %s; [%s]\n", prio, skipIt?"t":"o", token.CStr());
311 readWordIntr(token
, true);
312 res
= readCondition(token
, maxCPrio
, skipIt
);
313 if (token
!= ")") die("')' expected");
314 } else if (token
== "@") {
315 readWordIntr(token
, true);
316 if (!skipIt
) res
= getVar(token
);
320 readWordIntr(token
, true);
325 readWordIntr(token
, true);
326 res
= readCondition(token
, 1, skipIt
);
328 if (res
== "") res
= "tan"; else res
= "";
331 res
= readCondition(token
, prio
-1, skipIt
);
337 if (prio
> 4) return res
;
338 res
= readCondition(token
, prio
-1, skipIt
);
340 //readWordIntr(token, true);
342 if (token
== "=") die("no assignments yet!");
344 //fprintf(stderr, " RET: [%s]\n", res.CStr());
347 if (token
== "less") token
= "<";
348 else if (token
== "great") token
= ">";
349 else if (token
== "equ") token
= "==";
350 else if (token
== "neq") token
= "!=";
351 else if (token
== "lessequ") token
= "<=";
352 else if (token
== "greatequ") token
= ">=";
353 for (int f
= 0; opers
[prio
][f
]; f
++) {
354 if (!strcmp(opers
[prio
][f
], token
.CStr())) { myOp
= true; break; }
356 //fprintf(stderr, "tk: [%s]; %s\n", token.CStr(), myOp?"MY":"skip");
359 readWordIntr(token
, true);
360 op1
= readCondition(token
, prio
-1, skipIt
);
361 //fprintf(stderr, " prio: %d; opc=[%s]; res=[%s]; op1=[%s]\n", prio, opc.CStr(), res.CStr(), op1.CStr());
363 case 2: // comparisons
365 if (!skipIt
) res
= (res
== op1
? "tan" : "");
366 } else if (opc
== "!=") {
367 if (!skipIt
) res
= (res
!= op1
? "tan" : "");
368 } else if (opc
== "<") {
369 if (!skipIt
) res
= (res
< op1
? "tan" : "");
370 } else if (opc
== ">") {
371 if (!skipIt
) res
= (res
> op1
? "tan" : "");
372 } else if (opc
== "<=") {
373 if (!skipIt
) res
= (res
<= op1
? "tan" : "");
374 } else if (opc
== ">=") {
375 if (!skipIt
) res
= (res
>= op1
? "tan" : "");
381 res
= (res
!= "" && op1
!= "" ? "tan" : "");
382 if (res
== "") skipIt
= true;
389 res
= (res
!= "" || op1
!= "" ? "tan" : "");
390 if (res
!= "") skipIt
= true;
395 die("invalid priority");
399 //fprintf(stderr, "OUT: prio: %d; skip: %s; [%s]\n", prio, skipIt?"t":"o", token.CStr());
405 // 1: processing 'then'
406 // 2: processing 'else'
407 // -1: skiping 'then'
408 // -2: skiping 'else'
409 // -3: skiping whole 'if', 'then' part
410 // -4: skiping whole 'if', 'else' part
411 // -666: skiping '{}'
412 // 666: in '{}', processing
413 void TextInput::ReadWord (festring
&str
, truth AbortOnEOF
, truth skipIt
) {
416 if (!mIfStack
.empty()) prc
= mIfStack
.top(); else prc
= 0;
417 readWordIntr(str
, AbortOnEOF
);
419 readWordIntr(str
, true);
420 festring res
= readCondition(str
, maxCPrio
, prc
<0);
421 if (str
!= ";") die("';' expected");
426 mIfStack
.push(res
!="" ? 1 : -1);
432 case 1: // processing 'then'
436 case -1: // skiping 'then'
440 case -3: // skiping whole, 'then'
444 default: die("unexpected 'else'");
448 if (str
== "endif") {
450 case 1: // processing 'then'
451 case 2: // processing 'else'
452 case -1: // skiping 'then'
453 case -2: // skiping 'else'
454 case -3: // skiping whole, 'then'
455 case -4: // skiping whole, 'else'
458 default: die("unexpected 'endif'");
463 mIfStack
.push(prc
>=0 ? 666 : -666);
464 if (prc
>= 0) return;
468 if (abs(prc
) != 666) die("unexpected '}'");
470 if (prc
>= 0) return;
473 if (prc
>= 0) return;
478 festring
TextInput::ReadWord (truth AbortOnEOF
) {
480 ReadWord(ToReturn
, AbortOnEOF
);
485 #define MODE_WORD (1)
486 #define MODE_NUMBER (2)
488 #define PUNCT_RETURN (0)
489 #define PUNCT_CONTINUE (1)
492 int TextInput::HandlePunct (festring
&String
, int Char
, int Mode
) {
493 mTokenLine
= mCurrentLine
;
498 // multiline comment? (possibly nested)
500 int OldChar
= 0, CommentLevel
= 1;
502 if (Eof()) ABORT("Unterminated comment in file %s, beginning at line %d!", GetFileName().CStr(), mTokenLine
);
504 if (OldChar
!= '*' || Char
!= '/') {
505 if (OldChar
!= '/' || Char
!= '*') {
512 if (!--CommentLevel
) break;
516 return PUNCT_CONTINUE
;
522 if (ch
== '\n') break;
524 return PUNCT_CONTINUE
;
529 if (Mode
) UngetChar('/'); else String
<< '/';
539 lastWordWasString
= true;
541 if (Eof()) ABORT("Unterminated string in file %s, beginning at line %d!", GetFileName().CStr(), mTokenLine
);
545 if (Char
== EOF
) ABORT("Unterminated string in file %s, beginning at line %d!", GetFileName().CStr(), mTokenLine
);
547 case 't': String
<< '\t'; break;
548 case 'n': String
<< '\n'; break;
549 case 'r': String
<< '\r'; break;
550 case '1': String
<< '\x01'; break;
551 case '2': String
<< '\x02'; break;
552 case '"': String
<< '"'; break;
554 ABORT("Invalid escape in string in file %s at line %d!", GetFileName().CStr(), mTokenLine
);
556 } else if (Char
== '"') {
559 String
<< char(Char
);
563 String << char(Char);
565 } else if (OldChar == '\\') {
566 String[String.GetSize()-1] = '"';
568 } else return PUNCT_RETURN;
571 ABORT("The thing that should not be");
574 String
<< char(Char
);
575 // two-char delimiters?
577 if (Char
== '=' || Char
== '<' || Char
== '>' || Char
== '!') {
579 if (Char
== '=') String
<< char(Char
); else UngetChar(Char
);
580 } else if (Char
== '&' || Char
== '|') {
582 if (Char
== ch
) String
<< char(ch
); else UngetChar(ch
);
583 } else if (Char
== ':') {
585 if (Char
== '=') String
<< char(Char
); else UngetChar(Char
);
592 void TextInput::readWordIntr (festring
&String
, truth AbortOnEOF
) {
595 lastWordWasString
= false;
596 mTokenLine
= mCurrentLine
;
597 for (int Char
= GetChar(); !Eof(); Char
= GetChar()) {
598 if (isalpha(Char
) || Char
== '_') {
600 mTokenLine
= mCurrentLine
;
602 } else if (Mode
== MODE_NUMBER
) {
603 if (Char
== '_') continue;
607 String
<< char(Char
);
612 mTokenLine
= mCurrentLine
;
614 } else if (Mode
== MODE_WORD
) {
618 String
<< char(Char
);
621 if ((Char
== ' ' || Char
== '\n' || Char
== '\r' || Char
== '\t') && Mode
) return;
622 if (ispunct(Char
) && HandlePunct(String
, Char
, Mode
) == PUNCT_RETURN
) return;
624 if (AbortOnEOF
) ABORT("Unexpected end of file %s!", GetFileName().CStr());
625 if (Mode
) realClearFlags();
629 char TextInput::ReadLetter (truth AbortOnEOF
) {
630 mTokenLine
= mCurrentLine
;
631 for (int Char
= GetChar(); !Eof(); mTokenLine
= mCurrentLine
, Char
= GetChar()) {
632 if (isalpha(Char
) || isdigit(Char
)) return Char
;
638 // multiline comment? (possibly nested)
640 int OldChar
= 0, CommentLevel
= 1;
642 if (Eof()) ABORT("Unterminated comment in file %s, beginning at line %d!", GetFileName().CStr(), mTokenLine
);
644 if (OldChar
!= '*' || Char
!= '/') {
645 if (OldChar
!= '/' || Char
!= '*') OldChar
= Char
;
651 if (!--CommentLevel
) break;
665 if (AbortOnEOF
) ABORT("Unexpected end of file %s!", GetFileName().CStr());
670 /* Reads a number or a formula from inputfile. Valid values could be for
671 instance "3", "5 * 4+5", "2+Variable%4" etc. */
672 //sLong inputfile::ReadNumber (int CallLevel, truth PreserveTerminator) {
673 festring
TextInput::ReadNumberIntr (int CallLevel
, sLong
*num
, truth
*isString
, truth allowStr
, truth PreserveTerminator
, truth
*wasCloseBrc
) {
676 truth NumberCorrect
= false;
677 truth firstWord
= true;
678 if (isString
) *isString
= false;
680 if (wasCloseBrc
) *wasCloseBrc
= false;
681 mTokenLine
= mCurrentLine
;
682 //fprintf(stderr, ">>> ReadNumberIntr()\n");
685 //fprintf(stderr, " ReadNumberIntr: word='%s'\n", Word.CStr());
689 if (mCollectingNumStr
) mNumStr
<< Word
;
690 ReadWord(Word
, true);
691 if (mCollectingNumStr
) mNumStr
<< Word
;
692 //fprintf(stderr, "var: [%s]\n", Word.CStr());
694 //fprintf(stderr, " value: [%s]\n", Word.CStr());
695 const char *s
= Word
.CStr();
697 sLong l
= strtoll(s
, &e
, 10);
699 //fprintf(stderr, " number: [%d]\n", l);
701 NumberCorrect
= true;
704 if (firstWord
&& allowStr
) {
705 if (isString
) *isString
= true;
708 ABORT("Number expected in file %s, line %d!", GetFileName().CStr(), mTokenLine
);
713 if (allowStr
&& lastWordWasString
) {
714 if (isString
) *isString
= true;
716 if (res
.GetSize() == 1) {
717 if (res
[0] != ';' && res
[0] != ',' && res
[0] != ':') {
718 ABORT("Invalid terminator in file %s, line %d!", GetFileName().CStr(), mTokenLine
);
720 if (PreserveTerminator
) UngetChar(res
[0]);
722 ABORT("Terminator expected in file %s, line %d!", GetFileName().CStr(), mTokenLine
);
729 char First
= Word
[0];
731 if (isdigit(First
)) {
732 if (mCollectingNumStr
) mNumStr
<< Word
;
733 Value
= atoi(Word
.CStr());
734 NumberCorrect
= true;
735 // HACK: autoinsert terminator
740 if (ch
== '}') UngetChar(';');
745 if (Word
.GetSize() == 1) {
746 //fprintf(stderr, " ReadNumberIntr: First='%c'\n", First);
747 if (First
== ';' || First
== ',' || First
== ':' || (wasCloseBrc
&& First
== '}')) {
748 if (First
== '}' && wasCloseBrc
) *wasCloseBrc
= true;
749 if (CallLevel
!= HIGHEST
|| PreserveTerminator
) UngetChar(First
);
750 if (num
) *num
= Value
;
754 if ((CallLevel
!= HIGHEST
&& CallLevel
!= 4) || PreserveTerminator
) UngetChar(')');
755 if (num
) *num
= Value
;
759 if (mCollectingNumStr
) mNumStr
<< Word
;
760 Value
= ~ReadNumber(4);
761 NumberCorrect
= true;
764 /* Convert this into an inline function! */
765 #define CHECK_OP(op, cl) \
766 if (First == #op[0]) { \
767 if (cl < CallLevel) {\
768 if (mCollectingNumStr) mNumStr << Word; \
769 Value op##= ReadNumber(cl);\
770 NumberCorrect = true;\
774 if (num) *num = Value;\
778 CHECK_OP(&, 1); CHECK_OP(|, 1); CHECK_OP(^, 1);
779 CHECK_OP(*, 2); CHECK_OP(/, 2); CHECK_OP(%, 2);
780 CHECK_OP(+, 3); CHECK_OP(-, 3);
783 char Next
= GetChar();
786 if (mCollectingNumStr
) mNumStr
<< "<<";
787 Value
<<= ReadNumber(1);
788 NumberCorrect
= true;
793 if (num
) *num
= Value
;
801 char Next
= GetChar();
804 if (mCollectingNumStr
) mNumStr
<< ">>";
805 Value
>>= ReadNumber(1);
806 NumberCorrect
= true;
811 if (num
) *num
= Value
;
821 if (num
) *num
= Value
;
824 if (mCollectingNumStr
) mNumStr
<< Word
;
825 Value
= ReadNumber(4);
826 if (mCollectingNumStr
) mNumStr
<< ")";
827 NumberCorrect
= false;
831 if (First
== '=' && CallLevel
== HIGHEST
) continue;
835 if (num
) *num
= Value
;
840 if (Word == "enum" || Word == "bitenum") {
841 if (CallLevel != HIGHEST || PreserveTerminator) UngetChar(';');
842 if (num) *num = Value;
848 if (mCollectingNumStr
) mNumStr
<< Word
;
849 int Bits
= ReadNumber();
851 int Red
= ReadNumber();
852 int Green
= ReadNumber();
853 int Blue
= ReadNumber();
854 Value
= MakeRGB16(Red
, Green
, Blue
);
855 } else if (Bits
== 24) {
856 int Red
= ReadNumber();
857 int Green
= ReadNumber();
858 int Blue
= ReadNumber();
859 Value
= MakeRGB24(Red
, Green
, Blue
);
861 ABORT("Illegal RGB bit size %d in file %s, line %d!", Bits
, GetFileName().CStr(), mTokenLine
);
863 NumberCorrect
= true;
867 if (Word
== "true" || Word
== "tan") {
868 if (mCollectingNumStr
) mNumStr
<< Word
;
870 NumberCorrect
= true;
874 if (Word
== "false" || Word
== "ona") {
875 if (mCollectingNumStr
) mNumStr
<< Word
;
877 NumberCorrect
= true;
882 valuemap::const_iterator Iterator
= ValueMap
->find(Word
);
883 if (Iterator
!= ValueMap
->end()) {
884 if (mCollectingNumStr
) mNumStr
<< Word
;
885 Value
= Iterator
->second
;
886 NumberCorrect
= true;
891 ABORT("Odd numeric value \"%s\" encountered in file %s, line %d!", Word
.CStr(), GetFileName().CStr(), mTokenLine
);
896 festring
TextInput::ReadCode (truth AbortOnEOF
) {
900 mTokenLine
= mCurrentLine
;
901 for (int Char
= GetChar(); !Eof(); Char
= GetChar()) {
902 //fprintf(stderr, "char: [%c]; inString: %d; sqLevel: %d\n", (Char < 32 || Char > 126 ? '?' : Char), inString, sqLevel);
905 if (Char
== inString
) {
907 } else if (Char
== '\\') {
916 } else if (Char
== ']') {
917 if (--sqLevel
== 0) break;
919 } else if (Char
== '/') {
920 if (Eof()) { res
<< ((char)Char
); break; }
921 switch ((Char
= GetChar())) {
922 case '/': // eol comment
923 while (!Eof()) if (GetChar() == '\n') break;
925 case '*': // c-like comment
927 if (GetChar() == '*') {
929 if (GetChar() == '/') break;
938 } else if (Char
== '"' || Char
== '\'') {
940 inString
= ((char)Char
);
946 if (AbortOnEOF
&& Eof()) ABORT("Unexpected end of file %s!", GetFileName().CStr());
951 sLong
TextInput::ReadNumber (int CallLevel
, truth PreserveTerminator
, truth
*wasCloseBrc
) {
953 truth isString
= false;
954 ReadNumberIntr(CallLevel
, &num
, &isString
, false, PreserveTerminator
, wasCloseBrc
);
959 festring
TextInput::ReadStringOrNumber (sLong
*num
, truth
*isString
, truth PreserveTerminator
, truth
*wasCloseBrc
) {
960 return ReadNumberIntr(HIGHEST
, num
, isString
, true, PreserveTerminator
, wasCloseBrc
);
964 // ////////////////////////////////////////////////////////////////////////// //
965 // fuck you, shitplusplus!
966 struct FuckedShitForFuckedFinally
{
969 FuckedShitForFuckedFinally (truth
*avar
, truth nval
=true) {
974 ~FuckedShitForFuckedFinally () {
980 sLong
TextInput::ReadNumberKeepStr (int CallLevel
, truth PreserveTerminator
, truth
*wasCloseBrc
) {
981 auto fuck
= FuckedShitForFuckedFinally(&mCollectingNumStr
);
983 return ReadNumber(CallLevel
, PreserveTerminator
, wasCloseBrc
);
987 festring
TextInput::ReadStringOrNumberKeepStr (sLong
*num
, truth
*isString
, truth PreserveTerminator
, truth
*wasCloseBrc
) {
988 auto fuck
= FuckedShitForFuckedFinally(&mCollectingNumStr
);
990 return ReadStringOrNumber(num
, isString
, PreserveTerminator
, wasCloseBrc
);
994 // ////////////////////////////////////////////////////////////////////////// //
995 v2
TextInput::ReadVector2d () {
998 if (ch
== '{') ch
= '}'; else { UngetChar(ch
); ch
= 0; }
1001 Vector
.X
= ReadNumber();
1002 Vector
.Y
= ReadNumber();
1006 if (GetChar() != ch
) ABORT("Vector syntax error: \"%c\" expected in file %s, line %d!", ch
, GetFileName().CStr(), TokenLine());
1009 if (ch
== '}') UngetChar(ch
);
1010 else if (ch
!= ';' && ch
!= ',') ABORT("Vector syntax error: terminator expected in file %s, line %d!", GetFileName().CStr(), TokenLine());
1017 rect
TextInput::ReadRect () {
1020 if (ch
== '{') ch
= '}'; else { UngetChar(ch
); ch
= 0; }
1023 Rect
.X1
= ReadNumber();
1024 Rect
.Y1
= ReadNumber();
1025 Rect
.X2
= ReadNumber();
1026 Rect
.Y2
= ReadNumber();
1030 if (GetChar() != ch
) ABORT("Vector syntax error: \"%c\" expected in file %s, line %d!", ch
, GetFileName().CStr(), TokenLine());
1033 if (ch
== '}') UngetChar(ch
);
1034 else if (ch
!= ';' && ch
!= ',') ABORT("Vector syntax error: terminator expected in file %s, line %d!", GetFileName().CStr(), TokenLine());
1041 // ////////////////////////////////////////////////////////////////////////// //
1042 void ReadData (festring
&String
, TextInput
&SaveFile
) {
1043 SaveFile
.ReadWord(String
);
1044 if (String
== "=") SaveFile
.ReadWord(String
);
1045 SaveFile
.ReadWord();
1049 void ReadData (fearray
<sLong
> &Array
, TextInput
&SaveFile
) {
1052 SaveFile
.ReadWord(Word
);
1055 Array
.Data
[0] = SaveFile
.ReadNumber();
1056 } else if (Word
== ":=") {
1057 SaveFile
.ReadWord(Word
);
1058 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1059 std::vector
<sLong
> v
;
1061 truth wasCloseBrc
= false;
1062 sLong n
= SaveFile
.ReadNumber(HIGHEST
, false, &wasCloseBrc
);
1063 if (wasCloseBrc
) break;
1066 Array
.Allocate(v
.size());
1067 for (unsigned int f
= 0; f
< v
.size(); ++f
) Array
.Data
[f
] = v
[f
];
1068 } else if (Word
== "=") {
1069 SaveFile
.ReadWord(Word
);
1070 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1071 fearray
<sLong
>::sizetype Size
= SaveFile
.ReadNumber();
1072 Array
.Allocate(Size
);
1073 for (fearray
<sLong
>::sizetype c
= 0; c
< Size
; ++c
) Array
.Data
[c
] = SaveFile
.ReadNumber();
1074 if (SaveFile
.ReadWord() != "}") ABORT("Illegal array terminator \"%s\" encountered in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1076 ABORT("Array syntax error: '=', '==' or ':=' expected in file %s, line %d!", SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1081 void ReadData (fearray
<festring
> &Array
, TextInput
&SaveFile
) {
1084 SaveFile
.ReadWord(Word
);
1087 SaveFile
.ReadWord(Array
.Data
[0]);
1088 if (SaveFile
.ReadWord() != ";") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1089 } else if (Word
== ":=") {
1090 SaveFile
.ReadWord(Word
);
1091 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1093 std::vector
<festring
> v
;
1096 SaveFile
.ReadWord(Word
);
1097 if (Word
== "}") break;
1099 SaveFile
.ReadWord(Word
);
1100 if (Word
== "}") break;
1101 if (Word
!= "," && Word
!= ";") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1103 Array
.Allocate(v
.size());
1104 for (unsigned int f
= 0; f
< v
.size(); ++f
) Array
.Data
[f
] = v
[f
];
1105 } else if (Word
== "=") {
1106 SaveFile
.ReadWord(Word
);
1107 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1108 fearray
<festring
>::sizetype Size
= SaveFile
.ReadNumber();
1109 Array
.Allocate(Size
);
1110 for (fearray
<festring
>::sizetype c
= 0; c
< Size
; ++c
) {
1111 SaveFile
.ReadWord(Array
.Data
[c
]);
1112 SaveFile
.ReadWord(Word
);
1113 if (Word
!= "," && Word
!= ";") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1115 if (SaveFile
.ReadWord() != "}") ABORT("Illegal array terminator \"%s\" encountered in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1117 ABORT("Array syntax error: '=', '==' or ':=' expected in file %s, line %d!", SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1122 // ////////////////////////////////////////////////////////////////////////// //
1123 TextInputFile::TextInputFile (cfestring
&FileName
, const valuemap
*aValueMap
, truth AbortOnErr
) {
1124 ifile
.Open(FileName
, AbortOnErr
);
1129 TextInputFile::~TextInputFile () {
1130 //fprintf(stderr, "TIF:~this();\n");
1132 //fprintf(stderr, "TIF:~this(); -- exit\n");
1136 int TextInputFile::realGetChar () { return ifile
.Get(); }
1137 bool TextInputFile::isRealEof () { return ifile
.Eof(); }
1138 bool TextInputFile::isRealOpen () { return ifile
.IsOpen(); }
1139 void TextInputFile::Close () { /*fprintf(stderr, "TIF:Close();\n");*/ ifile
.Close(); TextInput::Close(); }
1140 void TextInputFile::realClearFlags () { ifile
.ClearFlags(); }
1142 sLong
TextInputFile::realGetPos () { return (ifile
.IsOpen() ? ifile
.TellPos() : 0); }
1143 void TextInputFile::realSetPos (sLong apos
) { if (ifile
.IsOpen()) ifile
.SeekPosBegin(apos
); }
1147 // ////////////////////////////////////////////////////////////////////////// //
1148 MemTextFile::MemTextFile (cfestring
&afname
, cfestring
&str
, const valuemap
*aValueMap
) :
1154 bufSize
= str
.GetSize();
1155 buf
= (unsigned char *)calloc(1, bufSize
+1);
1156 memmove(buf
, str
.CStr(), bufSize
);
1161 MemTextFile::~MemTextFile () {
1162 //fprintf(stderr, "MTF:~this();\n");
1164 //fprintf(stderr, "MTF:~this(); -- exit\n");
1168 int MemTextFile::realGetChar () {
1169 if (bufPos
>= bufSize
) return EOF
;
1170 return buf
[bufPos
++];
1174 bool MemTextFile::isRealEof () { return (bufPos
>= bufSize
); }
1175 bool MemTextFile::isRealOpen () { return (buf
!= nullptr); }
1178 void MemTextFile::Close () {
1179 //fprintf(stderr, "MTF:Close();\n");
1190 void MemTextFile::realClearFlags () {}
1193 sLong
MemTextFile::realGetPos () { return bufPos
; }
1194 void MemTextFile::realSetPos (sLong apos
) { if (buf
!= nullptr) bufPos
= apos
; }