struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / sdas / linksrc / lklex.c
blobb9e270dbd8ee9c43bae7024960e68585cbe71f25
1 /* lklex.c */
3 /*
4 * Copyright (C) 1989-2009 Alan R. Baldwin
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * Alan R. Baldwin
21 * 721 Berkeley St.
22 * Kent, Ohio 44240
25 #include "aslink.h"
27 /*)Module lklex.c
29 * The module lklex.c contains the general lexical analysis
30 * functions used to scan the text lines from the .rel files.
32 * lklex.c contains the following functions:
33 * VOID chopcrlf()
34 * char endline()
35 * int get()
36 * VOID getfid()
37 * VOID getid()
38 * VOID getSid()
39 * int getmap()
40 * int getnb()
41 * int more()
42 * int nxtline()
43 * VOID skip()
44 * VOID unget()
46 * lklex.c contains no local variables.
49 /*)Function VOID getid(id,c)
51 * char * id a pointer to a string of
52 * maximum length NCPS-1
53 * int c mode flag
54 * >=0 this is first character to
55 * copy to the string buffer
56 * <0 skip white space
58 * The function getid() scans the current input text line
59 * from the current position copying the next LETTER | DIGIT string
60 * into the external string buffer (id). The string ends when a non
61 * LETTER or DIGIT character is found. The maximum number of characters
62 * copied is NCPS-1. If the input string is larger than NCPS-1
63 * characters then the string is truncated. The string is always
64 * NULL terminated. If the mode argument (c) is >=0 then (c) is
65 * the first character copied to the string buffer, if (c) is <0
66 * then intervening white space (SPACES and TABS) are skipped.
68 * local variables:
69 * char * p pointer to external string buffer
70 * int c current character value
72 * global variables:
73 * char ctype[] a character array which defines the
74 * type of character being processed.
75 * This index is the character
76 * being processed.
78 * called functions:
79 * int get() lklex.c
80 * int getnb() lklex.c
81 * VOID unget() lklex.c
83 * side effects:
84 * use of getnb(), get(), and unget() updates the
85 * global pointer ip the position in the current
86 * input text line.
89 VOID
90 getid(char *id, int c)
92 char *p;
94 if (c < 0) {
95 c = getnb();
97 p = id;
98 do {
99 if (p < &id[NCPS-1])
100 *p++ = c;
101 } while (ctype[c=get()] & (LETTER|DIGIT));
102 unget(c);
103 *p++ = 0;
106 /*)Function VOID getSid (char *id)
108 * char * id a pointer to a string of
109 * maximum length NCPS-1
111 * getSid is derived from getid. It is called from newsym()
112 * in lksym.c, when an S-record has to be scanned. getSid accepts
113 * much more characters than getid, which is necessary for SDCC.
115 * The function getSid() scans the current input text line
116 * from the current position copying the next string
117 * into the external string buffer (id). The string ends when a space
118 * character (space, tab, \0) is found. The maximum number of
119 * characters copied is NCPS. If the input string is larger than
120 * NCPS characters then the string is truncated, if the input string
121 * is shorter than NCPS characters then the string is NULL filled.
122 * Intervening white space (SPACES and TABS) are skipped.
124 * local variables:
125 * char * p pointer to external string buffer
126 * int c current character value
128 * global variables:
129 * none
131 * called functions:
132 * int get() lklex.c
133 * int getnb() lklex.c
134 * VOID unget() lklex.c
136 * side effects:
137 * use of getnb(), get(), and unget() updates the
138 * global pointer ip the position in the current
139 * input text line.
142 VOID
143 getSid (char *id)
145 int c;
146 char *p;
148 c = getnb();
149 p = id;
150 do {
151 if (p < &id[NCPS-1])
152 *p++ = c;
153 c = get();
154 } while (c != '\0' && c != ' ' && c != '\t');
155 unget(c);
156 *p++ = 0;
159 /*)Function VOID getfid(str,c)
161 * char * str a pointer to a string of
162 * maximum length FILSPC-1
163 * int c this is first character to
164 * copy to the string buffer
166 * asxxxx version:
168 * The function getfid() copies a string of characters from
169 * the current text line into the external string buffer (str).
170 * The maximum number of characters copied is FILSPC-1. The
171 * string is terminated by a 'space', 'tab' or end of string.
173 * sdld version:
175 * The function getfid() scans the current input text line from
176 * the current position copying the next string into the external
177 * string buffer (str). The string ends when end of line is found.
178 * Trailing spaces are removed. The maximum number of characters
179 * copied is FILSPC-1. If the input string is larger than FILSPC-1
180 * characters then the string is truncated. The string is NULL
181 * terminated.
183 * local variables:
184 * char * p pointer to external string buffer
185 * int c current character value
187 * global variables:
188 * char ctype[] a character array which defines the
189 * type of character being processed.
190 * This index is the character
191 * being processed.
193 * called functions:
194 * int get() lklex.c
196 * side effects:
197 * use of get() updates the global pointer ip
198 * the position in the current input text line.
201 VOID
202 getfid(char *str, int c)
204 char *p;
206 p = str;
207 if (!is_sdld()) {
208 do {
209 if (p < &str[FILSPC-1])
210 *p++ = c;
211 c = get();
212 } while ((c != 0) && (c != ' ') && (c != '\t'));
213 *p++ = 0;
215 else {
216 do {
217 if (p < &str[FILSPC-1])
218 *p++ = c;
219 c = get();
220 /* skip comment */
221 if (c == ';')
222 while (c)
223 c = get();
224 } while (c);
225 /* trim trailing spaces */
226 --p;
227 while (p >= str && ctype[*p & 0x00FF] == SPACE)
228 --p;
229 /* terminate the string */
230 *(++p) = '\0';
234 /*)Function int getnb()
236 * The function getnb() scans the current input text
237 * line returning the first character not a SPACE or TAB.
239 * local variables:
240 * int c current character from input
242 * global variables:
243 * none
245 * called functions:
246 * int get() lklex.c
248 * side effects:
249 * use of get() updates the global pointer ip, the position
250 * in the current input text line
254 getnb()
256 int c;
258 while ((c=get())==' ' || c=='\t')
260 return (c);
263 /*)Function VOID skip(c)
265 * The function skip() scans the input text skipping all
266 * letters and digits.
268 * local variables:
269 * int c last character read
270 * none
272 * global variables:
273 * char ctype[] array of character types, one per
274 * ASCII character
276 * functions called:
277 * int get() lklex.c
278 * int getnb() lklex.c
279 * VOID unget() lklex.c
281 * side effects:
282 * Input letters and digits are skipped.
285 VOID
286 skip(c)
287 int c;
289 if (c < 0)
290 c = getnb();
291 while (ctype[c=get()] & (LETTER|DIGIT)) { ; }
292 unget(c);
295 /*)Function int get()
297 * The function get() returns the next character in the
298 * input text line, at the end of the line a
299 * NULL character is returned.
301 * local variables:
302 * int c current character from
303 * input text line
305 * global variables:
306 * char * ip pointer into the current
307 * input text line
309 * called functions:
310 * none
312 * side effects:
313 * updates ip to the next character position in the
314 * input text line. If ip is at the end of the
315 * line, ip is not updated.
319 get()
321 int c;
323 if ((c = *ip) != 0)
324 ++ip;
325 return (c & 0x00FF);
328 /*)Function VOID unget(c)
330 * int c value of last character
331 * read from input text line
333 * If (c) is not a NULL character then the global pointer ip
334 * is updated to point to the preceeding character in the
335 * input text line.
337 * NOTE: This function does not push the character (c)
338 * back into the input text line, only
339 * the pointer ip is changed.
341 * local variables:
342 * int c last character read
343 * from input text line
345 * global variables:
346 * char * ip position into the current
347 * input text line
349 * called functions:
350 * none
352 * side effects:
353 * ip decremented by 1 character position
356 VOID
357 unget(c)
358 int c;
360 if (c != 0)
361 --ip;
364 /*)Function int getmap(d)
366 * int d value to compare with the
367 * input text line character
369 * The function getmap() converts the 'C' style characters \b, \f,
370 * \n, \r, and \t to their equivalent ascii values and also
371 * converts 'C' style octal constants '\123' to their equivalent
372 * numeric values. If the first character is equivalent to (d) then
373 * a (-1) is returned, if the end of the line is detected then
374 * a 'q' error terminates the parse for this line, or if the first
375 * character is not a \ then the character value is returned.
377 * local variables:
378 * int c value of character
379 * from input text line
380 * int n looping counter
381 * int v current value of numeric conversion
383 * global variables:
384 * none
386 * called functions:
387 * int get() lklex.c
388 * VOID unget() lklex.c
390 * side effects:
391 * use of get() updates the global pointer ip the position
392 * in the current input text line
396 getmap(d)
397 int d;
399 int c, n, v;
401 if ((c = get()) == '\0')
402 return (-1);
403 if (c == d)
404 return (-1);
405 if (c == '\\') {
406 c = get();
407 switch (c) {
409 case 'b':
410 c = '\b';
411 break;
413 case 'f':
414 c = '\f';
415 break;
417 case 'n':
418 c = '\n';
419 break;
421 case 'r':
422 c = '\r';
423 break;
425 case 't':
426 c = '\t';
427 break;
429 case '0':
430 case '1':
431 case '2':
432 case '3':
433 case '4':
434 case '5':
435 case '6':
436 case '7':
437 n = 0;
438 v = 0;
439 while (++n<=3 && c>='0' && c<='7') {
440 v = (v<<3) + c - '0';
441 c = get();
443 unget(c);
444 c = v;
445 break;
448 return (c);
451 /*)Function int nxtline()
453 * The function nxtline() reads a line of input text from a
454 * .rel source text file, a .lnk command file or from stdin.
455 * Lines of text are processed from a single .lnk file or
456 * multiple .rel files until all files have been read.
457 * The input text line is copied into the global string ib[]
458 * and converted to a NULL terminated string. The function
459 * nxtline() returns a (1) after succesfully reading a line
460 * or a (0) if all files have been read.
461 * This function also opens each input .lst file and output
462 * .rst file as each .rel file is processed.
464 * local variables:
465 * int ftype file type
466 * char * fid file name
468 * global variables:
469 * lfile *cfp The pointer *cfp points to the
470 * current lfile structure
471 * lfile *filep The pointer *filep points to the
472 * beginning of a linked list of
473 * lfile structures.
474 * int gline get a line from the LST file
475 * to translate for the RST file
476 * char ib[NINPUT] REL file text line
477 * int pass linker pass number
478 * int pflag print linker command file flag
479 * FILE *rfp The file handle to the current
480 * output RST file
481 * FILE *sfp The file handle sfp points to the
482 * currently open file
483 * FILE * stdin c_library
484 * FILE * stdout c_library
485 * FILE *tfp The file handle to the current
486 * LST file being scanned
487 * int uflag update listing flag
488 * int obj_flag linked file/library object output flag
490 * called functions:
491 * VOID chopcrlf() lklex.c
492 * FILE * afile() lkmain.c
493 * int fclose() c_library
494 * char * fgets() c_library
495 * int fprintf() c_library
496 * VOID lkulist() lklist.c
497 * VOID lkexit() lkmain.c
499 * side effects:
500 * The input stream is scanned. The .rel files will be
501 * opened and closed sequentially scanning each in turn.
505 nxtline()
507 int ftype;
508 char *fid;
510 loop: if (pflag && cfp && cfp->f_type == F_STD)
511 fprintf(stdout, "ASlink >> ");
513 if (sfp == NULL || fgets(ib, sizeof(ib), sfp) == NULL) {
514 obj_flag = 0;
515 if (sfp) {
516 if(sfp != stdin) {
517 fclose(sfp);
519 sfp = NULL;
520 lkulist(0);
522 if (cfp == NULL) {
523 cfp = filep;
524 } else {
525 cfp = cfp->f_flp;
527 if (cfp) {
528 ftype = cfp->f_type;
529 fid = cfp->f_idp;
530 if (ftype == F_STD) {
531 sfp = stdin;
532 } else
533 if (ftype == F_LNK) {
534 sfp = afile(fid, strrchr(fid, FSEPX) ? "" : "lnk", 0);
535 } else
536 if (ftype == F_REL) {
537 obj_flag = cfp->f_obj;
538 sfp = afile(fid, "", 0);
539 if (sfp && (obj_flag == 0)) {
540 if (uflag && (pass != 0)) {
541 if (is_sdld())
542 SaveLinkedFilePath(fid); //Save the linked path for aomf51
543 if ((tfp = afile(fid, "lst", 0)) != NULL) {
544 if ((rfp = afile(fid, "rst", 1)) == NULL) {
545 fclose(tfp);
546 tfp = NULL;
552 #if SDCDB
553 if (sfp && (pass == 0)) {
554 SDCDBcopy(fid);
556 #endif
558 gline = 1;
559 } else {
560 fprintf(stderr, "Invalid file type\n");
561 lkexit(ER_FATAL);
563 if (sfp == NULL) {
564 lkexit(ER_FATAL);
566 goto loop;
567 } else {
568 filep = NULL;
569 return(0);
572 chopcrlf(ib);
573 return (1);
576 /*)Function int more()
578 * The function more() scans the input text line
579 * skipping white space (SPACES and TABS) and returns a (0)
580 * if the end of the line or a comment delimeter (;) is found,
581 * or a (1) if their are additional characters in the line.
583 * local variables:
584 * int c next character from
585 * the input text line
587 * global variables:
588 * none
590 * called functions:
591 * int getnb() lklex.c
592 * VOID unget() lklex.c
594 * side effects:
595 * use of getnb() and unget() updates the global pointer ip
596 * the position in the current input text line
599 static int isHex(int c)
601 if ('0' <= c && c <= '9')
602 return 1;
603 else if ('A' <= c && c <= 'F')
604 return 1;
605 else if ('a' <= c && c <= 'f')
606 return 1;
607 else
608 return 0;
612 more()
614 int c;
616 c = getnb();
617 if (c != '\0' && c != ';' && !isHex (c))
618 lkexit (ER_FATAL);
619 unget(c);
620 return( (c == '\0' || c == ';') ? 0 : 1 );
623 /*)Function char endline()
625 * The function endline() scans the input text line
626 * skipping white space (SPACES and TABS) and returns the next
627 * character or a (0) if the end of the line is found or a
628 * comment delimiter (;) is found.
630 * local variables:
631 * int c next character from
632 * the input text line
634 * global variables:
635 * none
637 * called functions:
638 * int getnb() lklex.c
640 * side effects:
641 * Use of getnb() updates the global pointer ip the
642 * position in the current input text line.
645 char
646 endline()
648 int c;
650 c = getnb();
651 return( (c == '\0' || c == ';') ? 0 : c );
654 /*)Function VOID chopcrlf(str)
656 * char *str string to chop
658 * The function chop_crlf() removes trailing LF or CR/LF from
659 * str, if present.
661 * local variables:
662 * int i string length
664 * global variables:
665 * none
667 * functions called:
668 * none
670 * side effects:
671 * none
674 VOID
675 chopcrlf(str)
676 char *str;
678 int i;
680 i = strlen(str);
681 if (i >= 1 && str[i-1] == '\n') str[i-1] = 0;
682 if (i >= 2 && str[i-2] == '\r') str[i-2] = 0;