/* * tokenize - turn a command line into tokens */ static void tokenize( const char *line, char **tokens, int *ntok ) { register const char *cp; register char *sp; static char tspace[MAXLINE]; sp = tspace; cp = line; for (*ntok = 0; *ntok < MAXTOKENS; (*ntok)++) { tokens[*ntok] = sp; while (ISSPACE(*cp)) cp++; if (ISEOL(*cp)) break; do { *sp++ = *cp++; } while (!ISSPACE(*cp) && !ISEOL(*cp)); *sp++ = '\0'; } }
/* * WriteExpanded - writes up to dwChars or EOL, expanding %SystemRoot% * returns number of CHARs processed in buffer * (not number of bytes actually written) */ DWORD WriteExpanded(HANDLE hFile, CHAR *pch, DWORD dwChars) { DWORD dw; DWORD dwSave = dwChars; CHAR *pSave = pch; while (dwChars && !ISEOL(*pch)) { if (*pch == '%' && !_strnicmp(pch, achSYSROOT, sizeof(achSYSROOT)-sizeof(CHAR)) ) { dw = pch - pSave; if (dw) { WriteFileAssert(hFile, pSave, dw); } WriteFileAssert(hFile, achSysRoot, dwLenSysRoot); pch += sizeof(achSYSROOT)-sizeof(CHAR); pSave = pch; dwChars -= sizeof(achSYSROOT)-sizeof(CHAR); } else { pch++; dwChars -= sizeof(CHAR); } } dw = pch - pSave; if (dw) { WriteFileAssert(hFile, pSave, dw); } return (dwSave - dwChars); }
/* return string to end of line from buffer*/ static void strEol(char *retbuf, char *buf) { while (ISBLANK(*buf)) ++buf; while (!ISEOL(*buf)) *retbuf++ = *buf++; *retbuf = 0; }
static void handle_macro(char *s) { char *name; if (name = parse_identifier(&s)) { s = skip(s); if (ISEOL(s)) s = NULL; /* no named arguments */ new_macro(name,endm_dirlist,s); myfree(name); } else syntax_error(10); /* identifier expected */ }
PCHAR IsConfigCommand(PCHAR pConfigCommand, int CmdLen, PCHAR pLine) { PCHAR pch; if (!_strnicmp(pLine, pConfigCommand, CmdLen)) { pch = pLine + CmdLen; while (!isgraph(*pch) && !ISEOL(*pch)) // skip to "=" pch++; if (*pch++ == '=') { return pch; } } return NULL; }
char *skip_operand(char *s) { int par_cnt=0; while(1){ if(*s=='(') par_cnt++; if(*s==')'){ if(par_cnt>0) par_cnt--; else syntax_error(3); } if(ISEOL(s)||(*s==','&&par_cnt==0)) break; s++; } if(par_cnt!=0) syntax_error(4); return s; }
static char *skip_macroparam(char *s) { int par_cnt=0; char c; while(1){ c = *s; if(START_PARENTH(c)) par_cnt++; if(END_PARENTH(c)){ if(par_cnt>0) par_cnt--; else return s; } if(ISEOL(s)||((c==','||isspace((unsigned char)c))&&par_cnt==0)) break; s++; } return s; }
char *skip_operand(char *s) { int par_cnt=0; char c; while(1){ c = *s; if(START_PARENTH(c)) par_cnt++; else if(END_PARENTH(c)){ if(par_cnt>0) par_cnt--; else syntax_error(3); }else if(c=='\''||c=='\"') s=skip_string(s,c,NULL)-1; else if(ISEOL(s)||(c==','&&par_cnt==0)) break; s++; } if(par_cnt!=0) syntax_error(4); return s; }
/* * Preprocesses the specfied config file (config.sys\autoexec.bat) * into a temporary file. * * - expands %SystemRoot% * - adds SHELL line for config.sys * * entry: BOOLEAN bConfig : TRUE - config.sys * FALSE - autoexec.bat */ void ExpandConfigFiles(BOOLEAN bConfig) { DWORD dw, dwRawFileSize; HANDLE hRawFile; HANDLE hTmpFile; CHAR **ppTmpFile; CHAR *pRawBuffer; CHAR *pLine; CHAR *pTmp; CHAR *pEnvParam= NULL; CHAR *pPartyShell=NULL; CHAR achRawFile[MAX_PATH+12]; CHAR *lpszzEnv, *lpszName; CHAR cchEnv; dw = GetWindowsDirectory(achRawFile, sizeof(achRawFile)); dwLenSysRoot = GetShortPathNameA(achRawFile, achSysRoot, sizeof(achSysRoot)); if (dwLenSysRoot >= sizeof(achSysRoot)) { dwLenSysRoot = 0; achSysRoot[0] = '\0'; } GetPIFConfigFiles(bConfig, achRawFile); ppTmpFile = bConfig ? &pchTmpConfigFile : &pchTmpAutoexecFile; hRawFile = CreateFile(achRawFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hRawFile == (HANDLE)0xFFFFFFFF || !dwLenSysRoot || dwLenSysRoot >= sizeof(achSysRoot) || !(dwRawFileSize = GetFileSize(hRawFile, NULL)) || dwRawFileSize == 0xFFFFFFFF ) { RcErrorDialogBox(ED_BADSYSFILE, achRawFile, NULL); TerminateVDM(); // skip cleanup since I insist that we exit! } pRawBuffer = malloc(dwRawFileSize+1); // allocate buffer to save environment settings in autoexec.nt // I know this is bad to allocate this amount of memory at this // moment as we dont know if there are anything we want to keep // at all. This allocation simply provides the following error // handling easily. if(!bConfig) { lpszzEnv = lpszzcmdEnv16 = (PCHAR)malloc(dwRawFileSize); cchEnv = 0; } if (!pRawBuffer || (!bConfig && lpszzcmdEnv16 == NULL)) { RcErrorDialogBox(ED_INITMEMERR, achRawFile, NULL); TerminateVDM(); // skip cleanup since I insist that we exit! } if (!cmdCreateTempFile(&hTmpFile,ppTmpFile) || !ReadFile(hRawFile, pRawBuffer, dwRawFileSize, &dw, NULL) || dw != dwRawFileSize ) { GetTempPath(MAX_PATH, achRawFile); achRawFile[63] = '\0'; RcErrorDialogBox(ED_INITTMPFILE, achRawFile, NULL); TerminateVDM(); // skip cleanup since I insist that we exit! } // CHANGE HERE WHEN YOU CHANGE cmdCreateTempFile !!!!!!!!!! // we depend on the buffer size allocated for the file name dw = GetShortPathNameA(*ppTmpFile, *ppTmpFile, MAX_PATH +13); if (dw == 0 || dw > 63) { GetTempPath(MAX_PATH, achRawFile); achRawFile[63] = '\0'; RcErrorDialogBox(ED_INITTMPFILE, achRawFile, NULL); TerminateVDM(); // skip cleanup since I insist that we exit! } // null terminate the buffer so we can use CRT string functions *(pRawBuffer+dwRawFileSize) = '\0'; // ensure no trailing backslash in System Directory if (*(achSysRoot+dwLenSysRoot-1) == '\\') { *(achSysRoot + --dwLenSysRoot) = '\0'; } pLine = pRawBuffer; while (dwRawFileSize) { // skip leading white space while (dwRawFileSize && !isgraph(*pLine)) { pLine++; dwRawFileSize -= sizeof(CHAR); } if (!dwRawFileSize) // anything left to do ? break; if (bConfig) { // // filter out country= setting we will create our own based // on current country ID and codepage. // pTmp = IsConfigCommand(achCOUNTRY, sizeof(achCOUNTRY) - sizeof(CHAR), pLine); if (pTmp) { while (dwRawFileSize && !ISEOL(*pLine)) { pLine++; dwRawFileSize -= sizeof(CHAR); } continue; } // filter out shell= command, saving /E:nn parameter pTmp = IsConfigCommand(achSHELL, sizeof(achSHELL) - sizeof(CHAR),pLine); if (pTmp) { // skip leading white space while (!isgraph(*pTmp) && !ISEOL(*pTmp)) { dwRawFileSize -= sizeof(CHAR); pTmp++; } /* if for a third party shell (not SCS command.com) * append the whole thing thru /c parameter * else * append user specifed /e: parameter */ if (!_strnicmp(achSYSROOT,pTmp,sizeof(achSYSROOT)-sizeof(CHAR))) { dw = sizeof(achSYSROOT) - sizeof(CHAR); } else if (!_strnicmp(achSysRoot,pTmp, strlen(achSysRoot))) { dw = strlen(achSysRoot); } else { dw = 0; } if (!dw || _strnicmp(achCOMMAND,pTmp+dw,sizeof(achCOMMAND)-sizeof(CHAR)) ) { pPartyShell = pTmp; } else { do { while (*pTmp != '/' && !ISEOL(*pTmp)) // save "/e:" pTmp++; if(ISEOL(*pTmp)) break; if (!_strnicmp(pTmp,achENV,sizeof(achENV)-sizeof(CHAR))) pEnvParam = pTmp; pTmp++; } while(1); // was: while (!ISEOL(*pTmp)); // we have break form this loop now, // and don't need in additional macro.. } // skip the "shell=" line while (dwRawFileSize && !ISEOL(*pLine)) { pLine++; dwRawFileSize -= sizeof(CHAR); } continue; } // END, really is "shell=" line! } /** Filter out PROMPT, SET and PATH from autoexec.nt for environment merging. The output we prepare here is a multiple strings buffer which has the format as : "EnvName_1 NULL EnvValue_1 NULL[EnvName_n NULL EnvValue_n NULL] NULL We don't take them out from the file because command.com needs them. **/ if (!bConfig) if (!_strnicmp(pLine, achPROMPT, sizeof(achPROMPT) - 1)){ // prompt command found. // the syntax of prompt can be eithe // prompt xxyyzz or // prompt=xxyyzz // strcpy(lpszzEnv, achPROMPT); // get the name lpszzEnv += sizeof(achPROMPT); cchEnv += sizeof(achPROMPT); pTmp = pLine + sizeof(achPROMPT) - 1; // skip possible white chars while (!isgraph(*pTmp) && !ISEOL(*pTmp)) pTmp++; if (*pTmp == '=') { pTmp++; while(!isgraph(*pTmp) && !ISEOL(*pTmp)) pTmp++; } while(!ISEOL(*pTmp)){ *lpszzEnv++ = *pTmp++; cchEnv++; } // null terminate this // it may be "prompt NULL NULL" for delete // or "prompt NULL something NULL" *lpszzEnv++ = '\0'; cchEnv++; } else if (!_strnicmp(pLine, achPATH, sizeof(achPATH) - 1)) { // PATH was found, it has the same syntax as // PROMPT strcpy(lpszzEnv, achPATH); lpszzEnv += sizeof(achPATH); cchEnv += sizeof(achPATH); pTmp = pLine + sizeof(achPATH) - 1; while (!isgraph(*pTmp) && !ISEOL(*pTmp)) pTmp++; if (*pTmp == '=') { pTmp++; while(!isgraph(*pTmp) && !ISEOL(*pTmp)) pTmp++; } while(!ISEOL(*pTmp)) { *lpszzEnv++ = *pTmp++; cchEnv++; } *lpszzEnv++ = '\0'; cchEnv++; } else if(!_strnicmp(pLine, achSET, sizeof(achSET) -1 )) { // SET was found, first search for name pTmp = pLine + sizeof(achSET) - 1; while(!isgraph(*pTmp) && !ISEOL(*pTmp)) *pTmp ++; // get the name lpszName = pTmp; // looking for the '=' // note that the name can have white characters while (!ISEOL(*lpszName) && *lpszName != '=') lpszName++; if (!ISEOL(*lpszName)) { // copy the name while (pTmp < lpszName) { *lpszzEnv++ = *pTmp++; cchEnv++; } *lpszzEnv++ = '\0'; cchEnv++; // discard the '=' pTmp++; // grab the value(may be nothing while (!ISEOL(*pTmp)) { *lpszzEnv++ = *pTmp++; cchEnv++; } *lpszzEnv++ = '\0'; cchEnv++; } } dw = WriteExpanded(hTmpFile, pLine, dwRawFileSize); pLine += dw; dwRawFileSize -=dw; WriteFileAssert(hTmpFile,achEOL,sizeof(achEOL) - sizeof(CHAR)); } // END, while (dwRawFileSize) if (bConfig) { UINT OemCP; UINT CtryId; CHAR szCtryId[64]; // expect "nnn" only /* Ensure that the country settings are in sync with NT This is * especially important for DosKrnl file UPCASE tables. The * doskrnl default is "CTRY_UNITED_STATES, 437". But we add the * country= line to config.sys, even if is US,437, so that the DOS * will know where the default country.sys is. */ if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTCOUNTRY, szCtryId, sizeof(szCtryId) - 1) ) { CtryId = strtoul(szCtryId,NULL,10); } else { CtryId = CTRY_UNITED_STATES; } OemCP = GetOEMCP(); sprintf(achRawFile, "%s=%3.3u,%3.3u,%s\\system32\\%s.sys%s", achCOUNTRY, CtryId, OemCP, achSysRoot, achCOUNTRY, achEOL); WriteFileAssert(hTmpFile,achRawFile,strlen(achRawFile)); /* We cannot allow the user to set an incorrect shell= command * so we will contruct the correct shell= command appending * either (in order of precedence): * 1. /c ThirdPartyShell * 2. /e:NNNN * 3. nothing * * If there is a third party shell then we must turn the console * on now since we no longer have control once system32\command.com * spawns the third party shell. */ // write shell=.... sprintf(achRawFile, "%s=%s%s /p %s\\system32", achSHELL,achSysRoot, achCOMMAND, achSysRoot); WriteFileAssert(hTmpFile,achRawFile,strlen(achRawFile)); // write extra string (/c ... or /e:nnn) if (pPartyShell && isgraph(*pPartyShell)) { pTmp = pPartyShell; while (!ISEOL(*pTmp)) pTmp++; } else if (pEnvParam && isgraph(*pEnvParam)) { pTmp = pEnvParam; while (isgraph(*pTmp)) pTmp++; } else { pTmp = NULL; } if (pTmp) { *pTmp = '\0'; if (pPartyShell) { cmdInitConsole(); strcpy(achRawFile, " /c "); strcat(achRawFile, pPartyShell); } else if (pEnvParam) { strcpy(achRawFile, " "); strcat(achRawFile, pEnvParam); } WriteExpanded(hTmpFile, achRawFile, strlen(achRawFile)); } WriteFileAssert(hTmpFile,achEOL,sizeof(achEOL) - sizeof(CHAR)); } SetEndOfFile(hTmpFile); CloseHandle(hTmpFile); CloseHandle(hRawFile); free(pRawBuffer); if (!bConfig) { // shrink(or free) the memory if (cchEnv && lpszzcmdEnv16) { // doubld null terminate it lpszzcmdEnv16[cchEnv++] = '\0'; // shrink the memory. If it fails, simple keep // it as is lpszzEnv = realloc(lpszzcmdEnv16, cchEnv); if (lpszzEnv != NULL) lpszzcmdEnv16 = lpszzEnv; } else { free(lpszzcmdEnv16); lpszzcmdEnv16 = NULL; } } }
void parse(void) { char *s,*line,*inst; char *ext[MAX_QUALIFIERS?MAX_QUALIFIERS:1]; char *op[MAX_OPERANDS]; int ext_len[MAX_QUALIFIERS?MAX_QUALIFIERS:1]; int op_len[MAX_OPERANDS]; int ext_cnt,op_cnt,inst_len; instruction *ip; while (line = read_next_line()) { if (!cond_state()) { /* skip source until ELSE or ENDIF */ int idx = -1; s = skip(line); if (labname = parse_labeldef(&s,1)) { if (*s == ':') s++; /* skip double-colon */ myfree(labname); s = skip(s); } else { if (inst = skip_identifier(s)) { inst = skip(inst); idx = check_directive(&inst); } } if (idx < 0) idx = check_directive(&s); if (idx >= 0) { if (directives[idx].func == handle_if) cond_skipif(); else if (directives[idx].func == handle_else) cond_else(); else if (directives[idx].func == handle_endif) cond_endif(); } continue; } s = skip(line); again: if (*s=='\0' || *line=='*' || *s==commentchar) continue; if (labname = parse_labeldef(&s,1)) { /* we have found a valid global or local label */ symbol *sym = new_labsym(0,labname); if (*s == ':') { /* double colon automatically declares label as exported */ sym->flags |= EXPORT; s++; } add_atom(0,new_label_atom(sym)); myfree(labname); s = skip(s); } else { /* there can still be a sym. in the 1st fld and an assignm. directive */ inst = s; labname = parse_symbol(&s); if (labname == NULL) { syntax_error(10); /* identifier expected */ continue; } s = skip(s); /* Now we have labname pointing to the first field in the line and s pointing to the second. Find out where the directive is. */ if (!ISEOL(s)) { #ifdef PARSE_CPU_LABEL if (PARSE_CPU_LABEL(labname,&s)) { myfree(labname); continue; } #endif if (handle_directive(s)) { myfree(labname); continue; } } /* directive or mnemonic must be in the first field */ myfree(labname); s = inst; } if (!strnicmp(s,".iif",4) || !(strnicmp(s,"iif",3))) { /* immediate conditional assembly: parse line after ',' when true */ s = skip(*s=='.'?s+4:s+3); if (do_cond(&s)) { s = skip(s); if (*s == ',') { s = skip(s+1); goto again; } else syntax_error(0); /* malformed immediate-if */ } continue; } /* check for directives */ s = parse_cpu_special(s); if (ISEOL(s)) continue; if (handle_directive(s)) continue; /* read mnemonic name */ inst = s; ext_cnt = 0; if (!ISIDSTART(*s)) { syntax_error(10); /* identifier expected */ continue; } #if MAX_QUALIFIERS==0 while (*s && !isspace((unsigned char)*s)) s++; inst_len = s - inst; #else s = parse_instruction(s,&inst_len,ext,ext_len,&ext_cnt); #endif if (!isspace((unsigned char)*s) && *s!='\0') syntax_error(2); /* no space before operands */ s = skip(s); if (execute_macro(inst,inst_len,ext,ext_len,ext_cnt,s)) continue; /* read operands, terminated by comma or blank (unless in parentheses) */ op_cnt = 0; while (!ISEOL(s) && op_cnt<MAX_OPERANDS) { op[op_cnt] = s; s = skip_operand(s); op_len[op_cnt] = oplen(s,op[op_cnt]); #if !ALLOW_EMPTY_OPS if (op_len[op_cnt] <= 0) syntax_error(5); /* missing operand */ else #endif op_cnt++; s = skip(s); if (*s != ',') break; else s = skip(s+1); } eol(s); ip = new_inst(inst,inst_len,op_cnt,op,op_len); #if MAX_QUALIFIERS>0 if (ip) { int i; for (i=0; i<ext_cnt; i++) ip->qualifiers[i] = cnvstr(ext[i],ext_len[i]); for(; i<MAX_QUALIFIERS; i++) ip->qualifiers[i] = NULL; } #endif if (ip) add_atom(0,new_inst_atom(ip)); } cond_check(); /* check for open conditional blocks */ }
static void handle_print(char *s) { while (!ISEOL(s)) { if (*s == '\"') { size_t len; char *txt; skip_string(s,'\"',&len); if (len > 0) { txt = mymalloc(len+1); s = read_string(txt,s,'\"',8); txt[len] = '\0'; add_atom(0,new_text_atom(txt)); } } else { int type = PEXP_HEX; int size = 16; while (*s == '/') { /* format character */ char f; s = skip(s+1); f = tolower((unsigned char)*s); if (s = skip_identifier(s)) { switch (f) { case 'x': type = PEXP_HEX; break; case 'd': type = PEXP_SDEC; break; case 'u': type = PEXP_UDEC; break; case 'w': size = 16; break; case 'l': size = 32; break; default: syntax_error(7,f); /* unknown print format flag */ break; } } else { syntax_error(9); /* print format corrupted */ break; } s = skip(s); } add_atom(0,new_expr_atom(parse_expr(&s),type,size)); } s = skip(s); if (*s != ',') break; s = skip(s+1); } add_atom(0,new_text_atom(NULL)); /* new line */ eol(s); }
void eol(char *s) { s = skip(s); if (!ISEOL(s)) syntax_error(6); }
/* * gettokens - read a line and return tokens */ static int gettokens( FILE *fp, char *line, char **tokenlist, int *ntokens ) { register char *cp; register int eol; register int ntok; register int quoted = 0; /* * Find start of first token */ again: while ((cp = fgets(line, MAXLINE, fp)) != NULL) { cp = line; while (ISSPACE(*cp)) cp++; if (!ISEOL(*cp)) break; } if (cp == NULL) { *ntokens = 0; return CONFIG_UNKNOWN; /* hack. Is recognized as EOF */ } /* * Now separate out the tokens */ eol = 0; ntok = 0; while (!eol) { tokenlist[ntok++] = cp; while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted)) quoted ^= (*cp++ == '"'); if (ISEOL(*cp)) { *cp = '\0'; eol = 1; } else { /* must be space */ *cp++ = '\0'; while (ISSPACE(*cp)) cp++; if (ISEOL(*cp)) eol = 1; } if (ntok == MAXTOKENS) eol = 1; } /* * Return the match */ *ntokens = ntok; ntok = matchkey(tokenlist[0], keywords); if (ntok == CONFIG_UNKNOWN) goto again; return ntok; }