Pristine Ack-5.5
[Ack-5.5.git] / modules / src / read_em / readk.c
1 /* $Id: readk.c,v 1.17 1994/06/24 11:21:35 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  */
6 /*      This file must be included in the file "read_emk.c".
7         It takes care of the reading of compact EM code.
8 */
9
10 #include <ctype.h>
11
12 /* get16, get32: read a signed constant
13 */
14 PRIVATE int
15 get16()
16 {
17         register int l_byte, h_byte;
18
19         l_byte = getbyte();
20         h_byte = getbyte();
21         if (h_byte >= 128) h_byte -= 256;
22         return l_byte | (h_byte << 8);
23 }
24
25 PRIVATE arith
26 get32()
27 {
28         register arith l;
29         register int h_byte;
30
31         l = getbyte();
32         l |= ((unsigned) getbyte() << 8);
33         l |= ((arith) getbyte() << 16);
34         h_byte = getbyte();
35         if (h_byte >= 128) h_byte -= 256;
36         return l | ((arith) h_byte << 24);
37 }
38
39 PRIVATE struct string *getstring();
40
41 /* getarg : read an argument of any type, and check it against "typset"
42    if neccesary. Put result in "ap".
43 */
44 PRIVATE void
45 getarg(typset, ap)
46         register struct e_arg *ap;
47 {
48         register int i = getbyte();
49 #ifdef CHECKING
50         int argtyp;
51 #endif /* CHECKING */
52
53         ap->ema_argtype = 0;
54         switch(i) {
55         default:
56                 if (i < sp_fcst0+sp_ncst0 && i >= sp_fcst0) { /* A cst */
57                         ap->ema_cst = i - sp_zcst0;
58                         ap->ema_argtype = cst_ptyp;
59                         i = sp_cst2;
60                 }
61                 break;
62
63         case sp_dlb1:   /* Numeric data label encoded in one byte */
64                 ap->ema_dlb = getbyte();
65                 ap->ema_szoroff = 0;
66                 ap->ema_argtype = nof_ptyp;
67                 break;
68
69         case sp_dlb2:   /* Numeric data label encoded in two bytes */
70                 ap->ema_dlb = get16();
71                 ap->ema_szoroff = 0;
72                 ap->ema_argtype = nof_ptyp;
73 #ifdef CHECKING
74                 if (ap->ema_dlb > 32767 && !EM_error) {
75                         EM_error = "Illegal data label";
76                         break;
77                 }
78 #endif /* CHECKING */
79                 break;
80
81         case sp_ilb1:   /* Instruction label encoded in one byte */
82                 ap->ema_ilb = getbyte();
83                 ap->ema_argtype = ilb_ptyp;
84                 break;
85
86         case sp_ilb2:   /* Instruction label encoded in two bytes */
87                 ap->ema_ilb = get16();
88                 ap->ema_argtype = ilb_ptyp;
89 #ifdef CHECKING
90                 if (ap->ema_ilb > 32767 && !EM_error) {
91                         EM_error = "Illegal instruction label";
92                         break;
93                 }
94 #endif /* CHECKING */
95                 break;
96
97         case sp_cst2:   /* A cst encoded in two bytes */
98                 ap->ema_cst = get16();
99                 ap->ema_argtype = cst_ptyp;
100                 break;
101
102         case sp_cst4:   /* A cst encoded in four bytes */
103                 ap->ema_cst = get32();
104                 ap->ema_argtype = cst_ptyp;
105                 break;
106
107         case sp_pnam:   /* A procedure name */
108         {
109                 register struct string *p;
110
111                 p = getstring(1);
112                 ap->ema_pnam = p->str;
113                 ap->ema_argtype = pro_ptyp;
114                 break;
115         }
116
117         case sp_dnam:   /* A Non-numeric data label */
118         {
119                 register struct string *p;
120
121                 p = getstring(1);
122                 ap->ema_dnam = p->str;
123                 ap->ema_szoroff = 0;
124                 ap->ema_argtype = sof_ptyp;
125                 break;
126         }
127
128         case sp_doff:   /* A data label + offset */
129         {
130                 struct e_arg dummy;
131
132                 getarg(lab_ptyp, ap);
133                 getarg(cst_ptyp, &dummy);
134                 ap->ema_szoroff = dummy.ema_cst;
135                 break;
136         }
137
138         case sp_icon:   /* An integer constant */
139         case sp_ucon:   /* An unsigned constant */
140         case sp_fcon:   /* A floating constant */
141         {
142                 register struct string *p;
143
144                 getarg(cst_ptyp, ap);
145                 ap->ema_szoroff = ap->ema_cst;
146                 p = getstring(0);
147                 ap->ema_argtype = ptyp(i);
148                 ap->ema_string = p->str;
149                 break;
150         }
151
152         case sp_scon:   /* A string constant */
153         {
154                 register struct string *p;
155
156                 p = getstring(0);
157                 ap->ema_argtype = str_ptyp;
158                 ap->ema_string = p->str;
159                 ap->ema_szoroff = p->length;
160                 break;
161         }
162         }
163 #ifdef CHECKING
164         argtyp = i;
165         if (EM_error) return;
166
167         if (i == EOF) {
168                 xfatal("Unexpected EOF");
169                 return;
170         }
171
172         if ((i -= sp_fspec) < 0 || i >= 16) {
173                 xerror("Illegal byte");
174                 return;
175         }
176
177         if ((typset & (1 << i)) == 0 && !EM_error) {
178                 EM_error = "Bad argument type";
179         }
180         if (argtyp == sp_cend) {
181                 ap->ema_argtype = 0;
182         }
183 #else /* not CHECKING */
184         if (i == sp_cend) {
185                 ap->ema_argtype = 0;
186         }
187 #endif /* CHECKING */
188 }
189
190 #ifdef CHECKING
191 /* checkident: check that a string indeed represents an identifier
192 */
193 PRIVATE int
194 checkident(s)
195         register struct string *s;
196 {
197         register char *p;
198         register int n;
199
200         p = s->str;
201         if (!isascii(*p) || (!isalpha(*p) && *p != '_')) {
202                 return 0;
203         }
204         p++;
205         for (n = s->length; --n > 0; p++) {
206                 if (!isascii(*p) || (!isalnum(*p) && *p != '_')) {
207                         return 0;
208                 }
209         }
210         return 1;
211 }
212 #endif /* CHECKING */
213
214 /* getstring: read a string from the input
215 */
216 /*ARGSUSED*/
217 PRIVATE struct string *
218 getstring(isident)
219 {
220         register char *p;
221         register int n;
222         register struct string *s = &string;
223         struct e_arg dummy;
224
225         getarg(cst_ptyp, &dummy);
226                                         /* Read length of string */
227         n = dummy.ema_cst;
228 #ifdef CHECKING
229         if (n < 0) {
230                 xerror("Negative length in string");
231                 s->length = 0;
232                 return s;
233         }
234 #endif /* CHECKING */
235
236         if (n > s->maxlen) {
237                 if (! s->maxlen) {
238                         s->str = Malloc(s->maxlen = 256);
239                 }
240                 else    s->str = Realloc(s->str, (s->maxlen = (n+255)&~255));
241         }
242
243         s->length = n;
244         p = s->str;
245         while (--n >= 0) {
246                 *p++ = getbyte();
247         }
248         *p++ = '\0';
249
250 #ifdef CHECKING
251         if (isident) {
252                 if (!checkident(s) && !EM_error) {
253                         EM_error = "Illegal identifier";
254                 }
255         }
256 #endif /* CHECKING */
257         return s;
258 }
259
260 /* gethead: read the start of an EM-line
261 */
262 PRIVATE void
263 gethead(p)
264         register struct e_instr *p;
265 {
266         register int i;
267
268         EM_lineno++;
269
270         if ((i = getbyte()) < sp_fmnem+sp_nmnem && i >= sp_fmnem) {
271                 /* A mnemonic */
272                 p->em_type = EM_MNEM;
273                 p->em_opcode = i;
274                 return;
275         }
276
277         if (i < sp_fpseu+sp_npseu && i >= sp_fpseu) {   /* A pseudo */
278                 if (i == ps_mes) {
279                         p->em_type = EM_STARTMES;
280                 }
281                 else    p->em_type = EM_PSEU;
282                 p->em_opcode = i;
283                 return;
284         }
285
286         if (i < sp_filb0+sp_nilb0 && i >= sp_filb0) {   /* Instruction label */
287                 p->em_type = EM_DEFILB;
288                 p->em_argtype = ilb_ptyp;
289                 p->em_ilb = i - sp_filb0;
290                 return;
291         }
292
293         switch(i) {
294         case sp_ilb1:   /* Instruction label */
295                 p->em_type = EM_DEFILB;
296                 p->em_argtype = ilb_ptyp;
297                 p->em_ilb = getbyte();
298                 break;
299
300         case sp_ilb2:   /* Instruction label */
301                 p->em_type = EM_DEFILB;
302                 p->em_argtype = ilb_ptyp;
303                 p->em_ilb = get16();
304 #ifdef CHECKING
305                 if (p->em_ilb > 32767 && !EM_error) {
306                         EM_error = "Illegal instruction label definition";
307                 }
308 #endif /* CHECKING */
309                 break;
310
311         case sp_dlb1:   /* Numeric data label */
312                 p->em_type = EM_DEFDLB;
313                 p->em_argtype = nof_ptyp;
314                 p->em_dlb = getbyte();
315                 break;
316
317         case sp_dlb2:   /* Numeric data label */
318                 p->em_type = EM_DEFDLB;
319                 p->em_argtype = nof_ptyp;
320                 p->em_dlb = get16();
321 #ifdef CHECKING
322                 if (p->em_dlb > 32767 && !EM_error) {
323                         EM_error = "Illegal data label definition";
324                 }
325 #endif /* CHECKING */
326                 break;
327
328         case sp_dnam:   /* Non-numeric data label */
329         {
330                 struct string *s;
331
332                 p->em_type = EM_DEFDNAM;
333                 p->em_argtype = sof_ptyp;
334                 if (!(s = getstring(1))) {
335                         p->em_dnam = "";
336                 }
337                 else    p->em_dnam = s->str;
338                 break;
339         }               
340
341         case EOF:       /* End of file */
342                 p->em_type = EM_EOF;
343                 return;
344
345         default:
346                 xerror("Unknown opcode");
347                 break;
348         }
349
350         return;
351 }