~ubuntu-branches/ubuntu/breezy/malaga/breezy

« back to all changes in this revision

Viewing changes to breakpoints.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Bushnell, BSG
  • Date: 2005-01-10 11:52:04 UTC
  • mfrom: (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050110115204-hpgncw5pb0m1t8i6
Tags: 6.13-5
debian/control (malaga-doc Recommends): Suggest gv as a
postscript-viewer instead of ghostview.  (Closes: #289701).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 1995 Bjoern Beutel. */
 
2
 
 
3
/* Description. =============================================================*/
 
4
 
 
5
/* In this file, the administration of breakpoints is managed. */
 
6
 
 
7
/* Includes. ================================================================*/
 
8
 
 
9
#include <stdio.h>
 
10
#include <stdlib.h>
 
11
#include <ctype.h>
 
12
#include <setjmp.h>
 
13
#include <string.h>
 
14
#include "basic.h"
 
15
#include "pools.h"
 
16
#include "values.h"
 
17
#include "files.h"
 
18
#include "rule_type.h"
 
19
#include "rules.h"
 
20
#include "input.h"
 
21
#include "commands.h"
 
22
#include "breakpoints.h"
 
23
 
 
24
/* Types. ===================================================================*/
 
25
 
 
26
typedef struct /* Definition of a breakpoint. */
 
27
 
28
  list_node_t *next;
 
29
  int_t number; /* Breakpoint number. */
 
30
  rule_sys_t *rule_sys; /* Rule system of breakpoint. */
 
31
  int_t instr; /* Instruction to break at. */
 
32
} breakpoint_t;
 
33
 
 
34
/* Variables. ===============================================================*/
 
35
 
 
36
static int_t breakpoint_count; /* Number of breakpoints so far. */
 
37
static list_t breakpoints; /* List of breakpoints. */
 
38
 
 
39
static int_t rule_system_count; /* Number of loaded rule systems. */
 
40
static rule_sys_name_t *rule_systems; /* Name for each rule system. */
 
41
 
 
42
/* Functions. ===============================================================*/
 
43
 
 
44
static int_t 
 
45
instruction_at( rule_sys_t *rule_sys, string_t file, int_t line )
 
46
/* Return the index of the first instruction at RULE_SYS, FILE, LINE
 
47
 * or -1 if there is no code there. */
 
48
 
49
  src_line_t *src_line;
 
50
  
 
51
  for (src_line = rule_sys->src_lines; 
 
52
       src_line < rule_sys->src_lines + rule_sys->src_line_count; 
 
53
       src_line++) 
 
54
  { 
 
55
    if (src_line->file != -1 
 
56
        && strcmp( rule_sys->strings + src_line->file, file ) == 0 
 
57
        && src_line->line >= line) 
 
58
    { 
 
59
      return src_line->instr; 
 
60
    }
 
61
  }
 
62
  return -1;
 
63
}
 
64
 
 
65
/*---------------------------------------------------------------------------*/
 
66
 
 
67
static int_t 
 
68
find_rule_by_name( rule_sys_t *rule_sys, string_t rule_name )
 
69
/* Find the first line of rule RULE_NAME in RULE_SYS.
 
70
 * Return the first instruction of this rule. */
 
71
 
72
  int_t i;
 
73
  
 
74
  for (i = 0; i < rule_sys->rule_count; i++) 
 
75
  { 
 
76
    if (strcmp_no_case( rule_sys->strings + rule_sys->rules[i].name,
 
77
                        rule_name ) == 0) 
 
78
    { 
 
79
      return rule_sys->rules[i].first_instr; 
 
80
    }
 
81
  }
 
82
  return -1;
 
83
}
 
84
 
 
85
/*---------------------------------------------------------------------------*/
 
86
 
 
87
static string_t 
 
88
complete_file_name( rule_sys_t *rule_sys, string_t file_name )
 
89
/* Return FILE_NAME completed if it is in RULE_SYS, else return NULL. */
 
90
 
91
  src_line_t *src_line;
 
92
  
 
93
  for (src_line = rule_sys->src_lines;
 
94
       src_line < rule_sys->src_lines + rule_sys->src_line_count; 
 
95
       src_line++) 
 
