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