1 /* $Id: pgsymtab.c,v 1.39 2001/10/07 22:59:51 moniot Rel $
2
3 Warning message routines for printing of global symbol table info
4
5 */
6
7 /*
8
9 Copyright (c) 2001 by Robert K. Moniot.
10
11 Permission is hereby granted, free of charge, to any person
12 obtaining a copy of this software and associated documentation
13 files (the "Software"), to deal in the Software without
14 restriction, including without limitation the rights to use,
15 copy, modify, merge, publish, distribute, sublicense, and/or
16 sell copies of the Software, and to permit persons to whom the
17 Software is furnished to do so, subject to the following
18 conditions:
19
20 The above copyright notice and this permission notice shall be
21 included in all copies or substantial portions of the
22 Software.
23
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
25 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
26 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
27 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
28 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
30 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
31 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
33 Acknowledgement: the above permission notice is what is known
34 as the "MIT License."
35 */
36
37 /*
38
39 Shared functions defined:
40 argcmp_error_head prints intro to argument mismatch
41 comcmp_error_head prints intro to common mismatch
42 arg_error_report Follow-on message about an argument mismatch
43 sub_error_report Error message line about one subprogram
44 invocation
45 com_error_report Error message line about one common block
46 declaration
47 comvar_error_report Error message line about one common var
48 mismatch
49 sort_gsymbols sort a list of Gsymtab ptrs alphabetically
50
51 */
52
53 #include <stdio.h>
54 #include <ctype.h>
55 #include <string.h>
56 #include "ftnchek.h"
57 #define PGSYMTAB
58 #include "symtab.h"
59 #include "pgsymtab.h"
60
61
62 /* Private functions defined: */
63 PROTO(PRIVATE void arg_error_locate,( ArgListHeader *alh ));
64 PROTO(PRIVATE int cmp_error_head,(const char *name, const char *tag, const char *filename,
65 LINENO_t lineno, const char *msg ));
66 PROTO(PRIVATE void com_error_locate,( ComListHeader *clh ));
67 PROTO(PRIVATE void error_report,( const char *module_name,
68 const char *filename, LINENO_t lineno,
69 const char *topfile, LINENO_t top_lineno,
70 int i, const char *item_tag, const char *item_name, const char *msg ));
71 PROTO(PRIVATE void module_locate, (const char *name));
72 PROTO(PRIVATE void novice_err_locate,( const char *filename, LINENO_t linenum ));
73 PROTO(PRIVATE void novice_inc_locate,( const char *filename, const char *topfile,
74 LINENO_t top_linenum ));
75 PROTO(PRIVATE void report_intro,( const char *filename, LINENO_t lineno,
76 const char *topfile, LINENO_t top_lineno ));
77
78 /* Var used to control spaces betw message blocks */
79 PRIVATE int global_warning_count=0;
80
81
82 /**** Definitions of shared functions ****/
83
84
85
86 /* Intro line of warning about subprogram argument mismatches.
87 */
88 int
89 #if HAVE_STDC
argcmp_error_head(const char * name,ArgListHeader * alh,const char * msg)90 argcmp_error_head(const char *name, ArgListHeader *alh, const char *msg)
91 #else /* K&R style */
92 argcmp_error_head(name, alh, msg)
93 char *name;
94 ArgListHeader *alh;
95 char *msg;
96 #endif /* HAVE_STDC */
97 {
98 return cmp_error_head(name,"Subprogram",
99 alh->filename,
100 alh->line_num,
101 msg);
102 }
103
104 /* Ditto for common block declaration mismatches.
105 */
106 int
107 #if HAVE_STDC
comcmp_error_head(const char * name,ComListHeader * clh,const char * msg)108 comcmp_error_head(const char *name, ComListHeader *clh, const char *msg)
109 #else /* K&R style */
110 comcmp_error_head(name, clh, msg)
111 char *name;
112 ComListHeader *clh;
113 char *msg;
114 #endif /* HAVE_STDC */
115 {
116 return cmp_error_head(name,"Common block",
117 clh->filename,
118 clh->line_num,
119 msg);
120 }
121
122 /* Follow-on message about an argument mismatch */
123 void
124 #if HAVE_STDC
arg_error_report(ArgListHeader * alh,const char * argtype,int i,const char * msg)125 arg_error_report(ArgListHeader *alh, const char *argtype, int i, const char *msg)
126 #else /* K&R style */
127 arg_error_report(alh, argtype, i, msg)
128 ArgListHeader *alh;
129 char *argtype;
130 int i;
131 char *msg;
132 #endif /* HAVE_STDC */
133 {
134 error_report(alh->module->name,
135 alh->filename,alh->line_num,alh->topfile,alh->top_line_num,
136 i,argtype,alh->arg_array[i].name,msg);
137 }
138
139 /* Formats an error message line about one subprogram
140 invocation.
141 */
142 void
143 #if HAVE_STDC
sub_error_report(ArgListHeader * alh,const char * msg)144 sub_error_report(ArgListHeader *alh, const char *msg)
145 #else /* K&R style */
146 sub_error_report(alh, msg)
147 ArgListHeader *alh;
148 const char *msg;
149 #endif /* HAVE_STDC */
150 {
151 report_intro(alh->filename,alh->line_num,alh->topfile,alh->top_line_num);
152 msg_tail(msg);
153 arg_error_locate(alh);
154 }
155
156
157
158 /* Formats an error message line about one common block
159 declaration.
160 */
161 void
162 #if HAVE_STDC
com_error_report(ComListHeader * clh,const char * msg)163 com_error_report(ComListHeader *clh, const char *msg)
164 #else /* K&R style */
165 com_error_report(clh, msg)
166 ComListHeader *clh;
167 char *msg;
168 #endif /* HAVE_STDC */
169 {
170 report_intro(clh->filename,clh->line_num,clh->topfile,clh->top_line_num);
171 msg_tail(msg);
172 com_error_locate(clh);
173 }
174
175 /* Formats an error message line about one common var mismatch.
176 */
177 void
178 #if HAVE_STDC
comvar_error_report(ComListHeader * clh,int i,const char * msg)179 comvar_error_report(ComListHeader *clh, int i, const char *msg)
180 #else /* K&R style */
181 comvar_error_report(clh, i, msg)
182 ComListHeader *clh;
183 int i;
184 char *msg;
185 #endif /* HAVE_STDC */
186 {
187 error_report(clh->module->name,
188 clh->filename,clh->line_num,clh->topfile,clh->top_line_num,
189 i,"Variable",clh->com_list_array[i].name,msg);
190 }
191
192
193 /**** Definitions of private functions ****/
194
195 PRIVATE int at_position_printed;
196
197
198 /* Increment error count, and if it is 1, print header for arg or com
199 mismatch error messages. If it is past limit, print "etc"
200 and return TRUE, otherwise return FALSE.
201 */
202 PRIVATE int
203 #if HAVE_STDC
cmp_error_head(const char * name,const char * tag,const char * filename,LINENO_t lineno,const char * msg)204 cmp_error_head(const char *name, const char *tag,
205 const char *filename, LINENO_t lineno, const char *msg)
206 #else /* K&R style */
207 cmp_error_head(name, tag,
208 filename, lineno, msg)
209 char *name;
210 char *tag;
211 char *filename;
212 LINENO_t lineno;
213 char *msg;
214 #endif /* HAVE_STDC */
215 {
216 /* stop after limit: probably a cascade */
217 if( CASCADE_LIMIT(cmp_error_count) ) {
218 (void)fprintf(list_fd,"\n etc...");
219 return TRUE;
220 }
221
222 /* (For expert mode, line number helps smart editors,
223 but in novice mode it looks silly to have a line
224 number for a mismatch involving two lines.)
225 */
226 if(novice_help) {
227 filename = (char *)NULL;
228 lineno = NO_LINE_NUM;
229 }
230
231 if(cmp_error_count == 1) {
232 /* If -noquiet mode, put a space between
233 successive warnings.
234 */
235 if( (global_warning_count != 0) && !quiet)
236 (void)fprintf(list_fd,"\n");
237 global_warning_count++;
238 global_warning(filename,lineno,tag);
239 msg_tail(name);
240 msg_tail(msg);
241 }
242 else { /* for "and at position n" on new line */
243 global_message(filename,lineno," and");
244 }
245 at_position_printed = FALSE;
246
247 return FALSE;
248 }
249
250
251
252 PRIVATE void
253 #if HAVE_STDC
error_report(const char * module_name,const char * filename,LINENO_t lineno,const char * topfile,LINENO_t top_lineno,int i,const char * item_tag,const char * item_name,const char * msg)254 error_report(const char *module_name, const char *filename, LINENO_t lineno,
255 const char *topfile, LINENO_t top_lineno,
256 int i, const char *item_tag, const char *item_name, const char *msg)
257 #else /* K&R style */
258 error_report(module_name, filename, lineno,
259 topfile, top_lineno,
260 i, item_tag, item_name, msg)
261 char *module_name;
262 char *filename;
263 LINENO_t lineno;
264 char *topfile;
265 LINENO_t top_lineno;
266 int i;
267 char *item_tag;
268 char *item_name;
269 char *msg;
270 #endif /* HAVE_STDC */
271 {
272 if( ! at_position_printed ) {
273 char posn[12+3*sizeof(int)+2];
274 (void)sprintf(posn,"at position %d:",i+1);
275 msg_tail(posn);
276 at_position_printed = TRUE;
277 }
278
279 report_intro(filename,lineno,topfile,top_lineno);
280 msg_tail(item_tag);
281
282 msg_tail(item_name);
283 /* Print module name, and for -novice mode, location info
284 that was suppressed before.
285 */
286 module_locate(module_name);
287
288 if( novice_help ) {
289 /* Error location itself */
290 novice_err_locate(filename,lineno);
291 /* Location where included */
292 novice_inc_locate(filename,topfile,top_lineno);
293 }
294
295 msg_tail(msg);
296
297 }
298
299
300 PRIVATE void
301 #if HAVE_STDC
report_intro(const char * filename,LINENO_t lineno,const char * topfile,LINENO_t top_lineno)302 report_intro(const char *filename, LINENO_t lineno,
303 const char *topfile, LINENO_t top_lineno)
304 #else /* K&R style */
305 report_intro(filename, lineno,
306 topfile, top_lineno)
307 char *filename;
308 LINENO_t lineno;
309 char *topfile;
310 LINENO_t top_lineno;
311 #endif /* HAVE_STDC */
312 {
313 /* In expert mode, if error is in include file,
314 need to give info about it.
315 */
316 if( ! novice_help && filename != topfile) {
317 global_message(filename,lineno,"(location of error)");
318 global_message(topfile,top_lineno,"(where included) ");
319 }
320 else {
321 global_message(filename,lineno," ");
322 }
323 }
324
325 /* Gives module and in novice mode line, filename for error messages
326 */
327 PRIVATE void
328 #if HAVE_STDC
arg_error_locate(ArgListHeader * alh)329 arg_error_locate(ArgListHeader *alh)
330 #else /* K&R style */
331 arg_error_locate(alh)
332 ArgListHeader *alh;
333 #endif /* HAVE_STDC */
334 {
335 /* Module (subprogram) containing the error.
336 This gets printed in both modes. */
337 module_locate(alh->module->name);
338
339 if( novice_help ) {
340 /* Error location itself */
341 novice_err_locate(alh->filename,alh->line_num);
342 /* Location where included */
343 novice_inc_locate(alh->filename,alh->topfile,alh->top_line_num);
344 }
345 }
346
347 PRIVATE void
348 #if HAVE_STDC
com_error_locate(ComListHeader * clh)349 com_error_locate(ComListHeader *clh)
350 #else /* K&R style */
351 com_error_locate(clh)
352 ComListHeader *clh;
353 #endif /* HAVE_STDC */
354 {
355 /* Module (subprogram) containing the error.
356 This gets printed in both modes. */
357 module_locate(clh->module->name);
358
359 if( novice_help ) {
360 /* Error location itself */
361 novice_err_locate(clh->filename,clh->line_num);
362 /* Location where included */
363 novice_inc_locate(clh->filename,clh->topfile,clh->top_line_num);
364 }
365 }
366
367 PRIVATE void
368 #if HAVE_STDC
module_locate(const char * name)369 module_locate(const char *name)
370 #else /* K&R style */
371 module_locate(name)
372 const char *name;
373 #endif /* HAVE_STDC */
374 {
375 msg_tail("in module");
376 msg_tail(name);
377 }
378
379 /* Non-include part of location, novice mode */
380 PRIVATE void
381 #if HAVE_STDC
novice_err_locate(const char * filename,LINENO_t linenum)382 novice_err_locate(const char *filename, LINENO_t linenum)
383 #else /* K&R style */
384 novice_err_locate(filename,linenum)
385 char *filename;
386 LINENO_t linenum;
387 #endif /* HAVE_STDC */
388 {
389 msg_tail("line");
390 msg_tail(ulongtostr((unsigned long)linenum));
391 msg_tail("file");
392 msg_tail(filename);
393 }
394
395 /* Include-file part of location, novice mode */
396 PRIVATE void
397 #if HAVE_STDC
novice_inc_locate(const char * filename,const char * topfile,LINENO_t top_linenum)398 novice_inc_locate(const char *filename, const char *topfile, LINENO_t top_linenum)
399 #else /* K&R style */
400 novice_inc_locate(filename,topfile,top_linenum)
401 char *filename;
402 char *topfile;
403 LINENO_t top_linenum;
404 #endif /* HAVE_STDC */
405 {
406 if(filename != topfile) { /* Track include filename */
407 msg_tail("(included at line");
408 msg_tail(ulongtostr((unsigned long)top_linenum));
409 msg_tail("in");
410 msg_tail(topfile);
411 msg_tail(")");
412 }
413 }
414
415
416 void
417 #if HAVE_STDC
sort_gsymbols(Gsymtab ** glist,int n)418 sort_gsymbols (Gsymtab **glist, int n) /* same as sort_lsymbols */
419 #else /* K&R style */
420 sort_gsymbols ( glist,n )
421 Gsymtab *glist[];
422 int n;
423 #endif /* HAVE_STDC */
424 {
425 int i,j,swaps;
426
427 for (i=0; i<n; i++ ){
428 swaps = 0;
429 for (j=n-1; j>=i+1; j--){
430 if ((strcmp (glist[j-1]->name, glist[j]->name)) >0) {
431 Gsymtab *temp = glist[j-1]; /* swap ptrs j and j-1 */
432 glist[j-1] = glist[j];
433 glist[j] = temp;
434 swaps++;
435 }
436 }
437 if (swaps == 0) break;
438 }
439
440
441 }
442