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