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