// This file is a part of the Framsticks GDK library. // Copyright (C) 2002-2011 Szymon Ulatowski. See LICENSE.txt for details. // Refer to http://www.framsticks.com/ for further information. #include "multiparamload.h" #include #include "common/framsg.h" #include void MultiParamLoader::init() { file=0; ownfile=0; status=0; reset(); } void MultiParamLoader::reset() { status=0; breakcond=OnError; emptyparam.setParamTab(empty_paramtab); } int MultiParamLoader::findObject(const ExtObject &o) { for(int i=0;i=0) { delete objects(i); objects-=i; } } void MultiParamLoader::clearObjects() { FOREACH(ExtObject*,o,objects) delete o; objects.clear(); } void MultiParamLoader::load() { clearstack(); if (!file) { lasterror="can't open file"; status=OnError; return; } status=Loading; } void MultiParamLoader::abort() { if (file && ownfile) { fclose(file); file=0; } clearstack(); status=Finished; } void MultiParamLoader::load(VirtFILE *f) { abort(); ownfile=0; file=f; load(); } void MultiParamLoader::load(const char* filename) { abort(); ownfile=1; file=Vfopen(filename,FOPEN_READ_BINARY); load(); } int MultiParamLoader::go() { SString buf; if (status==OnError) return status; while (!finished()) { if ((status==BeforeObject) || ((status==BeforeUnknown) && !lastobject.isEmpty())) { Param tmp_param; ParamInterface *pi=lastobject.getParamInterface(tmp_param); pi->load(file); if ((status!=Finished) && maybeBreak(AfterObject)) break; continue; } else if (status==BeforeUnknown) { loadObjectNow(&emptyparam); continue; } if (!loadSStringLine(file,buf)) { if (!returnFromIncluded()) { abort(); break; } else continue; } if (buf[0]=='#') { if (buf.startsWith("#include")) { const char* t=strchr((const char*)buf,'\"'),*t2=0; if (t) t2=strchr(t+1,'\"'); if (t2) { SString filename(t+1,t2-t-1); include(filename); } else { const char* thisfilename=file->VgetPath(); FMprintf("MultiParamLoader","go",FMLV_WARN,"invalid \"%s\"%s%s",(const char*)buf, (thisfilename?" in ":""),(thisfilename?thisfilename:"")); } continue; } else if ((status!=Finished) && maybeBreak(OnComment)) { lastcomment=buf.substr(1); break; } } buf=trim(buf); if ((buf.len()>1)&&(buf[buf.len()-1]==':')) { lastunknown=0; lastunknown=buf.substr(0,buf.len()-1); lastobject.setEmpty(); FOREACH(ExtObject*,o,objects) { if (!strcmp(o->interfaceName(),lastunknown)) {lastobject=*o; break;} } if (!lastobject.isEmpty()) { if (maybeBreak(BeforeObject)) break; } else { if (maybeBreak(BeforeUnknown)) break; } } } return status; } bool MultiParamLoader::alreadyIncluded(const char* filename) { int i; const char* t; for(i=0;iVgetPath(); if (!t) continue; if (!strcmp(filename,t)) return true; } return false; } void MultiParamLoader::include(SString& filename) { const char* thisfilename=file->VgetPath(); SString newfilename; const char* t=thisfilename?strrchr(thisfilename,PATH_SEPARATOR_CHAR):0; if (thisfilename && t) { newfilename.append(thisfilename,t-thisfilename+1); newfilename+=filename; } else newfilename=filename; if (alreadyIncluded(newfilename)) { FMprintf("MultiParamLoader","include",FMLV_WARN,"circular reference ignored (\"%s\")", (const char*)filename); return; } VirtFILE *f=Vfopen(newfilename,FOPEN_READ_BINARY); if (!f) { FMprintf("MultiParamLoader","include",FMLV_WARN,"\"%s\" not found",(const char*)newfilename); } else { filestack+=file; file=f; } } VirtFILE* MultiParamLoader::popstack() { if (!filestack.size()) return 0; VirtFILE* f=filestack(filestack.size()-1); filestack.remove(filestack.size()-1); return f; } void MultiParamLoader::clearstack() { VirtFILE *f; while(f=popstack()) fclose(f); } bool MultiParamLoader::returnFromIncluded() { if (!filestack.size()) return false; if (file) fclose(file); file=popstack(); return true; } int MultiParamLoader::loadObjectNow(const ExtObject& o) { Param tmp_param; ParamInterface *pi=o.getParamInterface(tmp_param); pi->load(file); status=AfterObject; return 0; } int MultiParamLoader::run() { int stat; breakOn(OnError); while(stat=go()) if (stat==OnError) { abort(); return 0; } return 1; }