Pristine Ack-5.5
[Ack-5.5.git] / util / grind / position.c
1 /* $Id: position.c,v 1.7 1994/06/24 11:00:41 ceriel Exp $ */
2
3 #include        <stdio.h>
4 #include        <assert.h>
5 #include        <alloc.h>
6 #include        <out.h>
7 #include        <stb.h>
8
9 #include        "position.h"
10 #include        "scope.h"
11 #include        "file.h"
12 #include        "idf.h"
13 #include        "symbol.h"
14 #include        "misc.h"
15
16 extern FILE     *db_out;
17
18 static struct outname *f_start, *f_end;
19
20 /* extern p_position get_position_from_addr(t_addr t);
21    Returns a pointer to a structure containing the source position of the code
22    at address 't'.  0 is returned if no source position could be found.
23 */
24 p_position
25 get_position_from_addr(t)
26   t_addr t;
27 {
28   static t_position retval;
29   register struct outname *p;
30   register int i,j;
31
32   if (! f_start) return 0;
33   i = 0;
34   j = f_end - f_start;
35   do {
36         p = &f_start[((i + j) >> 1) + ((i + j) & 1)];
37         while ((p->on_type >> 8) != N_SLINE) p++;
38         if (p->on_valu > t) {
39                 p--;
40                 while (p > &f_start[i] && (p->on_type >> 8) != N_SLINE) p--;
41                 j = p-f_start;
42         }
43         else    i = p-f_start;
44   } while (i < j);
45   retval.lineno = f_start[j].on_desc;
46   p = &f_start[j-1];
47   while ((i = p->on_type >> 8) != N_SOL && i != N_SO) p--;
48   retval.filename = p->on_mptr;
49   return &retval;
50 }
51
52 /* extern t_addr get_addr_from_position(p_position p);
53    Returns the address of the code at position 'p', or ILL_ADDR if it could
54    not be found. If there is no symbolic information for the filename in
55    position 'p', an error message will be given.
56 */
57 t_addr
58 get_addr_from_position(p)
59   p_position p;
60 {
61   register p_symbol sym = Lookup(findidf(p->filename), PervasiveScope, FILESYM);
62
63   if (sym) {
64         register unsigned int i;
65         register p_file map = sym->sy_file;
66
67         for (i = p->lineno; i > 0; i--) {
68                 register struct outname *n = map->f_line_addr[HASH(i)];
69
70                 while (n) {
71                         if (n->on_desc == i) return (t_addr) n->on_valu;
72                         n = next_outname(n);
73                 }
74         }
75         return ILL_ADDR;
76   }
77   error("no symbolic information for file %s", p->filename);
78   return ILL_ADDR;
79 }
80
81 /* extern add_position_addr(char *filename, struct outname *n);
82    Adds the ('filename','lineno'),'t' pair to the mapping information.
83 */
84 add_position_addr(filename, n)
85   char *filename;
86   register struct outname *n;
87 {
88   static char *lastfile = 0;
89   static p_file lastmap = 0;
90   register p_file map = lastmap;
91
92   if (filename != lastfile) {   /* new file ... */
93         register p_symbol sym;
94
95         lastfile = filename;
96         if (! filename) {       /* last call */
97                 return;
98         }
99         sym = Lookup(findidf(filename), PervasiveScope, FILESYM);
100         if (sym) map = sym->sy_file; 
101         else {
102                 sym = add_file(filename);
103                 map = sym->sy_file;
104                 map->f_scope = FileScope;
105         }
106         lastmap = map;
107         if (! f_start) f_start = n;
108   }
109   else map = lastmap;
110   if (map) {
111         f_end = n;
112         setnext_outname(n, map->f_line_addr[HASH(n->on_desc)]);
113         map->f_line_addr[HASH(n->on_desc)] = n;
114   }
115 }
116
117 /* extern p_position print_position(t_addr a, int print_function);
118    Prints position 'a' and returns it. If 'print_function' is set,
119    an attempt is made to print the function name as well.
120 */
121 p_position
122 print_position(a, print_function)
123   t_addr        a;
124   int           print_function;
125 {
126   register p_position   pos = get_position_from_addr(a);
127
128   if (print_function) {
129         register p_scope sc = base_scope(get_scope_from_addr(a));
130         if (sc) fprintf(db_out, "in %s ", sc->sc_definedby->sy_idf->id_text);
131   }
132   if (pos) fprintf(db_out, "at \"%s\":%u", pos->filename, pos->lineno);
133   return pos;
134 }