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(§ion);
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(§ion);
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