cvsuser     02/08/25 16:39:16

  Modified:    .        debug.c
               include/parrot debug.h
               config/gen/makefiles root.in
  Log:
  Added conditional breakpoints.
  Fixed dependecies.
  More documentation.
  
  Revision  Changes    Path
  1.29      +252 -19   parrot/debug.c
  
  Index: debug.c
  ===================================================================
  RCS file: /cvs/public/parrot/debug.c,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -w -r1.28 -r1.29
  --- debug.c   22 Aug 2002 15:17:31 -0000      1.28
  +++ debug.c   25 Aug 2002 23:38:13 -0000      1.29
  @@ -2,7 +2,7 @@
    * debug.c
    *
    * CVS Info
  - *    $Id: debug.c,v 1.28 2002/08/22 15:17:31 grunblatt Exp $
  + *    $Id: debug.c,v 1.29 2002/08/25 23:38:13 grunblatt Exp $
    * Overview:
    *    Parrot debugger
    * History:
  @@ -19,14 +19,28 @@
   #include <stdio.h>
   #include <stdlib.h>
   
  +/* na(c) [Next Argument (Char pointer)]
  + *
  + * Moves the pointer to the next argument in the user input.
  + */
   #define na(c) { \
       while(*c && !isspace((int) *c)) \
           c++; \
       while(*c && isspace((int) *c)) \
           c++; }
   
  -/* PDB_get_command
  - * get a command from stdin to execute
  +/* PDB_get_command(struct Parrot_Interp *interpreter)
  + *
  + * Get a command from the user input to execute.
  + *
  + * It saves the last command executed (in pdb->last_command), so it first 
  + * frees the old one and updates it with the current one.
  + *
  + * Also prints the next line to run if the program is still active.
  + *
  + * The user input can't be longer than 255 characters.
  + *
  + * The input is saved in pdb->cur_command.
    */
   void
   PDB_get_command(struct Parrot_Interp *interpreter)
  @@ -40,7 +54,7 @@
       fflush(stdout);
   
       /* not used any more */ 
  -    if (pdb->last_command && *pdb->cur_command)
  +    if (pdb->last_command && *pdb->last_command)
           mem_sys_free(pdb->last_command);
   
       /* update the last command */
  @@ -77,8 +91,11 @@
       pdb->cur_command = c;
   }
           
  -/* PDB_run_command
  - * run a command
  +/* PDB_run_command(struct Parrot_Interp *interpreter, const char *command)
  + *
  + * Run a command.
  + *
  + * Hash the command to make a simple switch calling the correct handler.
    */
   void
   PDB_run_command(struct Parrot_Interp *interpreter, const char *command)
  @@ -177,29 +194,36 @@
       }
   }
   
  -/* PDB_next
  - * execute the next instruction
  +/* PDB_next(struct Parrot_Interp *interpreter, const char *command)
  + *
  + * Execute the next N operation(s).
  + *
  + * Inits the program if needed, runs the next N >= 1 operations and 
  + * stops.
  + * 
    */
   void
  -PDB_next(struct Parrot_Interp *interpreter,
  -         const char *command)
  +PDB_next(struct Parrot_Interp *interpreter, const char *command)
   {
       PDB_t *pdb = interpreter->pdb;
       unsigned long n = 1;
   
  +    /* Init the program if it's not running */
       if (!(pdb->state & PDB_RUNNING))
  -    {
           PDB_init(interpreter,command);
  -    }
       
  +    /* Get the number of operations to execute if any */
       if (command && isdigit((int) *command))
           n = atol(command);
   
  +    /* Erase the stopped flag */
       pdb->state &= ~PDB_STOPPED;
   
  +    /* Execute */
       for ( ; n && pdb->cur_opcode; n--)
           DO_OP(pdb->cur_opcode,interpreter);
   
  +    /* Set the stopped flag */
       pdb->state |= PDB_STOPPED;
   
       /* If program ended */
  @@ -243,12 +267,143 @@
           PDB_program_end(interpreter);
   }
   
  +/*  PDB_cond
  + *
  + *  Analyzes a condition from the user input.
  + */
  +PDB_condition_t *
  +PDB_cond(struct Parrot_Interp *interpreter, const char *command)
  +{
  +    PDB_t *pdb = interpreter->pdb;
  +    PDB_breakpoint_t *newbreak,*sbreak;
  +    PDB_condition_t *condition;
  +    int i;
  +    char str[255];
  +
  +    /* Allocate new condition */
  +    condition = (PDB_condition_t *)mem_sys_allocate(sizeof(PDB_condition_t));
  +    /* The first argument after the 'if' MUST be a register of any type. */
  +    na(command);
  +
  +    /* return if no more arguments */
  +    if (!(command && *command))
  +        return NULL;
  +
  +    switch (*command) {
  +        case 'i':
  +        case 'I':
  +            condition->type = PDB_cond_int;
  +            break;
  +        case 'n':
  +        case 'N':
  +            condition->type = PDB_cond_num;
  +            break;
  +        case 's':
  +        case 'S':
  +            condition->type = PDB_cond_str;
  +            break;
  +        case 'p':
  +        case 'P':
  +            condition->type = PDB_cond_pmc;
  +            break;
  +        default:
  +            fprintf(stderr, "First argument must be a register\n");
  +            return NULL;
  +    }
  +
  +    /* get the register number */
  +    condition->reg = atoi(++command);
  +
  +    /* the next argument might have no spaces between the register and the
  +     * condition. */
  +    command++;
  +
  +    if (condition->reg > 9)
  +        command++;
  +
  +    if (*command == ' ')
  +        na(command);
  +
  +    /* Now the condition */
  +    switch (*command) {
  +        case '>':
  +            if (*(command + 1) == '=')
  +                condition->type |= PDB_cond_ge;
  +            else if (*(command + 1) == ' ')
  +                condition->type |= PDB_cond_gt;
  +            else
  +                goto INV_COND;     
  +            break;
  +        case '<':
  +            if (*(command + 1) == '=')
  +                condition->type |= PDB_cond_le;
  +            else if (*(command + 1) == ' ')
  +                condition->type |= PDB_cond_lt;
  +            else
  +                goto INV_COND;     
  +            break;
  +        case '=':
  +            if (*(command + 1) == '=')
  +                condition->type |= PDB_cond_eq;
  +            else
  +                goto INV_COND;     
  +            break;
  +        case '!':
  +            if (*(command + 1) == '=')
  +                condition->type |= PDB_cond_ne;
  +            else
  +                goto INV_COND;     
  +            break;
  +        default:
  +INV_COND:   fprintf(stderr, "Invalid condition\n");
  +            return NULL;
  +    }
  +
  +    if (*(command + 1) == '=')
  +        command += 2;
  +    else
  +        command ++;
  +
  +    if (*command == ' ')
  +        na(command);
  +
  +    /* return if no more arguments */
  +    if (!(command && *command))
  +        return NULL;
  +
  +    if (!((isdigit((int)*command)) || (*command == '"'))) {
  +        condition->value = (void *)mem_sys_allocate(sizeof(int));
  +        *(int *)condition->value = (int)atoi(++command);
  +    }
  +    /* If the first argument was an integer */
  +    else if (condition->type & PDB_cond_int) {
  +        /* This must be either an integer constant or register */
  +        condition->value = (void *)mem_sys_allocate(sizeof(INTVAL));
  +        *(INTVAL *)condition->value = (INTVAL)atoi(command);
  +        condition->type |= PDB_cond_const;
  +    }
  +    else if (condition->type & PDB_cond_num) {
  +        condition->value = (void *)mem_sys_allocate(sizeof(FLOATVAL));
  +        *(FLOATVAL *)condition->value = (FLOATVAL)atof(command);
  +        condition->type |= PDB_cond_const;
  +    }
  +    else if (condition->type & PDB_cond_str) {
  +        for (i = 1; ((command[i] != '"') && (i < 255)); i++)
  +            str[i - 1] = command[i];
  +        str[i - 1] = '\0'; 
  +        (STRING *)condition->value = string_make(interpreter,
  +            str, i - 1, NULL, BUFFER_external_FLAG, NULL);
  +        condition->type |= PDB_cond_const;
  +    }
  +
  +    return condition;
  +}
  + 
   /* PDB_set_break
    * set a break point, the source code file must be loaded.
    */
   void
  -PDB_set_break(struct Parrot_Interp *interpreter,
  -              const char *command)
  +PDB_set_break(struct Parrot_Interp *interpreter, const char *command)
   {
       PDB_t *pdb = interpreter->pdb;
       PDB_breakpoint_t *newbreak,*sbreak;
  @@ -304,6 +459,14 @@
       /* Allocate the new break point */
       newbreak = (PDB_breakpoint_t *)mem_sys_allocate(sizeof(PDB_breakpoint_t));
   
  +    na(command);
  +
  +    /* if there is another argument to break, besides the line number,
  +     * it should be an 'if', so we call another handler. */
  +    if (command && *command &&
  +        !(newbreak->condition = PDB_cond(interpreter, command)))
  +            return;
  + 
       /* Set the address where to stop */
       newbreak->pc = line->opcode;
       /* No next breakpoint */
  @@ -448,6 +611,72 @@
       return 1;
   }
   
  +/* PDB_check_condition
  + *
  + * Returns TRUE if the condition was met.
  + */
  +char
  +PDB_check_condition(struct Parrot_Interp *interpreter, 
  +    PDB_condition_t *condition)
  +{
  +    INTVAL i,j;
  +    FLOATVAL k, l;
  +    STRING *m, *n;
  +
  +    if (condition->type & PDB_cond_int) {
  +        i = interpreter->ctx.int_reg.registers[condition->reg];
  +        if (condition->type & PDB_cond_const)
  +            j = *(INTVAL *)condition->value;
  +        else
  +            j = interpreter->ctx.int_reg.registers[*(int *)condition->value];
  +        if (((condition->type & PDB_cond_gt) && (i > j)) ||
  +            ((condition->type & PDB_cond_ge) && (i >= j)) ||
  +            ((condition->type & PDB_cond_eq) && (i == j)) ||
  +            ((condition->type & PDB_cond_ne) && (i != j)) ||
  +            ((condition->type & PDB_cond_le) && (i <= j)) ||
  +            ((condition->type & PDB_cond_lt) && (i < j)))
  +                return 1;
  +        return 0;
  +    }
  +    else if (condition->type & PDB_cond_num) {
  +        k = interpreter->ctx.num_reg.registers[condition->reg];
  +        if (condition->type & PDB_cond_const)
  +            l = *(FLOATVAL *)condition->value;
  +        else
  +            l = interpreter->ctx.num_reg.registers[*(int *)condition->value];
  +        if (((condition->type & PDB_cond_gt) && (k > l)) ||
  +            ((condition->type & PDB_cond_ge) && (k >= l)) ||
  +            ((condition->type & PDB_cond_eq) && (k == l)) ||
  +            ((condition->type & PDB_cond_ne) && (k != l)) ||
  +            ((condition->type & PDB_cond_le) && (k <= l)) ||
  +            ((condition->type & PDB_cond_lt) && (k < l)))
  +                return 1;
  +        return 0;
  +    }
  +    else if (condition->type & PDB_cond_str) {
  +        m = interpreter->ctx.string_reg.registers[condition->reg];
  +        if (condition->type & PDB_cond_const)
  +            n = (STRING *)condition->value;
  +        else
  +            n = interpreter->ctx.string_reg.registers[*(int *)condition->value];
  +        if (((condition->type & PDB_cond_gt) && 
  +                (string_compare(interpreter, m, n) > 0)) ||
  +            ((condition->type & PDB_cond_ge) &&
  +                (string_compare(interpreter, m, n) >= 0)) ||
  +            ((condition->type & PDB_cond_eq) &&
  +                (string_compare(interpreter, m, n) == 0)) ||
  +            ((condition->type & PDB_cond_ne) &&
  +                (string_compare(interpreter, m, n) != 0)) ||
  +            ((condition->type & PDB_cond_le) &&
  +                (string_compare(interpreter, m, n) <= 0)) ||
  +            ((condition->type & PDB_cond_lt) &&
  +                (string_compare(interpreter, m, n) < 0)))
  +                    return 1;
  +        return 0;
  +    }
  +    return 0;
  +}
  +
   /* PDB_break
    * return true if we have to stop running
    */
  @@ -479,6 +708,11 @@
               if (breakpoint->skip < 0)
                   return 0;
   
  +            /* Check if there is a condition for this breakpoint */
  +            if ((breakpoint->condition) &&
  +                (!PDB_check_condition(interpreter, breakpoint->condition)))
  +                    return 0;
  +
               /* Add the STOPPED state and stop */ 
               pdb->state |= PDB_STOPPED;
               return 1;
  @@ -691,8 +925,7 @@
                                            constants[pc[j]]->string->strstart,
                                                interpreter->code->const_table->
                                            constants[pc[j]]->string->strlen);
  -                        if (escaped)
  -                        {
  +                        if (escaped) {
                               strcpy(&pfile->source[pfile->size],escaped);
                               pfile->size += strlen(escaped);
                               mem_sys_free(escaped);
  @@ -1086,7 +1319,7 @@
       char s[1], *c = buf;
       op_info_t *op_info;
       /* Opcodes can't have more that 10 arguments */
  -    opcode_t eval[11],*run;
  +    opcode_t eval[10],*run;
       int op_number,i,k,l,j = 0;
   
       /* find_op needs a string with only the opcode name */
  
  
  
  1.12      +96 -14    parrot/include/parrot/debug.h
  
  Index: debug.h
  ===================================================================
  RCS file: /cvs/public/parrot/include/parrot/debug.h,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -w -r1.11 -r1.12
  --- debug.h   23 Jul 2002 14:33:53 -0000      1.11
  +++ debug.h   25 Aug 2002 23:38:44 -0000      1.12
  @@ -2,7 +2,7 @@
    * debug.h
    *
    * CVS Info
  - *    $Id: debug.h,v 1.11 2002/07/23 14:33:53 grunblatt Exp $
  + *    $Id: debug.h,v 1.12 2002/08/25 23:38:44 grunblatt Exp $
    * Overview:
    *    Parrot debugger header files
    * History:
  @@ -23,6 +23,41 @@
       PDB_EXIT        = 1 << 5
   };
   
  +enum {
  +    PDB_cond_int    = 1 << 0,
  +    PDB_cond_num    = 1 << 1,
  +    PDB_cond_str    = 1 << 2,
  +    PDB_cond_pmc    = 1 << 3,
  +    PDB_cond_gt     = 1 << 4,
  +    PDB_cond_ge     = 1 << 5,
  +    PDB_cond_eq     = 1 << 6,
  +    PDB_cond_ne     = 1 << 7,
  +    PDB_cond_le     = 1 << 8,
  +    PDB_cond_lt     = 1 << 9,
  +    PDB_cond_const  = 1 << 10
  +};
  +
  +/*  PDB_condition_t
  + *      Conditions for breakpoint or watchpoints.
  + *
  + *  type:           The type of condition and the way to use arguments.
  + *  reg:            The register involved, there must be at least one.
  + *  value:          A pointer to the second argument.
  + */
  +
  +typedef struct PDB_condition {
  +    unsigned short          type;
  +    unsigned char           reg;
  +    void                    *value;
  +} PDB_condition_t;
  +
  +/*  PDB_label_t 
  + *      A label in the source file.
  + *
  + *  opcode:         The pointer to the bytecode where the label is.
  + *  number:         Number label.
  + */
  +
   typedef struct PDB_label *PDB_label_ptr;
   
   typedef struct PDB_label {
  @@ -31,6 +66,15 @@
       PDB_label_ptr           next;
   } PDB_label_t;
   
  +/*  PDB_line_t
  + *      A line in the source file. 
  + *
  + *  opcode:         A pointer to the opcode in the bytecode correspoinding to
  + *                  this line.
  + *  source_offset:  Offset from the source file start.
  + *  number:         Line number.
  + *  label:          The label if any.
  + */
   typedef struct PDB_line *PDB_line_ptr;
   
   typedef struct PDB_line {
  @@ -41,6 +85,16 @@
       PDB_line_ptr            next;
   } PDB_line_t;
   
  +/*  PDB_file_t
  + *      A source code file.
  + *
  + *  sourcefilename: The source code file name.
  + *  source:         The file it self.
  + *  size:           The size of the file.
  + *  list_line:      The next line to list.
  + *  line:           The first line of the source code.
  + *  label:          The first label.
  + */
   typedef struct PDB_file *PDB_file_ptr;
   
   typedef struct PDB_file {
  @@ -53,17 +107,38 @@
       PDB_file_ptr            next;
   } PDB_file_t;
   
  +/*  PDB_breakpoint_t
  + *      List of breakpoints.
  + *
  + *  pc:             Where the breakpoint is.
  + *  skip:           The number of times to skip this breakpoint.
  + */
  +
   typedef struct PDB_breakpoint *PDB_breakpoint_ptr;
   
   typedef struct PDB_breakpoint {
       opcode_t *              pc;
       long                    skip;
  +    PDB_condition_t         *condition;
       PDB_breakpoint_ptr      next;
   } PDB_breakpoint_t;
   
  +/*  PDB_t
  + *      The debugger.
  + *
  + *  file:               Source code file.
  + *  breakpoint:         The first breakpoint.
  + *  breakpoint_skip:    Number of breakpoints to skip.
  + *  cur_command:        The command being executed.
  + *  last_command:       Last command executed.
  + *  cur_opcode:         Current opcode.
  + *  state:              The status of the program being debugged.
  + */
  +
   typedef struct PDB {
       PDB_file_t *            file;
       PDB_breakpoint_t *      breakpoint;
  +    PDB_condition_t         *watchpoint;
       long                    breakpoint_skip;
       char *                  cur_command;
       char *                  last_command;
  @@ -123,6 +198,11 @@
   
   void PDB_set_break(struct Parrot_Interp *, const char *);
   
  +PDB_condition_t *PDB_cond(struct Parrot_Interp *, const char *);
  +
  +char PDB_check_condition(struct Parrot_Interp *interpreter, 
  +                         PDB_condition_t *condition);
  +
   char PDB_program_end(struct Parrot_Interp *);
   
   char PDB_hasinstruction(char *);
  @@ -168,6 +248,7 @@
   #define c_r             29325
   #define c_s             29580
   #define c_t             29835
  +#define c_w             30600
   #define c_int           175185
   #define c_run           176460
   #define c_num           174675
  @@ -184,6 +265,7 @@
   #define c_print         441150
   #define c_stack         414120
   #define c_trace         405705
  +#define c_watch         416160
   #define c_delete        588285
   #define c_continue      1053405
   #define c_disassemble   1903830
  
  
  
  1.24      +3 -3      parrot/config/gen/makefiles/root.in
  
  Index: root.in
  ===================================================================
  RCS file: /cvs/public/parrot/config/gen/makefiles/root.in,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -w -r1.23 -r1.24
  --- root.in   22 Aug 2002 21:55:09 -0000      1.23
  +++ root.in   25 Aug 2002 23:39:15 -0000      1.24
  @@ -67,7 +67,7 @@
   $(INC)/oplib/core_ops_prederef.h $(INC)/runops_cores.h $(INC)/trace.h \
   $(INC)/pmc.h $(INC)/key.h $(INC)/hash.h $(INC)/resources.h $(INC)/platform.h 
${cg_h} \
   $(INC)/interp_guts.h $(INC)/rx.h $(INC)/rxstacks.h \
  -$(INC)/embed.h $(INC)/warnings.h $(INC)/misc.h $(INC)/debug.h $(INC)/pmc.h \
  +$(INC)/embed.h $(INC)/warnings.h $(INC)/misc.h $(INC)/pmc.h \
   $(INC)/key.h $(INC)/hash.h $(INC)/smallobject.h $(INC)/headers.h $(INC)/dod.h \
   $(INC)/method_util.h
   
  @@ -332,7 +332,7 @@
   
   platform$(O) : $(GENERAL_H_FILES)
   
  -debug$(O) : $(GENERAL_H_FILES)
  +debug$(O) : $(GENERAL_H_FILES) $(INC)/debug.h
   
   method_util$(O) : $(GENERAL_H_FILES)
   
  @@ -384,7 +384,7 @@
   
   stacks$(O) : $(GENERAL_H_FILES)
   
  -embed$(O) : $(GENERAL_H_FILES)
  +embed$(O) : $(GENERAL_H_FILES) $(INC)/debug.h
   
   core_ops$(O) : $(GENERAL_H_FILES) core_ops.c
   
  
  
  


Reply via email to