Qore DebugCmdLine Module Reference  0.1.1
DebugCmdLine.qm.dox.h
1 // -*- mode: c++; indent-tabs-mode: nil -*-
3 
4 /* DebugCmdLine.qm Copyright 2013 - 2018 Qore Technologies, s.r.o.
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23 */
24 
25 // minimum required Qore version
26 
27 
28 
45 namespace DebugCmdLine {
47 
64 class WrapperGetOpt : public GetOpt {
65 
66 public:
68  constructor(hash options) ;
69 
70 
72 
104  split(list<string> args, reference<list<string>> wrp_args, reference<*string> pgm_name, reference<list<string>> pgm_args);
105  };
106 
108 class DebugCommandLine : public AbstractDebugControl {
109 
110 public:
111  public :
112  string ln_prompt = 'qdbg> ';
113  hash cx;
114  const defaultHistoryFileName = '.qdbg.history';
115  const defaultIndent = " ";
116 
117 public:
118 
119  private :
120  const fcHelp = 0x01;
121  const fcExpandUniqueCmd = 0x02;
122  const fcValidate = 0x04;
123  const fcFallback = 0x08;
124  *string historyFileName;
125 
126  Qore::Thread::RWLock rwlContext();
127 
128  hash commands = (
129  '>': (
130  'help': (
131  '**': (
132  'desc': 'help/*',
133  'enum';
134 ,
135  'action';
136 ,
137  ),
138  'desc': 'get help about command',
139  'action';
140 ,
141  ),
142  'version': (
143  'desc': 'get version info. Check "host" key to see if server side is reponding',
144  'action';
145 ,
146  ),
147  'history': (
148  '>': (
149  'load': (
150  'desc': 'load command line history from file, args: filename',
151  'action';
152 ,
153  ),
154  'save': (
155  'desc': 'save command line history to file, args: filename',
156  'action';
157 ,
158  ),
159 
160  ),
161  'desc': 'load or save history to file. The history is implicitly loaded when program starting and saved when exiting. See command line parameters.',
162  ),
163  'quit': (
164  'desc': 'quit debugger',
165  'action';
166 ,
167  ),
168 
169  'cmd': (
170  'desc': 'send a command to the server and show the output',
171  'action';
172 ,
173  ),
174  'frame': (
175  '>': {
176  'set': (
177  'desc': 'set current stack frame, args: frameId',
178  '*': (
179  'enum';
180 ,
181  'validate': \DebugCommandLine::validateInt(),
182  'action';
183 ,
184  ),
185  ),
186  'get': (
187  'desc': 'get current stack frame',
188  'action';
189 ,
190  ),
191  },
192  'fallback';
193 ,
194  'desc': 'Stack frame related commands',
195  ),
196  'session': (
197  'desc': 'get list of debugged programs, stopped threads and breakpoint stats',
198  'action';
199 ,
200  '>': (
201  'load': (
202  'desc': 'load session from file, args: filename',
203  'action';
204 ,
205  ),
206  'save': (
207  'desc': 'save session to file, args: filename',
208  'action';
209 ,
210  ),
211  ),
212  ),
213  'program': (
214  'alias': 'pgm',
215  ),
216  'pgm': (
217  '>': (
218  'load': (
219  'desc': 'load and run script, args: filename [args..]',
220  'action';
221 ,
222  ),
223  'search': (
224  'desc': 'regex search for a program, args: regex',
225  'action';
226 ,
227  ),
228  'list': (
229  '>': (
230  'full': (
231  'desc': 'verbose program listing',
232  'action';
233 ,
234  ),
235  ),
236  'desc': 'list programs, [full] for a verbose listing',
237  'action';
238 ,
239  ),
240  'set': (
241  'desc': 'set current program, arg: programId',
242  '*': (
243  'enum';
244 ,
245  'validate': \DebugCommandLine::validateInt(),
246  'action';
247 ,
248  ),
249  ),
250  'get': (
251  'desc': 'get current program',
252  'action';
253 ,
254  ),
255  'add': (
256  'desc': 'add current program for debugging',
257  'action';
258 ,
259  ),
260  'remove': (
261  'desc': 'remove current program from debugging',
262  'action';
263 ,
264  ),
265  'stop': (
266  'desc': 'stop current program, args: [threadId] to stop particular thread',
267  'action';
268 ,
269  ),
270  'global': (
271  '*': (
272  'enum';
273 ,
274  'action';
275 ,
276  ),
277  'action';
278 ,
279  'desc': 'get/set global variable, args: varName [value]',
280  ),
281  'define': (
282  '*': (
283  'enum';
284 ,
285  'action';
286 ,
287  ),
288  'action';
289 ,
290  'desc': 'get defines, args: [defineName]',
291  ),
292  'options': (
293  'desc': 'list parse options',
294  'action';
295 ,
296  ),
297  'info': (
298  'desc': 'get info about current program and list threads',
299  'action';
300 ,
301  ),
302  ),
303  'desc': 'program related commands',
304  /* TODO: what is intended enumeration ?
305  'enum': list sub(DebugCommandLine dcl, softlist path, softlist args) {
306  hash data.cmd = 'program//list';
307  *hash pgm_info = dcl.doCommandImpl(data);
308  list rv = ();
309  *string p = shift path;
310  bool id = p =~ /^[0-9]+$/;
311  foreach hash h in (pgm_info.pairIterator()) {
312  if (!p.val())
313  rv += h.key.toInt();
314  else {
315  if (id) {
316  if (regex(h.key, "^" + p))
317  rv += h.key.toInt();
318  }
319  else if (h.value.scriptName.val() && regex(h.value.scriptName, "^" + p))
320  rv += h.value.scriptName();
321  }
322  }
323  return rv;
324  },
325  */
326  'fallback';
327 ,
328  ),
329  'break': (
330  '>': (
331  'list': (
332  'desc': 'list breakpoints for current program',
333  'action';
334 ,
335  '>': (
336  'all': (
337  'desc': 'list breakpoints for all programs',
338  'action';
339 ,
340  ),
341  ),
342  ),
343  'create': (
344  'desc': 'create breakpoint and get breakpointId. Optionally assign to particular statement, i.e. code line, or do it later using "statement assign". args: [function([args, ...])] | [file] lineno | //statementId',
345  'action';
346 ,
347  ),
348  'delete': (
349  '*': (
350  'enum';
351 ,
352  'action';
353 ,
354  ),
355  'desc': 'delete breakpoint, args: breakpointId',
356  ),
357  'enable': (
358  '*': (
359  'enum';
360 ,
361  'action';
362 ,
363  ),
364  'desc': 'enable breakpoint, args: breakpointId',
365  ),
366  'disable': (
367  '*': (
368  'enum';
369 ,
370  'action';
371 ,
372  ),
373  'desc': 'disable breakpoint, args: breakpointId',
374  ),
375  'policy': (
376  '*': (
377  'enum';
378 ,
379  '*': (
380  'enum';
381 ,
382  'action';
383 ,
384  ),
385  'action';
386 ,
387  ),
388  'desc': sprintf('get/set breakpoint policy, args: breakpointId [%s]', (keys AbstractDebugControl::policyStrings).join('|')),
389  ),
390  'thread': (
391  '*': (
392  'enum';
393 ,
394  'action';
395 ,
396  ),
397  'desc': 'get/set threads assigned to breakpoint, args: breakpointId ["+"/"-" threadId | threadId ..]',
398  'action';
399 ,
400  ),
401  'statement': (
402  '*': (
403  'enum';
404 ,
405  'action';
406 ,
407  ),
408  'desc': 'get statement list assigned to breakpoint, args: breakpointId',
409  ),
410  ),
411  'desc': 'breakpoint related commands',
412  ),
413  'statement': (
414  'alias': 'stmt',
415  ),
416  'stmt': (
417  '>': (
418  'list': (
419  '*': (
420  'enum';
421 ,
422  'action';
423 ,
424  ),
425  'desc': 'list statements, args: breakpointId', // duplicate to breakpoint/statement
426  ),
427  'assign': (
428  '*': (
429  'enum';
430 ,
431  'action';
432 ,
433  ),
434  'desc': 'assign statement to breakpoint, args: breakpointId [function([args, ...])] | [file] lineno | //statementId',
435  ),
436  'unassign': (
437  '*': (
438  'enum';
439 ,
440  'action';
441 ,
442  ),
443  'desc': 'unassign statement from breakpoint, args: breakpointId [function([args, ...])] | [file] lineno | //statementId',
444  ),
445  ),
446  'desc': 'statement related commands',
447  ),
448 
449  'thread': (
450  '>': (
451  'set': (
452  '*': (
453  'desc': 'set current thread, args: threadId',
454  'enum';
455 ,
456  'validate': \DebugCommandLine::validateInt(),
457  'action';
458 ,
459  ),
460  ),
461  'get': (
462  'desc': 'get current thread',
463  'action';
464 ,
465  ),
466  'local': (
467  '*': (
468  'enum';
469 ,
470  'action';
471 ,
472  ),
473 
474  'action';
475 ,
476  'desc': 'get/set local variable, args: varName [value]',
477  ),
478  'debug': (
479  '*': (
480  'enum';
481 ,
482  'action';
483 ,
484  ),
485  'desc': 'get/set special debug variable, args: varName [value], use "thread debug list" command result to see value list of varNames',
486  ),
487  'pgmlist': (
488  'desc': 'show threads and related programs, interrupted programs are marked with \"S\"',
489  'action';
490 ,
491  ),
492  'list': (
493  'desc': 'show list of threads and top level stack position',
494  'action';
495 ,
496  )
497  ),
498  'desc': 'thread related commands',
499  'fallback';
500 ,
501  ),
502  'stack': (
503  'alias': 'bt',
504  ),
505  'backtrace': (
506  'alias': 'bt',
507  ),
508  'bt': (
509  'desc': 'get stack for current thread',
510  'action';
511 ,
512  '>': (
513  'all': (
514  'desc': 'show call stack for all threads',
515  'action';
516 ,
517  ),
518  ),
519  ),
520  'go': (
521  '*': (
522  'enum';
523 ,
524  'action';
525 ,
526  ),
527  'desc': sprintf('go thread with specified runstate, arg: %s', (keys AbstractDebugControl::runStateStrings).join('|')),
528  'action';
529 ,
530  ),
531  ),
532  );
533 
534 public:
535 
536  constructor();
537 
538 
540  abstract *hash doCommandImpl(hash data);
541  doCommand(hash data);
542 
543  showPrograms(hash ph, bool show_interrupted);
544 
545  showBreakpoints(*list bkpts);
546 
547  string getThreadStackStr(hash lh);
548 
549  showThreadStack(softint tid, list stack);
550 
551  static validateInt(DebugCommandLine dcl, softlist path, softlist val);
552 
553  auto parseValue();
554 
555  auto getContextValue(string key);
556 
557  setContextValue(string key, auto value);
558 
559  hash getStatementValue(list args);
560 
561 
562 private:
563  list splitCmd(string line);
564 public:
565 
566 
567  string listVariantCmds(hash v);
568 
569  *hash findCmd(list args, int opts = 0, *reference<int> last_param) { /* because it is needed from closure */ hash result;
570  result.path = ();
571  hash<auto> c = commands;
572  last_param = 0;
573  while (args);
574 
575  result.args = args;
576  return result;
577  }
578 
579 
580 private:
581  list ln_callback(string line);
582 public:
583 
584 
585  runCmdLine();
586 
587 
588 private:
589  bool isOneLineArray(list x);
590 public:
591 
592 
593  printVar(string name, hash value);
594 
595  printHuman(hash x, string indent = defaultIndent);
596 
597  printHuman(list x, string indent = defaultIndent);
598 
599  printHuman(string x, string indent = defaultIndent);
600  printHuman(any x, string indent = defaultIndent);
601 
602  printData(auto data);
603 
604  printLinenoise(*string outs);
605 
606  int checkProgramId();
607 
608  int checkThreadId();
609 
610  static softlist enumBreakpointId(DebugCommandLine dcl, softlist path, softlist args);
611 
612  loadSession(*string fn);
613 
614  init(hash opt);
615 
616  };
617 };
string sprintf(string fmt,...)
list list(...)
list< string > split(string sep, string str, bool with_separator=False)
hash hash(object obj)