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