1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - tools - makelcf
3   File:     createlcf.c
4 
5   Copyright 2003-2009 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2009-06-04#$
14   $Rev: 10698 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 #include	<stdio.h>
18 #include	<strings.h>
19 #include	<io.h>                 // setmode()
20 #include	<fcntl.h>              // setmode()
21 #include	<stdarg.h>             // va_start(),va_end()
22 #ifdef	SDK_TWL
23 #include	<twl/hw/common/mmap_shared.h>
24 #include	<twl/hw/ARM9/mmap_global.h>
25 #include	<twl/hw/ARM9/mmap_main.h>
26 #else
27 #include	<nitro_win32.h>
28 #endif
29 #include	"makelcf.h"
30 #include	"defval.h"
31 #include	"tlcf.tab.h"
32 
33 static void PutString(const char *str);
34 static void PutAddress(u32 address);
35 static BOOL PutObject(const tObject * object, const char *secName);
36 static void PutStaticCrt0Object(const char *secName);
37 static void PutStaticObject(const char *secName);
38 static void PutOverlayName(void);
39 static void PutOverlayGroup(void);
40 static void PutOverlayObject(const char *secName);
41 static void PutOverlayAddress(void);
42 static BOOL isObjectOK(const tObject * obj, const char *section, char filter_type);
43 static BOOL isSectionWildcard(const char *section);
44 static BOOL isSectionRegular(const char *section);
45 static int ForeachObjects(tObject ** ptrObject, tObject * start, int n);
46 static int ForeachStaticObjects(int n);
47 static int ForeachOverlayObjects(int n);
48 static int ForeachOverlays(int n);
49 static int PutToken(int n);
50 static void PutTokenBuffer(int start, int end);
51 static void PutTokenBufferAll(void);
52 
53 FILE   *fp_out;
54 tObject *StaticObject = NULL;
55 tObject *StaticLibrary = NULL;
56 tObject *StaticSearchSymbol = NULL;
57 tOverlay *Autoload = NULL;
58 tObject *AutoloadObject = NULL;
59 tObject *AutoloadLibrary = NULL;
60 tObject *AutoloadSearchSymbol = NULL;
61 tOverlay *Overlay = NULL;
62 tObject *OverlayObject = NULL;
63 tObject *OverlayLibrary = NULL;
64 tObject *OverlaySearchSymbol = NULL;
65 tOverlay *Ltdautoload = NULL;
66 tObject *LtdautoloadObject = NULL;
67 tObject *LtdautoloadLibrary = NULL;
68 tObject *LtdautoloadSearchSymbol = NULL;
69 tOverlay *Ltdoverlay = NULL;
70 tObject *LtdoverlayObject = NULL;
71 tObject *LtdoverlayLibrary = NULL;
72 tObject *LtdoverlaySearchSymbol = NULL;
73 
lcf_error(const char * fmt,...)74 void lcf_error(const char *fmt, ...)
75 {
76     va_list va;
77     va_start(va, fmt);
78     vfprintf(stderr, fmt, va);
79     va_end(va);
80     fprintf(stderr, "\n");
81 }
82 
83 /*============================================================================
84  *  Put Tokens
85  */
PutString(const char * str)86 static void PutString(const char *str)
87 {
88     if (str)
89         fprintf(fp_out, "%s", str);
90 }
91 
PutAddress(u32 address)92 static void PutAddress(u32 address)
93 {
94     fprintf(fp_out, "0x%08lx", address);
95 }
96 
PutNumber(u32 num)97 static void PutNumber(u32 num)
98 {
99     fprintf(fp_out, "%ld", num);
100 }
101 
102 
GetCharPos(const char * str,char target)103 static int GetCharPos(const char *str, char target)
104 {
105     int     n = 0;
106 
107     if (str)
108     {
109         while ('\0' != str[n] && target != str[n])
110         {
111             n++;
112         }
113     }
114     return n;
115 }
116 
GetObjectParam(const char * str,char start,char end)117 static char *GetObjectParam(const char *str, char start, char end)
118 {
119     int     pos_start = GetCharPos(str, start);
120     int     pos_end = GetCharPos(str, end);
121     int     len = pos_end - pos_start;
122     char   *buffer;
123 
124     if (len > 0)
125     {
126         buffer = Alloc(len);
127         strncpy(buffer, str + pos_start + 1, len - 1);
128         buffer[len - 1] = '\0';
129         return buffer;
130     }
131     return NULL;
132 }
133 
GetObjectSection(const char * str)134 static char *GetObjectSection(const char *str)
135 {
136     return GetObjectParam(str, '=', ':');       // return NULL if no section
137 }
138 
GetObjectModifier(const char * str)139 static char GetObjectModifier(const char *str)
140 {
141     char   *mod = GetObjectParam(str, ':', '\0');
142     char    ret;
143 
144     ret = mod ? mod[0] : '\0';
145     Free(&mod);
146 
147     return ret;
148 
149 }
150 
GetMemTypeParam(const char * str)151 static tMemType GetMemTypeParam(const char *str)
152 {
153     char   *mod = GetObjectParam(str, '=', ':');
154     int     i;
155 
156     static struct
157     {
158         tMemType type;
159         char   *name;
160     }
161     table[] =
162     {
163         {
164         MEMTYPE_MAIN, "MAIN"}
165         ,
166         {
167         MEMTYPE_MAINEX, "MAINEX"}
168         ,
169         {
170         MEMTYPE_ITCM, "ITCM"}
171         ,
172         {
173         MEMTYPE_DTCM, "DTCM"}
174         ,
175         {
176         MEMTYPE_ITCM_BSS, "ITCM.BSS"}
177         ,
178         {
179         MEMTYPE_DTCM_BSS, "DTCM.BSS"}
180         ,
181         {
182         MEMTYPE_SHARED, "SHARED"}
183         ,
184         {
185         MEMTYPE_WRAM, "WRAM"}
186         ,
187         {
188         MEMTYPE_WRAM_BSS, "WRAM.BSS"}
189         ,
190         {
191         MEMTYPE_VRAM, "VRAM"}
192         ,
193         {
194         MEMTYPE_NONE, "*"}
195     ,};
196 
197     for (i = 0; table[i].type != MEMTYPE_NONE; i++)
198     {
199         if (isSame(mod, table[i].name))
200         {
201             break;
202         }
203     }
204     Free(&mod);
205 
206     return table[i].type;
207 }
208 
209 //
210 // Decides to which memory region the section specified by name, address belongs
211 //
GetSectionMemType(const char * name,u32 address)212 static tMemType GetSectionMemType(const char *name, u32 address)
213 {
214     BOOL    isARM9 = (Static.address < 0x02300000);     // Actual decision value
215     tMemType memtype = MEMTYPE_NONE;
216 
217     if (isARM9)
218     {
219         if (isSame(name, "ITCM"))
220             memtype = MEMTYPE_ITCM;
221         else if (isSame(name, "DTCM"))
222             memtype = MEMTYPE_DTCM;
223         else if (isSame(name, "WRAM"))
224             memtype = MEMTYPE_WRAM;
225         else if (isSame(name, "ITCM.BSS"))
226             memtype = MEMTYPE_ITCM_BSS;
227         else if (isSame(name, "DTCM.BSS"))
228             memtype = MEMTYPE_DTCM_BSS;
229         else if (isSame(name, "WRAM.BSS"))
230             memtype = MEMTYPE_WRAM_BSS;
231         else if (HW_ITCM_IMAGE <= address && address < HW_ITCM_END)
232             memtype = MEMTYPE_ITCM;
233         else if (HW_MAIN_MEM_SUB <= address && address < HW_MAIN_MEM_SUB_END)
234             memtype = MEMTYPE_DTCM;
235         else if (HW_MAIN_MEM_MAIN <= address && address < HW_MAIN_MEM_MAIN_END)
236             memtype = MEMTYPE_MAIN;
237         else if (HW_MAIN_MEM_MAIN_END <= address && address < HW_MAIN_MEM_DEBUGGER)
238             memtype = MEMTYPE_MAINEX;
239         else if (HW_MAIN_MEM_SHARED <= address && address < HW_MAIN_MEM_SHARED_END)
240             memtype = MEMTYPE_SHARED;
241         else if (HW_WRAM <= address && address < HW_WRAM_END)
242             memtype = MEMTYPE_WRAM;
243         else if (HW_BG_PLTT <= address && address < HW_CTRDG_ROM)
244             memtype = MEMTYPE_VRAM;
245     }
246     else
247     {
248         if (isSame(name, "WRAM"))
249             memtype = MEMTYPE_WRAM;
250         else if (HW_MAIN_MEM_MAIN <= address && address < HW_MAIN_MEM_SUB_END)
251             memtype = MEMTYPE_MAIN;
252         else if (HW_MAIN_MEM_SHARED <= address && address < HW_MAIN_MEM_SHARED_END)
253             memtype = MEMTYPE_SHARED;
254         else if (HW_WRAM <= address && address < HW_WRAM_END)
255             memtype = MEMTYPE_WRAM;
256         else if (HW_BG_PLTT <= address && address < HW_CTRDG_ROM)
257             memtype = MEMTYPE_VRAM;
258     }
259     return memtype;
260 }
261 
262 //
263 // Return overlay that corresponds to the section specified by name
264 //
GetOverlayByName(const char * name)265 static tOverlay *GetOverlayByName(const char *name)
266 {
267     tOverlay *t;
268 
269     for (t = OverlayList.head; t; t = t->next)
270     {
271         if (isSame(t->name, name))
272             return t;
273     }
274     for (t = AutoloadList.head; t; t = t->next)
275     {
276         if (isSame(t->name, name))
277             return t;
278     }
279     for (t = LtdoverlayList.head; t; t = t->next)
280     {
281         if (isSame(t->name, name))
282             return t;
283     }
284     for (t = LtdautoloadList.head; t; t = t->next)
285     {
286         if (isSame(t->name, name))
287             return t;
288     }
289     return NULL;
290 }
291 
292 //
293 // Decides to which memory region the section specified by name belongs
294 //
RecgSectionMemTypeByName(const char * name)295 static tMemType RecgSectionMemTypeByName(const char *name)
296 {
297     tOverlay *overlay;
298     tMemType memtype, mt;
299     tAfter *after;
300 
301     if (isSame(name, Static.name))
302     {
303         Static.memtype = GetSectionMemType(Static.name, Static.address);
304         return Static.memtype;
305     }
306 
307     overlay = GetOverlayByName(name);
308     if (!overlay)
309     {
310         lcf_error("Unknown section %s, Ignored.", name);
311         return MEMTYPE_NONE;
312     }
313 
314     if (overlay->memtype == MEMTYPE_NONE)
315     {
316         memtype = GetSectionMemType(overlay->name, overlay->address);
317 
318         if (memtype == MEMTYPE_NONE)
319         {
320             overlay->memtype = MEMTYPE_DUMMY;
321 
322             for (after = overlay->afters.head; after; after = after->next)
323             {
324                 mt = RecgSectionMemTypeByName(after->name);
325 
326                 if (mt == MEMTYPE_DUMMY)
327                 {
328                     // Looping
329                     lcf_error("Recursive AFTER reference in section %s, Ignored.", name);
330                     overlay->memtype = MEMTYPE_NONE;
331                     return MEMTYPE_NONE;
332                 }
333                 else if (memtype == MEMTYPE_NONE)
334                 {
335                     memtype = mt;
336                 }
337                 else if (memtype != mt)
338                 {
339                     // Different memtype sections are collected in AFTER
340                     lcf_error("Bad address mapping in section %s, Ignored.", name);
341                     overlay->memtype = MEMTYPE_NONE;
342                     return MEMTYPE_NONE;
343                 }
344             }
345         }
346         overlay->memtype = memtype;
347     }
348     return overlay->memtype;
349 }
350 
351 
352 //====== COMMONS ======
353 
354 /*---------------------------------------------------------------------------*
355   Name:         isObjectOK
356 
357   Description:  Determines whether the designated object matches the conditions designated by the section or the filter_type.
358 
359 
360   Arguments:    obj         : object
361                               (What is actually determined is
362                               obj->sectionName, obj->objextType )
363                 section     : Designated section name
364                 filter_type : Qualifying options
365 
366   Returns:      None.
367  *---------------------------------------------------------------------------*/
368 
isObjectOK(const tObject * obj,const char * section,char filter_type)369 static BOOL isObjectOK(const tObject * obj, const char *section, char filter_type)
370 {
371     //
372     //  Checks pertaining to section naming
373     //          A "*" can be used as the section wildcard.
374     //          When the section is "*", all obj will pass
375     //          When obj->section is "*", the section designation is a general section
376     //          Pass for general sections (.text, .data, .bss, .init, and the like)
377     //
378     if (isSectionWildcard(section) ||
379         (isSectionWildcard(obj->sectionName) && isSectionRegular(section)) ||
380         isSame(obj->sectionName, section))
381     {
382         switch (filter_type)
383         {
384         case 'f':                     // only regular file
385             if (obj->objectType == OBJTYPE_FILE)
386                 return TRUE;
387             break;
388 
389         case '\0':                    // OK if NULL
390             return TRUE;
391 
392         default:
393             lcf_error("Unknown type setting Ignored.");
394             break;
395         }
396     }
397     return FALSE;
398 }
399 
isSectionWildcard(const char * section)400 static BOOL isSectionWildcard(const char *section)
401 {
402     return !section || isSame(section, "*");
403 }
404 
isSectionRegular(const char * section)405 static BOOL isSectionRegular(const char *section)
406 {
407     return (isSame(section, ".text") ||
408             isSame(section, ".rodata") ||
409             isSame(section, ".sdata") ||
410             isSame(section, ".data") ||
411             isSame(section, ".sbss") ||
412             isSame(section, ".bss") ||
413             isSame(section, ".init") ||
414             isSame(section, ".exception") || isSame(section, ".ctor") || isSame(section, ".sinit"));
415 }
416 
417 // Foreach Objects
ForeachObjects(tObject ** ptrObject,tObject * start,int n)418 static int ForeachObjects(tObject ** ptrObject, tObject * start, int n)
419 {
420     tTokenBuffer *token;
421     char   *section;
422     char    filter;
423 
424     token = &tokenBuffer[n];
425     section = GetObjectSection(token->string);
426     filter = GetObjectModifier(token->string);
427 
428     debug_printf("section =[%s]\n", section ? section : "");
429     debug_printf("filter  =[%c]\n", filter ? filter : ' ');
430 
431     while (start)
432     {
433         if (isObjectOK(start, section, filter))
434         {
435             *ptrObject = start;
436             PutTokenBuffer(n + 1, token->loop_end);
437         }
438 
439         start = start->next;
440     }
441 
442     Free(&section);
443 
444     *ptrObject = NULL;
445     return token->loop_end;
446 }
447 
448 // Object
PutObject(const tObject * object,const char * sectionName)449 static BOOL PutObject(const tObject * object, const char *sectionName)
450 {
451     if (object)
452     {
453         char    modifier = GetObjectModifier(sectionName);
454 
455         PutString(ResolveStringModifier(object->objectName, modifier));
456 
457         if (isNeedSection(object))
458         {
459             char   *section = GetObjectSection(sectionName);
460 
461             if (section)
462             {
463                 PutString(" (");
464                 PutString(section);
465                 PutString(")");
466                 Free(&section);
467             }
468         }
469         return TRUE;
470     }
471     return FALSE;
472 }
473 
474 // Address
PutSectionAddress(tOverlay * overlay)475 static void PutSectionAddress(tOverlay * overlay)
476 {
477     if (overlay->address)
478     {
479         PutAddress(overlay->address);
480     }
481     else
482     {
483         tAfter *t = overlay->afters.head;
484         if (t)
485         {
486             fprintf(fp_out, "AFTER(%s", t->name);
487             while (NULL != (t = t->next))
488             {
489                 fprintf(fp_out, ",%s", t->name);
490             }
491             fprintf(fp_out, ")");
492         }
493     }
494 }
495 
496 
497 //======== STATIC ========//
498 
499 // Crt0 Object
PutStaticCrt0Object(const char * sectionName)500 static void PutStaticCrt0Object(const char *sectionName)
501 {
502     const char *objectName = SearchDefVal("CRT0_O");
503 
504     if(objectName)
505     {
506         char*   section = GetObjectSection(sectionName);
507 
508         PutString(objectName);
509 
510         if (section)
511         {
512             PutString(" (");
513             PutString(section);
514             PutString(")");
515             Free(&section);
516         }
517     }
518     else
519     {
520         lcf_error("No <STATIC.CRT0.OBJECT> Ignored.");
521     }
522 }
523 
524 // Object
PutStaticObject(const char * sectionName)525 static void PutStaticObject(const char *sectionName)
526 {
527     if (!PutObject(StaticObject, sectionName))
528     {
529         lcf_error("No <FOREACH.STATIC.OBJECTS> Ignored.");
530     }
531 }
532 
533 // Foreach Objects
ForeachStaticObjects(int n)534 static int ForeachStaticObjects(int n)
535 {
536     return ForeachObjects(&StaticObject, Static.objects.head, n);
537 }
538 
539 // Library
PutStaticLibrary(const char * sectionName)540 static void PutStaticLibrary(const char *sectionName)
541 {
542     if (!PutObject(StaticLibrary, sectionName))
543     {
544         lcf_error("No <FOREACH.STATIC.LIBRARIES> Ignored.");
545     }
546 }
547 
548 // Foreach Libraries
ForeachStaticLibraries(int n)549 static int ForeachStaticLibraries(int n)
550 {
551     return ForeachObjects(&StaticLibrary, Static.libraries.head, n);
552 }
553 
554 // SearchSymbol
PutStaticSearchSymbol(const char * dummy)555 static void PutStaticSearchSymbol(const char *dummy)
556 {
557     if (!PutObject(StaticSearchSymbol, NULL))
558     {
559         lcf_error("No <FOREACH.STATIC.SEARCHSYMBOLS> Ignored.");
560     }
561 }
562 
563 // Foreach SearchSymbols
ForeachStaticSearchSymbols(int n)564 static int ForeachStaticSearchSymbols(int n)
565 {
566     return ForeachObjects(&StaticSearchSymbol, Static.searchSymbols.head, n);
567 }
568 
569 
570 //======== AUTOLOAD ========//
571 
572 // Id
PutAutoloadId(void)573 static void PutAutoloadId(void)
574 {
575     if (Autoload)
576         PutNumber(Autoload->id);
577     else
578         lcf_error("No <FOREACH.AUTOLOADS> Ignored.");
579 }
580 
581 // Name
PutAutoloadName(void)582 static void PutAutoloadName(void)
583 {
584     if (Autoload)
585         PutString(Autoload->name);
586     else
587         lcf_error("No <FOREACH.AUTOLOADS> Ignored.");
588 }
589 
590 // Address
PutAutoloadAddress(void)591 static void PutAutoloadAddress(void)
592 {
593     if (Autoload)
594         PutSectionAddress(Autoload);
595     else
596         lcf_error("No <FOREACH.AUTOLOADS> Ignored.");
597 }
598 
599 // Object
PutAutoloadObject(const char * sectionName)600 static void PutAutoloadObject(const char *sectionName)
601 {
602     if (!PutObject(AutoloadObject, sectionName))
603     {
604         lcf_error("No <FOREACH.AUTOLOAD.OBJECTS> Ignored.");
605     }
606 }
607 
608 // Foreach Objects
ForeachAutoloadObjects(int n)609 static int ForeachAutoloadObjects(int n)
610 {
611     return ForeachObjects(&AutoloadObject, Autoload->objects.head, n);
612 }
613 
614 // Library
PutAutoloadLibrary(const char * sectionName)615 static void PutAutoloadLibrary(const char *sectionName)
616 {
617     if (!PutObject(AutoloadLibrary, sectionName))
618     {
619         lcf_error("No <FOREACH.AUTOLOAD.LIBRARIES> Ignored.");
620     }
621 }
622 
623 // Foreach Libraries
ForeachAutoloadLibraries(int n)624 static int ForeachAutoloadLibraries(int n)
625 {
626     return ForeachObjects(&AutoloadLibrary, Autoload->libraries.head, n);
627 }
628 
629 // SearchSymbol
PutAutoloadSearchSymbol(const char * dummy)630 static void PutAutoloadSearchSymbol(const char *dummy)
631 {
632     if (!PutObject(AutoloadSearchSymbol, NULL))
633     {
634         lcf_error("No <FOREACH.AUTOLOAD.SEARCHSYMBOLS> Ignored.");
635     }
636 }
637 
638 // Foreach SearchSymbols
ForeachAutoloadSearchSymbols(int n)639 static int ForeachAutoloadSearchSymbols(int n)
640 {
641     return ForeachObjects(&AutoloadSearchSymbol, Autoload->searchSymbols.head, n);
642 }
643 
644 // Foreach Autoloads
ForeachAutoloads(int n)645 static int ForeachAutoloads(int n)
646 {
647     tOverlay *start = AutoloadList.head;
648 
649     while (start)
650     {
651         Autoload = start;
652         PutTokenBuffer(n + 1, tokenBuffer[n].loop_end);
653         start = start->next;
654     }
655     Autoload = NULL;
656     return tokenBuffer[n].loop_end;
657 }
658 
659 
660 //======== OVERLAY ========//
661 
662 // Id
PutOverlayId(void)663 static void PutOverlayId(void)
664 {
665     if (Overlay)
666         PutNumber(Overlay->id);
667     else
668         lcf_error("No <FOREACH.OVERLAYS> Ignored.");
669 }
670 
671 // Name
PutOverlayName(void)672 static void PutOverlayName(void)
673 {
674     if (Overlay)
675         PutString(Overlay->name);
676     else
677         lcf_error("No <FOREACH.OVERLAYS> Ignored.");
678 }
679 
680 // Group
PutOverlayGroup(void)681 static void PutOverlayGroup(void)
682 {
683     if (Overlay)
684     {
685         // If a group has not been set, use the name of the overlay as a group
686         PutString(Overlay->group ? Overlay->group : Overlay->name);
687     }
688     else
689     {
690         lcf_error("No <FOREACH.OVERLAYS> Ignored.");
691     }
692 }
693 
694 // Address
PutOverlayAddress(void)695 static void PutOverlayAddress(void)
696 {
697     if (Overlay)
698         PutSectionAddress(Overlay);
699     else
700         lcf_error("No <FOREACH.OVERLAYS> Ignored.");
701 }
702 
703 // Object
PutOverlayObject(const char * sectionName)704 static void PutOverlayObject(const char *sectionName)
705 {
706     if (!PutObject(OverlayObject, sectionName))
707     {
708         lcf_error("No <FOREACH.OVERLAY.OBJECTS> Ignored.");
709     }
710 }
711 
712 // Foreach Objects
ForeachOverlayObjects(int n)713 static int ForeachOverlayObjects(int n)
714 {
715     return ForeachObjects(&OverlayObject, Overlay->objects.head, n);
716 }
717 
718 // Library
PutOverlayLibrary(const char * sectionName)719 static void PutOverlayLibrary(const char *sectionName)
720 {
721     if (!PutObject(OverlayLibrary, sectionName))
722     {
723         lcf_error("No <FOREACH.OVERLAY.LIBRARIES> Ignored.");
724     }
725 }
726 
727 // Foreach Libraries
ForeachOverlayLibraries(int n)728 static int ForeachOverlayLibraries(int n)
729 {
730     return ForeachObjects(&OverlayLibrary, Overlay->libraries.head, n);
731 }
732 
733 // SearchSymbol
PutOverlaySearchSymbol(const char * dummy)734 static void PutOverlaySearchSymbol(const char *dummy)
735 {
736     if (!PutObject(OverlaySearchSymbol, NULL))
737     {
738         lcf_error("No <FOREACH.OVERLAY.SEARCHSYMBOLS> Ignored.");
739     }
740 }
741 
742 // Foreach SearchSymbols
ForeachOverlaySearchSymbols(int n)743 static int ForeachOverlaySearchSymbols(int n)
744 {
745     return ForeachObjects(&OverlaySearchSymbol, Overlay->searchSymbols.head, n);
746 }
747 
748 // Foreach Overlays
ForeachOverlays(int n)749 static int ForeachOverlays(int n)
750 {
751     tOverlay *start = OverlayList.head;
752     tTokenBuffer *token = &tokenBuffer[n];
753     tMemType memtype = GetMemTypeParam(token->string);
754 
755     while (start)
756     {
757         if (memtype == MEMTYPE_NONE || memtype == RecgSectionMemTypeByName(start->name))
758         {
759             Overlay = start;
760             PutTokenBuffer(n + 1, tokenBuffer[n].loop_end);
761         }
762         start = start->next;
763     }
764     Overlay = NULL;
765     return tokenBuffer[n].loop_end;
766 }
767 
768 //======== LTDAUTOLOAD ========//
769 
770 // Id
PutLtdautoloadId(void)771 static void PutLtdautoloadId(void)
772 {
773     if (Ltdautoload)
774         PutNumber(Ltdautoload->id);
775     else
776         lcf_error("No <FOREACH.LTDAUTOLOADS> Ignored.");
777 }
778 
779 // Name
PutLtdautoloadName(void)780 static void PutLtdautoloadName(void)
781 {
782     if (Ltdautoload)
783         PutString(Ltdautoload->name);
784     else
785         lcf_error("No <FOREACH.LTDAUTOLOADS> Ignored.");
786 }
787 
788 // Address
PutLtdautoloadAddress(void)789 static void PutLtdautoloadAddress(void)
790 {
791     if (Ltdautoload)
792         PutSectionAddress(Ltdautoload);
793     else
794         lcf_error("No <FOREACH.LTDAUTOLOADS> Ignored.");
795 }
796 
797 // Object
PutLtdautoloadObject(const char * sectionName)798 static void PutLtdautoloadObject(const char *sectionName)
799 {
800     if (!PutObject(LtdautoloadObject, sectionName))
801     {
802         lcf_error("No <FOREACH.LTDAUTOLOAD.OBJECTS> Ignored.");
803     }
804 }
805 
806 // Foreach Objects
ForeachLtdautoloadObjects(int n)807 static int ForeachLtdautoloadObjects(int n)
808 {
809     return ForeachObjects(&LtdautoloadObject, Ltdautoload->objects.head, n);
810 }
811 
812 // Library
PutLtdautoloadLibrary(const char * sectionName)813 static void PutLtdautoloadLibrary(const char *sectionName)
814 {
815     if (!PutObject(LtdautoloadLibrary, sectionName))
816     {
817         lcf_error("No <FOREACH.LTDAUTOLOAD.LIBRARIES> Ignored.");
818     }
819 }
820 
821 // Foreach Libraries
ForeachLtdautoloadLibraries(int n)822 static int ForeachLtdautoloadLibraries(int n)
823 {
824     return ForeachObjects(&LtdautoloadLibrary, Ltdautoload->libraries.head, n);
825 }
826 
827 // SearchSymbol
PutLtdautoloadSearchSymbol(const char * dummy)828 static void PutLtdautoloadSearchSymbol(const char *dummy)
829 {
830     if (!PutObject(LtdautoloadSearchSymbol, NULL))
831     {
832         lcf_error("No <FOREACH.LTDAUTOLOAD.SEARCHSYMBOLS> Ignored.");
833     }
834 }
835 
836 // Foreach SearchSymbols
ForeachLtdautoloadSearchSymbols(int n)837 static int ForeachLtdautoloadSearchSymbols(int n)
838 {
839     return ForeachObjects(&LtdautoloadSearchSymbol, Ltdautoload->searchSymbols.head, n);
840 }
841 
842 // Foreach Ltdautoloads
ForeachLtdautoloads(int n)843 static int ForeachLtdautoloads(int n)
844 {
845     tOverlay *start = LtdautoloadList.head;
846 
847     while (start)
848     {
849         Ltdautoload = start;
850         PutTokenBuffer(n + 1, tokenBuffer[n].loop_end);
851         start = start->next;
852     }
853     Ltdautoload = NULL;
854     return tokenBuffer[n].loop_end;
855 }
856 
857 //======== LTDOVERLAY ========//
858 
859 // Id
PutLtdoverlayId(void)860 static void PutLtdoverlayId(void)
861 {
862     if (Ltdoverlay)
863         PutNumber(Ltdoverlay->id);
864     else
865         lcf_error("No <FOREACH.LTDOVERLAYS> Ignored.");
866 }
867 
868 // Name
PutLtdoverlayName(void)869 static void PutLtdoverlayName(void)
870 {
871     if (Ltdoverlay)
872         PutString(Ltdoverlay->name);
873     else
874         lcf_error("No <FOREACH.LTDOVERLAYS> Ignored.");
875 }
876 
877 // Group
PutLtdoverlayGroup(void)878 static void PutLtdoverlayGroup(void)
879 {
880     if (Ltdoverlay)
881     {
882         // If a group has not been set, use the name of the overlay as a group
883         PutString(Ltdoverlay->group ? Ltdoverlay->group : Ltdoverlay->name);
884     }
885     else
886     {
887         lcf_error("No <FOREACH.LTDOVERLAYS> Ignored.");
888     }
889 }
890 
891 // Address
PutLtdoverlayAddress(void)892 static void PutLtdoverlayAddress(void)
893 {
894     if (Ltdoverlay)
895         PutSectionAddress(Ltdoverlay);
896     else
897         lcf_error("No <FOREACH.LTDOVERLAYS> Ignored.");
898 }
899 
900 // Object
PutLtdoverlayObject(const char * sectionName)901 static void PutLtdoverlayObject(const char *sectionName)
902 {
903     if (!PutObject(LtdoverlayObject, sectionName))
904     {
905         lcf_error("No <FOREACH.LTDOVERLAY.OBJECTS> Ignored.");
906     }
907 }
908 
909 // Foreach Objects
ForeachLtdoverlayObjects(int n)910 static int ForeachLtdoverlayObjects(int n)
911 {
912     return ForeachObjects(&LtdoverlayObject, Ltdoverlay->objects.head, n);
913 }
914 
915 // Library
PutLtdoverlayLibrary(const char * sectionName)916 static void PutLtdoverlayLibrary(const char *sectionName)
917 {
918     if (!PutObject(LtdoverlayLibrary, sectionName))
919     {
920         lcf_error("No <FOREACH.LTDOVERLAY.LIBRARIES> Ignored.");
921     }
922 }
923 
924 // Foreach Libraries
ForeachLtdoverlayLibraries(int n)925 static int ForeachLtdoverlayLibraries(int n)
926 {
927     return ForeachObjects(&LtdoverlayLibrary, Ltdoverlay->libraries.head, n);
928 }
929 
930 // SearchSymbol
PutLtdoverlaySearchSymbol(const char * dummy)931 static void PutLtdoverlaySearchSymbol(const char *dummy)
932 {
933     if (!PutObject(LtdoverlaySearchSymbol, NULL))
934     {
935         lcf_error("No <FOREACH.LTDOVERLAY.SEARCHSYMBOLS> Ignored.");
936     }
937 }
938 
939 // Foreach SearchSymbols
ForeachLtdoverlaySearchSymbols(int n)940 static int ForeachLtdoverlaySearchSymbols(int n)
941 {
942     return ForeachObjects(&LtdoverlaySearchSymbol, Ltdoverlay->searchSymbols.head, n);
943 }
944 
945 // Foreach Ltdoverlays
ForeachLtdoverlays(int n)946 static int ForeachLtdoverlays(int n)
947 {
948     tOverlay *start = LtdoverlayList.head;
949     tTokenBuffer *token = &tokenBuffer[n];
950     tMemType memtype = GetMemTypeParam(token->string);
951 
952     while (start)
953     {
954         if (memtype == MEMTYPE_NONE || memtype == RecgSectionMemTypeByName(start->name))
955         {
956             Ltdoverlay = start;
957             PutTokenBuffer(n + 1, tokenBuffer[n].loop_end);
958         }
959         start = start->next;
960     }
961     Ltdoverlay = NULL;
962     return tokenBuffer[n].loop_end;
963 }
964 
965 /*============================================================================
966  *  Put Token List
967  */
PutToken(int n)968 static int PutToken(int n)
969 {
970     switch (tokenBuffer[n].id)
971     {
972     case tSTRING:
973         PutString(tokenBuffer[n].string);
974         break;
975 
976     case tSTATIC_NAME:
977         PutString(Static.name);
978         break;
979 
980     case tSTATIC_ADDRESS:
981         PutAddress(Static.address);
982         break;
983 
984     case tSTATIC_CRT0_OBJECT:
985         PutStaticCrt0Object(tokenBuffer[n].string);
986         break;
987 
988     case tSTATIC_OBJECT:
989         PutStaticObject(tokenBuffer[n].string);
990         break;
991 
992     case tSTATIC_LIBRARY:
993         PutStaticLibrary(tokenBuffer[n].string);
994         break;
995 
996     case tSTATIC_SEARCHSYMBOL:
997         PutStaticSearchSymbol(tokenBuffer[n].string);
998         break;
999 
1000     case tSTATIC_STACKSIZE:
1001         PutNumber(Static.stacksize);
1002         break;
1003 
1004     case tSTATIC_IRQSTACKSIZE:
1005         PutNumber(Static.stacksize_irq);
1006         break;
1007 
1008     case tFOREACH_STATIC_OBJECTS:
1009         n = ForeachStaticObjects(n);
1010         break;
1011 
1012     case tFOREACH_STATIC_LIBRARIES:
1013         n = ForeachStaticLibraries(n);
1014         break;
1015 
1016     case tFOREACH_STATIC_SEARCHSYMBOLS:
1017         n = ForeachStaticSearchSymbols(n);
1018         break;
1019 
1020     case tAUTOLOAD_ID:
1021         PutAutoloadId();
1022         break;
1023 
1024     case tAUTOLOAD_NAME:
1025         PutAutoloadName();
1026         break;
1027 
1028     case tAUTOLOAD_ADDRESS:
1029         PutAutoloadAddress();
1030         break;
1031 
1032     case tAUTOLOAD_OBJECT:
1033         PutAutoloadObject(tokenBuffer[n].string);
1034         break;
1035 
1036     case tAUTOLOAD_LIBRARY:
1037         PutAutoloadLibrary(tokenBuffer[n].string);
1038         break;
1039 
1040     case tAUTOLOAD_SEARCHSYMBOL:
1041         PutAutoloadSearchSymbol(tokenBuffer[n].string);
1042         break;
1043 
1044     case tNUMBER_AUTOLOADS:
1045         PutNumber(AutoloadList.num);
1046         break;
1047 
1048     case tFOREACH_AUTOLOADS:
1049         n = ForeachAutoloads(n);
1050         break;
1051 
1052     case tFOREACH_AUTOLOAD_OBJECTS:
1053         n = ForeachAutoloadObjects(n);
1054         break;
1055 
1056     case tFOREACH_AUTOLOAD_LIBRARIES:
1057         n = ForeachAutoloadLibraries(n);
1058         break;
1059 
1060     case tFOREACH_AUTOLOAD_SEARCHSYMBOLS:
1061         n = ForeachAutoloadSearchSymbols(n);
1062         break;
1063 
1064     case tOVERLAY_ID:
1065         PutOverlayId();
1066         break;
1067 
1068     case tOVERLAY_NAME:
1069         PutOverlayName();
1070         break;
1071 
1072     case tOVERLAY_GROUP:
1073         PutOverlayGroup();
1074         break;
1075 
1076     case tOVERLAY_ADDRESS:
1077         PutOverlayAddress();
1078         break;
1079 
1080     case tOVERLAY_OBJECT:
1081         PutOverlayObject(tokenBuffer[n].string);
1082         break;
1083 
1084     case tOVERLAY_LIBRARY:
1085         PutOverlayLibrary(tokenBuffer[n].string);
1086         break;
1087 
1088     case tOVERLAY_SEARCHSYMBOL:
1089         PutOverlaySearchSymbol(tokenBuffer[n].string);
1090         break;
1091 
1092     case tNUMBER_OVERLAYS:
1093         PutNumber(OverlayList.num);
1094         break;
1095 
1096     case tFOREACH_OVERLAYS:
1097         n = ForeachOverlays(n);
1098         break;
1099 
1100     case tFOREACH_OVERLAY_OBJECTS:
1101         n = ForeachOverlayObjects(n);
1102         break;
1103 
1104     case tFOREACH_OVERLAY_LIBRARIES:
1105         n = ForeachOverlayLibraries(n);
1106         break;
1107 
1108     case tFOREACH_OVERLAY_SEARCHSYMBOLS:
1109         n = ForeachOverlaySearchSymbols(n);
1110         break;
1111 
1112     case tLTDAUTOLOAD_ID:
1113         PutLtdautoloadId();
1114         break;
1115 
1116     case tLTDAUTOLOAD_NAME:
1117         PutLtdautoloadName();
1118         break;
1119 
1120     case tLTDAUTOLOAD_ADDRESS:
1121         PutLtdautoloadAddress();
1122         break;
1123 
1124     case tLTDAUTOLOAD_OBJECT:
1125         PutLtdautoloadObject(tokenBuffer[n].string);
1126         break;
1127 
1128     case tLTDAUTOLOAD_LIBRARY:
1129         PutLtdautoloadLibrary(tokenBuffer[n].string);
1130         break;
1131 
1132     case tLTDAUTOLOAD_SEARCHSYMBOL:
1133         PutLtdautoloadSearchSymbol(tokenBuffer[n].string);
1134         break;
1135 
1136     case tNUMBER_LTDAUTOLOADS:
1137         PutNumber(LtdautoloadList.num);
1138         break;
1139 
1140     case tFOREACH_LTDAUTOLOADS:
1141         n = ForeachLtdautoloads(n);
1142         break;
1143 
1144     case tFOREACH_LTDAUTOLOAD_OBJECTS:
1145         n = ForeachLtdautoloadObjects(n);
1146         break;
1147 
1148     case tFOREACH_LTDAUTOLOAD_LIBRARIES:
1149         n = ForeachLtdautoloadLibraries(n);
1150         break;
1151 
1152     case tFOREACH_LTDAUTOLOAD_SEARCHSYMBOLS:
1153         n = ForeachLtdautoloadSearchSymbols(n);
1154         break;
1155 
1156     case tLTDOVERLAY_ID:
1157         PutLtdoverlayId();
1158         break;
1159 
1160     case tLTDOVERLAY_NAME:
1161         PutLtdoverlayName();
1162         break;
1163 
1164     case tLTDOVERLAY_GROUP:
1165         PutLtdoverlayGroup();
1166         break;
1167 
1168     case tLTDOVERLAY_ADDRESS:
1169         PutLtdoverlayAddress();
1170         break;
1171 
1172     case tLTDOVERLAY_OBJECT:
1173         PutLtdoverlayObject(tokenBuffer[n].string);
1174         break;
1175 
1176     case tLTDOVERLAY_LIBRARY:
1177         PutLtdoverlayLibrary(tokenBuffer[n].string);
1178         break;
1179 
1180     case tLTDOVERLAY_SEARCHSYMBOL:
1181         PutLtdoverlaySearchSymbol(tokenBuffer[n].string);
1182         break;
1183 
1184     case tNUMBER_LTDOVERLAYS:
1185         PutNumber(LtdoverlayList.num);
1186         break;
1187 
1188     case tFOREACH_LTDOVERLAYS:
1189         n = ForeachLtdoverlays(n);
1190         break;
1191 
1192     case tFOREACH_LTDOVERLAY_OBJECTS:
1193         n = ForeachLtdoverlayObjects(n);
1194         break;
1195 
1196     case tFOREACH_LTDOVERLAY_LIBRARIES:
1197         n = ForeachLtdoverlayLibraries(n);
1198         break;
1199 
1200     case tFOREACH_LTDOVERLAY_SEARCHSYMBOLS:
1201         n = ForeachLtdoverlaySearchSymbols(n);
1202         break;
1203 
1204     case tPROPERTY_OVERLAYDEFS:
1205         PutString(Property.overlaydefs);
1206         break;
1207 
1208     case tPROPERTY_OVERLAYTABLE:
1209         PutString(Property.overlaytable);
1210         break;
1211 
1212     case tPROPERTY_LTDOVERLAYDEFS:
1213         PutString(Property.ltdoverlaydefs);
1214         break;
1215 
1216     case tPROPERTY_LTDOVERLAYTABLE:
1217         PutString(Property.ltdoverlaytable);
1218         break;
1219 
1220     case tPROPERTY_SUFFIX:
1221         PutString(Property.suffix);
1222         break;
1223 
1224     case tPROPERTY_FLXSUFFIX:
1225         PutString(Property.flxsuffix);
1226         break;
1227 
1228     case tPROPERTY_LTDSUFFIX:
1229         PutString(Property.ltdsuffix);
1230         break;
1231 
1232     default:
1233         lcf_error("Unknown token\n");
1234     }
1235     return n;
1236 }
1237 
PutTokenBuffer(int start,int end)1238 static void PutTokenBuffer(int start, int end)
1239 {
1240     int     i;
1241 
1242     for (i = start; i <= end; i++)
1243     {
1244         i = PutToken(i);
1245     }
1246 }
1247 
PutTokenBufferAll(void)1248 static void PutTokenBufferAll(void)
1249 {
1250     PutTokenBuffer(0, tokenBufferEnd - 1);
1251 }
1252 
1253 
1254 /*============================================================================
1255  *  Create LCF file
1256  */
CreateLcfFile(const char * filename)1257 int CreateLcfFile(const char *filename)
1258 {
1259     if (filename)
1260     {
1261         if (NULL == (fp_out = fopen(filename, "wb")))
1262         {
1263             fprintf(stderr, "makelcf: Cannot write %s\n", filename);
1264             return 2;
1265         }
1266         PutTokenBufferAll();
1267         fclose(fp_out);
1268     }
1269     else
1270     {
1271         setmode(1, O_BINARY);
1272         fp_out = stdout;
1273         PutTokenBufferAll();
1274     }
1275 
1276     return 0;
1277 }
1278