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