2 * The contents of this file are subject to the Mozilla Public
3 * License Version 1.1 (the "License"); you may not use this file
4 * except in compliance with the License. You may obtain a copy of
5 * the License at http://www.mozilla.org/MPL/
7 * Software distributed under the License is distributed on an "AS
8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 * implied. See the License for the specific language governing
10 * rights and limitations under the License.
12 * The Original Code is the Sablotron XSLT Processor.
14 * The Initial Developer of the Original Code is Ginger Alliance Ltd.
15 * Portions created by Ginger Alliance are Copyright (C) 2000-2002
16 * Ginger Alliance Ltd. All Rights Reserved.
20 * Alternatively, the contents of this file may be used under the
21 * terms of the GNU General Public License Version 2 or later (the
22 * "GPL"), in which case the provisions of the GPL are applicable
23 * instead of those above. If you wish to allow use of your
24 * version of this file only under the terms of the GPL and not to
25 * allow others to use your version of this file under the MPL,
26 * indicate your decision by deleting the provisions above and
27 * replace them with the notice and other provisions required by
28 * the GPL. If you do not delete the provisions above, a recipient
29 * may use your version of this file under either the MPL or the
35 #ifdef SABLOT_DEBUGGER
51 #ifdef HAVE_READLINE_READLINE_H
52 #include <readline/readline.h>
54 #ifdef HAVE_READLINE_HISTORY_H
55 #include <readline/history.h>
59 ////////////////////////////////////////////////////////////
61 ////////////////////////////////////////////////////////////
63 Debugger* debugger = NULL;
68 debugger = new Debugger();
76 void debuggerEnterIdle()
78 debugger -> enterIdle();
84 #ifdef HAVE_READLINE_READLINE_H
85 aux = readline("sablot> ");
86 #ifdef HAVE_READLINE_HISTORY_H
91 aux = (char*)malloc(256);
93 fgets(aux, 256, stdin);
98 ////////////////////////////////////////////////////////////
100 ////////////////////////////////////////////////////////////
102 const char* theUsageStr =
104 " break filename:line - set the breakpoint\n" \
105 " bstat - show breakpoint stats (total/enabled/break)\n" \
106 " B - list all breakpoints\n" \
107 " condition num cond - for the breakpoint NUM set the condition COND\n" \
108 " del num - delete the breakpoint NUM\n" \
109 " disable num - (toggle) the breakpoint number NUM\n" \
110 " D - delete all breakpoints\n" \
111 " ignore num count - ignore the breakpoint NUM for COUNT times\n" \
112 "Execution control:\n" \
113 " continue - continue the execution\n" \
114 " finish - finish the current node parent\n" \
115 " kill - stop the processing immediately\n" \
116 " next - go to the next sibling\n" \
117 " run - run the processor\n" \
118 " step - continue until the next element\n" \
119 " templ - continue until the next template executed\n" \
120 "Processed data:\n" \
121 " data - set the data file\n" \
122 " param name value - set the external parameter\n" \
123 " P - list all params\n" \
124 " PP - clear all params\n" \
125 " sheet - set the stylesheet\n" \
127 " eval - evaluate the XPath expression\n" \
128 " x [list | num] - examine the current context\n" \
130 " batch filename - load the command set for file\n" \
131 " help - print this help\n" \
132 " output - toggles output on/off\n" \
133 " point - show where you are\n" \
134 " quit - quite the debgger\n";
139 ////////////////////////////////////////////////////////////
141 ////////////////////////////////////////////////////////////
143 DbgCommandDescription theNullCommand =
144 {NULL, 0, 0, false, false, SDBG_NOOP};
146 /*!!!!! MUST be sorted by command !!!! */
147 DbgCommandDescription dbgCommands[] = {
148 { "break", 1, 1, false, false, SDBG_BREAK },
149 { "batch", 1, 1, false, false, SDBG_BATCH },
150 { "bstat", 0, 0, false, false, SDBG_BREAK_STAT },
151 { "B", 0, 0, false, false, SDBG_BREAK_LIST },
152 { "continue", 0, 0, false, false, SDBG_CONTINUE },
153 { "condition", 1, 2, true, false, SDBG_BREAK_COND },
154 { "del", 1, 1, false, false, SDBG_BREAK_CLEAR },
155 { "data", 0, 1, false, false, SDBG_DATA },
156 { "disable", 1, 1, false, false, SDBG_BREAK_DISABLE },
157 { "D", 0, 0, false, false, SDBG_BREAK_CLEARALL },
158 { "eval", 1, 1, true, false, SDBG_EVAL },
159 { "finish", 0, 0, false, false, SDBG_FINISH },
160 { "help", 0, 0, false, false, SDBG_HELP },
161 { "ignore", 2, 2, false, false, SDBG_BREAK_IGNORE },
162 { "kill", 0, 0, false, false, SDBG_KILL },
163 { "next", 0, 0, false, false, SDBG_NEXT },
164 { "output", 0, 0, false, false, SDBG_OUTPUT },
165 { "param", 2, 2, true, false, SDBG_PARAM },
166 { "point", 0, 0, false, false, SDBG_POINT },
167 { "P", 0, 0, false, false, SDBG_PARAM_LIST },
168 { "PP", 0, 0, false, false, SDBG_PARAM_CLEAR },
169 { "run", 0, 0, false, false, SDBG_RUN },
170 { "step", 0, 0, false, false, SDBG_STEP },
171 { "sheet", 0, 1, false, false, SDBG_SHEET },
172 { "templ", 0, 0, false, false, SDBG_TEMPLATE },
173 { "quit", 0, 0, false, false, SDBG_QUIT },
174 { "x", 0, 1, false, false, SDBG_CONTEXT },
175 {NULL, 0, 0, false, false, SDBG_NOOP}
179 "list", "current", NULL
182 ////////////////////////////////////////////////////////////
184 ////////////////////////////////////////////////////////////
186 Bool strToInt(Str *str, long int& out)
188 char *val = (char*)*str;
190 out = strtol(val, &end, 10);
194 ////////////////////////////////////////////////////////////
196 ////////////////////////////////////////////////////////////
198 Breakpoint::~Breakpoint()
200 if (expr) delete expr;
203 Bool Breakpoint::buildExpression(Sit S)
205 if (valid && element && !condition.isEmpty())
207 GP(Expression) e = new Expression(*element);
208 Bool failed = (*e).parse(S, condition);
222 Bool Breakpoint::matches(Sit S, Context* c, Bool& wasError)
228 Expression ret(*element);
229 Bool failed = expr -> eval(S, ret, c);
244 Bool Breakpoint::countMatches(Sit S, Context* c, Bool& wasError)
246 Bool ret = matches(S, c, wasError);
247 if (ret) hitMatched++;
248 ret = ret && (wasError || hitMatched > ignoreNum);
253 void Breakpoint::reset()
256 if (expr) delete expr;
258 hitTotal = hitEnabled = hitBreak = hitMatched = 0;
261 Bool Breakpoint::countEnabled()
264 if (enabled) hitEnabled++;
268 ////////////////////////////////////////////////////////////
270 ////////////////////////////////////////////////////////////
272 Breakpoint* BPList::getBP(Str& uri, int line)
274 for (int i = 0; i < number(); i++)
276 if ((*this)[i] -> uri == uri && (*this)[i] -> line == line)
282 Breakpoint* BPList::setBP(Str& uri, int line)
284 Breakpoint *ret = NULL;
285 Breakpoint *item = getBP(uri, line);
288 item = new Breakpoint();
298 Bool BPList::clearBP(int idx, Bool running)
300 if (idx >= 0 && idx < number())
302 if (running && (*this)[idx] -> element)
303 (*this)[idx] -> element -> breakpoint = NULL;
305 printf("breakpoint deleted\n");
308 printf("invalid breakpoint number\n");
312 Bool BPList::disableBP(int idx)
314 if (idx >= 0 && idx < number())
316 (*this)[idx] -> enabled = !(*this)[idx] -> enabled;
317 printf("breakpoint #%d is now %s\n", idx,
318 (*this)[idx] -> enabled ? "enabled" : "disabled");
323 printf("invalid breakpoint number\n");
328 void BPList::clearAll(Bool running)
330 for (int i = number() - 1; i >= 0; i--)
336 void BPList::listAll(Bool running)
340 for (int i = 0; i < number(); i++)
342 Breakpoint *item = (*this)[i];
344 if (running && ! item -> valid)
345 printf("(invalid) ");
346 else if (!item -> enabled)
347 printf("(disabled) ");
348 printf("%s:%d", (char*)item -> uri, item -> line);
349 if (! item -> condition.isEmpty())
350 printf(" condition:'%s'", (char*)item -> condition);
351 if ( item -> ignoreNum )
352 printf(" ignore:%d", item -> ignoreNum);
358 printf("no breakpoints\n");
363 void BPList::statAll(Bool running)
368 for (int i = 0; i < number(); i++)
370 Breakpoint *item = (*this)[i];
372 sprintf(buff, "(%d/%d/%d)", item -> hitTotal,
373 item -> hitEnabled, item -> hitBreak);
374 int len = strlen(buff);
378 memset(buff, ' ', _STAT_LEN - len);
379 buff[_STAT_LEN - len] = 0;
384 printf("%s at %d", (char*)item -> uri, item -> line);
390 printf("no breakpoints\n");
394 void BPList::getLinesForURI(Str& uri, List<int>& lines)
397 for (i = 0; i < number(); i++)
399 if ((*this)[i] -> uri == uri)
400 lines.append((*this)[i] -> line);
407 for (i = 1; i < lines.number(); i++)
409 if (lines[i - 1] > lines[i])
412 lines.swap(i - 1, i);
420 for (int i = 0; i < number(); i++)
422 Breakpoint *bp = (*this)[i];
427 Bool BPList::ignore(long int idx, long int num)
429 if (idx >= 0 && idx < number())
431 (*this)[idx] -> ignoreNum = num;
436 printf("invalid breakpoint number\n");
441 Bool BPList::setExpression(Sit S, int idx, ArgList& args, Bool running)
443 if (idx >= 0 && idx < number())
445 Breakpoint *bp = (*this)[idx];
446 //delete old expression
447 if (bp -> expr) delete bp -> expr;
449 bp -> condition.empty();
450 if (args.number() == 3)
453 bp -> condition = *(args[2]);
454 if (running && bp -> valid)
456 assert(bp -> element);
457 if (! bp -> buildExpression(S)) return false;
462 printf("invalid breakpoint number\n");
466 ////////////////////////////////////////////////////////////
467 /* debugger functions */
468 ////////////////////////////////////////////////////////////
473 SablotCreateSituation(&situa);
475 msgHandler.makeCode = mhMakeCode;
476 msgHandler.log = mhLog;
477 msgHandler.error = mhError;
487 Debugger::~Debugger()
489 bpoints.freeall(FALSE);
493 MH_ERROR Debugger::mhMakeCode(void *userData, SablotHandle processor_,
494 int severity, unsigned short facility,
500 MH_ERROR Debugger::mhLog(void *userData, SablotHandle processor_,
501 MH_ERROR code, MH_LEVEL level, char **fields)
506 MH_ERROR Debugger::mhError(void *userData, SablotHandle processor_,
507 MH_ERROR code, MH_LEVEL level,
511 Debugger *this_ = (Debugger*)userData;
514 char *aux = strchr(*foo, ':');
527 this_ -> messages.appendConstruct(key, val);
528 this_ -> errorCode = code;
536 void Debugger::setBreakpointsOnElement(Sit S, Element *e)
538 SubtreeInfo *info = e -> subtree;
539 if (info != currentInfo)
544 currentLines.deppendall();
545 bpoints.getLinesForURI(info -> getBaseURI(), currentLines);
546 //first met? set the next breakpoint line index to be set
547 if (info -> nextBPIndex == -2)
548 info -> nextBPIndex = currentLines.number() ? 0 : -1;
551 if (info && info -> nextBPIndex >= 0)
553 int line = currentLines[info -> nextBPIndex];
554 if (e -> lineno == line)
556 Breakpoint *bp = bpoints.getBP(info -> getBaseURI(), line);
558 e -> breakpoint = bp;
561 //build expression (if any)
562 if (! bp -> buildExpression(S) )
564 reportError("wrong breakpoit expression:", false);
566 if (info -> nextBPIndex < (currentLines.number() - 1))
567 info -> nextBPIndex ++;
569 info -> nextBPIndex = -1;
572 //process recursively
573 for (int i = 0; i < e -> contents.number(); i++)
574 if (isElement(e -> contents[i]))
575 setBreakpointsOnElement(S, toE(e -> contents[i]));
578 void Debugger::setBreakpoints(Sit S, Tree* sheet_)
580 //info should be NULL
584 currentLines.deppendall();
586 setBreakpointsOnElement(S, &(sheet -> getRoot()));
589 void Debugger::enterIdle()
592 prompt(*(Situation*)situa, NULL, NULL, quited);
594 prompt(*(Situation*)situa, NULL, NULL, quited);
598 void Debugger::reportTrace(const char* msg, Str& uri, int line, Element *e)
601 e -> getOwner().expandQStr(e -> getName(), name);
602 printf("\n%s in %s:%d (<%s>)\n",
603 msg, (char*)uri, line, (char*)name);
606 Bool Debugger::elementBreakable(Sit S, Element *e, Context *c, Bool report)
609 Bool wasError = false;
612 Str &uri = e -> getSubtreeInfo() -> getBaseURI();
613 int line = e -> lineno;
617 if (report) reportTrace("Step to", uri, line, e);
619 else if ((ret = (intempl && isXSL(e) && toX(e) -> op == XSL_TEMPLATE)))
621 if (report) reportTrace("Template met", uri, line, e);
623 else if ((ret = (e == nextele)))
625 if (report) reportTrace("Step (next) to", uri, line, e);
627 else if ((ret = (e -> breakpoint && e -> breakpoint -> countEnabled()
628 && e -> breakpoint -> countMatches(S, c, wasError))))
631 reportError("error evaluating bp condition:", false);
632 if (report) reportTrace("Breakpoint met", uri, line, e);
637 if (ret) nextele = NULL;
638 if (ret) intempl = false;
643 Bool Debugger::tokenize(char* what_, ArgList &where,
644 DbgCommandDescription& desc)
647 desc = theNullCommand;
650 what += strspn(what, " \n\t");
651 char *aux = strpbrk(what, " \n\t");
652 if (! aux) aux = what + strlen(what);
654 strncpy(token, what, aux - what);
655 token[aux - what] = 0;
657 //perhaps we didnt find anything
658 if (!token[0]) return true;
660 //now we lookup the command in the table
662 //return the result of the command lookup
663 ret = lookupCommand(str, desc);
665 where.append(new Str(token));
668 if (desc.joinRest) numargs = desc.argsMax;
672 while (*aux && currnum < numargs)
674 aux += strspn(aux, " \n\t");
678 aux = strpbrk(what, " \n\t");
679 if (! aux) aux = what + strlen(what);
680 strncpy(token, what, aux - what);
681 token[aux - what] = 0;
682 where.append(new Str(token));
689 aux += strspn(aux, " \n\t");
691 where.append(new Str(aux));
696 Bool Debugger::lookupArg(Str &str, char** lst, int &op)
700 char *item = lst[idx++];
701 while (op == -1 && item)
703 char* aux = (char*) str;
704 int len = strlen(aux);
705 if ( ! strncmp(aux, item, len) )
708 char* auxi = lst[idx];
711 if ( strncmp(aux, auxi, len) )
724 Bool Debugger::lookupCommand(Str& str, DbgCommandDescription& out)
727 out = theNullCommand;
728 DbgCommandDescription desc = dbgCommands[idx++];
729 while (out.op == SDBG_NOOP && desc.command)
731 char* aux = (char*) str;
732 int len = strlen(aux);
733 if ( ! strncmp(aux, desc.command, len) )
736 DbgCommandDescription auxd = dbgCommands[idx];
737 if ( desc.strict && auxd.command )
739 if ( strncmp(aux, auxd.command, len) )
747 desc = dbgCommands[idx++];
753 const char* Debugger::nodeTypeName(Vertex *v)
760 return "ExtensionElement";
761 else if ( isElement(v) )
763 else if ( isAttr(v) )
766 return "ProcessingInstruction";
769 else if ( isComment(v) )
771 else if ( isText(v) )
777 void Debugger::listNode(Sit S, NodeHandle node, Bool detailed)
779 Vertex *v = toV(node);
783 if (isElement(v) || isAttr(v) || isPI(v))
785 v -> getOwner().expandQStr(v -> getName(), name);
788 if (isElement(v) || isAttr(v))
790 ns = v -> getOwner().expand(v -> getName().getUri());
793 switch (baseType(v)) {
795 cont = toA(v) -> cont; break;
797 cont = toText(v) -> cont; break;
799 cont = toPI(v) -> cont; break;
801 cont = toComment(v) -> cont; break;
807 printf("type: %s\n", nodeTypeName(v));
809 if (! name.isEmpty() )
811 printf("name: %s\n", (char*)name);
815 printf("ns: %s\n", (char*)ns);
817 if (! cont.isEmpty() )
819 printf("cont: %s\n", (char*)cont);
825 printf("%s:", nodeTypeName(v));
827 if (! name.isEmpty() )
828 printf(" name='%s'", (const char*) name);
831 printf(" ns='%s'", (const char*) ns);
833 if (! cont.isEmpty() )
836 strncpy(foo, (char*)cont, 10);
838 printf(" cont='%s';", foo);
846 void Debugger::listContext(Sit S, Element* e, Context* c, ArgList &args)
848 if (args.number() == 1)
850 printf("Context:\n size=%d\n position=%d\n",
851 c -> getSize(), c -> getPosition());
853 printf("Namespaces:\n");
856 for (int i = e -> namespaces.number() - 1; i >= 0; i--)
858 NmSpace *nm = toNS(e-> namespaces[i]);
859 prefix = e -> getOwner().expand(nm -> prefix);
860 uri = e -> getOwner().expand(nm -> uri);
863 for (int j = 0; j < curr.number() && !found; j++)
865 found = *(curr[j]) == prefix;
869 curr.append(new Str(prefix));
870 printf(" %s => %s\n", (char*)prefix, (char*)uri);
878 if (! lookupArg(*(args[1]), ctxArgs, op) )
879 printf("ambiguous command argument");
887 for (int i = 0; i < c -> getSize(); i++)
889 if (i == c -> getPosition())
894 listNode(S, (*c)[i], false);
899 printf("#current: ");
900 listNode(S, c -> getCurrentNode(), true);
911 if (strToInt(args[1], idx))
913 if (idx >= 0 && idx < c -> getSize())
915 listNode(S, (*c)[idx], true);
919 printf("index out of bounds\n");
924 printf("unknown command argument\n");
931 Bool Debugger::findElementForBreakpoint(Element *e, Breakpoint* bp)
933 SubtreeInfo* info = e -> subtree;
934 if (info != currentInfo)
937 inRightTree = info && (info -> getBaseURI() == bp -> uri);
939 //set breakpoint if we're in place
940 if (inRightTree && e -> lineno == bp -> line)
942 e -> breakpoint = bp;
948 for (int i = 0; i < e -> contents.number(); i++)
950 if (isElement(e -> contents[i]))
951 if (findElementForBreakpoint(toE(e -> contents[i]), bp))
957 Bool Debugger::setBreakpointRunning(Breakpoint *bp)
963 return findElementForBreakpoint(&(sheet -> getRoot()), bp);
966 void Debugger::doSetBreakpoint(Str& uri, int line)
969 if ((bp = bpoints.setBP(uri, line)))
971 if (!running || setBreakpointRunning(bp))
972 printf("breakpoint set in %s at %d\n", (char*)uri, line);
974 printf("breakpoint set (invalid) in %s at %d\n", (char*)uri, line);
977 printf("breakpoint already exists\n");
980 void Debugger::setBreakpoint(Sit S, Element *e, ArgList& args)
982 if (args.number() == 1)
984 Str &uri = e -> getSubtreeInfo() -> getBaseURI();
985 int line = e -> lineno;
986 doSetBreakpoint(uri, line);
990 char *aux = (char*) *(args[1]);
991 char *sep = strchr(aux, ':');
996 char *aline = sep + 1;
999 int line = strtol(aline, &aux, 10);
1002 printf("bad location\n");
1008 theBase = Str("file://") + theBase;
1011 makeAbsoluteURI(S, file, theBase, abs);
1013 doSetBreakpoint(abs, line);
1020 printf("bad location\n");
1025 Bool Debugger::checkIdle()
1028 printf("processor is running\n");
1032 Bool Debugger::checkRunning()
1035 printf("processor is NOT running\n");
1039 void Debugger::run()
1045 messages.freeall(FALSE);
1047 if (dataURI.isEmpty())
1048 printf("no datafile given\n");
1050 if (sheetURI.isEmpty())
1051 printf("no stylesheet given\n");
1053 if (!dataURI.isEmpty() && !sheetURI.isEmpty())
1056 SablotCreateProcessorForSituation(situa, &proc);
1058 //register the message handler
1059 SablotRegHandler(proc, HLR_MESSAGE, &msgHandler, this);
1061 for (int i = 0; i < params.number(); i++)
1063 SablotAddParam(situa, proc,
1064 (char*)(params[i] -> key),
1065 (char*)(params[i] -> value));
1070 printf("debugger started\n");
1071 int code = SablotRunProcessorGen(situa, proc,
1072 (const char*)sheetURI,
1073 (const char*)dataURI,
1078 if (this -> errorCode != DBG_BREAK_PROCESSOR)
1080 reportError("\ndebugger finished with error: ", true);
1084 printf("debugger finished (killed)\n");
1086 SablotClearSituation(situa);
1090 printf("\ndebugger finished successfully\n");
1092 SablotDestroyProcessor(proc);
1096 void Debugger::reportError(const char* msg, Bool details)
1099 for (int i = 0; i < messages.number(); i++)
1101 Str &key = messages[i] -> key;
1102 if (! (key == (const char*)"msgtype") &&
1103 ! (key == (const char*)"module") &&
1105 (! (key == (const char*)"URI") &&
1106 ! (key == (const char*)"line") &&
1107 ! (key == (const char*)"node")))
1110 printf("[%s: %s]", (char*)key, (char*)(messages[i] -> value));
1114 SablotClearSituation(situa);
1117 void Debugger::eval(Sit S, Context *c, Element *e, ArgList& args)
1120 if (args.number() == 1)
1122 printf("no expression given\n");
1128 Expression expr(*e);
1129 Bool failed = false;
1130 failed = expr.parse(S, estr);
1135 failed = expr.eval(S, ret, c);
1142 ret.tostring(S, str);
1143 printf("number: %s\n", (char*)str);
1148 ret.tostring(S, str);
1149 printf("string: '%s'\n", (char*)str);
1154 ret.tostring(S, str);
1155 printf("boolean: %s\n", (char*)str);
1159 const Context &nset = ret.tonodesetRef();
1160 printf("nodeset (size: %d):\n", nset.getSize());
1161 for (int i = 0; i < nset.getSize(); i++)
1164 listNode(S, nset[i], false);
1173 printf("ExternalValue\n");
1177 printf("unknown return type (%d)\n", ret.type);
1183 if (failed) reportError("error in evaluation: ", false);
1186 void Debugger::playBatch(Sit S, Element *e, Context *c, Str& file)
1189 char *res, line[256];
1192 f = fopen((char*)file, "r");
1195 Bool quited = false;
1196 res = fgets(line, 256, f);
1197 while (res && !done && !quited)
1199 doCommand(S, e, c, line, done, quited);
1200 res = fgets(line, 256, f);
1204 printf("can not read file %s\n", (char*)file);
1207 void Debugger::addParam(ArgList& args)
1209 params.appendConstruct(*(args[1]), *(args[2]));
1212 Bool Debugger::checkArgs(DbgCommandDescription& desc, ArgList& args)
1214 if (desc.op != SDBG_NOOP)
1216 int i = args.number() - 1;
1217 return i >= desc.argsMin && i <= desc.argsMax;
1223 Bool Debugger::doCommand(Sit S, Element *e, Context *c,
1224 char* line, Bool& done, Bool& quited)
1229 DbgCommandDescription cmd;
1230 if (! tokenize(line, args, cmd))
1232 printf("ambiguous command\n");
1236 if (!checkArgs(cmd, args))
1238 printf("wrong number of arguments\n");
1245 if (args.number()) printf("unknown command\n");
1249 setBreakpoint(S, e, args);
1251 case SDBG_BREAK_LIST:
1253 bpoints.listAll(running);
1255 case SDBG_BREAK_CLEAR:
1258 if (strToInt(args[1], idx))
1259 bpoints.clearBP(idx, running);
1261 printf("invalid argument\n");
1263 case SDBG_BREAK_COND:
1266 if (strToInt(args[1], idx))
1268 if (!bpoints.setExpression(S, idx, args, running))
1270 reportError("wrong breakpoit expression:", false);
1273 printf("breakpoint modified\n");
1276 printf("invalid argument\n");
1278 case SDBG_BREAK_DISABLE:
1281 if (strToInt(args[1], idx))
1283 if (bpoints.disableBP(idx))
1284 printf("breakpoint modified\n");
1287 printf("invalid argument\n");
1289 case SDBG_BREAK_CLEARALL:
1291 bpoints.clearAll(running);
1292 printf("all breakpoints deleted\n");
1294 case SDBG_BREAK_STAT:
1296 bpoints.statAll(running);
1298 case SDBG_BREAK_IGNORE:
1301 if (strToInt(args[1], idx) && strToInt(args[2], num))
1303 if (bpoints.ignore(idx, num))
1304 printf("breakpoint modified\n");
1307 printf("invalid argument\n");
1320 listContext(S, e, c, args);
1328 eval(S, c, e, args);
1333 playBatch(S, e, c, *(args[1]));
1342 case SDBG_PARAM_LIST:
1344 if (params.number())
1345 for (int i = 0; i < params.number(); i++)
1347 printf("$%s = '%s'\n",
1348 (char*)(params[i] -> key),
1349 (char*)(params[i] -> value));
1352 printf("no params\n");
1354 case SDBG_PARAM_CLEAR:
1358 params.freeall(FALSE);
1359 printf("all params removed\n");
1374 if (args.number() < 2)
1376 if (!dataURI.isEmpty())
1377 printf("using datafile %s\n", (char*)dataURI);
1379 printf("no datafile given\n");
1383 dataURI = *(args[1]);
1384 printf("using datafile %s\n", (char*)dataURI);
1392 if (args.number() < 2)
1394 if (!sheetURI.isEmpty())
1395 printf("using stylesheet %s\n", (char*)sheetURI);
1397 printf("no stylesheet given\n");
1401 sheetURI = *(args[1]);
1402 printf("using stylesheet %s\n", (char*)sheetURI);
1418 Vertex *aux = e -> getNextSibling();
1419 if ( aux && isElement(aux) ) nextele = toE(aux);
1427 Vertex *aux = e -> parent -> getNextSibling();
1428 if ( aux && isElement(aux) ) nextele = toE(aux);
1438 done = true; //continue
1443 printf("output is now %s\n", output ? "on" : "off");
1449 Str &uri = e -> getSubtreeInfo() -> getBaseURI();
1450 int line = e -> lineno;
1451 printf("%s:%d\n", (char*)uri, line);
1458 Err(S, DBG_BREAK_PROCESSOR);
1471 printf("debugger quited\n");
1477 args.freeall(FALSE);
1481 void Debugger::printUsage()
1483 printf("%s", theUsageStr);
1486 eFlag Debugger::prompt(Sit S, Element *e, Context *c, Bool& quited)
1492 if (line) free(line);
1493 line = dbgGetLine();
1496 E( doCommand(S, e, c, line, done, quited) );
1499 if (line) free(line);
1503 eFlag Debugger::breakOnElement(Sit S, Element *e, Context *c)
1506 if ( elementBreakable(S, e, c, true) )
1508 E( prompt(S, e, c, quited) );
1510 //quit may not happen while running
1514 void Debugger::report(Sit S, MsgType type, MsgCode code,
1515 const Str& arg1, const Str& arg2) const
1517 S.message(type, code, arg1, arg2);
1521 void Debugger::printOutput(const char* buff, int size)
1526 if (outputLastLine < outputLine)
1528 sprintf(fmt, "%d\t%%.%ds", outputLine, size);
1529 outputLastLine = outputLine;
1532 sprintf(fmt, "%%.%ds", size);
1536 if (*buff == '\n') outputLine++;
1539 #endif //SABLOT_DEBUGGER