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