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