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