source: git/Singular/sdb.cc @ f17318

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