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