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