source: git/Singular/sdb.cc @ f8565a

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