* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
[fw/sdcc] / as / link / lkaomf51.c
1 /* lkaomf51.c - Create an absolute object memory format 51 file
2
3    Copyright (C) 2002 Jesus Calvino-Fraga, jesusc at ieee dot org
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 3, or (at your option) any
8 later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
17
18 #include <ctype.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include "aslink.h"
23
24 #define EQ(A,B) !strcmp((A),(B))
25 #define MEMSIZE 0x10000
26 //#define DODUMP 1
27
28 typedef struct
29 {
30         char PathName[PATH_MAX];
31         char ModuleName[PATH_MAX];
32 } _infn;
33
34 int numin=0;
35 _infn * infn=NULL;
36
37 char ihxFileName[PATH_MAX];
38 char aomf51FileName[PATH_MAX];
39
40 typedef struct
41 {
42    char name[0x100];
43    int FileNameNumber;
44    int Procedure;//If the symbol belongs to a function
45    int Static; //If the symbol is only public on its file
46    int Address;
47    int UsageType;
48 } _symbol;
49
50 int numsym=0;
51 _symbol * symbol=NULL;
52
53 typedef struct
54 {
55    char name[0x100];
56    int FileNameNumber;
57    int BeginAdd;
58    int EndAdd;
59 } _procedure;
60
61 int numproc=0;
62 _procedure * procedure=NULL;
63
64 typedef struct
65 {
66    int Number;
67    int Address;
68    int Procedure;
69    int FileNameNumber;
70 } _linenum;
71
72 int numlinenum=0;
73 _linenum * linenum=NULL;
74 #if 0
75 typedef struct
76 {
77         char * name;
78         int usage;
79 }
80 _UsageType;
81
82 _UsageType UsageType[]=
83 {
84         {"CSEG",                0},
85         {"GSINIT",              0},
86         {"GSINIT0",             0},
87         {"GSINIT1",             0},
88         {"GSINIT2",             0},
89         {"GSINIT3",             0},
90         {"GSINIT4",             0},
91         {"GSINIT5",             0},
92         {"GSFINAL",             0},
93         {"HOME",                0},
94         {"XINIT",               0},
95         {"XSEG",                1},
96         {"XISEG",               1},
97         {"REG_BANK_0",  2},
98         {"REG_BANK_1",  2},
99         {"REG_BANK_2",  2},
100         {"REG_BANK_3",  2},
101         {"DSEG",                2},
102         {"OSEG",                2},
103         {"SSEG",                2},
104         {"ISEG",                3},
105         {"BSEG",                4},
106         {"",                    5} /*A typeless number?*/
107 };
108 #endif
109 char * UsageTypeName[]={"CODE", "XDATA", "DATA", "IDATA", "BIT", "NUMBER"};
110 int AddNumber;
111 unsigned char * ihxBuff=NULL;
112 FILE * aomf51out;
113 int GlobalChkSum=0;
114 int HexSize, HexBegin=0x10000;
115
116
117 void GetName(char * filepath, char * name)
118 {
119         int j, k;
120         for(j=strlen(filepath); j>0; j--)
121                 if( (filepath[j-1]=='/')||(filepath[j-1]=='\\') ) break;
122         for(k=0; (filepath[j]!=0)&&(filepath[j]!='.'); j++, k++)
123                 name[k]=filepath[j];
124         name[k]=0;
125 }
126
127 void SaveLinkedFilePath(char * filepath)
128 {
129         int j;
130
131         if((dflag) && (!rflag))
132         {
133                 infn=realloc(infn, sizeof(_infn)*(numin+1));
134
135                 strcpy(infn[numin].PathName, filepath);
136                 j=strlen(infn[numin].PathName);
137
138                 /*If there is an extension remove it*/
139                 if(j>=4)
140                 {
141                         if(EQ(&infn[numin].PathName[j-4], ".rel"))
142                         {
143                                 infn[numin].PathName[j-4]=0;
144                         }
145                 }
146
147                 /*Get the module name=filename, no drive, no dir, no ext*/
148                 GetName(infn[numin].PathName, infn[numin].ModuleName);
149                 //printf("%s, %s\n", infn[numin].PathName, infn[numin].ModuleName);
150
151                 /*Check if this filename is already in*/
152                 for(j=0; j<numin; j++)
153                 {
154                         if(EQ(infn[numin].PathName, infn[j].PathName)) break;
155                 }
156                 if(j==numin) numin++;
157         }
158 }
159
160 void FreeAll(void)
161 {
162         if(infn!=NULL)
163         {
164                 free(infn);
165                 numin=0;
166                 infn=NULL;
167         }
168
169         if(symbol!=NULL)
170         {
171                 free(symbol);
172                 numsym=0;
173                 symbol=NULL;
174         }
175
176         if(procedure!=NULL)
177         {
178                 free(procedure);
179                 numproc=0;
180                 procedure=NULL;
181
182         }
183         if(linenum!=NULL)
184         {
185                 free(linenum);
186                 numlinenum=0;
187                 linenum=NULL;
188         }
189
190         if(ihxBuff!=NULL)
191         {
192                 free(ihxBuff);
193                 ihxBuff=NULL;
194         }
195 }
196
197 void OutputByte(unsigned char value)
198 {
199         GlobalChkSum+=value;
200         fwrite( &value, 1, 1, aomf51out );
201 }
202
203 void OutputWord(int value)
204 {
205         OutputByte((unsigned char)(value%0x100));
206         OutputByte((unsigned char)(value/0x100));
207 }
208
209 void OutputName(char * name)
210 {
211         int k;
212         OutputByte((unsigned char)strlen(name));
213         for(k=0; name[k]!=0; k++)
214                 OutputByte((unsigned char)toupper(name[k]));
215 }
216
217 void OutputChkSum(void)
218 {
219         OutputByte((unsigned char)(0x100-(GlobalChkSum%0x100)));
220         GlobalChkSum=0;
221 }
222
223 #ifdef DODUMP
224 void DumpForDebug (void)
225 {
226         char DumpFileName[PATH_MAX];
227         FILE * DumpFile;
228         int j, k;
229
230         strcpy(DumpFileName, infn[0].PathName);
231         strcat(DumpFileName, ".d51");
232
233         DumpFile=fopen(DumpFileName, "wb");
234         if(DumpFile==NULL)
235         {
236                 printf("Couldn't create file %s\n", DumpFileName);
237                 return;
238         }
239
240         fprintf(DumpFile,"SYMBOLS:\n");
241
242         for(j=0; j<numsym; j++)
243         {
244                 k=symbol[j].UsageType&0xf;
245                 fprintf(DumpFile, "%s, %s, %s, 0x%04x, %s\n",
246                         symbol[j].name,
247                         infn[symbol[j].FileNameNumber].PathName,
248                         (symbol[j].Procedure>=0)?procedure[symbol[j].Procedure].name:"GLOBAL",
249                         symbol[j].Address,
250                         k<6?UsageTypeName[k]:"???");
251         }
252
253         fprintf(DumpFile,"\nPROCEDURES:\n");
254         for(j=0; j<numproc; j++)
255         {
256                 fprintf(DumpFile, "%s, %s, 0x%04x-0x%04x\n",
257                         procedure[j].name,
258                         infn[procedure[j].FileNameNumber].PathName,
259                         procedure[j].BeginAdd,
260                         procedure[j].EndAdd);
261         }
262
263         fprintf(DumpFile,"\nLINE NUMBERS:\n");
264         for(j=0; j<numlinenum; j++)
265         {
266                 fprintf(DumpFile, "%d:0x%04x, %s -> %s\n",
267                         linenum[j].Number,
268                         linenum[j].Address,
269                         infn[linenum[j].FileNameNumber].PathName,
270                         (linenum[j].Procedure>=0)?procedure[linenum[j].Procedure].name:"I don't know");
271         }
272
273         fclose(DumpFile);
274 }
275 #endif
276
277 void OutputAOEMF51(void)
278 {
279         int i, j, k, recsize;
280         char MHRname[0x100], Mname[0x100];
281
282         strcpy(aomf51FileName, infn[0].PathName);
283
284         aomf51out=fopen(aomf51FileName, "wb");
285         if(aomf51out==NULL)
286         {
287                 printf("Couldn't create file %s\n", aomf51FileName);
288                 return;
289         }
290
291         GetName(infn[0].PathName, MHRname);
292         GlobalChkSum=0;
293
294         /*Module header record*/
295         OutputByte(0x02);/*REC TYPE*/
296         OutputWord((strlen(MHRname)+1)+3);/*Record Length*/
297         OutputName(MHRname);/*Module Name*/
298         OutputByte(0xff);/*TRN ID: RL51?*/
299         OutputByte(0x00);
300         OutputChkSum();
301
302         for(j=0; j<numin; j++)
303         {
304                 GetName(infn[j].PathName, Mname);
305
306                 /*Scope Definition record: begin module block*/
307                 OutputByte(0x10);/*REC TYPE*/
308                 OutputWord((strlen(Mname)+1)+2);/*Record Length*/
309                 OutputByte(0x00);/*BLK TYP: module block*/
310                 OutputName(Mname);/*Module Name*/
311                 OutputChkSum();
312
313                 /*Public symbols defined in this module*/
314                 recsize=2;
315                 for(k=0; k<numsym; k++)/*Compute the record length*/
316                         if ( (symbol[k].FileNameNumber==j) && (symbol[k].Address!=-1) &&
317                                  (symbol[k].Procedure==-1) &&
318                                  (symbol[k].Static==-1) ) recsize+=((strlen(symbol[k].name)+1)+5);
319
320                 if(recsize>2) /*If there are any symbols*/
321                 {
322                         OutputByte(0x12);       /*REC TYPE*/
323                         OutputWord(recsize);/*Record Length*/
324                         OutputByte(0x01);       /*DEF TYPE: Public symbols*/
325                         for(k=0; k<numsym; k++)
326                         {
327                                 if ( (symbol[k].FileNameNumber==j) && (symbol[k].Address!=-1) &&
328                                          (symbol[k].Procedure==-1) &&
329                                          (symbol[k].Static==-1) )
330                                 {
331                                         OutputByte(0x00);/*SEG ID*/
332                                         OutputByte((unsigned char)symbol[k].UsageType);/*SYM INFO*/
333                                         OutputWord(symbol[k].Address);/*Offset*/
334                                         OutputByte(0x00);
335                                         OutputName(symbol[k].name);/*Symbol name*/
336                                 }
337                         }
338                         OutputChkSum();
339                 }
340
341                 /*Local symbols defined in this module*/
342                 recsize=2;
343                 for(k=0; k<numsym; k++)/*Compute the record length*/
344                         if ( (symbol[k].FileNameNumber==j) && (symbol[k].Address!=-1) &&
345                                  (symbol[k].Procedure==-1) &&
346                                  (symbol[k].Static==j) ) recsize+=((strlen(symbol[k].name)+1)+5);
347
348                 if(recsize>2) /*If there are any symbols*/
349                 {
350                         OutputByte(0x12);       /*REC TYPE*/
351                         OutputWord(recsize);/*Record Length*/
352                         OutputByte(0x00);       /*DEF TYPE: Local symbols*/
353                         for(k=0; k<numsym; k++)
354                         {
355                                 if ( (symbol[k].FileNameNumber==j) && (symbol[k].Address!=-1) &&
356                                          (symbol[k].Procedure==-1) &&
357                                          (symbol[k].Static==j) )
358                                 {
359                                         OutputByte(0x00);/*SEG ID*/
360                                         OutputByte((unsigned char)symbol[k].UsageType);/*SYM INFO*/
361                                         OutputWord(symbol[k].Address);/*Offset*/
362                                         OutputByte(0x00);
363                                         OutputName(symbol[k].name);/*Symbol name*/
364                                 }
365                         }
366                         OutputChkSum();
367                 }
368
369                 /*Output the procedures of this module*/
370
371                 for(k=0; k<numproc; k++)
372                 {
373                         if(procedure[k].FileNameNumber==j)
374                         {
375                                 /*Scope Definition record: begin PROCEDURE block*/
376                                 OutputByte(0x10);/*REC TYPE*/
377                                 OutputWord((strlen(procedure[k].name)+1)+2);/*Record Length*/
378                                 OutputByte(0x02);/*BLK TYP: PROCEDURE block*/
379                                 OutputName(procedure[k].name);/*Module Name*/
380                                 OutputChkSum();
381
382                                 /*Content Record*/
383                                 OutputByte(0x06);/*REC TYPE*/
384                                 if(procedure[k].EndAdd==-1) procedure[k].EndAdd=HexSize;
385                                 recsize=procedure[k].EndAdd-procedure[k].BeginAdd+1+4;
386                                 OutputWord(recsize);/*Record Length*/
387                                 OutputByte(0x00);/*SEG ID*/
388                                 OutputWord(procedure[k].BeginAdd); /*Offset*/
389                                 for(i=procedure[k].BeginAdd; i<=procedure[k].EndAdd; i++)
390                                         OutputByte(ihxBuff[i]);
391                                 OutputChkSum();
392
393                                 /*Local Symbols*/
394
395                                 recsize=2;
396                                 for(i=0; i<numsym; i++)/*Get the record length*/
397                                         if(symbol[i].Procedure==k)
398                                                 recsize+=((strlen(symbol[i].name)+1)+5);
399
400                                 if(recsize>2) /*If there are any symbols*/
401                                 {
402                                         OutputByte(0x12);       /*REC TYPE*/
403                                         OutputWord(recsize);/*Record Length*/
404                                         OutputByte(0x00);       /*DEF TYPE: Local symbols*/
405                                         for(i=0; i<numsym; i++)
406                                         {
407                                                 if ( (symbol[i].Procedure==k) )
408                                                 {
409                                                         OutputByte(0x00);/*SEG ID*/
410                                                         OutputByte((unsigned char)symbol[i].UsageType);/*SYM INFO*/
411                                                         OutputWord(symbol[i].Address);/*Offset*/
412                                                         OutputByte(0x00);
413                                                         OutputName(symbol[i].name);/*Symbol name*/
414                                                 }
415                                         }
416                                         OutputChkSum();
417                                 }
418
419                                 /*Line Numbers*/
420                                 recsize=2;
421                                 for(i=0; i<numlinenum; i++)/*Get the record length*/
422                                         if(linenum[i].Procedure==k) recsize+=5;
423
424                                 if(recsize>2) /*If there are any line numbers*/
425                                 {
426                                         OutputByte(0x12);       /*REC TYPE*/
427                                         OutputWord(recsize);/*Record Length*/
428                                         OutputByte(0x03);       /*DEF TYPE: Line numbers*/
429                                         for(i=0; i<numlinenum; i++)
430                                         {
431                                                 if ( (linenum[i].Procedure==k) )
432                                                 {
433                                                         OutputByte(0x00);/*SEG ID*/
434                                                         OutputWord(linenum[i].Address);/*Offset*/
435                                                         OutputWord(linenum[i].Number);/*Line Number*/
436                                                 }
437                                         }
438                                         OutputChkSum();
439                                 }
440
441                                 /*Scope Definition record: end PROCEDURE block*/
442                                 OutputByte(0x10);/*REC TYPE*/
443                                 OutputWord((strlen(procedure[k].name)+1)+2);/*Record Length*/
444                                 OutputByte(0x05);/*BLK TYP: PROCEDURE end block*/
445                                 OutputName(procedure[k].name);/*Module Name*/
446                                 OutputChkSum();
447                         }
448                 }
449
450                 /*Scope Definition record: end module block*/
451                 OutputByte(0x10);/*REC TYPE*/
452                 OutputWord((strlen(Mname)+1)+2);/*Record Length*/
453                 OutputByte(0x03);/*BLK TYP: module end*/
454                 OutputName(Mname);/*Module Name*/
455                 OutputChkSum();
456         }
457
458         /*Content records for everything that is not in the above procedures*/
459         strcpy(Mname, "OTHER_SDCC_STUF");
460
461         /*Scope Definition record: begin module block*/
462         OutputByte(0x10);/*REC TYPE*/
463         OutputWord((strlen(Mname)+1)+2);/*Record Length*/
464         OutputByte(0x00);/*BLK TYP: module block*/
465         OutputName(Mname);/*Module Name*/
466         OutputChkSum();
467
468         for(j=-1; j<numproc; j++)
469         {
470                 if(numproc)
471                 {
472                         if(j==-1)
473                         {
474                                 i=HexBegin;
475                                 k=procedure[0].BeginAdd;
476                         }
477                         else if(j==(numproc-1))
478                         {
479                                 i=procedure[j].EndAdd+1;
480                                 k=HexSize;
481                         }
482                         else
483                         {
484                                 i=procedure[j].EndAdd+1;
485                                 k=procedure[j+1].BeginAdd;
486                         }
487                 }
488                 else /*What, no procedures??? Ok, here it is the whole hex file*/
489                 {
490                         i=HexBegin;
491                         k=HexSize;
492                 }
493
494                 if(i<k)
495                 {
496                         /*Content Record*/
497                         OutputByte(0x06);/*REC TYPE*/
498                         OutputWord(k-i+4);/*Record Length*/
499                         OutputByte(0x00);/*SEG ID*/
500                         OutputWord(i); /*Offset*/
501                         for(; i<k; i++) OutputByte(ihxBuff[i]);
502                         OutputChkSum();
503                 }
504         }
505
506         /*Scope Definition record: end module block*/
507         OutputByte(0x10);/*REC TYPE*/
508         OutputWord((strlen(Mname)+1)+2);/*Record Length*/
509         OutputByte(0x03);/*BLK TYP: module end*/
510         OutputName(Mname);/*Module Name*/
511         OutputChkSum();
512
513         /*Module end record*/
514         OutputByte(0x04);/*REC TYPE*/
515         OutputWord((strlen(MHRname)+1)+5);/*Record Length*/
516         OutputName(MHRname);/*Module Name*/
517         OutputWord(0x00);
518         OutputByte(0x0f);/*REG MSK: All the register banks?*/
519         OutputByte(0x00);
520         OutputChkSum();
521
522         fclose(aomf51out);
523 }
524
525 void CollectInfoFromCDB(void)
526 {
527         int i, j, k, CurrentModule;
528         FILE * CDBin;
529         char buff[0x1000];
530         char SourceName[PATH_MAX];
531
532         //"S:{G|F<filename>|L<functionName>}$<name>$<level>$<block>(<type info>),<Address Space>,<on Stack?>,<stack offset>"
533         char Sfmt[]="%[^$] %c %[^$] %c %[^$] %c %s";
534         char c;
535         char scope[0x100];
536         char name[0x100];
537         char level[0x100];
538         char block[0x100];
539         char Bfmt[]="%[^)] %c %c %c %c %d %c %d";
540         char TypeInfo[0x100];
541         char AddressSpace;
542         int OnStack;
543         int StackOffset;
544         int Address, CLine;
545
546         if(numin==0) return;
547
548         if (dfp != NULL)
549         {
550                 fclose(dfp);
551                 dfp=NULL;
552         }
553
554         /*Build the source filename*/
555         strcpy(SourceName, infn[0].PathName);
556         strcat(SourceName, ".cdb");
557         CDBin=fopen(SourceName, "r");
558         if(CDBin==NULL)
559         {
560                 printf("Couldn't open file '%s'\n", SourceName);
561                 lkexit(1);
562         }
563
564         CurrentModule=0; /*Set the active module as the first one*/
565         while(!feof(CDBin))
566         {
567                 fgets(buff, sizeof(buff)-1, CDBin);
568
569                 if(!feof(CDBin)) switch(buff[0])
570                 {
571                         /*Example: "M:adq"*/
572                         case 'M':
573                                 sscanf(&buff[2], "%s", name);
574                                 for(j=0; j<numin; j++)
575                                         if(EQ(infn[j].ModuleName, name)) break;
576                                 if(j<numin) CurrentModule=j;
577                         break;
578
579                         /* Example:
580                         "S:G$actual$0$0({7}ST__00010000:S),E,0,0"
581                         "S:Lmain$j$1$1({2}SI:S),E,0,0"
582                         "S:G$DS1306_Reset_SPI$0$0({2}DF,SV:S),C,0,0"
583                         "S:G$main$0$0({2}DF,SV:S),C,0,0"
584                         */
585
586                         case 'S':
587                                 sscanf(buff, Sfmt,
588                                         scope, &c,
589                                         name, &c,
590                                         level, &c,
591                                         block);
592
593                                 /*<block>(<type info>),<Address Space>,<on Stack?>,<stack offset>*/
594                                 sscanf(block, Bfmt,
595                                            TypeInfo, &c, &c,
596                                            &AddressSpace, &c,
597                                            &OnStack, &c,
598                                            &StackOffset);
599
600                                 i=-1; k=-1;
601                                 switch(scope[2])
602                                 {
603                                         case 'G': /*Global symbol*/
604                                         break;
605                                         case 'L': /*Local symbol of a procedure*/
606                                                 for(j=0; j<numproc; j++)
607                                                 {
608                                                         if(EQ(&scope[3], procedure[j].name)) break;
609                                                 }
610                                                 if(j<numproc) k=j; /*Local symbol*/
611                                         break;
612                                         case 'F': /*Local symbol to a module*/
613                                                 for(j=0; j<numin; j++)
614                                                 {
615                                                         if(EQ(&scope[3], infn[j].ModuleName)) break;
616                                                 }
617                                                 if(j<numin) i=j;
618                                         break;
619                                 }
620
621                                 /*This symbol may have been already defined*/
622                                 for(j=0; j<numsym; j++)
623                                 {
624                                         if( EQ(name, symbol[j].name) &&
625                                                 (symbol[j].Procedure==k) &&
626                                                 (symbol[j].Static==i) ) break;
627                                 }
628                                 if(j==numsym) /*New symbol*/
629                                 {
630                                         symbol=realloc(symbol, sizeof(_symbol)*(numsym+1));
631                                         symbol[numsym].FileNameNumber=CurrentModule;
632                                         strcpy(symbol[numsym].name, name);
633                                         symbol[numsym].Procedure=k;
634                                         symbol[numsym].Static=i;
635                                         symbol[numsym].Address=-1;/*Collected later*/
636
637                                         switch(AddressSpace)
638                                         {
639                                                 case 'C': /*Code*/
640                                                 case 'D': /*Code/static segment*/
641                                                 case 'Z': /*Functions and undefined code space*/
642                                                         symbol[numsym].UsageType=0x40;
643                                                 break;
644
645                                                 case 'F': /*External ram*/
646                                                 case 'A': /*External stack*/
647                                                 case 'P': /*External Pdata*/
648                                                         symbol[numsym].UsageType=0x41;
649                                                 break;
650
651                                                 case 'E': /*Internal ram (lower 128) bytes*/
652                                                 case 'I': /*SFR space*/
653                                                 case 'R': /*Register Space*/
654                                                         symbol[numsym].UsageType=0x42;
655                                                 break;
656
657                                                 case 'B': /*Internal stack*/
658                                                 case 'G': /*Internal ram*/
659                                                         symbol[numsym].UsageType=0x43;
660                                                 break;
661
662                                                 case 'H': /*Bit addressable*/
663                                                 case 'J': /*SBIT space*/
664                                                         symbol[numsym].UsageType=0x44;
665                                                 break;
666
667                                                 default:
668                                                         printf("Unknown scope information for: %s, AddressSpace:%c\n", symbol[numsym].name, AddressSpace);
669                                                 break;
670                                         }
671                                         numsym++;
672                                 }
673                         break;
674
675                         /*Examples:
676                         F:G$AsciiToHex$0$0({2}DF,SC:U),C,0,0,0,0,0
677                         F:G$main$0$0({2}DF,SV:S),C,0,0,0,0,0   */
678
679                         case 'F':
680                                 sscanf(buff, "%[^$] %c %[^$]", scope, &c, name);
681                                 /*The same may have been already defined */
682                                 for(j=0; j<numproc; j++)
683                                 {
684                                         if(EQ(name, procedure[j].name)) break;
685                                 }
686                                 if(j==numproc)
687                                 {
688                                         procedure=realloc(procedure, sizeof(_procedure)*(numproc+1));
689                                         strcpy(procedure[numproc].name, name);
690                                         procedure[numproc].FileNameNumber=CurrentModule;
691                                         procedure[numproc].BeginAdd=-1;/*To be collected latter*/
692                                         procedure[numproc].EndAdd=-1;/*To be collected latter*/
693                                         numproc++;
694                                 }
695
696                                 /*This function name is also a global symbol*/
697                                 for(j=0; j<numsym; j++)/*A global symbol may have been already defined*/
698                                 {
699                                         if( EQ(name, symbol[j].name) && (symbol[j].Procedure==-1) ) break;
700                                 }
701                                 if(j==numsym)
702                                 {
703                                         symbol=realloc(symbol, sizeof(_symbol)*(numsym+1));
704                                         symbol[numsym].FileNameNumber=CurrentModule;
705                                         strcpy(symbol[numsym].name, name);
706                                         symbol[numsym].UsageType=0x00;/*A procedure name symbol*/
707                                         symbol[numsym].Procedure=-1; /*Global symbol*/
708                                         symbol[numsym].Address=-1;/*Collected later*/
709                                         symbol[numsym].Static=-1; // o_gloom
710                                         numsym++;
711                                 }
712                         break;
713
714                         case 'L':
715                                 switch(buff[2])
716                                 {
717                                         case 'G': /*Example L:G$P0$0$0:80*/
718                                                 sscanf(buff, "%[^$] %c %[^$] %c %[^:] %c %x",
719                                                         scope, &c, name, &c, level, &c, &Address);
720
721                                                 for(j=0; j<numsym; j++)
722                                                 {
723                                                         if(EQ(symbol[j].name, name))
724                                                         {
725                                                                 if( (symbol[j].Address==-1) && (symbol[j].Procedure==-1) )
726                                                                 {
727                                                                         symbol[j].Address=Address;
728                                                                 }
729
730                                                                 /*If the symbol is the name of a procedure, the address is also
731                                                                 the begining of such procedure*/
732                                                                 if((symbol[j].UsageType&0x0f)==0x00)
733                                                                 {
734                                                                         for(k=0; k<numproc; k++)
735                                                                         {
736                                                                                 if(EQ(symbol[j].name, procedure[k].name))
737                                                                                 {
738                                                                                         if(procedure[k].BeginAdd==-1)
739                                                                                                 procedure[k].BeginAdd=Address;
740                                                                                         break;
741                                                                                 }
742                                                                         }
743                                                                 }
744
745                                                                 break;
746                                                         }
747                                                 }
748                                         break;
749
750                                         case 'F': /*Example L:Fadq$_str_2$0$0:57A*/
751                                                 sscanf(buff, "%[^$] %c %[^$] %c %[^:] %c %x",
752                                                         scope, &c, name, &c, level, &c, &Address);
753
754                                                 for(j=0; j<numsym; j++)
755                                                 {
756                                                         if(EQ(symbol[j].name, name))
757                                                         {
758                                                                 if( (symbol[j].Address==-1) ) symbol[j].Address=Address;
759                                                                 break;
760                                                         }
761                                                 }
762
763                                                 /*It could be also a static function*/
764                                                 for(j=0; j<numproc; j++)
765                                                 {
766                                                         if(EQ(procedure[j].name, name))
767                                                         {
768                                                                 if( (procedure[j].BeginAdd==-1) ) procedure[j].BeginAdd=Address;
769                                                                 break;
770                                                         }
771                                                 }
772
773                                         break;
774
775                                         case 'L': /*Example L:Lmain$j$1$1:29*/
776
777                                                 /*
778                                                 L:LDS1306_Write$Value$1$1:34
779                                                 L:LDS1306_Burst_Read$count$1$1:35
780                                                 L:LDS1306_Burst_Read$address$1$1:36
781                                                 L:LDS1306_Burst_Write$count$1$1:37
782                                                 L:LDS1306_Burst_Write$address$1$1:38
783                                                 */
784                                                 sscanf(&buff[3], "%[^$] %c %[^$] %c %[^:] %c %x",
785                                                         scope, &c, name, &c, level, &c, &Address);
786
787                                                 for(k=0; k<numproc; k++)
788                                                 {
789                                                         if(EQ(procedure[k].name, scope)) break;
790                                                 }
791
792                                                 if(k<numproc) for(j=0; j<numsym; j++)
793                                                 {
794                                                         if( EQ(symbol[j].name, name) && (symbol[j].Procedure==k) )
795                                                         {
796                                                                 if(symbol[j].Address==-1) symbol[j].Address=Address;
797                                                                 break;
798                                                         }
799                                                 }
800                                         break;
801
802                                         /*Line Numbers*/
803                                         case 'C': /*Example L:C$adq.c$38$1$1:3E*/  /*L:C$hwinit.c$29$1$1:7AD*/
804                                                 sscanf(&buff[4], "%[^.] %[^$] %c %d %[^:] %c %x",
805                                                         name, level, &c, &CLine, level, &c, &Address);
806
807                                                 for(j=0; j<numin; j++)
808                                                         if(EQ(infn[j].ModuleName, name)) break;
809                                                 if(j<numin)
810                                                 {
811                                                         /*Check if this line is already defined*/
812                                                         for(k=0; k<numlinenum; k++)
813                                                         {
814                                                                 if( (linenum[k].Number==CLine) &&
815                                                                         (linenum[k].FileNameNumber==j) )break;
816                                                         }
817                                                         if(k==numlinenum) /*New line number*/
818                                                         {
819                                                                 linenum=realloc(linenum, sizeof(_linenum)*(numlinenum+1));
820                                                                 linenum[numlinenum].Number=CLine;
821                                                                 linenum[numlinenum].FileNameNumber=j;
822                                                                 linenum[numlinenum].Procedure=-1;/*To be asigned later*/
823                                                                 linenum[numlinenum].Address=Address;
824                                                                 numlinenum++;
825                                                         }
826                                                 }
827                                         break;
828
829                                         case 'A': /*Example L:A$adq$424:40*/
830                                                 /*No use for this one*/
831                                         break;
832
833                                         /*The end of a procedure*/
834                                         case 'X': /*Example L:XG$AsciiToHex$0$0:88*/
835                                                 sscanf(&buff[3], "%[^$] %c %[^$] %c %[^:] %c %x",
836                                                         scope, &c, name, &c, level, &c, &Address);
837
838                                                 for(k=0; k<numproc; k++)
839                                                 {
840                                                         if(EQ(procedure[k].name, name))
841                                                         {
842                                                                 if(procedure[k].EndAdd==-1) procedure[k].EndAdd=Address;
843                                                                 break;
844                                                         }
845                                                 }
846                                         break;
847                                 }
848                         break;
849
850                         default:
851                         break;
852                 }
853         }
854
855         /*Make sure each procedure has an end*/
856         for(k=0; k<(numproc-1); k++)
857         {
858                 if (procedure[k].EndAdd==-1) procedure[k].EndAdd=procedure[k+1].BeginAdd-1;
859         }
860         /*Asign each line number to a procedure*/
861         for(j=0; j<numlinenum; j++)
862         {
863                 for(k=0; k<numproc; k++)
864                 {
865                         if ( (linenum[j].Address>=procedure[k].BeginAdd) &&
866                                  (linenum[j].Address<=procedure[k].EndAdd) &&
867                                  (linenum[j].FileNameNumber==procedure[k].FileNameNumber) )
868                         {
869                                 linenum[j].Procedure=k;
870                         }
871                 }
872         }
873
874         fclose(CDBin);
875 }
876
877 int hex2dec (unsigned char hex_digit)
878 {
879    if (isdigit (hex_digit))
880       return hex_digit-'0';
881    else
882       return toupper (hex_digit)-'A'+10;
883 }
884
885 unsigned char GetByte(char * buffer)
886 {
887         return hex2dec(buffer[0])*0x10+hex2dec(buffer[1]);
888 }
889
890 unsigned short GetWord(char * buffer)
891 {
892         return  hex2dec(buffer[0])*0x1000+
893                         hex2dec(buffer[1])*0x100+
894                         hex2dec(buffer[2])*0x10+
895                         hex2dec(buffer[3]);
896 }
897
898 int ReadHexFile(int * Begin)
899 {
900         char buffer[1024];
901         FILE * filein;
902         int j;
903         unsigned char linesize, recordtype, rchksum, value;
904         unsigned short address;
905         int MaxAddress=0;
906         int chksum;
907
908         /*If the hexfile is already open, close it*/
909         if(ofp!=NULL)
910         {
911                 fclose(ofp);
912                 ofp=NULL;
913         }
914
915         strcpy(ihxFileName, infn[0].PathName);
916         strcat(ihxFileName, ".ihx");
917
918         if ( (filein=fopen(ihxFileName, "r")) == NULL )
919         {
920            printf("Error: Can't open file `%s`.\r\n", ihxFileName);
921            return 0;
922         }
923
924         ihxBuff=calloc(MEMSIZE, sizeof(unsigned char));
925         if(ihxBuff==NULL)
926         {
927                 printf("Insufficient memory\n");
928                 fclose(filein);
929                 return -1;
930         }
931
932         for(j=0; j<MEMSIZE; j++) ihxBuff[j]=0xff;
933
934     while(1)
935     {
936                 if(fgets(buffer, sizeof(buffer), filein)==NULL)
937                 {
938                         printf("Error reading file '%s'\n", ihxFileName);
939                         break;
940                 }
941         if(buffer[0]==':')
942         {
943                         linesize = GetByte(&buffer[1]);
944                         address = GetWord(&buffer[3]);
945                         recordtype = GetByte(&buffer[7]);
946                         rchksum = GetByte(&buffer[9]+(linesize*2));
947                         chksum=linesize+(address/0x100)+(address%0x100)+recordtype+rchksum;
948
949                         if (recordtype==1) break; /*End of record*/
950
951                         for(j=0; j<linesize; j++)
952                         {
953                                 value=GetByte(&buffer[9]+(j*2));
954                                 chksum+=value;
955                                 ihxBuff[address+j]=value;
956                         }
957                         if(MaxAddress<(address+linesize-1)) MaxAddress=(address+linesize-1);
958                         if(address<*Begin) *Begin=address;
959
960                         if((chksum%0x100)!=0)
961                         {
962                                 printf("ERROR: Bad checksum in file %s\n", ihxFileName);
963                                 fclose(filein);
964                                 return -1;
965                         }
966                 }
967     }
968     fclose(filein);
969
970     return MaxAddress;
971 }
972
973 void CreateAOMF51(void)
974 {
975         if((dflag) && (!rflag))
976         {
977                 CollectInfoFromCDB();
978                 #ifdef DODUMP
979                 DumpForDebug();
980                 #endif
981                 HexSize=ReadHexFile(&HexBegin)+1;
982                 OutputAOEMF51();
983                 FreeAll();
984         }
985 }