1 /* sdcclib.c: sdcc librarian
2 Copyright (C) 2003, Jesus Calvino-Fraga jesusc(at)ece.ubc.ca
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
27 char ProgName[PATH_MAX];
28 char LibName[PATH_MAX];
29 char LibNameTmp[PATH_MAX];
30 char IndexName[PATH_MAX];
31 char AdbName[PATH_MAX];
32 char ListName[PATH_MAX];
43 #define OPT_ADD_LIST 4
44 #define OPT_DUMP_SYM 5
45 #define OPT_DUMP_MOD 6
48 #define EQ(A,B) !strcmp((A),(B))
49 #define NEQ(A,B) strcmp((A),(B))
53 #define __assert(COND) do { assert(COND); } while (0)
55 #define __assert(COND) do { (void)(COND); } while (0)
58 #define fgets(S, SIZE, STREAM) do { \
60 char *__res4567 = fgets(__s4567, SIZE, STREAM); \
61 __assert(__s4567 == __res4567); \
64 #define system(CMD) do { \
65 int __res4568 = system(CMD); \
66 __assert(-1 != __res4568); \
70 FILE *lib, *newlib, *rel, *adb, *libindex;
71 char FLine[MAXLINE+1];
72 char ModName[MAXLINE+1];
74 void GetNameFromPath(char * path, char * name)
78 for(i=0; path[i]!=0; i++);
79 for(; (path[i]!='\\')&&(path[i]!='/')&&(i>=0); i--);
80 for(j=0, i++; (path[i]!='.')&&(path[i]!=0); i++, j++) name[j]=path[i];
84 void ChangeExtension(char * path, char * ext)
88 for(i=0; path[i]!=0; i++);
89 for(; (path[i]!='.')&&(path[i]!='\\')&&(path[i]!='/')&&(i>=0); i--);
97 printf("ERROR: Filename '%s' must have an extension\n", path);
102 void CleanLine(char * buff)
108 if((buff[j]=='\n')||(buff[j]=='\r')) buff[j]=0;
112 int set_options (char * opt)
114 int rvalue=0, unknown=0;
116 "Usage: %s [option|-options] library relfile1 relfile2 relfile3 ...\n\n"
117 "available options:\n"
118 "a,r - Adds relfile(s) to library. If relfile exists, replaces it.\n"
119 " l - Adds relfile list to library.\n"
120 " d - Deletes relfile(s) from library.\n"
121 "e,x - Extracts relfile(s) from library.\n"
122 " s - Dumps symbols of library.\n"
123 " m - Dumps modules of library.\n"
124 " v - Displays program version.\n"
125 "h,? - This help.\n";
134 printf("%s: SDCC librarian version %s\n", ProgName, version);
135 printf("by Jesus Calvino-Fraga\n\n");
136 if (unknown) printf("Unknown option: %c\n", opt[0]);
137 if (opt[0]=='v') exit(0);
138 printf(Help, ProgName);
165 void ProcLineOptions (int argc, char **argv)
170 /*Get the program name*/
171 GetNameFromPath(argv[0], ProgName);
173 for (j=1; j<argc; j++)
177 for(i=1; argv[j][i]!=0 ; i++)
178 if (set_options(&argv[j][i])) break;
185 if ((strlen(argv[j])==1) && (action==OPT_NONE))
186 set_options(argv[j]);
190 strcpy(LibName, argv[j]);
196 if(action==OPT_ADD_LIST)
197 strcpy(ListName, argv[j]);
201 RelName = (char **) calloc (1, sizeof (char *));
204 printf("ERROR: Insuficient memory.\n");
207 RelName[0]=(char *)malloc(PATH_MAX);
210 printf("ERROR: Insuficient memory.\n");
213 strcpy(RelName[0], argv[j]);
220 RelName = (char **) realloc (RelName, NumRelFiles * sizeof (char *));
223 printf("ERROR: Insuficient memory.\n");
226 RelName[NumRelFiles-1]=(char *)malloc(PATH_MAX);
227 if(RelName[NumRelFiles-1]==NULL)
229 printf("ERROR: Insuficient memory.\n");
232 strcpy(RelName[NumRelFiles-1], argv[j]);
238 if ( (cont_par<2) && (action<OPT_DUMP_SYM) )
240 printf("ERROR: Too few arguments.\n");
241 set_options("h"); /*Show help and exit*/
243 else if ( (cont_par!=1) && (action>=OPT_DUMP_SYM) )
245 printf("ERROR: Too %s arguments.\n", cont_par<1?"few":"many");
246 set_options("h"); /*Show help and exit*/
250 void AddRel(char * RelName)
254 long newlibpos, indexsize;
255 char symname[MAXLINE+1];
259 strcpy(LibNameTmp, LibName);
260 ChangeExtension(LibNameTmp, "__L");
262 strcpy(IndexName, LibName);
263 ChangeExtension(IndexName, "__I");
265 strcpy(AdbName, RelName);
266 ChangeExtension(AdbName, "adb");
268 lib=fopen(LibName, "r");
270 if(action==OPT_ADD_REL)
272 rel=fopen(RelName, "r");
275 printf("ERROR: Couldn't open file '%s'\n", RelName);
276 if(lib!=NULL) fclose(lib);
280 GetNameFromPath(RelName, ModName);
282 newlib=fopen(LibNameTmp, "w");
285 printf("ERROR: Couldn't create temporary file '%s'\n", LibNameTmp);
286 if(lib!=NULL) fclose(lib);
290 fprintf(newlib, "<FILES>\n\n");
292 libindex=fopen(IndexName, "w");
295 printf("ERROR: Couldn't create temporary file '%s'\n", IndexName);
296 if(lib!=NULL) fclose(lib);
302 if(lib!=NULL) while(!feof(lib))
305 fgets(FLine, MAXLINE, lib);
311 if(EQ(FLine, "<FILE>"))
314 fgets(FLine, MAXLINE, lib);
316 if(NEQ(FLine, ModName))
318 newlibpos=ftell(newlib);
319 fprintf(newlib, "<FILE>\n%s\n", FLine);
320 fprintf(libindex, "<MODULE>\n%s %ld\n", FLine, newlibpos);
326 fprintf(newlib, "%s\n", FLine);
327 if(EQ(FLine, "</FILE>"))
329 fprintf(newlib, "\n");
330 fprintf(libindex, "</MODULE>\n\n");
334 else if(EQ(FLine, "<REL>")) inrel=1;
335 else if(EQ(FLine, "</REL>")) inrel=0;
340 sscanf(FLine, "S %s %c", symname, &c);
341 if(c=='D') fprintf(libindex, "%s\n", symname);
348 if(action==OPT_ADD_REL)
350 newlibpos=ftell(newlib);
351 fprintf(newlib, "<FILE>\n%s\n<REL>\n", ModName);
352 fprintf(libindex, "<MODULE>\n%s %ld\n", ModName, newlibpos);
356 fgets(FLine, MAXLINE, rel);
360 fprintf(newlib, "%s\n", FLine);
364 sscanf(FLine, "S %s %c", symname, &c);
365 if(c=='D') fprintf(libindex, "%s\n", symname);
369 fprintf(libindex, "</MODULE>\n");
370 fprintf(newlib, "</REL>\n<ADB>\n");
372 adb=fopen(AdbName, "r");
378 fgets(FLine, MAXLINE, adb);
382 fprintf(newlib, "%s\n", FLine);
387 fprintf(newlib, "</ADB>\n</FILE>\n");
390 /*Put the temporary files together as a new library file*/
391 indexsize=ftell(libindex);
395 if(lib!=NULL) fclose(lib);
398 newlib=fopen(LibNameTmp, "r");
399 lib=fopen(LibName, "w");
400 libindex=fopen(IndexName, "r");
402 fprintf(lib, "<SDCCLIB>\n\n<INDEX>\n");
404 /*Find out if the \n is expanded to \r\n or not*/
405 if(ftell(lib)!=(long)strlen("<SDCCLIB>\n\n<INDEX>\n"))
410 indexsize+=ftell(lib)+strlen("0123456789\n\n</INDEX>\n\n");
411 if(IsDOSStyle) indexsize+=4;
413 fprintf(lib, "%10ld\n", indexsize);
415 while(!feof(libindex))
418 fgets(FLine, MAXLINE, libindex);
419 fprintf(lib, "%s", FLine);
421 fprintf(lib, "\n</INDEX>\n\n");
426 fgets(FLine, MAXLINE, newlib);
427 fprintf(lib, "%s", FLine);
429 fprintf(lib, "\n</FILES>\n\n");
430 fprintf(lib, "</SDCCLIB>\n");
440 void ExtractRel(char * RelName)
444 strcpy(AdbName, RelName);
445 ChangeExtension(AdbName, "adb");
447 lib=fopen(LibName, "r");
450 printf("ERROR: Couldn't open file '%s'\n", LibName);
454 rel=fopen(RelName, "w");
457 printf("ERROR: Couldn't create file '%s'\n", RelName);
461 GetNameFromPath(RelName, ModName);
463 adb=fopen(AdbName, "w");
466 printf("ERROR: Couldn't create file '%s'\n", AdbName);
476 fgets(FLine, MAXLINE, lib);
482 if(EQ(FLine, "<FILE>"))
485 fgets(FLine, MAXLINE, lib);
487 if(EQ(FLine, ModName)) state=1;
491 if(EQ(FLine, "<REL>")) state=2;
494 if(EQ(FLine, "</REL>"))
497 fprintf(rel, "%s\n", FLine);
500 if(EQ(FLine, "<ADB>")) state=4;
503 if(EQ(FLine, "</ADB>"))
506 fprintf(adb, "%s\n", FLine);
516 void DumpSymbols(void)
520 lib=fopen(LibName, "r");
523 printf("ERROR: Couldn't open file '%s'\n", LibName);
528 fgets(FLine, MAXLINE, lib);
530 if(NEQ(FLine, "<SDCCLIB>"))
532 printf("ERROR: File '%s' was not created with '%s'\n", LibName, ProgName);
540 fgets(FLine, MAXLINE, lib);
546 if(EQ(FLine, "<INDEX>")) state=1;
549 if(EQ(FLine, "<MODULE>"))
552 fgets(FLine, MAXLINE, lib);
553 sscanf(FLine, "%s", ModName);
554 if(action==OPT_DUMP_SYM)
556 printf("%s.rel:\n", ModName);
561 printf("%s.rel\n", ModName);
564 else if(EQ(FLine, "</INDEX>")) state=3;
567 if(EQ(FLine, "</MODULE>"))
572 else printf(" %s\n", FLine);
584 int fileexist(char * fname)
588 fp=fopen(fname, "r");
589 if(fp==NULL) return 0;
600 char SrcName[PATH_MAX];
601 char RelName[PATH_MAX];
603 list=fopen(ListName, "r");
606 printf("ERROR: Couldn't open list file '%s'\n", ListName);
610 cc = getenv("SDCCLIB_CC");
611 as = getenv("SDCCLIB_AS");
617 fgets(RelName, PATH_MAX, list);
619 if(strlen(RelName)>0) //Skip empty lines
621 if((cc!=NULL)||(as!=NULL))
623 strcpy(SrcName, RelName);
624 if(strchr(SrcName,'.')==NULL)
625 strcat(SrcName,".src");
630 ChangeExtension(SrcName, "c");
631 if(fileexist(SrcName))
633 sprintf(CmdLine, "%s %s", cc, SrcName);
634 printf("%s\n", CmdLine);
640 ChangeExtension(SrcName, "asm");
641 if(fileexist(SrcName))
643 sprintf(CmdLine, "%s %s", as, SrcName);
644 printf("%s\n", CmdLine);
649 if(strchr(RelName,'.')==NULL)
651 //Try adding the default sdcc extensions
652 strcat(RelName,".o");
653 if(!fileexist(RelName))
654 ChangeExtension(RelName, "rel");
657 printf("Adding: %s\n", RelName);
665 int main(int argc, char **argv)
668 ProcLineOptions (argc, argv);
676 for(j=0; j<NumRelFiles; j++) AddRel(RelName[j]);
678 for(j=0; j<NumRelFiles; j++) free(RelName[j]);
687 for(j=0; j<NumRelFiles; j++) ExtractRel(RelName[j]);
689 for(j=0; j<NumRelFiles; j++) free(RelName[j]);
698 return 0; //Success!!!