Pristine Ack-5.5
[Ack-5.5.git] / lang / pc / comp / label.c
1 /*      L A B E L   H A N D L I N G     */
2
3 #include        <alloc.h>
4 #include        <em.h>
5
6 #include        "LLlex.h"
7 #include        "def.h"
8 #include        "idf.h"
9 #include        "main.h"
10 #include        "node.h"
11 #include        "scope.h"
12 #include        "type.h"
13
14
15 DeclLabel(nd)
16         struct node *nd;
17 {
18         struct def *df;
19
20         if( !(df = define(nd->nd_IDF, CurrentScope, D_LABEL)) ) {
21                 node_error(nd, "label %s redeclared", nd->nd_IDF->id_text);
22         }
23         else    {
24                 df->lab_no = ++text_label;
25                 nd->nd_def = df;
26         }
27 }
28
29 chk_labels(Slevel)
30 {
31         register struct node *labnd = BlockScope->sc_lablist;
32         register struct def *df;
33
34         while( labnd )  {
35                 df = labnd->nd_def;
36                 if( Slevel == 1 )       {
37                         if( !df->lab_level )
38                                 if( df->lab_next )
39                                 /* jump to undefined label */
40                                         error("jump to undefined label %s",
41                                                         df->df_idf->id_text);
42                                 else
43                                         warning(
44                                           "label %s declared but never defined",
45                                                         df->df_idf->id_text);
46                 }
47                 else if( df->lab_level == Slevel )
48                         df->lab_level = -1;
49                 else if( !df->lab_level )       {
50                         struct lab *plab = df->lab_next;
51
52                         while( plab )   {
53                                 if( plab->lb_level == Slevel )
54                                         plab->lb_level--;
55                                 plab = plab->lb_next;
56                         }
57                 }
58                 labnd = labnd->nd_next;
59         }
60 }
61
62 TstLabel(nd, Slevel)
63         register struct node *nd;
64 {
65         register struct def *df;
66
67         df = lookfor(nd, CurrVis, 0);
68         if( df->df_kind == D_ERROR )    {
69                 node_error(nd, "label %s not declared", df->df_idf->id_text);
70                 df->df_kind = D_LABEL;
71                 nd->nd_def = df;
72                 nd->nd_next = BlockScope->sc_lablist;
73                 BlockScope->sc_lablist = nd;
74         }
75         else
76                 FreeNode(nd);
77
78         df->df_flags = D_USED;
79         if( !df->lab_level )    {
80                 /* forward jump */
81                 register struct lab *labelptr;
82
83                 labelptr = new_lab();
84                 labelptr->lb_next = df->lab_next;
85                 df->lab_next = labelptr;
86                 if( df->df_scope == BlockScope )        {
87                         /* local jump */
88                         labelptr->lb_level = Slevel;
89                         CodeLabel(df, 1);
90                 }
91                 else    {
92                         /* non-local jump, only permitted to
93                            outermost level (ISO 6.8.1 Note 2)
94                         */
95                         labelptr->lb_level = 1;
96                         CodeLabel(df, 0);
97                 }
98         }
99         else if( df->lab_level == -1 || df->lab_level > Slevel )
100                 node_error(nd, "illegal jump to label %s", df->df_idf->id_text);
101         else
102                 CodeLabel(df, 1);
103 }
104
105 DefLabel(nd, Slevel)
106         register struct node *nd;
107 {
108         register struct def *df;
109
110         if( !(df = lookup(nd->nd_IDF, BlockScope, D_INUSE)) )   {
111                 node_error(nd, "label %s must be declared in same block"
112                                                         , nd->nd_IDF->id_text);
113                 df = define(nd->nd_IDF, BlockScope, D_LABEL);
114                 nd->nd_def = df;
115                 df->lab_no = ++text_label;
116                 nd->nd_next = BlockScope->sc_lablist;
117                 BlockScope->sc_lablist = nd;
118         }
119         else FreeNode(nd);
120
121         df->df_flags |= D_SET;
122         if( df->lab_level)
123                 node_error(nd, "label %s already defined", nd->nd_IDF->id_text);
124         else    {
125                 register struct lab *labelptr;
126
127                 df->lab_level = Slevel;
128                 labelptr = df->lab_next;
129                 while( labelptr )       {
130                         if( labelptr->lb_level < Slevel )       {
131                                 node_error(nd, "illegal jump to label %s",
132                                                         nd->nd_IDF->id_text);
133                                 return;
134                         }
135                         labelptr = labelptr->lb_next;
136                 }
137                 C_df_ilb(df->lab_no);
138         }
139 }
140
141 CodeLabel(df, local)
142         register struct def *df;
143 {
144         if( err_occurred ) return;
145
146         if( local )
147                 C_bra(df->lab_no);
148         else    {
149                 /* non-local jump */
150                 int level = df->df_scope->sc_level;
151
152                 if( !df->lab_descr )    {
153                         /* generate label for goto descriptor */
154                         df->lab_descr = ++data_label;
155                         C_ina_dlb(data_label);
156                 }
157                 /* perform the jump */
158                 C_lae_dlb(df->lab_descr, (arith) 0);
159
160                 /* LB of target procedure */
161                 if( level > 0 )
162                         C_lxl((arith) proclevel - level);
163                 else
164                         C_zer(pointer_size);
165                 C_cal("_gto");
166                 C_asp( 2 * pointer_size);
167         }
168 }