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