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