96
  { 
 
97
    if (src_line->file != -1 
 
98
        && strcmp( name_in_path( rule_sys->strings + src_line->file ),
 
99
                   file_name ) == 0) 
 
100
    { 
 
101
      return rule_sys->strings + src_line->file; 
 
102
    }
 
103
  }
 
104
  return NULL;
 
105
}
 
106
 
 
107
/*---------------------------------------------------------------------------*/
 
108
 
 
109
static void 
 
110
parse_breakpoint( string_t arguments, 
 
111
                  rule_sys_t **rule_sys, 
 
112
                  string_t *file, 
 
113
                  int_t *line )
 
114
/* Parse a breakpoint specification; ARGUMENTS must be
 
115
 * "" (nothing) or
 
116
 * "LINE_NUMBER" or
 
117
 * "[RULE_SYS_NAME] [FILE LINE_NUMBER | RULE_NAME]".
 
118
 * Set RULE_SYS, FILE and LINE according to it. */
 
119
 
120
  int_t first_instr;
 
121
  string_t argument;
 
122
  int_t i;
 
123
      
 
124
  if (pc == -1) 
 
125
  { 
 
126
    *rule_sys = NULL; 
 
127
    *file = NULL; 
 
128
    *line = -1; 
 
129
  } 
 
130
  else 
 
131
  { 
 
132
    *rule_sys = executed_rule_sys;
 
133
    source_of_instr( executed_rule_sys, pc, line, file, NULL );
 
134
  }
 
135
  if (IS_DIGIT( *arguments )) 
 
136
    *line = parse_int( &arguments );
 
137
  else if (*arguments != EOS) /* Read file name or rule name. */  
 
138
  { 
 
139
    argument = parse_word( &arguments );
 
140
 
 
141
    /* See if ARGUMENT is a rule system name. */
 
142
    for (i = 0; i < rule_system_count; i++) 
 
143
    { 
 
144
      if (rule_systems[i].rule_sys != NULL
 
145
          && strcmp_no_case( argument, rule_systems[i].name ) == 0) 
 
146
      { 
 
147
        *rule_sys = rule_systems[i].rule_sys;
 
148
        free_mem( &argument );
 
149
        argument = parse_word( &arguments );
 
150
        break;
 
151
      }
 
152
    } 
 
153
 
 
154
    /* If a line number follows, we have a file name. */
 
155
    if (IS_DIGIT( *arguments )) 
 
156
    { 
 
157
      *line = parse_int( &arguments );
 
158
      if (*rule_sys != NULL) 
 
159
        *file = complete_file_name( *rule_sys, argument );
 
160
      else 
 
161
      { 
 
162
        for (i = 0; i < rule_system_count; i++) 
 
163
        { 
 
164
          if (rule_systems[i].rule_sys != NULL) 
 
165
          { 
 
166
            *rule_sys = rule_systems[i].rule_sys;
 
167
            *file = complete_file_name( *rule_sys, argument );
 
168
            if (*file != NULL) 
 
169
              break;
 
170
          }
 
171
        }
 
172
      }
 
173
      if (*file == NULL) 
 
174
        complain( "No source file \"%s\".", argument );
 
175
    } 
 
176
    else /* ARGUMENT should be a rule name. */
 
177
    { 
 
178
      if (*rule_sys != NULL) 
 
179
        first_instr = find_rule_by_name( *rule_sys, argument );
 
180
      else 
 
181
      { 
 
182
        first_instr = -1; /* Prevent a "not initialized" warning. */
 
183
        for (i = 0; i < rule_system_count; i++) 
 
184
        { 
 
185
          if (rule_systems[i].rule_sys != NULL) 
 
186
          { 
 
187
            *rule_sys = rule_systems[i].rule_sys;
 
188
            first_instr = find_rule_by_name( *rule_sys, argument );
 
189
            if (first_instr != -1) 
 
190
              break;
 
191
          }
 
192
        }
 
193
      }
 
194
      if (first_instr == -1) 
 
195
        complain( "Rule \"%s\" is unknown.", argument );
 
196
      
 
197
      /* Find the corresponding source line. */
 
198
      source_of_instr( *rule_sys, first_instr, line, file, NULL );
 
199
    }
 
200
    free_mem( &argument );
 
201
  }
 
