00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
#include <time.h>
00046
#include <sys/stat.h>
00047
00048
#if !defined(_MSC_VER) && !defined(_MINGW_)
00049
#include <sys/wait.h>
00050
#endif
00051
00052
00053
#ifdef WIN32
00054
#include <direct.h>
00055
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
00056
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
00057
00058
#define PL_MAX_FILE_SIZE 1000
00059
#define chdir _chdir
00060
#define stat _stat
00061
#include <Windows.h>
00062
00063
#else
00064
#include <dirent.h>
00065
#include <unistd.h>
00066
00067
#endif // WIN32
00068
00069
00070
#include <strstream>
00071
00072
#include "fileutils.h"
00073
#include <plearn/base/stringutils.h>
00074
#include <plearn/base/plerror.h>
00075
#include <plearn/math/pl_math.h>
00076
#include "PStream.h"
00077
00078
namespace PLearn {
00079
using namespace std;
00080
00081 string getcwd()
00082 {
00083
char buf[2000];
00084
00085
00086
00087
#ifdef WIN32
00088
_getcwd(buf, 2000);
00089
00090
for (
int i = 0; buf[i] != 0 && i < 2000; ++i) {
00091
if (buf[i] ==
'\\')
00092 buf[i] =
'/';
00093 }
00094
#else
00095
::getcwd(buf, 2000);
00096
#endif
00097
return string(buf);
00098 }
00099
00100 int chdir(
const string& path)
00101 {
00102
int status = ::chdir(path.c_str());
00103
if (status!=0)
00104
PLERROR(
"Could not chdir to %s\n",path.c_str());
00105
return status;
00106 }
00107
00108 string abspath(
const string& path)
00109 {
00110
string cwd =
getcwd();
00111
string result;
00112
if(
isdir(path))
00113 {
00114
chdir(path);
00115 result =
append_slash(
getcwd());
00116
chdir(cwd);
00117 }
00118
else
00119 {
00120
string dirname =
extract_directory(path);
00121
string filename =
extract_filename(path);
00122
chdir(dirname);
00123 result =
append_slash(
getcwd()) + filename;
00124
chdir(cwd);
00125 }
00126
return result;
00127 }
00128
00129 bool pathexists(
const string& path)
00130 {
00131
struct stat s;
00132
00133
int status = stat(path.c_str(),&s);
00134
if(status!=0)
00135
return false;
00136
return S_ISDIR(s.st_mode) | S_ISREG(s.st_mode);
00137 }
00138
00139 bool isdir(
const string& path)
00140 {
00141
#if defined(_MINGW_) || defined(WIN32)
00142
if (path[path.size()-1] ==
':')
00143
return true;
00144
#endif
00145
00146
struct stat s;
00147
int status = stat(path.c_str(),&s);
00148
if(status!=0)
00149
return false;
00150
return S_ISDIR(s.st_mode);
00151 }
00152
00153 bool isfile(
const string& path)
00154 {
00155
struct stat s;
00156
int status = stat(path.c_str(),&s);
00157
if(status!=0)
00158
return false;
00159
return S_ISREG(s.st_mode);
00160 }
00161
00162 time_t
mtime(
const string& path)
00163 {
00164
struct stat s;
00165
int status = stat(path.c_str(),&s);
00166
if(status!=0)
00167
return 0;
00168
else
00169
return s.st_mtime;
00170 }
00171
00172
00173
00174
00175 vector<string> lsdir(
const string& dirpath)
00176 {
00177
vector<string> list;
00178
00179
#ifdef WIN32
00180
00181
00182
00183 WIN32_FIND_DATA fileData;
00184 HANDLE hSearch;
00185
bool fFinished =
false;
00186
char oldpath[PL_MAX_FILE_SIZE];
00187
00188 GetCurrentDirectory(FILENAME_MAX, oldpath);
00189
00190
if (! SetCurrentDirectory(dirpath.c_str()) )
00191 {
00192 SetCurrentDirectory(oldpath);
00193
PLERROR(
"In lsdir: could not open directory %s",dirpath.c_str());
00194 }
00195
00196 hSearch = FindFirstFile(
"*", &fileData);
00197
if (hSearch == INVALID_HANDLE_VALUE)
00198 {
00199 SetCurrentDirectory(oldpath);
00200
PLERROR(
"In lsdir: could not open directory %s. Invalid Handle Value.",dirpath.c_str());
00201 }
00202
00203
while (!fFinished)
00204 {
00205
string s = fileData.cFileName;
00206
if(s!=
"." && s!=
"..")
00207 list.push_back(s);
00208
00209
if (!FindNextFile(hSearch, &fileData))
00210 {
00211
if (GetLastError() == ERROR_NO_MORE_FILES)
00212 {
00213 fFinished =
true;
00214 }
00215
else
00216 {
00217 printf(
"Couldn't find next file.");
00218
00219 }
00220 }
00221 }
00222
00223 SetCurrentDirectory(oldpath);
00224
00225
#else
00226
00227 DIR* d = opendir(dirpath.c_str());
00228
if(!d)
00229
PLERROR(
"In lsdir: could not open directory %s",dirpath.c_str());
00230
struct dirent* dent;
00231
while( (dent = readdir(d)) != 0)
00232 {
00233
string s = dent->d_name;
00234
if(s!=
"." && s!=
"..")
00235 list.push_back(s);
00236 }
00237 closedir(d);
00238
#endif
00239
return list;
00240 }
00241
00242
00243
00244 vector<string> lsdir_fullpath(
const string& dirpath)
00245 {
return addprefix(
remove_trailing_slash(dirpath)+
slash,
lsdir(dirpath)); }
00246
00247
00248
00249
00250
00251
00252 bool force_mkdir(
const string& dirname)
00253 {
00254
string path =
remove_trailing_slash(dirname);
00255
if(
isdir(path))
00256
return true;
00257
00258
#if !defined(_MINGW_) && !defined(WIN32)
00259
mode_t
mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
00260
#endif
00261
string pathpart;
00262
for (size_t pos = 1; pos != string::npos;)
00263 {
00264
00265 ++pos;
00266 pos = path.find(
slash, pos);
00267
if( pos != string::npos )
00268 pathpart = path.substr(0, pos);
00269
else
00270 pathpart = path;
00271
00272
if(!
isdir(pathpart))
00273 {
00274
#if !defined(_MINGW_) && !defined(WIN32)
00275
if(mkdir(pathpart.c_str(),
mode)!=0)
00276
#else
00277
if(mkdir(pathpart.c_str())!=0)
00278
#endif
00279
return false;
00280 }
00281 }
00282
00283
return true;
00284 }
00285
00286 void force_mkdir_for_file(
const string& filepath)
00287 {
00288
string dirpath =
extract_directory(filepath);
00289
if(!
force_mkdir(dirpath))
00290
PLERROR(
"force_mkdir(%s) failed",dirpath.c_str());
00291 }
00292
00293
00294
00295
00296 bool force_rmdir(
const string& dirname)
00297 {
00298 system(
"pwd");
00299
if(!
isdir(dirname))
00300
return false;
00301
vector<string> entries =
lsdir_fullpath(dirname);
00302
vector<string>::const_iterator it = entries.begin();
00303
while(it!=entries.end())
00304 {
00305
if(
isdir(*it))
00306 {
00307
if(!
force_rmdir(*it))
00308
return false;
00309 }
00310
else
00311 {
00312
if(unlink(it->c_str())!=0)
00313
return false;
00314 }
00315 ++it;
00316 }
00317
if(rmdir(dirname.c_str())!=0)
00318
return false;
00319
return true;
00320
00321 }
00322
00323 long filesize(
const string& filename)
00324 {
00325 FILE *f = fopen(filename.c_str(),
"r");
00326
long fsize;
00327
if (!f)
00328
PLERROR(
"In filesize(const string& filename): cannot open file %s.",filename.c_str());
00329 fseek(f,0,SEEK_END);
00330 fsize = ftell(f);
00331 fclose(f);
00332
return fsize;
00333 }
00334
00335 string loadFileAsString(
const string& filepath)
00336 {
00337
long l =
filesize(filepath);
00338
char* buf =
new char[l];
00339 ifstream in(filepath.c_str());
00340
if(in.bad())
00341
PLERROR(
"Cannot load file %s",filepath.c_str());
00342 in.read(buf, l);
00343
string text(buf,l);
00344
delete[] buf;
00345
return text;
00346 }
00347
00348 void saveStringInFile(
const string& filepath,
const string& text)
00349 {
00350
force_mkdir_for_file(filepath);
00351 ofstream out(filepath.c_str());
00352
if(!out)
00353
PLERROR(
"Couldn't open file %s for writing", filepath.c_str());
00354 out << text;
00355 }
00356
00357
00358 void cp(
const string& srcpath,
const string& destpath)
00359 {
00360
string command =
"\\cp -R " + srcpath +
" " + destpath;
00361 system(command.c_str());
00362 }
00363
00364 void rm(
const string& file)
00365 {
00366
#ifdef WIN32
00367
00368
if ( !DeleteFile(file.c_str()) )
00369 {
00370 DWORD errorCode = GetLastError();
00371 LPVOID lpMsgBuf;
00372 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
00373 FORMAT_MESSAGE_FROM_SYSTEM,
00374 NULL, errorCode,
00375 MAKELANGID(LANG_NEUTRAL,
00376 SUBLANG_DEFAULT),
00377 (LPTSTR) &lpMsgBuf, 0,
00378 NULL );
00379
00380
00381
00382 LocalFree( lpMsgBuf );
00383 }
00384
#else
00385
string command =
"\\rm -rf " + file;
00386 system(command.c_str());
00387
#endif
00388
}
00389
00390 void mv(
const string& file)
00391 {
00392
string command =
"\\mv " + file;
00393 system(command.c_str());
00394 }
00395
00396 void mvforce(
const string& file)
00397 {
00398
string command =
"\\mv -f " + file;
00399 system(command.c_str());
00400 }
00401
00402
00405 void readWhileMatches(istream& in,
const string& s){
00406
int i = 0;
00407
int c;
00408 c = in.get();
00409
int n = (
int)s.length();
00410
while(c!=EOF)
00411 {
00412
if(s[i]!=c)
00413 {
00414 in.unget();
00415
PLERROR(
"In readWhileMatches. Failure while matching %s: "
00416
"at position %d expected a '%c', but read a '%c'",s.c_str(),i,s[i],c);
00417 }
00418 ++i;
00419
if(i==n)
00420
return;
00421 c = in.get();
00422 }
00423
PLERROR(
"In readWhileMatches, met EOF while matching %s", s.c_str());
00424 }
00425
00426
00427 void skipRestOfLine(istream& in)
00428 {
00429
int c=in.get();
00430
while(c!=
'\n' && c!=EOF)
00431 c=in.get();
00432 }
00433
00434 void skipBlanksAndComments(istream& in)
00435 {
00436
int c = in.get();
00437
while(c!=EOF)
00438 {
00439
if(!isspace(c))
00440 {
00441
if(c==
'#')
00442
skipRestOfLine(in);
00443
else
00444
break;
00445 }
00446 c = in.get();
00447 }
00448 in.unget();
00449 }
00450
00451 void getNextNonBlankLine(istream& in,
string& line)
00452 {
00453
for(;;)
00454 {
00455 getline(in,line);
00456
if(in.eof())
00457 {
00458 line=
"";
00459
return;
00460 }
00461
int l = (
int)line.length();
00462
for(
int i=0; i<l; i++)
00463 {
00464
char c = line[i];
00465
if(!isspace(c) && c!=
'#')
00466
return;
00467 }
00468 }
00469 }
00470
00471 int countNonBlankLinesOfFile(
const string& filename)
00472 {
00473 ifstream in(filename.c_str());
00474
if(!in)
00475
PLERROR(
"Could not open file %s for reading",filename.c_str());
00476
int count = 0;
00477
int c = in.get();
00478
while(c!=EOF)
00479 {
00480
while(c==
'\n' || c==
' ' || c==
'\t' || c==
'\r')
00481 c = in.get();
00482
if(c!=
'\n' && c!=
'#' && c!=EOF)
00483 ++
count;
00484
while(c!=
'\n' && c!=EOF)
00485 c = in.get();
00486 c = in.get();
00487 }
00488
return count;
00489 }
00490
00491 int smartReadUntilNext(istream& in,
string stoppingsymbols,
string& characters_read,
bool ignore_brackets)
00492 {
00493
PStream pin(&in);
00494
return pin.
smartReadUntilNext(stoppingsymbols, characters_read, ignore_brackets);
00495 }
00496
00498 string newFilename(
const string directory,
const string prefix,
bool is_directory)
00499 {
00500
#if defined(_MINGW_) || defined(WIN32)
00501
PLERROR(
"This call is not yet implemented for this platform");
00502
return "";
00503
#else
00504
string tmpdirname =
remove_trailing_slash(directory);
00505
int length = tmpdirname.length()+1+prefix.length()+6+1;
00506
char* tmpfilename =
new char[length];
00507
if (tmpdirname==
"")
00508 sprintf(tmpfilename,
"%sXXXXXX",prefix.c_str());
00509
else
00510 sprintf(tmpfilename,
"%s/%sXXXXXX",tmpdirname.c_str(),prefix.c_str());
00511 mkstemp(tmpfilename);
00512
if (is_directory) {
00513
00514 std::remove(tmpfilename);
00515
00516 mode_t
mode = (S_IRUSR|S_IWUSR|S_IXUSR) | S_IRWXG | S_IRWXO;
00517 mkdir(tmpfilename,
mode);
00518 }
00519
if(!tmpfilename)
00520
PLERROR(
"In newFilename : could not make a new temporary filename");
00521
return tmpfilename;
00522
#endif
00523
}
00524
00525 string makeFileNameValid(
const string& path)
00526 {
00527
string dirname =
extract_directory(path);
00528
string filename =
extract_filename_without_extension(path);
00529
string ext=
extract_extension(path);
00530
string ret=path;
00531
if(filename.length() + ext.length() > 256)
00532 {
00533
int j= 0;
00534
string rest= filename.substr(256-ext.length()-12);
00535
do
00536 {
00537
unsigned int n= j++;
00538
for(
unsigned int i= 0; i < rest.length(); ++i)
00539 {
00540
int m=0;
00541
switch(i%4)
00542 {
00543
case 3: m= 1;
break;
00544
case 2: m= 256;
break;
00545
case 1: m= 65536;
break;
00546
case 0: m= 256*65536;
break;
00547 }
00548 n+= m*(
unsigned char)rest[i];
00549 }
00550 filename.resize(256-ext.length()-12);
00551 filename+=
"-" +
tostring(n);
00552 }
while(
pathexists(dirname + filename + ext));
00553
PLWARNING(
"makeFileNameValid: Filename '%s' changed to '%s'.",
00554 path.c_str(), (dirname + filename + ext).c_str());
00555 ret= dirname + filename + ext;
00556 }
00557
00558
00559
char illegal[]=
"*?'\"${}[]@ ,()";
00560
for(
int i=0;i<(
signed)ret.size();i++)
00561
for(
int j=0;j<15;j++)
00562
if(ret[i]==illegal[j])
00563 ret[i]=
'_';
00564
return ret;
00565 }
00566
00567 void touch(
const string& file)
00568 {
00569
string command =
"touch "+file;
00570 system(command.c_str());
00571 }
00572
00573 string makeExplicitPath(
const string& filename)
00574 {
00575
string fn =
removeblanks(filename);
00576
if(fn!=
"" && fn[0]!=
slash_char && fn[0]!=
'.')
00577 {
00578
string dot =
".";
00579
return dot+
slash+fn;
00580 }
00581
return fn;
00582 }
00583
00584
00585 string readFileAndMacroProcess(
const string& filepath, map<string, string>& variables)
00586 {
00587
00588
const char* OldVariables[] = {
00589
"FILEPATH",
"DIRPATH",
"FILENAME",
"FILEBASE",
"FILEEXT",
"DATE",
"TIME",
"DATETIME"
00590 };
00591
const int num_old =
sizeof(OldVariables) /
sizeof(OldVariables[0]);
00592 map<string,string> old_vars;
00593
for (
int i=0; i<num_old; ++i)
00594 old_vars[OldVariables[i]] = variables[OldVariables[i]];
00595
00596
00597
string fpath =
abspath(filepath);
00598 variables[
"FILEPATH"] = fpath;
00599 variables[
"DIRPATH"] =
remove_trailing_slash(
extract_directory(fpath));
00600 variables[
"FILENAME"] =
extract_filename(fpath);
00601 variables[
"FILEBASE"] =
remove_extension(
extract_filename(fpath));
00602 variables[
"FILEEXT"] =
extract_extension(fpath);
00603 variables[
"HOME"] = getenv(
"HOME");
00604
00605
00606 time_t curtime = time(NULL);
00607
struct tm *broken_down_time = localtime(&curtime);
00608
const int SIZE = 100;
00609
char time_buffer[SIZE];
00610 strftime(time_buffer,SIZE,
"%Y%m%d:%H%M%S",broken_down_time);
00611 variables[
"DATETIME"] = time_buffer;
00612 strftime(time_buffer,SIZE,
"%Y%m%d",broken_down_time);
00613 variables[
"DATE"] = time_buffer;
00614 strftime(time_buffer,SIZE,
"%H%M%S",broken_down_time);
00615 variables[
"TIME"] = time_buffer;
00616
00617
00618 ifstream in(fpath.c_str());
00619
if(!in)
00620
PLERROR(
"In readFileAndMacroProcess, could not open file %s for reading", fpath.c_str());
00621
string text =
readAndMacroProcess(in, variables);
00622
00623
00624
for (
int i=0; i<num_old; ++i)
00625 variables[OldVariables[i]] = old_vars[OldVariables[i]];
00626
00627
return text;
00628 }
00629
00630 string readAndMacroProcess(istream& in, map<string, string>& variables)
00631 {
00632
string text;
00633
bool inside_a_quoted_string=
false;
00634
int c=EOF,last_c=EOF;
00635
while(in)
00636 {
00637 last_c = c;
00638 c = in.get();
00639
if (last_c!=
'\\' && c==
'"')
00640 inside_a_quoted_string = !inside_a_quoted_string;
00641
00642
if(!inside_a_quoted_string && c==
'#')
00643 {
00644
while(c!=EOF && c!=
'\n' && c!=
'\r')
00645 c = in.get();
00646 }
00647
00648
if(c==EOF)
00649
break;
00650
else if(c!=
'$')
00651 text += c;
00652
else
00653 {
00654
int c = in.peek();
00655
switch(c)
00656 {
00657
case '{':
00658 {
00659
string varname;
00660 in.get();
00661
smartReadUntilNext(in,
"}", varname,
true);
00662
00663 istrstream varname_stream(varname.c_str());
00664 varname =
readAndMacroProcess(varname_stream, variables);
00665 varname =
removeblanks(varname);
00666 map<string, string>::iterator it = variables.find(varname);
00667
if(it==variables.end())
00668
PLERROR(
"Macro variable ${%s} undefined", varname.c_str());
00669 istrstream varin(it->second.c_str());
00670 text +=
readAndMacroProcess(varin, variables);
00671 }
00672
break;
00673
00674
case 'C':
00675 {
00676
string expr;
00677
readWhileMatches(in,
"CHAR");
00678
bool syntax_ok =
true;
00679
int c = in.get();
00680
if(c ==
'{')
00681
smartReadUntilNext(in,
"}", expr,
true);
00682
else
00683 syntax_ok =
false;
00684
if (!syntax_ok)
00685
PLERROR(
"$CHAR syntax is: $CHAR{expr}");
00686 istrstream expr_stream(expr.c_str());
00687
char ch = (
char)
toint(
readAndMacroProcess(expr_stream, variables));
00688 text += ch;
00689 }
00690
break;
00691
00692
case 'D':
00693 {
00694
int next = in.get();
00695 next = in.peek();
00696
switch(next) {
00697
00698
case 'E':
00699 {
00700
string varname;
00701
string vardef;
00702
readWhileMatches(in,
"EFINE{");
00703 getline(in,varname,
'}');
00704 varname =
removeblanks(varname);
00705
skipBlanksAndComments(in);
00706
if(in.get()!=
'{')
00707
PLERROR(
"Bad syntax in .plearn DEFINE macro: correct syntax is $DEFINE{name}{definition}");
00708
smartReadUntilNext(in,
"}", vardef,
true);
00709 variables[varname] = vardef;
00710 }
00711
break;
00712
00713
case 'I':
00714 {
00715
string expr1, expr2;
00716
readWhileMatches(in,
"IVIDE");
00717
bool syntax_ok =
true;
00718
int c = in.get();
00719
if (syntax_ok) {
00720
if(c ==
'{')
00721
smartReadUntilNext(in,
"}", expr1,
true);
00722
else
00723 syntax_ok =
false;
00724 }
00725
if (syntax_ok) {
00726 c = in.get();
00727
if(c ==
'{')
00728
smartReadUntilNext(in,
"}", expr2,
true);
00729
else
00730 syntax_ok =
false;
00731 }
00732
if (!syntax_ok)
00733
PLERROR(
"$DIVIDE syntax is: $DIVIDE{expr1}{expr2}");
00734 istrstream expr1_stream(expr1.c_str());
00735 istrstream expr2_stream(expr2.c_str());
00736
string expr1_eval =
readAndMacroProcess(expr1_stream, variables);
00737
string expr2_eval =
readAndMacroProcess(expr2_stream, variables);
00738
real e1, e2;
00739
if (!
pl_isnumber(expr1_eval, &e1) || !
pl_isnumber(expr2_eval, &e2)) {
00740
PLERROR(
"In $DIVIDE{expr1}{expr2}, either 'expr1' or 'expr2' is not a number");
00741 }
00742 text +=
tostring(e1 / e2);
00743 }
00744
break;
00745
00746 }
00747
break;
00748 }
00749
00750
case 'E':
00751 {
00752
int next = in.get();
00753 next = in.peek();
00754
switch(next) {
00755
00756
case 'C':
00757 {
00758
string expr;
00759
readWhileMatches(in,
"CHO");
00760
bool syntax_ok =
true;
00761
int c = in.get();
00762
if(c ==
'{')
00763
smartReadUntilNext(in,
"}", expr,
true);
00764
else
00765 syntax_ok =
false;
00766
if (!syntax_ok)
00767
PLERROR(
"$ECHO syntax is: $ECHO{expr}");
00768 istrstream expr_stream(expr.c_str());
00769 cout <<
readAndMacroProcess(expr_stream, variables) <<
endl;
00770 }
00771
break;
00772
00773
case 'V':
00774 {
00775
string expr;
00776
readWhileMatches(in,
"VALUATE");
00777
bool syntax_ok =
true;
00778
int c = in.get();
00779
if(c ==
'{')
00780
smartReadUntilNext(in,
"}", expr,
true);
00781
else
00782 syntax_ok =
false;
00783
if (!syntax_ok)
00784
PLERROR(
"$EVALUATE syntax is: $EVALUATE{varname}");
00785 istrstream expr_stream(expr.c_str());
00786
string varname =
readAndMacroProcess(expr_stream, variables);
00787
string to_evaluate = variables[varname];
00788 istrstream to_evaluate_stream(to_evaluate.c_str());
00789
string evaluated =
readAndMacroProcess(to_evaluate_stream, variables);
00790 variables[varname] = evaluated;
00791 }
00792
break;
00793 }
00794
break;
00795 }
00796
00797
case 'I':
00798 {
00799
int next = in.get();
00800 next = in.peek();
00801
switch(next) {
00802
00803
case 'F':
00804 {
00805
string cond, expr_cond_true, expr_cond_false, expr_evaluated;
00806
readWhileMatches(in,
"F");
00807
bool syntax_ok =
true;
00808
int c = in.get();
00809
if(c ==
'{')
00810
smartReadUntilNext(in,
"}", cond,
true);
00811
else
00812 syntax_ok =
false;
00813
if (syntax_ok) {
00814 c = in.get();
00815
if(c ==
'{')
00816
smartReadUntilNext(in,
"}", expr_cond_true,
true);
00817
else
00818 syntax_ok =
false;
00819 }
00820
if (syntax_ok) {
00821 c = in.get();
00822
if(c ==
'{')
00823
smartReadUntilNext(in,
"}", expr_cond_false,
true);
00824
else
00825 syntax_ok =
false;
00826 }
00827
if (!syntax_ok)
00828
PLERROR(
"$IF syntax is: $IF{cond}{expr_cond_true}{expr_cond_false}");
00829
00830 istrstream cond_stream(cond.c_str());
00831
string evaluate_cond =
readAndMacroProcess(cond_stream, variables);
00832
if (evaluate_cond ==
"1" ) {
00833 expr_evaluated = expr_cond_true;
00834 }
else if (evaluate_cond ==
"0") {
00835 expr_evaluated = expr_cond_false;
00836 }
else {
00837
PLERROR(
"$IF condition should be 0 or 1, but is %s", evaluate_cond.c_str());
00838 }
00839 istrstream expr_stream(expr_evaluated.c_str());
00840 text +=
readAndMacroProcess(expr_stream, variables);
00841 }
00842
break;
00843
00844
case 'N':
00845 {
00846
int next = in.get();
00847 next = in.peek();
00848
switch(next) {
00849
00850
case 'C':
00851 {
00852
string includefilepath;
00853
readWhileMatches(in,
"CLUDE");
00854
int c = in.get();
00855
if(c==
'<')
00856
smartReadUntilNext(in,
">", includefilepath,
true);
00857
else if(c==
'{')
00858
smartReadUntilNext(in,
"}", includefilepath,
true);
00859
else
00860
PLERROR(
"$INCLUDE must be followed immediately by a { or <");
00861 istringstream pathin(includefilepath);
00862 includefilepath =
readAndMacroProcess(pathin,variables);
00863 includefilepath =
removeblanks(includefilepath);
00864
string dirname =
extract_directory(includefilepath);
00865
string filename =
extract_filename(includefilepath);
00866
string olddir =
getcwd();
00867
chdir(dirname);
00868 text +=
readFileAndMacroProcess(filename, variables);
00869
chdir(olddir);
00870 }
00871
break;
00872
00873
case 'T':
00874 {
00875
string expr;
00876
readWhileMatches(in,
"T");
00877
bool syntax_ok =
true;
00878
int c = in.get();
00879
if(c ==
'{')
00880
smartReadUntilNext(in,
"}", expr,
true);
00881
else
00882 syntax_ok =
false;
00883
if (!syntax_ok)
00884
PLERROR(
"$INT syntax is: $INT{expr}");
00885 istrstream expr_stream(expr.c_str());
00886
string expr_eval =
readAndMacroProcess(expr_stream, variables);
00887
real e;
00888
if (!
pl_isnumber(expr_eval, &e)) {
00889
PLERROR(
"In $INT{expr}, 'expr' is not a number");
00890 }
00891 text +=
tostring(
int(e));
00892 }
00893 }
00894 }
00895
break;
00896
00897
case 'S':
00898 {
00899
00900
int next = in.get();
00901 next = in.peek();
00902
switch(next) {
00903
00904
case 'D':
00905 {
00906
string expr;
00907
readWhileMatches(in,
"DEFINED");
00908
bool syntax_ok =
true;
00909
int c = in.get();
00910
if(c ==
'{')
00911
smartReadUntilNext(in,
"}", expr,
true);
00912
else
00913 syntax_ok =
false;
00914
if (!syntax_ok)
00915
PLERROR(
"$ISDEFINED syntax is: $ISDEFINED{expr}");
00916 istrstream expr_stream(expr.c_str());
00917
string expr_eval =
readAndMacroProcess(expr_stream, variables);
00918 map<string, string>::iterator it = variables.find(expr_eval);
00919
if(it==variables.end()) {
00920
00921 text +=
"0";
00922 }
else {
00923 text +=
"1";
00924 }
00925 }
00926
break;
00927
00928
case 'E':
00929 {
00930
string expr1, expr2;
00931
readWhileMatches(in,
"EQUAL");
00932
bool syntax_ok =
true;
00933
int c = in.get();
00934
if(c ==
'{')
00935
smartReadUntilNext(in,
"}", expr1,
true);
00936
else
00937 syntax_ok =
false;
00938
if (syntax_ok) {
00939 c = in.get();
00940
if(c ==
'{')
00941
smartReadUntilNext(in,
"}", expr2,
true);
00942
else
00943 syntax_ok =
false;
00944 }
00945
if (!syntax_ok)
00946
PLERROR(
"$ISEQUAL syntax is: $ISEQUAL{expr1}{expr2}");
00947 istrstream expr1_stream(expr1.c_str());
00948 istrstream expr2_stream(expr2.c_str());
00949
string expr1_eval =
readAndMacroProcess(expr1_stream, variables);
00950
string expr2_eval =
readAndMacroProcess(expr2_stream, variables);
00951
if (expr1_eval == expr2_eval) {
00952 text +=
"1";
00953 }
else {
00954 text +=
"0";
00955 }
00956 }
00957
break;
00958
00959
case 'H':
00960 {
00961
string expr1, expr2;
00962
readWhileMatches(in,
"HIGHER");
00963
bool syntax_ok =
true;
00964
int c = in.get();
00965
if(c ==
'{')
00966
smartReadUntilNext(in,
"}", expr1,
true);
00967
else
00968 syntax_ok =
false;
00969
if (syntax_ok) {
00970 c = in.get();
00971
if(c ==
'{')
00972
smartReadUntilNext(in,
"}", expr2,
true);
00973
else
00974 syntax_ok =
false;
00975 }
00976
if (!syntax_ok)
00977
PLERROR(
"$ISHIGHER syntax is: $ISHIGHER{expr1}{expr2}");
00978 istrstream expr1_stream(expr1.c_str());
00979 istrstream expr2_stream(expr2.c_str());
00980
string expr1_eval =
readAndMacroProcess(expr1_stream, variables);
00981
string expr2_eval =
readAndMacroProcess(expr2_stream, variables);
00982
real e1, e2;
00983
if (!
pl_isnumber(expr1_eval, &e1) || !
pl_isnumber(expr2_eval, &e2)) {
00984
PLERROR(
"In $ISHIGHER{expr1}{expr2}, either 'expr1' or 'expr2' is not a number");
00985 }
00986
if (e1 > e2) {
00987 text +=
"1";
00988 }
else {
00989 text +=
"0";
00990 }
00991 }
00992
break;
00993 }
00994 }
00995
break;
00996 }
00997 }
00998
break;
00999
01000
case 'M':
01001 {
01002
string expr1, expr2;
01003
readWhileMatches(in,
"MINUS");
01004
bool syntax_ok =
true;
01005
int c = in.get();
01006
if (syntax_ok) {
01007
if(c ==
'{')
01008
smartReadUntilNext(in,
"}", expr1,
true);
01009
else
01010 syntax_ok =
false;
01011 }
01012
if (syntax_ok) {
01013 c = in.get();
01014
if(c ==
'{')
01015
smartReadUntilNext(in,
"}", expr2,
true);
01016
else
01017 syntax_ok =
false;
01018 }
01019
if (!syntax_ok)
01020
PLERROR(
"$MINUS syntax is: $MINUS{expr1}{expr2}");
01021 istrstream expr1_stream(expr1.c_str());
01022 istrstream expr2_stream(expr2.c_str());
01023
string expr1_eval =
readAndMacroProcess(expr1_stream, variables);
01024
string expr2_eval =
readAndMacroProcess(expr2_stream, variables);
01025
real e1, e2;
01026
if (!
pl_isnumber(expr1_eval, &e1) || !
pl_isnumber(expr2_eval, &e2)) {
01027
PLERROR(
"In $MINUS{expr1}{expr2}, either 'expr1' or 'expr2' is not a number");
01028 }
01029 text +=
tostring(e1 - e2);
01030 }
01031
break;
01032
01033
case 'O':
01034 {
01035
string expr1, expr2;
01036
readWhileMatches(in,
"OR");
01037
bool syntax_ok =
true;
01038
int c = in.get();
01039
if (syntax_ok) {
01040
if(c ==
'{')
01041
smartReadUntilNext(in,
"}", expr1,
true);
01042
else
01043 syntax_ok =
false;
01044 }
01045
if (syntax_ok) {
01046 c = in.get();
01047
if(c ==
'{')
01048
smartReadUntilNext(in,
"}", expr2,
true);
01049
else
01050 syntax_ok =
false;
01051 }
01052
if (!syntax_ok)
01053
PLERROR(
"$OR syntax is: $OR{expr1}{expr2}");
01054 istrstream expr1_stream(expr1.c_str());
01055 istrstream expr2_stream(expr2.c_str());
01056
string expr1_eval =
readAndMacroProcess(expr1_stream, variables);
01057
string expr2_eval =
readAndMacroProcess(expr2_stream, variables);
01058
real e1, e2;
01059
if (!
pl_isnumber(expr1_eval, &e1) || !
pl_isnumber(expr2_eval, &e2)) {
01060
PLERROR(
"In $OR{expr1}{expr2}, either 'expr1' or 'expr2' is not a number");
01061 }
01062
int i1 =
toint(expr1_eval);
01063
int i2 =
toint(expr2_eval);
01064
bool is_true = i1 || i2;
01065 text +=
tostring(is_true);
01066 }
01067
break;
01068
01069
case 'P':
01070 {
01071
string expr1, expr2;
01072
readWhileMatches(in,
"PLUS");
01073
bool syntax_ok =
true;
01074
int c = in.get();
01075
if (syntax_ok) {
01076
if(c ==
'{')
01077
smartReadUntilNext(in,
"}", expr1,
true);
01078
else
01079 syntax_ok =
false;
01080 }
01081
if (syntax_ok) {
01082 c = in.get();
01083
if(c ==
'{')
01084
smartReadUntilNext(in,
"}", expr2,
true);
01085
else
01086 syntax_ok =
false;
01087 }
01088
if (!syntax_ok)
01089
PLERROR(
"$PLUS syntax is: $PLUS{expr1}{expr2}");
01090 istrstream expr1_stream(expr1.c_str());
01091 istrstream expr2_stream(expr2.c_str());
01092
string expr1_eval =
readAndMacroProcess(expr1_stream, variables);
01093
string expr2_eval =
readAndMacroProcess(expr2_stream, variables);
01094
real e1, e2;
01095
if (!
pl_isnumber(expr1_eval, &e1) || !
pl_isnumber(expr2_eval, &e2)) {
01096
PLERROR(
"In $PLUS{expr1}{expr2}, either 'expr1' or 'expr2' is not a number");
01097 }
01098 text +=
tostring(e1 + e2);
01099 }
01100
break;
01101
01102
case 'S':
01103 {
01104
string expr, valdef;
01105
vector<string> comp;
01106
vector<string> val;
01107
readWhileMatches(in,
"SWITCH");
01108
bool syntax_ok =
true;
01109
01110
int c = in.get();
01111
if (syntax_ok) {
01112
if(c ==
'{')
01113
smartReadUntilNext(in,
"}", expr,
true);
01114
else
01115 syntax_ok =
false;
01116 }
01117
01118
bool done_parsing =
false;
01119
while (syntax_ok && !done_parsing) {
01120 c =
getAfterSkipBlanksAndComments(in);
01121
string tmp_comp, tmp_val;
01122
if(c ==
'{')
01123
smartReadUntilNext(in,
"}", tmp_comp,
true);
01124
else
01125 syntax_ok =
false;
01126
if (syntax_ok) {
01127 c =
peekAfterSkipBlanksAndComments(in);
01128
if(c ==
'{') {
01129 c =
getAfterSkipBlanksAndComments(in);
01130
smartReadUntilNext(in,
"}", tmp_val,
true);
01131 }
01132
else {
01133
01134 valdef = tmp_comp;
01135 done_parsing =
true;
01136 }
01137 }
01138
if (!done_parsing) {
01139 comp.push_back(tmp_comp);
01140
val.push_back(tmp_val);
01141 }
01142 }
01143
if (!syntax_ok)
01144
PLERROR(
"$SWITCH syntax is: $SWITCH{expr}{comp1}{val1}{comp2}{val2}...{valdef}");
01145 istrstream expr_stream(expr.c_str());
01146
string expr_eval =
readAndMacroProcess(expr_stream, variables);
01147
bool not_done =
true;
01148
for (
unsigned int i = 0; i < comp.size() && not_done; i++) {
01149 istrstream comp_stream(comp[i].
c_str());
01150
string comp_eval =
readAndMacroProcess(comp_stream, variables);
01151
if (expr_eval == comp_eval) {
01152 not_done =
false;
01153 istrstream val_stream(
val[i].
c_str());
01154 text +=
readAndMacroProcess(val_stream, variables);
01155 }
01156 }
01157
if (not_done) {
01158
01159 istrstream val_stream(valdef.c_str());
01160 text +=
readAndMacroProcess(val_stream, variables);
01161 }
01162 }
01163
break;
01164
01165
case 'T':
01166 {
01167
string expr1, expr2;
01168
readWhileMatches(in,
"TIMES");
01169
bool syntax_ok =
true;
01170
int c = in.get();
01171
if (syntax_ok) {
01172
if(c ==
'{')
01173
smartReadUntilNext(in,
"}", expr1,
true);
01174
else
01175 syntax_ok =
false;
01176 }
01177
if (syntax_ok) {
01178 c = in.get();
01179
if(c ==
'{')
01180
smartReadUntilNext(in,
"}", expr2,
true);
01181
else
01182 syntax_ok =
false;
01183 }
01184
if (!syntax_ok)
01185
PLERROR(
"$TIMES syntax is: $TIMES{expr1}{expr2}");
01186 istrstream expr1_stream(expr1.c_str());
01187 istrstream expr2_stream(expr2.c_str());
01188
string expr1_eval =
readAndMacroProcess(expr1_stream, variables);
01189
string expr2_eval =
readAndMacroProcess(expr2_stream, variables);
01190
real e1, e2;
01191
if (!
pl_isnumber(expr1_eval, &e1) || !
pl_isnumber(expr2_eval, &e2)) {
01192
PLERROR(
"In $TIMES{expr1}{expr2}, either 'expr1' or 'expr2' is not a number");
01193 }
01194 text +=
tostring(e1 * e2);
01195 }
01196
break;
01197
01198
case 'U':
01199 {
01200
string expr;
01201
readWhileMatches(in,
"UNDEFINE");
01202
bool syntax_ok =
true;
01203
int c = in.get();
01204
if(c ==
'{')
01205
smartReadUntilNext(in,
"}", expr,
true);
01206
else
01207 syntax_ok =
false;
01208
if (!syntax_ok)
01209
PLERROR(
"$UNDEFINE syntax is: $UNDEFINE{expr}");
01210 istrstream expr_stream(expr.c_str());
01211
string varname =
readAndMacroProcess(expr_stream, variables);
01212
while (variables.count(varname) > 0) {
01213
01214 variables.erase(varname);
01215 }
01216 }
01217
break;
01218
01219
default:
01220
PLERROR(
"In readAndMacroProcess: only supported macro commands are \n"
01221
"${varname}, $CHAR, $DEFINE, $DIVIDE, $ECHO, $EVALUATE, $IF, $INCLUDE, $INT, $ISDEFINED, $ISEQUAL, $ISHIGHER, $MINUS, $PLUS, $OR, $SWITCH, $TIMES, $UNDEFINE."
01222
"But I read $%c !!",c);
01223 }
01224 }
01225 }
01226
01227
01228
01229
return text;
01230 }
01231
01232
#ifdef WIN32
01233
#undef S_ISDIR
01234
#undef S_ISREG
01235
#undef PL_MAX_FILE_SIZE
01236
#undef chdir
01237
#undef stat
01238
#endif
01239
01240 }
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261