73093ce9ca72dcd96ab6f89d8d3877e7033d8cb6
[fw/sdcc] / as / link / 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 "aslink.h"
15
16 /*)Module       lklex.c
17  *
18  *      The module lklex.c contains the general lexical analysis
19  *      functions used to scan the text lines from the .rel files.
20  *
21  *      lklex.c contains the fllowing functions:
22  *              char    endline()
23  *              char    get()
24  *              VOID    getfid()
25  *              VOID    getid()
26  *              VOID    getSid()
27  *              int     lk_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    getSid (char *id)
99  *
100  *              char *  id              a pointer to a string of
101  *                                      maximum length NCPS
102  *
103  *  getSid is derived from getid. It is called from newsym()
104  *  in lksym.c, when an S-record has to be scanned. getSid accepts
105  *  much more characters than getid, which is necessary for SDCC.
106  *
107  *      The function getSid() scans the current input text line
108  *      from the current position copying the next string
109  *      into the external string buffer (id).  The string ends when a space
110  *  character (space, tab, \0) is found. The maximum number of
111  *      characters copied is NCPS.  If the input string is larger than
112  *      NCPS characters then the string is truncated, if the input string
113  *      is shorter than NCPS characters then the string is NULL filled.
114  *      Intervening white space (SPACES and TABS) are skipped.
115  *
116  *      local variables:
117  *              char *  p               pointer to external string buffer
118  *              int     c               current character value
119  *
120  *      global variables:
121  *              char    ctype[]         a character array which defines the
122  *                                      type of character being processed.
123  *                                      This index is the character
124  *                                      being processed.
125  *
126  *      called functions:
127  *              char    get()           lklex.c
128  *              char    getnb()         lklex.c
129  *              VOID    unget()         lklex.c
130  *
131  *      side effects:
132  *              use of getnb(), get(), and unget() updates the
133  *              global pointer ip the position in the current
134  *              input text line.
135  */
136
137 VOID
138 getSid (char *id)
139 {
140         register int c;
141         register char *p;
142
143         c = getnb();
144         p = id;
145         do {
146                 if (p < &id[NCPS])
147                         *p++ = c;
148                 c = get();
149         } while (c != '\0' && c != ' ' && c != '\t');
150         unget(c);
151         while (p < &id[NCPS])
152                 *p++ = 0;
153 }
154
155 /*)Function     VOID    getfid(fid,c)
156  *
157  *              char *  str             a pointer to a string of
158  *                                      maximum length PATH_MAX
159  *              int     c               this is first character to
160  *                                      copy to the string buffer
161  *
162  *      The function getfid() scans the current input text line from
163  *      the current position copying the next string into the external
164  *      string buffer (str).  The string ends when end of line is found.
165  *      Trailing spacers are removed. The maximum number of characters
166  *      copied is PATH_MAX. If the input string is larger than PATH_MAX
167  *      characters then the string is truncated. The string is NULL
168  *      terminated.
169  *
170  *      local variables:
171  *              char *  p               pointer to external string buffer
172  *              int     c               current character value
173  *
174  *      global variables:
175  *              char    ctype[]         a character array which defines the
176  *                                      type of character being processed.
177  *                                      This index is the character
178  *                                      being processed.
179  *
180  *      called functions:
181  *              char    get()           lklex.c
182  *
183  *      side effects:
184  *              use of get() updates the global pointer ip
185  *              the position in the current input text line.
186  */
187
188 VOID
189 getfid(str, c)
190 register int c;
191 char *str;
192 {
193         register char *p;
194
195         p = str;
196         do
197         {
198                 if (p < &str[PATH_MAX-1])
199                         *p++ = c;
200                 c = get();
201                 if (c == ';')
202                         while (c)
203                                 c = get();
204         } while (c);
205         /* trim trailing spaces */
206         --p;
207         while (p >= str && ctype[(int)*p] == SPACE)
208                 --p;
209         /* terminate the string */
210         *(++p) = '\0';
211 }
212
213 /*)Function     char    getnb()
214  *
215  *      The function getnb() scans the current input text
216  *      line returning the first character not a SPACE or TAB.
217  *
218  *      local variables:
219  *              int     c               current character from input
220  *
221  *      global variables:
222  *              none
223  *
224  *      called functions:
225  *              char    get()           lklex.c
226  *
227  *      side effects:
228  *              use of get() updates the global pointer ip, the position
229  *              in the current input text line
230  */
231
232 char
233 getnb()
234 {
235         register int c;
236
237         while ((c=get())==' ' || c=='\t')
238                 ;
239         return (c);
240 }
241
242 /*)Function     VOID    skip()
243  *
244  *      The function skip() scans the input text skipping all
245  *      letters and digits.
246  *
247  *      local variables:
248  *              none
249  *
250  *      global variables:
251  *              char    ctype[]         array of character types, one per
252  *                                      ASCII character
253  *
254  *      functions called:
255  *              char    get()           lklex.c
256  *              char    getnb()         lklex.c
257  *              VOID    unget()         lklex.c
258  *
259  *      side effects:
260  *              Input letters and digits are skipped.
261  */
262
263 VOID
264 skip(c)
265 register int c;
266 {
267         if (c < 0)
268                 c = getnb();
269         while (ctype[c=get()] & (LETTER|DIGIT)) { ; }
270         unget(c);
271 }
272
273 /*)Function     char    get()
274  *
275  *      The function get() returns the next character in the
276  *      input text line, at the end of the line a
277  *      NULL character is returned.
278  *
279  *      local variables:
280  *              int     c               current character from
281  *                                      input text line
282  *
283  *      global variables:
284  *              char *  ip              pointer into the current
285  *                                      input text line
286  *
287  *      called functions:
288  *              none
289  *
290  *      side effects:
291  *              updates ip to the next character position in the
292  *              input text line.  If ip is at the end of the
293  *              line, ip is not updated.
294  */
295
296 char
297 get()
298 {
299         register int c;
300
301         if ((c = *ip) != 0)
302                 ++ip;
303         return (c);
304 }
305
306 /*)Function     VOID    unget(c)
307  *
308  *              int     c               value of last character
309  *                                      read from input text line
310  *
311  *      If (c) is not a NULL character then the global pointer ip
312  *      is updated to point to the preceeding character in the
313  *      input text line.
314  *
315  *      NOTE:   This function does not push the character (c)
316  *              back into the input text line, only
317  *              the pointer ip is changed.
318  *
319  *      local variables:
320  *              int     c               last character read
321  *                                      from input text line
322  *
323  *      global variables:
324  *              char *  ip              position into the current
325  *                                      input text line
326  *
327  *      called functions:
328  *              none
329  *
330  *      side effects:
331  *              ip decremented by 1 character position
332  */
333
334 VOID
335 unget(c)
336 {
337         if (c != 0)
338                 --ip;
339 }
340
341 /*)Function     int     getmap(d)
342  *
343  *              int     d               value to compare with the
344  *                                      input text line character
345  *
346  *      The function getmap() converts the 'C' style characters \b, \f,
347  *      \n, \r, and \t to their equivalent ascii values and also
348  *      converts 'C' style octal constants '\123' to their equivalent
349  *      numeric values.  If the first character is equivalent to (d) then
350  *      a (-1) is returned, if the end of the line is detected then
351  *      a 'q' error terminates the parse for this line, or if the first
352  *      character is not a \ then the character value is returned.
353  *
354  *      local variables:
355  *              int     c               value of character
356  *                                      from input text line
357  *              int     n               looping counter
358  *              int     v               current value of numeric conversion
359  *
360  *      global variables:
361  *              none
362  *
363  *      called functions:
364  *              char    get()           lklex.c
365  *              VOID    unget()         lklex.c
366  *
367  *      side effects:
368  *              use of get() updates the global pointer ip the position
369  *              in the current input text line
370  */
371
372 int
373 getmap(d)
374 {
375         register int c, n, v;
376
377         if ((c = get()) == '\0')
378                 return (-1);
379         if (c == d)
380                 return (-1);
381         if (c == '\\') {
382                 c = get();
383                 switch (c) {
384
385                 case 'b':
386                         c = '\b';
387                         break;
388
389                 case 'f':
390                         c = '\f';
391                         break;
392
393                 case 'n':
394                         c = '\n';
395                         break;
396
397                 case 'r':
398                         c = '\r';
399                         break;
400
401                 case 't':
402                         c = '\t';
403                         break;
404
405                 case '0':
406                 case '1':
407                 case '2':
408                 case '3':
409                 case '4':
410                 case '5':
411                 case '6':
412                 case '7':
413                         n = 0;
414                         v = 0;
415                         while (++n<=3 && c>='0' && c<='7') {
416                                 v = (v<<3) + c - '0';
417                                 c = get();
418                         }
419                         unget(c);
420                         c = v;
421                         break;
422                 }
423         }
424         return (c);
425 }
426
427 /*)Function     int     lk_getline()
428  *
429  *      The function lk_getline() reads a line of input text from a
430  *      .rel source text file, a .lnk command file or from stdin.
431  *      Lines of text are processed from a single .lnk file or
432  *      multiple .rel files until all files have been read.
433  *      The input text line is copied into the global string ib[]
434  *      and converted to a NULL terminated string.  The function
435  *      lk_getline() returns a (1) after succesfully reading a line
436  *      or a (0) if all files have been read.
437  *      This function also opens each input .lst file and output
438  *      .rst file as each .rel file is processed.
439  *
440  *      local variables:
441  *              int     i               string length
442  *              int     ftype           file type
443  *              char *  fid             file name
444  *
445  *      global variables:
446  *              lfile   *cfp            The pointer *cfp points to the
447  *                                      current lfile structure
448  *              lfile   *filep          The pointer *filep points to the
449  *                                      beginning of a linked list of
450  *                                      lfile structures.
451  *              int     gline           get a line from the LST file
452  *                                      to translate for the RST file
453  *              char    ib[NINPUT]      REL file text line
454  *              int     pass            linker pass number
455  *              int     pflag           print linker command file flag
456  *              FILE    *rfp            The file handle to the current
457  *                                      output RST file
458  *              FILE    *sfp            The file handle sfp points to the
459  *                                      currently open file
460  *              FILE *  stdin           c_library
461  *              FILE *  stdout          c_library
462  *              FILE    *tfp            The file handle to the current
463  *                                      LST file being scanned
464  *              int     uflag           update listing flag
465  *
466  *      called functions:
467  *              FILE *  afile()         lkmain.c
468  *              int     fclose()        c_library
469  *              char *  fgets()         c_library
470  *              int     fprintf()       c_library
471  *              VOID    lkulist()       lklist.c
472  *              VOID    lkexit()        lkmain.c
473  *              int     strlen()        c_library
474  *
475  *      side effects:
476  *              The input stream is scanned.  The .rel files will be
477  *              opened and closed sequentially scanning each in turn.
478  */
479
480 int
481 lk_getline()
482 {
483         register int ftype;
484         register char *fid;
485
486 loop:   if (pflag && cfp && cfp->f_type == F_STD)
487                 fprintf(stdout, "ASlink >> ");
488
489         if (sfp == NULL || fgets(ib, sizeof ib, sfp) == NULL) {
490                 if (sfp) {
491                         fclose(sfp);
492                         sfp = NULL;
493                         lkulist(0);
494                 }
495                 if (cfp == NULL) {
496                         cfp = filep;
497                 } else {
498                         cfp = cfp->f_flp;
499                 }
500                 if (cfp) {
501                         ftype = cfp->f_type;
502                         fid = cfp->f_idp;
503                         if (ftype == F_STD) {
504                                 sfp = stdin;
505                         } else
506                         if (ftype == F_LNK) {
507                                 sfp = afile(fid, "lnk", 0);
508                         } else
509                         if (ftype == F_REL) {
510                                 sfp = afile(fid, "rel", 0);
511                                 /* if a .cdb file exists then copy it over */
512                                 if (dflag && sfp && dfp && pass == 0) {
513                                     FILE *xfp = afile(fid,"adb",0); //JCF: Nov 30, 2002
514                                     if (xfp) {
515                                         copyfile(dfp,xfp);
516                                         fclose(xfp);
517                                     }
518                                 }
519                                 if (uflag && pass != 0) {
520                                  SaveLinkedFilePath(fid); //Save the linked path for aomf51
521                                  if ((tfp = afile(fid, "lst", 0)) != NULL) {
522                                   if ((rfp = afile(fid, "rst", 1)) == NULL) {
523                                         fclose(tfp);
524                                         tfp = NULL;
525                                   }
526                                  }
527                                 }
528                                 gline = 1;
529                         } else {
530                                 fprintf(stderr, "Invalid file type\n");
531                                 lkexit(1);
532                         }
533                         if (sfp == NULL) {
534                                 lkexit(1);
535                         }
536                         goto loop;
537                 } else {
538                         filep = NULL;
539                         return(0);
540                 }
541         }
542         chop_crlf(ib);
543         return (1);
544 }
545
546 /*)Function     int     more()
547  *
548  *      The function more() scans the input text line
549  *      skipping white space (SPACES and TABS) and returns a (0)
550  *      if the end of the line or a comment delimeter (;) is found,
551  *      or a (1) if their are additional characters in the line.
552  *
553  *      local variables:
554  *              int     c               next character from
555  *                                      the input text line
556  *
557  *      global variables:
558  *              none
559  *
560  *      called functions:
561  *              char    getnb()         lklex.c
562  *              VOID    unget()         lklex.c
563  *
564  *      side effects:
565  *              use of getnb() and unget() updates the global pointer ip
566  *              the position in the current input text line
567  */
568
569 int
570 more()
571 {
572         register int c;
573
574         c = getnb();
575         unget(c);
576         return( (c == '\0' || c == ';') ? 0 : 1 );
577 }
578
579 /*)Function     char    endline()
580  *
581  *      The function endline() scans the input text line
582  *      skipping white space (SPACES and TABS) and returns the next
583  *      character or a (0) if the end of the line is found or a
584  *      comment delimiter (;) is found.
585  *
586  *      local variables:
587  *              int     c               next character from
588  *                                      the input text line
589  *
590  *      global variables:
591  *              none
592  *
593  *      called functions:
594  *              char    getnb()         lklex.c
595  *
596  *      side effects:
597  *              Use of getnb() updates the global pointer ip the
598  *              position in the current input text line.
599  */
600
601 char
602 endline()
603 {
604         register int c;
605
606         c = getnb();
607         return( (c == '\0' || c == ';') ? 0 : c );
608 }
609
610 /*)Function     VOID    chop_crlf(str)
611  *
612  *              char    *str            string to chop
613  *
614  *      The function chop_crlf() removes trailing LF or CR/LF from
615  *      str, if present.
616  *
617  *      local variables:
618  *              int     i               string length
619  *
620  *      global variables:
621  *              none
622  *
623  *      functions called:
624  *              none
625  *
626  *      side effects:
627  *              none
628  */
629
630 VOID
631 chop_crlf(str)
632 char *str;
633 {
634         register int i;
635
636         i = strlen(str);
637         if (i >= 1 && str[i-1] == '\n') str[i-1] = 0;
638         if (i >= 2 && str[i-2] == '\r') str[i-2] = 0;
639 }