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/>.
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:
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.*/
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",
81 for (j
= 0; rel
[j
][0] != 0; j
++) {
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;
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
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.
125 * int c character from argument string
132 * lfile *cfp The pointer *cfp points to the
133 * current lfile structure
134 * char ctype[] array of character types, one per
136 * lfile *filep The pointer *filep points to the
137 * beginning of a linked list of
139 * head *hp Pointer to the current
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
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
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
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
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
[])
193 fprintf(stderr
, "?ASlink-Error-Size of INT32 is not 32 bits or larger.\n\n");
198 /* sdas initialization */
201 /* use these defaults for parsing the .lnk script */
206 /* end sdas specific */
209 fprintf(stdout
, "\n");
211 startp
= (struct lfile
*) new (sizeof (struct lfile
));
216 for(i
=1; i
<argc
; i
++) {
218 if(argv
[i
][0] == '-') {
221 while((c
= argv
[j
][k
]) != '\0') {
223 sprintf(ip
, "-%c", c
);
227 * Options with arguments
250 strcat(ip
, argv
[++i
]);
255 * Preprocess these commands
268 * Options without arguments
274 fprintf(stdout
, "ASlink >> %s\n", ip
);
281 fprintf(stdout
, "ASlink >> %s\n", ip
);
290 * If no input file is specified
291 * then assume a single file with
292 * the same name as the output file.
295 lfp
->f_flp
= (struct lfile
*) new (sizeof (struct lfile
));
297 lfp
->f_idp
= strsto(linkp
->f_idp
);
298 lfp
->f_idx
= fndidx(linkp
->f_idp
);
307 * Open SDCC Debug output file
312 for (pass
=0; pass
<2; ++pass
) {
315 filep
= linkp
->f_flp
;
321 Areas51(); /*JCF: Create the default 8051 areas in the right order*/
322 /* end sdld specific */
330 * Search libraries for global symbols
335 /* use these defaults for parsing the .lk script */
340 /* end sdas specific */
343 * Set area base addresses.
347 * Set bank base addresses.
351 * Link all area addresses.
353 /* sdld 8051 specific */
354 if (is_sdld_target_8051_like())
357 /* end sdld 8051 specific */
360 * Check bank size limits.
364 * Process global definitions.
368 * Check for undefined globals.
373 * Open NoICE output file
383 if (sflag
) { /*JCF: memory usage summary output*/
384 if (is_sdld_target_8051_like()) {
385 if (summary2(areap
)) {
390 if (summary(areap
)) {
396 if ((iram_size
) && (!is_sdld_target_8051_like()))
399 /* end sdld specific */
402 * Open output file(s)
407 * Link in library files
411 * Complete Processing
417 if (TARGET_IS_PDK
&& get_sdld_target() != TARGET_ID_PDK
) {
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;
444 "RAM value %u too large "
445 "(%uB max)\n", ram
, max_ram
);
450 "ROM value %u too large "
451 "(%uW max)\n", rom
/ 2, max_rom
/ 2);
454 if (TARGET_IS_8051
) {
459 lkexit(lkerr
? ER_ERROR
: ER_NONE
);
463 /*)Function int intsiz()
465 * The function intsiz() returns the size of INT32
483 return(sizeof(a_uint
));
486 /*)Function VOID lkexit(i)
490 * The function lkexit() explicitly closes all open
491 * files and then terminates the program.
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
504 * int fclose() c_library
505 * VOID exit() c_library
506 * VOID lkfclose() lkbank.c
509 * All files closed. Program terminates.
518 if (jfp
!= NULL
) fclose(jfp
);
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
);
525 if (yfp
!= NULL
) fclose(yfp
);
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
535 * X, D, Q, H, M, A, S, T, R, and P.
538 * int c first non blank character of a line
541 * head *headp The pointer to the first
542 * head structure of a linked list
543 * head *hp Pointer to the current
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
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
560 * Head, area, and symbol structures are created and
561 * the radix is set as the .rel file(s) are read.
569 if ((c
=endline()) == 0) { return; }
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
;
580 if (strcmp(optsdcc
, &ip
[1]) != 0) {
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
);
591 /* end sdld specific */
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) {
634 a_mask
= 0x0000FFFFl
;
635 s_mask
= 0x00008000l
;
636 v_mask
= 0x00007FFFl
;
640 a_mask
= 0x00FFFFFFl
;
641 s_mask
= 0x00800000l
;
642 v_mask
= 0x007FFFFFl
;
646 a_mask
= 0xFFFFFFFFl
;
647 s_mask
= 0x80000000l
;
648 v_mask
= 0x7FFFFFFFl
;
699 if (sdp
.s_area
== NULL
) {
701 sdp
.s_areax
= areap
->a_axp
;
731 /*)Function VOID map()
733 * The function map() opens the output map file and calls the various
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.
744 * head * hdp pointer to head structure
745 * lbfile *lbfh pointer to library file structure
748 * area *ap Pointer to the current
750 * area *areap The pointer to the first
751 * area structure of a linked list
752 * base *basep The pointer to the first
754 * base *bsp Pointer to the current
756 * lfile *filep The pointer *filep points to the
757 * beginning of a linked list of
759 * globl *globlp The pointer to the first
761 * globl *gsp Pointer to the current
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
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
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
785 * The map file is created.
795 if (mflag
== 0) return;
800 mfp
= afile(linkp
->f_idp
, "map", 1);
806 * Output Map Bank/Area Lists
810 for (bp
= bankp
; bp
!= NULL
; bp
= bp
->b_bp
) {
811 for (ap
= areap
; ap
!= NULL
; ap
= ap
->a_ap
) {
821 fprintf(mfp
, "\nFiles Linked [ module(s) ]\n\n");
823 filep
= linkp
->f_flp
;
825 if (strlen (filep
->f_idp
) > 40)
826 fprintf(mfp
, "%s\n%40s [ ", filep
->f_idp
, "");
828 fprintf(mfp
, "%-40.40s [ ", filep
->f_idp
);
830 while ((hdp
!= NULL
) && (hdp
->h_lfile
== filep
)) {
832 fprintf(mfp
, ",\n%44s", "");
833 fprintf(mfp
, "%-.32s", hdp
->m_id
);
837 fprintf(mfp
, " ]\n");
838 filep
= filep
->f_flp
;
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
);
851 fprintf(mfp
, "%-40.40s [ %-.32s ]\n",
852 lbfh
->libspc
, lbfh
->relfil
);
857 * List Base Address Definitions
861 fprintf(mfp
, "\nUser Base Address Definitions\n\n");
864 fprintf(mfp
, "%s\n", bsp
->b_strp
);
869 * List Global Definitions
873 fprintf(mfp
, "\nUser Global Definitions\n\n");
876 fprintf(mfp
, "%s\n", gsp
->g_strp
);
880 fprintf(mfp
, "\n\f");
885 /*)Function int parse()
887 * The function parse() evaluates all command line or file input
888 * linker directives and updates the appropriate variables.
891 * int c character value
892 * int sv_type save type of processing
893 * char fid[] file id string
896 * char ctype[] array of character types, one per
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
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
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
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
929 * Various linker flags are updated and the linked
930 * structure lfile is created.
940 while ((c
= getnb()) != 0) {
944 /* end sdld specific */
946 while (ctype
[c
=get()] & LETTER
) {
950 if (is_sdld() && !(TARGET_IS_Z80
|| TARGET_IS_GB
)) {
956 if (startp
->f_type
!= 0)
958 startp
->f_type
= F_STD
;
964 if (startp
->f_type
== F_LNK
) {
965 fprintf(stderr
, "Nested option -%c ignored\n", c
);
971 sv_type
= startp
->f_type
;
972 startp
->f_idp
= strsto(ip
);
973 startp
->f_idx
= fndidx(ip
);
974 startp
->f_type
= F_LNK
;
976 if (sv_type
== F_STD
) {
979 startp
->f_type
= F_STD
;
985 if (is_sdld() && !(TARGET_IS_Z80
|| TARGET_IS_GB
)) {
995 if (TARGET_IS_8051
) {
1000 if (stacksize
> 256) stacksize
= 256;
1001 else if (stacksize
< 0) stacksize
= 0;
1005 // else fall through
1026 /*JCF: memory usage summary output*/
1031 // else fall through
1045 if (is_sdld() && !(TARGET_IS_Z80
|| TARGET_IS_GB
))
1057 if (is_sdld() && !(TARGET_IS_Z80
|| TARGET_IS_GB
)) {
1061 // else fall through
1077 if (TARGET_IS_6808
|| TARGET_IS_STM8
) {
1081 // else fall through
1122 if (TARGET_IS_8051
) {
1124 "Warning: Treating -Y as -y\n");
1126 // else fall through
1140 "Unknown option -%c ignored\n", c
);
1147 /* end sdld specific */
1149 if (!(ctype
[c
] & ILL
)) {
1150 if (linkp
== NULL
) {
1151 linkp
= (struct lfile
*)
1152 new (sizeof (struct lfile
));
1154 lfp
->f_type
= F_OUT
;
1156 lfp
->f_flp
= (struct lfile
*)
1157 new (sizeof (struct lfile
));
1159 lfp
->f_type
= F_REL
;
1162 lfp
->f_idp
= strsto(fid
);
1163 lfp
->f_obj
= objflg
;
1165 fprintf(stderr
, "Invalid input\n");
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.
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
1193 * lfile *startp asmlnk startup file structure
1194 * int pflag print linker command file flag
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
1204 * Various linker flags are updated and the linked
1205 * structure lfile may be updated.
1218 if (pflag
&& cfp
->f_type
!= F_STD
)
1219 fprintf(stdout
, "ASlink >> %s\n", ip
);
1220 if (*ip
== 0 || parse())
1223 if((sfp
!= NULL
) && (sfp
!= stdin
)) {
1232 /*)Function VOID bassav()
1234 * The function bassav() creates a linked structure containing
1235 * the base address strings input to the linker.
1241 * base *basep The pointer to the first
1243 * base *bsp Pointer to the current
1245 * char *ip pointer into the REL file
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
1256 * The basep structure is created.
1262 if (basep
== NULL
) {
1263 basep
= (struct base
*)
1264 new (sizeof (struct base
));
1267 bsp
->b_base
= (struct base
*)
1268 new (sizeof (struct base
));
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.
1286 * globl *globlp The pointer to the first
1288 * globl *gsp Pointer to the current
1290 * char *ip pointer into the REL file
1292 * int lkerr error flag
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
1302 * The globlp structure is created.
1308 if (globlp
== NULL
) {
1309 globlp
= (struct globl
*)
1310 new (sizeof (struct globl
));
1313 gsp
->g_globl
= (struct globl
*)
1314 new (sizeof (struct globl
));
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
1330 * int v expression value
1331 * char id[] base id string
1332 * sym * sp pointer to a symbol structure
1335 * char *ip pointer into the REL file
1337 * globl *globlp The pointer to the first
1339 * globl *gsp Pointer to the current
1341 * FILE * stderr c_library
1342 * int lkerr error flag
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
1352 * The value of a variable is set.
1366 if (getnb() == '=') {
1371 "No definition of symbol %s\n", id
);
1374 if (sp
->s_type
& S_DEF
) {
1376 "Redefinition of symbol %s\n", id
);
1381 sp
->s_type
|= S_DEF
;
1384 fprintf(stderr
, "No '=' in global expression");
1391 /*)Function FILE * afile(fn, ft, wf)
1393 * char * fn file specification string
1394 * char * ft file type string
1395 * int wf 0 ==>> read
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.
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
1421 * char afspec[] constructed file specification string
1422 * int lkerr error flag
1425 * int fndidx() lkmain.c
1426 * FILE * fopen() c_library
1427 * int fprintf() c_library
1430 * File is opened for read or write.
1434 afile(char *fn
, char *ft
, int wf
)
1441 if (strlen(fn
) > (FILSPC
-7)) {
1442 fprintf(stderr
, "?ASlink-Error-<filspc too long> : \"%s\"\n", fn
);
1454 * Skip to File Extension separator
1456 p1
= strrchr(&afspec
[c
], FSEPX
);
1459 * Copy File Extension
1466 p2
= strrchr(&fn
[c
], FSEPX
) + 1;
1470 p1
= &afspec
[strlen(afspec
)];
1473 while ((c
= *p2
++) != 0) {
1474 if (p1
< &afspec
[FILSPC
-1])
1480 * Select Read/Write/Binary Write
1484 case 0: frmt
= "r"; break;
1485 case 1: frmt
= "w"; break;
1487 case 2: frmt
= "wn"; break;
1489 case 2: frmt
= "wb"; break;
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
);
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
1508 * fndidx() returns the index value.
1511 * char * p1 temporary pointer
1512 * char * p2 temporary pointer
1518 * char * strrchr() c_library
1531 * Skip Path Delimiters
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.
1551 * char * p1 temporary pointer
1552 * char * p2 temporary pointer
1558 * char * strrchr() c_library
1571 * Find the file separator
1573 p1
= str
+ strlen(str
);
1574 if ((p2
= strrchr(str
, FSEPX
)) != NULL
) { p1
= p2
; }
1576 return((int) (p1
- str
));
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.
1591 * char *ip pointer into the REL file
1593 * unsigned int size of chip's internal
1594 * iram_size RAM segment
1597 * int getnb() lklex.c
1598 * VOID unget() lklex.c
1599 * a_uint expr() lkeval.c
1602 * The iram_size may be modified.
1610 iram_size
= expr(0); /* evaluate size expression */
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*/
1623 xram_size
= expr(0); /* evaluate size expression */
1625 xram_size
= rflag
?0x1000000:0x10000;
1628 /*Similar to iramsav but for code memory*/
1634 code_size
= expr(0); /* evaluate size expression */
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.
1651 * unsigned int size of chip's internal
1652 * iram_size RAM segment
1653 * struct area linked list of memory
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
)
1678 "\nWARNING! Segment %s extends past the end\n"
1679 " of internal RAM. Check map file.\n",
1684 /* end sdld specific */
1687 "Usage: [-Options] [-Option with arg] file",
1688 "Usage: [-Options] [-Option with arg] outfile file1 [file2 ...]",
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",
1696 " -k Library path specification, one per -k",
1697 " -l Library file specification, one per -l",
1699 " -b area base address = expression",
1700 " -g global symbol = expression",
1702 " -m Map output generated as (out)file[.map]",
1703 " -w Wide listing format for map file",
1704 " -x Hexadecimal (default)",
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-]",
1712 " -j NoICE Debug output as (out)file[.noi]",
1715 " -y SDCDB Debug output as (out)file[.cdb]",
1717 // " -o Linked file/library object output enable (default)",
1718 // " -v Linked file/library object output disable",
1720 " -u Update listing file(s) with link data as file(s)[.rst]",
1721 "Case Sensitivity:",
1722 " -z Disable Case Sensitivity for Symbols",
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 ...]",
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",
1739 " -k Library path specification, one per -k",
1740 " -l Library file specification, one per -l",
1742 " -b area base address = expression",
1743 " -g global symbol = expression",
1745 " -m Map output generated as (out)file[.map]",
1746 " -w Wide listing format for map file",
1747 " -x Hexadecimal (default)",
1751 " -i Intel Hex as (out)file[.ihx]",
1752 " -s Motorola S Record as (out)file[.s19]",
1754 " -j NoICE Debug output as (out)file[.noi]",
1757 " -y SDCDB Debug output as (out)file[.cdb]",
1760 " -u Update listing file(s) with link data as file(s)[.rst]",
1761 "Case Sensitivity:",
1762 " -z Disable Case Sensitivity for Symbols",
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",
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 ...]",
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",
1785 " -k Library path specification, one per -k",
1786 " -l Library file specification, one per -l",
1788 " -b area base address = expression",
1789 " -g global symbol = expression",
1791 " -m Map output generated as (out)file[.map]",
1792 " -w Wide listing format for map file",
1793 " -x Hexadecimal (default)",
1797 " -i Intel Hex as (out)file[.ihx]",
1798 " -s Motorola S Record as (out)file[.s19]",
1799 " -E ELF executable as file[.elf]",
1801 " -j NoICE Debug output as (out)file[.noi]",
1804 " -y SDCDB Debug output as (out)file[.cdb]",
1807 " -u Update listing file(s) with link data as file(s)[.rst]",
1808 "Case Sensitivity:",
1809 " -z Disable Case Sensitivity for Symbols",
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]",
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 ...]",
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",
1831 " -k Library path specification, one per -k",
1832 " -l Library file specification, one per -l",
1834 " -b area base address = expression",
1835 " -g global symbol = expression",
1837 " -m Map output generated as (out)file[.map]",
1838 " -w Wide listing format for map file",
1839 " -x Hexadecimal (default)",
1843 " -i Intel Hex as (out)file[.ihx]",
1844 " -s Motorola S Record as (out)file[.s19]",
1846 // can be converted into no$gmb compatible .sym
1847 " -j NoICE Debug output as (out)file[.noi]",
1850 " -y SDCDB Debug output as (out)file[.cdb]",
1853 " -u Update listing file(s) with link data as file(s)[.rst]",
1854 "Case Sensitivity:",
1855 " -z Disable Case Sensitivity for Symbols",
1857 " -e or null line terminates input",
1862 /*)Function VOID usage(n)
1866 * The function usage() outputs to the stderr device the
1867 * linker name and version and a list of valid linker options.
1870 * char ** dp pointer to an array of
1871 * text string pointers.
1874 * FILE * stderr c_library
1877 * int fprintf() c_library
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 */
1896 /*)Function VOID copyfile()
1898 * FILE *dest destination file
1899 * FILE *src source file
1901 * function will copy source file to destination file
1905 * int fgetc() c_library
1906 * int fputc() c_library
1912 copyfile (FILE *dest
, FILE *src
)
1916 while ((ch
= fgetc(src
)) != EOF
) {