/* IScanner */ static inline int ParseComment(struct IParse *parse) { while (ParseCommentLine(parse)); return 0; }
//--------------------------------------------------------------------------- // FetchLine // // This function "scans" the next parse-able line into the given buffer, // along with the file index and line number information that the parser will // use for error reporting and OP_LINE information. // // RETURNS: 1 if line copied, 0 if end of script), or -1 if error. //--------------------------------------------------------------------------- INT FetchLine (LPSTR szLineBuf, UINT FAR *nFile, UINT FAR *nLine) { // This while loop executes until an actual line is copied to the buffer, // or until we hit the end of the script, or until an error occurs. //----------------------------------------------------------------------- while (GetRawLine(szLineBuf) && (!fScanErr)) { szLine = szLineBuf; idx = 0; NextToken(); if ((curtok[0] == '\'') || (!_stricmp (curtok, szREM))) { INT type; // This line is a comment or metacommand. Parse it and find out. //--------------------------------------------------------------- type = ParseCommentLine (); switch (type) { case MC_DEFINE: // Add the symbol to the symbol table if CUR_STATE //------------------------------------------------------- if (CUR_STATE) { NextToken(); if (strchr (szSpecials, *curtok)) ScanError (SCN_SYMEXP); else if (!AddSymbol (pSymRoot, curtok)) ScanError (SCN_OSS); // Now make sure the rest of the line is either empty // or a comment character //--------------------------------------------------- CompleteLine(); } break; case MC_UNDEF: // Remove the symbol from the symbol table if CUR_STATE //------------------------------------------------------- if (CUR_STATE) { NextToken(); if (strchr (szSpecials, *curtok)) ScanError (SCN_SYMEXP); else RemoveSymbol (pSymRoot, curtok); // Now make sure the rest of the line is either empty // or a comment character //--------------------------------------------------- CompleteLine(); } break; case MC_IFDEF: case MC_IFNDEF: { BOOL truth; // Evaluate the symbol expression //------------------------------------------------------- truth = SymbolExpression(); if (type == MC_IFNDEF) truth = !truth; // Act accordingly //------------------------------------------------------- if (truth) truth = PushState (CUR_STATE, 0, CUR_STATE); else truth = PushState (0, 0, 0); if (!truth) ScanError (SCN_TOODEEP); break; } case MC_ELSEIFDEF: case MC_ELSEIFNDEF: // Check to see if we've seen an ELSE or are in an IF // block at all. Given an error if appropriate //------------------------------------------------------- if ((CUR_ELSESEEN) || (CUR_FILE.pIfStack == pIfStack)) ScanError (SCN_UNXPELSE); else { BOOL truth; // Evaluate the symbol expression //--------------------------------------------------- truth = SymbolExpression(); if (type == MC_ELSEIFNDEF) truth = !truth; // Act as appropriate //--------------------------------------------------- if (truth) { if (CUR_BLKCOPIED) CUR_STATE = 0; else CUR_STATE = CUR_BLKCOPIED = LAST_STATE; } else CUR_STATE = 0; } break; case MC_ELSE: if ((CUR_ELSESEEN) || (CUR_FILE.pIfStack == pIfStack)) ScanError (SCN_UNXPELSE); else { CUR_STATE = (CUR_STATE ^ LAST_STATE) & (!CUR_BLKCOPIED); CUR_ELSESEEN = 1; // Now make sure the rest of the line is either empty // or a comment character //--------------------------------------------------- //CompleteLine(); } break; case MC_ENDIF: if (CUR_FILE.pIfStack == pIfStack) ScanError (SCN_UNXPENDIF); else { PopState (); // Now make sure the rest of the line is either empty // or a comment character //--------------------------------------------------- //CompleteLine(); } break; case MC_INCLUDE: if (CUR_STATE) LoadIncludeFile(); break; } } else if (CUR_STATE && curtok[0]) { // This was not a comment, and we're not yanking this block, so // fill in the other data items and return this line. //--------------------------------------------------------------- *nFile = nFileIdx; *nLine = CUR_FILE.nLineNo; return (1); } } // The only way out of the loop above is if we're at the end of the // script, or an error occurred. Either way, this is it for the scan/ // parse process, so clean up before we return to the parser. First, // if there's more than one node on the IFREC stack, we didn't get an // ENDIF somewhere... //----------------------------------------------------------------------- if (pIfStack->next) ScanError (SCN_ENDIFEXP); // Get rid of the DEFINE table and last of the IFDEF stack //----------------------------------------------------------------------- FreeSymbolTree (pSymRoot); pSymRoot = NULL; FreeIfStack (); // Make sure the callback loader gets a chance to "unload" everything. // The lpFI table gets freed later -- after the basic engine returns. //----------------------------------------------------------------------- UnloadAllFiles (); // Zero-terminate the line buffer, and return 0 if no error. //----------------------------------------------------------------------- szLineBuf[0] = 0; return (fScanErr ? -1 : 0); }