struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / sdas / linksrc / lkmain.c
blob0f002447eb60052fa26a3e23ca3e42047ace1c49
1 /* lkmain.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 lkmain.c
29 * The module lkmain.c contains the functions which
30 * (1) input the linker options, parameters, and specifications
31 * (2) perform a two pass link
32 * (3) produce the appropriate linked data output and/or
33 * link map file and/or relocated listing files.
35 * lkmain.c contains the following functions:
36 * FILE * afile()
37 * VOID bassav()
38 * VOID gblsav()
39 * int intsiz()
40 * VOID link_main()
41 * VOID lkexit()
42 * int fndext()
43 * int fndidx()
44 * int main()
45 * VOID map()
46 * int parse()
47 * VOID doparse()
48 * VOID setgbl()
49 * VOID usage()
51 * lkmain.c contains the following local variables:
52 * char * usetext[] array of pointers to the
53 * command option tect lines
57 /* sdld 8051 specific */
58 /*JCF: Creates some of the default areas so they are allocated in the right order.*/
59 void Areas51 (void)
61 char * rel[] = {
62 "XH",
63 "H C areas 0 global symbols",
64 "A _CODE size 0 flags 0", /*Each .rel has one, so...*/
65 "A REG_BANK_0 size 0 flags 4", /*Register banks are overlayable*/
66 "A REG_BANK_1 size 0 flags 4",
67 "A REG_BANK_2 size 0 flags 4",
68 "A REG_BANK_3 size 0 flags 4",
69 "A BSEG size 0 flags 80", /*BSEG must be just before BITS*/
70 "A BSEG_BYTES size 0 flags 0", /*Size will be obtained from BSEG in lnkarea()*/
71 "A BIT_BANK size 0 flags 4", /*Bit register bank is overlayable*/
72 "A DSEG size 0 flags 0",
73 "A OSEG size 0 flags 4",
74 "A ISEG size 0 flags 0",
75 "A SSEG size 0 flags 4",
78 int j;
79 struct sym * sp;
81 for (j = 0; rel[j][0] != 0; j++) {
82 ip = rel[j];
83 link_main();
86 /*Set the start address of the default areas:*/
87 for (ap = areap; ap; ap = ap->a_ap) {
88 /**/ if (!strcmp(ap->a_id, "REG_BANK_0")) { ap->a_addr = 0x00; ap->a_bset = 1; }
89 else if (!strcmp(ap->a_id, "REG_BANK_1")) { ap->a_addr = 0x08; ap->a_bset = 1; }
90 else if (!strcmp(ap->a_id, "REG_BANK_2")) { ap->a_addr = 0x10; ap->a_bset = 1; }
91 else if (!strcmp(ap->a_id, "REG_BANK_3")) { ap->a_addr = 0x18; ap->a_bset = 1; }
92 else if (!strcmp(ap->a_id, "BSEG_BYTES")) { ap->a_addr = 0x20; ap->a_bset = 1; }
93 else if (TARGET_IS_8051 && !strcmp(ap->a_id, "SSEG")) {
94 if (stacksize) ap->a_axp->a_size = stacksize;
98 sp = lkpsym("l_IRAM", 1);
99 sp->s_addr = ((iram_size>0) && (iram_size<=0x100)) ? iram_size : 0x0100;
100 sp->s_axp = NULL;
101 sp->s_type |= S_DEF;
103 /* end sdld 8051 specific */
105 /*)Function int main(argc,argv)
107 * int argc number of command line arguments + 1
108 * char * argv[] array of pointers to the command line
109 * arguments
111 * The function main() evaluates the command line arguments to
112 * determine if the linker parameters are to input through 'stdin'
113 * or read from a command file. The functions nxtline() and parse()
114 * are to input and evaluate the linker parameters. The linking process
115 * proceeds by making the first pass through each .rel file in the order
116 * presented to the linker. At the end of the first pass the setarea(),
117 * lnkarea(), setgbl(), and symdef() functions are called to evaluate
118 * the base address terms, link all areas, define global variables,
119 * and look for undefined symbols. Following these routines a linker
120 * map file may be produced and the linker output files may be opened.
121 * The second pass through the .rel files will output the linked data
122 * in one of the supported formats.
124 * local variables:
125 * int c character from argument string
126 * int i loop counter
127 * int j loop counter
128 * int k loop counter
130 * global variables:
131 * text line in ib[]
132 * lfile *cfp The pointer *cfp points to the
133 * current lfile structure
134 * char ctype[] array of character types, one per
135 * ASCII character
136 * lfile *filep The pointer *filep points to the
137 * beginning of a linked list of
138 * lfile structures.
139 * head *hp Pointer to the current
140 * head structure
141 * char ib[NINPUT] .rel file text line
142 * char *ip pointer into the .rel file
143 * lfile *linkp pointer to first lfile structure
144 * containing an input .rel file
145 * specification
146 * int lkerr error flag
147 * int oflag Output file type flag
148 * int objflg Linked file/library output object flag
149 * int pass linker pass number
150 * int pflag print linker command file flag
151 * int radix current number conversion radix
152 * FILE *sfp The file handle sfp points to the
153 * currently open file
154 * lfile *startp aslink startup file structure
155 * FILE * stdout c_library
157 * functions called:
158 * VOID chkbank() lkbank.c
159 * int fclose() c_library
160 * int fprintf() c_library
161 * VOID library() lklibr.c
162 * VOID link_main() lkmain.c
163 * VOID lkexit() lkmain.c
164 * VOID lkfopen() lkbank.c
165 * VOID lnkarea() lkarea.c
166 * VOID map() lkmain.c
167 * VOID new() lksym.c
168 * int nxtline() lklex.c
169 * int parse() lkmain.c
170 * VOID reloc() lkreloc.c
171 * VOID search() lklibr.c
172 * VOID setarea() lkarea.c
173 * VOID setbank() lkbank.c
174 * VOID setgbl() lkmain.c
175 * char * sprintf() c_library
176 * VOID symdef() lksym.c
177 * VOID usage() lkmain.c
178 * int fndidx() lkmain.c
180 * side effects:
181 * Completion of main() completes the linking process
182 * and may produce a map file (.map) and/or a linked
183 * data files (.ihx or .s19) and/or one or more
184 * relocated listing files (.rst).
188 main(int argc, char *argv[])
190 int c, i, j, k;
192 if (intsiz() < 4) {
193 fprintf(stderr, "?ASlink-Error-Size of INT32 is not 32 bits or larger.\n\n");
194 exit(ER_FATAL);
197 /* sdas specific */
198 /* sdas initialization */
199 sdld_init(argv[0]);
201 /* use these defaults for parsing the .lnk script */
202 a_bytes = 4;
203 a_mask = 0xFFFFFFFF;
204 s_mask = 0x80000000;
205 v_mask = 0x7FFFFFFF;
206 /* end sdas specific */
208 if (!is_sdld())
209 fprintf(stdout, "\n");
211 startp = (struct lfile *) new (sizeof (struct lfile));
212 startp->f_idp = "";
214 pflag = 1;
216 for(i=1; i<argc; i++) {
217 ip = ib;
218 if(argv[i][0] == '-') {
219 j = i;
220 k = 1;
221 while((c = argv[j][k]) != '\0') {
222 ip = ib;
223 sprintf(ip, "-%c", c);
224 switch(c) {
227 * Options with arguments
229 case 'b':
230 case 'B':
232 case 'g':
233 case 'G':
235 case 'k':
236 case 'K':
238 case 'l':
239 case 'L':
241 case 'f':
242 case 'F':
244 case 'I':
245 case 'X':
246 case 'C':
247 case 'S':
248 strcat(ip, " ");
249 if (i < argc - 1)
250 strcat(ip, argv[++i]);
251 else
252 strcpy(ip, "");
253 break;
255 * Preprocess these commands
257 case 'n':
258 case 'N':
259 pflag = 0;
260 break;
262 case 'p':
263 case 'P':
264 pflag = 1;
265 break;
268 * Options without arguments
270 default:
271 break;
273 if(pflag)
274 fprintf(stdout, "ASlink >> %s\n", ip);
275 parse();
276 k++;
278 } else {
279 strcpy(ip, argv[i]);
280 if(pflag)
281 fprintf(stdout, "ASlink >> %s\n", ip);
282 parse();
286 if (linkp == NULL)
287 usage(ER_FATAL);
290 * If no input file is specified
291 * then assume a single file with
292 * the same name as the output file.
294 if (lfp == linkp) {
295 lfp->f_flp = (struct lfile *) new (sizeof (struct lfile));
296 lfp = lfp->f_flp;
297 lfp->f_idp = strsto(linkp->f_idp);
298 lfp->f_idx = fndidx(linkp->f_idp);
299 lfp->f_obj = objflg;
300 lfp->f_type = F_REL;
303 syminit();
305 #if SDCDB
307 * Open SDCC Debug output file
309 SDCDBfopen();
310 #endif
312 for (pass=0; pass<2; ++pass) {
313 cfp = NULL;
314 sfp = NULL;
315 filep = linkp->f_flp;
316 hp = NULL;
317 radix = 10;
319 /* sdld specific */
320 if (TARGET_IS_8051)
321 Areas51(); /*JCF: Create the default 8051 areas in the right order*/
322 /* end sdld specific */
324 while (nxtline()) {
325 ip = ib;
326 link_main();
328 if (pass == 0) {
330 * Search libraries for global symbols
332 search();
334 /* sdas specific */
335 /* use these defaults for parsing the .lk script */
336 a_bytes = 4;
337 a_mask = 0xFFFFFFFF;
338 s_mask = 0x80000000;
339 v_mask = 0x7FFFFFFF;
340 /* end sdas specific */
343 * Set area base addresses.
345 setarea();
347 * Set bank base addresses.
349 setbank();
351 * Link all area addresses.
353 /* sdld 8051 specific */
354 if (is_sdld_target_8051_like())
355 lnkarea2();
356 else
357 /* end sdld 8051 specific */
358 lnkarea();
360 * Check bank size limits.
362 chkbank(stderr);
364 * Process global definitions.
366 setgbl();
368 * Check for undefined globals.
370 symdef(stderr);
371 #if NOICE
373 * Open NoICE output file
375 NoICEfopen();
376 #endif
378 * Output Link Map.
380 map();
382 /* sdld specific */
383 if (sflag) { /*JCF: memory usage summary output*/
384 if (is_sdld_target_8051_like()) {
385 if (summary2(areap)) {
386 lkexit(1);
389 else {
390 if (summary(areap)) {
391 lkexit(1);
396 if ((iram_size) && (!is_sdld_target_8051_like()))
397 iramcheck();
399 /* end sdld specific */
402 * Open output file(s)
404 lkfopen();
405 } else {
407 * Link in library files
409 library();
411 * Complete Processing
413 reloc('E');
417 if (TARGET_IS_PDK && get_sdld_target() != TARGET_ID_PDK) {
418 unsigned ram = 0;
419 unsigned rom = 0;
420 for (struct area *it = areap; it; it = it->a_ap) {
421 if (!strcmp(it->a_id, "DATA") ||
422 !strcmp(it->a_id, "OSEG")) {
423 if (it->a_addr + it->a_size > ram) {
424 ram = it->a_addr + it->a_size;
426 } else if (!strcmp(it->a_id, "CODE") ||
427 !strcmp(it->a_id, "CONST")) {
428 if (it->a_addr + it->a_size > rom) {
429 rom = it->a_addr + it->a_size;
434 enum sdld_target_e target = get_sdld_target();
435 const unsigned max_ram =
436 target == TARGET_ID_PDK13 ? 64 :
437 target == TARGET_ID_PDK14 ? 128 : 256;
438 const unsigned max_rom =
439 target == TARGET_ID_PDK13 ? 2048 :
440 target == TARGET_ID_PDK14 ? 4096 : 8192;
441 if (ram > max_ram) {
442 fprintf(stderr,
443 "?ASlink-Warning-"
444 "RAM value %u too large "
445 "(%uB max)\n", ram, max_ram);
447 if (rom > max_rom) {
448 fprintf(stderr,
449 "?ASlink-Warning-"
450 "ROM value %u too large "
451 "(%uW max)\n", rom / 2, max_rom / 2);
454 if (TARGET_IS_8051) {
455 //JCF:
456 CreateAOMF51();
459 lkexit(lkerr ? ER_ERROR : ER_NONE);
460 return(0);
463 /*)Function int intsiz()
465 * The function intsiz() returns the size of INT32
467 * local variables:
468 * none
470 * global variables:
471 * none
473 * functions called:
474 * none
476 * side effects:
477 * none
481 intsiz()
483 return(sizeof(a_uint));
486 /*)Function VOID lkexit(i)
488 * int i exit code
490 * The function lkexit() explicitly closes all open
491 * files and then terminates the program.
493 * local variables:
494 * none
496 * global variables:
497 * FILE * jfp file handle for .noi
498 * FILE * mfp file handle for .map
499 * FILE * rfp file hanlde for .rst
500 * FILE * sfp file handle for .rel
501 * FILE * tfp file handle for .lst
503 * functions called:
504 * int fclose() c_library
505 * VOID exit() c_library
506 * VOID lkfclose() lkbank.c
508 * side effects:
509 * All files closed. Program terminates.
512 VOID
513 lkexit(i)
514 int i;
516 lkfclose();
517 #if NOICE
518 if (jfp != NULL) fclose(jfp);
519 #endif
520 if (mfp != NULL) fclose(mfp);
521 if (rfp != NULL) fclose(rfp);
522 if (sfp != NULL) { if (sfp != stdin) fclose(sfp); }
523 if (tfp != NULL) fclose(tfp);
524 #if SDCDB
525 if (yfp != NULL) fclose(yfp);
526 #endif
527 exit(i);
530 /*)Function link_main()
532 * The function link_main() evaluates the directives for each line of
533 * text read from the .rel file(s). The valid directives processed
534 * are:
535 * X, D, Q, H, M, A, S, T, R, and P.
537 * local variables:
538 * int c first non blank character of a line
540 * global variables:
541 * head *headp The pointer to the first
542 * head structure of a linked list
543 * head *hp Pointer to the current
544 * head structure
545 * int a_bytes T Line address bytes
546 * int hilo Byte ordering
547 * int pass linker pass number
548 * int radix current number conversion radix
550 * functions called:
551 * char endline() lklex.c
552 * VOID module() lkhead.c
553 * VOID newarea() lkarea.c
554 * VOID newhead() lkhead.c
555 * sym * newsym() lksym.c
556 * VOID NoICEmagic() lknoice.c
557 * VOID reloc() lkreloc.c
559 * side effects:
560 * Head, area, and symbol structures are created and
561 * the radix is set as the .rel file(s) are read.
564 VOID
565 link_main()
567 char c;
569 if ((c=endline()) == 0) { return; }
570 switch (c) {
572 /* sdld specific */
573 case 'O': /* For some important sdcc options */
574 if (is_sdld() && pass == 0) {
575 if (NULL == optsdcc) {
576 optsdcc = strsto(&ip[1]);
577 optsdcc_module = hp->m_id;
579 else {
580 if (strcmp(optsdcc, &ip[1]) != 0) {
581 fprintf(stderr,
582 "?ASlink-Warning-Conflicting sdcc options:\n"
583 " \"%s\" in module \"%s\" and\n"
584 " \"%s\" in module \"%s\".\n",
585 optsdcc, optsdcc_module, &ip[1], hp->m_id);
586 lkerr++;
590 break;
591 /* end sdld specific */
593 case 'X':
594 case 'D':
595 case 'Q':
596 ASxxxx_VERSION = 3;
597 a_bytes = 2; /* use default if unspecified */
598 hilo = 0; /* use default if unspecified */
599 if (c == 'X') { radix = 16; } else
600 if (c == 'D') { radix = 10; } else
601 if (c == 'Q') { radix = 8; }
603 while ((c = get()) != 0) {
604 switch(c) {
605 case 'H':
606 hilo = 1;
607 break;
609 case 'L':
610 hilo = 0;
611 break;
613 case '2':
614 a_bytes = 2;
615 break;
617 case '3':
618 a_bytes = 3;
619 break;
621 case '4':
622 a_bytes = 4;
623 break;
625 default:
626 break;
629 #ifdef LONGINT
630 switch(a_bytes) {
631 default:
632 a_bytes = 2;
633 case 2:
634 a_mask = 0x0000FFFFl;
635 s_mask = 0x00008000l;
636 v_mask = 0x00007FFFl;
637 break;
639 case 3:
640 a_mask = 0x00FFFFFFl;
641 s_mask = 0x00800000l;
642 v_mask = 0x007FFFFFl;
643 break;
645 case 4:
646 a_mask = 0xFFFFFFFFl;
647 s_mask = 0x80000000l;
648 v_mask = 0x7FFFFFFFl;
649 break;
651 #else
652 switch(a_bytes) {
653 default:
654 a_bytes = 2;
655 case 2:
656 a_mask = 0x0000FFFF;
657 s_mask = 0x00008000;
658 v_mask = 0x00007FFF;
659 break;
661 case 3:
662 a_mask = 0x00FFFFFF;
663 s_mask = 0x00800000;
664 v_mask = 0x007FFFFF;
665 break;
667 case 4:
668 a_mask = 0xFFFFFFFF;
669 s_mask = 0x80000000;
670 v_mask = 0x7FFFFFFF;
671 break;
673 #endif
674 break;
676 case 'H':
677 if (pass == 0) {
678 newhead();
679 } else {
680 if (hp == 0) {
681 hp = headp;
682 } else {
683 hp = hp->h_hp;
686 sdp.s_area = NULL;
687 sdp.s_areax = NULL;
688 sdp.s_addr = 0;
689 break;
691 case 'M':
692 if (pass == 0)
693 module();
694 break;
696 case 'A':
697 if (pass == 0)
698 newarea();
699 if (sdp.s_area == NULL) {
700 sdp.s_area = areap;
701 sdp.s_areax = areap->a_axp;
702 sdp.s_addr = 0;
704 break;
706 case 'S':
707 if (pass == 0)
708 newsym();
709 break;
711 case 'T':
712 case 'R':
713 case 'P':
714 if (pass == 0)
715 break;
716 reloc(c);
717 break;
719 #if NOICE
720 case ';':
721 unget(c);
722 NoICEmagic();
723 break;
724 #endif
726 default:
727 break;
731 /*)Function VOID map()
733 * The function map() opens the output map file and calls the various
734 * routines to
735 * (1) output the variables in each area,
736 * (2) list the files processed with module names,
737 * (3) list the libraries file processed,
738 * (4) list base address definitions,
739 * (5) list global variable definitions, and
740 * (6) list any undefined variables.
742 * local variables:
743 * int i counter
744 * head * hdp pointer to head structure
745 * lbfile *lbfh pointer to library file structure
747 * global variables:
748 * area *ap Pointer to the current
749 * area structure
750 * area *areap The pointer to the first
751 * area structure of a linked list
752 * base *basep The pointer to the first
753 * base structure
754 * base *bsp Pointer to the current
755 * base structure
756 * lfile *filep The pointer *filep points to the
757 * beginning of a linked list of
758 * lfile structures.
759 * globl *globlp The pointer to the first
760 * globl structure
761 * globl *gsp Pointer to the current
762 * globl structure
763 * head *headp The pointer to the first
764 * head structure of a linked list
765 * lbfile *lbfhead The pointer to the first
766 * lbfile structure of a linked list
767 * lfile *linkp pointer to first lfile structure
768 * containing an input REL file
769 * specification
770 * int lop current line number on page
771 * int mflag Map output flag
772 * FILE *mfp Map output file handle
773 * int page current page number
775 * functions called:
776 * FILE * afile() lkmain.c
777 * int fprintf() c_library
778 * VOID lkexit() lkmain.c
779 * VOID lstarea() lklist.c
780 * VOID newpag() lklist.c
781 * VOID chkbank() lkbank.c
782 * VOID symdef() lksym.c
784 * side effects:
785 * The map file is created.
788 VOID
789 map(void)
791 int i;
792 struct head *hdp;
793 struct lbfile *lbfh;
795 if (mflag == 0) return;
798 * Open Map File
800 mfp = afile(linkp->f_idp, "map", 1);
801 if (mfp == NULL) {
802 lkexit(ER_FATAL);
806 * Output Map Bank/Area Lists
808 page = 0;
809 lop = NLPP;
810 for (bp = bankp; bp != NULL; bp = bp->b_bp) {
811 for (ap = areap; ap != NULL; ap = ap->a_ap) {
812 if (ap->a_bp == bp)
813 lstarea(ap, bp);
818 * List Linked Files
820 newpag(mfp);
821 fprintf(mfp, "\nFiles Linked [ module(s) ]\n\n");
822 hdp = headp;
823 filep = linkp->f_flp;
824 while (filep) {
825 if (strlen (filep->f_idp) > 40)
826 fprintf(mfp, "%s\n%40s [ ", filep->f_idp, "");
827 else
828 fprintf(mfp, "%-40.40s [ ", filep->f_idp);
829 i = 0;
830 while ((hdp != NULL) && (hdp->h_lfile == filep)) {
831 if (i)
832 fprintf(mfp, ",\n%44s", "");
833 fprintf(mfp, "%-.32s", hdp->m_id);
834 hdp = hdp->h_hp;
835 i++;
837 fprintf(mfp, " ]\n");
838 filep = filep->f_flp;
840 fprintf(mfp, "\n");
842 * List Linked Libraries
844 if (lbfhead != NULL) {
845 fprintf(mfp, "\nLibraries Linked [ object file ]\n\n");
846 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
847 if (strlen (lbfh->libspc) > 40)
848 fprintf(mfp, "%s\n%40s [ %-.32s ]\n",
849 lbfh->libspc, "", lbfh->relfil);
850 else
851 fprintf(mfp, "%-40.40s [ %-.32s ]\n",
852 lbfh->libspc, lbfh->relfil);
854 fprintf(mfp, "\n");
857 * List Base Address Definitions
859 if (basep) {
860 newpag(mfp);
861 fprintf(mfp, "\nUser Base Address Definitions\n\n");
862 bsp = basep;
863 while (bsp) {
864 fprintf(mfp, "%s\n", bsp->b_strp);
865 bsp = bsp->b_base;
869 * List Global Definitions
871 if (globlp) {
872 newpag(mfp);
873 fprintf(mfp, "\nUser Global Definitions\n\n");
874 gsp = globlp;
875 while (gsp) {
876 fprintf(mfp, "%s\n", gsp->g_strp);
877 gsp = gsp->g_globl;
880 fprintf(mfp, "\n\f");
881 chkbank(mfp);
882 symdef(mfp);
885 /*)Function int parse()
887 * The function parse() evaluates all command line or file input
888 * linker directives and updates the appropriate variables.
890 * local variables:
891 * int c character value
892 * int sv_type save type of processing
893 * char fid[] file id string
895 * global variables:
896 * char ctype[] array of character types, one per
897 * ASCII character
898 * lfile *lfp pointer to current lfile structure
899 * being processed by parse()
900 * lfile *linkp pointer to first lfile structure
901 * containing an input REL file
902 * specification
903 * int mflag Map output flag
904 * int oflag Output file type flag
905 * int objflg Linked file/library output object flag
906 * int pflag print linker command file flag
907 * FILE * stderr c_library
908 * int uflag Relocated listing flag
909 * int xflag Map file radix type flag
910 * int wflag Wide listing format
911 * int zflag Disable symbol case sensitivity
913 * Functions called:
914 * VOID addlib() lklibr.c
915 * VOID addpath() lklibr.c
916 * VOID bassav() lkmain.c
917 * VOID doparse() lkmain.c
918 * int fprintf() c_library
919 * VOID gblsav() lkmain.c
920 * VOID getfid() lklex.c
921 * int get() lklex.c
922 * int getnb() lklex.c
923 * VOID lkexit() lkmain.c
924 * char * strsto() lksym.c
925 * int strlen() c_library
926 * int fndidx() lkmain.c
928 * side effects:
929 * Various linker flags are updated and the linked
930 * structure lfile is created.
934 parse()
936 int c;
937 int sv_type;
938 char fid[NINPUT];
940 while ((c = getnb()) != 0) {
941 /* sdld specific */
942 if ( c == ';')
943 return(0);
944 /* end sdld specific */
945 if ( c == '-') {
946 while (ctype[c=get()] & LETTER) {
947 switch(c) {
949 case 'C':
950 if (is_sdld() && !(TARGET_IS_Z80 || TARGET_IS_GB)) {
951 codesav();
952 return(0);
954 // else fall through
955 case 'c':
956 if (startp->f_type != 0)
957 break;
958 startp->f_type = F_STD;
959 doparse();
960 return(0);
962 case 'f':
963 case 'F':
964 if (startp->f_type == F_LNK) {
965 fprintf(stderr, "Nested option -%c ignored\n", c);
966 return(0);
968 unget(getnb());
969 if (*ip == 0)
970 usage(ER_FATAL);
971 sv_type = startp->f_type;
972 startp->f_idp = strsto(ip);
973 startp->f_idx = fndidx(ip);
974 startp->f_type = F_LNK;
975 doparse();
976 if (sv_type == F_STD) {
977 cfp = NULL;
978 sfp = NULL;
979 startp->f_type = F_STD;
980 filep = startp;
982 return(0);
984 case 'I':
985 if (is_sdld() && !(TARGET_IS_Z80 || TARGET_IS_GB)) {
986 iramsav();
987 return(0);
989 // else fall through
990 case 'i':
991 oflag = 1;
992 break;
994 case 'S':
995 if (TARGET_IS_8051) {
996 unget(getnb());
997 if (ip && *ip)
999 stacksize = expr(0);
1000 if (stacksize > 256) stacksize = 256;
1001 else if (stacksize < 0) stacksize = 0;
1003 return(0);
1005 // else fall through
1006 case 's':
1007 oflag = 2;
1008 break;
1010 case 't':
1011 case 'T':
1012 oflag = 3;
1013 break;
1015 case 'o':
1016 case 'O':
1017 objflg = 0;
1018 break;
1020 case 'v':
1021 case 'V':
1022 objflg = 1;
1023 break;
1025 case 'M':
1026 /*JCF: memory usage summary output*/
1027 if (is_sdld()) {
1028 sflag = 1;
1029 break;
1031 // else fall through
1032 case 'm':
1033 mflag = 1;
1034 break;
1036 #if NOICE
1037 case 'j':
1038 case 'J':
1039 jflag = 1;
1040 break;
1041 #endif
1043 case 'r':
1044 case 'R':
1045 if (is_sdld() && !(TARGET_IS_Z80 || TARGET_IS_GB))
1046 rflag = 1;
1047 else
1048 goto err;
1049 break;
1051 case 'u':
1052 case 'U':
1053 uflag = 1;
1054 break;
1056 case 'X':
1057 if (is_sdld() && !(TARGET_IS_Z80 || TARGET_IS_GB)) {
1058 xramsav();
1059 return(0);
1061 // else fall through
1062 case 'x':
1063 xflag = 0;
1064 break;
1066 case 'q':
1067 case 'Q':
1068 xflag = 1;
1069 break;
1071 case 'd':
1072 case 'D':
1073 xflag = 2;
1074 break;
1076 case 'E':
1077 if (TARGET_IS_6808 || TARGET_IS_STM8) {
1078 oflag = 4;
1079 break;
1081 // else fall through
1082 case 'e':
1083 return(1);
1085 case 'n':
1086 case 'N':
1087 pflag = 0;
1088 break;
1090 case 'p':
1091 case 'P':
1092 pflag = 1;
1093 break;
1095 case 'b':
1096 case 'B':
1097 bassav();
1098 return(0);
1100 case 'g':
1101 case 'G':
1102 gblsav();
1103 return(0);
1105 case 'k':
1106 case 'K':
1107 addpath();
1108 return(0);
1110 case 'l':
1111 case 'L':
1112 addlib();
1113 return(0);
1115 case 'w':
1116 case 'W':
1117 wflag = 1;
1118 break;
1120 #if SDCDB
1121 case 'Y':
1122 if (TARGET_IS_8051) {
1123 fprintf(stderr,
1124 "Warning: Treating -Y as -y\n");
1126 // else fall through
1127 case 'y':
1128 yflag = 1;
1129 break;
1130 #endif
1132 case 'z':
1133 case 'Z':
1134 zflag = 1;
1135 break;
1137 default:
1138 err:
1139 fprintf(stderr,
1140 "Unknown option -%c ignored\n", c);
1141 break;
1144 /* sdld specific */
1145 if ( c == ';')
1146 return(0);
1147 /* end sdld specific */
1148 } else
1149 if (!(ctype[c] & ILL)) {
1150 if (linkp == NULL) {
1151 linkp = (struct lfile *)
1152 new (sizeof (struct lfile));
1153 lfp = linkp;
1154 lfp->f_type = F_OUT;
1155 } else {
1156 lfp->f_flp = (struct lfile *)
1157 new (sizeof (struct lfile));
1158 lfp = lfp->f_flp;
1159 lfp->f_type = F_REL;
1161 getfid(fid, c);
1162 lfp->f_idp = strsto(fid);
1163 lfp->f_obj = objflg;
1164 } else {
1165 fprintf(stderr, "Invalid input\n");
1166 lkexit(ER_FATAL);
1169 return(0);
1172 /*)Function VOID doparse()
1174 * The function doparse() evaluates all interactive
1175 * command line or file input linker directives and
1176 * updates the appropriate variables.
1178 * local variables:
1179 * none
1181 * global variables:
1182 * FILE * stdin standard input
1183 * FILE * stdout standard output
1184 * lfile *cfp The pointer *cfp points to the
1185 * current lfile structure
1186 * FILE *sfp The file handle sfp points to the
1187 * currently open file
1188 * char ib[NINPUT] .rel file text line
1189 * char *ip pointer into the .rel file
1190 * lfile *filep The pointer *filep points to the
1191 * beginning of a linked list of
1192 * lfile structures.
1193 * lfile *startp asmlnk startup file structure
1194 * int pflag print linker command file flag
1196 * Functions called:
1197 * int fclose() c_library
1198 * int fprintf() c_library
1199 * VOID getfid() lklex.c
1200 * int nxtline() lklex.c
1201 * int parse() lkmain.c
1203 * side effects:
1204 * Various linker flags are updated and the linked
1205 * structure lfile may be updated.
1208 VOID
1209 doparse()
1211 cfp = NULL;
1212 sfp = NULL;
1213 filep = startp;
1214 while (1) {
1215 ip = ib;
1216 if (nxtline() == 0)
1217 break;
1218 if (pflag && cfp->f_type != F_STD)
1219 fprintf(stdout, "ASlink >> %s\n", ip);
1220 if (*ip == 0 || parse())
1221 break;
1223 if((sfp != NULL) && (sfp != stdin)) {
1224 fclose(sfp);
1226 sfp = NULL;
1227 startp->f_idp = "";
1228 startp->f_idx = 0;
1229 startp->f_type = 0;
1232 /*)Function VOID bassav()
1234 * The function bassav() creates a linked structure containing
1235 * the base address strings input to the linker.
1237 * local variables:
1238 * none
1240 * global variables:
1241 * base *basep The pointer to the first
1242 * base structure
1243 * base *bsp Pointer to the current
1244 * base structure
1245 * char *ip pointer into the REL file
1246 * text line in ib[]
1248 * functions called:
1249 * int getnb() lklex.c
1250 * VOID * new() lksym.c
1251 * int strlen() c_library
1252 * char * strcpy() c_library
1253 * VOID unget() lklex.c
1255 * side effects:
1256 * The basep structure is created.
1259 VOID
1260 bassav()
1262 if (basep == NULL) {
1263 basep = (struct base *)
1264 new (sizeof (struct base));
1265 bsp = basep;
1266 } else {
1267 bsp->b_base = (struct base *)
1268 new (sizeof (struct base));
1269 bsp = bsp->b_base;
1271 unget(getnb());
1272 bsp->b_strp = (char *) new (strlen(ip)+1);
1273 strcpy(bsp->b_strp, ip);
1277 /*)Function VOID gblsav()
1279 * The function gblsav() creates a linked structure containing
1280 * the global variable strings input to the linker.
1282 * local variable:
1283 * none
1285 * global variables:
1286 * globl *globlp The pointer to the first
1287 * globl structure
1288 * globl *gsp Pointer to the current
1289 * globl structure
1290 * char *ip pointer into the REL file
1291 * text line in ib[]
1292 * int lkerr error flag
1294 * functions called:
1295 * int getnb() lklex.c
1296 * VOID * new() lksym.c
1297 * int strlen() c_library
1298 * char * strcpy() c_library
1299 * VOID unget() lklex.c
1301 * side effects:
1302 * The globlp structure is created.
1305 VOID
1306 gblsav()
1308 if (globlp == NULL) {
1309 globlp = (struct globl *)
1310 new (sizeof (struct globl));
1311 gsp = globlp;
1312 } else {
1313 gsp->g_globl = (struct globl *)
1314 new (sizeof (struct globl));
1315 gsp = gsp->g_globl;
1317 unget(getnb());
1318 gsp->g_strp = (char *) new (strlen(ip)+1);
1319 strcpy(gsp->g_strp, ip);
1323 /*)Function VOID setgbl()
1325 * The function setgbl() scans the global variable lines in the
1326 * globlp structure, evaluates the arguments, and sets a variable
1327 * to this value.
1329 * local variables:
1330 * int v expression value
1331 * char id[] base id string
1332 * sym * sp pointer to a symbol structure
1334 * global variables:
1335 * char *ip pointer into the REL file
1336 * text line in ib[]
1337 * globl *globlp The pointer to the first
1338 * globl structure
1339 * globl *gsp Pointer to the current
1340 * globl structure
1341 * FILE * stderr c_library
1342 * int lkerr error flag
1344 * functions called:
1345 * a_uint expr() lkeval.c
1346 * int fprintf() c_library
1347 * VOID getid() lklex.c
1348 * int getnb() lklex.c
1349 * sym * lkpsym() lksym.c
1351 * side effects:
1352 * The value of a variable is set.
1355 VOID
1356 setgbl()
1358 int v;
1359 struct sym *sp;
1360 char id[NCPS];
1362 gsp = globlp;
1363 while (gsp) {
1364 ip = gsp->g_strp;
1365 getid(id, -1);
1366 if (getnb() == '=') {
1367 v = (int) expr(0);
1368 sp = lkpsym(id, 0);
1369 if (sp == NULL) {
1370 fprintf(stderr,
1371 "No definition of symbol %s\n", id);
1372 lkerr++;
1373 } else {
1374 if (sp->s_type & S_DEF) {
1375 fprintf(stderr,
1376 "Redefinition of symbol %s\n", id);
1377 lkerr++;
1378 sp->s_axp = NULL;
1380 sp->s_addr = v;
1381 sp->s_type |= S_DEF;
1383 } else {
1384 fprintf(stderr, "No '=' in global expression");
1385 lkerr++;
1387 gsp = gsp->g_globl;
1391 /*)Function FILE * afile(fn, ft, wf)
1393 * char * fn file specification string
1394 * char * ft file type string
1395 * int wf 0 ==>> read
1396 * 1 ==>> write
1397 * 2 ==>> binary write
1399 * The function afile() opens a file for reading or writing.
1400 * (1) If the file type specification string ft
1401 * is not NULL then a file specification is
1402 * constructed with the file path\name in fn
1403 * and the extension in ft.
1404 * (2) If the file type specification string ft
1405 * is NULL then the file specification is
1406 * constructed from fn. If fn does not have
1407 * a file type then the default .rel file
1408 * type is appended to the file specification.
1410 * afile() returns a file handle for the opened file or aborts
1411 * the assembler on an open error.
1413 * local variables:
1414 * int c character value
1415 * FILE * fp filehandle for opened file
1416 * char * p1 pointer to filespec string fn
1417 * char * p2 pointer to filespec string fb
1418 * char * p3 pointer to filetype string ft
1420 * global variables:
1421 * char afspec[] constructed file specification string
1422 * int lkerr error flag
1424 * functions called:
1425 * int fndidx() lkmain.c
1426 * FILE * fopen() c_library
1427 * int fprintf() c_library
1429 * side effects:
1430 * File is opened for read or write.
1433 FILE *
1434 afile(char *fn, char *ft, int wf)
1436 char *p1, *p2;
1437 int c;
1438 char * frmt;
1439 FILE *fp;
1441 if (strlen(fn) > (FILSPC-7)) {
1442 fprintf(stderr, "?ASlink-Error-<filspc too long> : \"%s\"\n", fn);
1443 lkerr++;
1444 return(NULL);
1448 * Skip The Path
1450 strcpy(afspec, fn);
1451 c = fndidx(afspec);
1454 * Skip to File Extension separator
1456 p1 = strrchr(&afspec[c], FSEPX);
1459 * Copy File Extension
1461 p2 = ft ? ft : "";
1462 if (*p2 == 0) {
1463 if (p1 == NULL) {
1464 p2 = LKOBJEXT;
1465 } else {
1466 p2 = strrchr(&fn[c], FSEPX) + 1;
1469 if (p1 == NULL) {
1470 p1 = &afspec[strlen(afspec)];
1472 *p1++ = FSEPX;
1473 while ((c = *p2++) != 0) {
1474 if (p1 < &afspec[FILSPC-1])
1475 *p1++ = c;
1477 *p1++ = 0;
1480 * Select Read/Write/Binary Write
1482 switch(wf) {
1483 default:
1484 case 0: frmt = "r"; break;
1485 case 1: frmt = "w"; break;
1486 #ifdef DECUS
1487 case 2: frmt = "wn"; break;
1488 #else
1489 case 2: frmt = "wb"; break;
1490 #endif
1492 if ((fp = fopen(afspec, frmt)) == NULL && strcmp(ft,"adb") != 0) { /* Do not complain for optional adb files */
1493 fprintf(stderr, "?ASlink-Error-<cannot %s> : \"%s\"\n", wf?"create":"open", afspec);
1494 lkerr++;
1496 return (fp);
1499 /*)Function int fndidx(str)
1501 * char * str file specification string
1503 * The function fndidx() scans the file specification string
1504 * to find the index to the file name. If the file
1505 * specification contains a 'path' then the index will
1506 * be non zero.
1508 * fndidx() returns the index value.
1510 * local variables:
1511 * char * p1 temporary pointer
1512 * char * p2 temporary pointer
1514 * global variables:
1515 * none
1517 * functions called:
1518 * char * strrchr() c_library
1520 * side effects:
1521 * none
1525 fndidx(str)
1526 char *str;
1528 char *p1, *p2;
1531 * Skip Path Delimiters
1533 p1 = str;
1534 if ((p2 = strrchr(p1, ':')) != NULL) { p1 = p2 + 1; }
1535 if ((p2 = strrchr(p1, '/')) != NULL) { p1 = p2 + 1; }
1536 if ((p2 = strrchr(p1, '\\')) != NULL) { p1 = p2 + 1; }
1538 return((int) (p1 - str));
1541 /*)Function int fndext(str)
1543 * char * str file specification string
1545 * The function fndext() scans the file specification string
1546 * to find the file.ext separater.
1548 * fndext() returns the index to FSEPX or the end of the string.
1550 * local variables:
1551 * char * p1 temporary pointer
1552 * char * p2 temporary pointer
1554 * global variables:
1555 * none
1557 * functions called:
1558 * char * strrchr() c_library
1560 * side effects:
1561 * none
1565 fndext(str)
1566 char * str;
1568 char *p1, *p2;
1571 * Find the file separator
1573 p1 = str + strlen(str);
1574 if ((p2 = strrchr(str, FSEPX)) != NULL) { p1 = p2; }
1576 return((int) (p1 - str));
1579 /* sdld specific */
1580 /*)Function VOID iramsav()
1582 * The function iramsav() stores the size of the chip's internal RAM.
1583 * This is used after linking to check that variable assignment to this
1584 * dataspace didn't overflow into adjoining segments. Variables in the
1585 * DSEG, OSEG, and ISEG are assigned to this dataspace.
1587 * local variables:
1588 * none
1590 * global variables:
1591 * char *ip pointer into the REL file
1592 * text line in ib[]
1593 * unsigned int size of chip's internal
1594 * iram_size RAM segment
1596 * functions called:
1597 * int getnb() lklex.c
1598 * VOID unget() lklex.c
1599 * a_uint expr() lkeval.c
1601 * side effects:
1602 * The iram_size may be modified.
1605 VOID
1606 iramsav()
1608 unget(getnb());
1609 if (ip && *ip)
1610 iram_size = expr(0); /* evaluate size expression */
1611 else
1612 iram_size = 128; /* Default is 128 (0x80) bytes */
1613 if ((iram_size<=0) || (iram_size>256))
1614 iram_size = 128; /* Default is 128 (0x80) bytes */
1617 /*Similar to iramsav but for xram memory*/
1618 VOID
1619 xramsav()
1621 unget(getnb());
1622 if (ip && *ip)
1623 xram_size = expr(0); /* evaluate size expression */
1624 else
1625 xram_size = rflag?0x1000000:0x10000;
1628 /*Similar to iramsav but for code memory*/
1629 VOID
1630 codesav()
1632 unget(getnb());
1633 if (ip && *ip)
1634 code_size = expr(0); /* evaluate size expression */
1635 else
1636 code_size = rflag?0x1000000:0x10000;
1640 /*)Function VOID iramcheck()
1642 * The function iramcheck() is used at the end of linking to check that
1643 * the internal RAM area wasn't overflowed by too many variable
1644 * assignments. Variables in the DSEG, ISEG, and OSEG are assigned to
1645 * the chip's internal RAM.
1647 * local variables:
1648 * none
1650 * global variables:
1651 * unsigned int size of chip's internal
1652 * iram_size RAM segment
1653 * struct area linked list of memory
1654 * *areap areas
1656 * functions called:
1658 * side effects:
1661 VOID
1662 iramcheck()
1664 register unsigned int last_addr;
1665 register struct area *ap;
1667 for (ap = areap; ap; ap=ap->a_ap) {
1668 if ((ap->a_size != 0) &&
1669 (!strcmp(ap->a_id, "DSEG") ||
1670 !strcmp(ap->a_id, "OSEG") ||
1671 !strcmp(ap->a_id, "ISEG")
1675 last_addr = ap->a_addr + ap->a_size - 1;
1676 if (last_addr >= iram_size)
1677 fprintf(stderr,
1678 "\nWARNING! Segment %s extends past the end\n"
1679 " of internal RAM. Check map file.\n",
1680 ap->a_id);
1684 /* end sdld specific */
1686 char *usetxt[] = {
1687 "Usage: [-Options] [-Option with arg] file",
1688 "Usage: [-Options] [-Option with arg] outfile file1 [file2 ...]",
1689 "Startup:",
1690 " -p Echo commands to stdout (default)",
1691 " -n No echo of commands to stdout",
1692 "Alternates to Command Line Input:",
1693 " -c ASlink >> prompt input",
1694 " -f file[.lk] Command File input",
1695 "Libraries:",
1696 " -k Library path specification, one per -k",
1697 " -l Library file specification, one per -l",
1698 "Relocation:",
1699 " -b area base address = expression",
1700 " -g global symbol = expression",
1701 "Map format:",
1702 " -m Map output generated as (out)file[.map]",
1703 " -w Wide listing format for map file",
1704 " -x Hexadecimal (default)",
1705 " -d Decimal",
1706 " -q Octal",
1707 "Output:",
1708 " -i Intel Hex as (out)file[.ihx]",
1709 " -s Motorola S Record as (out)file[.s19]",
1710 // " -t Tandy CoCo Disk BASIC binary as (out)file[.bi-]",
1711 #if NOICE
1712 " -j NoICE Debug output as (out)file[.noi]",
1713 #endif
1714 #if SDCDB
1715 " -y SDCDB Debug output as (out)file[.cdb]",
1716 #endif
1717 // " -o Linked file/library object output enable (default)",
1718 // " -v Linked file/library object output disable",
1719 "List:",
1720 " -u Update listing file(s) with link data as file(s)[.rst]",
1721 "Case Sensitivity:",
1722 " -z Disable Case Sensitivity for Symbols",
1723 "End:",
1724 " -e or null line terminates input",
1729 char *usetxt_8051[] = {
1730 "Usage: [-Options] [-Option with arg] file",
1731 "Usage: [-Options] [-Option with arg] outfile file1 [file2 ...]",
1732 "Startup:",
1733 " -p Echo commands to stdout (default)",
1734 " -n No echo of commands to stdout",
1735 "Alternates to Command Line Input:",
1736 " -c ASlink >> prompt input",
1737 " -f file[.lk] Command File input",
1738 "Libraries:",
1739 " -k Library path specification, one per -k",
1740 " -l Library file specification, one per -l",
1741 "Relocation:",
1742 " -b area base address = expression",
1743 " -g global symbol = expression",
1744 "Map format:",
1745 " -m Map output generated as (out)file[.map]",
1746 " -w Wide listing format for map file",
1747 " -x Hexadecimal (default)",
1748 " -d Decimal",
1749 " -q Octal",
1750 "Output:",
1751 " -i Intel Hex as (out)file[.ihx]",
1752 " -s Motorola S Record as (out)file[.s19]",
1753 #if NOICE
1754 " -j NoICE Debug output as (out)file[.noi]",
1755 #endif
1756 #if SDCDB
1757 " -y SDCDB Debug output as (out)file[.cdb]",
1758 #endif
1759 "List:",
1760 " -u Update listing file(s) with link data as file(s)[.rst]",
1761 "Case Sensitivity:",
1762 " -z Disable Case Sensitivity for Symbols",
1763 "Miscellaneous:\n"
1764 " -I [iram-size] Check for internal RAM overflow",
1765 " -X [xram-size] Check for external RAM overflow",
1766 " -C [code-size] Check for code overflow",
1767 " -M Generate memory usage summary file[.mem]",
1768 " -S [stack-size] Allocate space for stack",
1769 "End:",
1770 " -e or null line terminates input",
1775 char *usetxt_6808[] = {
1776 "Usage: [-Options] [-Option with arg] file",
1777 "Usage: [-Options] [-Option with arg] outfile file1 [file2 ...]",
1778 "Startup:",
1779 " -p Echo commands to stdout (default)",
1780 " -n No echo of commands to stdout",
1781 "Alternates to Command Line Input:",
1782 " -c ASlink >> prompt input",
1783 " -f file[.lk] Command File input",
1784 "Libraries:",
1785 " -k Library path specification, one per -k",
1786 " -l Library file specification, one per -l",
1787 "Relocation:",
1788 " -b area base address = expression",
1789 " -g global symbol = expression",
1790 "Map format:",
1791 " -m Map output generated as (out)file[.map]",
1792 " -w Wide listing format for map file",
1793 " -x Hexadecimal (default)",
1794 " -d Decimal",
1795 " -q Octal",
1796 "Output:",
1797 " -i Intel Hex as (out)file[.ihx]",
1798 " -s Motorola S Record as (out)file[.s19]",
1799 " -E ELF executable as file[.elf]",
1800 #if NOICE
1801 " -j NoICE Debug output as (out)file[.noi]",
1802 #endif
1803 #if SDCDB
1804 " -y SDCDB Debug output as (out)file[.cdb]",
1805 #endif
1806 "List:",
1807 " -u Update listing file(s) with link data as file(s)[.rst]",
1808 "Case Sensitivity:",
1809 " -z Disable Case Sensitivity for Symbols",
1810 "Miscellaneous:\n"
1811 " -I [iram-size] Check for internal RAM overflow",
1812 " -X [xram-size] Check for external RAM overflow",
1813 " -C [code-size] Check for code overflow",
1814 " -M Generate memory usage summary file[.mem]",
1815 "End:",
1816 " -e or null line terminates input",
1821 char *usetxt_z80_gb[] = {
1822 "Usage: [-Options] [-Option with arg] file",
1823 "Usage: [-Options] [-Option with arg] outfile file1 [file2 ...]",
1824 "Startup:",
1825 " -p Echo commands to stdout (default)",
1826 " -n No echo of commands to stdout",
1827 "Alternates to Command Line Input:",
1828 " -c ASlink >> prompt input",
1829 " -f file[.lk] Command File input",
1830 "Libraries:",
1831 " -k Library path specification, one per -k",
1832 " -l Library file specification, one per -l",
1833 "Relocation:",
1834 " -b area base address = expression",
1835 " -g global symbol = expression",
1836 "Map format:",
1837 " -m Map output generated as (out)file[.map]",
1838 " -w Wide listing format for map file",
1839 " -x Hexadecimal (default)",
1840 " -d Decimal",
1841 " -q Octal",
1842 "Output:",
1843 " -i Intel Hex as (out)file[.ihx]",
1844 " -s Motorola S Record as (out)file[.s19]",
1845 #if NOICE
1846 // can be converted into no$gmb compatible .sym
1847 " -j NoICE Debug output as (out)file[.noi]",
1848 #endif
1849 #if SDCDB
1850 " -y SDCDB Debug output as (out)file[.cdb]",
1851 #endif
1852 "List:",
1853 " -u Update listing file(s) with link data as file(s)[.rst]",
1854 "Case Sensitivity:",
1855 " -z Disable Case Sensitivity for Symbols",
1856 "End:",
1857 " -e or null line terminates input",
1862 /*)Function VOID usage(n)
1864 * int n exit code
1866 * The function usage() outputs to the stderr device the
1867 * linker name and version and a list of valid linker options.
1869 * local variables:
1870 * char ** dp pointer to an array of
1871 * text string pointers.
1873 * global variables:
1874 * FILE * stderr c_library
1876 * functions called:
1877 * int fprintf() c_library
1879 * side effects:
1880 * none
1883 VOID
1884 usage(int n)
1886 char **dp;
1888 /* sdld specific */
1889 fprintf(stderr, "\n%s Linker %s\n\n", is_sdld() ? "sdld" : "ASxxxx", VERSION);
1890 for (dp = TARGET_IS_8051 ? usetxt_8051 : (TARGET_IS_6808 ? usetxt_6808 : ((TARGET_IS_Z80 || TARGET_IS_GB) ? usetxt_z80_gb : usetxt)); *dp; dp++)
1891 fprintf(stderr, "%s\n", *dp);
1892 /* end sdld specific */
1893 lkexit(n);
1896 /*)Function VOID copyfile()
1898 * FILE *dest destination file
1899 * FILE *src source file
1901 * function will copy source file to destination file
1904 * functions called:
1905 * int fgetc() c_library
1906 * int fputc() c_library
1908 * side effects:
1909 * none
1911 VOID
1912 copyfile (FILE *dest, FILE *src)
1914 int ch;
1916 while ((ch = fgetc(src)) != EOF) {
1917 fputc(ch,dest);