1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - tools - makelcf
3   File:     createlcf.c
4 
5   Copyright 2003-2008 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:: 2008-09-18#$
14   $Rev: 8573 $
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 PutStaticObject(const char *secName);
37 static void PutOverlayName(void);
38 static void PutOverlayGroup(void);
39 static void PutOverlayObject(const char *secName);
40 static void PutOverlayAddress(void);
41 static BOOL isObjectOK(const tObject * obj, const char *section, char filter_type);
42 static BOOL isSectionWildcard(const char *section);
43 static BOOL isSectionRegular(const char *section);
44 static int ForeachObjects(tObject ** ptrObject, tObject * start, int n);
45 static int ForeachStaticObjects(int n);
46 static int ForeachOverlayObjects(int n);
47 static int ForeachOverlays(int n);
48 static int PutToken(int n);
49 static void PutTokenBuffer(int start, int end);
50 static void PutTokenBufferAll(void);
51 
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 // Object
PutStaticObject(const char * sectionName)500 static void PutStaticObject(const char *sectionName)
501 {
502     if (!PutObject(StaticObject, sectionName))
503     {
504         lcf_error("No <FOREACH.STATIC.OBJECTS> Ignored.");
505     }
506 }
507 
508 // Foreach Objects
ForeachStaticObjects(int n)509 static int ForeachStaticObjects(int n)
510 {
511     return ForeachObjects(&StaticObject, Static.objects.head, n);
512 }
513 
514 // Library
PutStaticLibrary(const char * sectionName)515 static void PutStaticLibrary(const char *sectionName)
516 {
517     if (!PutObject(StaticLibrary, sectionName))
518     {
519         lcf_error("No <FOREACH.STATIC.LIBRARIES> Ignored.");
520     }
521 }
522 
523 // Foreach Libraries
ForeachStaticLibraries(int n)524 static int ForeachStaticLibraries(int n)
525 {
526     return ForeachObjects(&StaticLibrary, Static.libraries.head, n);
527 }
528 
529 // SearchSymbol
PutStaticSearchSymbol(const char * dummy)530 static void PutStaticSearchSymbol(const char *dummy)
531 {
532     if (!PutObject(StaticSearchSymbol, NULL))
533     {
534         lcf_error("No <FOREACH.STATIC.SEARCHSYMBOLS> Ignored.");
535     }
536 }
537 
538 // Foreach SearchSymbols
ForeachStaticSearchSymbols(int n)539 static int ForeachStaticSearchSymbols(int n)
540 {
541     return ForeachObjects(&StaticSearchSymbol, Static.searchSymbols.head, n);
542 }
543 
544 
545 //======== AUTOLOAD ========//
546 
547 // Id
PutAutoloadId(void)548 static void PutAutoloadId(void)
549 {
550     if (Autoload)
551         PutNumber(Autoload->id);
552     else
553         lcf_error("No <FOREACH.AUTOLOADS> Ignored.");
554 }
555 
556 // Name
PutAutoloadName(void)557 static void PutAutoloadName(void)
558 {
559     if (Autoload)
560         PutString(Autoload->name);
561     else
562         lcf_error("No <FOREACH.AUTOLOADS> Ignored.");
563 }
564 
565 // Address
PutAutoloadAddress(void)566 static void PutAutoloadAddress(void)
567 {
568     if (Autoload)
569         PutSectionAddress(Autoload);
570     else
571         lcf_error("No <FOREACH.AUTOLOADS> Ignored.");
572 }
573 
574 // Object
PutAutoloadObject(const char * sectionName)575 static void PutAutoloadObject(const char *sectionName)
576 {
577     if (!PutObject(AutoloadObject, sectionName))
578     {
579         lcf_error("No <FOREACH.AUTOLOAD.OBJECTS> Ignored.");
580     }
581 }
582 
583 // Foreach Objects
ForeachAutoloadObjects(int n)584 static int ForeachAutoloadObjects(int n)
585 {
586     return ForeachObjects(&AutoloadObject, Autoload->objects.head, n);
587 }
588 
589 // Library
PutAutoloadLibrary(const char * sectionName)590 static void PutAutoloadLibrary(const char *sectionName)
591 {
592     if (!PutObject(AutoloadLibrary, sectionName))
593     {
594         lcf_error("No <FOREACH.AUTOLOAD.LIBRARIES> Ignored.");
595     }
596 }
597 
598 // Foreach Libraries
ForeachAutoloadLibraries(int n)599 static int ForeachAutoloadLibraries(int n)
600 {
601     return ForeachObjects(&AutoloadLibrary, Autoload->libraries.head, n);
602 }
603 
604 // SearchSymbol
PutAutoloadSearchSymbol(const char * dummy)605 static void PutAutoloadSearchSymbol(const char *dummy)
606 {
607     if (!PutObject(AutoloadSearchSymbol, NULL))
608     {
609         lcf_error("No <FOREACH.AUTOLOAD.SEARCHSYMBOLS> Ignored.");
610     }
611 }
612 
613 // Foreach SearchSymbols
ForeachAutoloadSearchSymbols(int n)614 static int ForeachAutoloadSearchSymbols(int n)
615 {
616     return ForeachObjects(&AutoloadSearchSymbol, Autoload->searchSymbols.head, n);
617 }
618 
619 // Foreach Autoloads
ForeachAutoloads(int n)620 static int ForeachAutoloads(int n)
621 {
622     tOverlay *start = AutoloadList.head;
623 
624     while (start)
625     {
626         Autoload = start;
627         PutTokenBuffer(n + 1, tokenBuffer[n].loop_end);
628         start = start->next;
629     }
630     Autoload = NULL;
631     return tokenBuffer[n].loop_end;
632 }
633 
634 
635 //======== OVERLAY ========//
636 
637 // Id
PutOverlayId(void)638 static void PutOverlayId(void)
639 {
640     if (Overlay)
641         PutNumber(Overlay->id);
642     else
643         lcf_error("No <FOREACH.OVERLAYS> Ignored.");
644 }
645 
646 // Name
PutOverlayName(void)647 static void PutOverlayName(void)
648 {
649     if (Overlay)
650         PutString(Overlay->name);
651     else
652         lcf_error("No <FOREACH.OVERLAYS> Ignored.");
653 }
654 
655 // Group
PutOverlayGroup(void)656 static void PutOverlayGroup(void)
657 {
658     if (Overlay)
659     {
660         // If a group has not been set, use the name of the overlay as a group
661         PutString(Overlay->group ? Overlay->group : Overlay->name);
662     }
663     else
664     {
665         lcf_error("No <FOREACH.OVERLAYS> Ignored.");
666     }
667 }
668 
669 // Address
PutOverlayAddress(void)670 static void PutOverlayAddress(void)
671 {
672     if (Overlay)
673         PutSectionAddress(Overlay);
674     else
675         lcf_error("No <FOREACH.OVERLAYS> Ignored.");
676 }
677 
678 // Object
PutOverlayObject(const char * sectionName)679 static void PutOverlayObject(const char *sectionName)
680 {
681     if (!PutObject(OverlayObject, sectionName))
682     {
683         lcf_error("No <FOREACH.OVERLAY.OBJECTS> Ignored.");
684     }
685 }
686 
687 // Foreach Objects
ForeachOverlayObjects(int n)688 static int ForeachOverlayObjects(int n)
689 {
690     return ForeachObjects(&OverlayObject, Overlay->objects.head, n);
691 }
692 
693 // Library
PutOverlayLibrary(const char * sectionName)694 static void PutOverlayLibrary(const char *sectionName)
695 {
696     if (!PutObject(OverlayLibrary, sectionName))
697     {
698         lcf_error("No <FOREACH.OVERLAY.LIBRARIES> Ignored.");
699     }
700 }
701 
702 // Foreach Libraries
ForeachOverlayLibraries(int n)703 static int ForeachOverlayLibraries(int n)
704 {
705     return ForeachObjects(&OverlayLibrary, Overlay->libraries.head, n);
706 }
707 
708 // SearchSymbol
PutOverlaySearchSymbol(const char * dummy)709 static void PutOverlaySearchSymbol(const char *dummy)
710 {
711     if (!PutObject(OverlaySearchSymbol, NULL))
712     {
713         lcf_error("No <FOREACH.OVERLAY.SEARCHSYMBOLS> Ignored.");
714     }
715 }
716 
717 // Foreach SearchSymbols
ForeachOverlaySearchSymbols(int n)718 static int ForeachOverlaySearchSymbols(int n)
719 {
720     return ForeachObjects(&OverlaySearchSymbol, Overlay->searchSymbols.head, n);
721 }
722 
723 // Foreach Overlays
ForeachOverlays(int n)724 static int ForeachOverlays(int n)
725 {
726     tOverlay *start = OverlayList.head;
727     tTokenBuffer *token = &tokenBuffer[n];
728     tMemType memtype = GetMemTypeParam(token->string);
729 
730     while (start)
731     {
732         if (memtype == MEMTYPE_NONE || memtype == RecgSectionMemTypeByName(start->name))
733         {
734             Overlay = start;
735             PutTokenBuffer(n + 1, tokenBuffer[n].loop_end);
736         }
737         start = start->next;
738     }
739     Overlay = NULL;
740     return tokenBuffer[n].loop_end;
741 }
742 
743 //======== LTDAUTOLOAD ========//
744 
745 // Id
PutLtdautoloadId(void)746 static void PutLtdautoloadId(void)
747 {
748     if (Ltdautoload)
749         PutNumber(Ltdautoload->id);
750     else
751         lcf_error("No <FOREACH.LTDAUTOLOADS> Ignored.");
752 }
753 
754 // Name
PutLtdautoloadName(void)755 static void PutLtdautoloadName(void)
756 {
757     if (Ltdautoload)
758         PutString(Ltdautoload->name);
759     else
760         lcf_error("No <FOREACH.LTDAUTOLOADS> Ignored.");
761 }
762 
763 // Address
PutLtdautoloadAddress(void)764 static void PutLtdautoloadAddress(void)
765 {
766     if (Ltdautoload)
767         PutSectionAddress(Ltdautoload);
768     else
769         lcf_error("No <FOREACH.LTDAUTOLOADS> Ignored.");
770 }
771 
772 // Object
PutLtdautoloadObject(const char * sectionName)773 static void PutLtdautoloadObject(const char *sectionName)
774 {
775     if (!PutObject(LtdautoloadObject, sectionName))
776     {
777         lcf_error("No <FOREACH.LTDAUTOLOAD.OBJECTS> Ignored.");
778     }
779 }
780 
781 // Foreach Objects
ForeachLtdautoloadObjects(int n)782 static int ForeachLtdautoloadObjects(int n)
783 {
784     return ForeachObjects(&LtdautoloadObject, Ltdautoload->objects.head, n);
785 }
786 
787 // Library
PutLtdautoloadLibrary(const char * sectionName)788 static void PutLtdautoloadLibrary(const char *sectionName)
789 {
790     if (!PutObject(LtdautoloadLibrary, sectionName))
791     {
792         lcf_error("No <FOREACH.LTDAUTOLOAD.LIBRARIES> Ignored.");
793     }
794 }
795 
796 // Foreach Libraries
ForeachLtdautoloadLibraries(int n)797 static int ForeachLtdautoloadLibraries(int n)
798 {
799     return ForeachObjects(&LtdautoloadLibrary, Ltdautoload->libraries.head, n);
800 }
801 
802 // SearchSymbol
PutLtdautoloadSearchSymbol(const char * dummy)803 static void PutLtdautoloadSearchSymbol(const char *dummy)
804 {
805     if (!PutObject(LtdautoloadSearchSymbol, NULL))
806     {
807         lcf_error("No <FOREACH.LTDAUTOLOAD.SEARCHSYMBOLS> Ignored.");
808     }
809 }
810 
811 // Foreach SearchSymbols
ForeachLtdautoloadSearchSymbols(int n)812 static int ForeachLtdautoloadSearchSymbols(int n)
813 {
814     return ForeachObjects(&LtdautoloadSearchSymbol, Ltdautoload->searchSymbols.head, n);
815 }
816 
817 // Foreach Ltdautoloads
ForeachLtdautoloads(int n)818 static int ForeachLtdautoloads(int n)
819 {
820     tOverlay *start = LtdautoloadList.head;
821 
822     while (start)
823     {
824         Ltdautoload = start;
825         PutTokenBuffer(n + 1, tokenBuffer[n].loop_end);
826         start = start->next;
827     }
828     Ltdautoload = NULL;
829     return tokenBuffer[n].loop_end;
830 }
831 
832 //======== LTDOVERLAY ========//
833 
834 // Id
PutLtdoverlayId(void)835 static void PutLtdoverlayId(void)
836 {
837     if (Ltdoverlay)
838         PutNumber(Ltdoverlay->id);
839     else
840         lcf_error("No <FOREACH.LTDOVERLAYS> Ignored.");
841 }
842 
843 // Name
PutLtdoverlayName(void)844 static void PutLtdoverlayName(void)
845 {
846     if (Ltdoverlay)
847         PutString(Ltdoverlay->name);
848     else
849         lcf_error("No <FOREACH.LTDOVERLAYS> Ignored.");
850 }
851 
852 // Group
PutLtdoverlayGroup(void)853 static void PutLtdoverlayGroup(void)
854 {
855     if (Ltdoverlay)
856     {
857         // If a group has not been set, use the name of the overlay as a group
858         PutString(Ltdoverlay->group ? Ltdoverlay->group : Ltdoverlay->name);
859     }
860     else
861     {
862         lcf_error("No <FOREACH.LTDOVERLAYS> Ignored.");
863     }
864 }
865 
866 // Address
PutLtdoverlayAddress(void)867 static void PutLtdoverlayAddress(void)
868 {
869     if (Ltdoverlay)
870         PutSectionAddress(Ltdoverlay);
871     else
872         lcf_error("No <FOREACH.LTDOVERLAYS> Ignored.");
873 }
874 
875 // Object
PutLtdoverlayObject(const char * sectionName)876 static void PutLtdoverlayObject(const char *sectionName)
877 {
878     if (!PutObject(LtdoverlayObject, sectionName))
879     {
880         lcf_error("No <FOREACH.LTDOVERLAY.OBJECTS> Ignored.");
881     }
882 }
883 
884 // Foreach Objects
ForeachLtdoverlayObjects(int n)885 static int ForeachLtdoverlayObjects(int n)
886 {
887     return ForeachObjects(&LtdoverlayObject, Ltdoverlay->objects.head, n);
888 }
889 
890 // Library
PutLtdoverlayLibrary(const char * sectionName)891 static void PutLtdoverlayLibrary(const char *sectionName)
892 {
893     if (!PutObject(LtdoverlayLibrary, sectionName))
894     {
895         lcf_error("No <FOREACH.LTDOVERLAY.LIBRARIES> Ignored.");
896     }
897 }
898 
899 // Foreach Libraries
ForeachLtdoverlayLibraries(int n)900 static int ForeachLtdoverlayLibraries(int n)
901 {
902     return ForeachObjects(&LtdoverlayLibrary, Ltdoverlay->libraries.head, n);
903 }
904 
905 // SearchSymbol
PutLtdoverlaySearchSymbol(const char * dummy)906 static void PutLtdoverlaySearchSymbol(const char *dummy)
907 {
908     if (!PutObject(LtdoverlaySearchSymbol, NULL))
909     {
910         lcf_error("No <FOREACH.LTDOVERLAY.SEARCHSYMBOLS> Ignored.");
911     }
912 }
913 
914 // Foreach SearchSymbols
ForeachLtdoverlaySearchSymbols(int n)915 static int ForeachLtdoverlaySearchSymbols(int n)
916 {
917     return ForeachObjects(&LtdoverlaySearchSymbol, Ltdoverlay->searchSymbols.head, n);
918 }
919 
920 // Foreach Ltdoverlays
ForeachLtdoverlays(int n)921 static int ForeachLtdoverlays(int n)
922 {
923     tOverlay *start = LtdoverlayList.head;
924     tTokenBuffer *token = &tokenBuffer[n];
925     tMemType memtype = GetMemTypeParam(token->string);
926 
927     while (start)
928     {
929         if (memtype == MEMTYPE_NONE || memtype == RecgSectionMemTypeByName(start->name))
930         {
931             Ltdoverlay = start;
932             PutTokenBuffer(n + 1, tokenBuffer[n].loop_end);
933         }
934         start = start->next;
935     }
936     Ltdoverlay = NULL;
937     return tokenBuffer[n].loop_end;
938 }
939 
940 /*============================================================================
941  *  Put Token List
942  */
PutToken(int n)943 static int PutToken(int n)
944 {
945     switch (tokenBuffer[n].id)
946     {
947     case tSTRING:
948         PutString(tokenBuffer[n].string);
949         break;
950 
951     case tSTATIC_NAME:
952         PutString(Static.name);
953         break;
954 
955     case tSTATIC_ADDRESS:
956         PutAddress(Static.address);
957         break;
958 
959     case tSTATIC_OBJECT:
960         PutStaticObject(tokenBuffer[n].string);
961         break;
962 
963     case tSTATIC_LIBRARY:
964         PutStaticLibrary(tokenBuffer[n].string);
965         break;
966 
967     case tSTATIC_SEARCHSYMBOL:
968         PutStaticSearchSymbol(tokenBuffer[n].string);
969         break;
970 
971     case tSTATIC_STACKSIZE:
972         PutNumber(Static.stacksize);
973         break;
974 
975     case tSTATIC_IRQSTACKSIZE:
976         PutNumber(Static.stacksize_irq);
977         break;
978 
979     case tFOREACH_STATIC_OBJECTS:
980         n = ForeachStaticObjects(n);
981         break;
982 
983     case tFOREACH_STATIC_LIBRARIES:
984         n = ForeachStaticLibraries(n);
985         break;
986 
987     case tFOREACH_STATIC_SEARCHSYMBOLS:
988         n = ForeachStaticSearchSymbols(n);
989         break;
990 
991     case tAUTOLOAD_ID:
992         PutAutoloadId();
993         break;
994 
995     case tAUTOLOAD_NAME:
996         PutAutoloadName();
997         break;
998 
999     case tAUTOLOAD_ADDRESS:
1000         PutAutoloadAddress();
1001         break;
1002 
1003     case tAUTOLOAD_OBJECT:
1004         PutAutoloadObject(tokenBuffer[n].string);
1005         break;
1006 
1007     case tAUTOLOAD_LIBRARY:
1008         PutAutoloadLibrary(tokenBuffer[n].string);
1009         break;
1010 
1011     case tAUTOLOAD_SEARCHSYMBOL:
1012         PutAutoloadSearchSymbol(tokenBuffer[n].string);
1013         break;
1014 
1015     case tNUMBER_AUTOLOADS:
1016         PutNumber(AutoloadList.num);
1017         break;
1018 
1019     case tFOREACH_AUTOLOADS:
1020         n = ForeachAutoloads(n);
1021         break;
1022 
1023     case tFOREACH_AUTOLOAD_OBJECTS:
1024         n = ForeachAutoloadObjects(n);
1025         break;
1026 
1027     case tFOREACH_AUTOLOAD_LIBRARIES:
1028         n = ForeachAutoloadLibraries(n);
1029         break;
1030 
1031     case tFOREACH_AUTOLOAD_SEARCHSYMBOLS:
1032         n = ForeachAutoloadSearchSymbols(n);
1033         break;
1034 
1035     case tOVERLAY_ID:
1036         PutOverlayId();
1037         break;
1038 
1039     case tOVERLAY_NAME:
1040         PutOverlayName();
1041         break;
1042 
1043     case tOVERLAY_GROUP:
1044         PutOverlayGroup();
1045         break;
1046 
1047     case tOVERLAY_ADDRESS:
1048         PutOverlayAddress();
1049         break;
1050 
1051     case tOVERLAY_OBJECT:
1052         PutOverlayObject(tokenBuffer[n].string);
1053         break;
1054 
1055     case tOVERLAY_LIBRARY:
1056         PutOverlayLibrary(tokenBuffer[n].string);
1057         break;
1058 
1059     case tOVERLAY_SEARCHSYMBOL:
1060         PutOverlaySearchSymbol(tokenBuffer[n].string);
1061         break;
1062 
1063     case tNUMBER_OVERLAYS:
1064         PutNumber(OverlayList.num);
1065         break;
1066 
1067     case tFOREACH_OVERLAYS:
1068         n = ForeachOverlays(n);
1069         break;
1070 
1071     case tFOREACH_OVERLAY_OBJECTS:
1072         n = ForeachOverlayObjects(n);
1073         break;
1074 
1075     case tFOREACH_OVERLAY_LIBRARIES:
1076         n = ForeachOverlayLibraries(n);
1077         break;
1078 
1079     case tFOREACH_OVERLAY_SEARCHSYMBOLS:
1080         n = ForeachOverlaySearchSymbols(n);
1081         break;
1082 
1083     case tLTDAUTOLOAD_ID:
1084         PutLtdautoloadId();
1085         break;
1086 
1087     case tLTDAUTOLOAD_NAME:
1088         PutLtdautoloadName();
1089         break;
1090 
1091     case tLTDAUTOLOAD_ADDRESS:
1092         PutLtdautoloadAddress();
1093         break;
1094 
1095     case tLTDAUTOLOAD_OBJECT:
1096         PutLtdautoloadObject(tokenBuffer[n].string);
1097         break;
1098 
1099     case tLTDAUTOLOAD_LIBRARY:
1100         PutLtdautoloadLibrary(tokenBuffer[n].string);
1101         break;
1102 
1103     case tLTDAUTOLOAD_SEARCHSYMBOL:
1104         PutLtdautoloadSearchSymbol(tokenBuffer[n].string);
1105         break;
1106 
1107     case tNUMBER_LTDAUTOLOADS:
1108         PutNumber(LtdautoloadList.num);
1109         break;
1110 
1111     case tFOREACH_LTDAUTOLOADS:
1112         n = ForeachLtdautoloads(n);
1113         break;
1114 
1115     case tFOREACH_LTDAUTOLOAD_OBJECTS:
1116         n = ForeachLtdautoloadObjects(n);
1117         break;
1118 
1119     case tFOREACH_LTDAUTOLOAD_LIBRARIES:
1120         n = ForeachLtdautoloadLibraries(n);
1121         break;
1122 
1123     case tFOREACH_LTDAUTOLOAD_SEARCHSYMBOLS:
1124         n = ForeachLtdautoloadSearchSymbols(n);
1125         break;
1126 
1127     case tLTDOVERLAY_ID:
1128         PutLtdoverlayId();
1129         break;
1130 
1131     case tLTDOVERLAY_NAME:
1132         PutLtdoverlayName();
1133         break;
1134 
1135     case tLTDOVERLAY_GROUP:
1136         PutLtdoverlayGroup();
1137         break;
1138 
1139     case tLTDOVERLAY_ADDRESS:
1140         PutLtdoverlayAddress();
1141         break;
1142 
1143     case tLTDOVERLAY_OBJECT:
1144         PutLtdoverlayObject(tokenBuffer[n].string);
1145         break;
1146 
1147     case tLTDOVERLAY_LIBRARY:
1148         PutLtdoverlayLibrary(tokenBuffer[n].string);
1149         break;
1150 
1151     case tLTDOVERLAY_SEARCHSYMBOL:
1152         PutLtdoverlaySearchSymbol(tokenBuffer[n].string);
1153         break;
1154 
1155     case tNUMBER_LTDOVERLAYS:
1156         PutNumber(LtdoverlayList.num);
1157         break;
1158 
1159     case tFOREACH_LTDOVERLAYS:
1160         n = ForeachLtdoverlays(n);
1161         break;
1162 
1163     case tFOREACH_LTDOVERLAY_OBJECTS:
1164         n = ForeachLtdoverlayObjects(n);
1165         break;
1166 
1167     case tFOREACH_LTDOVERLAY_LIBRARIES:
1168         n = ForeachLtdoverlayLibraries(n);
1169         break;
1170 
1171     case tFOREACH_LTDOVERLAY_SEARCHSYMBOLS:
1172         n = ForeachLtdoverlaySearchSymbols(n);
1173         break;
1174 
1175     case tPROPERTY_OVERLAYDEFS:
1176         PutString(Property.overlaydefs);
1177         break;
1178 
1179     case tPROPERTY_OVERLAYTABLE:
1180         PutString(Property.overlaytable);
1181         break;
1182 
1183     case tPROPERTY_LTDOVERLAYDEFS:
1184         PutString(Property.ltdoverlaydefs);
1185         break;
1186 
1187     case tPROPERTY_LTDOVERLAYTABLE:
1188         PutString(Property.ltdoverlaytable);
1189         break;
1190 
1191     case tPROPERTY_SUFFIX:
1192         PutString(Property.suffix);
1193         break;
1194 
1195     case tPROPERTY_FLXSUFFIX:
1196         PutString(Property.flxsuffix);
1197         break;
1198 
1199     case tPROPERTY_LTDSUFFIX:
1200         PutString(Property.ltdsuffix);
1201         break;
1202 
1203     default:
1204         lcf_error("Unknown token\n");
1205     }
1206     return n;
1207 }
1208 
PutTokenBuffer(int start,int end)1209 static void PutTokenBuffer(int start, int end)
1210 {
1211     int     i;
1212 
1213     for (i = start; i <= end; i++)
1214     {
1215         i = PutToken(i);
1216     }
1217 }
1218 
PutTokenBufferAll(void)1219 static void PutTokenBufferAll(void)
1220 {
1221     PutTokenBuffer(0, tokenBufferEnd - 1);
1222 }
1223 
1224 
1225 /*============================================================================
1226  *  Create LCF file
1227  */
CreateLcfFile(const char * filename)1228 int CreateLcfFile(const char *filename)
1229 {
1230     if (filename)
1231     {
1232         if (NULL == (fp_out = fopen(filename, "wb")))
1233         {
1234             fprintf(stderr, "makelcf: Cannot write %s\n", filename);
1235             return 2;
1236         }
1237         PutTokenBufferAll();
1238         fclose(fp_out);
1239     }
1240     else
1241     {
1242         setmode(1, O_BINARY);
1243         fp_out = stdout;
1244         PutTokenBufferAll();
1245     }
1246 
1247     return 0;
1248 }
1249