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