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