source: git/Singular/sdb.cc

spielwiese
Last change on this file was ad7c8c, checked in by Hans Schoenemann <hannes@…>, 5 weeks ago
compiler warnings
  • Property mode set to 100644
File size: 7.7 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT: Singular debugger
6*/
7
8#include "kernel/mod2.h"
9#include "omalloc/omalloc.h"
10#include "misc/options.h"
11#include "reporter/si_signals.h"
12#include "Singular/tok.h"
13#include "Singular/ipshell.h"
14#include "Singular/ipid.h"
15#include "Singular/fevoices.h"
16#include "kernel/oswrapper/feread.h"
17#include "Singular/sdb.h"
18
19#include <unistd.h>   // for unlink,fork,execlp,getpid
20#include <sys/wait.h> // for wait
21
22
23#ifdef HAVE_SDB
24// We use 8 breakpoints - corresponding to a bit in a char variable in procinfo
25// bit 1..7 force a breakpoint, if lineno==sdb_lines[i-1],
26//                         (for displaying only: file sdb_files[i-1])
27// bit 0 force a breakpoint in every line (used for 'n')
28
29VAR int sdb_lines[]={-1,-1,-1,-1,-1,-1,-1,-1};
30VAR char * sdb_files[6];
31VAR int sdb_flags=0;
32
33int sdb_checkline(char f)
34{
35  int i;
36  char ff=f>>1;
37  for(i=0;i<7;i++)
38  {
39    if((ff & 1) && (yylineno==sdb_lines[i]))
40      return i+1;
41    ff>>=1;
42    if (ff==0) return 0;
43  }
44  return 0;
45}
46
47static char *sdb_find_arg(char *p)
48{
49  p++;
50  while (*p==' ') p++;
51  char *pp=p;
52  while (*pp>' ') pp++;
53  *pp='\0';
54  return p;
55}
56
57void sdb_show_bp()
58{
59  for(int i=0; i<7;i++)
60    if (sdb_lines[i]!= -1)
61      Print("Breakpoint %d: %s::%d\n",i+1,sdb_files[i],sdb_lines[i]);
62}
63
64BOOLEAN sdb_set_breakpoint(const char *pp, int given_lineno)
65{
66  idhdl h=ggetid(pp);
67  if ((h==NULL)||(IDTYP(h)!=PROC_CMD))
68  {
69    PrintS(" not found\n");
70    return TRUE;
71  }
72  else
73  {
74    procinfov p=(procinfov)IDDATA(h);
75    #ifdef HAVE_DYNAMIC_LOADING
76    if (p->language!=LANG_SINGULAR)
77    {
78      PrintS("is not a Singular procedure\n");
79      return TRUE;
80    }
81    #endif
82    int lineno;
83    if (given_lineno >0) lineno=given_lineno;
84    else                 lineno=p->data.s.body_lineno;
85    int i;
86    if (given_lineno== -1)
87    {
88      i=p->trace_flag;
89      p->trace_flag &=1;
90      Print("breakpoints in %s deleted(%#x)\n",p->procname,i &255);
91      return FALSE;
92    }
93    i=0;
94    while((i<7) && (sdb_lines[i]!=-1)) i++;
95    if (sdb_lines[i]!= -1)
96    {
97      PrintS("too many breakpoints set, max is 7\n");
98      return TRUE;
99    }
100    sdb_lines[i]=lineno;
101    sdb_files[i]=p->libname;
102    i++;
103    p->trace_flag|=(1<<i);
104    Print("breakpoint %d, at line %d in %s\n",i,lineno,p->procname);
105    return FALSE;
106  }
107}
108
109void sdb_edit(procinfo *pi)
110{
111  char * filename = omStrDup("/tmp/sdXXXXXX");
112  int f=mkstemp(filename);
113  if (f==-1)
114  {
115    Print("cannot open %s\n",filename);
116    omFree(filename);
117    return;
118  }
119  if (pi->language!= LANG_SINGULAR)
120  {
121    Print("cannot edit type %d\n",pi->language);
122    si_close(f);
123  }
124  else
125  {
126    const char *editor=getenv("EDITOR");
127    if (editor==NULL)
128      editor=getenv("VISUAL");
129    if (editor==NULL)
130      editor="vi";
131    editor=omStrDup(editor);
132
133    if (pi->data.s.body==NULL)
134    {
135      iiGetLibProcBuffer(pi);
136      if (pi->data.s.body==NULL)
137      {
138        PrintS("cannot get the procedure body\n");
139        si_close(f);
140        si_unlink(filename);
141        omFree(filename);
142        return;
143      }
144    }
145
146    ssize_t res=write(f,pi->data.s.body,strlen(pi->data.s.body));
147    si_close(f);
148    if (res==-1)
149    {
150      PrintS("cannot write the procedure body\n");
151      si_unlink(filename);
152      omFree(filename);
153      return;
154    }
155
156    int pid=fork();
157    if (pid!=0)
158    {
159      si_wait(&pid);
160    }
161    else if(pid==0)
162    {
163      if (strchr(editor,' ')==NULL)
164      {
165        execlp(editor,editor,filename,NULL);
166        Print("cannot exec %s\n",editor);
167      }
168      else
169      {
170        size_t len=strlen(editor)+strlen(filename)+2;
171        char *p=(char *)omAlloc(len);
172        snprintf(p,len,"%s %s",editor,filename);
173        int res=system(p);
174        if (res<0)
175        {
176          Print("cannot call `%s`\n",editor);
177        }
178      }
179      exit(0);
180    }
181    else
182    {
183      PrintS("cannot fork\n");
184    }
185
186    FILE* fp=fopen(filename,"r");
187    if (fp==NULL)
188    {
189      Print("cannot read from %s\n",filename);
190    }
191    else
192    {
193      fseek(fp,0L,SEEK_END);
194      long len=ftell(fp);
195      fseek(fp,0L,SEEK_SET);
196
197      omFree((ADDRESS)pi->data.s.body);
198      pi->data.s.body=(char *)omAlloc((int)len+1);
199      myfread( pi->data.s.body, len, 1, fp);
200      pi->data.s.body[len]='\0';
201      fclose(fp);
202    }
203  }
204  si_unlink(filename);
205  omFree(filename);
206}
207
208STATIC_VAR char sdb_lastcmd='c';
209
210void sdb(Voice * currentVoice, const char * currLine, int len)
211{
212  int bp=0;
213  if ((len>1)
214  && ((currentVoice->pi->trace_flag & 1)
215    || (bp=sdb_checkline(currentVoice->pi->trace_flag)))
216  )
217  {
218    loop
219    {
220      char gdb[80];
221      char *p=(char *)currLine+len-1;
222      while ((*p<=' ') && (p!=currLine))
223      {
224        p--; len--;
225      }
226      if (p==currLine) return;
227
228      currentVoice->pi->trace_flag&= ~1; // delete flag for "all lines"
229      Print("(%s,%d) >>",currentVoice->filename,yylineno);
230      fwrite(currLine,1,len,stdout);
231      Print("<<\nbreakpoint %d (press ? for list of commands)\n",bp);
232      p=fe_fgets_stdin(">>",gdb,80);
233      while (*p==' ') p++;
234      if (*p >' ')
235      {
236        sdb_lastcmd=*p;
237      }
238      Print("command:%c\n",sdb_lastcmd);
239      switch(sdb_lastcmd)
240      {
241        case '?':
242        case 'h':
243        {
244          PrintS(
245          "b - print backtrace of calling stack\n"
246          "B <proc> [<line>] - define breakpoint\n"
247          "c - continue\n"
248          "d - delete current breakpoint\n"
249          "D - show all breakpoints\n"
250          "e - edit the current procedure (current call will be aborted)\n"
251          "h,? - display this help screen\n"
252          "n - execute current line, break at next line\n"
253          "p <var> - display type and value of the variable <var>\n"
254          "q <flags> - quit debugger, set debugger flags(0,1,2)\n"
255          "   0: stop debug, 1:continue, 2: throw an error, return to toplevel\n"
256          "Q - quit Singular\n");
257          int i;
258          for(i=0;i<7;i++)
259          {
260            if (sdb_lines[i] != -1)
261              Print("breakpoint %d at line %d in %s\n",
262                i,sdb_lines[i],sdb_files[i]);
263          }
264          break;
265        }
266        case 'd':
267        {
268          Print("delete break point %d\n",bp);
269          currentVoice->pi->trace_flag &= (~Sy_bit(bp));
270          if (bp!=0)
271          {
272            sdb_lines[bp-1]=-1;
273          }
274          break;
275        }
276        case 'D':
277          sdb_show_bp();
278          break;
279        #if 0
280        case 'l':
281        {
282          extern void listall(int showproc);
283          listall(FALSE);
284          break;
285        }
286        #endif
287        case 'n':
288          currentVoice->pi->trace_flag|= 1;
289          return;
290        case 'e':
291        {
292          sdb_edit(currentVoice->pi);
293          sdb_flags=2;
294          return;
295        }
296        case 'p':
297        {
298          p=sdb_find_arg(p);
299          EXTERN_VAR int myynest;
300          Print("variable `%s`at level %d",p,myynest);
301          idhdl h=ggetid(p);
302          if (h==NULL)
303            PrintS(" not found\n");
304          else
305          {
306            sleftv tmp;
307            memset(&tmp,0,sizeof(tmp));
308            tmp.rtyp=IDHDL;
309            tmp.data=h;
310            Print("(type %s):\n",Tok2Cmdname(tmp.Typ()));
311            tmp.Print();
312          }
313          break;
314        }
315        case 'b':
316          VoiceBackTrack();
317          break;
318        case 'B':
319        {
320          p=sdb_find_arg(p);
321          Print("procedure `%s` ",p);
322          sdb_set_breakpoint(p);
323          break;
324        }
325        case 'q':
326        {
327          p=sdb_find_arg(p);
328          if (*p!='\0')
329          {
330            sdb_flags=atoi(p);
331            Print("new sdb_flags:%d\n",sdb_flags);
332          }
333          return;
334        }
335        case 'Q':
336          m2_end(999);
337        case 'c':
338        default:
339          return;
340      }
341    }
342  }
343}
344#endif
Note: See TracBrowser for help on using the repository browser.