// ------------------------------------------------------------------------ private void SearchForMacros(List <Token> tokenList, Stack <string> nameStack) { for (int index = 0; index < tokenList.Count; ++index) { Token thisToken = tokenList[index]; /*if (CCompiler_Main.Scanner.Path.Name.Contains("AssertTest")) { * Console.Out.WriteLine("5: " + CCompiler_Main.Scanner.Line); * }*/ CCompiler_Main.Scanner.Line += thisToken.GetNewlineCount(); if (thisToken.Id == CCompiler_Pre.Tokens.NAME) { string name = (string)thisToken.Value; int beginNewlineCount = thisToken.GetNewlineCount(); if (!nameStack.Contains(name) && Preprocessor.MacroMap.ContainsKey(name)) { Token nextToken = tokenList[index + 1]; if ((nextToken.Id == CCompiler_Pre.Tokens.LEFT_PARENTHESIS) && !nextToken.HasWhitespace()) { int countIndex = index + 2, level = 1, totalNewlineCount = 0; List <Token> subList = new List <Token>(); List <List <Token> > mainList = new List <List <Token> >(); while (true) { nextToken = tokenList[countIndex]; int newlineCount = nextToken.GetNewlineCount(); totalNewlineCount += newlineCount; CCompiler_Main.Scanner.Line += newlineCount; /*if (CCompiler_Main.Scanner.Path.Name.Contains("AssertTest")) { * Console.Out.WriteLine("6: " + CCompiler_Main.Scanner.Line); * }*/ nextToken.ClearNewlineCount(); Token token = tokenList[countIndex]; Assert.Error(token.Id != CCompiler_Pre.Tokens.EOF, Message.Invalid_end_of_macro_call); switch (token.Id) { case CCompiler_Pre.Tokens.LEFT_PARENTHESIS: ++level; subList.Add(token); break; case CCompiler_Pre.Tokens.RIGHT_PARENTHESIS: if ((--level) > 0) { subList.Add(token); } break; default: if ((level == 1) && (token.Id == CCompiler_Pre.Tokens.COMMA)) { Assert.Error(subList.Count > 0, name, Message.Empty_macro_parameter); SearchForMacros(subList, nameStack); // XXX mainList.Add(subList); subList = new List <Token>(); } else { subList.Add(token); } break; } if (level == 0) { Assert.Error(subList.Count > 0, name, Message.Empty_macro_parameter_list); mainList.Add(subList); break; } ++countIndex; } Macro macro = Preprocessor.MacroMap[name]; Assert.Error(macro.Parameters() == mainList.Count, name, Message.Invalid_number_of_parameters_in_macro_call); List <Token> cloneListX = CloneList(macro.TokenList()); for (int macroIndex = (cloneListX.Count - 1); macroIndex >= 0; --macroIndex) { Token macroToken = cloneListX[macroIndex]; if (macroToken.Id == CCompiler_Pre.Tokens.MARK) { int markIndex = (int)macroToken.Value; cloneListX.RemoveAt(macroIndex); List <Token> replaceList = CloneList(mainList[markIndex]); if ((macroIndex > 0) && (cloneListX[macroIndex - 1].Id == CCompiler_Pre.Tokens.SHARP)) { string text = "\"" + TokenListToString(replaceList) + "\""; cloneListX.Insert(macroIndex, new Token(CCompiler_Pre.Tokens.STRING, text)); cloneListX.RemoveAt(--macroIndex); } else { cloneListX.InsertRange(macroIndex, replaceList); } } } nameStack.Push(name); SearchForMacros(cloneListX, nameStack); nameStack.Pop(); /*for (int removeCount = index; removeCount <= countIndex; ++removeCount) { * tokenList.RemoveAt(index); * }*/ tokenList.RemoveRange(index, countIndex - index + 1); tokenList.InsertRange(index, cloneListX); tokenList[index].AddNewlineCount(beginNewlineCount); tokenList[index + cloneListX.Count].AddNewlineCount(totalNewlineCount); index += cloneListX.Count - 1; } else { Macro macro = Preprocessor.MacroMap[name]; Assert.Error(macro.Parameters() == 0, name, Message.Invalid_number_of_parameters_in_macro_call); List <Token> cloneListX = CloneList(macro.TokenList()); nameStack.Push(name); SearchForMacros(cloneListX, nameStack); nameStack.Pop(); tokenList.RemoveAt(index); tokenList.InsertRange(index, cloneListX); tokenList[index].AddNewlineCount(beginNewlineCount); index += cloneListX.Count - 1; } } else if (name.Equals("__STDC__")) { tokenList[index] = new Token(CCompiler_Pre.Tokens.TOKEN, 1, beginNewlineCount); } else if (name.Equals("__FILE__")) { string text = "\"" + CCompiler_Main.Scanner.Path.FullName.Replace("\\", "\\\\") + "\""; tokenList[index] = new Token(CCompiler_Pre.Tokens.TOKEN, text, beginNewlineCount); } else if (name.Equals("__LINE__")) { /*if (CCompiler_Main.Scanner.Path.Name.Contains("AssertTest")) { * Console.Out.WriteLine("__LINE__ " + CCompiler_Main.Scanner.Line); * }*/ tokenList[index] = new Token(CCompiler_Pre.Tokens.TOKEN, CCompiler_Main.Scanner.Line, beginNewlineCount); } else if (name.Equals("__DATE__")) { string text = "\"" + DateTime.Now.ToString("MMMM dd yyyy") + "\""; tokenList[index] = new Token(CCompiler_Pre.Tokens.TOKEN, text, beginNewlineCount); } else if (name.Equals("__TIME__")) { string text = "\"" + DateTime.Now.ToString("HH:mm:ss") + "\""; tokenList[index] = new Token(CCompiler_Pre.Tokens.TOKEN, text, beginNewlineCount); } } } }
// ------------------------------------------------------------------------ private void SearchForMacros(List <Token> tokenList, Stack <string> nameStack) { for (int index = 0; index < tokenList.Count; ++index) { Token thisToken = tokenList[index]; CCompiler_Main.Scanner.Line += thisToken.GetNewlineCount(); if (thisToken.Id == CCompiler_Pre.Tokens.NAME) { string name = (string)thisToken.Value; int beginNewlineCount = thisToken.GetNewlineCount(); if (!nameStack.Contains(name) && m_macroMap.ContainsKey(name)) { Macro macro = m_macroMap[name]; Error.Check(macro.Parameters == 0, name, Message. Invalid_number_of_parameters_in_macro_call); List <Token> cloneListX = CloneList(macro.TokenList); nameStack.Push(name); SearchForMacros(cloneListX, nameStack); nameStack.Pop(); tokenList.RemoveAt(index); tokenList.InsertRange(index, cloneListX); tokenList[index].AddNewlineCount(beginNewlineCount); index += cloneListX.Count - 1; } else { switch (name) { case "__STDC__": tokenList[index] = new Token(CCompiler_Pre.Tokens.TOKEN, 1, beginNewlineCount); break; case "__FILE__": { string text = "\"" + CCompiler_Main.Scanner.Path .FullName.Replace("\\", "\\\\") + "\""; tokenList[index] = new Token(CCompiler_Pre.Tokens.TOKEN, text, beginNewlineCount); } break; case "__LINE__": tokenList[index] = new Token(CCompiler_Pre.Tokens.TOKEN, CCompiler_Main.Scanner.Line, beginNewlineCount); break; case "__DATE__": { string text = "\"" + DateTime.Now.ToString("MMMM dd yyyy") + "\""; tokenList[index] = new Token(CCompiler_Pre.Tokens.TOKEN, text, beginNewlineCount); } break; case "__TIME__": { string text = "\"" + DateTime.Now.ToString("HH:mm:ss") + "\""; tokenList[index] = new Token(CCompiler_Pre.Tokens.TOKEN, text, beginNewlineCount); } break; } } } else if (thisToken.Id == CCompiler_Pre.Tokens.NAME_WITH_PARENTHESES) { string name = (string)thisToken.Value; int beginNewlineCount = thisToken.GetNewlineCount(); if (!nameStack.Contains(name) && m_macroMap.ContainsKey(name)) { int countIndex = index + 1, level = 1, totalNewlineCount = 0; List <Token> subList = new List <Token>(); List <List <Token> > mainList = new List <List <Token> >(); while (true) { Token nextToken = tokenList[countIndex]; int newlineCount = nextToken.GetNewlineCount(); totalNewlineCount += newlineCount; CCompiler_Main.Scanner.Line += newlineCount; nextToken.ClearNewlineCount(); Token token = tokenList[countIndex]; Error.Check(token.Id != CCompiler_Pre.Tokens.END_OF_LINE, Message.Invalid_end_of_macro_call); switch (token.Id) { case CCompiler_Pre.Tokens.LEFT_PARENTHESIS: ++level; subList.Add(token); break; case CCompiler_Pre.Tokens.RIGHT_PARENTHESIS: if ((--level) > 0) { subList.Add(token); } break; default: if ((level == 1) && (token.Id == CCompiler_Pre.Tokens.COMMA)) { Error.Check(subList.Count > 0, name, Message.Empty_macro_parameter); SearchForMacros(subList, nameStack); // XXX mainList.Add(subList); subList = new List <Token>(); } else { subList.Add(token); } break; } if (level == 0) { Error.Check(subList.Count > 0, name, Message.Empty_macro_parameter_list); mainList.Add(subList); break; } ++countIndex; } Macro macro = m_macroMap[name]; Error.Check(macro.Parameters == mainList.Count, name, Message.Invalid_number_of_parameters_in_macro_call); List <Token> cloneList = CloneList(macro.TokenList); IDictionary <int, int> indexToParamMap = macro.IndexToParamMap; for (int macroIndex = (cloneList.Count - 1); macroIndex >= 0; --macroIndex) { Token macroToken = cloneList[macroIndex]; int paramIndex; if (indexToParamMap.TryGetValue(macroIndex, out paramIndex)) { cloneList.RemoveAt(macroIndex); List <Token> replaceList = CloneList(mainList[paramIndex]); if ((macroIndex > 0) && (cloneList[macroIndex - 1].Id == CCompiler_Pre.Tokens.SHARP)) { string text = "\"" + TokenListToString(replaceList) + "\""; cloneList.Insert(macroIndex, new Token(CCompiler_Pre.Tokens.STRING, text)); cloneList.RemoveAt(--macroIndex); } else { cloneList.InsertRange(macroIndex, replaceList); } } } nameStack.Push(name); SearchForMacros(cloneList, nameStack); nameStack.Pop(); tokenList.RemoveRange(index, countIndex - index + 1); tokenList.InsertRange(index, cloneList); tokenList[index].AddNewlineCount(beginNewlineCount); tokenList[index + cloneList.Count].AddNewlineCount(totalNewlineCount); index += cloneList.Count - 1; } } } }
// ------------------------------------------------------------------------ public void DoDefine(List <Token> tokenList) { Assert.Error(tokenList[2].Id == CCompiler_Pre.Tokens.NAME, TokenListToString(tokenList), Message.Invalid_define_directive); string name = tokenList[2].ToString(); Macro macro; if ((tokenList[3].Id == CCompiler_Pre.Tokens.LEFT_PARENTHESIS) && !tokenList[3].HasWhitespace()) { int tokenIndex = 4, paramIndex = 0; IDictionary <string, int> paramMap = new Dictionary <string, int>(); while (true) { Token nextToken = tokenList[tokenIndex++]; Assert.Error(nextToken.Id == CCompiler_Pre.Tokens.NAME, nextToken.ToString(), Message.Invalid_macro_definitializerion); string paramName = (string)nextToken.Value; Assert.Error(!paramMap.ContainsKey(paramName), paramName, Message.Repeated_macro_parameter); paramMap.Add(paramName, paramIndex++); nextToken = tokenList[tokenIndex++]; if (nextToken.Id == CCompiler_Pre.Tokens.COMMA) { // Empty. } else if (nextToken.Id == CCompiler_Pre.Tokens.RIGHT_PARENTHESIS) { break; } else { Assert.Error(nextToken.ToString(), Message.Invalid_macro_definitializerion); } } List <Token> macroList = tokenList.GetRange(tokenIndex, tokenList.Count - tokenIndex); foreach (Token macroToken in macroList) { if (macroToken.Id == CCompiler_Pre.Tokens.NAME) { string macroName = (string)macroToken.Value; if (paramMap.ContainsKey(macroName)) { macroToken.Id = CCompiler_Pre.Tokens.MARK; macroToken.Value = paramMap[macroName]; } } } macro = new Macro(paramMap.Count, macroList); } else { macro = new Macro(0, tokenList.GetRange(3, tokenList.Count - 3)); } if (!Preprocessor.MacroMap.ContainsKey(name)) { Preprocessor.MacroMap.Add(name, macro); } else { Assert.Error(Preprocessor.MacroMap[name].Equals(macro), name, Message.Invalid_macro_redefinitializerion); } }
// ------------------------------------------------------------------------ public void DoDefine(List <Token> tokenList) { Error.Check((tokenList[2].Id == CCompiler_Pre.Tokens.NAME) || (tokenList[2].Id == CCompiler_Pre.Tokens.NAME_WITH_PARENTHESES), TokenListToString(tokenList), Message.Invalid_define_directive); Macro macro; if (tokenList[2].Id == CCompiler_Pre.Tokens.NAME) { macro = new Macro(0, tokenList.GetRange(3, tokenList.Count - 3), null); } else { int tokenIndex = 3, paramIndex = 0; IDictionary <string, int> paramMap = new Dictionary <string, int>(); while (true) { Token nextToken = tokenList[tokenIndex++]; Error.Check(nextToken.Id == CCompiler_Pre.Tokens.NAME, nextToken.ToString(), Message.Invalid_macro_definition); string paramName = (string)nextToken.Value; Error.Check(!paramMap.ContainsKey(paramName), paramName, Message.Repeated_macro_parameter); paramMap.Add(paramName, paramIndex++); nextToken = tokenList[tokenIndex++]; if (nextToken.Id == CCompiler_Pre.Tokens.COMMA) { // Empty. } else if (nextToken.Id == CCompiler_Pre.Tokens.RIGHT_PARENTHESIS) { break; } else { Error.Report(nextToken.ToString(), Message.Invalid_macro_definition); } } List <Token> macroList = tokenList.GetRange(tokenIndex, tokenList.Count - tokenIndex); for (int index = macroList.Count - 1; index >= 0; --index) { if (macroList[index].Id == CCompiler_Pre.Tokens.NAME_WITH_PARENTHESES) { macroList[index].Id = CCompiler_Pre.Tokens.NAME; Token newToken = new Token(CCompiler_Pre.Tokens.LEFT_PARENTHESIS, "("); macroList.Insert(index + 1, newToken); } } IDictionary <int, int> indexToParamMap = new Dictionary <int, int>(); for (int index = 0; index < macroList.Count; ++index) { Token macroToken = macroList[index]; if (macroToken.Id == CCompiler_Pre.Tokens.NAME) { string macroName = (string)macroToken.Value; if (paramMap.ContainsKey(macroName)) { indexToParamMap[index] = paramMap[macroName]; } } } macro = new Macro(paramMap.Count, macroList, indexToParamMap); } string name = (string)tokenList[2].Value; if (!m_macroMap.ContainsKey(name)) { m_macroMap.Add(name, macro); } else { Error.Check(m_macroMap[name].Equals(macro), name, Message.Invalid_macro_redefinition); } }