]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************* | |
3 | * | |
57a6839d | 4 | * Copyright (C) 1999-2014, International Business Machines |
b75a7d8f A |
5 | * Corporation and others. All Rights Reserved. |
6 | * | |
7 | ******************************************************************************* | |
8 | * file name: toolutil.c | |
9 | * encoding: US-ASCII | |
10 | * tab size: 8 (not used) | |
11 | * indentation:4 | |
12 | * | |
13 | * created on: 1999nov19 | |
14 | * created by: Markus W. Scherer | |
15 | * | |
729e4ab9 A |
16 | * 6/25/08 - Added Cygwin specific code in uprv_mkdir - Brian Rower |
17 | * | |
b75a7d8f A |
18 | * This file contains utility functions for ICU tools like genccode. |
19 | */ | |
20 | ||
57a6839d A |
21 | #include "unicode/platform.h" |
22 | #if U_PLATFORM == U_PF_MINGW | |
23 | // *cough* - for struct stat | |
24 | #ifdef __STRICT_ANSI__ | |
25 | #undef __STRICT_ANSI__ | |
26 | #endif | |
27 | #endif | |
28 | ||
73c04bcf | 29 | #include <stdio.h> |
729e4ab9 | 30 | #include <sys/stat.h> |
73c04bcf | 31 | #include "unicode/utypes.h" |
73c04bcf | 32 | |
4388f060 A |
33 | #ifndef U_TOOLUTIL_IMPLEMENTATION |
34 | #error U_TOOLUTIL_IMPLEMENTATION not set - must be set for all ICU source files in common/ - see http://userguide.icu-project.org/howtouseicu | |
35 | #endif | |
36 | ||
37 | #if U_PLATFORM_USES_ONLY_WIN32_API | |
b75a7d8f A |
38 | # define VC_EXTRALEAN |
39 | # define WIN32_LEAN_AND_MEAN | |
b75a7d8f A |
40 | # define NOUSER |
41 | # define NOSERVICE | |
42 | # define NOIME | |
43 | # define NOMCX | |
57a6839d A |
44 | # if U_PLATFORM == U_PF_MINGW |
45 | # define __NO_MINGW_LFS /* gets around missing 'off64_t' */ | |
46 | # endif | |
b75a7d8f | 47 | # include <windows.h> |
73c04bcf A |
48 | # include <direct.h> |
49 | #else | |
50 | # include <sys/stat.h> | |
51 | # include <sys/types.h> | |
b75a7d8f | 52 | #endif |
729e4ab9 A |
53 | |
54 | /* In MinGW environment, io.h needs to be included for _mkdir() */ | |
4388f060 | 55 | #if U_PLATFORM == U_PF_MINGW |
729e4ab9 A |
56 | #include <io.h> |
57 | #endif | |
58 | ||
73c04bcf | 59 | #include <errno.h> |
b75a7d8f | 60 | |
729e4ab9 A |
61 | #include "unicode/errorcode.h" |
62 | #include "unicode/putil.h" | |
63 | #include "cmemory.h" | |
64 | #include "cstring.h" | |
65 | #include "toolutil.h" | |
66 | #include "unicode/ucal.h" | |
67 | ||
68 | U_NAMESPACE_BEGIN | |
69 | ||
70 | IcuToolErrorCode::~IcuToolErrorCode() { | |
71 | // Safe because our handleFailure() does not throw exceptions. | |
72 | if(isFailure()) { handleFailure(); } | |
73 | } | |
74 | ||
75 | void IcuToolErrorCode::handleFailure() const { | |
76 | fprintf(stderr, "error at %s: %s\n", location, errorName()); | |
77 | exit(errorCode); | |
78 | } | |
79 | ||
80 | U_NAMESPACE_END | |
81 | ||
46f4442e A |
82 | static int32_t currentYear = -1; |
83 | ||
84 | U_CAPI int32_t U_EXPORT2 getCurrentYear() { | |
85 | #if !UCONFIG_NO_FORMATTING | |
86 | UErrorCode status=U_ZERO_ERROR; | |
87 | UCalendar *cal = NULL; | |
88 | ||
89 | if(currentYear == -1) { | |
90 | cal = ucal_open(NULL, -1, NULL, UCAL_TRADITIONAL, &status); | |
91 | ucal_setMillis(cal, ucal_getNow(), &status); | |
92 | currentYear = ucal_get(cal, UCAL_YEAR, &status); | |
93 | ucal_close(cal); | |
94 | } | |
46f4442e | 95 | #else |
729e4ab9 | 96 | /* No formatting- no way to set the current year. */ |
46f4442e | 97 | #endif |
729e4ab9 | 98 | return currentYear; |
46f4442e A |
99 | } |
100 | ||
101 | ||
b75a7d8f A |
102 | U_CAPI const char * U_EXPORT2 |
103 | getLongPathname(const char *pathname) { | |
4388f060 | 104 | #if U_PLATFORM_USES_ONLY_WIN32_API |
b75a7d8f | 105 | /* anticipate problems with "short" pathnames */ |
729e4ab9 | 106 | static WIN32_FIND_DATAA info; |
46f4442e | 107 | HANDLE file=FindFirstFileA(pathname, &info); |
b75a7d8f A |
108 | if(file!=INVALID_HANDLE_VALUE) { |
109 | if(info.cAlternateFileName[0]!=0) { | |
110 | /* this file has a short name, get and use the long one */ | |
111 | const char *basename=findBasename(pathname); | |
112 | if(basename!=pathname) { | |
113 | /* prepend the long filename with the original path */ | |
114 | uprv_memmove(info.cFileName+(basename-pathname), info.cFileName, uprv_strlen(info.cFileName)+1); | |
115 | uprv_memcpy(info.cFileName, pathname, basename-pathname); | |
116 | } | |
117 | pathname=info.cFileName; | |
118 | } | |
119 | FindClose(file); | |
120 | } | |
121 | #endif | |
122 | return pathname; | |
123 | } | |
124 | ||
729e4ab9 A |
125 | U_CAPI const char * U_EXPORT2 |
126 | findDirname(const char *path, char *buffer, int32_t bufLen, UErrorCode* status) { | |
127 | if(U_FAILURE(*status)) return NULL; | |
128 | const char *resultPtr = NULL; | |
129 | int32_t resultLen = 0; | |
130 | ||
131 | const char *basename=uprv_strrchr(path, U_FILE_SEP_CHAR); | |
132 | #if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR | |
133 | const char *basenameAlt=uprv_strrchr(path, U_FILE_ALT_SEP_CHAR); | |
134 | if(basenameAlt && (!basename || basename<basenameAlt)) { | |
135 | basename = basenameAlt; | |
136 | } | |
137 | #endif | |
138 | if(!basename) { | |
4388f060 A |
139 | /* no basename - return ''. */ |
140 | resultPtr = ""; | |
141 | resultLen = 0; | |
729e4ab9 A |
142 | } else { |
143 | resultPtr = path; | |
144 | resultLen = basename - path; | |
145 | if(resultLen<1) { | |
146 | resultLen = 1; /* '/' or '/a' -> '/' */ | |
147 | } | |
148 | } | |
149 | ||
150 | if((resultLen+1) <= bufLen) { | |
151 | uprv_strncpy(buffer, resultPtr, resultLen); | |
152 | buffer[resultLen]=0; | |
153 | return buffer; | |
154 | } else { | |
155 | *status = U_BUFFER_OVERFLOW_ERROR; | |
156 | return NULL; | |
157 | } | |
158 | } | |
159 | ||
b75a7d8f A |
160 | U_CAPI const char * U_EXPORT2 |
161 | findBasename(const char *filename) { | |
162 | const char *basename=uprv_strrchr(filename, U_FILE_SEP_CHAR); | |
374ca955 A |
163 | |
164 | #if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR | |
b331163b A |
165 | #if !(U_PLATFORM == U_PF_CYGWIN && U_PLATFORM_USES_ONLY_WIN32_API) |
166 | if(basename==NULL) | |
167 | #endif | |
168 | { | |
b75a7d8f | 169 | /* Use lenient matching on Windows, which can accept either \ or / |
374ca955 | 170 | This is useful for environments like Win32+CygWin which have both. |
b75a7d8f | 171 | */ |
374ca955 A |
172 | basename=uprv_strrchr(filename, U_FILE_ALT_SEP_CHAR); |
173 | } | |
b75a7d8f | 174 | #endif |
374ca955 A |
175 | |
176 | if(basename!=NULL) { | |
177 | return basename+1; | |
178 | } else { | |
b75a7d8f A |
179 | return filename; |
180 | } | |
181 | } | |
374ca955 | 182 | |
73c04bcf A |
183 | U_CAPI void U_EXPORT2 |
184 | uprv_mkdir(const char *pathname, UErrorCode *status) { | |
729e4ab9 | 185 | |
73c04bcf | 186 | int retVal = 0; |
4388f060 | 187 | #if U_PLATFORM_USES_ONLY_WIN32_API |
73c04bcf A |
188 | retVal = _mkdir(pathname); |
189 | #else | |
190 | retVal = mkdir(pathname, S_IRWXU | (S_IROTH | S_IXOTH) | (S_IROTH | S_IXOTH)); | |
191 | #endif | |
192 | if (retVal && errno != EEXIST) { | |
4388f060 A |
193 | #if U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN |
194 | /*if using Cygwin and the mkdir says it failed...check if the directory already exists..*/ | |
195 | /* if it does...don't give the error, if it does not...give the error - Brian Rower - 6/25/08 */ | |
196 | struct stat st; | |
197 | ||
198 | if(stat(pathname,&st) != 0) | |
199 | { | |
200 | *status = U_FILE_ACCESS_ERROR; | |
201 | } | |
729e4ab9 A |
202 | #else |
203 | *status = U_FILE_ACCESS_ERROR; | |
204 | #endif | |
205 | } | |
206 | } | |
207 | ||
57a6839d A |
208 | #if !UCONFIG_NO_FILE_IO |
209 | U_CAPI UBool U_EXPORT2 | |
210 | uprv_fileExists(const char *file) { | |
211 | struct stat stat_buf; | |
212 | if (stat(file, &stat_buf) == 0) { | |
213 | return TRUE; | |
214 | } else { | |
215 | return FALSE; | |
216 | } | |
217 | } | |
218 | #endif | |
219 | ||
729e4ab9 A |
220 | /*U_CAPI UDate U_EXPORT2 |
221 | uprv_getModificationDate(const char *pathname, UErrorCode *status) | |
222 | { | |
223 | if(U_FAILURE(*status)) { | |
224 | return; | |
225 | } | |
226 | // TODO: handle case where stat is not available | |
227 | struct stat st; | |
228 | ||
229 | if(stat(pathname,&st) != 0) | |
230 | { | |
73c04bcf | 231 | *status = U_FILE_ACCESS_ERROR; |
729e4ab9 A |
232 | } else { |
233 | return st.st_mtime; | |
73c04bcf A |
234 | } |
235 | } | |
729e4ab9 | 236 | */ |
73c04bcf | 237 | |
374ca955 A |
238 | /* tool memory helper ------------------------------------------------------- */ |
239 | ||
240 | struct UToolMemory { | |
241 | char name[64]; | |
729e4ab9 | 242 | int32_t capacity, maxCapacity, size, idx; |
374ca955 A |
243 | void *array; |
244 | UAlignedMemory staticArray[1]; | |
245 | }; | |
246 | ||
247 | U_CAPI UToolMemory * U_EXPORT2 | |
248 | utm_open(const char *name, int32_t initialCapacity, int32_t maxCapacity, int32_t size) { | |
249 | UToolMemory *mem; | |
250 | ||
251 | if(maxCapacity<initialCapacity) { | |
252 | maxCapacity=initialCapacity; | |
253 | } | |
254 | ||
255 | mem=(UToolMemory *)uprv_malloc(sizeof(UToolMemory)+initialCapacity*size); | |
256 | if(mem==NULL) { | |
257 | fprintf(stderr, "error: %s - out of memory\n", name); | |
258 | exit(U_MEMORY_ALLOCATION_ERROR); | |
259 | } | |
260 | mem->array=mem->staticArray; | |
261 | ||
262 | uprv_strcpy(mem->name, name); | |
263 | mem->capacity=initialCapacity; | |
264 | mem->maxCapacity=maxCapacity; | |
265 | mem->size=size; | |
729e4ab9 | 266 | mem->idx=0; |
374ca955 A |
267 | return mem; |
268 | } | |
269 | ||
270 | U_CAPI void U_EXPORT2 | |
271 | utm_close(UToolMemory *mem) { | |
272 | if(mem!=NULL) { | |
273 | if(mem->array!=mem->staticArray) { | |
274 | uprv_free(mem->array); | |
275 | } | |
276 | uprv_free(mem); | |
277 | } | |
278 | } | |
279 | ||
280 | ||
281 | U_CAPI void * U_EXPORT2 | |
282 | utm_getStart(UToolMemory *mem) { | |
283 | return (char *)mem->array; | |
284 | } | |
285 | ||
286 | U_CAPI int32_t U_EXPORT2 | |
287 | utm_countItems(UToolMemory *mem) { | |
729e4ab9 | 288 | return mem->idx; |
374ca955 A |
289 | } |
290 | ||
291 | ||
292 | static UBool | |
293 | utm_hasCapacity(UToolMemory *mem, int32_t capacity) { | |
294 | if(mem->capacity<capacity) { | |
295 | int32_t newCapacity; | |
296 | ||
297 | if(mem->maxCapacity<capacity) { | |
298 | fprintf(stderr, "error: %s - trying to use more than maxCapacity=%ld units\n", | |
299 | mem->name, (long)mem->maxCapacity); | |
300 | exit(U_MEMORY_ALLOCATION_ERROR); | |
301 | } | |
302 | ||
303 | /* try to allocate a larger array */ | |
304 | if(capacity>=2*mem->capacity) { | |
305 | newCapacity=capacity; | |
306 | } else if(mem->capacity<=mem->maxCapacity/3) { | |
307 | newCapacity=2*mem->capacity; | |
308 | } else { | |
309 | newCapacity=mem->maxCapacity; | |
310 | } | |
311 | ||
312 | if(mem->array==mem->staticArray) { | |
313 | mem->array=uprv_malloc(newCapacity*mem->size); | |
314 | if(mem->array!=NULL) { | |
729e4ab9 | 315 | uprv_memcpy(mem->array, mem->staticArray, mem->idx*mem->size); |
374ca955 A |
316 | } |
317 | } else { | |
318 | mem->array=uprv_realloc(mem->array, newCapacity*mem->size); | |
319 | } | |
320 | ||
321 | if(mem->array==NULL) { | |
322 | fprintf(stderr, "error: %s - out of memory\n", mem->name); | |
323 | exit(U_MEMORY_ALLOCATION_ERROR); | |
324 | } | |
729e4ab9 | 325 | mem->capacity=newCapacity; |
374ca955 A |
326 | } |
327 | ||
328 | return TRUE; | |
329 | } | |
330 | ||
331 | U_CAPI void * U_EXPORT2 | |
332 | utm_alloc(UToolMemory *mem) { | |
729e4ab9 A |
333 | char *p=NULL; |
334 | int32_t oldIndex=mem->idx; | |
335 | int32_t newIndex=oldIndex+1; | |
374ca955 | 336 | if(utm_hasCapacity(mem, newIndex)) { |
729e4ab9 A |
337 | p=(char *)mem->array+oldIndex*mem->size; |
338 | mem->idx=newIndex; | |
374ca955 A |
339 | uprv_memset(p, 0, mem->size); |
340 | } | |
341 | return p; | |
342 | } | |
343 | ||
344 | U_CAPI void * U_EXPORT2 | |
345 | utm_allocN(UToolMemory *mem, int32_t n) { | |
729e4ab9 A |
346 | char *p=NULL; |
347 | int32_t oldIndex=mem->idx; | |
348 | int32_t newIndex=oldIndex+n; | |
374ca955 | 349 | if(utm_hasCapacity(mem, newIndex)) { |
729e4ab9 A |
350 | p=(char *)mem->array+oldIndex*mem->size; |
351 | mem->idx=newIndex; | |
374ca955 A |
352 | uprv_memset(p, 0, n*mem->size); |
353 | } | |
354 | return p; | |
355 | } |