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>
35 # define Xungc gzungetc
38 # define Xclre gzclearerr
45 # define Xclre clearerr
49 ////////////////////////////////////////////////////////////////////////////////
50 outputfile::outputfile (cfestring
&FileName
, truth maxcomp
, truth AbortOnErr
) :
52 Buffer(gzopen(FileName
.CStr(), (maxcomp
?"wb9":"wb1"))),
54 Buffer(fopen(FileName
.CStr(), "wb")),
58 if (AbortOnErr
&& !IsOpen()) ABORT("Can't open %s for output!", FileName
.CStr());
62 outputfile::~outputfile () {
67 void outputfile::Close () {
79 void outputfile::Flush () {
81 gzflush(Buffer
, Z_FINISH
);
88 void outputfile::Put (char What
) {
97 void outputfile::Write (cchar
*Offset
, sLong Size
) {
99 gzwrite(Buffer
, Offset
, Size
);
101 fwrite(Offset
, 1, Size
, Buffer
);
106 ////////////////////////////////////////////////////////////////////////////////
107 truth
inputfile::fileExists (const festring
&fname
) {
110 if (stat(fname
.CStr(), &st
)) return false;
111 if (!S_ISREG(st
.st_mode
)) return false;
112 return access(fname
.CStr(), R_OK
) == 0;
114 FILE *fl
= fopen(fname
.CStr(), "rb");
121 festring
inputfile::GetMyDir (void) {
125 pid_t mypid
= getpid();
126 memset(myDir
, 0, sizeof(myDir
));
127 sprintf(buf
, "/proc/%u/exe", (unsigned int)mypid
);
128 if (readlink(buf
, myDir
, sizeof(myDir
)-1) < 0) strcpy(myDir
, ".");
130 char *p
= (char *)strrchr(myDir
, '/');
131 if (!p
) strcpy(myDir
, "."); else *p
= '\0';
133 if (myDir
[strlen(myDir
)-1] == '/') myDir
[strlen(myDir
)-1] = '\0';
136 memset(myDir
, 0, sizeof(myDir
));
137 GetModuleFileName(GetModuleHandle(NULL
), myDir
, sizeof(myDir
)-1);
138 p
= strrchr(myDir
, '\\');
139 if (!p
) strcpy(myDir
, "."); else *p
= '\0';
145 ////////////////////////////////////////////////////////////////////////////////
146 inputfile::inputfile (cfestring
&FileName
, const valuemap
*ValueMap
, truth AbortOnErr
) :
148 Buffer(gzopen(FileName
.CStr(), "rb")),
150 Buffer(fopen(FileName
.CStr(), "rb")),
154 lastWordWasString(false),
162 if (AbortOnErr
&& !IsOpen()) ABORT("File %s not found!", FileName
.CStr());
166 inputfile::~inputfile () {
171 void inputfile::Close () {
183 int inputfile::Get () {
184 if (mCharBufPos
> 0) {
185 return mCharBuf
[--mCharBufPos
];
187 int ch
= Xgetc(Buffer
);
189 if (ch
== '\n') ++mCurrentLine
;
190 return (ch
< 0 ? EOF
: ch
);
197 void inputfile::Unget (int ch
) {
199 if (mCharBufPos
> 4) die("too many unread chars");
200 mCharBuf
[mCharBufPos
++] = ch
;
205 truth
inputfile::Eof () {
206 if (Buffer
) return (mCharBufPos
== 0 && Xfeof(Buffer
));
211 void inputfile::Read (char *Offset
, sLong Size
) {
213 if (gzread(Buffer
, Offset
, Size
) != Size
) ABORT("File '%s' read error!", FileName
.CStr());
215 if (fread(Offset
, Size
, 1, Buffer
) != 1) ABORT("File '%s' read error!", FileName
.CStr());
220 void inputfile::SeekPosBegin (sLong Offset
) {
221 if (Xseek(Buffer
, Offset
, SEEK_SET
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
225 void inputfile::SeekPosCurrent (sLong Offset
) {
226 if (Xseek(Buffer
, Offset
, SEEK_CUR
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
231 void inputfile::SeekPosEnd (sLong Offset
) {
232 //HACKHACK: emulate this
234 //SLOOOW, but we have to do that
236 char *buffer
, buf
[512];
239 for (bufsize
= 256*1024; bufsize
> (int)sizeof(buf
); bufsize
/= 2) {
240 if ((buffer
= (char *)malloc(bufsize
)) != NULL
) break;
242 if (buffer
== NULL
) { buffer
= buf
; bufsize
= sizeof(buf
); }
244 //fprintf(stderr, "determining file size...\n");
245 mFileSize
= opos
= gztell(Buffer
);
247 int len
= gzread(Buffer
, buffer
, bufsize
);
249 if (len
< 0) { mFileSize
= -1; break; } // error
251 if (len
< bufsize
) break; // eof reached
253 if (buffer
!= buf
) free(buffer
);
254 //fprintf(stderr, "file size: %d\n", ctx->filesize);
257 if (mFileSize
< 0) ABORT("File '%s': seek error!", FileName
.CStr());
259 if (gzseek(Buffer
, mFileSize
+Offset
, SEEK_SET
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
264 void inputfile::SeekPosEnd (sLong Offset
) {
265 if (fseek(Buffer
, Offset
, SEEK_END
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
270 sLong
inputfile::TellPos () {
271 return Xtell(Buffer
);
275 void inputfile::ClearFlags () {
280 festring
inputfile::findVar (cfestring
&name
, truth
*found
) const {
281 VarMap::const_iterator i
= mVars
.find(name
);
282 if (i
!= mVars
.end()) {
283 if (found
) *found
= true;
286 if (found
) *found
= false;
291 festring
inputfile::getVar (cfestring
&name
) {
293 festring res
= findVar(name
, &found
);
297 res
= mGetVar(this, name
);
299 festring s
= "unknown variable: "+name
;
307 void inputfile::setVar (cfestring
&name
, cfestring
&value
) {
312 //TODO: invoke callback
313 truth
inputfile::delVar (cfestring
&name
) {
314 VarMap::iterator i
= mVars
.find(name
);
315 if (i
!= mVars
.end()) {
323 void inputfile::die (cfestring
&msg
) {
324 ABORT("ERROR in file %s, line %d: %s", GetFileName().CStr(), mTokenLine
, msg
.CStr());
333 static const int maxCPrio
= 4;
334 static const char *opers
[5][7] = {
337 {"<", ">", "<=", ">=", "==", "!=", NULL
},
342 festring
inputfile::readCondition (festring
&token
, int prio
, truth skipIt
) {
343 festring res
, op1
, opc
;
345 //fprintf(stderr, "IN: prio: %d; skip: %s; [%s]\n", prio, skipIt?"t":"o", token.CStr());
349 readWordIntr(token
, true);
350 res
= readCondition(token
, maxCPrio
, skipIt
);
351 if (token
!= ")") die("')' expected");
352 } else if (token
== "@") {
353 readWordIntr(token
, true);
354 if (!skipIt
) res
= getVar(token
);
358 readWordIntr(token
, true);
363 readWordIntr(token
, true);
364 res
= readCondition(token
, 1, skipIt
);
366 if (res
== "") res
= "tan"; else res
= "";
369 res
= readCondition(token
, prio
-1, skipIt
);
375 if (prio
> 4) return res
;
376 res
= readCondition(token
, prio
-1, skipIt
);
378 //readWordIntr(token, true);
380 if (token
== "=") die("no assignments yet!");
382 //fprintf(stderr, " RET: [%s]\n", res.CStr());
385 if (token
== "less") token
= "<";
386 else if (token
== "great") token
= ">";
387 else if (token
== "equ") token
= "==";
388 else if (token
== "neq") token
= "!=";
389 else if (token
== "lessequ") token
= "<=";
390 else if (token
== "greatequ") token
= ">=";
391 for (int f
= 0; opers
[prio
][f
]; f
++) {
392 if (!strcmp(opers
[prio
][f
], token
.CStr())) { myOp
= true; break; }
394 //fprintf(stderr, "tk: [%s]; %s\n", token.CStr(), myOp?"MY":"skip");
397 readWordIntr(token
, true);
398 op1
= readCondition(token
, prio
-1, skipIt
);
399 //fprintf(stderr, " prio: %d; opc=[%s]; res=[%s]; op1=[%s]\n", prio, opc.CStr(), res.CStr(), op1.CStr());
401 case 2: // comparisons
403 if (!skipIt
) res
= res
==op1
? "tan" : "";
404 } else if (opc
== "!=") {
405 if (!skipIt
) res
= res
!=op1
? "tan" : "";
406 } else if (opc
== "<") {
407 if (!skipIt
) res
= res
<op1
? "tan" : "";
408 } else if (opc
== ">") {
409 if (!skipIt
) res
= res
>op1
? "tan" : "";
410 } else if (opc
== "<=") {
411 if (!skipIt
) res
= res
<=op1
? "tan" : "";
412 } else if (opc
== ">=") {
413 if (!skipIt
) res
= res
>=op1
? "tan" : "";
419 res
= res
!=""&&op1
!="" ? "tan" : "";
420 if (res
== "") skipIt
= true;
427 res
= res
!=""||op1
!="" ? "tan" : "";
428 if (res
!= "") skipIt
= true;
433 die("invalid priority");
437 //fprintf(stderr, "OUT: prio: %d; skip: %s; [%s]\n", prio, skipIt?"t":"o", token.CStr());
443 // 1: processing 'then'
444 // 2: processing 'else'
445 // -1: skiping 'then'
446 // -2: skiping 'else'
447 // -3: skiping whole 'if', 'then' part
448 // -4: skiping whole 'if', 'else' part
449 // -666: skiping '{}'
450 // 666: in '{}', processing
451 void inputfile::ReadWord (festring
&str
, truth AbortOnEOF
, truth skipIt
) {
455 if (!mIfStack
.empty()) prc
= mIfStack
.top(); else prc
= 0;
456 readWordIntr(str
, AbortOnEOF
);
458 readWordIntr(str
, true);
459 festring res
= readCondition(str
, maxCPrio
, prc
<0);
460 if (str
!= ";") die("';' expected");
465 mIfStack
.push(res
!="" ? 1 : -1);
471 case 1: // processing 'then'
475 case -1: // skiping 'then'
479 case -3: // skiping whole, 'then'
483 default: die("unexpected 'else'");
487 if (str
== "endif") {
489 case 1: // processing 'then'
490 case 2: // processing 'else'
491 case -1: // skiping 'then'
492 case -2: // skiping 'else'
493 case -3: // skiping whole, 'then'
494 case -4: // skiping whole, 'else'
497 default: die("unexpected 'endif'");
502 mIfStack
.push(prc
>=0 ? 666 : -666);
503 if (prc
>= 0) return;
507 if (abs(prc
) != 666) die("unexpected '}'");
509 if (prc
>= 0) return;
512 if (prc
>= 0) return;
517 festring
inputfile::ReadWord (truth AbortOnEOF
) {
520 ReadWord(ToReturn
, AbortOnEOF
);
525 void inputfile::SkipSpaces () {
528 if (ch
== EOF
) break;
529 if ((unsigned char)ch
> ' ') {
537 #define MODE_WORD (1)
538 #define MODE_NUMBER (2)
540 #define PUNCT_RETURN (0)
541 #define PUNCT_CONTINUE (1)
544 int inputfile::HandlePunct (festring
&String
, int Char
, int Mode
) {
545 mTokenLine
= mCurrentLine
;
547 // comment? (can be nested)
551 int OldChar
= 0, CommentLevel
= 1;
554 if (Eof()) ABORT("Unterminated comment in file %s, beginning at line %d!", FileName
.CStr(), mTokenLine
);
556 if (OldChar
!= '*' || Char
!= '/') {
557 if (OldChar
!= '/' || Char
!= '*') OldChar
= Char
;
563 if (!--CommentLevel
) break;
567 return PUNCT_CONTINUE
;
573 if (ch
== '\n') break;
575 return PUNCT_CONTINUE
;
580 if (Mode
) Unget('/'); else String
<< '/';
591 lastWordWasString
= true;
593 if (Eof()) ABORT("Unterminated string in file %s, beginning at line %d!", FileName
.CStr(), mTokenLine
);
597 if (Char
== EOF
) ABORT("Unterminated string in file %s, beginning at line %d!", FileName
.CStr(), mTokenLine
);
599 case 't': String
<< '\t'; break;
600 case 'n': String
<< '\n'; break;
601 case 'r': String
<< '\r'; break;
602 case '"': String
<< '"'; break;
604 ABORT("Invalid escape in string in file %s at line %d!", FileName
.CStr(), mTokenLine
);
606 } else if (Char
== '"') {
609 String
<< char(Char
);
613 String << char(Char);
615 } else if (OldChar == '\\') {
616 String[String.GetSize()-1] = '"';
618 } else return PUNCT_RETURN;
622 String
<< char(Char
);
624 if (Char
== '=' || Char
== '<' || Char
== '>' || Char
== '!') {
626 if (Char
== '=') String
<< char(Char
); else Unget(Char
);
627 } else if (Char
== '&' || Char
== '|') {
629 if (Char
== ch
) String
<< char(ch
); else Unget(ch
);
630 } else if (Char
== ':') {
632 if (Char
== '=') String
<< char(Char
); else Unget(Char
);
639 void inputfile::readWordIntr (festring
&String
, truth AbortOnEOF
) {
643 lastWordWasString
= false;
644 mTokenLine
= mCurrentLine
;
645 for (int Char
= Get(); !Eof(); Char
= Get()) {
646 if (isalpha(Char
) || Char
== '_') {
648 mTokenLine
= mCurrentLine
;
650 } else if (Mode
== MODE_NUMBER
) {
654 String
<< char(Char
);
659 mTokenLine
= mCurrentLine
;
661 } else if (Mode
== MODE_WORD
) {
665 String
<< char(Char
);
668 if ((Char
== ' ' || Char
== '\n' || Char
== '\r' || Char
== '\t') && Mode
) return;
669 if (ispunct(Char
) && HandlePunct(String
, Char
, Mode
) == PUNCT_RETURN
) return;
671 if (AbortOnEOF
) ABORT("Unexpected end of file %s!", FileName
.CStr());
672 if (Mode
) ClearFlags();
676 char inputfile::ReadLetter (truth AbortOnEOF
) {
677 mTokenLine
= mCurrentLine
;
678 for (int Char
= Get(); !Eof(); mTokenLine
= mCurrentLine
, Char
= Get()) {
679 if (isalpha(Char
) || isdigit(Char
)) return Char
;
685 int OldChar
= 0, CommentLevel
= 1;
688 if (Eof()) ABORT("Unterminated comment in file %s, beginning at line %d!", FileName
.CStr(), mTokenLine
);
690 if (OldChar
!= '*' || Char
!= '/') {
691 if (OldChar
!= '/' || Char
!= '*') OldChar
= Char
;
697 if (!--CommentLevel
) break;
711 if (AbortOnEOF
) ABORT("Unexpected end of file %s!", FileName
.CStr());
716 /* Reads a number or a formula from inputfile. Valid values could be for
717 instance "3", "5 * 4+5", "2+Variable%4" etc. */
718 //sLong inputfile::ReadNumber (int CallLevel, truth PreserveTerminator) {
719 festring
inputfile::ReadNumberIntr (int CallLevel
, sLong
*num
, truth
*isString
, truth allowStr
, truth PreserveTerminator
, truth
*wasCloseBrc
) {
722 truth NumberCorrect
= false;
723 truth firstWord
= true;
727 if (wasCloseBrc
) *wasCloseBrc
= false;
728 mTokenLine
= mCurrentLine
;
733 ReadWord(Word
, true);
734 //fprintf(stderr, "var: [%s]\n", Word.CStr());
736 //fprintf(stderr, " value: [%s]\n", Word.CStr());
737 const char *s
= Word
.CStr();
739 sLong l
= strtoll(s
, &e
, 10);
741 //fprintf(stderr, " number: [%d]\n", l);
743 NumberCorrect
= true;
746 if (firstWord
&& allowStr
) {
750 ABORT("Number expected in file %s, line %d!", FileName
.CStr(), mTokenLine
);
754 if (allowStr
&& lastWordWasString
) {
757 if (res
.GetSize() == 1) {
758 if (res
[0] != ';' && res
[0] != ',' && res
[0] != ':') {
759 ABORT("Invalid terminator in file %s, line %d!", FileName
.CStr(), mTokenLine
);
761 if (PreserveTerminator
) Unget(res
[0]);
763 ABORT("Terminator expected in file %s, line %d!", FileName
.CStr(), mTokenLine
);
769 char First
= Word
[0];
770 if (isdigit(First
)) {
771 Value
= atoi(Word
.CStr());
772 NumberCorrect
= true;
775 if (Word
.GetSize() == 1) {
776 if (First
== ';' || First
== ',' || First
== ':' || (wasCloseBrc
&& First
== '}')) {
777 if (First
== '}' && wasCloseBrc
) *wasCloseBrc
= true;
778 if (CallLevel
!= HIGHEST
|| PreserveTerminator
) Unget(First
);
783 if ((CallLevel
!= HIGHEST
&& CallLevel
!= 4) || PreserveTerminator
) Unget(')');
788 Value
= ~ReadNumber(4);
789 NumberCorrect
= true;
792 /* Convert this into an inline function! */
793 #define CHECK_OP(op, cl) \
794 if (First == #op[0]) { \
795 if (cl < CallLevel) {\
796 Value op##= ReadNumber(cl);\
797 NumberCorrect = true;\
805 CHECK_OP(&, 1); CHECK_OP(|, 1); CHECK_OP(^, 1);
806 CHECK_OP(*, 2); CHECK_OP(/, 2); CHECK_OP(%, 2);
807 CHECK_OP(+, 3); CHECK_OP(-, 3);
812 Value
<<= ReadNumber(1);
813 NumberCorrect
= true;
828 Value
>>= ReadNumber(1);
829 NumberCorrect
= true;
846 Value
= ReadNumber(4);
847 NumberCorrect
= false;
851 if (First
== '=' && CallLevel
== HIGHEST
) continue;
860 if (Word == "enum" || Word == "bitenum") {
861 if (CallLevel != HIGHEST || PreserveTerminator) Unget(';');
867 int Bits
= ReadNumber();
869 int Red
= ReadNumber();
870 int Green
= ReadNumber();
871 int Blue
= ReadNumber();
872 Value
= MakeRGB16(Red
, Green
, Blue
);
873 } else if (Bits
== 24) {
874 int Red
= ReadNumber();
875 int Green
= ReadNumber();
876 int Blue
= ReadNumber();
877 Value
= MakeRGB24(Red
, Green
, Blue
);
879 ABORT("Illegal RGB bit size %d in file %s, line %d!", Bits
, FileName
.CStr(), mTokenLine
);
881 NumberCorrect
= true;
884 if (Word
== "true" || Word
== "tan") {
886 NumberCorrect
= true;
889 if (Word
== "false" || Word
== "ona") {
891 NumberCorrect
= true;
895 valuemap::const_iterator Iterator
= ValueMap
->find(Word
);
896 if (Iterator
!= ValueMap
->end()) {
897 Value
= Iterator
->second
;
898 NumberCorrect
= true;
902 ABORT("Odd numeric value \"%s\" encountered in file %s, line %d!", Word
.CStr(), FileName
.CStr(), mTokenLine
);
907 festring
inputfile::ReadCode (truth AbortOnEOF
) {
912 mTokenLine
= mCurrentLine
;
913 for (int Char
= Get(); !Eof(); Char
= Get()) {
914 //fprintf(stderr, "char: [%c]; inString: %d; sqLevel: %d\n", (Char < 32 || Char > 126 ? '?' : Char), inString, sqLevel);
917 if (Char
== inString
) {
919 } else if (Char
== '\\') {
928 } else if (Char
== ']') {
929 if (--sqLevel
== 0) break;
931 } else if (Char
== '/') {
932 if (Eof()) { res
<< Char
; break; }
933 switch ((Char
= Get())) {
934 case '/': // eol comment
935 while (!Eof()) if (Get() == '\n') break;
937 case '*': // c-like comment
941 if (Get() == '/') break;
950 } else if (Char
== '"' || Char
== '\'') {
958 if (AbortOnEOF
&& Eof()) ABORT("Unexpected end of file %s!", FileName
.CStr());
963 sLong
inputfile::ReadNumber (int CallLevel
, truth PreserveTerminator
, truth
*wasCloseBrc
) {
965 truth isString
= false;
967 ReadNumberIntr(CallLevel
, &num
, &isString
, false, PreserveTerminator
, wasCloseBrc
);
972 festring
inputfile::ReadStringOrNumber (sLong
*num
, truth
*isString
, truth PreserveTerminator
, truth
*wasCloseBrc
) {
973 return ReadNumberIntr(HIGHEST
, num
, isString
, true, PreserveTerminator
, wasCloseBrc
);
977 v2
inputfile::ReadVector2d () {
980 Vector
.X
= ReadNumber();
981 Vector
.Y
= ReadNumber();
986 rect
inputfile::ReadRect () {
989 Rect
.X1
= ReadNumber();
990 Rect
.Y1
= ReadNumber();
991 Rect
.X2
= ReadNumber();
992 Rect
.Y2
= ReadNumber();
997 outputfile
&operator << (outputfile
&SaveFile
, cfestring
&String
) {
998 uShort Length
= String
.GetSize();
1000 if (Length
) SaveFile
.Write(String
.CStr(), Length
);
1005 inputfile
&operator >> (inputfile
&SaveFile
, festring
&String
) {
1006 char *RealBuffer
, StackBuffer
[1024];
1009 RealBuffer
= Length
< 1024 ? StackBuffer
: new char[Length
+1];
1012 SaveFile
.Read(RealBuffer
, Length
);
1013 RealBuffer
[Length
] = 0;
1014 String
<< RealBuffer
;
1016 if (Length
>= 1024) delete [] RealBuffer
;
1021 outputfile
&operator << (outputfile
&SaveFile
, cchar
*String
) {
1022 uShort Length
= String
? strlen(String
) : 0;
1024 if (Length
) SaveFile
.Write(String
, Length
);
1029 inputfile
&operator >> (inputfile
&SaveFile
, char *&String
) {
1033 String
= new char[Length
+1];
1034 SaveFile
.Read(String
, Length
);
1043 void ReadData (festring
&String
, inputfile
&SaveFile
) {
1044 SaveFile
.ReadWord(String
);
1045 if (String
== "=") SaveFile
.ReadWord(String
);
1046 SaveFile
.ReadWord();
1050 void ReadData (fearray
<sLong
> &Array
, inputfile
&SaveFile
) {
1053 SaveFile
.ReadWord(Word
);
1056 Array
.Data
[0] = SaveFile
.ReadNumber();
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());
1061 std::vector
<sLong
> v
;
1064 truth wasCloseBrc
= false;
1065 sLong n
= SaveFile
.ReadNumber(HIGHEST
, false, &wasCloseBrc
);
1066 if (wasCloseBrc
) break;
1069 Array
.Allocate(v
.size());
1070 for (unsigned int f
= 0; f
< v
.size(); ++f
) Array
.Data
[f
] = v
[f
];
1071 } else if (Word
== "=") {
1072 SaveFile
.ReadWord(Word
);
1073 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1074 fearray
<sLong
>::sizetype Size
= SaveFile
.ReadNumber();
1075 Array
.Allocate(Size
);
1076 for (fearray
<sLong
>::sizetype c
= 0; c
< Size
; ++c
) Array
.Data
[c
] = SaveFile
.ReadNumber();
1077 if (SaveFile
.ReadWord() != "}") ABORT("Illegal array terminator \"%s\" encountered in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1079 ABORT("Array syntax error: '=', '==' or ':=' expected in file %s, line %d!", SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1084 void ReadData (fearray
<festring
> &Array
, inputfile
&SaveFile
) {
1087 SaveFile
.ReadWord(Word
);
1090 SaveFile
.ReadWord(Array
.Data
[0]);
1091 if (SaveFile
.ReadWord() != ";") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1092 } else if (Word
== ":=") {
1093 SaveFile
.ReadWord(Word
);
1094 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1096 std::vector
<festring
> v
;
1099 SaveFile
.ReadWord(Word
);
1100 if (Word
== "}") break;
1102 SaveFile
.ReadWord(Word
);
1103 if (Word
== "}") break;
1104 if (Word
!= "," && Word
!= ";") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1106 Array
.Allocate(v
.size());
1107 for (unsigned int f
= 0; f
< v
.size(); ++f
) Array
.Data
[f
] = v
[f
];
1108 } else if (Word
== "=") {
1109 SaveFile
.ReadWord(Word
);
1110 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1111 fearray
<festring
>::sizetype Size
= SaveFile
.ReadNumber();
1112 Array
.Allocate(Size
);
1113 for (fearray
<festring
>::sizetype c
= 0; c
< Size
; ++c
) {
1114 SaveFile
.ReadWord(Array
.Data
[c
]);
1115 SaveFile
.ReadWord(Word
);
1116 if (Word
!= "," && Word
!= ";") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1118 if (SaveFile
.ReadWord() != "}") ABORT("Illegal array terminator \"%s\" encountered in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1120 ABORT("Array syntax error: '=', '==' or ':=' expected in file %s, line %d!", SaveFile
.GetFileName().CStr(), SaveFile
.TokenLine());
1126 feuLong inputfile::TellLineOfPos (sLong Pos) {
1128 sLong BackupPos = TellPos();
1130 while (TellPos() != Pos) { if (Get() == '\n') ++Line; }
1131 if (TellPos() != BackupPos) SeekPosBegin(BackupPos);
1137 ////////////////////////////////////////////////////////////////////////////////
1139 meminputfile::meminputfile (cfestring
&str
, const valuemap
*ValueMap
) :
1140 inputfile("", ValueMap
, false),
1147 char nbuf
[MAX_PATH
+1], tfn
[MAX_PATH
+1];
1148 GetTempPath(MAX_PATH
, nbuf
);
1149 GetTempFileName(nbuf
, "ivan", 0, tfn
);
1151 FILE *fl
= fopen(tfn
, "wb");
1152 fwrite(str
.CStr(), str
.GetSize(), 1, fl
);
1154 Buffer
= gzopen(tfn
, "rb");
1159 strcpy(fname
, "/tmp/ivan.XXXXXX");
1160 fd
= mkstemp(fname
);
1162 //fprintf(stderr, "[%s]\n", tfname.CStr());
1163 if (fd
< 0) ABORT("Can't create temporary file!");
1164 write(fd
, str
.CStr(), str
.GetSize());
1166 Buffer
= gzopen(fname
, "rb");
1168 FileName
= "<memory>";
1172 meminputfile::~meminputfile () {
1175 unlink(tfname
.CStr());
1182 meminputfile::meminputfile (cfestring
&str
, const valuemap
*ValueMap
) :
1183 inputfile("", ValueMap
, false),
1190 char nbuf
[MAX_PATH
+1], tfn
[MAX_PATH
+1];
1191 GetTempPath(MAX_PATH
, nbuf
);
1192 GetTempFileName(nbuf
, "ivan", 0, tfn
);
1194 FILE *fl
= fopen(tfn
, "wb");
1195 fwrite(str
.CStr(), str
.GetSize(), 1, fl
);
1197 Buffer
= fopen(tfn
, "rb");
1199 bufSize
= str
.GetSize();
1200 buf
= (char *)calloc(1, bufSize
+1);
1201 memmove(buf
, str
.CStr(), bufSize
);
1202 Buffer
= fmemopen(buf
, bufSize
, "rb");
1204 FileName
= "<memory>";
1208 meminputfile::~meminputfile () {
1212 DeleteFile(tfname
.CStr());