private string ApplyDefines(string parameter, DefineCollection defcol, bool firstParam) { parameter = parameter.Trim(); if (parameter.StartsWith("@")) { messageHandler.AddWarning("Do not use @ in front of defined parameter or lable: " + parameter); parameter = parameter.TrimStart('@'); if (firstParam) { parameter += ":"; } } if (parameter.ContainsAnyOf(extraLineSplitters)) { string[] splitLine = parameter.Split(extraLineSplitters, StringSplitOptions.RemoveEmptyEntries); StringBuilder newline = new StringBuilder(); for (int i = 0; i < splitLine.Length; i++) { splitLine[i] = ApplyDefines("\"" + splitLine[i] + "\"", defcol, firstParam && i == 0); newline.Append(splitLine[i] + ";"); } return(newline.ToString(0, newline.Length - 1)); } int index = parameter.IndexOf('('); int arithIndex = parameter.IndexOfAny(wordArithmetchic); bool startsWith = parameter.StartsWith("["); bool endsWith = parameter.EndsWith("]"); bool startsWithQuote = parameter.StartsWith("\""); bool endsWithQuote = parameter.EndsWith("\""); if (startsWith && endsWith)//Coordinate handling { string[] parameters = parameter.Trim('[', ']').Split(','); StringBuilder newLine = new StringBuilder(); if (parameters.Length > 1) { newLine.Append("["); for (int i = 0; true; i++) { newLine.Append(ApplyDefines(parameters[i], defcol, false)); if (i == parameters.Length - 1) { break; } newLine.Append(","); } newLine.Append("]"); } else { newLine.Append(ApplyDefines(parameters[0], defcol, false)); } return(newLine.ToString()); } else if (startsWith != endsWith)//Vector calculus: 1*[8,9] one day? { messageHandler.AddError("Error with parameter: " + parameter + ". Coordinate problem."); return("0"); } else if (startsWithQuote && endsWithQuote) { string[] parameters = parameter.Trim('\"').Split(' '); StringBuilder newLine = new StringBuilder(); if (parameters.Length > 1) { for (int i = 0; true; i++) { newLine.Append(ApplyDefines(parameters[i], defcol, false)); if (i == parameters.Length - 1) { break; } newLine.Append(" "); } } else { newLine.Append(ApplyDefines(parameters[0], defcol, false)); } return(newLine.ToString()); } else if (startsWithQuote != endsWithQuote) { messageHandler.AddError("Error with parameter: " + parameter + ". Quote problem."); return("0"); } else if (index > 0 && (index <= arithIndex || arithIndex < 0))//handle macros { string macroName = parameter.Substring(0, index); string macroParameters = parameter.Substring(index + 1, parameter.Length - index - 2); string[] macroParametersSplit = macroParameters.Split( macroParameterSplitCharacters, parameterUniterCharacters); List <string> appliedParameters = new List <string>(); for (int i = 0; i < macroParametersSplit.Length; i++) { macroParametersSplit[i] = ApplyDefines(macroParametersSplit[i], defcol, false); appliedParameters.AddRange(macroParametersSplit[i].Trim().Split(',')); } string[] macroParametersArray = appliedParameters.ToArray(); KeyValuePair <string, string[]> replacer = defcol.GetReplacerAndParameters( macroName, macroParametersArray); if (replacer.Key == null || replacer.Value == null) { messageHandler.AddError("Match for macro not found: " + parameter); return(parameter); } parameter = replacer.Key.ReplaceEach(replacer.Value, macroParametersArray); parameter = parameter.Trim('\"'); return(ApplyDefines(parameter, defcol, false)); } else if (arithIndex >= 0)//Arithmetic { #region Mess and lots of it int inBeg = parameter.AmountInTheBeginning('('); int inEnd = parameter.AmountInTheEnd(')'); int min = Math.Min(inBeg, inEnd); if (min > 0) { parameter = parameter.Substring(min, parameter.Length - 2 * min); } int parenthIndex = parameter.IndexOf('('); int multIndex = parameter.IndexOfAny(new char[] { '*', '/', '%' }); int additionIndex = parameter.IndexOfAny(new char[] { '+', '-' }); int binaryIndex = parameter.IndexOfAny(new char[] { '&', '|', '^' }); if (parenthIndex >= 0) { int endIndex = parameter.IndexOf(')', parenthIndex); if (endIndex < 0) { //throw error } string first = parameter.Substring(parenthIndex + 1, endIndex - parenthIndex - 1); int parenthValue = StringExtensions.GetValue(ApplyDefines(first, defcol, firstParam)); return(ApplyDefines(parameter.Replace("(" + first + ")", parenthValue.ToString()), defcol, false)); } else { //int index; if (binaryIndex >= 0) { index = binaryIndex; } else if (additionIndex >= 0) { index = additionIndex; } else if (multIndex >= 0) { index = multIndex; } else { index = 0; } string first = parameter.Substring(0, index); string second = parameter.Substring(index + 1); int value1 = 0; int value2 = 0; if (first.IsValidNumber()) { value1 = StringExtensions.GetValue(ApplyDefines(first, defcol, firstParam)); } if (second.IsValidNumber()) { value2 = StringExtensions.GetValue(ApplyDefines(second, defcol, false)); } int value; switch (parameter[index]) { case '*': value = value1 * value2; break; case '/': value = value1 / value2; break; case '%': value = value1 % value2; break; case '+': value = value1 + value2; break; case '-': value = value1 - value2; break; case '&': value = value1 & value2; break; case '|': value = value1 | value2; break; case '^': value = value1 ^ value2; break; default: throw new InvalidOperationException(); } return(value.ToString()); } #endregion } else if (defcol.ContainsName(parameter))//The most common case { parameter = ApplyDefines(defcol.GetReplacer(parameter), defcol, firstParam); parameter = parameter.Trim('\"'); return(parameter); } return(parameter); }
private void Preprocess(TextReader reader, string file, DefineCollection defCol, ICollection <string> lines, Stack <bool> ifStack) { int stackDepth = ifStack.Count; string line; bool include = ifStack.And(); while ((line = reader.ReadLine()) != null) { line = line.Trim(); if (line.Length > 0) { if (line[0] == '#') { string[] splitLine = StringExtensions.Split(line, parameterSplitCharacters, parameterUniterCharacters); //string[] splitLine = StringHelper.DivideLine(line); switch (splitLine[0].ToLower()) { case define: if (include) { if (splitLine.Length > 1) { if (splitLine[1].Equals(defineFile)) { string path = IOHelpers.FindFile(file, splitLine[2]); if (!string.IsNullOrEmpty(path)) { IOHelpers.DefineFile(path, defCol); } else { messageHandler.AddFileNotFoundError(file, line, splitLine[2]); } } else { int indexBeg = splitLine[1].IndexOf('('); int indexEnd = splitLine[1].IndexOf(')'); if (indexBeg >= 0 && indexEnd >= 0 && indexBeg < indexEnd) { string parametersList = splitLine[1].Substring(indexBeg + 1, indexEnd - indexBeg - 1); string[] parameters = parametersList.Split(','); string original = splitLine[1].Substring(0, indexBeg); for (int i = 0; i < parameters.Length; i++) { parameters[i] = parameters[i].Trim(); } defCol.Add(original, splitLine[2], parameters); } else if (indexBeg == -1 && indexEnd == -1) { if (splitLine.Length > 2) { defCol.Add(splitLine[1], splitLine[2]); } else { defCol.Add(splitLine[1], ""); } } else { messageHandler.AddError(define + " is improperly defined: " + line); } } } else { messageHandler.AddNotEnoughParametersError(file, line, define, 1); } } break; case unDefine: if (include) { if (splitLine.Length > 1) { defCol.Remove(splitLine[1]); } else { messageHandler.AddNotEnoughParametersError(file, line, unDefine, 1); } } break; case includeFile: if (include) { if (splitLine.Length > 1) { string path = IOHelpers.FindFile(file, splitLine[1]); if (!string.IsNullOrEmpty(path)) { string moreText = File.ReadAllText(path); moreText = this.RemoveComments(moreText); lines.Add("{"); using (StringReader newReader = new StringReader(moreText)) { Preprocess(newReader, path, defCol, lines, ifStack); //Preprocess(moreText, path, defCol, lines, ifStack); } lines.Add("}"); } else { messageHandler.AddFileNotFoundError(file, line, splitLine[1]); } } else { messageHandler.AddNotEnoughParametersError(file, line, includeFile, 1); } } break; case includeBinary: if (include) { if (splitLine.Length > 1) { string path = IOHelpers.FindFile(file, splitLine[1]); if (!string.IsNullOrEmpty(path)) { byte[] data = File.ReadAllBytes(path); StringBuilder newLine = new StringBuilder("CODE"); for (int i = 0; i < data.Length; i++) { newLine.Append(data[i].ToHexString(" 0x")); } lines.Add(newLine.ToString()); } else { messageHandler.AddFileNotFoundError(file, line, splitLine[1]); } } else { messageHandler.AddNotEnoughParametersError(file, line, includeBinary, 1); } } break; case ifDefined: if (splitLine.Length > 1) { ifStack.Push(defCol.ContainsName(splitLine[1])); include = ifStack.And(); } else { messageHandler.AddNotEnoughParametersError(file, line, ifDefined, 1); } break; case ifNotDefined: if (splitLine.Length > 1) { ifStack.Push(!defCol.ContainsName(splitLine[1])); include = ifStack.And(); } else { messageHandler.AddNotEnoughParametersError(file, line, ifNotDefined, 1); } break; case ifElse: bool top = ifStack.Pop(); ifStack.Push(!top); include = ifStack.And(); break; case ifEnd: ifStack.Pop(); include = ifStack.And(); break; case "#org": lines.Add(line.Substring(1)); messageHandler.AddWarning("#ORG no longer exists. Use ORG instead."); break; default: messageHandler.AddError(splitLine[0] + " is not usable preprocessor command: " + line); break; } } else if (include) { string[] newLines = line.Split(extraLineSplitters); for (int i = 0; i < newLines.Length; i++) { lines.Add(newLines[i]); } } } } if (ifStack.Count != stackDepth) { messageHandler.AddWarning("#IFDEF stack unbalanced in file " + file + "."); } }