1 /*   $Id: labels.c,v 1.22 2004/12/29 19:40:21 moniot Exp $
2  *   Handles defs and refs of statement labels
3  *
4  *   Written by Heba Elsayed
5  *   Modified to use an open hash backend by Robert Landrito
6  */
7 
8 /*
9 
10 
11 Copyright (c) 2001 by Robert K. Moniot.
12 
13 Permission is hereby granted, free of charge, to any person
14 obtaining a copy of this software and associated documentation
15 files (the "Software"), to deal in the Software without
16 restriction, including without limitation the rights to use,
17 copy, modify, merge, publish, distribute, sublicense, and/or
18 sell copies of the Software, and to permit persons to whom the
19 Software is furnished to do so, subject to the following
20 conditions:
21 
22 The above copyright notice and this permission notice shall be
23 included in all copies or substantial portions of the
24 Software.
25 
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
27 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
28 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
29 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
30 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
32 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
33 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 
35 Acknowledgement: the above permission notice is what is known
36 as the "MIT License."
37 */
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 #include "ftnchek.h"
44 #include "symtab.h"
45 #include "plsymtab.h"
46 
47 #define TOP_FILE -1               /* not an include file */
48 #define HASHSIZE 50               /* hash table size */
49 
50 
51 /* Linked-list: describe how references are used */
52 
53 typedef struct lab_ref_list
54 {
55     short file_ref;               /* file referenced: = TOP_FILE
56       				     if not an include file, else =
57 				     inctable_index */
58 
59     LINENO_t line_ref;            /* line referenced */
60 
61     int ref_type;                 /* reference type: arg, assign, do,
62 				     goto, or I/O (format) */
63 
64     struct lab_ref_list *next;    /* link to next element */
65 } Lab_ref_list;
66 
67 
68 
69 /* A label */
70 
71 typedef struct label_node {
72     LABEL_t lab;                  /* label numeric value */
73     short file_def;               /* file where defined; = TOP_FILE if
74 				     not an include file, else =
75 				     inctable_index */
76 
77 
78     LINENO_t line_def;            /* line number where defined */
79     int stmt_type;                /* statement type: specification
80 		        	     format, or executable  */
81 
82     unsigned defined:1;           /* TRUE if label is defined */
83     unsigned referenced:1;        /* TRUE if label is referenced */
84     unsigned do_label:1;	  /* TRUE if label used in DO statement */
85     Lab_ref_list *how_used;       /* list describing each ref to label */
86     struct label_node *next;      /* pointer to next label in linked list */
87 } Lab;
88 
89 
90 /* >>>>> function prototypes <<<<< */
91 
92 PRIVATE unsigned int hash_label(LABEL_t label);
93 
94 PRIVATE int insert_lab(LABEL_t label);
95 
96 PRIVATE void ref_error_check(char *mod_name, int type1, int type2, int type3,
97 			     Lab *label);
98 
99 PRIVATE void print_msg(LABEL_t label, short file,
100 		       LINENO_t line, const char string[]);
101 
102 
103 PRIVATE void bubble_sort(int n);
104 
105 PRIVATE void swap(Lab *x, Lab *y);
106 
107 PRIVATE int compare_labs(const void *a, const void *b);
108 
109 PRIVATE Lab_ref_list *reverse_ref_list(Lab_ref_list *t);
110 
111 PRIVATE int find_label(LABEL_t label);
112 
113 PRIVATE void clear_footnotes(void);
114 
115 PRIVATE void print_key(int num_footnotes);
116 
117 
118 /* >>>>> global variables <<<<< */
119 
120 PRIVATE int num_labels;
121    /* current number of entries in labtable */
122 
123 PRIVATE Lab *labtable;
124    /* table of labels defined or used: mallocked at run-time */
125 
126 PRIVATE int labtable_size=0;
127   /* current size of labtable */
128 
129 PRIVATE int ref_index;
130    /* index of ref_lists */
131 
132 PRIVATE int ref_lists_size = REF_LISTS_SIZE;
133    /* current max size of ref_lists */
134 
135 PRIVATE Lab_ref_list *ref_lists = NULL;
136    /* table of label ref_lists */
137 
138 PRIVATE unsigned any_lab_defined;
139    /* used to check if any label has been defined */
140 
141 PRIVATE unsigned any_lab_referenced;
142    /* used to check if any label has been referenced */
143 
144 PRIVATE Lab *hash_table[HASHSIZE];
145    /* array of pointers to label linked list for use in hashing scheme */
146 
147 PRIVATE unsigned int last_hash_index;
148    /* last hash index searched */
149 
150 /*
151  * hash: get a hash index
152  */
hash_label(LABEL_t label)153 PRIVATE unsigned int hash_label(LABEL_t label) {
154     /* numbers used in the following random number generator obtained from
155        Numerical Recipes in C: The Art of Scientific Computing */
156     return ( (1861 * label + 49297) % 233280 );
157 }
158 
159 
160 /*
161  * init_labtable: initialize space for labels in labtable
162  */
init_labtable(void)163 void init_labtable(void) {
164     int i;
165     num_labels = ref_index = last_hash_index = 0;
166     any_lab_defined = any_lab_referenced = FALSE;
167 
168     if ( labtable_size == 0 ) {
169         labtable_size = LABTABLE_SIZE;
170 
171         if ( NULL == (labtable = (Lab *) malloc(sizeof(Lab) * labtable_size)) )
172             oops_message(OOPS_FATAL, NO_LINE_NUM, NO_COL_NUM,
173                     "Cannot alloc space for label table");
174     } /* end (outer) if */
175 
176     /* nullify hash table */
177     for (i = 0; i < HASHSIZE; i++)
178         hash_table[i] = NULL;
179 
180     return;
181 }
182 
183 /*
184  * grow_labtable: double the size of the hashtable
185  */
grow_labtable(void)186 PRIVATE void grow_labtable(void) {
187     Lab *old_labtable = labtable;
188     int i;
189 
190     labtable_size *= 2;
191     if ( NULL == ( labtable =
192                 (Lab *) realloc(labtable, sizeof(Lab) * labtable_size) ) )
193         oops_message(OOPS_FATAL, NO_LINE_NUM, NO_COL_NUM,
194                 "Cannot realloc space for label tabel");
195 
196 #ifdef DEBUG_LABELS
197     fprintf(stderr, "DEBUG: resizing labtable to %d...", labtable_size);
198 #endif
199 
200     /* fix the pointers in hash_table */
201     for (i = 0; i < HASHSIZE; i++)
202         if (hash_table[i] != NULL)
203             hash_table[i] = labtable + (hash_table[i] - old_labtable);
204 
205     /* fix pointers in linked lists */
206     for (i = 0; i < num_labels; i++)
207         if (labtable[i].next != NULL)
208             labtable[i].next = labtable + (labtable[i].next - old_labtable);
209 
210 #ifdef DEBUG_LABELS
211     fprintf(stderr, "DONE\n");
212 #endif
213 
214     return;
215 }
216 
217 /*
218  * insert_lab: inserts new label into labtable
219  */
insert_lab(LABEL_t label)220 PRIVATE int insert_lab(LABEL_t label) {
221 
222     /* check if we have any space */
223     if ( num_labels >= labtable_size )
224         grow_labtable();
225 
226     /* place label in linked list pointed to in hash_table */
227     labtable[num_labels].next = hash_table[last_hash_index];
228     hash_table[last_hash_index] = &labtable[num_labels];
229 
230     /* set up the label */
231     labtable[num_labels].how_used = NULL;
232 
233     labtable[num_labels].defined = FALSE;
234     labtable[num_labels].referenced = FALSE;
235     labtable[num_labels].do_label = FALSE;
236 
237     labtable[num_labels].file_def = TOP_FILE;
238     labtable[num_labels].line_def = NO_LINE_NUM;
239     labtable[num_labels].stmt_type = LAB_NO_TYPE;
240 
241     labtable[num_labels].lab = label;
242 
243     ++num_labels;
244 
245     return (num_labels - 1);
246 }
247 
248 /*
249  * sort_labtable
250  * WARNING: THIS RENDERS THE HASH TABLE USELESS
251  *          DO *NOT REFERENCE THE HASH TABLE AFTER
252  *          CALLING THIS FUNCTION, UNLESS init_labtable()
253  *          IS FIRST CALLED.
254  */
sort_labtable(void)255 void sort_labtable(void)
256 {
257     int j, k;
258     int count = 0;  /* number of unsorted pairs */
259 
260 
261     for (j = 0; j < num_labels; j++)
262     {
263 	    /* Put ref lines into ascending order */
264 
265 	    labtable[j].how_used =
266 		reverse_ref_list(labtable[j].how_used);
267 
268     }
269                      /* assert: i == num_labels */
270 
271 
272     for (k = 1; k < num_labels; k++)
273     {
274 	/* Count out-of-order table entries */
275 
276 	if (labtable[k-1].lab > labtable[k].lab)
277 	{
278 	    count++;
279 	}
280     }
281 
282     /* choose more efficient sorting alg., if nec. */
283 
284     if (count == 0) {}
285 	/* labtable is sorted */
286 
287     else if (count > 25)
288     {
289 	qsort(labtable, num_labels, sizeof(Lab), compare_labs);
290     }
291     else
292     {
293 	bubble_sort(num_labels);
294     }
295 }
296 
297 
298 /*
299  * bubble_sort: sort in ascending order
300  */
301 
bubble_sort(int n)302 PRIVATE void bubble_sort(int n)
303 {
304     int i, j, numswaps;
305 
306     numswaps = 1;
307 
308     for (i = 0; (i < n) && (numswaps != 0); i++)
309     {
310 	numswaps = 0;
311 
312 	for (j = n - 2; j >= i; j--)
313 	{
314 	    if (labtable[j].lab > labtable[j+1].lab)
315 	    {
316 		swap(&labtable[j], &labtable[j+1]);
317 		numswaps++;
318 	    }
319 	}
320     }
321 }
322 
323 
324 /*
325  * swap
326  */
327 
swap(Lab * x,Lab * y)328 PRIVATE void swap(Lab *x, Lab *y)
329 {
330     Lab temp = *x;
331     *x = *y;
332     *y = temp;
333 }
334 
335 
336 /*
337  * compare_labs: for qsort routine
338  */
339 
compare_labs(const void * v1,const void * v2)340 PRIVATE int compare_labs(const void *v1, const void *v2)
341 {
342     Lab *a, *b;
343 
344     a = (Lab *)v1;
345     b = (Lab *)v2;
346 
347     return (a->lab - b->lab);
348 }
349 
350 
351 /*
352  * print_label_refs: print label cross-references
353  */
354 
print_label_refs(void)355 void print_label_refs(void)
356 {
357     int k;                     /* LCV */
358     int num_refs;              /* number of refs in how_used */
359     int n;                     /* number of refs printed so far */
360     int per_line = 4;          /* number of refs to print per line */
361     int footnote_num = 0;      /* number of footnotes--for include files */
362     char buf[13];              /* holds label enclosed in <> */
363 
364     unsigned per_line_decreased = FALSE; /* for output formatting */
365 
366     if (!any_lab_referenced)   /* nothing to print! */
367     {
368 	return;
369     }
370 
371     clear_footnotes();
372 
373     (void)fprintf(list_fd, "\n\nLabel cross-references:");
374 
375     for (k = 0; k < num_labels; k++)
376     {
377 	if (labtable[k].how_used != NULL)
378 	{
379 	    Lab_ref_list *how_used;
380 	    (void)sprintf(buf, "<%d>:", labtable[k].lab);
381 	    (void)fprintf(list_fd, "\n\n%8s", buf);
382 
383 	    /* count refs */
384 
385 	    num_refs = 0;
386 	    for (how_used = labtable[k].how_used; how_used != NULL;
387 		 how_used = how_used->next, num_refs++) {}
388 
389 	    /* print ref list */
390 
391 	    n = 0;
392 	    for (how_used = labtable[k].how_used; how_used != NULL;
393 		 how_used = how_used->next, n++)
394 	    {
395 		if ((n > 0) && (n < num_refs))
396 		{
397 		    (void)fprintf(list_fd, ",");
398 		}
399 
400 		/* indent after first line is printed */
401 
402 		if ((n > 0) && (n % per_line) == 0)
403 		{
404 		    (void)fprintf(list_fd, "\n%8s", "");
405 
406 		    if (per_line_decreased)
407 		    {
408 			per_line++;
409 			per_line_decreased = FALSE;
410 		    }
411 		}
412 
413 		(void)fprintf(list_fd, " (line %d", how_used->line_ref);
414 
415 
416 		/* include file: print footnote */
417 
418 		if (how_used->file_ref != TOP_FILE)
419 		{
420 		    /* is this a new include file? */
421 
422 		    if (incfile_list[how_used->file_ref].footnote == 0)
423 		    {
424 			footnote_num++;
425 			incfile_list[how_used->file_ref].footnote
426 			    = footnote_num;
427 		    }
428 
429 	      	    (void)fprintf(list_fd, "[%d]", footnote_num);
430 
431    		    if (!per_line_decreased)
432 		    {
433 			per_line--;
434 			per_line_decreased = TRUE;
435 		    }
436 		}
437 
438 		(void)fprintf(list_fd, ": %s)",
439 			      lab_type_name[how_used->ref_type]);
440 	    }
441 
442 	}
443     }
444 
445     (void)fprintf(list_fd, "\n");
446 
447     if (footnote_num > 0 )
448     {
449 	print_key(footnote_num);
450     }
451 }
452 
453 
454 
455 /*
456  * reverse_ref_list: reverse order of items
457  *                   in a Lab_ref_list
458  */
459 
reverse_ref_list(Lab_ref_list * t)460 PRIVATE Lab_ref_list *reverse_ref_list(Lab_ref_list *t)
461 {
462     Lab_ref_list *curr, *next, *temp;
463 
464     if (t == NULL)
465     {
466 	return t;
467     }
468     curr = t;
469     next = curr->next;
470 
471     while (next != NULL)
472     {
473 	temp = next->next;
474 	next->next = curr;
475 	curr = next;
476 	next = temp;
477     }
478     t->next = NULL;	  /* former head is now tail */
479     return curr;	  /* curr now points to new head */
480 }
481 
482 
483 /*
484  * print_labels
485  */
486 
print_labels(void)487 void print_labels(void)
488 {
489     int i, k;
490     int per_line = 3;       /* number of labels to print per line */
491     char buf[13];           /* holds label enclosed in <> */
492     int footnote_num = 0;   /* number of footnotes--for include files */
493 
494     if (!any_lab_defined)   /* no labels to print */
495     {
496 	return;
497     }
498 
499     clear_footnotes();
500 
501     (void)fprintf(list_fd, "\n\nStatement labels defined:\n\n");
502 
503     for (i = 0; (i < per_line) && (i < num_labels); i++)
504     {
505 	(void)fprintf(list_fd, "%4sLabel   Line  StmtType", "");
506     }
507 
508     for (k = 0; k < num_labels; k++)
509     {
510 	if ((k % per_line) == 0)
511 	{
512 	    (void)fprintf(list_fd, "\n");
513 	}
514 
515 	if (labtable[k].line_def != NO_LINE_NUM)
516 	{
517 	    (void)sprintf(buf, "<%d>", labtable[k].lab);
518 	    (void)fprintf(list_fd, "%9s", buf);
519 
520 
521 	     /* include file: print footnote */
522 
523 	    if (labtable[k].file_def != TOP_FILE)
524 
525 	    {
526 		/* is this a new include file? */
527 
528 		if (incfile_list[labtable[k].file_def].footnote == 0)
529 		{
530 		    footnote_num++;
531 		    incfile_list[labtable[k].file_def].footnote = footnote_num;
532 		}
533 		(void)fprintf(list_fd, "%4d[%d]",
534 			      labtable[k].line_def, footnote_num);
535 	    }
536 
537 	    else
538 	    {
539 		(void)fprintf(list_fd, "%7d", labtable[k].line_def);
540 	    }
541 
542 	    (void)fprintf(list_fd,"%10s",
543 			  lab_type_name[labtable[k].stmt_type]);
544 
545 	}
546     }
547 
548     (void)fprintf(list_fd, "\n");
549 
550     if (footnote_num > 0)
551     {
552 	print_key(footnote_num);
553     }
554 }
555 
556 /*
557  * find_label
558  */
559 
find_label(LABEL_t label)560 PRIVATE int find_label(LABEL_t label)
561 {
562     Lab *label_ptr;
563 
564     /* index value of linked list where "label" is a part of */
565     last_hash_index = (hash_label(label) >> 9) % HASHSIZE;
566     label_ptr = hash_table[last_hash_index];
567 
568     while ( label_ptr != NULL && label_ptr->lab != label )
569         label_ptr = label_ptr->next;
570 
571     if ( label_ptr == NULL )    /* not found! */
572         return NO_LABEL;
573 
574     /* return the index of *labtable* */
575     return (label_ptr - labtable);
576 }
577 
578 /*
579  * def_label.  Called where label is attached to a statement.  Returns
580  *    TRUE if the label marks end of a DO range.
581  */
582 
def_label(Token * t,int type)583 int def_label(Token *t, int type)
584 {
585     LABEL_t label = (LABEL_t)(t->value.integer);
586     LINENO_t line_number = (LINENO_t)t->line_num;
587 
588     int i = find_label(label);        /* label's index */
589 
590     if (i == NO_LABEL)  /* label never defined/used */
591     {
592 	i = insert_lab(label);
593     }
594 
595     any_lab_defined = TRUE;
596 
597     /* set appropriate fields */
598 
599     labtable[i].file_def = inctable_index;
600     labtable[i].line_def = line_number;
601 
602     if (!labtable[i].defined)
603     {
604 	labtable[i].defined = TRUE;
605     }
606     else   /* error--duplicate label */
607     {
608 	syntax_error(line_number, t->col_num, "Label previously defined");
609     }
610 
611     labtable[i].stmt_type = type;
612     return labtable[i].do_label;
613 }
614 
615 /*
616  * def_do_label
617  */
618 
def_do_label(Token * t)619 void def_do_label(Token *t)
620 {
621     LABEL_t label = (LABEL_t)(t->value.integer);
622 
623     int i = find_label(label);        /* label's index */
624 
625 
626     if (i == NO_LABEL)  /* label has to be defined by now */
627     {
628 	oops_message(OOPS_FATAL,t->line_num,t->col_num,
629 		     "def_do_label called for undefined label");
630     }
631 
632     labtable[i].do_label = TRUE;
633 }
634 
635 /*
636  * ref_label
637  */
638 
ref_label(Token * t,int type)639 void ref_label(Token *t, int type)
640 {
641     LABEL_t label = (LABEL_t)(t->value.integer);
642     LINENO_t line_number = (LINENO_t)t->line_num;
643 
644     int i = find_label(label);        /* label's index */
645 
646 
647     if (i == NO_LABEL)  /* label never defined/used */
648     {
649 	i = insert_lab(label);
650     }
651 
652     any_lab_referenced = TRUE;
653 
654 
655     /* add entry to how_used */
656 
657     if (ref_lists == NULL)   /* allocate array space for our ref_lists */
658     {
659 	ref_lists = (Lab_ref_list *) malloc(ref_lists_size *
660 					    sizeof(Lab_ref_list));
661 	if (ref_lists == NULL)
662 	{
663 		oops_message(OOPS_FATAL, NO_LINE_NUM, NO_COL_NUM,
664 			     "unable to allocate memory for ref_lists");
665 	}
666     }
667 
668     if (ref_index == ref_lists_size) /* out of ref_list space:
669 					double size of memory chunk */
670     {
671 	Lab_ref_list *oldbase=ref_lists; /* for fixing pointers later */
672 	ref_lists_size *= 2;
673 	ref_lists = (Lab_ref_list *) realloc(ref_lists,
674 					 ref_lists_size*sizeof(Lab_ref_list));
675 	if (ref_lists == NULL)
676 	{
677 	    oops_message(OOPS_FATAL, NO_LINE_NUM, NO_COL_NUM,
678 			 "unable to reallocate memory for ref_lists");
679 	}
680 			/* If realloc moved the array, fix all the pointers
681 			   that refer to it.
682 			*/
683 	if(oldbase != ref_lists) {
684 	  int j;
685 	  for(j=0; j<ref_index; j++) {
686 	    if( ref_lists[j].next != NULL ) {
687 	      ref_lists[j].next = (ref_lists[j].next-oldbase)+ref_lists;
688 	    }
689 	  }
690 	  for(j=0; j<labtable_size; j++ ) {
691 	    if( labtable[j].lab != NO_LABEL && labtable[j].how_used != NULL ) {
692 	      labtable[j].how_used = (labtable[j].how_used-oldbase)+ref_lists;
693 	    }
694 	  }
695 	}
696     }
697 
698     ref_lists[ref_index].file_ref = inctable_index;
699     ref_lists[ref_index].line_ref = line_number;
700     ref_lists[ref_index].ref_type = type;
701 
702     ref_lists[ref_index].next = labtable[i].how_used;
703     labtable[i].how_used = ref_lists + ref_index;
704 
705     labtable[i].referenced = TRUE;
706 
707     ref_index++;
708 }
709 
710 
711 /*
712  * check_labels: report problems with label usage
713  */
714 
check_labels(char * mod_name)715 void check_labels(char *mod_name)
716 {
717     int i;
718     unsigned head_printed;   /* has error header been printed? */
719 
720 		/* does a goto refer to	a non-executable stmt? */
721     if (misc_warn)
722     {
723 	for (i = 0; i < num_labels; i++)
724 	{
725 	    if ( (labtable[i].stmt_type == LAB_FORMAT) ||
726 		 (labtable[i].stmt_type == LAB_SPECIFICATION) )
727 	    {
728 
729 		ref_error_check(mod_name, LAB_GOTO, LAB_DO, LAB_CALL,
730 				&labtable[i]);
731 	    }
732 	}
733     }
734 
735 		/* does a format-id refer to a non format? */
736     if (misc_warn)
737     {
738 	for (i = 0; i < num_labels; i++)
739 	{
740 	    if( (labtable[i].stmt_type == LAB_SPECIFICATION) ||
741 		(labtable[i].stmt_type == LAB_EXECUTABLE) )
742 	    {
743 
744 		ref_error_check(mod_name, LAB_IO, LAB_NO_TYPE,
745 				LAB_NO_TYPE, &labtable[i]);
746 	    }
747 	}
748     }
749 
750 		/* does an assign refer to a specification stmt? */
751     if (misc_warn)
752     {
753 	for (i = 0; i < num_labels; i++)
754 	{
755 	    if (labtable[i].stmt_type == LAB_SPECIFICATION)
756 	    {
757 
758 		ref_error_check(mod_name, LAB_ASSIGN, LAB_NO_TYPE,
759 				LAB_NO_TYPE, &labtable[i]);
760 	    }
761 	}
762     }
763 
764 
765     if (usage_label_undefined)
766     {
767 	head_printed = FALSE;
768 	for (i = 0; i < num_labels; i++)
769 	{
770 	    if (!labtable[i].defined)     /* undefined label is referenced */
771 	    {
772 		Lab_ref_list *how_used;
773 
774 		if (!head_printed)
775 		{
776 		    local_err_head(mod_name,
777 				   choose_filename(labtable[i].how_used,
778 						   file_ref),
779 				   labtable[i].how_used->line_ref,
780 				   (Lsymtab *)NULL, FALSE,
781 				   "Labels referenced but not defined:");
782 
783 		    head_printed = TRUE;
784 		}
785 
786 		/* print error msg for EACH reference to undefined
787 		   label */
788 
789 		for (how_used = labtable[i].how_used;
790 		     how_used != NULL; how_used = how_used->next)
791 		{
792 		    print_msg(labtable[i].lab, how_used->file_ref,
793 			      how_used->line_ref, "referenced");
794 		}
795 	    }
796 	}
797     }
798 
799     if (usage_label_unused)
800     {
801 	head_printed = FALSE;
802 
803 	for (i = 0; i < num_labels; i++)
804 	{
805 	    if (!labtable[i].referenced)  /* defined label is unused */
806 	    {
807 		if (!head_printed)
808 		{
809 		    local_warn_head(mod_name,
810 				    choose_filename(&labtable[i], file_def),
811 				    labtable[i].line_def,
812 				    (Lsymtab *)NULL, FALSE,
813 				    "Labels defined but not used:");
814 
815 		    head_printed = TRUE;
816 		}
817 		print_msg(labtable[i].lab, labtable[i].file_def,
818 			  labtable[i].line_def, "defined");
819 	    }
820 	}
821     }
822 }
823 
824 
825 /*
826  * ref_error_check: ref_error_check is called to check whether
827  *   a non-executable stmt is referred to by a goto
828  *
829  *   whether a non-format stmt is referred to by a format-id,
830  *  OR
831  *   whether an assign refers to a specification statement
832  *
833  *   type1, type2, and type3 are reference types.
834  *
835  *   if we are checking for goto errors, then type1 is LAB_GOTO, type2
836  *     is LAB_DO, and type3 is LAB_CALL
837  *   otherwise, type1 is either LAB_IO or LAB_ASSIGN, and type2 & type3
838  *     are LAB_NO_TYPE
839  */
840 
ref_error_check(char * mod_name,int type1,int type2,int type3,Lab * label)841 PRIVATE void ref_error_check(char *mod_name, int type1, int type2, int type3,
842 			     Lab *label)
843 {
844     Lab_ref_list *how_used;
845     unsigned head_printed = FALSE;   /* has error header been printed? */
846 
847     for (how_used = label->how_used; how_used != NULL;
848 	 how_used = how_used->next)
849     {
850 	if ((how_used->ref_type == type1) ||
851 	    (how_used->ref_type == type2) ||
852 	    (how_used->ref_type == type3))
853 	{
854 	    if (type1 == LAB_GOTO)
855 	    {
856 		if (!head_printed)
857 		{
858 		    local_err_head(mod_name,
859 				   choose_filename(how_used, file_ref),
860 				   how_used->line_ref,
861 				   (Lsymtab *)NULL, FALSE,
862 				   "Goto refers to a non-executable stmt");
863 
864 		    head_printed = TRUE;
865 		}
866 		print_msg(label->lab, how_used->file_ref,
867 			  how_used->line_ref, "referenced");
868 	    }
869 	    else if (type1 == LAB_IO)
870 	    {
871 		if (!head_printed)
872 		{
873 		    local_err_head(mod_name,
874 				   choose_filename(how_used, file_ref),
875 				   how_used->line_ref,
876 				   (Lsymtab *)NULL, FALSE,
877 				   "Format-id refers to a non-format");
878 
879 		    head_printed = TRUE;
880 		}
881 		print_msg(label->lab, how_used->file_ref,
882 			  how_used->line_ref, "referenced");
883 
884 	    }
885 
886 	    else if (type1 == LAB_ASSIGN)
887 	    {
888 		if (!head_printed)
889 		{
890 		    local_err_head(mod_name,
891 				   choose_filename(how_used, file_ref),
892 				   how_used->line_ref,
893 				   (Lsymtab *)NULL, FALSE,
894 				   "Assign refers to a specification stmt");
895 		    head_printed = TRUE;
896 		}
897 		print_msg(label->lab, how_used->file_ref,
898 			  how_used->line_ref, "referenced");
899 	    }
900 	}
901     }
902 }
903 
904 
905 /*
906  * print_msg: prints error message detail;
907  *            string is either "defined" or "referenced"
908  */
909 
print_msg(LABEL_t label,short file,LINENO_t line,const char string[])910 PRIVATE void print_msg(LABEL_t label, short file, LINENO_t line, const char string[])
911 {
912     char detail[25];
913     (void)sprintf(detail, "    <%d> %s", label, string);
914     local_detail(file, line, (char *)NULL, detail);
915 }
916 
917 
918 /*
919  * clear_footnotes
920  */
921 
clear_footnotes(void)922 PRIVATE void clear_footnotes(void)
923 {
924     int i;
925 
926     for (i = 0; i < num_incfiles; i++)
927     {
928 	incfile_list[i].footnote = 0;
929     }
930 }
931 
932 
933 /*
934  * print_key: correlates bracketed footnote numbers
935  *            with include file names
936  */
937 
938 
print_key(int num_footnotes)939 PRIVATE void print_key(int num_footnotes)
940 {
941     int i;         /* footnote number */
942     int j;         /* include file index */
943     char buf[6];   /* holds bracketed footnote # */
944 
945 
946     (void)fprintf(list_fd, "\n________\n\n");
947     for (i = 1; i <= num_footnotes; i++)
948     {
949 	(void)sprintf(buf, "[%d]", i);
950         (void)fprintf(list_fd, "%5s -- in include file: ", buf);
951 
952         for (j = 0; j < num_incfiles; j++)
953         {
954             if (incfile_list[j].footnote == i)
955             {
956                 (void)fprintf(list_fd, "%s\n", incfile_list[j].fname);
957             }
958         }
959     }
960 }
961 
962 		/* Keep track of number of statement labels use, max
963 		   in any subprogram and total.
964 		 */
update_label_resources()965 void update_label_resources()
966 {
967     if (num_labels > max_labels)
968     {
969 	max_labels = num_labels;
970     }
971     tot_label_count += num_labels;
972 }
973