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>
31 # define Xungc gzungetc
34 # define Xclre gzclearerr
41 # define Xclre clearerr
45 ////////////////////////////////////////////////////////////////////////////////
46 outputfile::outputfile (cfestring
&FileName
, truth maxcomp
, truth AbortOnErr
) :
48 Buffer(gzopen(FileName
.CStr(), (maxcomp
?"wb9":"wb1"))),
50 Buffer(fopen(FileName
.CStr(), "wb")),
54 if (AbortOnErr
&& !IsOpen()) ABORT("Can't open %s for output!", FileName
.CStr());
58 outputfile::~outputfile () {
63 void outputfile::Close () {
75 void outputfile::Flush () {
77 gzflush(Buffer
, Z_FINISH
);
84 void outputfile::Put (char What
) {
93 void outputfile::Write (cchar
*Offset
, sLong Size
) {
95 gzwrite(Buffer
, Offset
, Size
);
97 fwrite(Offset
, 1, Size
, Buffer
);
102 ////////////////////////////////////////////////////////////////////////////////
103 truth
inputfile::fileExists (const festring
&fname
) {
105 if (stat(fname
.CStr(), &st
)) return false;
106 if (!S_ISREG(st
.st_mode
)) return false;
107 return access(fname
.CStr(), R_OK
) == 0;
111 festring
inputfile::GetMyDir (void) {
113 return IVAN_DATA_DIR
;
117 pid_t mypid
= getpid();
118 memset(myDir
, 0, sizeof(myDir
));
119 sprintf(buf
, "/proc/%u/exe", (unsigned int)mypid
);
120 if (readlink(buf
, myDir
, sizeof(myDir
)-1) < 0) strcpy(myDir
, ".");
122 char *p
= (char *)strrchr(myDir
, '/');
123 if (!p
) strcpy(myDir
, "."); else *p
= '\0';
125 if (myDir
[strlen(myDir
)-1] == '/') myDir
[strlen(myDir
)-1] = '\0';
131 ////////////////////////////////////////////////////////////////////////////////
132 inputfile::inputfile (cfestring
&FileName
, const valuemap
*ValueMap
, truth AbortOnErr
) :
134 Buffer(gzopen(FileName
.CStr(), "rb")),
136 Buffer(fopen(FileName
.CStr(), "rb")),
140 lastWordWasString(false),
148 if (AbortOnErr
&& !IsOpen()) ABORT("File %s not found!", FileName
.CStr());
152 inputfile::~inputfile () {
157 void inputfile::Close () {
169 int inputfile::Get () {
170 if (mCharBufPos
> 0) {
171 return mCharBuf
[--mCharBufPos
];
173 int ch
= Xgetc(Buffer
);
175 if (ch
== '\n') ++mCurrentLine
;
176 return (ch
< 0 ? EOF
: ch
);
183 void inputfile::Unget (int ch
) {
185 if (mCharBufPos
> 4) die("too many unread chars");
186 mCharBuf
[mCharBufPos
++] = ch
;
191 truth
inputfile::Eof () {
192 if (Buffer
) return (mCharBufPos
== 0 && Xfeof(Buffer
));
197 void inputfile::Read (char *Offset
, sLong Size
) {
199 if (gzread(Buffer
, Offset
, Size
) != Size
) ABORT("File '%s' read error!", FileName
.CStr());
201 if (fread(Offset
, Size
, 1, Buffer
) != 1) ABORT("File '%s' read error!", FileName
.CStr());
206 void inputfile::SeekPosBegin (sLong Offset
) {
207 if (Xseek(Buffer
, Offset
, SEEK_SET
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
211 void inputfile::SeekPosCurrent (sLong Offset
) {
212 if (Xseek(Buffer
, Offset
, SEEK_CUR
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
217 void inputfile::SeekPosEnd (sLong Offset
) {
218 //HACKHACK: emulate this
220 //SLOOOW, but we have to do that
222 char *buffer
, buf
[512];
225 for (bufsize
= 256*1024; bufsize
> (int)sizeof(buf
); bufsize
/= 2) {
226 if ((buffer
= (char *)malloc(bufsize
)) != NULL
) break;
228 if (buffer
== NULL
) { buffer
= buf
; bufsize
= sizeof(buf
); }
230 //fprintf(stderr, "determining file size...\n");
231 mFileSize
= opos
= gztell(Buffer
);
233 int len
= gzread(Buffer
, buffer
, bufsize
);
235 if (len
< 0) { mFileSize
= -1; break; } // error
237 if (len
< bufsize
) break; // eof reached
239 if (buffer
!= buf
) free(buffer
);
240 //fprintf(stderr, "file size: %d\n", ctx->filesize);
243 if (mFileSize
< 0) ABORT("File '%s': seek error!", FileName
.CStr());
245 if (gzseek(Buffer
, mFileSize
+Offset
, SEEK_SET
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
250 void inputfile::SeekPosEnd (sLong Offset
) {
251 if (fseek(Buffer
, Offset
, SEEK_END
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
256 sLong
inputfile::TellPos () {
257 return Xtell(Buffer
);
261 void inputfile::ClearFlags () {
266 festring
inputfile::findVar (cfestring
&name
, truth
*found
) const {
267 VarMap::const_iterator i
= mVars
.find(name
);
268 if (i
!= mVars
.end()) {
269 if (found
) *found
= true;
272 if (found
) *found
= false;
277 festring
inputfile::getVar (cfestring
&name
) {
279 festring res
= findVar(name
, &found
);
283 res
= mGetVar(this, name
);
285 festring s
= "unknown variable: "+name
;
293 void inputfile::setVar (cfestring
&name
, cfestring
&value
) {
298 //TODO: invoke callback
299 truth
inputfile::delVar (cfestring
&name
) {
300 VarMap::iterator i
= mVars
.find(name
);
301 if (i
!= mVars
.end()) {
309 void inputfile::die (cfestring
&msg
) {
310 ABORT("ERROR in file %s, line %d: %s", GetFileName().CStr(), mTokenLine
, msg
.CStr());
319 static const int maxCPrio
= 4;
320 static const char *opers
[5][7] = {
323 {"<", ">", "<=", ">=", "==", "!=", NULL
},
328 festring
inputfile::readCondition (festring
&token
, int prio
, truth skipIt
) {
329 festring res
, op1
, opc
;
331 //fprintf(stderr, "IN: prio: %d; skip: %s; [%s]\n", prio, skipIt?"t":"o", token.CStr());
335 readWordIntr(token
, true);
336 res
= readCondition(token
, maxCPrio
, skipIt
);
337 if (token
!= ")") die("')' expected");
338 } else if (token
== "@") {
339 readWordIntr(token
, true);
340 if (!skipIt
) res
= getVar(token
);
344 readWordIntr(token
, true);
349 readWordIntr(token
, true);
350 res
= readCondition(token
, 1, skipIt
);
352 if (res
== "") res
= "tan"; else res
= "";
355 res
= readCondition(token
, prio
-1, skipIt
);
361 if (prio
> 4) return res
;
362 res
= readCondition(token
, prio
-1, skipIt
);
364 //readWordIntr(token, true);
366 if (token
== "=") die("no assignments yet!");
368 //fprintf(stderr, " RET: [%s]\n", res.CStr());
371 if (token
== "less") token
= "<";
372 else if (token
== "great") token
= ">";
373 else if (token
== "equ") token
= "==";
374 else if (token
== "neq") token
= "!=";
375 else if (token
== "lessequ") token
= "<=";
376 else if (token
== "greatequ") token
= ">=";
377 for (int f
= 0; opers
[prio
][f
]; f
++) {
378 if (!strcmp(opers
[prio
][f
], token
.CStr())) { myOp
= true; break; }
380 //fprintf(stderr, "tk: [%s]; %s\n", token.CStr(), myOp?"MY":"skip");
383 readWordIntr(token
, true);
384 op1
= readCondition(token
, prio
-1, skipIt
);
385 //fprintf(stderr, " prio: %d; opc=[%s]; res=[%s]; op1=[%s]\n", prio, opc.CStr(), res.CStr(), op1.CStr());
387 case 2: // comparisons
389 if (!skipIt
) res
= res
==op1
? "tan" : "";
390 } else if (opc
== "!=") {
391 if (!skipIt
) res
= res
!=op1
? "tan" : "";
392 } else if (opc
== "<") {
393 if (!skipIt
) res
= res
<op1
? "tan" : "";
394 } else if (opc
== ">") {
395 if (!skipIt
) res
= res
>op1
? "tan" : "";
396 } else if (opc
== "<=") {
397 if (!skipIt
) res
= res
<=op1
? "tan" : "";
398 } else if (opc
== ">=") {
399 if (!skipIt
) res
= res
>=op1
? "tan" : "";
405 res
= res
!=""&&op1
!="" ? "tan" : "";
406 if (res
== "") skipIt
= true;
413 res
= res
!=""||op1
!="" ? "tan" : "";
414 if (res
!= "") skipIt
= true;
419 die("invalid priority");
423 //fprintf(stderr, "OUT: prio: %d; skip: %s; [%s]\n", prio, skipIt?"t":"o", token.CStr());
429 // 1: processing 'then'
430 // 2: processing 'else'
431 // -1: skiping 'then'
432 // -2: skiping 'else'
433 // -3: skiping whole 'if', 'then' part
434 // -4: skiping whole 'if', 'else' part
435 // -666: skiping '{}'
436 // 666: in '{}', processing
437 void inputfile::ReadWord (festring
&str
, truth AbortOnEOF
, truth skipIt
) {
441 if (!mIfStack
.empty()) prc
= mIfStack
.top(); else prc
= 0;
442 readWordIntr(str
, AbortOnEOF
);
444 readWordIntr(str
, true);
445 festring res
= readCondition(str
, maxCPrio
, prc
<0);
446 if (str
!= ";") die("';' expected");
451 mIfStack
.push(res
!="" ? 1 : -1);
457 case 1: // processing 'then'
461 case -1: // skiping 'then'
465 case -3: // skiping whole, 'then'
469 default: die("unexpected 'else'");
473 if (str
== "endif") {
475 case 1: // processing 'then'
476 case 2: // processing 'else'
477 case -1: // skiping 'then'
478 case -2: // skiping 'else'
479 case -3: // skiping whole, 'then'
480 case -4: // skiping whole, 'else'
483 default: die("unexpected 'endif'");
488 mIfStack
.push(prc
>=0 ? 666 : -666);
489 if (prc
>= 0) return;
493 if (abs(prc
) != 666) die("unexpected '}'");
495 if (prc
>= 0) return;
498 if (prc
>= 0) return;
503 festring
inputfile::ReadWord (truth AbortOnEOF
) {
506 ReadWord(ToReturn
, AbortOnEOF
);
511 void inputfile::SkipSpaces () {
514 if (ch
== EOF
) break;
515 if ((unsigned char)ch
> ' ') {
523 #define MODE_WORD (1)
524 #define MODE_NUMBER (2)
526 #define PUNCT_RETURN (0)
527 #define PUNCT_CONTINUE (1)
530 int inputfile::HandlePunct (festring
&String
, int Char
, int Mode
) {
531 mTokenLine
= mCurrentLine
;
533 // comment? (can be nested)
537 int OldChar
= 0, CommentLevel
= 1;
540 if (Eof()) ABORT("Unterminated comment in file %s, beginning at line %d!", FileName
.CStr(), mTokenLine
);
542 if (OldChar
!= '*' || Char
!= '/') {
543 if (OldChar
!= '/' || Char
!= '*') OldChar
= Char
;
549 if (!--CommentLevel
) break;
553 return PUNCT_CONTINUE
;
559 if (ch
== '\n') break;
561 return PUNCT_CONTINUE
;
566 if (Mode
) Unget('/'); else String
<< '/';
577 lastWordWasString
= true;
579 if (Eof()) ABORT("Unterminated string in file %s, beginning at line %d!", FileName
.CStr(), mTokenLine
);
583 if (Char
== EOF
) ABORT("Unterminated string in file %s, beginning at line %d!", FileName
.CStr(), mTokenLine
);
585 case 't': String
<< '\t'; break;
586 case 'n': String
<< '\n'; break;
587 case 'r': String
<< '\r'; break;
588 case '"': String
<< '"'; break;
590 ABORT("Invalid escape in string in file %s at line %d!", FileName
.CStr(), mTokenLine
);
592 } else if (Char
== '"') {
595 String
<< char(Char
);
599 String << char(Char);
601 } else if (OldChar == '\\') {
602 String[String.GetSize()-1] = '"';
604 } else return PUNCT_RETURN;
608 String
<< char(Char
);
610 if (Char
== '=' || Char
== '<' || Char
== '>' || Char
== '!') {
612 if (Char
== '=') String
<< char(Char
); else Unget(Char
);
613 } else if (Char
== '&' || Char
== '|') {
615 if (Char
== ch
) String
<< char(ch
); else Unget(ch
);
616 } else if (Char
== ':') {
618 if (Char
== '=') String
<< char(Char
); else Unget(Char
);
625 void inputfile::readWordIntr (festring
&String
, truth AbortOnEOF
) {
629 lastWordWasString
= false;
630 mTokenLine
= mCurrentLine
;
631 for (int Char
= Get(); !Eof(); Char
= Get()) {
632 if (isalpha(Char
) || Char
== '_') {
634 mTokenLine
= mCurrentLine
;
636 } else if (Mode
== MODE_NUMBER
) {
640 String
<< char(Char
);
645 mTokenLine
= mCurrentLine
;
647 } else if (Mode
== MODE_WORD
) {
651 String
<< char(Char
);
654 if ((Char
== ' ' || Char
== '\n' || Char
== '\r' || Char
== '\t') && Mode
) return;
655 if (ispunct(Char
) && HandlePunct(String
, Char
, Mode
) == PUNCT_RETURN
) return;
657 if (AbortOnEOF
) ABORT("Unexpected end of file %s!", FileName
.CStr());
658 if (Mode
) ClearFlags();
662 char inputfile::ReadLetter (truth AbortOnEOF
) {
663 mTokenLine
= mCurrentLine
;
664 for (int Char
= Get(); !Eof(); mTokenLine
= mCurrentLine
, Char
= Get()) {
665 if (isalpha(Char
) || isdigit(Char
)) return Char
;
671 int OldChar
= 0, CommentLevel
= 1;
674 if (Eof()) ABORT("Unterminated comment in file %s, beginning at line %d!", FileName
.CStr(), mTokenLine
);
676 if (OldChar
!= '*' || Char
!= '/') {
677 if (OldChar
!= '/' || Char
!= '*') OldChar
= Char
;
683 if (!--CommentLevel
) break;
697 if (AbortOnEOF
) ABORT("Unexpected end of file %s!", FileName
.CStr());
702 /* Reads a number or a formula from inputfile. Valid values could be for
703 instance "3", "5 * 4+5", "2+Variable%4" etc. */
704 //sLong inputfile::ReadNumber (int CallLevel, truth PreserveTerminator) {
705 festring
inputfile::ReadNumberIntr (int CallLevel
, sLong
*num
, truth
*isString
, truth allowStr
, truth PreserveTerminator
, truth
*wasCloseBrc
) {
708 truth NumberCorrect
= false;
709 truth firstWord
= true;
713 if (wasCloseBrc
) *wasCloseBrc
= false;
714 mTokenLine
= mCurrentLine
;
719 ReadWord(Word
, true);
720 //fprintf(stderr, "var: [%s]\n", Word.CStr());
722 //fprintf(stderr, " value: [%s]\n", Word.CStr());
723 const char *s
= Word
.CStr();
725 sLong l
= strtoll(s
, &e
, 10);
727 //fprintf(stderr, " number: [%d]\n", l);
729 NumberCorrect
= true;
732 if (firstWord
&& allowStr
) {
736 ABORT("Number expected in file %s, line %d!", FileName
.CStr(), mTokenLine
);
740 if (allowStr
&& lastWordWasString
) {
743 if (res
.GetSize() == 1) {
744 if (res
[0] != ';' && res
[0] != ',' && res
[0] != ':') {
745 ABORT("Invalid terminator in file %s, line %d!", FileName
.CStr(), mTokenLine
);
747 if (PreserveTerminator
) Unget(res
[0]);
749 ABORT("Terminator expected in file %s, line %d!", FileName
.CStr(), mTokenLine
);
755 char First
= Word
[0];
756 if (isdigit(First
)) {
757 Value
= atoi(Word
.CStr());
758 NumberCorrect
= true;
761 if (Word
.GetSize() == 1) {
762 if (First
== ';' || First
== ',' || First
== ':' || (wasCloseBrc
&& First
== '}')) {
763 if (First
== '}' && wasCloseBrc
) *wasCloseBrc
= true;
764 if (CallLevel
!= HIGHEST
|| PreserveTerminator
) Unget(First
);
769 if ((CallLevel
!= HIGHEST
&& CallLevel
!= 4) || PreserveTerminator
) Unget(')');
774 Value
= ~ReadNumber(4);
775 NumberCorrect
= true;
778 /* Convert this into an inline function! */
779 #define CHECK_OP(op, cl) \
780 if (First == #op[0]) { \
781 if (cl < CallLevel) {\
782 Value op##= ReadNumber(cl);\
783 NumberCorrect = true;\
791 CHECK_OP(&, 1); CHECK_OP(|, 1); CHECK_OP(^, 1);
792 CHECK_OP(*, 2); CHECK_OP(/, 2); CHECK_OP(%, 2);
793 CHECK_OP(+, 3); CHECK_OP(-, 3);
798 Value
<<= ReadNumber(1);
799 NumberCorrect
= true;
814 Value
>>= ReadNumber(1);
815 NumberCorrect
= true;
832 Value
= ReadNumber(4);
833 NumberCorrect
= false;
837 if (First
== '=' && CallLevel
== HIGHEST
) continue;
846 if (Word == "enum" || Word == "bitenum") {
847 if (CallLevel != HIGHEST || PreserveTerminator) Unget(';');
853 int Bits
= ReadNumber();
855 int Red
= ReadNumber();
856 int Green
= ReadNumber();
857 int Blue
= ReadNumber();
858 Value
= MakeRGB16(Red
, Green
, Blue
);
859 } else if (Bits
== 24) {
860 int Red
= ReadNumber();
861 int Green
= ReadNumber();
862 int Blue
= ReadNumber();
863 Value
= MakeRGB24(Red
, Green
, Blue
);
865 ABORT("Illegal RGB bit size %d in file %s, line %d!", Bits
, FileName
.CStr(), mTokenLine
);
867 NumberCorrect
= true;
870 if (Word
== "true" || Word
== "tan") {
872 NumberCorrect
= true;
875 if (Word
== "false" || Word
== "ona") {
877 NumberCorrect
= true;
881 valuemap::const_iterator Iterator
= ValueMap
->find(Word
);
882 if (Iterator
!= ValueMap
->end()) {
883 Value
= Iterator
->second
;
884 NumberCorrect
= true;
888 ABORT("Odd numeric value \"%s\" encountered in file %s, line %d!", Word
.CStr(), FileName
.CStr(), mTokenLine
);
893 festring
inputfile::ReadCode (truth AbortOnEOF
) {
898 mTokenLine
= mCurrentLine
;
899 for (int Char
= Get(); !Eof(); Char
= Get()) {
900 //fprintf(stderr, "char: [%c]; inString: %d; sqLevel: %d\n", (Char < 32 || Char > 126 ? '?' : Char), inString, sqLevel);
903 if (Char
== inString
) {
905 } else if (Char
== '\\') {
914 } else if (Char
== ']') {
915 if (--sqLevel
== 0) break;
917 } else if (Char
== '/') {
918 if (Eof()) { res
<< ((char)Char
); break; }
919 switch ((Char
= Get())) {
920 case '/': // eol comment
921 while (!Eof()) if (Get() == '\n') break;
923 case '*': // c-like comment
927 if (Get() == '/') break;
936 } else if (Char
== '"' || Char
== '\'') {
938 inString
= ((char)Char
);
944 if (AbortOnEOF
&& Eof()) ABORT("Unexpected end of file %s!", FileName
.CStr());
949 sLong
inputfile::ReadNumber (int CallLevel
, truth PreserveTerminator
, truth
*wasCloseBrc
) {
951 truth isString
= false;
953 ReadNumberIntr(CallLevel
, &num
, &isString
, false, PreserveTerminator
, wasCloseBrc
);
958 festring
inputfile::ReadStringOrNumber (sLong
*num
, truth
*isString
, truth PreserveTerminator
, truth
*wasCloseBrc
) {
959 return ReadNumberIntr(HIGHEST
, num
, isString
, true, PreserveTerminator
, wasCloseBrc
);
963 v2
inputfile::ReadVector2d () {
966 Vector
.X
= ReadNumber();
967 Vector
.Y
= ReadNumber();
972 rect
inputfile::ReadRect () {
975 Rect
.X1
= ReadNumber();
976 Rect
.Y1
= ReadNumber();
977 Rect
.X2
= ReadNumber();
978 Rect
.Y2
= ReadNumber();
983 outputfile
&operator << (outputfile
&SaveFile
, cfestring
&String
) {
984 uShort Length
= String
.GetSize();
986 if (Length
) SaveFile
.Write(String
.CStr(), Length
);
991 inputfile
&operator >> (inputfile
&SaveFile
, festring
&String
) {
992 char *RealBuffer
, StackBuffer
[1024];
995 RealBuffer
= Length
< 1024 ? StackBuffer
: new char[Length
+1];
998 SaveFile
.Read(RealBuffer
, Length
);
999 RealBuffer
[Length
] = 0;
1000 String
<< RealBuffer
;
1002 if (Length
>= 1024) delete [] RealBuffer
;
1007 outputfile
&operator << (outputfile
&SaveFile
, cchar
*String
) {
1008 uShort Length
= String
? strlen(String
) : 0;
1010 if (Length
) SaveFile
.Write(String
, Length
);
1015 inputfile
&operator >> (inputfile
&SaveFile
, char *&String
) {
1019 String
= new char[Length
+1];
1020 SaveFile
.Read(String
, Length
);
1029 void ReadData (festring
&String
, inputfile
&SaveFile
) {
1030 SaveFile
.ReadWord(String
);
1031 if (String
== "=") SaveFile
.ReadWord(String
);
1032 SaveFile
.ReadWord();
1036 void ReadData (fearray
<sLong
> &Array
, inputfile
&SaveFile
) {
1039 SaveFile
.ReadWord(Word
);
1042 Array
.Data
[0] = SaveFile
.ReadNumber();
1043 } else if (Word
== ":=") {
1044 SaveFile
.ReadWord(Word
);
1045 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1047 std::vector
<sLong
> v
;
1050 truth wasCloseBrc
= false;
1051 sLong n
= SaveFile
.ReadNumber(HIGHEST
, false, &wasCloseBrc
);
1052 if (wasCloseBrc
) break;
1055 Array
.Allocate(v
.size());
1056 for (unsigned int f
= 0; f
< v
.size(); ++f
) Array
.Data
[f
] = v
[f
];
1057 } else if (Word
== "=") {
1058 SaveFile
.ReadWord(Word
);
1059 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1060 fearray
<sLong
>::sizetype Size
= SaveFile
.ReadNumber();
1061 Array
.Allocate(Size
);
1062 for (fearray
<sLong
>::sizetype c
= 0; c
< Size
; ++c
) Array
.Data
[c
] = SaveFile
.ReadNumber();
1063 if (SaveFile
.ReadWord() != "}") ABORT("Illegal array terminator \"%s\" encountered in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1065 ABORT("Array syntax error: '=', '==' or ':=' expected in file %s, line %d!", SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1070 void ReadData (fearray
<festring
> &Array
, inputfile
&SaveFile
) {
1073 SaveFile
.ReadWord(Word
);
1076 SaveFile
.ReadWord(Array
.Data
[0]);
1077 if (SaveFile
.ReadWord() != ";") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1078 } else if (Word
== ":=") {
1079 SaveFile
.ReadWord(Word
);
1080 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1082 std::vector
<festring
> v
;
1085 SaveFile
.ReadWord(Word
);
1086 if (Word
== "}") break;
1088 SaveFile
.ReadWord(Word
);
1089 if (Word
== "}") break;
1090 if (Word
!= "," && Word
!= ";") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1092 Array
.Allocate(v
.size());
1093 for (unsigned int f
= 0; f
< v
.size(); ++f
) Array
.Data
[f
] = v
[f
];
1094 } else if (Word
== "=") {
1095 SaveFile
.ReadWord(Word
);
1096 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1097 fearray
<festring
>::sizetype Size
= SaveFile
.ReadNumber();
1098 Array
.Allocate(Size
);
1099 for (fearray
<festring
>::sizetype c
= 0; c
< Size
; ++c
) {
1100 SaveFile
.ReadWord(Array
.Data
[c
]);
1101 SaveFile
.ReadWord(Word
);
1102 if (Word
!= "," && Word
!= ";") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1104 if (SaveFile
.ReadWord() != "}") ABORT("Illegal array terminator \"%s\" encountered in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1106 ABORT("Array syntax error: '=', '==' or ':=' expected in file %s, line %d!", SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1112 feuLong inputfile::TellLineOfPos (sLong Pos) {
1114 sLong BackupPos = TellPos();
1116 while (TellPos() != Pos) { if (Get() == '\n') ++Line; }
1117 if (TellPos() != BackupPos) SeekPosBegin(BackupPos);
1123 ////////////////////////////////////////////////////////////////////////////////
1125 meminputfile::meminputfile (cfestring
&str
, const valuemap
*ValueMap
) :
1126 inputfile("", ValueMap
, false),
1135 strcpy(fname
, "/tmp/ivan.XXXXXX");
1136 fd
= mkstemp(fname
);
1138 //fprintf(stderr, "[%s]\n", tfname.CStr());
1139 if (fd
< 0) ABORT("Can't create temporary file!");
1140 write(fd
, str
.CStr(), str
.GetSize());
1142 Buffer
= gzopen(fname
, "rb");
1143 FileName
= "<memory>";
1147 meminputfile::~meminputfile () {
1150 unlink(tfname
.CStr());
1157 meminputfile::meminputfile (cfestring
&str
, const valuemap
*ValueMap
) :
1158 inputfile("", ValueMap
, false),
1164 bufSize
= str
.GetSize();
1165 buf
= (char *)calloc(1, bufSize
+1);
1166 memmove(buf
, str
.CStr(), bufSize
);
1167 Buffer
= fmemopen(buf
, bufSize
, "rb");
1168 FileName
= "<memory>";
1172 meminputfile::~meminputfile () {