202
  parse_end( &arguments );
 
203
  
 
204
  if (*file == NULL) 
 
205
    complain( "Missing file name." );
 
206
  if (*line == -1) 
 
207
    complain( "Missing line number." );
 
208
}
 
209
 
 
210
/*---------------------------------------------------------------------------*/
 
211
 
 
212
int_t 
 
213
at_breakpoint( rule_sys_t *rule_sys, int_t instr )
 
214
/* Return breakpoint number if INSTR in RULE_SYS hits a 
 
215
 * breakpoint; return 0 else. */
 
216
 
217
  breakpoint_t *bp;
 
218
  
 
219
  FOREACH( bp, breakpoints ) 
 
220
  { 
 
221
    if (bp->rule_sys == rule_sys && bp->instr == instr) 
 
222
      return bp->number;
 
223
  }
 
224
  return 0;
 
225
}
 
226
 
 
227
/*---------------------------------------------------------------------------*/
 
228
 
 
229
static void 
 
230
delete_all_breakpoints( void )
 
231
/* Run through breakpoint list and free all breakpoints. */
 
232
 
233
  while (breakpoints.first != NULL) 
 
234
    free_first_node( &breakpoints );
 
235
}
 
236
 
 
237
/*---------------------------------------------------------------------------*/
 
238
 
 
239
static void 
 
240
do_delete( string_t argument )
 
241
/* Remove a breakpoint. */
 
242
 
243
  string_t word;
 
244
  int_t break_num;
 
245
  breakpoint_t *breakpoint;
 
246
 
 
247
  if (IS_ALPHA( *argument )) 
 
248
  { 
 
249
    word = parse_word( &argument );
 
250
    if (strcmp_no_case( word, "all" ) != 0) 
 
251
      complain( "\"all\" or breakpoint numbers expected, not \"%s\".", word );
 
252
    delete_all_breakpoints();
 
253
  } 
 
254
  else 
 
255
  { 
 
256
    while (*argument != EOS) 
 
257
    { 
 
258
      break_num = parse_int( &argument );
 
259
 
 
260
      /* Delete breakpoint with BREAK_NUM. */
 
261
      FOREACH( breakpoint, breakpoints ) 
 
262
      { 
 
263
        if (breakpoint->number == break_num) 
 
264
          break;
 
265
      }
 
266
      if (breakpoint == NULL) 
 
267
        complain( "No breakpoint %d.", break_num );
 
268
      free_node( &breakpoints, (list_node_t *) breakpoint );
 
269
    }
 
270
  }
 
271
  parse_end( &argument );
 
272
}
 
273
 
 
274
command_t delete_command = 
 
275
 
276
  "delete d", do_delete,
 
277
  "Delete breakpoints.\n"
 
278
  "Usage:\n"
 
279
  "  delete NUMBER ... -- Delete specified breakpoints.\n"
 
280
  "  delete all -- Delete all breakpoints.\n"
 
281
};
 
282
 
 
283
/*---------------------------------------------------------------------------*/
 
284
 
 
285
void 
 
286
get_breakpoint( string_t argument, 
 
287
                rule_sys_t **rule_sys_p, int_t *instr_p )
 
288
/* Parse a breakpoint in ARGUMENT and set the remaining arguments. */
 
289
 
290
  string_t file;
 
291
  int_t line;
 
292
 
 
293
  /* Parse breakpoint ARGUMENT. */
 
294
  parse_breakpoint( argument, rule_sys_p, &file, &line );
 
295
 
 
296
  /* Find first instruction of this breakpoint */
 
297
  *instr_p = instruction_at( *rule_sys_p, file, line );
 
298
  if (*instr_p == -1) 
 
299
    complain( "No code at file \"%s\", line %d.", name_in_path( file ), line );
 
300
}
 
301
 
 
302
/*---------------------------------------------------------------------------*/
 
303
 
 
304
static void 
 
305
do_break( string_t argument )
 
