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