1 /*
2 Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 R. Bernstein
3 <rocky@gnu.org>
4 This file is part of GNU Make (remake variant).
5
6 GNU Make is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Make is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Make; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20 /* Create filename to line number table used by breakpoints */
21 #include "../make.h"
22 #include <assert.h>
23 #include "../filedef.h"
24 #include "../file.h"
25 #include "../read.h"
26 #include "../rule.h"
27 #include "./file2line.h"
28
29 unsigned long
file2lines_hash_1(const void * key)30 file2lines_hash_1 (const void *key)
31 {
32 return_ISTRING_HASH_1 (((const lineno_array_t *) key)->hname);
33 }
34
35 unsigned long
file2lines_hash_2(const void * key)36 file2lines_hash_2 (const void *key)
37 {
38 return_ISTRING_HASH_2 (((const lineno_array_t *) key)->hname);
39 }
40
41 static int
file2lines_hash_cmp(const void * x,const void * y)42 file2lines_hash_cmp (const void *x, const void *y)
43 {
44 return strcmp(((const lineno_array_t *) x)->hname,
45 ((const lineno_array_t *) y)->hname);
46 }
47
48 lineno_array_t *
lookup_file2lines(const char * psz_filename)49 lookup_file2lines (const char *psz_filename)
50 {
51 assert (*psz_filename != '\0');
52 return hash_find_item (&file2lines, &psz_filename);
53 }
54
55 /* FIXME return a status code when we fail. */
56 file_t *
target_for_file_and_line(const char * psz_filename,unsigned int lineno,f2l_entry_t * entry_type)57 target_for_file_and_line (const char *psz_filename, unsigned int lineno,
58 /*out*/ f2l_entry_t *entry_type)
59 {
60 lineno_array_t **pp_linenos;
61 lineno_array_t lookup_linenos;
62 assert (*psz_filename != '\0');
63 lookup_linenos.hname = psz_filename;
64 if (0 == file2lines.ht_size) file2lines_init();
65 pp_linenos = (lineno_array_t **)
66 hash_find_slot(&file2lines, &lookup_linenos);
67
68 if (NULL == *pp_linenos) return NULL;
69 if (lineno > (*pp_linenos)->size) return NULL;
70 *entry_type = (*pp_linenos)->type[lineno];
71 return (*pp_linenos)->array[lineno];
72 }
73
74 void
enter_target_lineno(const char * psz_filename,unsigned int lineno,file_t * p_target)75 enter_target_lineno (const char *psz_filename, unsigned int lineno,
76 file_t *p_target)
77 {
78 lineno_array_t lookup_linenos;
79 lineno_array_t **pp_linenos;
80 file_t *p_file;
81
82 lookup_linenos.hname = psz_filename;
83 pp_linenos = (lineno_array_t **)
84 hash_find_slot(&file2lines, &lookup_linenos);
85 p_file = lookup_file(psz_filename);
86
87 if (p_file == NULL) {
88 printf("Could not find file %s\n", psz_filename);
89 return;
90 }
91 if (p_file->nlines == 0) {
92 printf("Warning: %s shows no lines\n", psz_filename);
93 }
94
95 if (HASH_VACANT(*pp_linenos)) {
96 const unsigned int nlines = p_file->nlines+1;
97 void **new_array = calloc (sizeof(void *), nlines);
98 f2l_entry_t *new_type = calloc (sizeof(f2l_entry_t *), nlines);
99 lineno_array_t *p_new_linenos = calloc (sizeof(lineno_array_t), 1);
100 *pp_linenos = p_new_linenos;
101 (*pp_linenos)->hname = psz_filename;
102 (*pp_linenos)->type = new_type;
103 (*pp_linenos)->array = new_array;
104 (*pp_linenos)->size = nlines;
105 }
106 (*pp_linenos)->type[lineno] = F2L_TARGET;
107 (*pp_linenos)->array[lineno] = p_target;
108 }
109
110
111 static void
file2line_init(const void * item)112 file2line_init (const void *item)
113 {
114 file_t *p_target = (file_t *) item;
115 const gmk_floc *p_floc = &p_target->floc;
116 if (p_floc && p_floc->filenm) {
117 enter_target_lineno(p_floc->filenm, p_floc->lineno, p_target);
118 }
119 }
120
121 static void
enter_rule_lineno(rule_t * r)122 enter_rule_lineno (rule_t *r)
123 {
124 lineno_array_t lookup_linenos;
125 lineno_array_t **pp_linenos;
126 const char *psz_filename = r->floc.filenm;
127 const unsigned int lineno = r->floc.lineno;
128 file_t *p_file;
129
130 if (!psz_filename) return;
131 lookup_linenos.hname = psz_filename;
132 pp_linenos = (lineno_array_t **)
133 hash_find_slot(&file2lines, &lookup_linenos);
134 p_file = lookup_file(psz_filename);
135
136 if (p_file == NULL) {
137 printf("Could not find file %s\n", psz_filename);
138 return;
139 }
140 if (p_file->nlines == 0) {
141 printf("Warning: %s shows no lines\n", psz_filename);
142 }
143
144 if (HASH_VACANT(*pp_linenos)) {
145 const unsigned int nlines = p_file->nlines+1;
146 void **new_array = calloc (sizeof(void *), nlines);
147 f2l_entry_t *new_type = calloc (sizeof(f2l_entry_t *), nlines);
148 lineno_array_t *p_new_linenos = calloc (sizeof(lineno_array_t), 1);
149 *pp_linenos = p_new_linenos;
150 (*pp_linenos)->hname = psz_filename;
151 (*pp_linenos)->type = new_type;
152 (*pp_linenos)->array = new_array;
153 (*pp_linenos)->size = nlines;
154 }
155 (*pp_linenos)->type[lineno] = F2L_PATTERN;
156 (*pp_linenos)->array[lineno] = r;
157 }
158
159
160 /*!
161 Initializes hash table file2lines. file2lines is used in breakpoints
162 only. So we do this on demand.
163 */
file2lines_init(void)164 bool file2lines_init(void)
165 {
166 if (!read_makefiles) return false;
167 hash_init (&file2lines, files.ht_size, file2lines_hash_1, file2lines_hash_2,
168 file2lines_hash_cmp);
169 hash_map (&files, file2line_init);
170
171 {
172 rule_t *r;
173 for (r = pattern_rules; r != 0; r = r->next) {
174 enter_rule_lineno(r);
175 }
176 }
177
178 return true;
179 }
180
file2lines_print_entry(const void * item)181 void file2lines_print_entry(const void *item)
182 {
183 const lineno_array_t *p_linenos = (lineno_array_t *) item;
184 unsigned int i;
185 file_t *p_target;
186 printf("%s:\n", p_linenos->hname);
187 for (i=0; i<p_linenos->size; i++)
188 {
189 p_target = p_linenos->array[i];
190 if (p_target) {
191 if (p_linenos->type[i] == F2L_TARGET) {
192 printf("%8lu: %s\n",
193 p_target->floc.lineno, p_target->name);
194 } else {
195 rule_t *p_rule = (rule_t *) p_target;
196 printf("%8lu: %s (pattern)\n",
197 p_rule->floc.lineno, p_rule->targets[0]);
198 }
199 }
200 }
201 }
202
file2lines_dump(void)203 void file2lines_dump(void)
204 {
205 file2lines_init();
206 hash_map (&file2lines, file2lines_print_entry);
207 }
208
209 /*
210 * Local variables:
211 * eval: (c-set-style "gnu")
212 * indent-tabs-mode: nil
213 * End:
214 */
215