1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - tools - defval
3 File: misc.c
4
5 Copyright 2005-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-17#$
14 $Rev: 8556 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17 #include "misc.h"
18
19 /*---------------------------------------------------------------------------*
20 Name: StrDup
21
22 Description: Error handling version of strdup
23
24 Arguments: str String to copy
25
26 Returns: String that was copied
27 *---------------------------------------------------------------------------*/
StrDup(const char * str)28 char *StrDup(const char *str)
29 {
30 char *cp;
31
32 if (NULL == (cp = strdup(str ? str : "")))
33 {
34 fprintf(stderr, "Error: No memory.");
35 exit(2);
36 }
37 return cp;
38 }
39
40 /*---------------------------------------------------------------------------*
41 Name: StrNDup
42
43 Description: Error-handling version of strdup with character length specification.
44
45 Arguments: str String to copy
46 len String to copy (Not including '\0')
47
48 Returns: String that was copied
49 *---------------------------------------------------------------------------*/
StrNDup(const char * str,int len)50 char *StrNDup(const char *str, int len)
51 {
52 char *cp;
53
54 cp = Calloc(len + 1);
55 if (str && len)
56 (void)strncpy(cp, str, len);
57 return cp;
58
59 // Area having len+1 bytes was allocated with malloc, so there is no need to add '\0' after strncpy.
60 //
61 // Can also support cases where str is NULL
62 }
63
64 /*---------------------------------------------------------------------------*
65 Name: StrCatDup
66
67 Description: Allocates room for a concatenated string from the heap area.
68
69 Arguments: str1 String 1 (When str1 == NULL, treated as "")
70 str2 String 2 (When str2 == NULL, treated as "")
71
72 Returns: Concatenated string
73 *---------------------------------------------------------------------------*/
StrCatDup(const char * str1,const char * str2)74 char *StrCatDup(const char *str1, const char *str2)
75 {
76 int len1, len2;
77 char *cp;
78
79 len1 = str1 ? strlen(str1) : 0;
80 len2 = str2 ? strlen(str2) : 0;
81
82 cp = Calloc(len1 + len2 + 1);
83
84 if (str1)
85 (void)strcpy(cp, str1);
86 if (str2)
87 (void)strcat(cp, str2);
88
89 return cp;
90 }
91
92 /*---------------------------------------------------------------------------*
93 Name: Calloc
94
95 Description: Error-handling version of calloc (only one argument)
96
97 Arguments: size Length of area to allocate
98
99 Returns: Allocated area
100 *---------------------------------------------------------------------------*/
Calloc(int size)101 void *Calloc(int size)
102 {
103 void *cp;
104
105 if (NULL == (cp = calloc(1, size)))
106 {
107 fprintf(stderr, "Error: No memory.");
108 exit(2);
109 }
110 return cp;
111 }
112
113 /*---------------------------------------------------------------------------*
114 Name: Free
115
116 Description: NULL-handling version of free
117 Variable *ptr is cleared to NULL
118
119 Arguments: ptr Area to free
120
121 Returns: None.
122 *---------------------------------------------------------------------------*/
Free(void ** ptr)123 void Free(void **ptr)
124 {
125 if (NULL != *ptr)
126 {
127 free(*ptr);
128 *ptr = NULL;
129 }
130 return;
131 }
132
133 /*---------------------------------------------------------------------------*
134 Name: Realloc
135
136 Description: Error-handling version of realloc
137
138 Arguments: buffer Original size
139 size Length of area to allocate
140
141 Returns: Allocated area
142 *---------------------------------------------------------------------------*/
Realloc(void * buffer,int size)143 void *Realloc(void *buffer, int size)
144 {
145 void *cp;
146
147 cp = Calloc(size);
148 if (buffer)
149 {
150 strcpy(cp, buffer);
151 free(buffer);
152 }
153 return cp;
154 }
155
156 /*---------------------------------------------------------------------------*
157 Name: Fopen
158
159 Description: Version of fopen with stdin/stdout taken into account.
160 If '-' is specified and also access mode is 'r', set to stdin.
161 If the access mode is 'w', set to stdout.
162
163 Arguments: name (Pointer to) the pointer to the file buffer
164 mode (Pointer to) the file buffer size
165
166 Returns: fp File pointer
167 *---------------------------------------------------------------------------*/
Fopen(const char * filename,const char * mode)168 FILE *Fopen(const char *filename, const char *mode)
169 {
170 FILE *fp;
171
172 DebugPrintf("filename=[%s] mode=[%s]\n", filename, mode);
173
174 if ('-' == filename[0] && '\0' == filename[1])
175 {
176 fp = (mode[0] == 'r') ? stdin : stdout;
177 }
178 else
179 {
180 if (NULL == (fp = fopen(filename, mode)))
181 {
182 fprintf(stderr, "Error: cannot open %s\n", filename);
183 return NULL;
184 }
185 }
186
187 DebugPrintf("fp=[%x] stdin=[%x] stdout=[%x]\n", fp, stdin, stdout);
188
189 return fp;
190 }
191
192 /*---------------------------------------------------------------------------*
193 Name: Fclose
194
195 Description: Version of fclose with stdin/stdout taken into account.
196 If NULL, stdin, stdout or stderr, does not close
197
198 Arguments: fp File pointer
199
200 Returns: None.
201 *---------------------------------------------------------------------------*/
Fclose(FILE * fp)202 void Fclose(FILE * fp)
203 {
204 if (fp != NULL && fp != stdin && fp != stdout && fp != stderr)
205 {
206 fclose(fp);
207 }
208 return;
209 }
210
211 /*---------------------------------------------------------------------------*
212 Name: Fgets
213
214 Description: Reads the file one line at a time.
215 Unlike the normal fgets, uses dynamic control of the buffer size to precisely read just one line.
216
217
218 Arguments: *buffer (Pointer to) the pointer to the file buffer
219 *size (Pointer to) the file buffer size
220 fp The file (If =NULL, reads from stdin)
221
222 'buffer' and 'size' are realloc'ed as necessary inside Fgets.
223 Passing 'size' as an argument reuses 'buffer' so that alloc/free processing is reduced.
224
225 It is expected that the first call will be to set *buffer to NULL.
226
227 Returns: If successful, returns *buffer. If it fails at the end of file, etc., returns NULL.
228 *---------------------------------------------------------------------------*/
Fgets(char ** pbuffer,int * pbuffer_size,FILE * fp)229 char *Fgets(char **pbuffer, int *pbuffer_size, FILE * fp)
230 {
231 char *buffer;
232 int buffer_size;
233 int buffer_gets;
234
235 assert(pbuffer);
236 assert(pbuffer_size);
237
238 buffer = *pbuffer;
239 buffer_size = *pbuffer_size;
240
241 if (buffer == NULL || buffer_size == 0)
242 {
243 buffer_size = DEFAULT_LINE_BUFFER_SIZE;
244 buffer = Calloc(buffer_size);
245 }
246
247 buffer_gets = 0;
248
249 while (NULL != fgets(buffer + buffer_gets, buffer_size - buffer_gets, fp))
250 {
251 //
252 // If the loaded line reaches the line-end, register the definition value
253 // In loading done by fgets, the end of a line is determined when:
254 // 1) Data could not be loaded up to the very end of the buffer area;
255 // 2) Data could be loaded fully, but the line ends exactly at that location.
256 //
257 buffer_gets = strlen(buffer);
258 if (buffer_gets < buffer_size - 1 || buffer[buffer_gets - 1] == '\n')
259 {
260 *pbuffer = buffer;
261 *pbuffer_size = buffer_size;
262 return buffer;
263 }
264 //
265 // If the loaded line does not reach the end of the line, double the buffer size, and continue reading.
266 //
267 //
268 else
269 {
270 buffer_size *= 2;
271 buffer = Realloc(buffer, buffer_size);
272 }
273 }
274
275 // Processing at the end of file
276 free(*pbuffer);
277 *pbuffer = NULL;
278 *pbuffer_size = 0;
279 return NULL;
280 }
281
282 /*---------------------------------------------------------------------------*
283 Name: UnpackFileName
284
285 Description: Analyzes the file name and divides it into parts: (directory, file base name, file extension)
286
287
288 Arguments: path Full path name
289 dir Directory (Including '/' etc.)
290 base File's base name
291 ext File extension (including '.')
292
293 * * Because dir, base, and ext are allocated from the heap, they must be freed
294 * * When dir, base or ext is NULL, no value is assigned
295
296 Returns: None.
297 *---------------------------------------------------------------------------*/
UnpackFileName(const char * path,char ** dir,char ** base,char ** ext)298 void UnpackFileName(const char *path, char **dir, char **base, char **ext)
299 {
300 int i, base_top, ext_top;
301 int path_len = strlen(path);
302
303 // Search for the position of the final '.' and the path delimiters
304 ext_top = path_len;
305 base_top = 0;
306
307 for (i = path_len - 1; i >= 0; i--)
308 {
309 if (path[i] == '.' && ext_top == path_len)
310 {
311 ext_top = i;
312 }
313 if (path[i] == '/' || path[i] == '\\' || path[i] == ':')
314 {
315 base_top = i + 1;
316 break;
317 }
318 }
319
320 // Processing of "." and ".." (In this case, the base is "." or "..", with no extension)
321 if (!strcmp(path + base_top, ".") || !strcmp(path + base_top, ".."))
322 {
323 ext_top = path_len;
324 }
325
326 // Assign
327 if (dir)
328 *dir = StrNDup(path, base_top);
329 if (base)
330 *base = StrNDup(path + base_top, ext_top - base_top);
331 if (ext)
332 *ext = StrDup(path + ext_top);
333 return;
334 }
335
336 /*---------------------------------------------------------------------------*
337 Name: SetDebugMode
338
339 Description: Sets debug mode.
340
341 Arguments: mode The mode
342
343 Returns: None.
344 *---------------------------------------------------------------------------*/
345 static BOOL sDebugMode = FALSE;
346
SetDebugMode(BOOL mode)347 void SetDebugMode(BOOL mode)
348 {
349 sDebugMode = mode;
350 }
351
352 /*---------------------------------------------------------------------------*
353 Name: DebugPrintf
354
355 Description: Debug print
356
357 Arguments: fmt Printf format
358 ... Variables to print
359
360 Returns: None.
361 *---------------------------------------------------------------------------*/
DebugPrintf(const char * fmt,...)362 void DebugPrintf(const char *fmt, ...)
363 {
364 va_list va;
365
366 if (sDebugMode)
367 {
368 va_start(va, fmt);
369 vfprintf(stderr, fmt, va);
370 va_end(va);
371 }
372 }
373