static bool scriptinternalcmd() { bool bContinue = true; LINEMAPENTRY cur = linemap.at(scriptIp - 1); if(cur.type == linecommand) { switch(scriptinternalcmdexec(cur.u.command)) { case STATUS_CONTINUE: break; case STATUS_ERROR: bContinue = false; GuiScriptError(scriptIp, "Error executing command!"); break; case STATUS_EXIT: bContinue = false; scriptIp = scriptinternalstep(0); GuiScriptSetIp(scriptIp); break; case STATUS_PAUSE: bContinue = false; //stop running the script scriptIp = scriptinternalstep(scriptIp); GuiScriptSetIp(scriptIp); break; } } else if(cur.type == linebranch) { if(cur.u.branch.type == scriptcall) //calls have a special meaning scriptstack.push_back(scriptIp); if(scriptinternalbranch(cur.u.branch.type)) scriptIp = scriptlabelfind(cur.u.branch.branchlabel); } return bContinue; }
static bool scriptcreatelinemap(const char* filename) { Handle hFile = CreateFileW(StringUtils::Utf8ToUtf16(filename).c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if(hFile == INVALID_HANDLE_VALUE) { GuiScriptError(0, "CreateFile failed..."); return false; } unsigned int filesize = GetFileSize(hFile, 0); if(!filesize) { GuiScriptError(0, "Empty script..."); return false; } Memory<char*> filedata(filesize + 1, "createlinemap:filedata"); DWORD read = 0; if(!ReadFile(hFile, filedata(), filesize, &read, 0)) { GuiScriptError(0, "ReadFile failed..."); return false; } hFile.Close(); int len = (int)strlen(filedata()); char temp[256] = ""; LINEMAPENTRY entry; memset(&entry, 0, sizeof(entry)); std::vector<LINEMAPENTRY>().swap(linemap); for(int i = 0, j = 0; i < len; i++) //make raw line map { if(filedata()[i] == '\r' && filedata()[i + 1] == '\n') //windows file { memset(&entry, 0, sizeof(entry)); int add = 0; while(temp[add] == ' ') add++; strcpy_s(entry.raw, temp + add); *temp = 0; j = 0; i++; linemap.push_back(entry); } else if(filedata()[i] == '\n') //other file { memset(&entry, 0, sizeof(entry)); int add = 0; while(temp[add] == ' ') add++; strcpy_s(entry.raw, temp + add); *temp = 0; j = 0; linemap.push_back(entry); } else if(j >= 254) { memset(&entry, 0, sizeof(entry)); int add = 0; while(temp[add] == ' ') add++; strcpy_s(entry.raw, temp + add); *temp = 0; j = 0; linemap.push_back(entry); } else j += sprintf(temp + j, "%c", filedata()[i]); } if(*temp) { memset(&entry, 0, sizeof(entry)); strcpy_s(entry.raw, temp); linemap.push_back(entry); } int linemapsize = (int)linemap.size(); while(!*linemap.at(linemapsize - 1).raw) //remove empty lines from the end { linemapsize--; linemap.pop_back(); } for(int i = 0; i < linemapsize; i++) { LINEMAPENTRY cur = linemap.at(i); //temp. remove comments from the raw line char line_comment[256] = ""; char* comment = strstr(&cur.raw[0], "//"); if(comment && comment != cur.raw) //only when the line doesnt start with a comment { if(*(comment - 1) == ' ') //space before comment { strcpy_s(line_comment, comment); *(comment - 1) = '\0'; } else //no space before comment { strcpy_s(line_comment, comment); *comment = 0; } } int rawlen = (int)strlen(cur.raw); if(!rawlen) //empty { cur.type = lineempty; } else if(!strncmp(cur.raw, "//", 2)) //comment { cur.type = linecomment; strcpy_s(cur.u.comment, cur.raw); } else if(cur.raw[rawlen - 1] == ':') //label { cur.type = linelabel; sprintf(cur.u.label, "l %.*s", rawlen - 1, cur.raw); //create a fake command for formatting strcpy_s(cur.u.label, StringUtils::Trim(cur.u.label).c_str()); char temp[256] = ""; strcpy_s(temp, cur.u.label + 2); strcpy_s(cur.u.label, temp); //remove fake command if(!*cur.u.label || !strcmp(cur.u.label, "\"\"")) //no label text { char message[256] = ""; sprintf(message, "Empty label detected on line %d!", i + 1); GuiScriptError(0, message); std::vector<LINEMAPENTRY>().swap(linemap); return false; } int foundlabel = scriptlabelfind(cur.u.label); if(foundlabel) //label defined twice { char message[256] = ""; sprintf(message, "Duplicate label \"%s\" detected on lines %d and %d!", cur.u.label, foundlabel, i + 1); GuiScriptError(0, message); std::vector<LINEMAPENTRY>().swap(linemap); return false; } } else if(scriptgetbranchtype(cur.raw) != scriptnobranch) //branch { cur.type = linebranch; cur.u.branch.type = scriptgetbranchtype(cur.raw); char newraw[MAX_SCRIPT_LINE_SIZE] = ""; strcpy_s(newraw, StringUtils::Trim(cur.raw).c_str()); int len = (int)strlen(newraw); for(int i = 0; i < len; i++) if(newraw[i] == ' ') { strcpy_s(cur.u.branch.branchlabel, newraw + i + 1); break; } } else { cur.type = linecommand; strcpy_s(cur.u.command, cur.raw); } //append the comment to the raw line again if(*line_comment) sprintf(cur.raw + rawlen, " %s", line_comment); linemap.at(i) = cur; } linemapsize = (int)linemap.size(); for(int i = 0; i < linemapsize; i++) { auto & currentLine = linemap.at(i); if(currentLine.type == linebranch) //invalid branch label { int labelline = scriptlabelfind(currentLine.u.branch.branchlabel); if(!labelline) //invalid branch label { char message[256] = ""; sprintf(message, "Invalid branch label \"%s\" detected on line %d!", currentLine.u.branch.branchlabel, i + 1); GuiScriptError(0, message); std::vector<LINEMAPENTRY>().swap(linemap); return false; } else //set the branch destination line currentLine.u.branch.dest = scriptinternalstep(labelline); } } if(linemap.at(linemapsize - 1).type == linecomment || linemap.at(linemapsize - 1).type == linelabel) //label/comment on the end { memset(&entry, 0, sizeof(entry)); entry.type = linecommand; strcpy_s(entry.raw, "ret"); strcpy_s(entry.u.command, "ret"); linemap.push_back(entry); } return true; }
static bool scriptcreatelinemap(const char* filename) { String filedata; if(!FileHelper::ReadAllText(filename, filedata)) { String TranslatedString = GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "FileHelper::ReadAllText failed...")); GuiScriptError(0, TranslatedString.c_str()); return false; } auto len = filedata.length(); char temp[256] = ""; LINEMAPENTRY entry; memset(&entry, 0, sizeof(entry)); std::vector<LINEMAPENTRY>().swap(linemap); for(size_t i = 0, j = 0; i < len; i++) //make raw line map { if(filedata[i] == '\r' && filedata[i + 1] == '\n') //windows file { memset(&entry, 0, sizeof(entry)); int add = 0; while(temp[add] == ' ') add++; strcpy_s(entry.raw, temp + add); *temp = 0; j = 0; i++; linemap.push_back(entry); } else if(filedata[i] == '\n') //other file { memset(&entry, 0, sizeof(entry)); int add = 0; while(temp[add] == ' ') add++; strcpy_s(entry.raw, temp + add); *temp = 0; j = 0; linemap.push_back(entry); } else if(j >= 254) { memset(&entry, 0, sizeof(entry)); int add = 0; while(temp[add] == ' ') add++; strcpy_s(entry.raw, temp + add); *temp = 0; j = 0; linemap.push_back(entry); } else j += sprintf(temp + j, "%c", filedata[i]); } if(*temp) { memset(&entry, 0, sizeof(entry)); strcpy_s(entry.raw, temp); linemap.push_back(entry); } int linemapsize = (int)linemap.size(); while(!*linemap.at(linemapsize - 1).raw) //remove empty lines from the end { linemapsize--; linemap.pop_back(); } for(int i = 0; i < linemapsize; i++) { LINEMAPENTRY cur = linemap.at(i); //temp. remove comments from the raw line char line_comment[256] = ""; char* comment = strstr(&cur.raw[0], "//"); if(!comment) comment = strstr(&cur.raw[0], ";"); if(comment && comment != cur.raw) //only when the line doesnt start with a comment { if(*(comment - 1) == ' ') //space before comment { strcpy_s(line_comment, comment); *(comment - 1) = '\0'; } else //no space before comment { strcpy_s(line_comment, comment); *comment = 0; } } int rawlen = (int)strlen(cur.raw); if(!rawlen) //empty { cur.type = lineempty; } else if(!strncmp(cur.raw, "//", 2) || *cur.raw == ';') //comment { cur.type = linecomment; strcpy_s(cur.u.comment, cur.raw); } else if(cur.raw[rawlen - 1] == ':') //label { cur.type = linelabel; sprintf(cur.u.label, "l %.*s", rawlen - 1, cur.raw); //create a fake command for formatting strcpy_s(cur.u.label, StringUtils::Trim(cur.u.label).c_str()); strcpy_s(temp, cur.u.label + 2); strcpy_s(cur.u.label, temp); //remove fake command if(!*cur.u.label || !strcmp(cur.u.label, "\"\"")) //no label text { char message[256] = ""; sprintf(message, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Empty label detected on line %d!")), i + 1); GuiScriptError(0, message); std::vector<LINEMAPENTRY>().swap(linemap); return false; } int foundlabel = scriptlabelfind(cur.u.label); if(foundlabel) //label defined twice { char message[256] = ""; sprintf(message, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Duplicate label \"%s\" detected on lines %d and %d!")), cur.u.label, foundlabel, i + 1); GuiScriptError(0, message); std::vector<LINEMAPENTRY>().swap(linemap); return false; } } else if(scriptgetbranchtype(cur.raw) != scriptnobranch) //branch { cur.type = linebranch; cur.u.branch.type = scriptgetbranchtype(cur.raw); char newraw[MAX_SCRIPT_LINE_SIZE] = ""; strcpy_s(newraw, StringUtils::Trim(cur.raw).c_str()); int rlen = (int)strlen(newraw); for(int j = 0; j < rlen; j++) if(newraw[j] == ' ') { strcpy_s(cur.u.branch.branchlabel, newraw + j + 1); break; } } else { cur.type = linecommand; strcpy_s(cur.u.command, cur.raw); } //append the comment to the raw line again if(*line_comment) sprintf(cur.raw + rawlen, " %s", line_comment); linemap.at(i) = cur; } linemapsize = (int)linemap.size(); for(int i = 0; i < linemapsize; i++) { auto & currentLine = linemap.at(i); if(currentLine.type == linebranch) //invalid branch label { int labelline = scriptlabelfind(currentLine.u.branch.branchlabel); if(!labelline) //invalid branch label { char message[256] = ""; sprintf(message, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Invalid branch label \"%s\" detected on line %d!")), currentLine.u.branch.branchlabel, i + 1); GuiScriptError(0, message); std::vector<LINEMAPENTRY>().swap(linemap); return false; } else //set the branch destination line currentLine.u.branch.dest = scriptinternalstep(labelline); } } if(linemap.at(linemapsize - 1).type == linecomment || linemap.at(linemapsize - 1).type == linelabel) //label/comment on the end { memset(&entry, 0, sizeof(entry)); entry.type = linecommand; strcpy_s(entry.raw, "ret"); strcpy_s(entry.u.command, "ret"); linemap.push_back(entry); } return true; }