1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - tools - makerom
3   File:     defval.c
4 
5   Copyright 2003-2008 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2008-09-18#$
14   $Rev: 8573 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 #include	<stdio.h>
18 #include	<stdlib.h>             // getenv()
19 #include	<ctype.h>              // isspace()
20 #include	<string.h>             // strcasecmp()
21 #include	<getopt.h>             // getopt()
22 #include	"misc.h"
23 #include	"defval.h"
24 #include	"makelcf.h"
25 
26 typedef struct tValdef
27 {
28     struct tValdef *next;
29     char   *name;
30     char   *value;
31 }
32 tValdef;
33 
34 tValdef *valdef_top = NULL;
35 
36 //
37 //  Add new define value via file
38 //
39 //      opt : "DEFINE=VALUE"
40 //
AddDefValFromFile(char * filename)41 BOOL AddDefValFromFile(char *filename)
42 {
43     char   *buffer;
44     int     buffer_size;
45     int     read_size;
46     FILE   *fp;
47 
48     if (filename[0] == '-' && filename[1] == '\0')
49     {
50         fp = stdin;
51     }
52     else if (NULL == (fp = fopen(filename, "rb")))
53     {
54         fprintf(stderr, "Cannot open file \"%s\".\n", filename);
55         return FALSE;
56     }
57 
58     buffer_size = DEFVAL_DEFAULT_BUFFER_SIZE;
59 
60     if (NULL == (buffer = malloc(buffer_size)))
61     {
62         fprintf(stderr, "Cannot allocate memory.\n");
63         return FALSE;
64     }
65 
66     read_size = 0;
67 
68     while (NULL != fgets(buffer + read_size, buffer_size - read_size, fp))
69     {
70         read_size = strlen(buffer);
71 
72         if (read_size == buffer_size - 1 && buffer[read_size - 1] != '\n')
73         {
74             buffer_size *= 2;
75 
76             if (NULL == (buffer = realloc(buffer, buffer_size)))
77             {
78                 fprintf(stderr, "Cannot allocate memory.\n");
79                 return FALSE;
80             }
81             continue;
82         }
83 
84         AddDefVal(buffer);
85         read_size = 0;
86     }
87 
88     if (fp != stdin)
89     {
90         fclose(fp);
91     }
92     free(buffer);
93 
94     return TRUE;
95 }
96 
97 
98 //
99 //  Add new define value
100 //
101 //      opt : "DEFINE=VALUE"
102 //
AddDefVal(char * opt)103 void AddDefVal(char *opt)
104 {
105     int     i, lastword;
106     tValdef *t;
107 
108     for (i = lastword = 0;; i++)
109     {
110         if ('=' == opt[i] || '\0' == opt[i])
111         {
112             break;
113         }
114 
115         if (!isspace(opt[i]))
116         {
117             lastword = i + 1;
118         }
119     }
120 
121     if (lastword > 0)
122     {
123         t = Alloc(sizeof(tValdef));
124         t->name = strncpy(Alloc(lastword + 1), opt, lastword);
125         t->name[lastword] = '\0';
126 
127         if (opt[i] == '=')
128         {
129             i++;
130         }
131 
132         t->value = strdup(opt + i);
133         lastword = strlen(t->value) - 1;
134         while (lastword >= 0)
135         {
136             if ('\r' != t->value[lastword] && '\n' != t->value[lastword])
137             {
138                 break;
139             }
140             t->value[lastword] = '\0';
141             lastword--;
142         }
143 
144         t->next = valdef_top;
145         valdef_top = t;
146 
147         debug_printf("DEFINE:$(%s)=\"%s\"\n", t->name, t->value);
148     }
149     return;
150 }
151 
152 //
153 //  Search define value
154 //
155 //      Return: value of specified name
156 //
SearchDefVal(const char * name)157 const char *SearchDefVal(const char *name)
158 {
159     tValdef *t;
160 
161     for (t = valdef_top; t; t = t->next)
162     {
163         if (!strcmp(t->name, name))
164         {
165             return t->value;
166         }
167     }
168     return getenv(name);
169 }
170 
171 //
172 //  SearchDefVal with NULL string handling
173 //
SearchDefValCleaned(const char * name)174 const char *SearchDefValCleaned(const char *name)
175 {
176     const char *result = NULL;
177 
178     if (name != NULL)
179     {
180         result = SearchDefVal(name);
181     }
182 
183     return result ? result : "";
184 }
185 
186 //
187 //  Resolve modifier
188 //
189 //      Return: duplicated value of specified name modified by :x option
190 //
ResolveStringModifier(const char * in_value,char modifier)191 char   *ResolveStringModifier(const char *in_value, char modifier)
192 {
193     char   *value;
194 
195     if (in_value == NULL)
196     {
197         value = NULL;
198     }
199     else if (!modifier)                // No modifier
200     {
201         value = strdup(in_value);
202     }
203     else
204     {
205         const int NO_EXTENSION = -1;
206         int     value_len = strlen(in_value);
207         int     col_extension = NO_EXTENSION;
208         int     col_filename = 0;
209         int     i;
210 
211         for (i = 0; i < value_len; i++)
212         {
213             switch (in_value[i])
214             {
215             case '.':
216                 if (col_filename == i &&
217                     (in_value[i + 1] == '\0' ||
218                      (in_value[i + 1] == '.' && in_value[i + 2] == '\0')))
219                 {
220                     i = value_len;     // exit loop if last entry is '.' or '..'
221                 }
222                 else
223                 {
224                     col_extension = i; // Save the last dot column
225                 }
226                 break;
227 
228             case '/':
229             case '\\':
230             case ':':
231                 col_filename = i + 1;  // Save the last filename
232                 col_extension = NO_EXTENSION;   // Reset dot position
233                 break;
234 
235             default:
236                 ;
237             }
238         }
239 
240         switch (modifier)
241         {
242         case 'h':                     // Dirname with the last slash
243             value = strdup(in_value);
244             value[col_filename] = '\0';
245             break;
246 
247         case 't':                     // Filename
248             value = strdup(in_value + col_filename);
249             break;
250 
251         case 'r':                     // All without . file extension
252             value = strdup(in_value);
253             if (col_extension >= 0)
254             {
255                 value[col_extension] = '\0';
256             }
257             break;
258 
259         case 'e':                     // File extension
260             if (col_extension >= 0)
261             {
262                 value = strdup(in_value + col_extension + 1);
263             }
264             else
265             {
266                 value = strdup("");
267             }
268             break;
269 
270         default:                      // Unknown
271             fprintf(stderr, "Unknown modifier ':%c'... Ignored.\n", modifier);
272             value = strdup(in_value);
273             break;
274         }
275     }
276     return value;
277 }
278 
279 
280 //
281 //  Search define value and Modify it by ':' modifier
282 //
283 //      Return: duplicated value of specified name modified by ':X'
284 //
SearchDefValWithOption(const char * in_name)285 char   *SearchDefValWithOption(const char *in_name)
286 {
287     char   *name = strdup(in_name);
288     int     len_name = strlen(in_name);
289     char    modifier = '\0';
290     char   *value;
291 
292     if (len_name > 2 && name[len_name - 2] == ':')
293     {
294         name[len_name - 2] = '\0';
295         modifier = name[len_name - 1];
296     }
297 
298     value = ResolveStringModifier(SearchDefVal(name), modifier);
299 
300     debug_printf("REFERED(%s)=[%s]\n", in_name, value ? value : "(NULL)");
301 
302     free(name);
303 
304     return value;
305 }
306 
307 
308 //
309 //  Resolve define value
310 //
311 //      Return: new string
312 //
ResolveDefVal(char * str)313 char   *ResolveDefVal(char *str)
314 {
315     int     i, j;
316     char   *val;
317     VBuffer buf;
318 
319     InitVBuffer(&buf);
320 
321     for (i = 0; '\0' != str[i]; i++)
322     {
323         // search $(XXX)
324         if ('$' == str[i] && '(' == str[i + 1])
325         {
326             for (j = i + 2; '\0' != str[j]; j++)
327             {
328                 if (')' == str[j])
329                 {
330                     str[j] = '\0';
331 
332                     // get value of XXX
333                     val = SearchDefValWithOption(&str[i + 2]);
334 
335                     // copy value of XXX
336                     if (val)
337                     {
338                         char   *s = val;
339 
340                         while (*s)
341                         {
342                             PutVBuffer(&buf, *s);
343                             s++;
344                         }
345                         free(val);
346                     }
347                     i = j;
348                     goto next;
349                 }
350             }
351         }
352         PutVBuffer(&buf, str[i]);
353       next:;
354     }
355     return GetVBuffer(&buf);           // pass allocated buffer, should be freed by caller
356 }
357