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