Lengthened the maximum filename to 100 chars
[fw/sdcc] / link / z80 / lklibr.c
1 /* lklibr.c */
2
3 /*
4  * (C) Copyright 1989-1995
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  *
11  * With contributions for the
12  * object libraries from
13  * Ken Hornstein
14  * kenh@cmf.nrl.navy.mil
15  *
16  */
17
18 /*
19  * Extensions: P. Felber
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include "aslink.h"
26
27 /*)Module       lklibr.c
28  *
29  *      The module lklibr.c contains the functions which
30  *      (1) specify the path(s) to library files [.LIB]
31  *      (2) specify the library file(s) [.LIB] to search
32  *      (3) search the library files for specific symbols
33  *          and link the module containing this symbol
34  *
35  *      lklibr.c contains the following functions:
36  *              VOID    addpath()
37  *              VOID    addlib()
38  *              VOID    addfile()
39  *              VOID    search()
40  *              VOID    fndsym()
41  *              VOID    library()
42  *              VOID    loadfile()
43  *
44  */
45
46 #ifdef INDEXLIB
47 typedef struct slibrarysymbol mlibrarysymbol;
48 typedef struct slibrarysymbol *pmlibrarysymbol;
49
50 struct slibrarysymbol {
51         char name[40];
52         pmlibrarysymbol next;
53 };
54
55 typedef struct slibraryfile mlibraryfile;
56 typedef struct slibraryfile *pmlibraryfile;
57
58 struct slibraryfile {
59         int loaded;
60         char *libspc;
61         char *str;
62         char relfil[FILSPC];
63         char filename[FILSPC];
64         pmlibrarysymbol symbols;
65         pmlibraryfile next;
66 };
67
68 int buildlibraryindex();
69 #endif /* INDEXLIB */
70
71 /*)Function     VOID    addpath()
72  *
73  *      The function addpath() creates a linked structure containing
74  *      the paths to various object module library files.
75  *
76  *      local variables:
77  *              lbpath  *lbph           pointer to new path structure
78  *              lbpath  *lbp            temporary pointer
79  *
80  *      global variables:
81  *              lbpath  *lbphead        The pointer to the first
82  *                                      path structure
83  *
84  *       functions called:
85  *              char    getnb()         lklex.c
86  *              VOID *  new()           lksym.c
87  *              int     strlen()        c_library
88  *              char *  strcpy()        c_library
89  *              VOID    unget()         lklex.c
90  *
91  *      side effects:
92  *              An lbpath structure may be created.
93  */
94
95 VOID
96 addpath()
97 {
98         struct lbpath *lbph, *lbp;
99
100         lbph = (struct lbpath *) new (sizeof(struct lbpath));
101         if (lbphead == NULL) {
102                 lbphead = lbph;
103         } else {
104                 lbp = lbphead;
105                 while (lbp->next)
106                         lbp = lbp->next;
107                 lbp->next = lbph;
108         }
109         unget(getnb());
110         lbph->path = (char *) new (strlen(ip)+1);
111         strcpy(lbph->path, ip);
112 }
113
114 /*)Function     VOID    addlib()
115  *
116  *      The function addlib() tests for the existance of a
117  *      library path structure to determine the method of
118  *      adding this library file to the library search structure.
119  *
120  *      This function calls the function addfile() to actually
121  *      add the library file to the search list.
122  *
123  *      local variables:
124  *              lbpath  *lbph           pointer to path structure
125  *
126  *      global variables:
127  *              lbpath  *lbphead        The pointer to the first
128  *                                      path structure
129  *
130  *       functions called:
131  *              VOID    addfile()       lklibr.c
132  *              char    getnb()         lklex.c
133  *              VOID    unget()         lklex.c
134  *
135  *      side effects:
136  *              The function addfile() may add the file to
137  *              the library search list.
138  */
139
140 VOID
141 addlib()
142 {
143         struct lbpath *lbph;
144
145         unget(getnb());
146
147         if (lbphead == NULL) {
148                 addfile(NULL,ip);
149                 return;
150         }       
151         for (lbph=lbphead; lbph; lbph=lbph->next) {
152                 addfile(lbph->path,ip);
153         }
154 }
155
156 /*)Function     VOID    addfile(path,libfil)
157  *
158  *              char    *path           library path specification
159  *              char    *libfil         library file specification
160  *
161  *      The function addfile() searches for the library file
162  *      by concatenating the path and libfil specifications.
163  *      if the library is found, an lbname structure is created
164  *      and linked to any previously defined structures.  This
165  *      linked list is used by the function fndsym() to attempt
166  *      to find any undefined symbols.
167  *
168  *      The function does not give report an error on invalid
169  *      path / file specifications or if the file is not found.
170  *
171  *      local variables:
172  *              lbname  *lbnh           pointer to new name structure
173  *              lbname  *lbn            temporary pointer
174  *
175  *      global variables:
176  *              lbname  *lbnhead        The pointer to the first
177  *                                      path structure
178  *
179  *       functions called:
180  *              char    getnb()         lklex.c
181  *              VOID *  new()           lksym.c
182  *              int     strlen()        c_library
183  *              char *  strcpy()        c_library
184  *              VOID    unget()         lklex.c
185  *
186  *      side effects:
187  *              An lbname structure may be created.
188  */
189
190 VOID
191 addfile(path,libfil)
192 char *path;
193 char *libfil;
194 {
195         FILE *fp;
196         char *str;
197         struct lbname *lbnh, *lbn;
198
199         if ((path != NULL) && (strchr(libfil,':') == NULL)){
200                 str = (char *) new (strlen(path) + strlen(libfil) + 6);
201                 strcpy(str,path);
202 #ifdef  OTHERSYSTEM
203 #ifdef SDK
204 #ifdef UNIX
205                 if (str[strlen(str)-1] != '/') {
206                         strcat(str,"/");
207 #else /* UNIX */
208                 if (str[strlen(str)-1] != '\\') {
209                         strcat(str,"\\");
210 #endif /* UNIX */
211 #else /* SDK */
212                 if (str[strlen(str)-1] != '\\') {
213                         strcat(str,"\\");
214 #endif /* SDK */
215                 }
216 #endif
217         } else {
218                 str = (char *) new (strlen(libfil) + 5);
219         }
220 #ifdef  OTHERSYSTEM
221 #ifdef SDK
222 #ifdef UNIX
223         if (libfil[0] == '/') { libfil++; }
224 #else /* UNIX */
225         if (libfil[0] == '\\') { libfil++; }
226 #endif /* UNIX */
227 #else /* SDK */
228         if (libfil[0] == '\\') { libfil++; }
229 #endif /* SDK */
230 #endif
231         strcat(str,libfil);
232         if(strchr(str,FSEPX) == NULL) {
233                 sprintf(&str[strlen(str)], "%clib", FSEPX);
234         }
235         if ((fp = fopen(str, "r")) != NULL) {
236                 fclose(fp);
237                 lbnh = (struct lbname *) new (sizeof(struct lbname));
238                 if (lbnhead == NULL) {
239                         lbnhead = lbnh;
240                 } else {
241                         lbn = lbnhead;
242                         while (lbn->next)
243                                 lbn = lbn->next;
244                         lbn->next = lbnh;
245                 }
246                 if ((path != NULL) && (strchr(libfil,':') == NULL)){
247                         lbnh->path = path;
248                 }
249                 lbnh->libfil = (char *) new (strlen(libfil) + 1);
250                 strcpy(lbnh->libfil,libfil);
251                 lbnh->libspc = str;
252         } else {
253                 free(str);
254         }
255 }
256
257 /*)Function     VOID    search()
258  *
259  *      The function search() looks through all the symbol tables
260  *      at the end of pass 1.  If any undefined symbols are found
261  *      then the function fndsym() is called. Function fndsym()
262  *      searches any specified library files to automagically
263  *      import the object modules containing the needed symbol.
264  *
265  *      After a symbol is found and imported by the function
266  *      fndsym() the symbol tables are again searched.  The
267  *      symbol tables are search until no more symbols can be
268  *      resolved within the library files.  This ensures that
269  *      back references from one library module to another are
270  *      also resolved.
271  *
272  *      local variables:
273  *              int     i               temporary counter
274  *              sym     *sp             pointer to a symbol structure
275  *              int     symfnd          found a symbol flag
276  *
277  *      global variables:
278  *              sym     *symhash[]      array of pointers to symbol tables
279  *
280  *       functions called:
281  *              int     fndsym()        lklibr.c
282  *
283  *      side effects:
284  *              If a symbol is found then the library object module
285  *              containing the symbol will be imported and linked.
286  */
287
288 VOID
289 search()
290 {
291         register struct sym *sp;
292         register int i, symfnd;
293
294         /*
295          * Look for undefined symbols.  Keep
296          * searching until no more symbols are resolved.
297          */
298         symfnd = 1;
299         while (symfnd) {
300                 symfnd = 0;
301                 /*
302                  * Look through all the symbols
303                  */
304                 for (i=0; i<NHASH; ++i) {
305                         sp = symhash[i];
306                         while (sp) {
307                                 /* If we find an undefined symbol
308                                  * (one where S_DEF is not set), then
309                                  * try looking for it.  If we find it
310                                  * in any of the libraries then
311                                  * increment symfnd.  This will force
312                                  * another pass of symbol searching and
313                                  * make sure that back references work.
314                                  */
315                                 if ((sp->s_type & S_DEF) == 0) {
316                                         if (fndsym(sp->s_id)) {
317                                                 symfnd++;
318                                         }
319                                 }
320                                 sp = sp->s_sp;
321                         }
322                 }
323         }
324 }
325
326
327 /*)Function     VOID    fndsym(name)
328  *
329  *              char    *name           symbol name to find
330  *
331  *      The function fndsym() searches through all combinations of the
332  *      library path specifications (input by the -k option) and the
333  *      library file specifications (input by the -l option) that
334  *      lead to an existing file.
335  *
336  *      The file specicifation may be formed in one of two ways:
337  *
338  *      (1)     If the library file contained an absolute
339  *              path/file specification then this becomes filspc.
340  *              (i.e. C:\...)
341  *
342  *      (2)     If the library file contains a relative path/file
343  *              specification then the concatenation of the path
344  *              and this file specification becomes filspc.
345  *              (i.e. \...)
346  *
347  *      The structure lbfile is created for the first library
348  *      object file which contains the definition for the
349  *      specified undefined symbol.
350  *
351  *      If the library file [.LIB] contains file specifications for
352  *      non existant files, no errors are returned.
353  *
354  *      local variables:
355  *              char    buf[]           [.REL] file input line
356  *              char    c               [.REL] file input character
357  *              FILE    *fp             file handle for object file
358  *              lbfile  *lbf            temporary pointer
359  *              lbfile  *lbfh           pointer to lbfile structure
360  *              FILE    *libfp          file handle for library file
361  *              lbname  *lbnh           pointer to lbname structure
362  *              char    *path           file specification path
363  *              char    relfil[]        [.REL] file specification
364  *              char    *str            combined path and file specification
365  *              char    symname[]       [.REL] file symbol string
366  *
367  *      global variables:
368  *              lbname  *lbnhead        The pointer to the first
369  *                                      name structure
370  *              lbfile  *lbfhead        The pointer to the first
371  *                                      file structure
372  *
373  *       functions called:
374  *              int     fclose()        c_library
375  *              int     fgets()         c_library
376  *              FILE    *fopen()        c_library
377  *              VOID    free()          c_library
378  *              char    getnb()         lklex.c
379  *              VOID    lkexit()        lkmain.c
380  *              VOID    loadfile()      lklibr.c
381  *              VOID *  new()           lksym.c
382  *              char *  sprintf()       c_library
383  *              int     sscanf()        c_library
384  *              char *  strcat()        c_library
385  *              char *  strchr()        c_library
386  *              char *  strcpy()        c_library
387  *              int     strlen()        c_library
388  *              int     strncmp()       c_library
389  *              VOID    unget()         lklex.c
390  *
391  *      side effects:
392  *              If the symbol is found then a new lbfile structure
393  *              is created and added to the linked list of lbfile
394  *              structures.  The file containing the found symbol
395  *              is linked.
396  */
397
398 #ifdef INDEXLIB
399
400 /* First entry in the library object symbol cache */
401 mlibraryfile libr;
402
403 int fndsym( char *name )
404 {
405         struct lbfile *lbfh, *lbf;
406         pmlibraryfile ThisLibr;
407         pmlibrarysymbol ThisSym = NULL;
408
409         /* Build the index if this is the first call to fndsym */
410         if (libr.next==NULL)
411                 buildlibraryindex();
412         
413         /* Iterate through all library object files */
414         ThisLibr = libr.next;
415         while (ThisLibr) {
416
417                 /* Iterate through all symbols in an object file */
418                 ThisSym = ThisLibr->symbols->next;
419
420                 while (ThisSym) {
421                         if (!strcmp(ThisSym->name, name)) {
422                                 if (!ThisLibr->loaded) {
423                                         /* Object file is not loaded - add it to the list */
424                                         lbfh = (struct lbfile *) new (sizeof(struct lbfile));
425                                         if (lbfhead == NULL) {
426                                                 lbfhead = lbfh;
427                                         } else {
428                                                 lbf = lbfhead;
429                                                 while (lbf->next)
430                                                 lbf = lbf->next;
431                                                 lbf->next = lbfh;
432                                         }
433                                         lbfh->libspc = ThisLibr->libspc;
434                                         lbfh->filspc = ThisLibr->str;
435                                         lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
436                                         strcpy(lbfh->relfil,ThisLibr->relfil);
437                                         loadfile(lbfh->filspc);
438                                         ThisLibr->loaded=1;
439                                 }
440                                 return (1);     /* Found the symbol, return */
441                         }
442                         ThisSym=ThisSym->next;  /* Next sym in library */
443                 }
444                 ThisLibr=ThisLibr->next; /* Next library in list */
445         }
446         return 0;       /* Failure - symbol not found in any library */
447 };
448
449 /* buildlibraryindex - build an in-memory cache of the symbols contained in
450  *                      the libraries
451  */
452
453 int buildlibraryindex()
454 {
455         FILE *libfp, *fp;
456         struct lbname *lbnh;
457         char relfil[NINPUT+2], *str, *path;
458         char buf[NINPUT+2], c;
459         char symname[NINPUT+2];
460         pmlibraryfile This;
461         pmlibrarysymbol ThisSym;
462
463         This=&libr;
464
465         /* Iterate through all library files */
466 /*1*/   for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
467                 libfp = fopen( lbnh->libspc, "r" );
468                 if (libfp) {
469                         path=lbnh->path;
470
471                         /*
472                          * Read in a line from the library file.
473                          * This is the relative file specification
474                          * for a .REL file in this library.
475                          */
476
477 /*2*/                   while (fgets(relfil, NINPUT, libfp) != NULL) {
478                                 relfil[NINPUT+1] = '\0';
479                                 relfil[strlen(relfil) - 1] = '\0';
480                                 if (path != NULL) {
481                                         str = (char *)new(strlen(path)+strlen(relfil)+6);
482                                         strcpy(str,path);
483 #ifdef  OTHERSYSTEM
484 #ifdef SDK
485 #ifdef UNIX
486                                         if (str[strlen(str)-1] != '/') {
487                                                 strcat(str,"/");
488 #else /* UNIX */
489                                         if (str[strlen(str)-1] != '\\') {
490                                                 strcat(str,"\\");
491 #endif /* UNIX */
492 #else /* SDK */
493                                         if (str[strlen(str)-1] != '\\') {
494                                                 strcat(str,"\\");
495 #endif /* SDK */
496                                         }
497 #endif
498                                 } else {
499                                         str = (char *)new(strlen(relfil) + 5);
500                                 }
501 #ifdef SDK
502 #ifdef UNIX
503                                 if (relfil[0] == '/') {
504 #else /* UNIX */
505                                 if (relfil[0] == '\\') {
506 #endif /* UNIX */
507 #else /* SDK */
508                                 if (relfil[0] == '\\') {
509 #endif /* SDK */
510                                         strcat(str,relfil+1);
511                                 } else {
512                                         strcat(str,relfil);
513                                 }
514                                 if(strchr(str,FSEPX) == NULL) {
515 #ifdef SDK
516                                         sprintf(&str[strlen(str)], "%co", FSEPX);
517 #else /* SDK */
518                                         sprintf(&str[strlen(str)], "%crel", FSEPX);
519 #endif /* SDK */
520                                 }
521 /*3*/                           if ((fp = fopen(str, "r")) != NULL) {
522
523                                         /* Opened OK - create a new libraryfile object for it */
524                                         This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
525                                         if (This->next == NULL) {
526                                                 printf("panic: cant allocate memory.\n");
527                                                 exit(-1);
528                                         }
529
530                                         This=This->next;
531                                         This->next = NULL;
532                                         This->loaded=-1;
533
534                                         strcpy( This->filename, str );
535
536                                         ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
537                                         ThisSym->next = NULL;
538
539                                         /*
540                                          * Read in the object file.  Look for lines that
541                                          * begin with "S" and end with "D".  These are
542                                          * symbol table definitions.  If we find one, see
543                                          * if it is our symbol.  Make sure we only read in
544                                          * our object file and don't go into the next one.
545                                          */
546                         
547 /*4*/                                   while (fgets(buf, NINPUT, fp) != NULL) {
548
549                                         buf[NINPUT+1] = '\0';
550                                         buf[strlen(buf) - 1] = '\0';
551
552                                         /*
553                                          * Skip everything that's not a symbol record.
554                                          */
555                                         if (buf[0] != 'S')
556                                                 continue;
557
558                                         /*
559                                          * When a 'T line' is found terminate file scan.
560                                          * All 'S line's preceed 'T line's in .REL files.
561                                          */
562                                         if (buf[0] == 'T')
563                                                 break;
564
565                                         sscanf(buf, "S %s %c", symname, &c);
566
567                                         /* If it's an actual symbol, record it */
568 /*5*/                                   if (c == 'D') {
569                                                 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
570                                                 ThisSym=ThisSym->next;
571                                                 if (ThisSym == NULL) {
572                                                         printf("panic: cant allocate memory.\n");
573                                                         exit(-2);
574                                                 }
575                                                 This->loaded=0;
576                                                 ThisSym->next=NULL;
577                                                 This->str = str;
578                                                 strcpy(This->relfil,relfil);
579                                                 strcpy(ThisSym->name, symname);
580                                                 This->libspc = lbnh->libspc;
581                                         }
582                                 } /* Closes while - read object file */
583                                 fclose(fp);
584                         } /* Closes if object file opened OK */
585                 } /* Ends while - processing all in libr */
586                 fclose(libfp);
587         } /* Ends good open of libr file */
588         }
589         return 0;
590 }
591 #else /* INDEXLIB */
592
593 int
594 fndsym(name)
595 char *name;
596 {
597         FILE *libfp, *fp;
598         struct lbname *lbnh;
599         struct lbfile *lbfh, *lbf;
600         char relfil[NINPUT+2];
601         char buf[NINPUT+2];
602         char symname[NINPUT];
603         char *path,*str;
604         char c;
605
606         /*
607          * Search through every library in the linked list "lbnhead".
608          */
609
610 /*1*/   for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
611                 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
612                         fprintf(stderr, "Cannot open library file %s\n",
613                                 lbnh->libspc);
614                         lkexit(1);
615                 }
616                 path = lbnh->path;
617
618                 /*
619                  * Read in a line from the library file.
620                  * This is the relative file specification
621                  * for a .REL file in this library.
622                  */
623
624 /*2*/           while (fgets(relfil, NINPUT, libfp) != NULL) {
625                     relfil[NINPUT+1] = '\0';
626                     relfil[strlen(relfil) - 1] = '\0';
627                     if (path != NULL) {
628                         str = (char *) new (strlen(path)+strlen(relfil)+6);
629                         strcpy(str,path);
630 #ifdef  OTHERSYSTEM
631 #ifdef SDK
632 #ifdef UNIX
633                         if (str[strlen(str)-1] != '/') {
634                                 strcat(str,"/");
635 #else /* UNIX */
636                         if (str[strlen(str)-1] != '\\') {
637                                 strcat(str,"\\");
638 #endif /* UNIX */
639 #else /* SDK */
640                         if (str[strlen(str)-1] != '\\') {
641                                 strcat(str,"\\");
642 #endif /* SDK */
643                         }
644 #endif
645                     } else {
646                         str = (char *) new (strlen(relfil) + 5);
647                     }
648 #ifdef SDK
649 #ifdef UNIX
650                     if (relfil[0] == '/') {
651 #else /* UNIX */
652                     if (relfil[0] == '\\') {
653 #endif /* UNIX */
654 #else /* SDK */
655                     if (relfil[0] == '\\') {
656 #endif /* SDK */
657                         strcat(str,relfil+1);
658                     } else {
659                         strcat(str,relfil);
660                     }
661                     if(strchr(str,FSEPX) == NULL) {
662 #ifdef SDK
663                         sprintf(&str[strlen(str)], "%co", FSEPX);
664 #else /* SDK */
665                         sprintf(&str[strlen(str)], "%crel", FSEPX);
666 #endif /* SDK */
667                     }
668 /*3*/               if ((fp = fopen(str, "r")) != NULL) {
669
670                         /*
671                          * Read in the object file.  Look for lines that
672                          * begin with "S" and end with "D".  These are
673                          * symbol table definitions.  If we find one, see
674                          * if it is our symbol.  Make sure we only read in
675                          * our object file and don't go into the next one.
676                          */
677                         
678 /*4*/                   while (fgets(buf, NINPUT, fp) != NULL) {
679
680                         buf[NINPUT+1] = '\0';
681                         buf[strlen(buf) - 1] = '\0';
682
683                         /*
684                          * Skip everything that's not a symbol record.
685                          */
686                         if (buf[0] != 'S')
687                                 continue;
688
689                         /*
690                          * When a 'T line' is found terminate file scan.
691                          * All 'S line's preceed 'T line's in .REL files.
692                          */
693                         if (buf[0] == 'T')
694                                 break;
695
696                         sscanf(buf, "S %s %c", symname, &c);
697
698                         /*
699                          * If we find a symbol definition for the
700                          * symbol we're looking for, load in the
701                          * file and add it to lbfhead so it gets
702                          * loaded on pass number 2.
703                          */
704 /*5*/                   if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
705
706                         lbfh = (struct lbfile *) new (sizeof(struct lbfile));
707                         if (lbfhead == NULL) {
708                                 lbfhead = lbfh;
709                         } else {
710                                 lbf = lbfhead;
711                                 while (lbf->next)
712                                         lbf = lbf->next;
713                                 lbf->next = lbfh;
714                         }
715                         lbfh->libspc = lbnh->libspc;
716                         lbfh->filspc = str;
717                         lbfh->relfil = (char *) new (strlen(relfil) + 1);
718                         strcpy(lbfh->relfil,relfil);
719                         fclose(fp);
720                         fclose(libfp);
721                         loadfile(str);
722                         return (1);
723
724 /*5*/                   }
725
726 /*4*/                   }
727                     fclose(fp);
728 /*3*/               }
729
730                     free(str);
731 /*2*/           }
732                 fclose(libfp);
733 /*1*/   }
734         return(0);
735 }
736 #endif /* INDEXLIB */
737
738 /*)Function     VOID    library()
739  *
740  *      The function library() links all the library object files
741  *      contained in the lbfile structures.
742  *
743  *      local variables:
744  *              lbfile  *lbfh           pointer to lbfile structure
745  *
746  *      global variables:
747  *              lbfile  *lbfhead        pointer to first lbfile structure
748  *
749  *       functions called:
750  *              VOID    loadfile        lklibr.c
751  *
752  *      side effects:
753  *              Links all files contained in the lbfile structures.
754  */
755
756 VOID
757 library()
758 {
759         struct lbfile *lbfh;
760
761         for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
762                 loadfile(lbfh->filspc);
763         }
764 }
765
766 /*)Function     VOID    loadfile(filspc)
767  *
768  *              char    *filspc         library object file specification
769  *
770  *      The function loadfile() links the library object module.
771  *
772  *      local variables:
773  *              FILE    *fp             file handle
774  *              int     i               input line length
775  *              char    str[]           file input line
776  *
777  *      global variables:
778  *              char    *ip             pointer to linker input string
779  *
780  *       functions called:
781  *              int     fclose()        c_library
782  *              int     fgets()         c_library
783  *              FILE *  fopen()         c_library
784  *              VOID    link()          lkmain.c
785  *              int     strlen()        c_library
786  *
787  *      side effects:
788  *              If file exists it is linked.
789  */
790
791 VOID
792 loadfile(filspc)
793 char *filspc;
794 {
795         FILE *fp;
796         char str[NINPUT+2];
797         int i;
798
799         if ((fp = fopen(filspc,"r")) != NULL) {
800                 while (fgets(str, NINPUT, fp) != NULL) {
801                         str[NINPUT+1] = '\0';
802                         i = strlen(str) - 1;
803                         if (str[i] == '\n')
804                                 str[i] = '\0';
805                         ip = str;
806                         link();
807                 }
808                 fclose(fp);
809         }
810 }