First try to build under Linux
[fw/sdcc] / support / librarian / sdcclib.c
1 /* sdcclib.c: sdcc librarian
2    Copyright (C) 2003, Jesus Calvino-Fraga jesusc(at)ece.ubc.ca
3
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
7 later version.
8
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.
13
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. */
17
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #define _POSIX_
22 #include <limits.h>
23 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
24 #include <unistd.h>
25 #endif
26
27 char ProgName[PATH_MAX];
28 char LibName[PATH_MAX];
29 char LibNameTmp[PATH_MAX];
30 char IndexName[PATH_MAX];
31 char RelName[PATH_MAX];
32 char AdbName[PATH_MAX];
33
34 #define version "0.1"
35
36 #define OPT_ADD_REL 0
37 #define OPT_EXT_REL 1
38 #define OPT_DEL_REL 2
39 #define OPT_DUMP_SYM 3
40 #define OPT_DUMP_MOD 4
41
42 #define MAXLINE 254
43 #define EQ(A,B) !strcmp((A),(B))
44 #define NEQ(A,B) strcmp((A),(B))
45
46 int action=0;
47 FILE *lib, *newlib, *rel, *adb, *libindex;
48 char FLine[MAXLINE+1];
49 char ModName[MAXLINE+1];
50 int state=0;
51
52 void GetNameFromPath(char * path, char * name)
53 {
54         int i, j;
55
56         for(i=0; path[i]!=0; i++);
57         for(; (path[i]!='\\')&&(path[i]!='/')&&(i>=0); i--);
58         for(j=0, i++; (path[i]!='.')&&(path[i]!=0); i++, j++) name[j]=path[i];
59         name[j]=0;
60 }
61
62 void ChangeExtension(char * path, char * ext)
63 {
64         int i;
65
66         for(i=0; path[i]!=0; i++);
67         for(; (path[i]!='.')&&(path[i]!='\\')&&(path[i]!='/')&&(i>=0); i--);
68         if(path[i]=='.')
69         {
70             path[i+1]=0;
71         strcat(path, ext);
72         }
73         else
74         {
75             printf("ERROR: Filename '%s' must have an extension\n", path);
76             exit(1);
77         }
78 }
79
80 void CleanLine(char * buff)
81 {
82     int j, l;
83     l=strlen(buff);
84     for(j=0; j<l; j++)
85     {
86         if((buff[j]=='\n')||(buff[j]=='\r')) buff[j]=0;
87     }
88 }
89
90 int set_options (char * opt)
91 {
92         int rvalue=0, unknown=0;
93         static char Help[] =
94         "Usage: %s [-options] library relfile\n\n"
95         "available options:\n"
96         "a - Adds relfile to library.  If relfile exists, replaces it.\n"
97         "d - Deletes relfile from library.\n"
98         "e - Extracts relfile from library.\n"
99         "s - Dumps symbols of library.\n"
100         "m - Dumps modules of library.\n"
101         "v - Displays program version.\n"
102         "h - This help.\n";
103
104         switch (opt[0])
105         {
106                 default:
107                     unknown=1;
108                 case 'h':
109                 case '?':
110                 case 'v':
111                     printf("%s: SDCC librarian version %s\n", ProgName, version);
112                     printf("by Jesus Calvino-Fraga\n\n");
113                         if (unknown) printf("Unknown option: %c\n", opt[0]);
114                     if (opt[0]=='v') exit(0);
115                         printf(Help, ProgName);
116                         exit(1);
117                 break;
118                 case 'a':
119                     action=OPT_ADD_REL;
120                 break;
121                 case 'e':
122                     action=OPT_EXT_REL;
123                 break;
124                 case 'd':
125                     action=OPT_DEL_REL;
126                 break;
127                 case 's':
128                     action=OPT_DUMP_SYM;
129                 break;
130                 case 'm':
131                     action=OPT_DUMP_MOD;
132                 break;
133         }
134         return (rvalue);
135 }
136
137 void ProcLineOptions (int argc, char **argv)
138 {
139         int cont_par=0;
140         int i, j;
141
142         /*Get the program name*/
143     GetNameFromPath(argv[0], ProgName);
144
145         for (j=1; j<argc; j++)
146         {
147                 if(argv[j][0]=='-')
148                 {
149                         for(i=1; argv[j][i]!=0 ; i++)
150                                 if (set_options(&argv[j][i])) break;
151                 }
152                 else
153                 {
154                         switch(cont_par)
155                         {
156                                 case 0:
157                                         cont_par++;
158                                         strcpy(LibName, argv[j]);
159                                 break;
160
161                                 case 1:
162                                         cont_par++;
163                                         strcpy(RelName, argv[j]);
164                                 break;
165
166                                 default:
167                                         cont_par++;
168                                 break;
169                         }
170                 }
171         }
172
173         if ( (cont_par!=2) && (action<OPT_DUMP_SYM) )
174         {
175                 printf("Error: Too %s arguments.\n", cont_par<2?"few":"many");
176                 set_options("h"); /*Show help and exit*/
177         }
178         else if ( (cont_par!=1) && (action>=OPT_DUMP_SYM) )
179         {
180                 printf("Error: Too %s arguments.\n", cont_par<1?"few":"many");
181                 set_options("h"); /*Show help and exit*/
182         }
183 }
184
185 void AddRel(void)
186 {
187     int inrel=0;
188     long newlibpos, indexsize;
189     char symname[MAXLINE+1];
190     char c;
191
192     strcpy(LibNameTmp, LibName);
193     ChangeExtension(LibNameTmp, "__L");
194
195     strcpy(IndexName, LibName);
196     ChangeExtension(IndexName, "__I");
197
198     strcpy(AdbName, RelName);
199     ChangeExtension(AdbName, "adb");
200
201     lib=fopen(LibName, "r");
202
203     if(action==OPT_ADD_REL)
204     {
205         rel=fopen(RelName, "r");
206         if(rel==NULL)
207         {
208             printf("ERROR: Couldn't open file '%s'", RelName);
209             if(lib!=NULL) fclose(lib);
210             return;
211         }
212     }
213     GetNameFromPath(RelName, ModName);
214
215     newlib=fopen(LibNameTmp, "w");
216     if(newlib==NULL)
217     {
218         printf("ERROR: Couldn't create temporary file '%s'", LibNameTmp);
219         if(lib!=NULL) fclose(lib);
220         fclose(rel);
221         return;
222     }
223     fprintf(newlib, "<FILES>\n\n");
224
225     libindex=fopen(IndexName, "w");
226     if(libindex==NULL)
227     {
228         printf("ERROR: Couldn't create temporary file '%s'", IndexName);
229         if(lib!=NULL) fclose(lib);
230         fclose(newlib);
231         fclose(rel);
232         return;
233     }
234
235     if(lib!=NULL) while(!feof(lib))
236     {
237         FLine[0]=0;
238         fgets(FLine, MAXLINE, lib);
239         CleanLine(FLine);
240
241         switch(state)
242         {
243             case 0:
244                 if(EQ(FLine, "<FILE>"))
245                 {
246                     FLine[0]=0;
247                     fgets(FLine, MAXLINE, lib);
248                     CleanLine(FLine);
249                     if(NEQ(FLine, ModName))
250                     {
251                         newlibpos=ftell(newlib);
252                         fprintf(newlib, "<FILE>\n%s\n", FLine);
253                         fprintf(libindex, "<MODULE>\n%s %ld\n", FLine, newlibpos);
254                         state++;
255                     }
256                 }                
257             break;
258             case 1:
259                 fprintf(newlib, "%s\n", FLine);
260                 if(EQ(FLine, "</FILE>"))
261                 {
262                     fprintf(newlib, "\n");
263                     fprintf(libindex, "</MODULE>\n\n");
264                     state=0;
265                     inrel=0;
266                 }
267                 else if(EQ(FLine, "<REL>")) inrel=1;
268                 else if(EQ(FLine, "</REL>")) inrel=0;
269                 if(inrel)
270                 {
271                     if(FLine[0]=='S')
272                     {
273                         sscanf(FLine, "S %s %c", symname, &c);
274                         if(c=='D') fprintf(libindex, "%s\n", symname);
275                     }
276                 }
277             break;
278         }
279     }
280
281     if(action==OPT_ADD_REL)
282     {
283         newlibpos=ftell(newlib);
284         fprintf(newlib, "<FILE>\n%s\n<REL>\n", ModName);
285         fprintf(libindex, "<MODULE>\n%s %ld\n", ModName, newlibpos);
286         while(!feof(rel))
287         {
288             FLine[0]=0;
289             fgets(FLine, MAXLINE, rel);
290             CleanLine(FLine);
291             if(strlen(FLine)>0)
292             {
293                 fprintf(newlib, "%s\n", FLine);
294             }
295             if(FLine[0]=='S')
296             {
297                 sscanf(FLine, "S %s %c", symname, &c);
298                 if(c=='D') fprintf(libindex, "%s\n", symname);
299             }
300         }
301         fclose(rel);
302         fprintf(libindex, "</MODULE>\n");
303         fprintf(newlib, "</REL>\n<ADB>\n");
304     
305         adb=fopen(AdbName, "r");
306         if(adb!=NULL)
307         {
308             while(!feof(rel))
309             {
310                 FLine[0]=0;
311                 fgets(FLine, MAXLINE, adb);
312                 CleanLine(FLine);
313                 if(strlen(FLine)>0)
314                 {
315                     fprintf(newlib, "%s\n", FLine);
316                 }
317             }
318             fclose(adb);
319         }
320         fprintf(newlib, "</ADB>\n</FILE>\n");
321     }
322
323     /*Put the temporary files together as a new library file*/
324     indexsize=ftell(libindex);
325     fflush(libindex);
326     fflush(newlib);
327     fclose(newlib);
328     if(lib!=NULL) fclose(lib);
329     fclose(libindex);
330
331     newlib=fopen(LibNameTmp, "r");
332     lib=fopen(LibName, "w");
333     libindex=fopen(IndexName, "r");
334
335     fprintf(lib, "<SDCCLIB>\n\n");
336     fprintf(lib, "<INDEX>\n");
337
338     indexsize+=ftell(lib)+12+14;
339     fprintf(lib, "%10ld\n", indexsize);
340
341     while(!feof(libindex))
342     {
343         FLine[0]=0;
344         fgets(FLine, MAXLINE, libindex);
345         fprintf(lib, "%s", FLine);
346     }
347     fprintf(lib, "\n</INDEX>\n\n");
348
349     while(!feof(newlib))
350     {
351         FLine[0]=0;
352         fgets(FLine, MAXLINE, newlib);
353         fprintf(lib, "%s", FLine);
354     }
355     fprintf(lib, "\n</FILES>\n\n");
356     fprintf(lib, "</SDCCLIB>\n");
357
358     fclose(newlib);
359     fclose(lib);
360     fclose(libindex);
361
362     unlink(LibNameTmp);
363     unlink(IndexName);
364 }
365
366 void ExtractRel(void)
367 {
368     strcpy(AdbName, RelName);
369     ChangeExtension(AdbName, "adb");
370
371     lib=fopen(LibName, "r");
372     if(lib==NULL)
373     {
374         printf("ERROR: Couldn't open file '%s'", LibName);
375         return;
376     }
377
378     rel=fopen(RelName, "w");
379     if(rel==NULL)
380     {
381         printf("ERROR: Couldn't create file '%s'", RelName);
382         fclose(lib);
383         return;
384     }
385     GetNameFromPath(RelName, ModName);
386
387     adb=fopen(AdbName, "w");
388     if(adb==NULL)
389     {
390         printf("ERROR: Couldn't create file '%s'", AdbName);
391         fclose(lib);
392         fclose(rel);
393         return;
394     }
395
396     while(!feof(lib))
397     {
398         if(state==5) break;
399         FLine[0]=0;
400         fgets(FLine, MAXLINE, lib);
401         CleanLine(FLine);
402
403         switch(state)
404         {
405             case 0:
406                 if(EQ(FLine, "<FILE>"))
407                 {
408                     FLine[0]=0;
409                     fgets(FLine, MAXLINE, lib);
410                     CleanLine(FLine);
411                     if(EQ(FLine, ModName)) state=1;
412                 }                
413             break;
414             case 1:
415                 if(EQ(FLine, "<REL>")) state=2;
416             break;
417             case 2:
418                 if(EQ(FLine, "</REL>"))
419                     state=3;
420                 else
421                     fprintf(rel, "%s\n", FLine);
422             break;
423             case 3:
424                 if(EQ(FLine, "<ADB>")) state=4;
425             break;
426             case 4:
427                 if(EQ(FLine, "</ADB>"))
428                     state=5;
429                 else
430                     fprintf(adb, "%s\n", FLine);
431             break; 
432         }
433     }
434     
435     fclose(rel);
436     fclose(lib);
437     fclose(adb);
438 }
439
440 void DumpSymbols(void)
441 {
442     lib=fopen(LibName, "r");
443     if(lib==NULL)
444     {
445         printf("ERROR: Couldn't open file '%s'", LibName);
446         return;
447     }
448
449     while(!feof(lib))
450     {
451         if(state==3) break;
452         FLine[0]=0;
453         fgets(FLine, MAXLINE, lib);
454         CleanLine(FLine);
455
456         switch(state)
457         {
458             case 0:
459                 if(EQ(FLine, "<INDEX>")) state=1;
460             break;
461             case 1:
462                 if(EQ(FLine, "<MODULE>"))
463                 {
464                     FLine[0]=0;
465                     fgets(FLine, MAXLINE, lib);
466                     sscanf(FLine, "%s", ModName);
467                     if(action==OPT_DUMP_SYM)
468                     {
469                         printf("%s.rel:\n", ModName);
470                         state=2;
471                     }
472                     else
473                     {
474                         printf("%s.rel\n", ModName);
475                     }
476                 }
477                 else if(EQ(FLine, "</INDEX>")) state=3;
478             break;
479             case 2:
480                 if(EQ(FLine, "</MODULE>"))
481                 {
482                     state=1;
483                     printf("\n");
484                 }
485                 else printf("   %s\n", FLine);
486             break;
487             default:
488                 state=3;
489             case 3:
490             break;
491         }
492     }
493     
494     fclose(lib);
495 }
496
497 int main(int argc, char **argv)
498 {
499         ProcLineOptions (argc, argv);
500
501         switch(action)
502         {
503             default:
504                 action=OPT_ADD_REL;
505                 case OPT_ADD_REL:
506                 case OPT_DEL_REL:
507                     AddRel();
508                 break;
509                 
510                 case OPT_EXT_REL:
511             ExtractRel();
512         break;
513         
514                 case OPT_DUMP_SYM:
515                 case OPT_DUMP_MOD:
516                     DumpSymbols();
517                 break;
518         }
519         return 0; //Success!!!
520 }