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 inputfile::inputfile (cfestring
&FileName
, const valuemap
*ValueMap
, truth AbortOnErr
) :
147 Buffer(gzopen(FileName
.CStr(), "rb")),
149 Buffer(fopen(FileName
.CStr(), "rb")),
153 lastWordWasString(false)
158 if (AbortOnErr
&& !IsOpen()) ABORT("File %s not found!", FileName
.CStr());
162 inputfile::~inputfile () {
167 void inputfile::Close () {
179 int inputfile::Get () {
180 return Xgetc(Buffer
);
184 int inputfile::Unget (int ch
) {
185 return Xungc(ch
, Buffer
);
189 void inputfile::Read (char *Offset
, sLong Size
) {
191 if (gzread(Buffer
, Offset
, Size
) != Size
) ABORT("File '%s' read error!", FileName
.CStr());
193 if (fread(Offset
, Size
, 1, Buffer
) != 1) ABORT("File '%s' read error!", FileName
.CStr());
198 truth
inputfile::Eof () {
199 return Xfeof(Buffer
);
203 void inputfile::SeekPosBegin (sLong Offset
) {
204 if (Xseek(Buffer
, Offset
, SEEK_SET
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
208 void inputfile::SeekPosCurrent (sLong Offset
) {
209 if (Xseek(Buffer
, Offset
, SEEK_CUR
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
214 void inputfile::SeekPosEnd (sLong Offset
) {
215 //HACKHACK: emulate this
217 //SLOOOW, but we have to do that
219 char *buffer
, buf
[512];
222 for (bufsize
= 256*1024; bufsize
> (int)sizeof(buf
); bufsize
/= 2) {
223 if ((buffer
= (char *)malloc(bufsize
)) != NULL
) break;
225 if (buffer
== NULL
) { buffer
= buf
; bufsize
= sizeof(buf
); }
227 //fprintf(stderr, "determining file size...\n");
228 mFileSize
= opos
= gztell(Buffer
);
230 int len
= gzread(Buffer
, buffer
, bufsize
);
232 if (len
< 0) { mFileSize
= -1; break; } // error
234 if (len
< bufsize
) break; // eof reached
236 if (buffer
!= buf
) free(buffer
);
237 //fprintf(stderr, "file size: %d\n", ctx->filesize);
240 if (mFileSize
< 0) ABORT("File '%s': seek error!", FileName
.CStr());
242 if (gzseek(Buffer
, mFileSize
+Offset
, SEEK_SET
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
247 void inputfile::SeekPosEnd (sLong Offset
) {
248 if (fseek(Buffer
, Offset
, SEEK_END
) < 0) ABORT("File '%s': seek error!", FileName
.CStr());
253 sLong
inputfile::TellPos () {
254 return Xtell(Buffer
);
258 void inputfile::ClearFlags () {
263 festring
inputfile::findVar (cfestring
&name
, truth
*found
) const {
264 VarMap::const_iterator i
= mVars
.find(name
);
265 if (i
!= mVars
.end()) {
266 if (found
) *found
= true;
269 if (found
) *found
= false;
274 festring
inputfile::getVar (cfestring
&name
) {
276 festring res
= findVar(name
, &found
);
280 res
= mGetVar(this, name
);
282 festring s
= "unknown variable: "+name
;
290 void inputfile::setVar (cfestring
&name
, cfestring
&value
) {
295 //TODO: invoke callback
296 truth
inputfile::delVar (cfestring
&name
) {
297 VarMap::iterator i
= mVars
.find(name
);
298 if (i
!= mVars
.end()) {
306 void inputfile::die (cfestring
&msg
) {
307 ABORT("ERROR in file %s, line %d: %s", GetFileName().CStr(), TellLine(), msg
.CStr());
316 const int maxCPrio
= 4;
317 const char *opers
[5][7] = {
320 {"<", ">", "<=", ">=", "==", "!=", NULL
},
325 festring
inputfile::readCondition (festring
&token
, int prio
, truth skipIt
) {
326 festring res
, op1
, opc
;
327 //fprintf(stderr, "IN: prio: %d; skip: %s; [%s]\n", prio, skipIt?"t":"o", token.CStr());
331 readWordIntr(token
, true);
332 res
= readCondition(token
, maxCPrio
, skipIt
);
333 if (token
!= ")") die("')' expected");
334 } else if (token
== "@") {
335 readWordIntr(token
, true);
336 if (!skipIt
) res
= getVar(token
);
340 readWordIntr(token
, true);
345 readWordIntr(token
, true);
346 res
= readCondition(token
, 1, skipIt
);
348 if (res
== "") res
= "tan"; else res
= "";
351 res
= readCondition(token
, prio
-1, skipIt
);
357 if (prio
> 4) return res
;
358 res
= readCondition(token
, prio
-1, skipIt
);
360 //readWordIntr(token, true);
362 if (token
== "=") die("no assignments yet!");
364 //fprintf(stderr, " RET: [%s]\n", res.CStr());
367 if (token
== "less") token
= "<";
368 else if (token
== "great") token
= ">";
369 else if (token
== "equ") token
= "==";
370 else if (token
== "neq") token
= "!=";
371 else if (token
== "lessequ") token
= "<=";
372 else if (token
== "greatequ") token
= ">=";
373 for (int f
= 0; opers
[prio
][f
]; f
++) {
374 if (!strcmp(opers
[prio
][f
], token
.CStr())) { myOp
= true; break; }
376 //fprintf(stderr, "tk: [%s]; %s\n", token.CStr(), myOp?"MY":"skip");
379 readWordIntr(token
, true);
380 op1
= readCondition(token
, prio
-1, skipIt
);
381 //fprintf(stderr, " prio: %d; opc=[%s]; res=[%s]; op1=[%s]\n", prio, opc.CStr(), res.CStr(), op1.CStr());
383 case 2: // comparisons
385 if (!skipIt
) res
= res
==op1
? "tan" : "";
386 } else if (opc
== "!=") {
387 if (!skipIt
) res
= res
!=op1
? "tan" : "";
388 } else if (opc
== "<") {
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" : "";
401 res
= res
!=""&&op1
!="" ? "tan" : "";
402 if (res
== "") skipIt
= true;
409 res
= res
!=""||op1
!="" ? "tan" : "";
410 if (res
!= "") skipIt
= true;
415 die("invalid priority");
419 //fprintf(stderr, "OUT: prio: %d; skip: %s; [%s]\n", prio, skipIt?"t":"o", token.CStr());
425 // 1: processing 'then'
426 // 2: processing 'else'
427 // -1: skiping 'then'
428 // -2: skiping 'else'
429 // -3: skiping whole 'if', 'then' part
430 // -4: skiping whole 'if', 'else' part
431 // -666: skiping '{}'
432 // 666: in '{}', processing
433 void inputfile::ReadWord (festring
&str
, truth AbortOnEOF
, truth skipIt
) {
436 if (!mIfStack
.empty()) prc
= mIfStack
.top(); else prc
= 0;
437 readWordIntr(str
, AbortOnEOF
);
439 readWordIntr(str
, true);
440 festring res
= readCondition(str
, maxCPrio
, prc
<0);
441 if (str
!= ";") die("';' expected");
446 mIfStack
.push(res
!="" ? 1 : -1);
452 case 1: // processing 'then'
456 case -1: // skiping 'then'
460 case -3: // skiping whole, 'then'
464 default: die("unexpected 'else'");
468 if (str
== "endif") {
470 case 1: // processing 'then'
471 case 2: // processing 'else'
472 case -1: // skiping 'then'
473 case -2: // skiping 'else'
474 case -3: // skiping whole, 'then'
475 case -4: // skiping whole, 'else'
478 default: die("unexpected 'endif'");
483 mIfStack
.push(prc
>=0 ? 666 : -666);
484 if (prc
>= 0) return;
488 if (abs(prc
) != 666) die("unexpected '}'");
490 if (prc
>= 0) return;
493 if (prc
>= 0) return;
498 festring
inputfile::ReadWord (truth AbortOnEOF
) {
500 ReadWord(ToReturn
, AbortOnEOF
);
505 void inputfile::SkipSpaces () {
506 while (!Xfeof(Buffer
)) {
507 int ch
= Xgetc(Buffer
);
508 if (ch
== EOF
) break;
509 if ((unsigned char)ch
> ' ') {
518 #define MODE_NUMBER 2
520 #define PUNCT_RETURN 0
521 #define PUNCT_CONTINUE 1
523 int inputfile::HandlePunct (festring
&String
, int Char
, int Mode
) {
525 // comment? (can be nested)
526 if (!Xfeof(Buffer
)) {
527 Char
= Xgetc(Buffer
);
529 sLong StartPos
= TellPos();
530 int OldChar
= 0, CommentLevel
= 1;
532 if (Xfeof(Buffer
)) ABORT("Unterminated comment in file %s, beginning at line %d!", FileName
.CStr(), TellLineOfPos(StartPos
));
533 Char
= Xgetc(Buffer
);
534 if (OldChar
!= '*' || Char
!= '/') {
535 if (OldChar
!= '/' || Char
!= '*') OldChar
= Char
;
541 if (!--CommentLevel
) break;
545 return PUNCT_CONTINUE
;
549 while (!Xfeof(Buffer
)) {
550 int ch
= Xgetc(Buffer
);
551 if (ch
== '\n') break;
553 return PUNCT_CONTINUE
;
558 if (Mode
) Xungc('/', Buffer
); else String
<< '/';
569 lastWordWasString
= true;
570 sLong StartPos
= TellPos();
572 if (Xfeof(Buffer
)) ABORT("Unterminated string in file %s, beginning at line %d!", FileName
.CStr(), TellLineOfPos(StartPos
));
573 Char
= Xgetc(Buffer
);
575 Char
= Xgetc(Buffer
);
576 if (Char
== EOF
) ABORT("Unterminated string in file %s, beginning at line %d!", FileName
.CStr(), TellLineOfPos(StartPos
));
578 case 't': String
<< '\t'; break;
579 case 'n': String
<< '\n'; break;
580 case 'r': String
<< '\r'; break;
581 case '"': String
<< '"'; break;
583 ABORT("Invalid escape in string in file %s at line %d!", FileName
.CStr(), TellLine());
585 } else if (Char
== '"') {
588 String
<< char(Char
);
592 String << char(Char);
594 } else if (OldChar == '\\') {
595 String[String.GetSize()-1] = '"';
597 } else return PUNCT_RETURN;
601 String
<< char(Char
);
602 if (!Xfeof(Buffer
)) {
603 if (Char
== '=' || Char
== '<' || Char
== '>' || Char
== '!') {
604 Char
= Xgetc(Buffer
);
605 if (Char
== '=') String
<< char(Char
); else Xungc(Char
, Buffer
);
606 } else if (Char
== '&' || Char
== '|') {
607 int ch
= Xgetc(Buffer
);
608 if (Char
== ch
) String
<< char(ch
); else Xungc(ch
, Buffer
);
615 void inputfile::readWordIntr (festring
&String
, truth AbortOnEOF
) {
618 lastWordWasString
= false;
619 for (int Char
= Xgetc(Buffer
); !Xfeof(Buffer
); Char
= Xgetc(Buffer
)) {
620 if (isalpha(Char
) || Char
== '_') {
621 if (!Mode
) Mode
= MODE_WORD
;
622 else if (Mode
== MODE_NUMBER
) {
626 String
<< char(Char
);
630 if (!Mode
) Mode
= MODE_NUMBER
;
631 else if (Mode
== MODE_WORD
) {
635 String
<< char(Char
);
638 if ((Char
== ' ' || Char
== '\n' || Char
== '\r' || Char
== '\t') && Mode
) return;
639 if (ispunct(Char
) && HandlePunct(String
, Char
, Mode
) == PUNCT_RETURN
) return;
641 if (AbortOnEOF
) ABORT("Unexpected end of file %s!", FileName
.CStr());
642 if (Mode
) Xclre(Buffer
);
646 char inputfile::ReadLetter (truth AbortOnEOF
) {
647 for (int Char
= Xgetc(Buffer
); !Xfeof(Buffer
); Char
= Xgetc(Buffer
)) {
648 if (isalpha(Char
) || isdigit(Char
)) return Char
;
651 if (!Xfeof(Buffer
)) {
652 Char
= Xgetc(Buffer
);
654 sLong StartPos
= TellPos();
655 int OldChar
= 0, CommentLevel
= 1;
657 if (Xfeof(Buffer
)) ABORT("Unterminated comment in file %s, beginning at line %d!", FileName
.CStr(), TellLineOfPos(StartPos
));
658 Char
= Xgetc(Buffer
);
659 if (OldChar
!= '*' || Char
!= '/') {
660 if (OldChar
!= '/' || Char
!= '*') OldChar
= Char
;
666 if (!--CommentLevel
) break;
680 if (AbortOnEOF
) ABORT("Unexpected end of file %s!", FileName
.CStr());
685 /* Reads a number or a formula from inputfile. Valid values could be for
686 instance "3", "5 * 4+5", "2+Variable%4" etc. */
687 //sLong inputfile::ReadNumber (int CallLevel, truth PreserveTerminator) {
688 festring
inputfile::ReadNumberIntr (int CallLevel
, sLong
*num
, truth
*isString
, truth allowStr
, truth PreserveTerminator
) {
691 truth NumberCorrect
= false;
692 truth firstWord
= true;
700 ReadWord(Word
, true);
701 //fprintf(stderr, "var: [%s]\n", Word.CStr());
703 //fprintf(stderr, " value: [%s]\n", Word.CStr());
704 const char *s
= Word
.CStr();
706 sLong l
= strtoll(s
, &e
, 10);
708 //fprintf(stderr, " number: [%d]\n", l);
710 NumberCorrect
= true;
713 if (firstWord
&& allowStr
) {
717 ABORT("Number expected in file %s, line %d!", FileName
.CStr(), TellLine());
721 if (allowStr
&& lastWordWasString
) {
724 if (res
.GetSize() == 1) {
725 if (res
[0] != ';' && res
[0] != ',' && res
[0] != ':') {
726 ABORT("Invalid terminator in file %s, line %d!", FileName
.CStr(), TellLine());
728 if (PreserveTerminator
) Xungc(res
[0], Buffer
);
730 ABORT("Terminator expected in file %s, line %d!", FileName
.CStr(), TellLine());
736 char First
= Word
[0];
737 if (isdigit(First
)) {
738 Value
= atoi(Word
.CStr());
739 NumberCorrect
= true;
742 if (Word
.GetSize() == 1) {
743 if (First
== ';' || First
== ',' || First
== ':') {
744 if (CallLevel
!= HIGHEST
|| PreserveTerminator
) Xungc(First
, Buffer
);
749 if ((CallLevel
!= HIGHEST
&& CallLevel
!= 4) || PreserveTerminator
) Xungc(')', Buffer
);
754 Value
= ~ReadNumber(4);
755 NumberCorrect
= true;
758 /* Convert this into an inline function! */
759 #define CHECK_OP(op, cl) \
760 if (First == #op[0]) { \
761 if (cl < CallLevel) {\
762 Value op##= ReadNumber(cl);\
763 NumberCorrect = true;\
766 Xungc(#op[0], Buffer);\
771 CHECK_OP(&, 1); CHECK_OP(|, 1); CHECK_OP(^, 1);
772 CHECK_OP(*, 2); CHECK_OP(/, 2); CHECK_OP(%, 2);
773 CHECK_OP(+, 3); CHECK_OP(-, 3);
778 Value
<<= ReadNumber(1);
779 NumberCorrect
= true;
794 Value
>>= ReadNumber(1);
795 NumberCorrect
= true;
812 Value
= ReadNumber(4);
813 NumberCorrect
= false;
817 if (First
== '=' && CallLevel
== HIGHEST
) continue;
826 if (Word == "enum" || Word == "bitenum") {
827 if (CallLevel != HIGHEST || PreserveTerminator) Xungc(';', Buffer);
833 int Bits
= ReadNumber();
835 int Red
= ReadNumber();
836 int Green
= ReadNumber();
837 int Blue
= ReadNumber();
838 Value
= MakeRGB16(Red
, Green
, Blue
);
839 } else if (Bits
== 24) {
840 int Red
= ReadNumber();
841 int Green
= ReadNumber();
842 int Blue
= ReadNumber();
843 Value
= MakeRGB24(Red
, Green
, Blue
);
845 ABORT("Illegal RGB bit size %d in file %s, line %d!", Bits
, FileName
.CStr(), TellLine());
847 NumberCorrect
= true;
850 if (Word
== "true" || Word
== "tan") {
852 NumberCorrect
= true;
855 if (Word
== "false" || Word
== "ona") {
857 NumberCorrect
= true;
861 valuemap::const_iterator Iterator
= ValueMap
->find(Word
);
862 if (Iterator
!= ValueMap
->end()) {
863 Value
= Iterator
->second
;
864 NumberCorrect
= true;
868 ABORT("Odd numeric value \"%s\" encountered in file %s, line %d!",
869 Word
.CStr(), FileName
.CStr(), TellLine());
874 festring
inputfile::ReadCode (truth AbortOnEOF
) {
879 for (char Char
= Xgetc(Buffer
); !Xfeof(Buffer
); Char
= Xgetc(Buffer
)) {
880 //fprintf(stderr, "char: [%c]; inString: %d; sqLevel: %d\n", (Char < 32 || Char > 126 ? '?' : Char), inString, sqLevel);
883 if (Char
== inString
) {
885 } else if (Char
== '\\') {
886 if (Xfeof(Buffer
)) break;
887 Char
= Xgetc(Buffer
);
894 } else if (Char
== ']') {
895 if (--sqLevel
== 0) break;
897 } else if (Char
== '/') {
898 if (Xfeof(Buffer
)) { res
<< Char
; break; }
899 switch ((Char
= Xgetc(Buffer
))) {
900 case '/': // eol comment
901 while (!Xfeof(Buffer
)) if (Xgetc(Buffer
) == '\n') break;
903 case '*': // c-like comment
904 while (!Xfeof(Buffer
)) {
905 if (Xgetc(Buffer
) == '*') {
906 if (Xfeof(Buffer
)) break;
907 if (Xgetc(Buffer
) == '/') break;
916 } else if (Char
== '"' || Char
== '\'') {
924 if (AbortOnEOF
&& Xfeof(Buffer
)) ABORT("Unexpected end of file %s!", FileName
.CStr());
929 sLong
inputfile::ReadNumber (int CallLevel
, truth PreserveTerminator
) {
931 truth isString
= false;
932 ReadNumberIntr(CallLevel
, &num
, &isString
, false, PreserveTerminator
);
937 festring
inputfile::ReadStringOrNumber (sLong
*num
, truth
*isString
, truth PreserveTerminator
) {
938 return ReadNumberIntr(0xFF, num
, isString
, true, PreserveTerminator
);
942 v2
inputfile::ReadVector2d () {
944 Vector
.X
= ReadNumber();
945 Vector
.Y
= ReadNumber();
950 rect
inputfile::ReadRect () {
952 Rect
.X1
= ReadNumber();
953 Rect
.Y1
= ReadNumber();
954 Rect
.X2
= ReadNumber();
955 Rect
.Y2
= ReadNumber();
960 outputfile
&operator << (outputfile
&SaveFile
, cfestring
&String
) {
961 uShort Length
= String
.GetSize();
963 if (Length
) SaveFile
.Write(String
.CStr(), Length
);
968 inputfile
&operator >> (inputfile
&SaveFile
, festring
&String
) {
969 char *RealBuffer
, StackBuffer
[1024];
972 RealBuffer
= Length
< 1024 ? StackBuffer
: new char[Length
+1];
975 SaveFile
.Read(RealBuffer
, Length
);
976 RealBuffer
[Length
] = 0;
977 String
<< RealBuffer
;
979 if (Length
>= 1024) delete [] RealBuffer
;
984 outputfile
&operator << (outputfile
&SaveFile
, cchar
*String
) {
985 uShort Length
= String
? strlen(String
) : 0;
987 if (Length
) SaveFile
.Write(String
, Length
);
992 inputfile
&operator >> (inputfile
&SaveFile
, char *&String
) {
996 String
= new char[Length
+1];
997 SaveFile
.Read(String
, Length
);
1006 void ReadData (festring
&String
, inputfile
&SaveFile
) {
1007 SaveFile
.ReadWord(String
);
1008 if (String
== "=") SaveFile
.ReadWord(String
);
1009 SaveFile
.ReadWord();
1013 void ReadData (fearray
<sLong
> &Array
, inputfile
&SaveFile
) {
1016 SaveFile
.ReadWord(Word
);
1017 //if (Word == "=") SaveFile.ReadWord(Word);
1020 Array
.Data
[0] = SaveFile
.ReadNumber();
1023 if (Word
!= "=") ABORT("Array syntax error: '=' or '==' expected in file %s, line %d!", SaveFile
.GetFileName().CStr(), SaveFile
.TellLine());
1024 SaveFile
.ReadWord(Word
);
1025 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TellLine());
1026 fearray
<sLong
>::sizetype Size
= SaveFile
.ReadNumber();
1027 Array
.Allocate(Size
);
1028 for (fearray
<sLong
>::sizetype c
= 0; c
< Size
; ++c
) Array
.Data
[c
] = SaveFile
.ReadNumber();
1029 if (SaveFile
.ReadWord() != "}") ABORT("Illegal array terminator \"%s\" encountered in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TellLine());
1033 void ReadData (fearray
<festring
> &Array
, inputfile
&SaveFile
) {
1036 SaveFile
.ReadWord(Word
);
1037 //if (Word == "=") SaveFile.ReadWord(Word);
1040 SaveFile
.ReadWord(Array
.Data
[0]);
1041 if (SaveFile
.ReadWord() != ";") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TellLine());
1044 if (Word
!= "=") ABORT("Array syntax error: '=' or '==' expected in file %s, line %d!", SaveFile
.GetFileName().CStr(), SaveFile
.TellLine());
1045 SaveFile
.ReadWord(Word
);
1046 if (Word
!= "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TellLine());
1047 fearray
<festring
>::sizetype Size
= SaveFile
.ReadNumber();
1048 Array
.Allocate(Size
);
1049 for (fearray
<festring
>::sizetype c
= 0; c
< Size
; ++c
) {
1050 SaveFile
.ReadWord(Array
.Data
[c
]);
1051 SaveFile
.ReadWord(Word
);
1052 if (Word
!= "," && Word
!= ";") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TellLine());
1054 if (SaveFile
.ReadWord() != "}") ABORT("Illegal array terminator \"%s\" encountered in file %s, line %d!", Word
.CStr(), SaveFile
.GetFileName().CStr(), SaveFile
.TellLine());
1058 feuLong
inputfile::TellLineOfPos (sLong Pos
) {
1060 sLong BackupPos
= TellPos();
1062 while (TellPos() != Pos
) { if (Xgetc(Buffer
) == '\n') ++Line
; }
1063 if (TellPos() != BackupPos
) SeekPosBegin(BackupPos
);
1068 ////////////////////////////////////////////////////////////////////////////////
1070 meminputfile::meminputfile (cfestring
&str
, const valuemap
*ValueMap
) :
1071 inputfile("", ValueMap
, false),
1078 char nbuf
[MAX_PATH
+1], tfn
[MAX_PATH
+1];
1079 GetTempPath(MAX_PATH
, nbuf
);
1080 GetTempFileName(nbuf
, "ivan", 0, tfn
);
1082 FILE *fl
= fopen(tfn
, "wb");
1083 fwrite(str
.CStr(), str
.GetSize(), 1, fl
);
1085 Buffer
= gzopen(tfn
, "rb");
1090 strcpy(fname
, "/tmp/ivan.XXXXXX");
1091 fd
= mkstemp(fname
);
1093 //fprintf(stderr, "[%s]\n", tfname.CStr());
1094 if (fd
< 0) ABORT("Can't create temporary file!");
1095 write(fd
, str
.CStr(), str
.GetSize());
1097 Buffer
= gzopen(fname
, "rb");
1099 FileName
= "<memory>";
1103 meminputfile::~meminputfile () {
1106 unlink(tfname
.CStr());
1113 meminputfile::meminputfile (cfestring
&str
, const valuemap
*ValueMap
) :
1114 inputfile("", ValueMap
, false),
1121 char nbuf
[MAX_PATH
+1], tfn
[MAX_PATH
+1];
1122 GetTempPath(MAX_PATH
, nbuf
);
1123 GetTempFileName(nbuf
, "ivan", 0, tfn
);
1125 FILE *fl
= fopen(tfn
, "wb");
1126 fwrite(str
.CStr(), str
.GetSize(), 1, fl
);
1128 Buffer
= fopen(tfn
, "rb");
1130 bufSize
= str
.GetSize();
1131 buf
= (char *)calloc(1, bufSize
+1);
1132 memmove(buf
, str
.CStr(), bufSize
);
1133 Buffer
= fmemopen(buf
, bufSize
, "rb");
1135 FileName
= "<memory>";
1139 meminputfile::~meminputfile () {
1143 DeleteFile(tfname
.CStr());