📄 property.cpp
字号:
// Copyright (C) 2005 David Sugar, Tycho Softworks.// // This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// // As a special exception, you may use this file as part of a free software// library without restriction. Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License. This exception does not however// invalidate any other reasons why the executable file might be covered by// the GNU General Public License.//// This exception applies only to the code released under the name GNU// ccScript. If you copy code from other releases into a copy of GNU// ccScript, as the General Public License permits, the exception does// not apply to the code that you add in this way. To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU ccScript, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.//#include "script3.h"#include <cstdio>#ifdef WIN32#define EXT_PROP ".pro"#define EXT_TEMP ".tmp"#define PRE_PROP "\\Script Properties\\"#define PRE_MAKE "\\Script Properties"#else#define EXT_PROP ".init"#define EXT_TEMP ".temp"#define PRE_PROP "/.properties/"#define PRE_MAKE "/.properties"#endif#define MAX_LIST 256namespace ccscript3Extension {using namespace std;using namespace ost; class LoadThread : public ScriptThread{private: FILE *fp; Symbol *list[MAX_LIST]; char path[128]; char var[128]; void run(void);public: LoadThread(ScriptInterp *interp); ~LoadThread();};class SaveThread : public ScriptThread{private: FILE *fp, *fr; Symbol *list[MAX_LIST]; char path[128]; char temp[128]; char var[128]; const char *id; void run(void);public: SaveThread(ScriptInterp *interp, const char *uid); ~SaveThread();}; class PropertyChecks : public ScriptChecks{public: const char *chkIO(Line *line, ScriptImage *img); const char *chkVar(Line *line, ScriptImage *img);};class PropertyMethods : public ScriptMethods{public: bool scrLoad(void); bool scrSave(void); bool scrVar(void);};class PropertyBinder : public ScriptBinder{public: PropertyBinder(Script::Define *run);};static Script::Define runtime[] = { {"load", false, (Script::Method)&PropertyMethods::scrLoad, (Script::Check)&PropertyChecks::chkIO}, {"save", false, (Script::Method)&PropertyMethods::scrSave, (Script::Check)&PropertyChecks::chkIO}, {"prop", true, (Script::Method)&PropertyMethods::scrVar, (Script::Check)&PropertyChecks::chkVar}, {"property", true, (Script::Method)&PropertyMethods::scrVar, (Script::Check)&PropertyChecks::chkVar}, {NULL, false, NULL, NULL}};PropertyBinder::PropertyBinder(Script::Define *run) :ScriptBinder(run){ char path[128]; if(*Script::var_prefix != '.') { snprintf(path, sizeof(path), "%s" PRE_MAKE, Script::var_prefix); Dir::create(path); }}static PropertyBinder bindProperty(runtime);LoadThread::LoadThread(ScriptInterp *interp) :ScriptThread(interp, 0){ fp = NULL;}SaveThread::SaveThread(ScriptInterp *interp, const char *uid) :ScriptThread(interp, 0){ fp = NULL; fr = NULL; id = uid;}LoadThread::~LoadThread(){ terminate(); if(fp) ::fclose(fp);}SaveThread::~SaveThread(){ terminate(); if(fp) ::fclose(fp); if(fr) ::fclose(fr);}void SaveThread::run(void){ char prof[128]; char buf[128]; const char *grp = interp->getMember(); const char *cp; char *ep; Symbol *sym; unsigned idx = 0, count; char base[64]; Name *scr = interp->getName(); if(!grp) { setString(base, sizeof(base), scr->name); ep = strchr(base, ':'); if(ep) *ep = 0; grp = base; } #ifdef WIN32 if(*Script::var_prefix == '.') { snprintf(temp, sizeof(temp), "%s%s" EXT_TEMP, grp, id); snprintf(path, sizeof(path), "%s%s" EXT_PROP, grp, id); } else { snprintf(temp, sizeof(temp), "%s" PRE_PROP "%s%s" EXT_TEMP, Script::var_prefix, grp, id); snprintf(path, sizeof(path), "%s" PRE_PROP "%s%s" EXT_PROP, Script::var_prefix, grp, id); }#else if(*Script::var_prefix == '.') { snprintf(path, sizeof(path), "%s.%s", grp, id); snprintf(temp, sizeof(temp), ".%s.%s", grp, id); } else { snprintf(temp, sizeof(temp), "%s" PRE_PROP ".%s.%s", Script::var_prefix, grp, id); snprintf(path, sizeof(path), "%s" PRE_PROP "%s.%s", Script::var_prefix, grp, id); }#endif snprintf(prof, sizeof(prof), "%s/%s" EXT_PROP, Script::etc_prefix, grp); remove(temp); fp = ::fopen(temp, "w"); if(!fp) exit("save-failed"); fr = ::fopen(path, "r"); if(!fr) fr = ::fopen(prof, "r"); while(fr) { if(!fgets(buf, sizeof(buf), fr) || feof(fr)) break; cp = buf; while(isspace(*cp)) ++cp; if(!isalpha(*cp)) continue; ep = strrchr(buf, '\r'); if(!ep) ep = strrchr(buf, '\n'); if(ep) *ep = 0; ep = (char *)cp; while(isalnum(*ep)) ++ep; *(ep++) = 0; while(isspace(*ep) || *ep == '=') ++ep; snprintf(var, sizeof(var), "%s.%s", grp, cp); lock(); sym = interp->mapSymbol(var, 0); if(sym && sym->type == symMODIFIED) { fprintf(fp, "%s = %s\n", cp, sym->data); sym->type = symORIGINAL; } else fprintf(fp, "%s = %s\n", cp, ep); release(); Thread::yield(); } lock(); count = interp->gathertype(list, MAX_LIST - 1, grp, symMODIFIED); release(); while(idx < count) { sym = list[idx++]; sym->type = symORIGINAL; cp = strrchr(sym->id, '.'); if(!cp) continue; fprintf(fp, "%s = %s\n", ++cp, sym->data); Thread::yield(); } ::fflush(fp); rename(temp, path); exit(NULL);}void LoadThread::run(void){ const char *id; const char *grp = interp->getMember(); char *cp; char *ep; Symbol *sym; char base[64]; Name *scr = interp->getName(); unsigned count, idx = 0; if(!grp) { setString(base, sizeof(base), scr->name); ep = strchr(base, ':'); if(ep) *ep = 0; grp = base; } lock(); id = interp->getKeyword("id"); idx = 0; count = interp->gathertype(list, MAX_LIST - 1, grp, symMODIFIED); while(idx < count) { sym = list[idx++]; sym->data[0] = 0; sym->type = symORIGINAL; } idx = 0; count = interp->gathertype(list, MAX_LIST - 1, grp, symORIGINAL); while(idx < count) { sym = list[idx++]; sym->data[0] = 0; } release(); if(id && *id) {#ifdef WIN32 if(*Script::var_prefix == '.') snprintf(path, sizeof(path), "%s%s" EXT_PROP, grp, id); else snprintf(path, sizeof(path), "%s" PRE_PROP "%s%s" EXT_PROP, Script::var_prefix, grp, id);#else if(*Script::var_prefix == '.') snprintf(path, sizeof(path), "%s.%s", grp, id); else snprintf(path, sizeof(path), "%s" PRE_PROP "%s.%s", Script::var_prefix, grp, id);#endif fp = ::fopen(path, "r"); if(fp) goto load; } snprintf(path, sizeof(path), "%s/%s" EXT_PROP, Script::etc_prefix, grp); fp = ::fopen(path, "r"); if(!fp) exit("load-failed"); load: for(;;) { if(!fgets(path, sizeof(path), fp) || feof(fp)) break; cp = path; while(isspace(*cp)) ++cp; if(!isalpha(*cp)) continue; ep = strrchr(path, '\r'); if(!ep) ep = strrchr(path, '\n'); if(ep) *ep = 0; ep = cp; while(isalnum(*ep)) ++ep; *(ep++) = 0; while(isspace(*ep) || *ep == '=') ++ep; snprintf(var, sizeof(var), "%s.%s", grp, cp); lock(); sym = interp->mapSymbol(var, 0); if(!sym) goto unlock; if(sym->type != symORIGINAL && sym->type != symMODIFIED) goto unlock; sym->type = symORIGINAL; snprintf(sym->data, sym->size + 1, ep);unlock: release(); Thread::yield(); } exit(NULL);}bool PropertyMethods::scrVar(void){ char base[64]; char var[128]; Symbol *sym; const char *cp; const char *prefix = getMember(); char *ep; unsigned len; Name *scr = getName(); if(!prefix) { setString(base, sizeof(base), scr->name); ep = strchr(base, ':'); if(ep) *ep = 0; prefix = base; } while(NULL != (cp = getOption())) { if(strchr(cp, '.') || *cp == '%' || *cp == '&') setString(var, sizeof(var), cp); else snprintf(var, sizeof(var), "%s.%s", prefix, cp); ep = strrchr(var, ':'); if(ep) { *(ep++) = 0; len = atoi(ep); } else len = symsize; sym = mapSymbol(var, len); if(!sym) continue; if(sym->type != symINITIAL) continue; sym->type = symORIGINAL; } advance(); return true;} bool PropertyMethods::scrLoad(void){ release(); new LoadThread(dynamic_cast<ScriptInterp*>(this)); return false;}bool PropertyMethods::scrSave(void){ const char *id = getKeyword("id"); if(!id || !*id) { error("save-missing-id"); return true; } release(); new SaveThread(dynamic_cast<ScriptInterp*>(this), id); return false;}const char *PropertyChecks::chkVar(Line *line, ScriptImage *img){ unsigned idx = 0; const char *cp; if(hasKeywords(line)) return "property uses no keywords"; if(!line->argc) return "property requires arguments"; while(NULL != (cp = getOption(line, &idx))) { if(*cp == '&' || *cp == '%') goto chksize; if(!isalpha(*cp)) return "property must be field name"; if(strchr(cp, '.')) return "field must not be compound";chksize: cp = strrchr(cp, ':'); if(!cp) continue; ++cp; if(!isdigit(*cp)) return "field size must be number"; } return NULL;}const char *PropertyChecks::chkIO(Line *line, ScriptImage *img){ unsigned idx = 0; // if(!getMember(line))// return "property requires .group"; if(!useKeywords(line, "=id")) return "invalid keyword used"; if(getOption(line, &idx)) return "property io uses no arguments"; return NULL;}};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -