1 /*---------------------------------------------------------------------------*
2   Project:  NitroSDK - tools - makelcf
3   File:     container.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: container.c,v $
14   Revision 1.21  2007/07/09 12:17:54  yasu
15   Support for TARGET_NAME.
16 
17   Revision 1.20  2007/04/12 03:29:45  yasu
18   Revised such that IF FIRST/LAST can also support FOREACH OBJECT/LIBRARY
19 
20   Revision 1.19  2007/04/10 14:13:20  yasu
21   Support for multiple uses of SEARCH_SYMBOL
22 
23   Revision 1.18  2006/05/10 02:06:00  yasu
24   Added support for CodeWarrior 2.x
25 
26   Revision 1.17  2006/01/18 02:11:19  kitase_hirotake
27   do-indent
28 
29   Revision 1.16  2005/09/01 04:30:52  yasu
30   Support for Overlay Group
31 
32   Revision 1.15  2005/06/20 12:21:48  yasu
33   Changed Surffix to Suffix
34 
35   Revision 1.14  2005/02/28 05:26:03  yosizaki
36   do-indent.
37 
38   Revision 1.13  2004/07/10 04:06:17  yasu
39   Added support for command 'Library'
40   Support for modifier ':x' in template
41   Fixed line continue '\' issue
42 
43   Revision 1.12  2004/07/08 02:58:53  yasu
44   Support section name for multi-objects as 'Objects' parameters
45 
46   Revision 1.11  2004/07/02 07:34:53  yasu
47   Added support for OBJECT( )
48 
49   Revision 1.10  2004/06/29 04:15:13  yasu
50   Allowed string regions of OverlayDefs and OverlayTable to be expandable
51 
52   Revision 1.9  2004/06/24 07:18:54  yasu
53   Support for keyword "Autoload"
54 
55   Revision 1.8  2004/06/14 11:28:45  yasu
56   Support for section filter "FOREACH.STATIC.OBJECTS=.sectionName"
57 
58   Revision 1.7  2004/03/26 05:07:11  yasu
59   Support for variables like as -DNAME=VALUE
60 
61   Revision 1.6  2004/02/13 07:13:03  yasu
62   Support for SDK_IRQ_STACKSIZE
63 
64   Revision 1.5  2004/02/05 07:09:03  yasu
65   Changed SDK prefix iris -> nitro
66 
67   Revision 1.4  2004/01/15 10:51:45  yasu
68   Implementation of a static StackSize
69 
70   Revision 1.3  2004/01/14 12:38:08  yasu
71   Changed OverlayName to OverlayDefs
72 
73   Revision 1.2  2004/01/07 13:10:17  yasu
74   Fixed all warnings at compile -Wall
75 
76   Revision 1.1  2004/01/05 02:32:59  yasu
77   Initial version
78 
79   $NoKeywords: $
80  *---------------------------------------------------------------------------*/
81 #include	<stdio.h>
82 #include	<stdlib.h>             // exit()
83 #include	<string.h>             // strcpy(), strcat()
84 #include	<malloc.h>
85 #include	"misc.h"
86 #include	"makelcf.h"
87 #include	"defval.h"
88 
89 
90 /*============================================================================
91  *   MISC
92  */
93 tStatic Static = { 0 };
94 tProperty Property = { 0 };
95 tForeach Foreach = { { 0 } };
96 tOverlayList OverlayList = { 0, 0, 0 };
97 tOverlayList AutoloadList = { 0, 0, 0 };
98 
99 static tOverlayList *CurrentOverlay = &OverlayList;
100 
isSame(const char * s1,const char * s2)101 BOOL isSame(const char *s1, const char *s2)
102 {
103     if (s1 == s2)
104     {
105         return TRUE;
106     }
107 
108     if (!s1 || !s2)
109     {
110         return FALSE;
111     }
112 
113     while (*s1 == *s2)
114     {
115         if (!*s1)
116         {
117             return TRUE;
118         }
119         s1++;
120         s2++;
121     }
122     return FALSE;
123 }
124 
125 
126 /*============================================================================
127  *   OVERLAY
128  */
129 
NewOverlay(tOverlayList * list)130 static tOverlay *NewOverlay(tOverlayList * list)
131 {
132     tOverlay *t = Alloc(sizeof(tOverlay));
133 
134     if (list->tail)
135         list->tail->next = t;
136     else
137         list->head = t;
138     list->tail = t;
139 
140     return t;
141 }
142 
GetOverlay(tOverlayList * list,const char * overlayName)143 static tOverlay *GetOverlay(tOverlayList * list, const char *overlayName)
144 {
145     tOverlay *t = list->head;
146 
147     while (t)
148     {
149         if (isSame(t->name, overlayName))
150         {
151             return t;
152         }
153         t = t->next;
154     }
155     return NULL;
156 }
157 
158 
s_AddOverlay(tOverlayList * list,const char * overlayName)159 static BOOL s_AddOverlay(tOverlayList * list, const char *overlayName)
160 {
161     if (isSame(Static.name, overlayName) || GetOverlay(&OverlayList, overlayName)
162         || GetOverlay(&AutoloadList, overlayName))
163     {
164         spec_yyerror("Same named MAIN/OVERLAY already existed. Aborted.");
165         return FALSE;
166     }
167     else
168     {
169         tOverlay *t = NewOverlay(list);
170         t->id = list->num++;
171         t->name = overlayName;
172         t->compressSpec = 'S';
173         CurrentOverlay = list;
174     }
175     return TRUE;
176 }
177 
AddOverlay(const char * overlayName)178 BOOL AddOverlay(const char *overlayName)
179 {
180     return s_AddOverlay(&OverlayList, overlayName);
181 }
182 
AddAutoload(const char * overlayName)183 BOOL AddAutoload(const char *overlayName)
184 {
185     return s_AddOverlay(&AutoloadList, overlayName);
186 }
187 
188 /*============================================================================
189  *   OVERLAY - id
190  */
191 
OverlaySetId(u32 id)192 BOOL OverlaySetId(u32 id)
193 {
194     tOverlay *t = CurrentOverlay->tail;
195 
196     if (t->id)
197     {
198         spec_yyerror("OVERLAY ID already set. Ignored.");
199     }
200     else
201     {
202         t->id = id;
203     }
204     return TRUE;
205 }
206 
207 
208 /*============================================================================
209  *   OVERLAY - group
210  */
211 
OverlaySetGroup(const char * group)212 BOOL OverlaySetGroup(const char *group)
213 {
214     tOverlay *t = CurrentOverlay->tail;
215 
216     if (t->group)
217     {
218         spec_yyerror("overlay GROUP already set. Ignored.");
219     }
220     else
221     {
222         t->group = group;
223     }
224     return TRUE;
225 }
226 
227 
228 /*============================================================================
229  *   OVERLAY - address
230  */
231 
OverlaySetAddress(u32 address)232 BOOL OverlaySetAddress(u32 address)
233 {
234     tOverlay *t = CurrentOverlay->tail;
235 
236     if (t->afters.tail || t->address)
237     {
238         spec_yyerror("ADDRESS/AFTER already set. Ignored.");
239     }
240     else
241     {
242         t->address = address;
243     }
244     return TRUE;
245 }
246 
247 
248 /*============================================================================
249  *   OVERLAY - after
250  */
251 
NewAfter(tAfterList * list)252 static tAfter *NewAfter(tAfterList * list)
253 {
254     tAfter *t = Alloc(sizeof(tAfter));
255 
256     if (list->tail)
257         list->tail->next = t;
258     else
259         list->head = t;
260     list->tail = t;
261 
262     return t;
263 }
264 
265 
GetAfter(tAfterList * list,const char * name)266 static tAfter *GetAfter(tAfterList * list, const char *name)
267 {
268     tAfter *t = list->head;
269 
270     while (t)
271     {
272         if (isSame(t->name, name))
273         {
274             return t;
275         }
276         t = t->next;
277     }
278     return NULL;
279 }
280 
281 
AddAfter(tAfterList * list,const char * name)282 BOOL AddAfter(tAfterList * list, const char *name)
283 {
284     if (GetAfter(list, name))
285     {
286         spec_yyerror("Same AFTER already existed. Ignored.");
287     }
288     else
289     {
290         tAfter *t = NewAfter(list);
291         t->name = name;
292     }
293     return TRUE;
294 }
295 
296 
OverlayAddAfter(const char * overlayName)297 BOOL OverlayAddAfter(const char *overlayName)
298 {
299     if (CurrentOverlay->tail->address)
300     {
301         spec_yyerror("ADDRESS already set. Ignored.");
302         return TRUE;
303     }
304     return AddAfter(&CurrentOverlay->tail->afters, overlayName);
305 }
306 
307 
308 /*============================================================================
309  *   Object/Library - common
310  */
311 
NewObject(tObjectList * list)312 tObject *NewObject(tObjectList * list)
313 {
314     tObject *t = Alloc(sizeof(tObject));
315 
316     if (list->tail)
317         list->tail->next = t;
318     else
319         list->head = t;
320     list->tail = t;
321 
322     return t;
323 }
324 
325 
GetObject(tObjectList * list,const char * objectName,const char * sectionName)326 tObject *GetObject(tObjectList * list, const char *objectName, const char *sectionName)
327 {
328     tObject *t = list->head;
329 
330     while (t)
331     {
332         if (isSame(t->objectName, objectName) && isSame(t->sectionName, sectionName))
333         {
334             return t;
335         }
336         t = t->next;
337     }
338     return NULL;
339 }
340 
341 
AddObject(tObjectList * list,const char * objectName,tObjectType objectType)342 BOOL AddObject(tObjectList * list, const char *objectName, tObjectType objectType)
343 {
344     tObject *t = NewObject(list);
345     t->objectName = objectName;
346     t->sectionName = NULL;
347     t->objectType = objectType;
348     return TRUE;
349 }
350 
351 
SetObjectSection(tObjectList * list,const char * sectionName)352 BOOL SetObjectSection(tObjectList * list, const char *sectionName)
353 {
354     tObject *t = list->head;
355 
356     debug_printf("sectionName=[%s]\n", sectionName);
357 
358     while (t)
359     {
360         if (!t->sectionName)
361         {
362             debug_printf("list=%08x\n", list);
363 
364             if (!isNeedSection(t) && sectionName[0] == '*')
365             {
366                 spec_yyerror("OBJECT() must be with section option like as (.text),(.data),..");
367                 return FALSE;
368             }
369 
370             debug_printf("t->objectName=[%s]\n", t->objectName);
371 
372             if (GetObject(list, t->objectName, sectionName))
373             {
374                 char   *s = Alloc(strlen(t->objectName) + strlen(sectionName) + 80);
375                 sprintf(s, "OBJECT '%s (%s)' already existed. Ignored.", t->objectName,
376                         sectionName);
377                 spec_yyerror(s);
378                 Free(&s);
379             }
380 
381             t->sectionName = strdup(sectionName);
382         }
383         t = t->next;
384     }
385     return TRUE;
386 }
387 
388 
389 /*============================================================================
390  *   OVERLAY - object
391  */
392 
OverlayAddObject(const char * objectName,tObjectType objectType)393 BOOL OverlayAddObject(const char *objectName, tObjectType objectType)
394 {
395     return AddObject(&CurrentOverlay->tail->objects, objectName, objectType);
396 }
397 
398 
OverlaySetObjectSection(const char * sectionName)399 BOOL OverlaySetObjectSection(const char *sectionName)
400 {
401     return SetObjectSection(&CurrentOverlay->tail->objects, sectionName);
402 }
403 
404 
405 /*============================================================================
406  *   OVERLAY - library
407  */
408 
OverlayAddLibrary(const char * objectName,tObjectType objectType)409 BOOL OverlayAddLibrary(const char *objectName, tObjectType objectType)
410 {
411     return AddObject(&CurrentOverlay->tail->libraries, objectName, objectType);
412 }
413 
414 
OverlaySetLibrarySection(const char * sectionName)415 BOOL OverlaySetLibrarySection(const char *sectionName)
416 {
417     return SetObjectSection(&CurrentOverlay->tail->libraries, sectionName);
418 }
419 
420 
421 /*============================================================================
422  *   OVERLAY - searchsymbol
423  */
424 
OverlayAddSearchSymbol(const char * searchName)425 BOOL OverlayAddSearchSymbol(const char *searchName)
426 {
427     return AddObject(&CurrentOverlay->tail->searchSymbols, searchName, OBJTYPE_NONE);
428 }
429 
430 
431 /*============================================================================
432  *   OVERLAY - force
433  */
434 
OverlayAddForce(const char * forceName)435 BOOL OverlayAddForce(const char *forceName)
436 {
437     return AddObject(&CurrentOverlay->tail->forces, forceName, OBJTYPE_NONE);
438 }
439 
440 
441 /*============================================================================
442  *   OVERLAY - compress
443  */
444 
OverlaySetCompress(const char * compressSpec)445 BOOL OverlaySetCompress(const char *compressSpec)
446 {
447     char c;
448 
449     if(!strcmp(compressSpec, "SMART"))          c = 'S';
450     else if(!strcmp(compressSpec, "EXCLUSION")) c = 'E';
451     else                                        return FALSE;
452 
453     CurrentOverlay->tail->compressSpec = c;
454     return TRUE;
455 }
456 
457 
458 /*============================================================================
459  *   STATIC - name
460  */
461 
StaticSetTargetName(const char * staticTargetName)462 BOOL StaticSetTargetName(const char *staticTargetName)
463 {
464     tStatic *t = &Static;
465 
466     if (t->targetName)
467     {
468         return FALSE;
469     }
470     t->targetName = strdup(staticTargetName);
471     return TRUE;
472 }
473 
StaticSetName(const char * staticName)474 BOOL StaticSetName(const char *staticName)
475 {
476     tStatic *t = &Static;
477 
478     if (t->name)
479     {
480         spec_yyerror("'Static' section already existed. Aborted.");
481         return FALSE;
482     }
483     else if (GetOverlay(&OverlayList, staticName) || GetOverlay(&AutoloadList, staticName))
484     {
485         spec_yyerror("Same named 'Overlay' or 'Autoload' already existed. Aborted.");
486         return FALSE;
487     }
488     else
489     {
490         t->name = staticName;
491     }
492     return TRUE;
493 }
494 
495 
496 /*============================================================================
497  *   STATIC - address
498  */
499 
StaticSetAddress(u32 address)500 BOOL StaticSetAddress(u32 address)
501 {
502     tStatic *t = &Static;
503 
504     if (t->address)
505     {
506         spec_yyerror("'Address' already set. Ignored.");
507     }
508     else
509     {
510         t->address = address;
511     }
512     return TRUE;
513 }
514 
515 
516 /*============================================================================
517  *   STATIC - object
518  */
519 
StaticAddObject(const char * objectName,tObjectType objectType)520 BOOL StaticAddObject(const char *objectName, tObjectType objectType)
521 {
522     return AddObject(&Static.objects, objectName, objectType);
523 }
524 
525 
StaticSetObjectSection(const char * sectionName)526 BOOL StaticSetObjectSection(const char *sectionName)
527 {
528     return SetObjectSection(&Static.objects, sectionName);
529 }
530 
531 
532 /*============================================================================
533  *   STATIC - library
534  */
535 
StaticAddLibrary(const char * objectName,tObjectType objectType)536 BOOL StaticAddLibrary(const char *objectName, tObjectType objectType)
537 {
538     return AddObject(&Static.libraries, objectName, objectType);
539 }
540 
541 
StaticSetLibrarySection(const char * sectionName)542 BOOL StaticSetLibrarySection(const char *sectionName)
543 {
544     return SetObjectSection(&Static.libraries, sectionName);
545 }
546 
547 
548 /*============================================================================
549  *   STATIC - searchsymbol
550  */
551 
StaticAddSearchSymbol(const char * searchName)552 BOOL StaticAddSearchSymbol(const char *searchName)
553 {
554     return AddObject(&Static.searchSymbols, searchName, OBJTYPE_NONE);
555 }
556 
557 
558 /*============================================================================
559  *   STATIC - force
560  */
561 
StaticAddForce(const char * forceName)562 BOOL StaticAddForce(const char *forceName)
563 {
564     return AddObject(&Static.forces, forceName, OBJTYPE_NONE);
565 }
566 
567 
568 /*============================================================================
569  *   STATIC - address
570  */
571 
StaticSetStackSize(u32 stacksize)572 BOOL StaticSetStackSize(u32 stacksize)
573 {
574     tStatic *t = &Static;
575 
576     if (t->stacksize)
577     {
578         spec_yyerror("'StackSize' already set. Ignored.");
579     }
580     else
581     {
582         t->stacksize = stacksize;
583     }
584     return TRUE;
585 }
586 
587 
StaticSetStackSizeIrq(u32 stacksize_irq)588 BOOL StaticSetStackSizeIrq(u32 stacksize_irq)
589 {
590     tStatic *t = &Static;
591 
592     if (t->stacksize_irq)
593     {
594         spec_yyerror("'IrqStackSize' already set. Ignored.");
595     }
596     else
597     {
598         t->stacksize_irq = stacksize_irq;
599     }
600     return TRUE;
601 }
602 
603 
604 /*============================================================================
605  *   PROPERTY - OverlayTable
606  *   PROPERTY - OverlayTable
607  *   PROPERTY - Suffix
608  */
609 
610 #define	SET_PROPERTY( func, member, token )			\
611     BOOL  func( const char* val )				\
612     {								\
613 	tProperty*  t = &Property;				\
614 								\
615 	if ( t->member )					\
616 	{							\
617             spec_yyerror( "'" #token "' already set. Ignored." );\
618 	}							\
619 	else							\
620 	{							\
621 	    t->member = val;					\
622 	}							\
623         return TRUE;						\
624     }
625 
SET_PROPERTY(PropertySetOverlayDefs,overlaydefs,OverlayDefs)626 SET_PROPERTY(PropertySetOverlayDefs, overlaydefs, OverlayDefs)
627 SET_PROPERTY(PropertySetOverlayTable, overlaytable, OverlayTable)
628 SET_PROPERTY(PropertySetSuffix, suffix, Suffix)
629 /*============================================================================
630  *   CHECK SPECS
631  */
632      static BOOL CheckAfters(const char *name, tAfterList * list)
633 {
634     tAfter *t = list->head;
635 
636     while (t)
637     {
638         if (!isSame(t->name, Static.name) && !GetOverlay(&OverlayList, t->name)
639             && !GetOverlay(&AutoloadList, t->name))
640         {
641             fprintf(stderr, "No such static/autoload/overlay %s referred in overlay %s", t->name,
642                     name);
643             return FALSE;
644         }
645         t = t->next;
646     }
647     return TRUE;
648 }
649 
650 
s_CheckOverlay(tOverlayList * list)651 static BOOL s_CheckOverlay(tOverlayList * list)
652 {
653     tOverlay *t = list->head;
654 
655     while (t)
656     {
657         if (t->address)
658         {
659             if (t->afters.tail)
660             {
661                 fprintf(stderr, "Set both of 'Address' and 'After' in overlay %s", t->name);
662                 return FALSE;
663             }
664         }
665         else
666         {
667             if (t->afters.tail)
668             {
669                 if (!CheckAfters(t->name, &t->afters))
670                 {
671                     return FALSE;
672                 }
673             }
674             else
675             {
676                 fprintf(stderr, "No addressing commands 'Address'/ 'After' in overlay %s", t->name);
677                 return FALSE;
678             }
679         }
680         t = t->next;
681     }
682     return TRUE;
683 }
684 
CheckOverlay(void)685 static BOOL CheckOverlay(void)
686 {
687     return s_CheckOverlay(&AutoloadList) && s_CheckOverlay(&OverlayList);
688 }
689 
CheckStatic(void)690 static BOOL CheckStatic(void)
691 {
692     tStatic *t = &Static;
693 
694     if (!t->address)
695     {
696         fprintf(stderr, "No addressing commands 'After' in static %s", t->name);
697         return FALSE;
698     }
699 
700     if (!t->stacksize_irq)
701     {
702         t->stacksize_irq = DEFAULT_IRQSTACKSIZE;
703     }
704 
705     return TRUE;
706 }
707 
708 
CheckProperty(void)709 static BOOL CheckProperty(void)
710 {
711     tProperty *t = &Property;
712     const char *target = Static.targetName ? Static.targetName : Static.name;
713 
714     // Set default values
715     if (!t->overlaydefs)
716     {
717         t->overlaydefs = strdup(DEFAULT_OVERLAYDEFS);
718     }
719     if (t->overlaydefs[0] == '%')
720     {
721         char   *name = Alloc(strlen(target) + strlen(t->overlaydefs + 1) + 1);
722         strcpy(name, target);
723         strcat(name, t->overlaydefs + 1);
724         Free(&t->overlaydefs);
725         t->overlaydefs = name;
726     }
727 
728     if (!t->overlaytable)
729     {
730         t->overlaytable = strdup(DEFAULT_OVERLAYTABLE);
731     }
732     if (t->overlaytable[0] == '%')
733     {
734         char   *name = Alloc(strlen(target) + strlen(t->overlaytable + 1) + 1);
735         strcpy(name, target);
736         strcat(name, t->overlaytable + 1);
737         Free(&t->overlaytable);
738         t->overlaytable = name;
739     }
740 
741     if (!t->suffix)
742     {
743         t->suffix = strdup(DEFAULT_SUFFIX);
744     }
745     return TRUE;
746 }
747 
748 
CheckSpec(void)749 BOOL CheckSpec(void)
750 {
751     return (CheckStatic() && CheckOverlay() && CheckProperty());
752 }
753 
754 
755 /*============================================================================
756  *   DUMP UTILITIES
757  */
758 
DumpAfters(tAfterList * list)759 static void DumpAfters(tAfterList * list)
760 {
761     tAfter *t = list->head;
762 
763     while (t)
764     {
765         printf("  After        : %s\n", t->name);
766         t = t->next;
767     }
768 }
769 
770 
DumpObjects(tObjectList * list)771 static void DumpObjects(tObjectList * list)
772 {
773     tObject *t = list->head;
774 
775     while (t)
776     {
777         printf("  Object       : %s %s\n", t->objectName, t->sectionName);
778         t = t->next;
779     }
780 }
781 
782 
DumpAutoload(void)783 static void DumpAutoload(void)
784 {
785     tOverlay *t = AutoloadList.head;
786 
787     while (t)
788     {
789         printf("Autoload       : %s\n", t->name);
790         printf("  Address      : %08lx\n", t->address);
791         DumpAfters(&t->afters);
792         DumpObjects(&t->objects);
793         printf("\n");
794         t = t->next;
795     }
796 }
797 
798 
DumpOverlay(void)799 static void DumpOverlay(void)
800 {
801     tOverlay *t = OverlayList.head;
802 
803     while (t)
804     {
805         printf("Overlay        : %s\n", t->name);
806         printf("  Address      : %08lx\n", t->address);
807         DumpAfters(&t->afters);
808         DumpObjects(&t->objects);
809         printf("\n");
810         t = t->next;
811     }
812 }
813 
814 
DumpStatic(void)815 static void DumpStatic(void)
816 {
817     tStatic *t = &Static;
818 
819     printf("Static         : %s\n", t->name);
820     printf("  Address      : %08lx\n", t->address);
821     DumpObjects(&t->objects);
822     printf("  StackSize    : %08lx\n", t->stacksize);
823     printf("\n");
824 }
825 
826 
DumpProperty(void)827 static void DumpProperty(void)
828 {
829     tProperty *t = &Property;
830 
831     printf("Property       :\n");
832     printf("  OverlayDefs  : %s\n", t->overlaydefs);
833     printf("  OverlayTable : %s\n", t->overlaytable);
834     printf("  Suffix       : %s\n", t->suffix);
835     printf("\n");
836 }
837 
838 
DumpSpec(void)839 void DumpSpec(void)
840 {
841     DumpStatic();
842     DumpAutoload();
843     DumpOverlay();
844     DumpProperty();
845 }
846