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