2 * label - label handling routines
4 * Copyright (C) 1999-2007 David I. Bell
6 * Calc is open software; you can redistribute it and/or modify it under
7 * the terms of the version 2.1 of the GNU Lesser General Public License
8 * as published by the Free Software Foundation.
10 * Calc is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
13 * Public License for more details.
15 * A copy of version 2.1 of the GNU Lesser General Public License is
16 * distributed with calc under the filename COPYING-LGPL. You should have
17 * received a copy with calc; if not, write to Free Software Foundation, Inc.
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * @(#) $Revision: 30.1 $
21 * @(#) $Id: label.c,v 30.1 2007/03/16 11:09:46 chongo Exp $
22 * @(#) $Source: /usr/local/src/bin/calc/RCS/label.c,v $
24 * Under source code control: 1990/02/15 01:48:17
25 * File existed as early as: before 1990
27 * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
38 STATIC
long labelcount
; /* number of user labels defined */
39 STATIC STRINGHEAD labelnames
; /* list of user label names */
40 STATIC LABEL labels
[MAXLABELS
]; /* list of user labels */
44 * Initialize the table of labels for a function.
55 * Define a user named label to have the offset of the next opcode.
61 definelabel(char *name
)
63 register LABEL
*lp
; /* current label */
64 long i
; /* current label index */
66 i
= findstr(&labelnames
, name
);
69 if (lp
->l_offset
>= 0) {
70 scanerror(T_NULL
, "Label \"%s\" is multiply defined",
77 if (labelcount
>= MAXLABELS
) {
78 scanerror(T_NULL
, "Too many labels in use");
81 lp
= &labels
[labelcount
++];
83 lp
->l_offset
= (long)curfunc
->f_opcodecount
;
84 lp
->l_name
= addstr(&labelnames
, name
);
90 * Add the offset corresponding to the specified user label name to the
91 * opcode table for a function. If the label is not yet defined, then a
92 * chain of undefined offsets is built using the offset value, and it
93 * will be fixed up when the label is defined.
96 * name user symbol name
101 register LABEL
*lp
; /* current label */
102 long i
; /* counter */
104 for (i
= labelcount
, lp
= labels
; --i
>= 0; lp
++) {
105 if (strcmp(name
, lp
->l_name
))
110 if (labelcount
>= MAXLABELS
) {
111 scanerror(T_NULL
, "Too many labels in use");
114 lp
= &labels
[labelcount
++];
117 lp
->l_name
= addstr(&labelnames
, name
);
123 * Check to make sure that all labels are defined.
128 register LABEL
*lp
; /* label being checked */
129 long i
; /* counter */
131 for (i
= labelcount
, lp
= labels
; --i
>= 0; lp
++) {
132 if (lp
->l_offset
>= 0)
134 scanerror(T_NULL
, "Label \"%s\" was never defined",
141 * Clear an internal label for use.
144 * lp label being cleared
147 clearlabel(LABEL
*lp
)
156 * Set any label to have the value of the next opcode in the current
157 * function being defined. If there were forward references to it,
158 * all such references are patched up.
166 register FUNC
*fp
; /* current function */
167 long curfix
; /* offset of current location being fixed */
168 long nextfix
; /* offset of next location to fix up */
169 unsigned long offset
; /* offset of this label */
172 offset
= fp
->f_opcodecount
;
173 nextfix
= (long)lp
->l_chain
;
174 while (nextfix
>= 0) {
176 nextfix
= (long)fp
->f_opcodes
[curfix
];
177 fp
->f_opcodes
[curfix
] = offset
;
180 lp
->l_offset
= (long)offset
;
186 * Use the specified label at the current location in the function
187 * being compiled. This adds one word to the current function being
188 * compiled. If the label is not yet defined, a patch chain is built
189 * so the reference can be fixed when the label is defined.
192 * lp label being used
197 unsigned long offset
; /* offset being added */
199 offset
= curfunc
->f_opcodecount
;
200 if (lp
->l_offset
>= 0) {
201 curfunc
->f_opcodes
[curfunc
->f_opcodecount
++] = lp
->l_offset
;
204 curfunc
->f_opcodes
[curfunc
->f_opcodecount
++] = lp
->l_chain
;
205 lp
->l_chain
= (long)offset
;