306
/* Define a breakpoint. */
 
307
 
308
  rule_sys_t *rule_sys;
 
309
  string_t file, rule;
 
310
  int_t line, instr;
 
311
  breakpoint_t *breakpoint;
 
312
 
 
313
  /* Parse breakpoint ARGUMENT. */
 
314
  get_breakpoint( argument, &rule_sys, &instr );
 
315
 
 
316
  /* Check if other breakpoints exist at this position. */
 
317
  FOREACH( breakpoint, breakpoints ) 
 
318
  { 
 
319
    if (breakpoint->rule_sys == rule_sys && breakpoint->instr == instr) 
 
320
      complain( "Breakpoint %d already set here.", breakpoint->number );
 
321
  }
 
322
 
 
323
  /* Add breakpoint. */
 
324
  breakpoint = new_node( &breakpoints, sizeof( breakpoint_t ), LIST_END );
 
325
  breakpoint->number = ++breakpoint_count;
 
326
  breakpoint->rule_sys = rule_sys;
 
327
  breakpoint->instr = instr;
 
328
 
 
329
  /* Print source position of the instruction. */
 
330
  source_of_instr( rule_sys, instr, &line, &file, &rule );
 
331
  printf( "Breakpoint %d in file \"%s\", line %d, rule \"%s\".\n",
 
332
          breakpoint->number, name_in_path( file ), line, rule );
 
333
}
 
334
 
 
335
command_t break_command = 
 
336
 
337
  "break b", do_break,
 
338
  "Set a breakpoint at the specified position.\n"
 
339
  "Usage:\n"
 
340
  "  break RULE -- Set a breakpoint at the beginning of RULE.\n"
 
341
  "  break FILE LINE -- Set a breakpoint at LINE in FILE.\n"
 
342
  "  break LINE -- Set a breakpoint at LINE in the current rule file.\n"
 
343
  "  break -- Set a breakpoint at the current line in the current rule file.\n"
 
344
  "The first two forms may begin with a rule system specification.\n"
 
345
  "The last two forms can only be used in debug mode or after a rule error.\n"
 
346
  "You can't set two breakpoints at the same position.\n"
 
347
};
 
348
 
 
349
/*---------------------------------------------------------------------------*/
 
350
 
 
351
static void 
 
352
do_list( string_t argument )
 
353
/* List breakpoints. */
 
354
 
355
  breakpoint_t *breakpoint;
 
356
  string_t file, rule;
 
357
  int_t line;
 
358
 
 
359
  parse_end( &argument );
 
360
 
 
361
  if (breakpoints.first == NULL) 
 
362
    printf( "No breakpoints.\n" );
 
363
  FOREACH( breakpoint, breakpoints )
 
364
  { 
 
365
    source_of_instr( breakpoint->rule_sys, breakpoint->instr, 
 
366
                     &line, &file, &rule );
 
367
    printf( "Breakpoint %d in file \"%s\", line %d, rule \"%s\".\n", 
 
368
            breakpoint->number, name_in_path( file ), line, rule );
 
369
  }
 
370
}
 
371
 
 
372
command_t list_command = 
 
373
 
374
  "list l", do_list,
 
375
  "List all breakpoints.\n"
 
376
  "Usage: list\n"
 
377
};
 
378
 
 
379
/*---------------------------------------------------------------------------*/
 
380
 
 
381
void 
 
382
init_breakpoints( int_t rule_sys_count, rule_sys_name_t rule_sys[] )
 
383
/* Initialise this module. 
 
384
 * Pass the number of rule systems in RULE_SYS_COUNT
 
385
 * and their names in RULE_SYS. */
 
386
 
387
  rule_system_count = rule_sys_count;
 
388
  rule_systems = rule_sys;
 
389
  clear_list( &breakpoints );
 
390
}
 
391
 
 
392
/*---------------------------------------------------------------------------*/
 
393
 
 
394
void 
 
395
terminate_breakpoints( void )
 
396
/* Terminate this module. */
 
397
 
398
  delete_all_breakpoints(); 
 
399
}
 
400
 
 
401
/* End of file. =============================================================*/