struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / sdas / linksrc / lkaomf51.c
bloba6a952f92d1dc50b087b3cfebf876612a3a7fffe
1 /* lkaomf51.c - Create an absolute object memory format 51 file
3 Copyright (C) 2002 Jesus Calvino-Fraga, jesusc at ieee dot org
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.
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.
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/>. */
18 #include <ctype.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include "aslink.h"
24 #define EQ(A,B) !strcmp((A),(B))
25 #define MEMSIZE 0x1000000
26 #ifndef DODUMP
27 #define DODUMP 0
28 #endif
30 typedef struct
32 char PathName[PATH_MAX];
33 char ModuleName[PATH_MAX];
34 } _infn;
36 int numin=0;
37 _infn * infn=NULL;
39 typedef struct
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;
49 int numsym=0;
50 _symbol * symbol=NULL;
52 typedef struct
54 char name[0x100];
55 int FileNameNumber;
56 int BeginAdd;
57 int EndAdd;
58 int RegBank;
59 } _procedure;
61 int numproc=0;
62 _procedure * procedure=NULL;
64 typedef struct
66 int Number;
67 int Address;
68 int Procedure;
69 int FileNameNumber;
70 } _linenum;
72 int numlinenum=0;
73 _linenum * linenum=NULL;
74 #if 0
75 typedef struct
77 char * name;
78 int usage;
80 _UsageType;
82 _UsageType UsageType[]=
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?*/
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;
117 int GetName(char * filepath, char * name)
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;
128 void SaveLinkedFilePath(char * filepath)
130 int j;
132 if((yflag) && (!rflag))
134 int ext;
136 infn = realloc(infn, sizeof(_infn)*(numin+1));
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);
142 strcpy(infn[numin].PathName, filepath);
144 /*If there is an extension remove it*/
145 if (infn[numin].PathName[ext] == '.')
146 infn[numin].PathName[ext] = '\0';
148 /*Check if this filename is already in*/
149 for (j=0; j<numin; j++)
151 if (EQ(infn[numin].PathName, infn[j].PathName))
152 break;
154 if (j==numin)
155 numin++;
159 void FreeAll(void)
161 if(infn!=NULL)
163 free(infn);
164 numin=0;
165 infn=NULL;
168 if(symbol!=NULL)
170 free(symbol);
171 numsym=0;
172 symbol=NULL;
175 if(procedure!=NULL)
177 free(procedure);
178 numproc=0;
179 procedure=NULL;
182 if(linenum!=NULL)
184 free(linenum);
185 numlinenum=0;
186 linenum=NULL;
189 if(ihxBuff!=NULL)
191 free(ihxBuff);
192 ihxBuff=NULL;
196 void OutputByte(unsigned char value)
198 GlobalChkSum+=value;
199 fwrite( &value, 1, 1, aomf51out );
202 void OutputWord(int value)
204 OutputByte((unsigned char)(value%0x100));
205 OutputByte((unsigned char)(value/0x100));
208 void OutputName(char * name)
210 int k;
211 OutputByte((unsigned char)strlen(name));
212 for(k=0; name[k]!=0; k++)
214 if (zflag)
216 OutputByte((unsigned char)toupper(name[k]));
218 else
220 OutputByte((unsigned char)name[k]);
225 void OutputChkSum(void)
227 OutputByte((unsigned char)(0x100-(GlobalChkSum%0x100)));
228 GlobalChkSum=0;
231 void DumpForDebug (void)
233 char DumpFileName[PATH_MAX];
234 FILE * DumpFile;
235 int j, k;
237 strcpy(DumpFileName, infn[0].PathName);
238 strcat(DumpFileName, ".d51");
240 DumpFile=fopen(DumpFileName, "wb");
241 if(DumpFile==NULL)
243 printf("Couldn't create file %s\n", DumpFileName);
244 return;
247 fprintf(DumpFile,"SYMBOLS:\n");
249 for(j=0; j<numsym; j++)
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]:"???");
260 fprintf(DumpFile,"\nPROCEDURES:\n");
261 for(j=0; j<numproc; j++)
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');
271 fprintf(DumpFile,"\nLINE NUMBERS:\n");
272 for(j=0; j<numlinenum; j++)
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");
281 fclose(DumpFile);
284 void ParseRegisters(_symbol * symbol, const char * Registers)
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++)
295 if ((regs[i][0] == 'r') && isdigit(regs[i][1]))
297 address[i] = regs[i][1] - '0';
300 for (i=1; i<nRegs; i++)
302 if (address[i] != address[i-1] + 1)
303 {// we need strict ascending registers
304 return;
307 if (0 <= symbol->Procedure && symbol->Procedure < numproc)
308 symbol->Address = address[0] + procedure[symbol->Procedure].RegBank * 8;
311 void OutputAOEMF51(void)
313 int i, j, k, recsize;
314 char MHRname[0x100], Mname[0x100];
315 char aomf51FileName[PATH_MAX];
317 strcpy(aomf51FileName, infn[0].PathName);
318 strcat(aomf51FileName, ".omf");
320 aomf51out=fopen(aomf51FileName, "wb");
321 if(aomf51out==NULL)
323 printf("Couldn't create file %s\n", aomf51FileName);
324 return;
327 GetName(infn[0].PathName, MHRname);
328 GlobalChkSum=0;
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();
338 for(j=0; j<numin; j++)
340 GetName(infn[j].PathName, Mname);
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();
349 /*Public symbols defined in this module*/
350 recsize=2;
351 for(k=0; k<numsym; k++)/*Compute the record length*/
353 if ( (symbol[k].FileNameNumber==j) &&
354 (symbol[k].Address!=-1) &&
355 (symbol[k].Procedure==-1) &&
356 (symbol[k].Static==-1) )
358 recsize+=((strlen(symbol[k].name)+1)+5);
362 if(recsize>2) /*If there are any symbols*/
364 OutputByte(0x12); /*REC TYPE*/
365 OutputWord(recsize); /*Record Length*/
366 OutputByte(0x01); /*DEF TYPE: Public symbols*/
367 for(k=0; k<numsym; k++)
369 if ( (symbol[k].FileNameNumber==j) &&
370 (symbol[k].Address!=-1) &&
371 (symbol[k].Procedure==-1) &&
372 (symbol[k].Static==-1) )
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*/
381 OutputChkSum();
384 /*Local symbols defined in this module*/
385 recsize=2;
386 for(k=0; k<numsym; k++)/*Compute the record length*/
388 if ( (symbol[k].FileNameNumber==j) &&
389 (symbol[k].Address!=-1) &&
390 (symbol[k].Procedure==-1) &&
391 (symbol[k].Static==j) )
393 recsize+=((strlen(symbol[k].name)+1)+5);
397 if(recsize>2) /*If there are any symbols*/
399 OutputByte(0x12); /*REC TYPE*/
400 OutputWord(recsize); /*Record Length*/
401 OutputByte(0x00); /*DEF TYPE: Local symbols*/
402 for(k=0; k<numsym; k++)
404 if ( (symbol[k].FileNameNumber==j) &&
405 (symbol[k].Address!=-1) &&
406 (symbol[k].Procedure==-1) &&
407 (symbol[k].Static==j) )
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*/
416 OutputChkSum();
419 /*Output the procedures of this module*/
421 for(k=0; k<numproc; k++)
423 if(procedure[k].FileNameNumber==j)
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();
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++)
442 if (i < 0 || MEMSIZE <= i)
443 continue;
444 OutputByte((unsigned char)ihxBuff[i]);
445 ihxBuff[i] -= 0x200;
447 OutputChkSum();
449 /*Local Symbols*/
451 recsize=2;
452 for(i=0; i<numsym; i++)/*Get the record length*/
454 if( (symbol[i].Procedure==k) &&
455 (symbol[i].Address!=-1) )
457 recsize+=((strlen(symbol[i].name)+1)+5);
461 if(recsize>2) /*If there are any symbols*/
463 OutputByte(0x12); /*REC TYPE*/
464 OutputWord(recsize); /*Record Length*/
465 OutputByte(0x00); /*DEF TYPE: Local symbols*/
466 for(i=0; i<numsym; i++)
468 if ( (symbol[i].Procedure==k) &&
469 (symbol[i].Address!=-1) )
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*/
478 OutputChkSum();
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;
487 if(recsize>2) /*If there are any line numbers*/
489 OutputByte(0x12); /*REC TYPE*/
490 OutputWord(recsize); /*Record Length*/
491 OutputByte(0x03); /*DEF TYPE: Line numbers*/
492 for(i=0; i<numlinenum; i++)
494 if ( (linenum[i].Procedure==k) )
496 OutputByte(0x00);/*SEG ID*/
497 OutputWord(linenum[i].Address);/*Offset*/
498 OutputWord(linenum[i].Number);/*Line Number*/
501 OutputChkSum();
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();
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();
521 /*Content records for everything that is not in the above procedures*/
522 strcpy(Mname, "OTHER_SDCC_STUFF");
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();
531 for (i=HexBegin; i<HexSize; )
533 for (k=i; k<HexSize; k++)
535 if (ihxBuff[k] < 0)
536 break;
538 if (k > i)
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++)
547 OutputByte((unsigned char)ihxBuff[i]);
548 ihxBuff[i] -= 0x200;
550 OutputChkSum();
552 for ( ; i<HexSize; i++)
554 if (ihxBuff[i] >= 0)
555 break;
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();
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();
575 fclose(aomf51out);
578 void CollectInfoFromCDB(void)
580 int i, j, k, CurrentModule;
581 FILE * CDBin;
582 char buff[0x1000];
583 char SourceName[PATH_MAX];
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;
603 if(numin==0) return;
605 if (yfp != NULL)
607 fclose(yfp);
608 yfp=NULL;
611 /*Build the source filename*/
612 strcpy(SourceName, infn[0].PathName);
613 strcat(SourceName, ".cdb");
614 CDBin=fopen(SourceName, "r");
615 if(CDBin==NULL)
617 printf("Couldn't open file '%s'\n", SourceName);
618 lkexit(1);
621 CurrentModule=0; /*Set the active module as the first one*/
622 while(!feof(CDBin))
624 if(NULL==fgets(buff, sizeof(buff)-1, CDBin))
626 if(ferror(CDBin))
628 perror("Can't read file");
629 lkexit(1);
631 else if(!feof(CDBin))
633 fprintf(stderr, "Unknown error while reading file '%s'\n", SourceName);
634 lkexit(1);
638 if(!feof(CDBin)) switch(buff[0])
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;
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"
656 case 'S':
657 sscanf(buff, Sfmt,
658 scope, &c,
659 name, &c,
660 level, &c,
661 block);
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);
671 i=-1; k=-1;
672 switch(scope[2])
674 case 'G': /*Global symbol*/
675 break;
676 case 'F': /*Local symbol to a module*/
677 for(j=0; j<numin; j++)
679 if (EQ(&scope[3], infn[j].ModuleName))
681 i = j;
682 break;
685 break;
686 case 'L': /*Local symbol of a procedure*/
687 for(j=0; j<numproc; j++)
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)))
694 k = j; /*Local symbol*/
695 break;
698 break;
701 /*This symbol may have been already defined*/
702 for (j=0; j<numsym; j++)
704 if (EQ(name, symbol[j].name) &&
705 (symbol[j].Procedure == k) &&
706 (symbol[j].Static == i) ) break;
708 if(j==numsym) /*New symbol*/
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*/
717 switch(AddressSpace)
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;
725 case 'F': /*External ram*/
726 case 'A': /*External stack*/
727 case 'P': /*External Pdata*/
728 symbol[numsym].UsageType=0x41;
729 break;
731 case 'E': /*Internal ram (lower 128) bytes*/
732 case 'I': /*SFR space*/
733 symbol[numsym].UsageType=0x42;
734 break;
736 case 'R': /*Register Space*/
737 ParseRegisters(&symbol[numsym], Registers);
738 symbol[numsym].UsageType=0x42;
739 break;
741 case 'B': /*Internal stack*/
742 case 'G': /*Internal ram*/
743 symbol[numsym].UsageType=0x43;
744 break;
746 case 'H': /*Bit addressable*/
747 case 'J': /*SBIT space*/
748 symbol[numsym].UsageType=0x44;
749 break;
751 default:
752 printf("Unknown scope information for: %s, AddressSpace:%c\n", symbol[numsym].name, AddressSpace);
753 break;
755 numsym++;
757 break;
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 */
764 case 'F':
765 sscanf(buff, "%[^$] %c %[^$] %c %[^$] %c %s",
766 scope, &c,
767 name, &c,
768 level, &c,
769 block);
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++)
783 if (EQ(name, procedure[j].name) &&
784 (procedure[j].FileNameNumber == CurrentModule))
786 break;
789 if (j==numproc)
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++;
800 /*This function name is also a global symbol*/
801 for(j=0; j<numsym; j++)/*A global symbol may have been already defined*/
803 if (EQ(name, symbol[j].name) &&
804 (symbol[j].Procedure==-1) &&
805 (symbol[j].FileNameNumber == CurrentModule))
807 break;
810 if (j==numsym)
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++;
821 break;
823 case 'L':
824 switch(buff[2])
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);
830 for(j=0; j<numsym; j++)
832 if(EQ(symbol[j].name, name))
834 if( (symbol[j].Address==-1) && (symbol[j].Procedure==-1) )
836 symbol[j].Address=Address;
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)
843 for (k=0; k<numproc; k++)
845 if (EQ(symbol[j].name, procedure[k].name))
847 if (procedure[k].BeginAdd == -1)
848 procedure[k].BeginAdd = Address;
849 break;
854 break;
857 break;
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);
863 for (j=0; j<numsym; j++)
865 if (EQ(symbol[j].name, name) &&
866 EQ(infn[symbol[j].FileNameNumber].ModuleName, scope))
868 if( (symbol[j].Address == -1) )
870 symbol[j].Address = Address;
872 break;
876 /*It could be also a static function*/
877 for (j=0; j<numproc; j++)
879 if (EQ(procedure[j].name, name) &&
880 EQ(infn[procedure[j].FileNameNumber].ModuleName, scope))
882 if( (procedure[j].BeginAdd == -1) )
884 procedure[j].BeginAdd = Address;
886 break;
890 break;
892 case 'L': /*Example L:Lmain$j$1$1:29*/
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
901 sscanf(&buff[3], "%[^.] %c %[^$] %c %[^$] %c %[^:] %c %x",
902 module, &c, scope, &c, name, &c, level, &c, &Address);
904 for (k=0; k<numproc; k++)
906 if (EQ(procedure[k].name, scope) &&
907 EQ(infn[procedure[k].FileNameNumber].ModuleName, module))
909 for (j=0; j<numsym; j++)
911 if ((symbol[j].FileNameNumber == procedure[k].FileNameNumber) &&
912 (symbol[j].Procedure == k) &&
913 (EQ(symbol[j].name, name)))
915 if (symbol[j].Address == -1)
916 symbol[j].Address = Address;
917 break;
920 if (j<numsym)
921 break;
924 break;
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);
931 for(j=0; j<numin; j++)
932 if(EQ(infn[j].ModuleName, name)) break;
933 if(j<numin)
935 /*Check if this line is already defined*/
936 for(k=0; k<numlinenum; k++)
938 if( (linenum[k].Number==CLine) &&
939 (linenum[k].FileNameNumber==j) )break;
941 if(k==numlinenum) /*New line number*/
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++;
951 break;
953 case 'A': /*Example L:A$adq$424:40*/
954 /*No use for this one*/
955 break;
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);
962 for(k=0; k<numproc; k++)
964 if (EQ(procedure[k].name, name) &&
965 (scope[0] == 'G' ||
966 EQ(infn[procedure[k].FileNameNumber].ModuleName, &scope[1])))
968 if( (procedure[k].EndAdd == -1) )
970 procedure[k].EndAdd = Address;
972 break;
975 break;
977 break;
979 default:
980 break;
984 /*Make sure each procedure has an end*/
985 for(k=0; k<(numproc-1); k++)
987 if (procedure[k].EndAdd==-1) procedure[k].EndAdd=procedure[k+1].BeginAdd-1;
989 /*Assign each line number to a procedure*/
990 for(j=0; j<numlinenum; j++)
992 for(k=0; k<numproc; k++)
994 if ( (linenum[j].Address>=procedure[k].BeginAdd) &&
995 (linenum[j].Address<=procedure[k].EndAdd) &&
996 (linenum[j].FileNameNumber==procedure[k].FileNameNumber) )
998 linenum[j].Procedure=k;
1003 fclose(CDBin);
1006 int hex2dec (unsigned char hex_digit)
1008 if (isdigit (hex_digit))
1009 return hex_digit-'0';
1010 else
1011 return toupper (hex_digit)-'A'+10;
1014 unsigned char GetByte(char * buffer)
1016 return hex2dec(buffer[0])*0x10+hex2dec(buffer[1]);
1019 unsigned short GetWord(char * buffer)
1021 return hex2dec(buffer[0])*0x1000+
1022 hex2dec(buffer[1])*0x100+
1023 hex2dec(buffer[2])*0x10+
1024 hex2dec(buffer[3]);
1027 int ReadHexFile(int * Begin)
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;
1038 /*If the hexfile is already open, close it*/
1039 if(ofp!=NULL)
1041 fclose(ofp);
1042 ofp=NULL;
1045 strcpy(ihxFileName, infn[0].PathName);
1046 strcat(ihxFileName, ".ihx");
1048 if ( (filein=fopen(ihxFileName, "r")) == NULL )
1050 printf("Error: Can't open file `%s`.\r\n", ihxFileName);
1051 return 0;
1054 ihxBuff = calloc(MEMSIZE, sizeof(short));
1055 if (ihxBuff==NULL)
1057 printf("Insufficient memory\n");
1058 fclose(filein);
1059 return -1;
1062 for (j=0; j<MEMSIZE; j++) ihxBuff[j]=-1;
1064 while(1)
1066 if(fgets(buffer, sizeof(buffer), filein)==NULL)
1068 printf("Error reading file '%s'\n", ihxFileName);
1069 break;
1071 if(buffer[0]==':')
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;
1079 switch (recordtype)
1081 case 0:
1082 for (j=0; j<linesize; j++)
1084 value = GetByte(&buffer[9]+(j*2));
1085 chksum += value;
1086 ihxBuff[address+j] = value;
1088 if (MaxAddress < (address+linesize-1))
1089 MaxAddress = (address+linesize-1);
1090 if (address < *Begin)
1091 *Begin = address;
1092 break;
1094 case 4:
1095 hi_addr = (GetWord(&buffer[9]) << 16) & 0x00FFFFFF; //upto 24 bit address space
1096 break;
1098 default:
1099 break;
1102 if ((chksum % 0x100) != 0)
1104 printf("ERROR: Bad checksum in file %s\n", ihxFileName);
1105 fclose(filein);
1106 return -1;
1109 if (recordtype==1) /*End of record*/
1110 break;
1113 fclose(filein);
1115 return MaxAddress;
1118 void CreateAOMF51(void)
1120 if((yflag) && (!rflag))
1122 CollectInfoFromCDB();
1123 #if DODUMP
1124 DumpForDebug();
1125 #endif
1126 HexSize=ReadHexFile(&HexBegin)+1;
1127 OutputAOEMF51();
1128 FreeAll();