3 Copyright (C) 1989-1995 Alan R. Baldwin
4 721 Berkeley St., Kent, Ohio 44240
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
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/>. */
21 * - add jflag and jfp to control NoICE output file generation
23 * - use a_type == 0 as "virgin area" flag: set == 1 if -b
34 void Timer(int action, char * message)
36 static double start, end, total=0.0;
37 static const double secs_per_tick = 1.0 / CLOCKS_PER_SEC;
39 if(action==0) start=clock()*secs_per_tick;
42 end=clock() * secs_per_tick;
43 printf("%s \t%f seconds.\n", message, (end-start));
48 printf("Total time: \t%f seconds.\n", total);
56 * The module lkmain.c contains the functions which
57 * (1) input the linker options, parameters, and specifications
58 * (2) perform a two pass link
59 * (3) produce the appropriate linked data output and/or
60 * link map file and/or relocated listing files.
62 * lkmain.c contains the following functions:
63 * FILE * afile(fn,ft,wf)
68 * VOID main(argc,argv)
75 * lkmain.c contains the following local variables:
76 * char * usetext[] array of pointers to the
77 * command option tect lines
81 /*JCF: Creates some of the default areas so they are allocated in the right order.*/
86 "H 7 areas 0 global symbols",
87 "A _CODE size 0 flags 0", /*Each .rel has one, so...*/
88 "A REG_BANK_0 size 0 flags 4", /*Register banks are overlayable*/
89 "A REG_BANK_1 size 0 flags 4",
90 "A REG_BANK_2 size 0 flags 4",
91 "A REG_BANK_3 size 0 flags 4",
92 "A BSEG size 0 flags 80", /*BSEG must be just before BITS*/
93 "A BSEG_BYTES size 0 flags 0", /*Size will be obtained from BSEG in lnkarea()*/
99 "H C areas 0 global symbols",
100 "A _CODE size 0 flags 0", /*Each .rel has one, so...*/
101 "A REG_BANK_0 size 0 flags 4", /*Register banks are overlayable*/
102 "A REG_BANK_1 size 0 flags 4",
103 "A REG_BANK_2 size 0 flags 4",
104 "A REG_BANK_3 size 0 flags 4",
105 "A BSEG size 0 flags 80", /*BSEG must be just before BITS*/
106 "A BSEG_BYTES size 0 flags 0", /*Size will be obtained from BSEG in lnkarea()*/
107 "A BIT_BANK size 0 flags 4", /*Bit register bank is overlayable*/
108 "A DSEG size 0 flags 0",
109 "A OSEG size 0 flags 4",
110 "A ISEG size 0 flags 0",
111 "A SSEG size 0 flags 4",
119 for (j=0; rel2[j][0]!=0; j++)
127 for (j=0; rel[j][0]!=0; j++)
134 /*Set the start address of the default areas:*/
135 for(ap=areap; ap; ap=ap->a_ap)
137 /**/ if (!strcmp(ap->a_id, "REG_BANK_0")) { ap->a_addr=0x00; ap->a_type=1; }
138 else if (!strcmp(ap->a_id, "REG_BANK_1")) { ap->a_addr=0x08; ap->a_type=1; }
139 else if (!strcmp(ap->a_id, "REG_BANK_2")) { ap->a_addr=0x10; ap->a_type=1; }
140 else if (!strcmp(ap->a_id, "REG_BANK_3")) { ap->a_addr=0x18; ap->a_type=1; }
141 else if (!strcmp(ap->a_id, "BSEG_BYTES")) { ap->a_addr=0x20; ap->a_type=1; }
142 else if (!strcmp(ap->a_id, "SSEG"))
144 if(stacksize) ap->a_axp->a_size=stacksize;
148 sp = lkpsym("l_IRAM", 1);
149 sp->s_addr = ((iram_size>0) && (iram_size<=0x100)) ? iram_size : 0x0100;
154 /*)Function VOID main(argc,argv)
156 * int argc number of command line arguments + 1
157 * char * argv[] array of pointers to the command line
160 * The function main() evaluates the command line arguments to
161 * determine if the linker parameters are to input through 'stdin'
162 * or read from a command file. The functions lk_getline() and parse()
163 * are to input and evaluate the linker parameters. The linking process
164 * proceeds by making the first pass through each .rel file in the order
165 * presented to the linker. At the end of the first pass the setbase(),
166 * lnkarea(), setgbl(), and symdef() functions are called to evaluate
167 * the base address terms, link all areas, define global variables,
168 * and look for undefined symbols. Following these routines a linker
169 * map file may be produced and the linker output files may be opened.
170 * The second pass through the .rel files will output the linked data
171 * in one of the four supported formats.
174 * char * p pointer to an argument string
175 * int c character from argument string
180 * lfile *cfp The pointer *cfp points to the
181 * current lfile structure
182 * char ctype[] array of character types, one per
184 * lfile *filep The pointer *filep points to the
185 * beginning of a linked list of
187 * head *hp Pointer to the current
189 * char ib[NINPUT] .rel file text line
190 * char *ip pointer into the .rel file
191 * lfile *linkp pointer to first lfile structure
192 * containing an input .rel file
194 * int lkerr error flag
195 * int mflag Map output flag
196 * int oflag Output file type flag
197 * FILE *ofp Output file handle
199 * FILE *ofph Output file handle
200 * for high byte format
201 * FILE *ofpl Output file handle
202 * for low byte format
203 * int pass linker pass number
204 * int pflag print linker command file flag
205 * int radix current number conversion radix
206 * FILE *sfp The file handle sfp points to the
207 * currently open file
208 * lfile *startp asmlnk startup file structure
209 * FILE * stdin c_library
210 * FILE * stdout c_library
213 * FILE * afile() lkmain.c
214 * int fclose() c_library
215 * int fprintf() c_library
216 * int lk_getline() lklex.c
217 * VOID library() lklibr.c
218 * VOID link_main() lkmain.c
219 * VOID lkexit() lkmain.c
220 * VOID lnkarea() lkarea.c
221 * VOID map() lkmain.c
223 * int parse() lkmain.c
224 * VOID reloc() lkreloc.c
225 * VOID search() lklibr.c
226 * VOID setbas() lkmain.c
227 * VOID setgbl() lkmain.c
228 * VOID symdef() lksym.c
229 * VOID usage() lkmain.c
232 * Completion of main() completes the linking process
233 * and may produce a map file (.map) and/or a linked
234 * data files (.ihx or .s19) and/or one or more
235 * relocated listing files (.rst).
239 main(int argc, char *argv[])
248 startp = (struct lfile *) new (sizeof (struct lfile));
251 for (i=1; i<argc; ++i) {
254 while (ctype[c = *(++p)] & LETTER) {
259 startp->f_type = F_STD;
264 startp->f_type = F_LNK;
282 if (startp->f_type == F_LNK) {
287 if (startp->f_type == 0)
289 if (startp->f_type == F_LNK && startp->f_idp == NULL)
297 if (lk_getline() == 0)
299 if (pflag && sfp != stdin)
300 fprintf(stdout, "%s\n", ip);
301 if (*ip == '\0' || parse())
316 //dfp = afile("temp", "cdb", 1);
317 SaveLinkedFilePath(linkp->f_idp); //Must be the first one...
318 dfp = afile(linkp->f_idp,"cdb",1); //JCF: Nov 30, 2002
323 for (pass=0; pass<2; ++pass) {
330 Areas51(); /*JCF: Create the default 8051 areas in the right order*/
332 while (lk_getline()) {
335 /* pass any "magic comments" to NoICE output */
336 if ((ip[0] == ';') && (ip[1] == '!') && jfp) {
337 fprintf( jfp, "%s\n", &ip[2] );
343 * Search libraries for global symbols
347 * Set area base addresses.
351 * Link all area addresses.
358 * Process global definitions.
362 * Check for undefined globals.
366 /* Open NoICE output file if requested */
368 jfp = afile(linkp->f_idp, "NOI", 1);
375 * Output Link Map if requested,
376 * or if NoICE output requested (since NoICE
377 * file is generated in part by map() processing)
382 if (sflag) /*JCF: memory usage summary output*/
386 if(summary(areap)) lkexit(1);
390 if(summary2(areap)) lkexit(1);
394 if ((iram_size) && (!packflag))
401 ofp = afile(linkp->f_idp, "ihx", 1);
405 /* include NoICE command to load hex file */
406 if (jfp) fprintf( jfp, "LOAD %s.IHX\n", linkp->f_idp );
410 ofp = afile(linkp->f_idp, "S19", 1);
414 /* include NoICE command to load hex file */
415 if (jfp) fprintf( jfp, "LOAD %s.S19\n", linkp->f_idp );
419 * Link in library files
429 Timer(1, "Linker execution time");
434 /* Never get here. */
438 /*)Function VOID lkexit(i)
442 * The function lkexit() explicitly closes all open
443 * files and then terminates the program.
449 * FILE * mfp file handle for .map
450 * FILE * ofp file handle for .ihx/.s19
451 * FILE * rfp file hanlde for .rst
452 * FILE * sfp file handle for .rel
453 * FILE * tfp file handle for .lst
456 * int fclose() c_library
457 * VOID exit() c_library
460 * All files closed. Program terminates.
466 if (mfp != NULL) fclose(mfp);
467 if (jfp != NULL) fclose(jfp);
468 if (ofp != NULL) fclose(ofp);
469 if (rfp != NULL) fclose(rfp);
470 if (sfp != NULL) fclose(sfp);
471 if (tfp != NULL) fclose(tfp);
472 if (dfp != NULL) fclose(dfp);
476 /*)Function link_main()
478 * The function link_main() evaluates the directives for each line of
479 * text read from the .rel file(s). The valid directives processed
481 * X, D, Q, H, M, A, S, T, R, and P.
484 * int c first non blank character of a line
487 * head *headp The pointer to the first
488 * head structure of a linked list
489 * head *hp Pointer to the current
491 * int pass linker pass number
492 * int radix current number conversion radix
495 * char endline() lklex.c
496 * VOID module() lkhead.c
497 * VOID newarea() lkarea.c
498 * VOID newhead() lkhead.c
499 * sym * newsym() lksym.c
500 * VOID reloc() lkreloc.c
503 * Head, area, and symbol structures are created and
504 * the radix is set as the .rel file(s) are read.
512 if ((c=endline()) == 0) { return; }
515 case 'O': /*For some important sdcc options*/
518 if(strlen(sdccopt)==0)
520 strcpy(sdccopt, &ip[1]);
521 strcpy(sdccopt_module, curr_module);
525 if(strcmp(sdccopt, &ip[1])!=0)
528 "?ASlink-Warning-Conflicting sdcc options:\n"
529 " \"%s\" in module \"%s\" and\n"
530 " \"%s\" in module \"%s\".\n",
531 sdccopt, sdccopt_module, &ip[1], curr_module);
568 strcpy(curr_module, &ip[1]);
576 if (sdp.s_area == NULL) {
578 sdp.s_areax = areap->a_axp;
599 if (c == 'X' || c == 'D' || c == 'Q') {
600 if ((c = get()) == 'H') {
609 /*)Function VOID map()
611 * The function map() opens the output map file and calls the various
613 * (1) output the variables in each area,
614 * (2) list the files processed with module names,
615 * (3) list the libraries file processed,
616 * (4) list base address definitions,
617 * (5) list global variable definitions, and
618 * (6) list any undefined variables.
622 * head * hdp pointer to head structure
623 * lbfile *lbfh pointer to library file structure
626 * area *ap Pointer to the current
628 * area *areap The pointer to the first
629 * area structure of a linked list
630 * base *basep The pointer to the first
632 * base *bsp Pointer to the current
634 * lfile *filep The pointer *filep points to the
635 * beginning of a linked list of
637 * globl *globlp The pointer to the first
639 * globl *gsp Pointer to the current
641 * head *headp The pointer to the first
642 * head structure of a linked list
643 * lbfile *lbfhead The pointer to the first
644 * lbfile structure of a linked list
645 * lfile *linkp pointer to first lfile structure
646 * containing an input REL file
648 * int lop current line number on page
649 * FILE *mfp Map output file handle
650 * int page current page number
653 * FILE * afile() lkmain.c
654 * int fprintf() c_library
655 * VOID lkexit() lkmain.c
656 * VOID lstarea() lklist.c
657 * VOID newpag() lklist.c
658 * VOID symdef() lksym.c
661 * The map file is created.
668 register struct head *hdp;
669 register struct lbfile *lbfh;
674 mfp = afile(linkp->f_idp, "map", 1);
680 * Output Map Area Lists
693 fprintf(mfp, "\nFiles Linked [ module(s) ]\n\n");
697 fprintf(mfp, "%-16s", filep->f_idp);
699 while ((hdp != NULL) && (hdp->h_lfile == filep)) {
701 fprintf(mfp, ", %8.8s", hdp->m_id);
704 fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id);
706 fprintf(mfp, " [ %8.8s", hdp->m_id);
715 filep = filep->f_flp;
718 * List Linked Libraries
720 if (lbfhead != NULL) {
722 "\nLibraries Linked [ object file ]\n\n");
723 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
724 fprintf(mfp, "%-32s [ %16.16s ]\n",
725 lbfh->libspc, lbfh->relfil);
730 * List Base Address Definitions
734 fprintf(mfp, "\nUser Base Address Definitions\n\n");
737 fprintf(mfp, "%s\n", bsp->b_strp);
742 * List Global Definitions
746 fprintf(mfp, "\nUser Global Definitions\n\n");
749 fprintf(mfp, "%s\n", gsp->g_strp);
753 fprintf(mfp, "\n\f");
757 /*)Function int parse()
759 * The function parse() evaluates all command line or file input
760 * linker directives and updates the appropriate variables.
763 * int c character value
764 * char fid[] file id string
767 * char ctype[] array of character types, one per
769 * lfile *lfp pointer to current lfile structure
770 * being processed by parse()
771 * lfile *linkp pointer to first lfile structure
772 * containing an input REL file
774 * int mflag Map output flag
775 * int oflag Output file type flag
776 * int pflag print linker command file flag
777 * FILE * stderr c_library
778 * int uflag Relocated listing flag
779 * int xflag Map file radix type flag
782 * VOID addlib() lklibr.c
783 * VOID addpath() lklibr.c
784 * VOID bassav() lkmain.c
785 * int fprintf() c_library
786 * VOID gblsav() lkmain.c
787 * VOID getfid() lklex.c
788 * char getnb() lklex.c
789 * VOID lkexit() lkmain.c
790 * char * strcpy() c_library
791 * int strlen() c_library
794 * Various linker flags are updated and the linked
795 * structure lfile is created.
804 while ((c = getnb()) != 0) {
808 while (ctype[c=get()] & LETTER) {
826 case 'y': /*JCF: memory usage summary output*/
840 if(stacksize>256) stacksize=256;
841 else if(stacksize<0) stacksize=0;
927 fprintf(stderr, "Invalid option\n");
934 if (ctype[c] & ILL) {
935 fprintf(stderr, "Invalid input");
939 linkp = (struct lfile *)
940 new (sizeof (struct lfile));
943 lfp->f_flp = (struct lfile *)
944 new (sizeof (struct lfile));
948 lfp->f_idp = (char *) new (strlen(fid)+1);
949 strcpy(lfp->f_idp, fid);
956 /*)Function VOID bassav()
958 * The function bassav() creates a linked structure containing
959 * the base address strings input to the linker.
965 * base *basep The pointer to the first
967 * base *bsp Pointer to the current
969 * char *ip pointer into the REL file
973 * char getnb() lklex.c
974 * VOID * new() lksym.c
975 * int strlen() c_library
976 * char * strcpy() c_library
977 * VOID unget() lklex.c
980 * The basep structure is created.
987 basep = (struct base *)
988 new (sizeof (struct base));
991 bsp->b_base = (struct base *)
992 new (sizeof (struct base));
996 bsp->b_strp = (char *) new (strlen(ip)+1);
997 strcpy(bsp->b_strp, ip);
1000 /*)Function VOID setbas()
1002 * The function setbas() scans the base address lines in the
1003 * basep structure, evaluates the arguments, and sets beginning
1004 * address of the specified areas.
1007 * int v expression value
1008 * char id[] base id string
1011 * area *ap Pointer to the current
1013 * area *areap The pointer to the first
1014 * area structure of a linked list
1015 * base *basep The pointer to the first
1017 * base *bsp Pointer to the current
1019 * char *ip pointer into the REL file
1021 * int lkerr error flag
1024 * Addr_T expr() lkeval.c
1025 * int fprintf() c_library
1026 * VOID getid() lklex.c
1027 * char getnb() lklex.c
1028 * int symeq() lksym.c
1031 * The base address of an area is set.
1044 if (getnb() == '=') {
1046 for (ap = areap; ap != NULL; ap = ap->a_ap) {
1047 if (symeq(id, ap->a_id))
1052 "ASlink-Warning-No definition of area %s\n", id);
1056 ap->a_type = 1; /* JLH: value set */
1059 fprintf(stderr, "ASlink-Warning-No '=' in base expression");
1066 /*)Function VOID gblsav()
1068 * The function gblsav() creates a linked structure containing
1069 * the global variable strings input to the linker.
1075 * globl *globlp The pointer to the first
1077 * globl *gsp Pointer to the current
1079 * char *ip pointer into the REL file
1081 * int lkerr error flag
1084 * char getnb() lklex.c
1085 * VOID * new() lksym.c
1086 * int strlen() c_library
1087 * char * strcpy() c_library
1088 * VOID unget() lklex.c
1091 * The globlp structure is created.
1097 if (globlp == NULL) {
1098 globlp = (struct globl *)
1099 new (sizeof (struct globl));
1102 gsp->g_globl = (struct globl *)
1103 new (sizeof (struct globl));
1107 gsp->g_strp = (char *) new (strlen(ip)+1);
1108 strcpy(gsp->g_strp, ip);
1111 /*)Function VOID setgbl()
1113 * The function setgbl() scans the global variable lines in the
1114 * globlp structure, evaluates the arguments, and sets a variable
1118 * int v expression value
1119 * char id[] base id string
1120 * sym * sp pointer to a symbol structure
1123 * char *ip pointer into the REL file
1125 * globl *globlp The pointer to the first
1127 * globl *gsp Pointer to the current
1129 * FILE * stderr c_library
1130 * int lkerr error flag
1133 * Addr_T expr() lkeval.c
1134 * int fprintf() c_library
1135 * VOID getid() lklex.c
1136 * char getnb() lklex.c
1137 * sym * lkpsym() lksym.c
1140 * The value of a variable is set.
1147 register struct sym *sp;
1154 if (getnb() == '=') {
1158 fprintf(stderr, "No definition of symbol %s\n", id);
1161 if (sp->s_flag & S_DEF) {
1162 fprintf(stderr, "Redefinition of symbol %s\n", id);
1167 sp->s_type |= S_DEF;
1170 fprintf(stderr, "No '=' in global expression");
1177 /*)Function FILE * afile(fn, ft, wf)
1179 * char * fn file specification string
1180 * char * ft file type string
1181 * int wf read(0)/write(1) flag
1183 * The function afile() opens a file for reading or writing.
1184 * (1) If the file type specification string ft
1185 * is not NULL then a file specification is
1186 * constructed with the file path\name in fn
1187 * and the extension in ft.
1188 * (2) If the file type specification string ft
1189 * is NULL then the file specification is
1190 * constructed from fn. If fn does not have
1191 * a file type then the default .rel file
1192 * type is appended to the file specification.
1194 * afile() returns a file handle for the opened file or aborts
1195 * the assembler on an open error.
1198 * char fb[] constructed file specification string
1199 * FILE * fp filehandle for opened file
1202 * int lkerr error flag
1205 * FILE * fopen() c_library
1206 * int fprintf() c_library
1209 * File is opened for read or write.
1213 afile(char *fn, char *ft, int wf)
1221 case 0: omode = "r"; break;
1222 case 1: omode = "w"; break;
1223 case 2: omode = "a"; break;
1224 case 3: omode = "rb"; break;
1225 case 4: omode = "wb"; break;
1226 case 5: omode = "ab"; break;
1227 default: omode = "r"; break;
1230 /*Look backward the name path and get rid of the extension, if any*/
1232 for(; (fn[i]!=FSEPX)&&(fn[i]!=LKDIRSEP)&&(fn[i]!='/')&&(i>0); i--);
1233 if( (fn[i]==FSEPX) && strcmp(ft, "lnk") )
1243 /*Add the extension*/
1248 strcat(fb, strlen(ft)?ft:LKOBJEXT);
1251 fp = fopen(fb, omode);
1254 if (strcmp(ft,"adb"))/*Do not complain for optional adb files*/
1256 fprintf(stderr, "%s: cannot %s.\n", fb, (wf%3)==1?"create":"open");
1263 /*)Function VOID iramsav()
1265 * The function iramsav() stores the size of the chip's internal RAM.
1266 * This is used after linking to check that variable assignment to this
1267 * dataspace didn't overflow into adjoining segments. Variables in the
1268 * DSEG, OSEG, and ISEG are assigned to this dataspace.
1274 * char *ip pointer into the REL file
1276 * unsigned int size of chip's internal
1277 * iram_size RAM segment
1280 * char getnb() lklex.c
1281 * VOID unget() lklex.c
1282 * Addr_T expr() lkeval.c
1285 * The iram_size may be modified.
1293 iram_size = expr(0); /* evaluate size expression */
1295 iram_size = 128; /* Default is 128 (0x80) bytes */
1296 if ((iram_size<=0) || (iram_size>256))
1297 iram_size = 128; /* Default is 128 (0x80) bytes */
1300 /*Similar to iramsav but for xram memory*/
1306 xram_size = expr(0); /* evaluate size expression */
1308 xram_size = rflag?0x1000000:0x10000;
1311 /*Similar to iramsav but for code memory*/
1317 code_size = expr(0); /* evaluate size expression */
1319 code_size = rflag?0x1000000:0x10000;
1323 /*)Function VOID iramcheck()
1325 * The function iramcheck() is used at the end of linking to check that
1326 * the internal RAM area wasn't overflowed by too many variable
1327 * assignments. Variables in the DSEG, ISEG, and OSEG are assigned to
1328 * the chip's internal RAM.
1334 * unsigned int size of chip's internal
1335 * iram_size RAM segment
1336 * struct area linked list of memory
1347 register unsigned int last_addr;
1348 register struct area *ap;
1350 for (ap = areap; ap; ap=ap->a_ap) {
1351 if ((ap->a_size != 0) &&
1352 (!strcmp(ap->a_id, "DSEG") ||
1353 !strcmp(ap->a_id, "OSEG") ||
1354 !strcmp(ap->a_id, "ISEG")
1358 last_addr = ap->a_addr + ap->a_size - 1;
1359 if (last_addr >= iram_size)
1361 "\nWARNING! Segment %s extends past the end\n"
1362 " of internal RAM. Check map file.\n",
1370 " -c Command line input",
1371 " -f file[LNK] File input",
1372 " -p Prompt and echo of file[LNK] to stdout (default)",
1373 " -n No echo of file[LNK] to stdout",
1374 /* "Usage: [-Options] file [file ...]", */
1376 " -k Library path specification, one per -k",
1377 " -l Library file specification, one per -l",
1379 " -b area base address = expression",
1380 " -g global symbol = expression",
1382 " -m Map output generated as file[MAP]",
1383 " -x Hexadecimal (default), -d Decimal, -q Octal",
1385 " -i Intel Hex as file[IHX]",
1386 " -s Motorola S19 as file[S19]",
1387 " -j Produce NoICE debug as file[NOI]",
1388 " -z Produce SDCdb debug as file[cdb]",
1390 " -u Update listing file(s) with link data as file(s)[.RST]",
1392 " -a [iram-size] Check for internal RAM overflow",
1393 " -v [xram-size] Check for external RAM overflow",
1394 " -w [code-size] Check for code overflow",
1395 " -y Generate memory usage summary file[mem]",
1396 " -Y Pack internal ram",
1397 " -A [stack-size] Allocate space for stack",
1399 " -e or null line terminates input",
1403 /*)Function VOID usage()
1405 * The function usage() outputs to the stderr device the
1406 * assembler name and version and a list of valid assembler options.
1409 * char ** dp pointer to an array of
1410 * text string pointers.
1413 * FILE * stderr c_library
1416 * int fprintf() c_library
1427 fprintf(stderr, "\nASxxxx Linker %s\n\n", VERSION);
1428 for (dp = usetxt; *dp; dp++)
1429 fprintf(stderr, "%s\n", *dp);
1433 /*)Function VOID copyfile()
1435 * FILE *dest destination file
1436 * FILE *src source file
1438 * function will copy source file to destination file
1442 * int fgetc() c_library
1443 * int fputc() c_library
1448 VOID copyfile (FILE *dest, FILE *src)
1452 while ((ch = fgetc(src)) != EOF) {