public static bool PerformPreProcessFile(string filePath, List<PreProcessFile> ppFiles, List<preprocessFile_IfDefModes> ifdefs = null, string name = "", Dictionary<string, PPDefine> defines = null) { if (name == "") name = filePath.Substring(filePath.LastIndexOf('\\') + 1); if (ifdefs == null) ifdefs = new List<preprocessFile_IfDefModes>(); if (defines == null) defines = new Dictionary<string, PPDefine>(); //Open given file StreamReader reader = new StreamReader(filePath); PreProcessFile ppFile = new PreProcessFile(filePath, name); if (ppFiles != null) ppFiles.Add(ppFile); StreamWriter writer = new StreamWriter(ppFile.FileStream); //Prepare some variables needed for the entire processing periode in this function string s; uint filelinenumber = 0; while ((s = reader.ReadLine()) != null) { filelinenumber++; //skip empty lines if (string.IsNullOrWhiteSpace(s)) { writer.WriteLine(); continue; } //Remove left & right whitespaces and tabs from current string string sTrimmed = s.TrimStart(); string leading = s.Substring(0, s.Length - sTrimmed.Length); s = sTrimmed; if (s[0] != '#') {//Current line is no define, thus handle it normally (find & replace) //Make sure we are not inside of an ifdef/ifndef that disallows further processing of following lines int i = ifdefs.Count - 1; if (i >= 0 && ifdefs[i] != preprocessFile_IfDefModes.TRUE) continue; try { //Let every define check if it is inside of current line foreach (PPDefine def in defines.Values) s = def.replace(s); } catch (Exception ex) { //Catch possible exceptions from define parsing Logger.Error(string.Concat("Experienced some error while parsing existing defines. ", ex.Message, ". file: ", filePath, ". linenumber: ", filelinenumber)); reader.Close(); return false; } writer.WriteLine(leading + s); continue; } //We DO have a define here //get end of the define name int spaceIndex = s.IndexOf(' '); if (spaceIndex < 0) spaceIndex = s.Length; //set some required variables for the switch int index = -1; int index2 = -1; //get text AFTER the define string afterDefine = s.Substring(spaceIndex).TrimStart(); writer.WriteLine(); //Check which define was used switch (s.Substring(0, spaceIndex)) { default: throw new Exception("Encountered unknown define '" + s.Substring(0, spaceIndex) + "'"); case "#include": //We are supposed to include a new file at this spot so lets do it //Beautify the filepath so we can work with it afterDefine.Trim(); string newFile; newFile = afterDefine.Trim(new char[] { '"', '\'', ' ' }); //make sure we have no self reference here if (newFile.Equals(filePath, StringComparison.OrdinalIgnoreCase)) { //Ohhh no ... some problem in OSI layer 8 reader.Close(); writer.Close(); throw new Exception("Include contains self reference. file: " + filePath + ". linenumber: " + filelinenumber); } //process the file before continuing with this try { if (!PerformPreProcessFile(newFile, ppFiles, ifdefs, afterDefine.Trim(new char[] { '<', '>', '"', '\'', ' ' }), defines)) { //A sub file encountered an error, so stop here to prevent useles waste of ressources reader.Close(); writer.Close(); return false; } } catch (Exception e) { throw new Exception(e.Message + ", from " + filePath); } break; case "#define": //The user wants to define something here while (s.EndsWith("\\")) { writer.WriteLine(); afterDefine += reader.ReadLine(); filelinenumber++; } //Get the two possible characters index that can be encountered after a define index = afterDefine.IndexOf(' '); index2 = afterDefine.IndexOf('('); //check which one is found first if (index < 0 || (index2 < index && index2 >= 0)) index = afterDefine.IndexOf('('); //check that we really got a define with a value here, if not just take the entire length as no value is needed and only value provided if (index < 0) index = afterDefine.Length; if (defines.ContainsKey(afterDefine.Substring(0, index))) { //Redefining something is not allowed, so throw an error here reader.Close(); writer.Close(); throw new Exception("Redefining a define is not allowed! Use #undefine to undef something. file: " + filePath + ". linenumber: " + filelinenumber); } //FINALLY add the define defines.Add(afterDefine.Substring(0, index), new PPDefine(afterDefine)); break; case "#undefine": //just remove straigth defines.Remove(s.Substring(spaceIndex).Trim()); break; case "#ifdef": //do required stuff for define ifs if (defines.ContainsKey(afterDefine)) ifdefs.Add(ifdefs.Count == 0 || ifdefs[ifdefs.Count - 1] == preprocessFile_IfDefModes.TRUE ? preprocessFile_IfDefModes.TRUE : preprocessFile_IfDefModes.IGNORE); else ifdefs.Add(ifdefs.Count == 0 || ifdefs[ifdefs.Count - 1] == preprocessFile_IfDefModes.TRUE ? preprocessFile_IfDefModes.FALSE : preprocessFile_IfDefModes.IGNORE); break; case "#ifndef": //do required stuff for define ifs if (defines.ContainsKey(afterDefine)) ifdefs.Add(ifdefs.Count == 0 || ifdefs[ifdefs.Count - 1] == preprocessFile_IfDefModes.TRUE ? preprocessFile_IfDefModes.FALSE : preprocessFile_IfDefModes.IGNORE); else ifdefs.Add(ifdefs.Count == 0 || ifdefs[ifdefs.Count - 1] == preprocessFile_IfDefModes.TRUE ? preprocessFile_IfDefModes.TRUE : preprocessFile_IfDefModes.IGNORE); break; case "#else": //do required stuff for define ifs index = ifdefs.Count - 1; if (index < 0) { reader.Close(); writer.Close(); throw new Exception("unexpected #else. file: " + filePath + ". linenumber: " + filelinenumber); } //swap the value of currents if scope to the correct value ifdefs[index] = (ifdefs[index] == preprocessFile_IfDefModes.TRUE ? preprocessFile_IfDefModes.FALSE : (ifdefs[index] == preprocessFile_IfDefModes.FALSE ? preprocessFile_IfDefModes.TRUE : preprocessFile_IfDefModes.IGNORE)); break; case "#endif": //do required stuff for define ifs index = ifdefs.Count - 1; if (index < 0) { reader.Close(); writer.Close(); throw new Exception("unexpected #endif. file: " + filePath + ". linenumber: " + filelinenumber); } //remove current if scope ifdefs.RemoveAt(index); break; } } reader.Close(); writer.Flush(); ppFile.resetPosition(); return true; }
public static bool PerformPreProcessFile(string filePath, List <PreProcessFile> ppFiles, List <preprocessFile_IfDefModes> ifdefs = null, string name = "", Dictionary <string, PPDefine> defines = null) { if (name == "") { name = filePath.Substring(filePath.LastIndexOf('\\') + 1); } if (ifdefs == null) { ifdefs = new List <preprocessFile_IfDefModes>(); } if (defines == null) { defines = new Dictionary <string, PPDefine>(); } //Open given file StreamReader reader = new StreamReader(filePath); PreProcessFile ppFile = new PreProcessFile(filePath, name); if (ppFiles != null) { ppFiles.Add(ppFile); } StreamWriter writer = new StreamWriter(ppFile.FileStream); //Prepare some variables needed for the entire processing periode in this function string s; uint filelinenumber = 0; while ((s = reader.ReadLine()) != null) { filelinenumber++; //skip empty lines if (string.IsNullOrWhiteSpace(s)) { writer.WriteLine(); continue; } //Remove left & right whitespaces and tabs from current string string sTrimmed = s.TrimStart(); string leading = s.Substring(0, s.Length - sTrimmed.Length); s = sTrimmed; if (s[0] != '#') {//Current line is no define, thus handle it normally (find & replace) //Make sure we are not inside of an ifdef/ifndef that disallows further processing of following lines int i = ifdefs.Count - 1; if (i >= 0 && ifdefs[i] != preprocessFile_IfDefModes.TRUE) { continue; } try { //Let every define check if it is inside of current line foreach (PPDefine def in defines.Values) { s = def.replace(s); } } catch (Exception ex) { //Catch possible exceptions from define parsing Logger.Error(string.Concat("Experienced some error while parsing existing defines. ", ex.Message, ". file: ", filePath, ". linenumber: ", filelinenumber)); reader.Close(); return(false); } writer.WriteLine(leading + s); continue; } //We DO have a define here //get end of the define name int spaceIndex = s.IndexOf(' '); if (spaceIndex < 0) { spaceIndex = s.Length; } //set some required variables for the switch int index = -1; int index2 = -1; //get text AFTER the define string afterDefine = s.Substring(spaceIndex).TrimStart(); writer.WriteLine(); //Check which define was used switch (s.Substring(0, spaceIndex)) { default: throw new Exception("Encountered unknown define '" + s.Substring(0, spaceIndex) + "'"); case "#include": //We are supposed to include a new file at this spot so lets do it //Beautify the filepath so we can work with it afterDefine.Trim(); string newFile; newFile = afterDefine.Trim(new char[] { '"', '\'', ' ' }); //make sure we have no self reference here if (newFile.Equals(filePath, StringComparison.OrdinalIgnoreCase)) { //Ohhh no ... some problem in OSI layer 8 reader.Close(); writer.Close(); throw new Exception("Include contains self reference. file: " + filePath + ". linenumber: " + filelinenumber); } //process the file before continuing with this try { if (!PerformPreProcessFile(newFile, ppFiles, ifdefs, afterDefine.Trim(new char[] { '<', '>', '"', '\'', ' ' }), defines)) { //A sub file encountered an error, so stop here to prevent useles waste of ressources reader.Close(); writer.Close(); return(false); } } catch (Exception e) { throw new Exception(e.Message + ", from " + filePath); } break; case "#define": //The user wants to define something here while (s.EndsWith("\\")) { writer.WriteLine(); afterDefine += reader.ReadLine(); filelinenumber++; } //Get the two possible characters index that can be encountered after a define index = afterDefine.IndexOf(' '); index2 = afterDefine.IndexOf('('); //check which one is found first if (index < 0 || (index2 < index && index2 >= 0)) { index = afterDefine.IndexOf('('); } //check that we really got a define with a value here, if not just take the entire length as no value is needed and only value provided if (index < 0) { index = afterDefine.Length; } if (defines.ContainsKey(afterDefine.Substring(0, index))) { //Redefining something is not allowed, so throw an error here reader.Close(); writer.Close(); throw new Exception("Redefining a define is not allowed! Use #undefine to undef something. file: " + filePath + ". linenumber: " + filelinenumber); } //FINALLY add the define defines.Add(afterDefine.Substring(0, index), new PPDefine(afterDefine)); break; case "#undefine": //just remove straigth defines.Remove(s.Substring(spaceIndex).Trim()); break; case "#ifdef": //do required stuff for define ifs if (defines.ContainsKey(afterDefine)) { ifdefs.Add(ifdefs.Count == 0 || ifdefs[ifdefs.Count - 1] == preprocessFile_IfDefModes.TRUE ? preprocessFile_IfDefModes.TRUE : preprocessFile_IfDefModes.IGNORE); } else { ifdefs.Add(ifdefs.Count == 0 || ifdefs[ifdefs.Count - 1] == preprocessFile_IfDefModes.TRUE ? preprocessFile_IfDefModes.FALSE : preprocessFile_IfDefModes.IGNORE); } break; case "#ifndef": //do required stuff for define ifs if (defines.ContainsKey(afterDefine)) { ifdefs.Add(ifdefs.Count == 0 || ifdefs[ifdefs.Count - 1] == preprocessFile_IfDefModes.TRUE ? preprocessFile_IfDefModes.FALSE : preprocessFile_IfDefModes.IGNORE); } else { ifdefs.Add(ifdefs.Count == 0 || ifdefs[ifdefs.Count - 1] == preprocessFile_IfDefModes.TRUE ? preprocessFile_IfDefModes.TRUE : preprocessFile_IfDefModes.IGNORE); } break; case "#else": //do required stuff for define ifs index = ifdefs.Count - 1; if (index < 0) { reader.Close(); writer.Close(); throw new Exception("unexpected #else. file: " + filePath + ". linenumber: " + filelinenumber); } //swap the value of currents if scope to the correct value ifdefs[index] = (ifdefs[index] == preprocessFile_IfDefModes.TRUE ? preprocessFile_IfDefModes.FALSE : (ifdefs[index] == preprocessFile_IfDefModes.FALSE ? preprocessFile_IfDefModes.TRUE : preprocessFile_IfDefModes.IGNORE)); break; case "#endif": //do required stuff for define ifs index = ifdefs.Count - 1; if (index < 0) { reader.Close(); writer.Close(); throw new Exception("unexpected #endif. file: " + filePath + ". linenumber: " + filelinenumber); } //remove current if scope ifdefs.RemoveAt(index); break; } } reader.Close(); writer.Flush(); ppFile.resetPosition(); return(true); }