void SQDbgServer::Attribute(const SQChar *name,const SQChar *value) { XMLElementState *self = &xmlstate[_xmlcurrentement]; assert(!self->haschildren); //cannot have attributes if already has children const SQChar *escval = escape_xml(value); _scratchstring.resize(5+scstrlen(name)+scstrlen(escval)); scsprintf(&_scratchstring[0],_SC(" %s=\"%s\""),name,escval); SendChunk(&_scratchstring[0]); }
void SQDbgServer::SendChunk(const SQChar *chunk) { char *buf=NULL; int buf_len=0; #ifdef _UNICODE buf_len=(int)scstrlen(chunk)+1; buf=(char *)sq_getscratchpad(_v,(buf_len)*3); wcstombs((char *)buf,chunk,buf_len); #else buf_len=(int)scstrlen(chunk); buf=(char *)chunk; #endif send(_endpoint,(const char*)buf,(int)strlen((const char *)buf),0); }
void SQDbgServer::SendChunk(const SQChar *chunk) { char *buf = NULL; int buf_len = 0; #ifdef _UNICODE buf_len=(int)scstrlen(chunk)+1; buf=(char *)sq_getscratchpad(_v,(buf_len)*3); //wcstombs((char *)buf,chunk,buf_len*3); WideCharToMultiByte(CP_UTF8,0,chunk,-1,buf,buf_len*3,NULL,NULL); #else buf_len = (int) scstrlen(chunk); buf = (char *) chunk; #endif send(_endpoint, (const char *) buf, (int) strlen((const char *) buf), 0); }
/** Run the dummy info.nut. */ void Script_CreateDummyInfo(HSQUIRRELVM vm, const char *type, const char *dir) { char dummy_script[4096]; char *dp = dummy_script; dp += seprintf(dp, lastof(dummy_script), "class Dummy%s extends %sInfo {\n", type, type); dp += seprintf(dp, lastof(dummy_script), "function GetAuthor() { return \"OpenTTD Developers Team\"; }\n"); dp += seprintf(dp, lastof(dummy_script), "function GetName() { return \"Dummy%s\"; }\n", type); dp += seprintf(dp, lastof(dummy_script), "function GetShortName() { return \"DUMM\"; }\n"); dp += seprintf(dp, lastof(dummy_script), "function GetDescription() { return \"A Dummy %s that is loaded when your %s/ dir is empty\"; }\n", type, dir); dp += seprintf(dp, lastof(dummy_script), "function GetVersion() { return 1; }\n"); dp += seprintf(dp, lastof(dummy_script), "function GetDate() { return \"2008-07-26\"; }\n"); dp += seprintf(dp, lastof(dummy_script), "function CreateInstance() { return \"Dummy%s\"; }\n", type); dp += seprintf(dp, lastof(dummy_script), "} RegisterDummy%s(Dummy%s());\n", type, type); const SQChar *sq_dummy_script = OTTD2SQ(dummy_script); sq_pushroottable(vm); /* Load and run the script */ if (SQ_SUCCEEDED(sq_compilebuffer(vm, sq_dummy_script, scstrlen(sq_dummy_script), _SC("dummy"), SQTrue))) { sq_push(vm, -2); if (SQ_SUCCEEDED(sq_call(vm, 1, SQFalse, SQTrue))) { sq_pop(vm, 1); return; } } NOT_REACHED(); }
void SQVM::Raise_Error(const SQChar *s, ...) { va_list vl; va_start(vl, s); scvsprintf(_sp(rsl((SQInteger)scstrlen(s)+(NUMBER_MAX_CHAR*2))), s, vl); va_end(vl); _lasterror = SQString::Create(_ss(this),_spval,-1); }
//this can be done much better/faster(do we need that?) const SQChar *SQDbgServer::escape_xml(const SQChar *s) { SQChar *temp = sq_getscratchpad(_v, ((SQInteger) scstrlen(s) * 6) + sizeof(SQChar)); SQChar *dest = temp; while (*s != _SC('\0')) { const SQChar *escape = NULL; switch (*s) { case _SC('<'): escape = _SC("<"); break; case _SC('>'): escape = _SC(">"); break; case _SC('&'): escape = _SC("&"); break; case _SC('\''): escape = _SC("'"); break; case _SC('\"'): escape = _SC("""); break; case _SC('\n'): escape = _SC("\\n"); break; case _SC('\r'): escape = _SC("\\r"); break; } if (escape) { scstrcpy(dest, escape); dest += scstrlen(escape); } else { *dest = *s; *dest++; } *s++; } *dest = _SC('\0'); return temp; }
SQInteger SquirrelStd::require(HSQUIRRELVM vm) { SQInteger top = sq_gettop(vm); const SQChar *filename; SQChar *real_filename; sq_getstring(vm, 2, &filename); /* Get the script-name of the current file, so we can work relative from it */ SQStackInfos si; sq_stackinfos(vm, 1, &si); if (si.source == NULL) { DEBUG(misc, 0, "[squirrel] Couldn't detect the script-name of the 'require'-caller; this should never happen!"); return SQ_ERROR; } real_filename = scstrdup(si.source); /* Keep the dir, remove the rest */ SQChar *s = scstrrchr(real_filename, PATHSEPCHAR); if (s != NULL) { /* Keep the PATHSEPCHAR there, remove the rest */ s++; *s = '\0'; } /* And now we concat, so we are relative from the current script * First, we have to make sure we have enough space for the full path */ real_filename = ReallocT(real_filename, scstrlen(real_filename) + scstrlen(filename) + 1); scstrcat(real_filename, filename); /* Tars dislike opening files with '/' on Windows.. so convert it to '\\' ;) */ char *filen = strdup(SQ2OTTD(real_filename)); #if (PATHSEPCHAR != '/') for (char *n = filen; *n != '\0'; n++) if (*n == '/') *n = PATHSEPCHAR; #endif bool ret = Squirrel::LoadScript(vm, filen); /* Reset the top, so the stack stays correct */ sq_settop(vm, top); free(real_filename); free(filen); return ret ? 0 : SQ_ERROR; }
int Xml_registerCode(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); SQ_GET_STRING(v, 2, decoded); SQ_GET_STRING(v, 3, encoded); size_t i; for(i=0; i<sv_code_size; i+=2) if(scstrcmp(sv_code[i],decoded)==0) return sq_throwerror(v,_SC"SQXml ERROR: code already exists.")); if(sv_code_size+2>sv_code_capacity) { size_t old_capacity = sv_code_capacity; sv_code_capacity*=2; sv_code = (SQChar**)sq_realloc(sv_code, old_capacity*sizeof(SQChar*), sv_code_capacity*sizeof(SQChar*)); } sv_code[sv_code_size]=(SQChar*)sq_malloc((scstrlen(decoded)+1)*sizeof(SQChar*)); strcpy(sv_code[sv_code_size++], decoded); sv_code[sv_code_size]=(SQChar*)sq_malloc((scstrlen(decoded)+1)*sizeof(SQChar*)); strcpy(sv_code[sv_code_size++],encoded); return 0; }
/* * Comple script buffers */ SQInteger sqCompileBuffer(HSQUIRRELVM v, const char* script, const char* sourcename) { if (SQ_SUCCEEDED(sq_compilebuffer(v, script, scstrlen(script), sourcename, SQTrue))) { sq_pushroottable(v); if (SQ_FAILED(sq_call(v, 1, SQFalse, SQTrue))) { return ERR_SCRIPT_CALL_ROOT; } } else { return ERR_SCRIPT_COMPILE; } return EMO_NO_ERROR; }
/** Run the dummy AI and let it generate an error message. */ void Script_CreateDummy(HSQUIRRELVM vm, StringID string, const char *type) { /* We want to translate the error message. * We do this in three steps: * 1) We get the error message */ char error_message[1024]; GetString(error_message, string, lastof(error_message)); /* Make escapes for all quotes and slashes. */ char safe_error_message[1024]; char *q = safe_error_message; for (const char *p = error_message; *p != '\0' && q < lastof(safe_error_message) - 2; p++, q++) { if (*p == '"' || *p == '\\') *q++ = '\\'; *q = *p; } *q = '\0'; /* 2) We construct the AI's code. This is done by merging a header, body and footer */ char dummy_script[4096]; char *dp = dummy_script; dp += seprintf(dp, lastof(dummy_script), "class Dummy%s extends %sController {\n function Start()\n {\n", type, type); /* As special trick we need to split the error message on newlines and * emit each newline as a separate error printing string. */ char *newline; char *p = safe_error_message; do { newline = strchr(p, '\n'); if (newline != NULL) *newline = '\0'; dp += seprintf(dp, lastof(dummy_script), " %sLog.Error(\"%s\");\n", type, p); p = newline + 1; } while (newline != NULL); dp = strecpy(dp, " }\n}\n", lastof(dummy_script)); /* 3) We translate the error message in the character format that Squirrel wants. * We can use the fact that the wchar string printing also uses %s to print * old style char strings, which is what was generated during the script generation. */ const SQChar *sq_dummy_script = OTTD2SQ(dummy_script); /* And finally we load and run the script */ sq_pushroottable(vm); if (SQ_SUCCEEDED(sq_compilebuffer(vm, sq_dummy_script, scstrlen(sq_dummy_script), _SC("dummy"), SQTrue))) { sq_push(vm, -2); if (SQ_SUCCEEDED(sq_call(vm, 1, SQFalse, SQTrue))) { sq_pop(vm, 1); return; } } NOT_REACHED(); }
static const SQChar *sq_str_replace (HSQUIRRELVM v, const SQChar *s, const SQChar *p, const SQChar *r) { const SQChar *wild; size_t l = scstrlen(p); SQBlob b(0, BLOB_BUFSIZE); while ((wild = scstrstr(s, p)) != NULL) { b.Write(s, wild - s); /* push prefix */ b.WriteZstr(r); /* push replacement in place of pattern */ s = wild + l; /* continue after `p' */ } b.WriteZstr(s); /* push last suffix */ sq_pushstring(v, (const SQChar*)b.GetBuf(), b.Len()); return sq_tostring(v, -1); }
const SQChar *EscapeXMLString(HSQUIRRELVM v,const SQChar *s) { SQChar *temp=sq_getscratchpad(v,((int)scstrlen(s)*6) + sizeof(SQChar)); SQChar *dest=temp; while(*s!=_SC('\0')){ int i=0; bool escaped=false; while(g_escapes[i].esc!=NULL){ if(*s==g_escapes[i].c){ scstrcpy(dest,g_escapes[i].esc); dest+=scstrlen(g_escapes[i].esc); escaped=true; break; } i++; } if(!escaped){*dest=*s;*dest++;} *s++; } *dest=_SC('\0'); return temp; }
void SQDbgServer::EndElement(const SQChar *name) { XMLElementState *self = &xmlstate[_xmlcurrentement]; assert(scstrcmp(self->name,name) == 0); if(self->haschildren) { _scratchstring.resize(4+scstrlen(name)); scsprintf(&_scratchstring[0],_SC("</%s>"),name); SendChunk(&_scratchstring[0]); } else { SendChunk(_SC("/>")); } _xmlcurrentement--; }
void SQDbgServer::BeginElement(const SQChar *name) { _xmlcurrentement++; XMLElementState *self = &xmlstate[_xmlcurrentement]; scstrcpy(self->name,name); self->haschildren = false; if(_xmlcurrentement > 0) { XMLElementState *parent = &xmlstate[_xmlcurrentement-1]; if(!parent->haschildren) { SendChunk(_SC(">")); // closes the parent tag parent->haschildren = true; } } _scratchstring.resize(2+scstrlen(name)); scsprintf(&_scratchstring[0],_SC("<%s"),name); SendChunk(&_scratchstring[0]); }
void Interactive(HSQUIRRELVM v) { #define MAXINPUT 1024 SQChar buffer[MAXINPUT]; SQInteger blocks =0; SQInteger string=0; SQInteger retval=0; SQInteger done=0; PrintVersionInfos(); sq_pushroottable(v); sq_pushstring(v,_SC("quit"),-1); sq_pushuserpointer(v,&done); sq_newclosure(v,quit,1); sq_setparamscheck(v,1,NULL); sq_newslot(v,-3,SQFalse); sq_pop(v,1); while (!done) { SQInteger i = 0; scprintf(_SC("\nsq>")); for(;;) { int c; if(done)return; c = getchar(); if (c == _SC('\n')) { if (i>0 && buffer[i-1] == _SC('\\')) { buffer[i-1] = _SC('\n'); } else if(blocks==0)break; buffer[i++] = _SC('\n'); } else if (c==_SC('}')) {blocks--; buffer[i++] = (SQChar)c;} else if(c==_SC('{') && !string){ blocks++; buffer[i++] = (SQChar)c; } else if(c==_SC('"') || c==_SC('\'')){ string=!string; buffer[i++] = (SQChar)c; } else if (i >= MAXINPUT-1) { scfprintf(stderr, _SC("sq : input line too long\n")); break; } else{ buffer[i++] = (SQChar)c; } } buffer[i] = _SC('\0'); if(buffer[0]==_SC('=')){ scsprintf(sq_getscratchpad(v,MAXINPUT),_SC("return (%s)"),&buffer[1]); memcpy(buffer,sq_getscratchpad(v,-1),(scstrlen(sq_getscratchpad(v,-1))+1)*sizeof(SQChar)); retval=1; } i=scstrlen(buffer); if(i>0){ SQInteger oldtop=sq_gettop(v); if(SQ_SUCCEEDED(sq_compilebuffer(v,buffer,i,_SC("interactive console"),SQTrue))){ sq_pushroottable(v); if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue)) && retval){ scprintf(_SC("\n")); sq_pushroottable(v); sq_pushstring(v,_SC("print"),-1); sq_get(v,-2); sq_pushroottable(v); sq_push(v,-4); sq_call(v,2,SQFalse,SQTrue); retval=0; scprintf(_SC("\n")); } } sq_settop(v,oldtop); } } }
void SQVM::Raise_ErrorV(const SQChar *s, va_list &vl) { scvsprintf(_sp(rsl((SQInteger)scstrlen(s)+(NUMBER_MAX_CHAR*2))), s, vl); Raise_Error(_spval); }
SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output) { const SQChar *format; SQChar *dest; SQChar fmt[MAX_FORMAT_LEN]; sq_getstring(v,nformatstringidx,&format); SQInteger allocated = (sq_getsize(v,nformatstringidx)+2)*sizeof(SQChar); dest = sq_getscratchpad(v,allocated); SQInteger n = 0,i = 0, nparam = nformatstringidx+1, w = 0; while(format[n] != '\0') { if(format[n] != '%') { assert(i < allocated); dest[i++] = format[n]; n++; } else if(format[n+1] == '%') { //handles %% dest[i++] = '%'; n += 2; } else { n++; if( nparam > sq_gettop(v) ) return sq_throwerror(v,_SC("not enough paramters for the given format string")); n = validate_format(v,fmt,format,n,w); if(n < 0) return -1; SQInteger addlen = 0; SQInteger valtype = 0; const SQChar *ts; SQInteger ti; SQFloat tf; switch(format[n]) { case 's': if(SQ_FAILED(sq_getstring(v,nparam,&ts))) return sq_throwerror(v,_SC("string expected for the specified format")); addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar)); valtype = 's'; break; case 'i': case 'd': case 'o': case 'u': case 'x': case 'X': #ifdef _SQ64 { size_t flen = scstrlen(fmt); SQInteger fpos = flen - 1; SQChar f = fmt[fpos]; SQChar *prec = (SQChar *)_PRINT_INT_PREC; while(*prec != _SC('\0')) { fmt[fpos++] = *prec++; } fmt[fpos++] = f; fmt[fpos++] = _SC('\0'); } #endif case 'c': if(SQ_FAILED(sq_getinteger(v,nparam,&ti))) return sq_throwerror(v,_SC("integer expected for the specified format")); addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); valtype = 'i'; break; case 'f': case 'g': case 'G': case 'e': case 'E': if(SQ_FAILED(sq_getfloat(v,nparam,&tf))) return sq_throwerror(v,_SC("float expected for the specified format")); addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); valtype = 'f'; break; default: return sq_throwerror(v,_SC("invalid format")); } n++; allocated += addlen + sizeof(SQChar); dest = sq_getscratchpad(v,allocated); switch(valtype) { #pragma warning(push) #pragma warning(disable : 4996) case 's': i += scsprintf(&dest[i],fmt,ts); break; case 'i': i += scsprintf(&dest[i],fmt,ti); break; case 'f': i += scsprintf(&dest[i],fmt,tf); break; #pragma warning(pop) }; nparam ++; } } *outlen = i; dest[i] = '\0'; *output = dest; return SQ_OK; }
static size_t find(const SQChar* s, const SQChar* pattern, size_t start) { const SQChar* found =scstrstr(s+start, pattern); return found ? found-s : scstrlen(s); }
int Xml_eval(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); SQChar* str = 0; size_t str_size=0; if(sq_gettype(v,2) == OT_USERPOINTER) sq_getuserpointer(v, 2, &str); else { SQ_GET_STRING(v, 2, sTmp); str = (SQChar*)sq_malloc(sTmp_size+(sizeof(SQChar))); memcpy(str, sTmp, sTmp_size); str[sTmp_size]=0; str_size = sTmp_size; } Tokenizer* tok = Tokenizer_new(str, str_size ? str_size : scstrlen(str)); sq_settop(v,0); const SQChar* token=0; int firstStatement = 1; while((token=Tokenizer_next(tok))!=0) if(token[0]==OPN) { // new tag found if(sq_gettop(v)) { int newIndex=sq_size(v,-1)+1; sq_pushinteger(v,newIndex); sq_newtable(v); sq_set(v, -3); sq_pushinteger(v,newIndex); sq_get(v,-2); } else { if (firstStatement) { sq_newtable(v); firstStatement = 0; } else return lua_gettop(L); } // set metatable: sq_newtable(v); sq_pushliteral(v, _SC("__index")); sq_getglobal(v, "xml"); lua_settable(v, -3); sq_pushliteral(v, _SC("__tostring")); // set __tostring metamethod lua_getglobal(L, "xml"); lua_pushliteral(L,"str"); lua_gettable(v, -2); sq_remove(v, -2); sq_set(v, -3); lua_setmetatable(L, -2); // parse tag and content: sq_pushinteger(v,0); // use index 0 for storing the tag sq_pushstring(v, Tokenizer_next(tok), -1); sq_set(v, -3); while(((token = Tokenizer_next(tok))!=0)&&(token[0]!=CLS)&&(token[0]!=ESC)) { // parse tag header size_t sepPos=find(token, "=", 0); if(token[sepPos]) { // regular attribute const SQChar* aVal =token+sepPos+2; sq_pushstring(v, token, sepPos); size_t lenVal = strlen(aVal)-1; if(!lenVal) Xml_pushDecode(v, _SC(""), 0); else Xml_pushDecode(v, aVal, lenVal); sq_set(v, -3); } } if(!token||(token[0]==ESC)) { if(sq_gettop(v)>1) sq_settop(v,-2); // this tag has no content, only attributes else break; } } else if(token[0]==ESC) { // previous tag is over if(sq_gettop(v)>1) sq_settop(v,-2); // pop current table else break; } else { // read elements sq_pushinteger(v,sq_size(v,-1)+1); Xml_pushDecode(v, token, 0); sq_rawset(v, -3); } Tokenizer_delete(tok); sq_free(str); return sq_gettop(v); }