⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gbx_trace.c

📁 Gambas is a graphical development environment based on a Basic interpreter, like Visual Basic. It us
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************  trace.c  The debugger  (c) 2000-2004 Beno� Minisini <gambas@users.sourceforge.net>  This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 1, or (at your option)  any later version.  This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.  You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __GBX_TRACE_C#include "gb_common.h"#include "gb_common_buffer.h"#include "gb_common_case.h"#include <unistd.h>#include <signal.h>#include <fcntl.h>#include "gb_error.h"#include "gbx_type.h"#include "gbx_debug.h"#include "gb_limit.h"#include "gbx_stack.h"#include "gbx_class.h"#include "gbx_exec.h"#include "gbx_local.h"#include "gbx_object.h"#include "gbx_c_application.h"#include "gbx_eval.h"#include "gbx_trace.h"/*#define DEBUG_ME*/PUBLIC TRACE_GLOBAL TRACE = { 0 };PRIVATE TRACE_BREAK *Breakpoint;PRIVATE bool Error;EVAL_INTERFACE EVAL;static int _fdr;static int _fdw;static FILE *_out;static FILE *_in;PUBLIC void TRACE_break_on_next_line(void){  TRACE.stop = TRUE;  TRACE.fp = NULL;  TRACE.bp = NULL;}PRIVATE void new_line(void){  fprintf(_out, "\n");}PRIVATE void signal_user(int sig){  signal(SIGUSR1, signal_user);  #ifdef DEBUG_ME  fprintf(stderr, "Got SIGUSR1\n");  #endif  /*CAPP_got_signal();*/  TRACE_break_on_next_line();}PRIVATE boolean calc_line_from_position(CLASS *class, FUNCTION *func, PCODE *addr, ushort *line){  int i;  ushort pos = addr - func->code;  ushort *post;  if (func->debug)  {    post =  func->debug->pos;    for (i = 0; i < (func->debug->nline - 1); i++)    {      if (pos >= post[i] && pos < post[i + 1])      {        *line = i + func->debug->line;        return FALSE;      }    }    /*printf("pos = %d addr=%p func->code=%p\n", pos, addr, func->code);*/  }  return TRUE;}PRIVATE boolean calc_position_from_line(CLASS *class, ushort line, FUNCTION **function, PCODE **addr){  int i;  ushort pos, pos_after;  FUNCTION *func = NULL;  FUNC_DEBUG *debug = NULL;  for (i = 0; i < class->load->n_func; i++)  {    func = &class->load->func[i];    debug = func->debug;    if (debug && line >= debug->line && line < (debug->line + debug->nline))      break;  }  if (i >= class->load->n_func)    return TRUE;  line -= debug->line;  for(;;)  {    pos = debug->pos[line];    pos_after = debug->pos[line + 1];    if (pos != pos_after)      break;    line++;    if (line >= debug->nline)      return TRUE;  }  *function = func;  *addr = &func->code[pos];  /*printf("%s.%d -> %04X\n", class->name, line + debug->line, **addr);*/  return FALSE;}PRIVATE bool get_value(const char *sym, long len, GB_VARIANT *ret){  int i;  VALUE value;  LOCAL_SYMBOL *lp;  GLOBAL_SYMBOL *gp;  CLASS_VAR *var;  char *addr;  if (TRACE.fp)  {    for (i = 0; i < TRACE.fp->debug->n_local; i++)    {      lp = &TRACE.fp->debug->local[i];      if (len == lp->sym.len && strncasecmp(sym, lp->sym.name, len) == 0)      {        value = TRACE.bp[lp->value];        goto __FOUND;      }    }  }  if (TRACE.cp)  {    for (i = 0; i < TRACE.cp->load->n_global; i++)    {      gp = &TRACE.cp->load->global[i];      if (len != gp->sym.len || strncasecmp(sym, gp->sym.name, len) != 0)        continue;      if (CTYPE_get_kind(gp->ctype) != TK_VARIABLE)        continue;      if (!CTYPE_is_static(gp->ctype) && TRACE.op)      {        var = &TRACE.cp->load->dyn[gp->value];        addr = (char *)TRACE.op + var->pos;      }      else      {        var = &TRACE.cp->load->stat[gp->value];        addr = (char *)TRACE.cp->stat + var->pos;      }      VALUE_class_read(TRACE.cp, &value, addr, var->type);      goto __FOUND;    }  }  /*printf("Unknown symbol %.*s\n", (int)len, sym);  ret->type = GB_T_NULL;*/  return TRUE;__FOUND:  /*printf("%.*s =", (int)len, sym);  print_value(&value);*/  BORROW(&value);  if (value.type == T_ARRAY)    value._array.keep = TRUE;  else    VALUE_conv(&value, T_VARIANT);  UNBORROW(&value);  *((VALUE *)ret) = value;  return FALSE;}PUBLIC void TRACE_init(void){  char path[MAX_PATH];  if (!EXEC_debug)    return;  LIBRARY_get_interface_by_name("gb.eval", EVAL_INTERFACE_VERSION, &EVAL);  if (EXEC_fifo)  {    sprintf(path, "/tmp/gambas.%d/%d.out", getuid(), getppid());    _fdr = open(path, O_RDONLY);    sprintf(path, "/tmp/gambas.%d/%d.in", getuid(), getppid());    _fdw = open(path, O_WRONLY);    _in = fdopen(_fdr, "r");    _out = fdopen(_fdw, "w");    if (!_in || !_out)      ERROR_panic("Cannot open fifos");    setlinebuf(_in); /*setvbuf(_in, NULL, _IOLBF, 0);*/    setlinebuf(_out); /*setvbuf(_out, NULL, _IOLBF, 0);*/  }  else  {    _in = stdin;    _out = stdout;  }  ARRAY_create(&Breakpoint);  signal(SIGUSR1, signal_user);  signal(SIGPIPE, SIG_IGN);}/*PUBLIC void TRACE_check_signal(void){  static bool msg = FALSE;  struct sigaction action;  if (msg)    return;  sigaction(SIGUSR1, NULL, &action);  if (action.sa_handler != signal_user)  {    fprintf(stderr, "SIGUSR1 handler has changed !\n");    msg = TRUE;  }  else  {    fprintf(stderr, "OK\n");  }}*/PUBLIC void TRACE_exit(void){  ARRAY_delete(&Breakpoint);  /*  if (EXEC_fifo)  {    fclose(_in);    fclose(_out);  }  */}PRIVATE int find_free_breakpoint(void){  int i;  char used[MAX_BREAKPOINT];  memset(used, FALSE, MAX_BREAKPOINT);  for (i = 0; i < ARRAY_count(Breakpoint); i++)    used[Breakpoint[i].id - 1] = TRUE;  for (i = 0; i < MAX_BREAKPOINT; i++)    if (!used[i])      return (i + 1);  return 0;}PRIVATE boolean set_breakpoint(CLASS *class, ushort line){  PCODE *addr = NULL;  TRACE_BREAK *brk;  int id;  FUNCTION *func;  if (ARRAY_count(Breakpoint) >= MAX_BREAKPOINT)  {    fprintf(_out, "Too many breakpoints (max = %d)\n", MAX_BREAKPOINT);    return TRUE;  }  if (CLASS_is_native(class) || !class->debug)  {    fprintf(_out, "No debugging information\n");    return TRUE;  }  if (calc_position_from_line(class, line, &func, &addr))  {    fprintf(_out, "Cannot calc position from line number\n");    return TRUE;  }  if (!PCODE_is_breakpoint(*addr))  {    fprintf(_out, "Not a line beginning ?\n");    return TRUE;  }  if (*addr & 0xFF)  {    fprintf(_out, "Breakpoint already set\n");    return TRUE;  }  id = find_free_breakpoint();  if (id == 0)  {    fprintf(_out, "Cannot create breakpoint\n");    return TRUE;  }  brk = ARRAY_add(&Breakpoint);  brk->id = id;  /*brk->func = func;*/  brk->addr = addr;  brk->class = class;  brk->line = line;  *addr = PCODE_BREAKPOINT(id);  #ifdef DEBUG_ME  fprintf(stderr, "set_breakpoint: %s.%d\n", class->name, line);  #endif  return FALSE;}PRIVATE boolean unset_breakpoint(CLASS *class, ushort line){  int i;  for (i = 0; i < ARRAY_count(Breakpoint); i++)  {    if (Breakpoint[i].class == class && Breakpoint[i].line == line)    {      *(Breakpoint[i].addr) = PCODE_BREAKPOINT(0);      ARRAY_remove(&Breakpoint, i);      #ifdef DEBUG_ME      fprintf(stderr, "unset_breakpoint: %s.%d\n", class->name, line);      #endif      return FALSE;    }  }  fprintf(_out, "Unknown breakpoint\n");  return TRUE;}/*PRIVATE boolean reset_breakpoint(int num){  TRACE_BREAK *tb;  if (num < 0 || num >= MAX_BREAKPOINT)    return TRUE;  tb = &Breakpoint[num];  if (tb->addr == NULL)    return TRUE;  *(tb->addr) = tb->value;  EXEC_stop_next = TRUE;  Reset_breakpoint = num;  return FALSE;}PUBLIC ushort TRACE_get_current_line(void){  int i;  ushort pos = PC - FP->code;  if (FP->debug)  {    for (i = 0; i < (FP->debug->nline - 1); i++)    {      if (pos >= FP->debug->pos[i] && pos < FP->debug->pos[i + 1])        return i + FP->debug->line;    }  }  return 0;}*/PRIVATE void command_quit(const char *cmd){  exit(1);}PRIVATE void command_go(const char *cmd){  TRACE.stop = FALSE;  TRACE.fp = NULL;  TRACE.bp = NULL;}PRIVATE void command_step(const char *cmd){  TRACE_break_on_next_line();}PRIVATE void command_next(const char *cmd){  TRACE.stop = TRUE;  TRACE.fp = FP;  TRACE.bp = BP;}PRIVATE void command_from(const char *cmd){  STACK_CONTEXT *sc = STACK_get_current();  if (sc)  {    TRACE.stop = TRUE;    TRACE.fp = sc->fp;    TRACE.bp = sc->bp;  }  else    command_go(cmd);}PRIVATE void command_set_breakpoint(const char *cmd){  char class_name[64];  CLASS *class;  ushort line;  if (sscanf(cmd, "+%64[^.].%hu", class_name, &line) != 2)    fprintf(_out, "Syntax error\n");  else  {    class = CLASS_find(class_name);    CLASS_load_without_init(class);    set_breakpoint(class, line);  }}PRIVATE void command_unset_breakpoint(const char *cmd){  char class_name[64];  CLASS *class;  ushort line;  if (sscanf(cmd, "-%64[^.].%hu", class_name, &line) != 2)    fprintf(_out, "Syntax error\n");  else  {    class = CLASS_find(class_name);    CLASS_load_without_init(class);    unset_breakpoint(class, line);  }}PRIVATE void command_where(const char *cmd){  int i;  STACK_CONTEXT *context;  ushort line;  if (CP)    fprintf(_out, "%s", TRACE_get_current_position());  else    fprintf(_out, "?");  for (i = 0; i < (STACK_frame_count - 1); i++)  {    context = &STACK_frame[i];    if (context->pc)    {      line = 0;      if (calc_line_from_position(context->cp, context->fp, context->pc, &line))        fprintf(_out, " %s.?.?", context->cp->name);      else        fprintf(_out, " %s.%s.%d", context->cp->name, context->fp->debug->name, line);    }    else if (context->cp)      fprintf(_out, " ?");  }  if (Error)  {    fprintf(_out, "*");    ERROR_print_at(_out);  }  else    new_line();}PRIVATE void to_string(VALUE *value, char **addr, long *len, boolean *more){  static void *jump[16] = {    &&__VOID, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__FLOAT, &&__DATE,    &&__STRING, &&__STRING, &&__VARIANT, &&__ARRAY, &&__STRUCT, &&__FUNCTION, &&__CLASS, &&__NULL    };  VALUE conv;  *more = FALSE;__CONV:  if (TYPE_is_object(value->type))    goto __OBJECT;  else    goto *jump[value->type];__NULL:  *addr = "NULL";  *len = 4;  return;__BOOLEAN:  if (value->_boolean.value)  {    *addr = "TRUE";    *len = 4;  }  else  {    *addr = "FALSE";    *len = 5;  }  return;__BYTE:__SHORT:__INTEGER:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -