|
|
|
#include <inttypes.h>
|
|
|
|
#include "init.h"
|
|
|
|
#include "object.h"
|
|
|
|
#include "globals.h"
|
|
|
|
#include "builtin.h"
|
|
|
|
#include "parser.h"
|
|
|
|
// We can't include lexical.h before grammatical.h, because of strange errors, but grammatical.h only needs definition of yyscan_t
|
|
|
|
#ifndef YY_TYPEDEF_YY_SCANNER_T
|
|
|
|
#define YY_TYPEDEF_YY_SCANNER_T
|
|
|
|
typedef void* yyscan_t;
|
|
|
|
#endif
|
|
|
|
#include "grammatical.h"
|
|
|
|
// definitions for bison-bridge
|
|
|
|
#define YYSTYPE CONFSTYPE
|
|
|
|
#define YYLTYPE CONFLTYPE
|
|
|
|
#include "lexical.h"
|
|
|
|
#undef YYSTYPE
|
|
|
|
#undef YYLTYPE
|
|
|
|
|
|
|
|
int BuildDepTree(DepTree* deptree, UsedType& used) {return deptree->CreateGlobalTree(used);}
|
|
|
|
|
|
|
|
|
|
|
|
int CheckFunctions()
|
|
|
|
{
|
|
|
|
UsedType funcs;
|
|
|
|
|
|
|
|
for(auto& i:G_tosave)
|
|
|
|
{
|
|
|
|
i->UsedFuncs(funcs);
|
|
|
|
for(auto& f:funcs) if(G_funcs.find(f)==G_funcs.end())
|
|
|
|
{
|
|
|
|
COUT(ERROR)<<"Unknown function "<<f<<" in directive save"<<i->Dump()<<std::endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
funcs.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
for(auto& i:G_toprint)
|
|
|
|
{
|
|
|
|
i->UsedFuncs(funcs);
|
|
|
|
for(auto& f:funcs) if(G_funcs.find(f)==G_funcs.end())
|
|
|
|
{
|
|
|
|
COUT(ERROR)<<"Unknown function "<<f<<" in directive print"<<i->Dump()<<std::endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
funcs.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
for(auto& i:G_vars)
|
|
|
|
{
|
|
|
|
i.second->UsedFuncs(funcs);
|
|
|
|
for(auto& f:funcs) if(G_funcs.find(f)==G_funcs.end())
|
|
|
|
{
|
|
|
|
COUT(ERROR)<<"Unknown function "<<f<<" in definition of variable "<<i.first<<std::endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
funcs.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DumpConfig()
|
|
|
|
{
|
|
|
|
for(auto& i: G_vars) COUT(NORMAL)<<i.first<<"="+i.second->Dump()<<";"<<std::endl;
|
|
|
|
for(auto& i: G_tosave) COUT(NORMAL)<<"save"<<i->Dump()<<";"<<std::endl;
|
|
|
|
for(auto& i: G_toprint) COUT(NORMAL)<<"print"<<i->Dump()<<";"<<std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ParseConfigFile(const char* config)
|
|
|
|
{
|
|
|
|
yyscan_t scanner;
|
|
|
|
struct lexical_extra extra;
|
|
|
|
FILE* conffd;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
conffd=fopen(config,"r");
|
|
|
|
if(conffd==0)
|
|
|
|
{
|
|
|
|
COUT(ERROR)<<"Can't open file "<<config<<std::endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
extra.maxinclevel=10;
|
|
|
|
extra.retcode=0;
|
|
|
|
extra.state.inclevel=0;
|
|
|
|
extra.state.curline=1;
|
|
|
|
extra.state.curpos=extra.state.curoffset=0;
|
|
|
|
char* cwd=get_current_dir_name();
|
|
|
|
extra.state.curdir=cwd;
|
|
|
|
free(cwd);
|
|
|
|
extra.ParsePath(config);
|
|
|
|
|
|
|
|
conflex_init_extra(&extra,&scanner);
|
|
|
|
confset_in(conffd,scanner);
|
|
|
|
// {YYSTYPE qqq; while(conflex(&qqq,scanner)>0);}
|
|
|
|
ret=confparse(scanner);
|
|
|
|
conflex_destroy(scanner);
|
|
|
|
fclose(conffd);
|
|
|
|
return ret+extra.retcode;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ParseOptions(int argc, char** argv, struct program_options& options)
|
|
|
|
{
|
|
|
|
int opt=0;
|
|
|
|
const char* optstr="t:hdgiq";
|
|
|
|
|
|
|
|
optind=1;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
opt=getopt(argc,argv,optstr);
|
|
|
|
switch(opt)
|
|
|
|
{
|
|
|
|
case(-1): break;
|
|
|
|
case('t'):{options.threads=atoi(optarg); if(options.threads<1) return 1; else break;}
|
|
|
|
case('h'):{options.help=true; break;}
|
|
|
|
case('d'):{options.dump=true; break;}
|
|
|
|
case('g'):{options.dl=DEBUG; break;}
|
|
|
|
case('i'):{options.dl=INFO; break;}
|
|
|
|
case('q'):{options.dl=WARNING; break;}
|
|
|
|
default: return 1;
|
|
|
|
}
|
|
|
|
} while(-1!=opt);
|
|
|
|
if(optind!=argc-1) return 1;
|
|
|
|
options.config=argv[optind];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int RegisterBuiltinFunctions()
|
|
|
|
{
|
|
|
|
RegisterFunction("ADD",Arifm_Add);
|
|
|
|
RegisterFunction("SUB",Arifm_Sub);
|
|
|
|
RegisterFunction("MUL",Arifm_Mul);
|
|
|
|
RegisterFunction("DIV",Arifm_Div);
|
|
|
|
RegisterFunction("POW",Arifm_Pow);
|
|
|
|
RegisterFunction("POS",Arifm_Pos);
|
|
|
|
RegisterFunction("NEG",Arifm_Neg);
|
|
|
|
|
|
|
|
RegisterFunction("GET",Get<ObjectList>);
|
|
|
|
RegisterFunction("GET",Get<ObjectPair>);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
debug_level SetDebugLevel(debug_level dl)
|
|
|
|
{
|
|
|
|
static debug_level DEBUG_LEVEL=INFO;
|
|
|
|
if(dl==INTERNALREQUEST) return DEBUG_LEVEL;
|
|
|
|
debug_level s=DEBUG_LEVEL;
|
|
|
|
DEBUG_LEVEL=dl;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::ostream& COUT(debug_level dl)
|
|
|
|
{
|
|
|
|
if(dl==ERROR) return std::cerr;
|
|
|
|
if(dl>=SetDebugLevel(INTERNALREQUEST)) std::cout.clear();
|
|
|
|
else std::cout.setstate(std::cout.failbit);
|
|
|
|
return std::cout;
|
|
|
|
}
|