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