void MacroDef::Init (const TextStream & name, int numArgs) { // Only allowing arg values between 0 and 9, inclusive. assert (numArgs < 100); assert (numArgs >= 0); assert (name.GetLength()); _definition.Clear (); _numArgs = numArgs; _name = name; }
ArgSet::eInitArgsStat ArgSet::InitArgs (TextStream & text, int numExpected) { // we'll re-init even if we've been init'd already _args.Clear (); if (! numExpected) { // If no args expected, don't try to consume "()" return kInitNoError; } if (! text.Expect ("(")) return kInitNoStartParen; while (numExpected--) { ArgDef thisArg; ArgDef::eInitStat stat; if (! text.GetLength()) return kInitArgsTooFew; // // why did this line cause Purify to // think there was a memory leak? // // if (text.Expect(")")) TextStream closeParen (")"); if (text.Expect(closeParen)) { return kInitArgsTooFew; } stat = thisArg.Init (text); switch (stat) { case ArgDef::kInitBadEscape: return kInitNoEndParen; case ArgDef::kInitNotTerminated: return kInitNoEndParen; default: // unknown error assert (0); break; case ArgDef::kInitNoError: _args.Append (thisArg); break; } } if (! text.Expect(")")) { return kInitArgsTooMany; } return kInitNoError; }
void MacroDef::Test () { // // ctor // MacroDef md; assert (0 == md._numArgs); assert (0 == md._name.GetLength()); assert (0 == md._definition.GetLength()); // // Init() // TextStream name = "mac"; md.Init (name, 2); assert (2 == md._numArgs); assert (3 == md._name.GetLength()); assert (md._name.Snoop("mac")); // // AppendMacroExpansion() // TextStream exp; eAppendStat aStat; TextStream ts; exp = "arg %03 too great"; aStat = md.AppendMacroExpansion (exp); assert (kAppendArgRange == aStat); exp = "arg %x illegal"; aStat = md.AppendMacroExpansion (exp); assert (kAppendBadArg == aStat); md.Init (name, 2); // re-init to clear out old macro def crap assert (0 == md._definition.GetLength()); exp = "Second=%02, First=%01"; aStat = md.AppendMacroExpansion (exp); assert (kAppendNoError == aStat); assert (0 != md._definition.GetLength()); ts = md._definition; assert (ts.GetLength()); assert (ts.Expect ("Second=%02, First=%01")); assert (! ts.GetLength()); // // IsMacro() // TextStream input; bool stat; input = "amac"; stat = md.IsMacro (input); assert (! stat); input = "macro"; stat = md.IsMacro (input); assert (stat); input = "macanudo"; stat = md.IsMacro (input); assert (stat); input = "madness"; stat = md.IsMacro (input); assert (! stat); // // InvokeMacro() // TextStream output; eInvokeMacroStat iStat; SourceInfo si ("foo", 2); ArgSet as; ArgSet::eInitArgsStat iasStat; TextStream argText; argText = "(ONE!,TWO!,THREE!)"; iasStat = as.InitArgs (argText, 3); assert (ArgSet::kInitNoError == iasStat); assert (0 == output.GetLength()); iStat = md.InvokeMacro(as, output, si); assert (kInvokeWrongArgCount == iStat); assert (0 == output.GetLength()); MacroDef md2; iStat = md2.InvokeMacro(as, output, si); assert (kInvokeNotInited == iStat); md2.Init (name, 2); iStat = md2.InvokeMacro(as, output, si); assert (kInvokeWrongArgCount == iStat); assert (0 == output.GetLength()); argText = "(ONE!,TWO!)"; iasStat = as.InitArgs (argText, 2); assert (ArgSet::kInitNoError == iasStat); assert (0 == output.GetLength()); iStat = md.InvokeMacro(as, output, si); assert (kInvokeNoError == iStat); assert (0 != output.GetLength()); stat = output.Expect ("Second=TWO!, First=ONE!"); assert (stat); assert (0 == output.GetLength()); // // GetNumArgs() // assert (2 == md2.GetNumArgs()); md2.Init (name, 0); assert (0 == md2.GetNumArgs()); assert (2 == md.GetNumArgs()); }
MacroDef::eInvokeMacroStat MacroDef::InvokeMacro (const ArgSet & args, TextStream & outText, const SourceInfo &si) const { if (! _name.GetLength()) { return kInvokeNotInited; } if (args.GetNumArgs() != _numArgs) { return kInvokeWrongArgCount; } TextStream tmp = _definition; while (tmp.GetLength()) { bool stat; char c; stat = tmp.Consume (c); assert (stat); if ('%' != c) { outText.Append (c); } else { // Looks like a macro argument invocation, maybe! stat = tmp.Consume (c); assert (stat); // should have already checked for this in // AppendMacroExpansion() if ('%' == c) { // Not a macro, just an escaped '%' outText.Append (c); } else { int idx = c - '0'; TextStream txt; stat = tmp.Consume (c); assert (stat); // should have already checked for // this in AppendMacroExpansion() assert (c >= '0'); assert (c <= '9'); idx = idx * 10 + (c - '0'); // AppendMacroExpansion should have already checked for // proper range assert (idx > 0); assert (idx < 100); txt = args.GetArg(idx-1).GetText(); // index is 0-based outText.SetCurSourceInfo (si); outText.Append (txt); } } } return kInvokeNoError; }
void ArgDef::Test () { // // Init(), GetText() // ArgDef ad; TextStream ts; TextStream input; eInitStat stat; assert (0 == ad._rep.GetLength()); input = "something"; stat = ad.Init (input); assert (kInitNotTerminated == stat); input = "proper)"; stat = ad.Init (input); assert (kInitNoError == stat); ts = ad.GetText (); assert (0 != ts.GetLength()); assert (ts.Expect ("proper")); assert (0 == ts.GetLength()); assert (input.Expect (")")); assert (0 == input.GetLength()); input = "(paren in arg)"; stat = ad.Init (input); assert (kInitNoError == stat); ts = ad.GetText (); assert (0 != ts.GetLength()); assert (ts.Expect ("(paren in arg")); assert (0 == ts.GetLength()); assert (input.Expect (")")); assert (0 == input.GetLength()); input = "middle arg,yup)"; stat = ad.Init (input); assert (kInitNoError == stat); ts = ad.GetText (); assert (0 != ts.GetLength()); assert (ts.Expect ("middle arg")); assert (0 == ts.GetLength()); assert (input.Expect ("yup)")); assert (0 == input.GetLength()); input = "comma in\\, arg, here"; stat = ad.Init (input); assert (kInitNoError == stat); ts = ad.GetText (); assert (0 != ts.GetLength()); assert (ts.Expect ("comma in, arg")); assert (0 == ts.GetLength()); assert (input.Expect (" here")); assert (0 == input.GetLength()); input = " \t\t\n\t White\tspace in here.,"; stat = ad.Init (input); assert (kInitNoError == stat); ts = ad.GetText (); assert (0 != ts.GetLength()); assert (ts.Expect ("White\tspace in here.")); assert (0 == ts.GetLength()); assert (0 == input.GetLength()); input = "bad escape\\"; stat = ad.Init (input); assert (kInitBadEscape == stat); }