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