Initial revision
[fw/sdcc] / as / mcs51 / lklex.c
1 /* lklex.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 #include <stdio.h>
13 #include <string.h>
14 #include <alloc.h>
15 #include "aslink.h"
16
17 /*)Module       lklex.c
18  *
19  *      The module lklex.c contains the general lexical analysis
20  *      functions used to scan the text lines from the .rel files.
21  *
22  *      lklex.c contains the fllowing functions:
23  *              char    endline()
24  *              char    get()
25  *              VOID    getfid()
26  *              VOID    getid()
27  *              int     getline()
28  *              int     getmap()
29  *              char    getnb()
30  *              int     more()
31  *              VOID    skip()
32  *              VOID    unget()
33  *
34  *      lklex.c contains no local variables.
35  */
36
37 /*)Function     VOID    getid(id,c)
38  *
39  *              char *  id              a pointer to a string of
40  *                                      maximum length NCPS
41  *              int     c               mode flag
42  *                                      >=0     this is first character to
43  *                                              copy to the string buffer
44  *                                      <0      skip white space
45  *
46  *      The function getid() scans the current input text line
47  *      from the current position copying the next LETTER | DIGIT string
48  *      into the external string buffer (id).  The string ends when a non
49  *      LETTER or DIGIT character is found. The maximum number of
50  *      characters copied is NCPS.  If the input string is larger than
51  *      NCPS characters then the string is truncated, if the input string
52  *      is shorter than NCPS characters then the string is NULL filled.
53  *      If the mode argument (c) is >=0 then (c) is the first character
54  *      copied to the string buffer, if (c) is <0 then intervening white
55  *      space (SPACES and TABS) are skipped.
56  *
57  *      local variables:
58  *              char *  p               pointer to external string buffer
59  *              int     c               current character value
60  *
61  *      global variables:
62  *              char    ctype[]         a character array which defines the
63  *                                      type of character being processed.
64  *                                      This index is the character
65  *                                      being processed.
66  *
67  *      called functions:
68  *              char    get()           lklex.c
69  *              char    getnb()         lklex.c
70  *              VOID    unget()         lklex.c
71  *
72  *      side effects:
73  *              use of getnb(), get(), and unget() updates the
74  *              global pointer ip the position in the current
75  *              input text line.
76  */
77
78 VOID
79 getid(id, c)
80 register int c;
81 char *id;
82 {
83         register char *p;
84
85         if (c < 0) {
86                 c = getnb();
87         }
88         p = id;
89         do {
90                 if (p < &id[NCPS])
91                         *p++ = c;
92         } while (ctype[c=get()] & (LETTER|DIGIT));
93         unget(c);
94         while (p < &id[NCPS])
95                 *p++ = 0;
96 }
97
98 /*)Function     VOID    getfid(fid,c)
99  *
100  *              char *  str             a pointer to a string of
101  *                                      maximum length FILSPC
102  *              int     c               this is first character to
103  *                                      copy to the string buffer
104  *
105  *      The function getfid() scans the current input text line
106  *      from the current position copying the next string
107  *      into the external string buffer (str).  The string ends when a
108  *      non SPACE type character is found. The maximum number of
109  *      characters copied is FILSPC. If the input string is larger than
110  *      FILSPC characters then the string is truncated, if the input string
111  *      is shorter than FILSPC characters then the string is NULL filled.
112  *
113  *      local variables:
114  *              char *  p               pointer to external string buffer
115  *              int     c               current character value
116  *
117  *      global variables:
118  *              char    ctype[]         a character array which defines the
119  *                                      type of character being processed.
120  *                                      This index is the character
121  *                                      being processed.
122  *
123  *      called functions:
124  *              char    get()           lklex.c
125  *
126  *      side effects:
127  *              use of get() updates the global pointer ip
128  *              the position in the current input text line.
129  */
130
131 VOID
132 getfid(str, c)
133 register int c;
134 char *str;
135 {
136         register char *p;
137
138         p = str;
139         do {
140                 if (p < &str[FILSPC-1])
141                         *p++ = c;
142                 c = get();
143         } while (c && (ctype[c] != SPACE));
144         while (p < &str[FILSPC])
145                 *p++ = 0;
146 }
147
148 /*)Function     char    getnb()
149  *
150  *      The function getnb() scans the current input text
151  *      line returning the first character not a SPACE or TAB.
152  *
153  *      local variables:
154  *              int     c               current character from input
155  *
156  *      global variables:
157  *              none
158  *
159  *      called functions:
160  *              char    get()           lklex.c
161  *
162  *      side effects:
163  *              use of get() updates the global pointer ip, the position
164  *              in the current input text line
165  */
166
167 char
168 getnb()
169 {
170         register int c;
171
172         while ((c=get())==' ' || c=='\t')
173                 ;
174         return (c);
175 }
176
177 /*)Function     VOID    skip()
178  *
179  *      The function skip() scans the input text skipping all
180  *      letters and digits.
181  *
182  *      local variables:
183  *              none
184  *
185  *      global variables:
186  *              char    ctype[]         array of character types, one per
187  *                                      ASCII character
188  *              
189  *      functions called:
190  *              char    get()           lklex.c
191  *              char    getnb()         lklex.c
192  *              VOID    unget()         lklex.c
193  *
194  *      side effects:
195  *              Input letters and digits are skipped.
196  */
197
198 VOID
199 skip(c)
200 register int c;
201 {
202         if (c < 0)
203                 c = getnb();
204         while (ctype[c=get()] & (LETTER|DIGIT)) { ; }
205         unget(c);
206 }
207
208 /*)Function     char    get()
209  *
210  *      The function get() returns the next character in the
211  *      input text line, at the end of the line a
212  *      NULL character is returned.
213  *
214  *      local variables:
215  *              int     c               current character from
216  *                                      input text line
217  *
218  *      global variables:
219  *              char *  ip              pointer into the current
220  *                                      input text line
221  *
222  *      called functions:
223  *              none
224  *
225  *      side effects:
226  *              updates ip to the next character position in the
227  *              input text line.  If ip is at the end of the
228  *              line, ip is not updated.
229  */
230
231 char
232 get()
233 {
234         register int c;
235
236         if ((c = *ip) != 0)
237                 ++ip;
238         return (c);
239 }
240
241 /*)Function     VOID    unget(c)
242  *
243  *              int     c               value of last character
244  *                                      read from input text line
245  *
246  *      If (c) is not a NULL character then the global pointer ip
247  *      is updated to point to the preceeding character in the
248  *      input text line.
249  *
250  *      NOTE:   This function does not push the character (c)
251  *              back into the input text line, only
252  *              the pointer ip is changed.
253  *
254  *      local variables:
255  *              int     c               last character read
256  *                                      from input text line
257  *
258  *      global variables:
259  *              char *  ip              position into the current
260  *                                      input text line
261  *
262  *      called functions:
263  *              none
264  *
265  *      side effects:
266  *              ip decremented by 1 character position
267  */
268
269 VOID
270 unget(c)
271 {
272         if (c != 0)
273                 --ip;
274 }
275
276 /*)Function     int     getmap(d)
277  *
278  *              int     d               value to compare with the
279  *                                      input 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
291  *                                      from input 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()           lklex.c
300  *              VOID    unget()         lklex.c
301  *
302  *      side effects:
303  *              use of get() updates the global pointer ip the position
304  *              in the current input text line
305  */
306
307 int
308 getmap(d)
309 {
310         register int c, n, v;
311
312         if ((c = get()) == '\0')
313                 return (-1);
314         if (c == d)
315                 return (-1);
316         if (c == '\\') {
317                 c = get();
318                 switch (c) {
319
320                 case 'b':
321                         c = '\b';
322                         break;
323
324                 case 'f':
325                         c = '\f';
326                         break;
327
328                 case 'n':
329                         c = '\n';
330                         break;
331
332                 case 'r':
333                         c = '\r';
334                         break;
335
336                 case 't':
337                         c = '\t';
338                         break;
339
340                 case '0':
341                 case '1':
342                 case '2':
343                 case '3':
344                 case '4':
345                 case '5':
346                 case '6':
347                 case '7':
348                         n = 0;
349                         v = 0;
350                         while (++n<=3 && c>='0' && c<='7') {
351                                 v = (v<<3) + c - '0';
352                                 c = get();
353                         }
354                         unget(c);
355                         c = v;
356                         break;
357                 }
358         }
359         return (c);
360 }
361
362 /*)Function     int     getline()
363  *
364  *      The function getline() reads a line of input text from a
365  *      .rel source text file, a .lnk command file or from stdin.
366  *      Lines of text are processed from a single .lnk file or
367  *      multiple .rel files until all files have been read.
368  *      The input text line is copied into the global string ib[]
369  *      and converted to a NULL terminated string.  The function
370  *      getline() returns a (1) after succesfully reading a line
371  *      or a (0) if all files have been read.
372  *      This function also opens each input .lst file and output
373  *      .rst file as each .rel file is processed.
374  *
375  *      local variables:
376  *              int     i               string length
377  *              int     ftype           file type
378  *              char *  fid             file name
379  *
380  *      global variables:
381  *              lfile   *cfp            The pointer *cfp points to the
382  *                                      current lfile structure
383  *              lfile   *filep          The pointer *filep points to the
384  *                                      beginning of a linked list of
385  *                                      lfile structures.
386  *              int     gline           get a line from the LST file
387  *                                      to translate for the RST file
388  *              char    ib[NINPUT]      REL file text line
389  *              int     pass            linker pass number
390  *              int     pflag           print linker command file flag
391  *              FILE    *rfp            The file handle to the current
392  *                                      output RST file
393  *              FILE    *sfp            The file handle sfp points to the
394  *                                      currently open file
395  *              FILE *  stdin           c_library
396  *              FILE *  stdout          c_library
397  *              FILE    *tfp            The file handle to the current
398  *                                      LST file being scanned
399  *              int     uflag           update listing flag
400  *
401  *      called functions:
402  *              FILE *  afile()         lkmain.c
403  *              int     fclose()        c_library
404  *              char *  fgets()         c_library
405  *              int     fprintf()       c_library
406  *              VOID    lkulist()       lklist.c
407  *              VOID    lkexit()        lkmain.c
408  *              int     strlen()        c_library
409  *
410  *      side effects:
411  *              The input stream is scanned.  The .rel files will be
412  *              opened and closed sequentially scanning each in turn.
413  */
414
415 int
416 getline()
417 {
418         register int i, ftype;
419         register char *fid;
420
421 loop:   if (pflag && cfp && cfp->f_type == F_STD)
422                 fprintf(stdout, "ASlink >> ");
423
424         if (sfp == NULL || fgets(ib, sizeof ib, sfp) == NULL) {
425                 if (sfp) {
426                         fclose(sfp);
427                         sfp = NULL;
428                         lkulist(0);
429                 }
430                 if (cfp == NULL) {
431                         cfp = filep;
432                 } else {
433                         cfp = cfp->f_flp;
434                 }
435                 if (cfp) {
436                         ftype = cfp->f_type;
437                         fid = cfp->f_idp;
438                         if (ftype == F_STD) {
439                                 sfp = stdin;
440                         } else
441                         if (ftype == F_LNK) {
442                                 sfp = afile(fid, "lnk", 0);
443                         } else
444                         if (ftype == F_REL) {
445                                 sfp = afile(fid, "rel", 0);
446                                 /* if a .cdb file exists then copy it over */
447                                 if (dflag && sfp && dfp && pass == 0) {
448                                     FILE *xfp = afile(fid,"cdb",0);
449                                     if (xfp) {
450                                         copyfile(dfp,xfp);
451                                         fclose(xfp);
452                                     }
453                                 }
454                                 if (uflag && pass != 0) {
455                                  if ((tfp = afile(fid, "lst", 0)) != NULL) {
456                                   if ((rfp = afile(fid, "rst", 1)) == NULL) {
457                                         fclose(tfp);
458                                         tfp = NULL;
459                                   }
460                                  }
461                                 }
462                                 gline = 1;
463                         } else {
464                                 fprintf(stderr, "Invalid file type\n");
465                                 lkexit(1);
466                         }
467                         if (sfp == NULL) {
468                                 lkexit(1);
469                         }
470                         goto loop;
471                 } else {
472                         filep = NULL;
473                         return(0);
474                 }
475         }
476         i = strlen(ib) - 1;
477         if (ib[i] == '\n')
478                 ib[i] = 0;
479         return (1);
480 }
481
482 /*)Function     int     more()
483  *
484  *      The function more() scans the input text line
485  *      skipping white space (SPACES and TABS) and returns a (0)
486  *      if the end of the line or a comment delimeter (;) is found,
487  *      or a (1) if their are additional characters in the line.
488  *
489  *      local variables:
490  *              int     c               next character from
491  *                                      the input text line
492  *
493  *      global variables:
494  *              none
495  *
496  *      called functions:
497  *              char    getnb()         lklex.c
498  *              VOID    unget()         lklex.c
499  *
500  *      side effects:
501  *              use of getnb() and unget() updates the global pointer ip
502  *              the position in the current input text line
503  */
504
505 int
506 more()
507 {
508         register int c;
509
510         c = getnb();
511         unget(c);
512         return( (c == '\0' || c == ';') ? 0 : 1 );
513 }
514
515 /*)Function     char    endline()
516  *
517  *      The function endline() scans the input text line
518  *      skipping white space (SPACES and TABS) and returns the next
519  *      character or a (0) if the end of the line is found or a
520  *      comment delimiter (;) is found.
521  *
522  *      local variables:
523  *              int     c               next character from
524  *                                      the input text line
525  *
526  *      global variables:
527  *              none
528  *
529  *      called functions:
530  *              char    getnb()         lklex.c
531  *
532  *      side effects:
533  *              Use of getnb() updates the global pointer ip the
534  *              position in the current input text line.
535  */
536
537 char
538 endline()
539 {
540         register int c;
541
542         c = getnb();
543         return( (c == '\0' || c == ';') ? 0 : c );
544 }