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