Initial revision
[fw/sdcc] / as / z80 / aslex.c
1 /* aslex.c */
2
3 /*
4  * (C) Copyright 1989-1995
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  */
11
12 /*
13  * Extensions: P. Felber, M. Hope
14  */
15
16 #include <stdio.h>
17 #include <setjmp.h>
18 #include <string.h>
19 #include <alloc.h>
20 #include "asm.h"
21
22 /*)Module       aslex.c
23  *
24  *      The module aslex.c includes the general lexical
25  *      analysis routines for the assembler.
26  *
27  *      aslex.c contains the following functions:
28  *              char    endline()
29  *              char    get()
30  *              VOID    getid(id,c)
31  *              int     getline()
32  *              int     getmap()
33  *              char    getnb()
34  *              VOID    getst()
35  *              int     more()
36  *              VOID    unget(c)
37  *
38  *      aslex.c contains no local/static variables
39  */
40
41 /*)Function     VOID    getid(id,c)
42  *
43  *              char *  id              a pointer to a string of
44  *                                      maximum length NCPS
45  *              int     c               mode flag
46  *                                      >=0     this is first character to
47  *                                              copy to the string buffer
48  *                                      <0      skip white space, first
49  *                                              character must be a LETTER
50  *
51  *      The function getid() scans the current assembler-source text line
52  *      from the current position copying the next LETTER | DIGIT string
53  *      into the external string buffer (id).  The string ends when a non
54  *      LETTER or DIGIT character is found. The maximum number of
55  *      characters copied is NCPS.  If the input string is larger than
56  *      NCPS characters then the string is truncated, if the input string
57  *      is shorter than NCPS characters then the string is NULL filled.
58  *      If the mode argument (c) is >=0 then (c) is the first character
59  *      copied to the string buffer, if (c) is <0 then intervening white
60  *      space (SPACES and TABS) are skipped and the first character found
61  *      must be a LETTER else a 'q' error terminates the parse of this
62  *      assembler-source text line.
63  *
64  *      local variables:
65  *              char *  p               pointer to external string buffer
66  *              int     c               current character value
67  *
68  *      global variables:
69  *              char    ctype[]         a character array which defines the
70  *                                      type of character being processed.
71  *                                      This index is the character
72  *                                      being processed.
73  *
74  *      called functions:
75  *              char    get()           aslex.c
76  *              char    getnb()         aslex.c
77  *              VOID    unget()         aslex.c
78  *
79  *      side effects:
80  *              use of getnb(), get(), and unget() updates the
81  *              global pointer ip, the position in the current
82  *              assembler-source text line.
83  */
84
85 VOID
86 getid(id, c)
87 register c;
88 char *id;
89 {
90         register char *p;
91
92         if (c < 0) {
93                 c = getnb();
94                 if ((ctype[c] & LETTER) == 0)
95                         qerr();
96         }
97         p = id;
98         do {
99                 if (p < &id[NCPS])
100                         *p++ = c;
101         } while (ctype[c=get()] & (LETTER|DIGIT));
102         unget(c);
103         while (p < &id[NCPS])
104                 *p++ = 0;
105 }
106
107 /*)Function     VOID    getst(id,c)
108  *
109  *              char *  id              a pointer to a string of
110  *                                      maximum length NCPS
111  *              int     c               mode flag
112  *                                      >=0     this is first character to
113  *                                              copy to the string buffer
114  *                                      <0      skip white space, first
115  *                                              character must be a LETTER
116  *
117  *      The function getnbid() scans the current assembler-source text line
118  *      from the current position copying the next character string into
119  *      the external string buffer (id).  The string ends when a SPACE or
120  *      ILL character is found. The maximum number of
121  *      characters copied is NCPS.  If the input string is larger than
122  *      NCPS characters then the string is truncated, if the input string
123  *      is shorter than NCPS characters then the string is NULL filled.
124  *      If the mode argument (c) is >=0 then (c) is the first character
125  *      copied to the string buffer, if (c) is <0 then intervening white
126  *      space (SPACES and TABS) are skipped and the first character found
127  *      must be a LETTER else a 'q' error terminates the parse of this
128  *      assembler-source text line.
129  *
130  *      local variables:
131  *              char *  p               pointer to external string buffer
132  *              int     c               current character value
133  *
134  *      global variables:
135  *              char    ctype[]         a character array which defines the
136  *                                      type of character being processed.
137  *                                      This index is the character
138  *                                      being processed.
139  *
140  *      called functions:
141  *              char    get()           aslex.c
142  *              char    getnb()         aslex.c
143  *              VOID    unget()         aslex.c
144  *
145  *      side effects:
146  *              use of getnb(), get(), and unget() updates the
147  *              global pointer ip, the position in the current
148  *              assembler-source text line.
149  */
150
151 VOID
152 getst(id, c)
153 register c;
154 char *id;
155 {
156         register char *p;
157
158         if (c < 0) {
159                 c = getnb();
160                 if ((ctype[c] & LETTER) == 0)
161                         qerr();
162         }
163         p = id;
164         do {
165                 if (p < &id[NCPS])
166                         *p++ = c;
167         } while (ctype[c=get()] & ~(SPACE|ILL));
168         unget(c);
169         while (p < &id[NCPS])
170                 *p++ = 0;
171 }
172
173 /*)Function     char    getnb()
174  *
175  *      The function getnb() scans the current assembler-source
176  *      text line returning the first character not a SPACE or TAB.
177  *
178  *      local variables:
179  *              int     c               current character from
180  *                                      assembler-source text line
181  *
182  *      global variables:
183  *              none
184  *
185  *      called functions:
186  *              char    get()           aslex.c
187  *
188  *      side effects:
189  *              use of get() updates the global pointer ip, the position
190  *              in the current assembler-source text line
191  */
192
193 char
194 getnb()
195 {
196         register c;
197
198         while ((c=get()) == ' ' || c == '\t')
199                 ;
200         return (c);
201 }
202
203 /*)Function     char    get()
204  *
205  *      The function get() returns the next character in the
206  *      assembler-source text line, at the end of the line a
207  *      NULL character is returned.
208  *
209  *      local variables:
210  *              int     c               current character from
211  *                                      assembler-source text line
212  *
213  *      global variables:
214  *              char *  ip              pointer into the current
215  *                                      assembler-source text line
216  *
217  *      called functions:
218  *              none
219  *
220  *      side effects:
221  *              updates ip to the next character position in the
222  *              assembler-source text line.  If ip is at the end of the
223  *              line, ip is not updated.
224  */
225
226 char
227 get()
228 {
229         register c;
230
231         if ((c = *ip) != 0)
232                 ++ip;
233         return (c);
234 }
235
236 /*)Function     VOID    unget(c)
237  *
238  *              int     c               value of last character read from
239  *                                      assembler-source text line
240  *
241  *      If (c) is not a NULL character then the global pointer ip
242  *      is updated to point to the preceeding character in the
243  *      assembler-source text line.
244  *
245  *      NOTE:   This function does not push the character (c)
246  *              back into the assembler-source text line, only
247  *              the pointer ip is changed.
248  *
249  *      local variables:
250  *              int     c               last character read from
251  *                                      assembler-source text line
252  *
253  *      global variables:
254  *              char *  ip              position into the current
255  *                                      assembler-source text line
256  *
257  *      called functions:
258  *              none
259  *
260  *      side effects:
261  *              ip decremented by 1 character position
262  */
263
264 VOID
265 unget(c)
266 {
267         if (c)
268                 if (ip != ib)
269                         --ip;
270 }
271
272 /*)Function     int     getmap(d)
273  *
274  *              int     d               value to compare with the
275  *                                      assembler-source text line character
276  *
277  *      The function getmap() converts the 'C' style characters \b, \f,
278  *      \n, \r, and \t to their equivalent ascii values and also
279  *      converts 'C' style octal constants '\123' to their equivalent
280  *      numeric values.  If the first character is equivalent to (d) then
281  *      a (-1) is returned, if the end of the line is detected then
282  *      a 'q' error terminates the parse for this line, or if the first
283  *      character is not a \ then the character value is returned.
284  *
285  *      local variables:
286  *              int     c               value of character from the
287  *                                      assembler-source text line
288  *              int     n               looping counter
289  *              int     v               current value of numeric conversion
290  *
291  *      global variables:
292  *              none
293  *
294  *      called functions:
295  *              char    get()           aslex.c
296  *
297  *      side effects:
298  *              use of get() updates the global pointer ip the position
299  *              in the current assembler-source text line
300  */
301
302 int
303 getmap(d)
304 {
305         register c, n, v;
306
307         if ((c=get()) == '\0')
308                 qerr();
309         if (c == d)
310                 return (-1);
311         if (c == '\\') {
312                 c = get();
313                 switch (c) {
314
315                 case 'b':
316                         c = '\b';
317                         break;
318
319                 case 'f':
320                         c = '\f';
321                         break;
322
323                 case 'n':
324                         c = '\n';
325                         break;
326
327                 case 'r':
328                         c = '\r';
329                         break;
330
331                 case 't':
332                         c = '\t';
333                         break;
334
335                 case '0':
336                 case '1':
337                 case '2':
338                 case '3':
339                 case '4':
340                 case '5':
341                 case '6':
342                 case '7':
343                         n = 0;
344                         v = 0;
345                         while (++n<=3 && c>='0' && c<='7') {
346                                 v = (v<<3) + c - '0';
347                                 c = get();
348                         }
349                         unget(c);
350                         c = v;
351                         break;
352                 }
353         }
354         return (c);
355 }
356
357 /*)Function     int     getline()
358  *
359  *      The function getline() reads a line of assembler-source text
360  *      from an assembly source text file or an include file.
361  *      Lines of text are processed from assembler-source files until
362  *      all files have been read.  If an include file is opened then
363  *      lines of text are read from the include file (or nested
364  *      include file) until the end of the include file is found.
365  *      The input text line is copied into the global string ib[]
366  *      and converted to a NULL terminated string.  The function
367  *      getline() returns a (1) after succesfully reading a line
368  *      or a (0) if all files have been read.
369  *
370  *      local variables:
371  *              int     i               string length
372  *
373  *      global variables:
374  *              char    ib[]            string buffer containing
375  *                                      assembler-source text line
376  *              char    ifp[]           array of file handles for
377  *                                      include files
378  *              int     incfil          index for ifp[] specifies
379  *                                      active include file
380  *              int     incline[]       array of include file
381  *                                      line numbers
382  *              char    sfp[]           array of file handles for
383  *                                      assembler source files
384  *              int     cfile           index for sfp[] specifies
385  *                                      active source file
386  *              int     srcline[]       array of source file
387  *                                      line numbers
388  *              int     inpfil          maximum input file index
389  *
390  *      called functions:
391  *              int     fclose()        c-library
392  *              char *  fgets()         c-library
393  *              int     strlen()        c-library
394  *
395  *      side effects:
396  *              include file will be closed at detection of end of file.
397  *              the next sequential source file may be selected.
398  *              the global file indexes incfil or cfile may be changed.
399  *              The respective source line or include line counter
400  *              will be updated.
401  */
402
403 int
404 getline()
405 {
406 register i;
407
408 loop:   if (incfil >= 0) {
409                 if (fgets(ib, sizeof ib, ifp[incfil]) == NULL) {
410 #ifdef SDK
411                         fclose(ifp[incfil]);
412                         ifp[incfil--] = NULL;
413 #else /* SDK */
414                         fclose(ifp[incfil--]);
415 #endif /* SDK */
416                         lop = NLPP;
417                         goto loop;
418                 } else {
419                         ++incline[incfil];
420                 }
421         } else {
422                 if (fgets(ib, sizeof ib, sfp[cfile]) == NULL) {
423                         if (++cfile <= inpfil) {
424                                 srcline[cfile] = 0;
425                                 goto loop;
426                         }
427                         return (0);
428                 } else {
429                         ++srcline[cfile];
430                 }
431         }
432         i = strlen(ib) - 1;
433         if (ib[i] == '\n')
434                 ib[i] = 0;
435         return (1);
436 }
437
438 /*)Function     int     more()
439  *
440  *      The function more() scans the assembler-source text line
441  *      skipping white space (SPACES and TABS) and returns a (0)
442  *      if the end of the line or a comment delimeter (;) is found,
443  *      or a (1) if their are additional characters in the line.
444  *
445  *      local variables:
446  *              int     c               next character from the
447  *                                      assembler-source text line
448  *
449  *      global variables:
450  *              none
451  *
452  *      called functions:
453  *              char    getnb()         aslex.c
454  *              VOID    unget()         aslex.c
455  *
456  *      side effects:
457  *              use of getnb() and unget() updates the global pointer ip
458  *              the position in the current assembler-source text line
459  */
460
461 int
462 more()
463 {
464         register c;
465
466         c = getnb();
467         unget(c);
468         return( (c == '\0' || c == ';') ? 0 : 1 );
469 }
470
471 /*)Function     char    endline()
472  *
473  *      The function endline() scans the assembler-source text line
474  *      skipping white space (SPACES and TABS) and returns the next
475  *      character or a (0) if the end of the line is found or a
476  *      comment delimiter (;) is found.
477  *
478  *      local variables:
479  *              int     c               next character from the
480  *                                      assembler-source text line
481  *
482  *      global variables:
483  *              none
484  *
485  *      called functions:
486  *              char    getnb()         aslex.c
487  *
488  *      side effects:
489  *              use of getnb() updates the global pointer ip the
490  *              position in the current assembler-source text line
491  */
492
493 char
494 endline()
495 {
496         register c;
497
498         c = getnb();
499         return( (c == '\0' || c == ';') ? 0 : c );
500 }