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