1 /*
2 *******************************************************************************
3 *
4 * Copyright (C) 1999-2007, International Business Machines
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 *
16 * This file contains utility functions for ICU tools like genccode.
17 */
18
19 #include <stdio.h>
20 #include "unicode/utypes.h"
21 #include "unicode/putil.h"
22 #include "cmemory.h"
23 #include "cstring.h"
24 #include "toolutil.h"
25
26 #ifdef U_WINDOWS
27 # define VC_EXTRALEAN
28 # define WIN32_LEAN_AND_MEAN
29 # define NOUSER
30 # define NOSERVICE
31 # define NOIME
32 # define NOMCX
33 # include <windows.h>
34 # include <direct.h>
35 #else
36 # include <sys/stat.h>
37 # include <sys/types.h>
38 #endif
39 #include <errno.h>
40
41 U_CAPI const char * U_EXPORT2
getLongPathname(const char * pathname)42 getLongPathname(const char *pathname) {
43 #ifdef U_WINDOWS
44 /* anticipate problems with "short" pathnames */
45 static WIN32_FIND_DATA info;
46 HANDLE file=FindFirstFileA(pathname, &info);
47 if(file!=INVALID_HANDLE_VALUE) {
48 if(info.cAlternateFileName[0]!=0) {
49 /* this file has a short name, get and use the long one */
50 const char *basename=findBasename(pathname);
51 if(basename!=pathname) {
52 /* prepend the long filename with the original path */
53 uprv_memmove(info.cFileName+(basename-pathname), info.cFileName, uprv_strlen(info.cFileName)+1);
54 uprv_memcpy(info.cFileName, pathname, basename-pathname);
55 }
56 pathname=info.cFileName;
57 }
58 FindClose(file);
59 }
60 #endif
61 return pathname;
62 }
63
64 U_CAPI const char * U_EXPORT2
findBasename(const char * filename)65 findBasename(const char *filename) {
66 const char *basename=uprv_strrchr(filename, U_FILE_SEP_CHAR);
67
68 #if U_FILE_ALT_SEP_CHAR!=U_FILE_SEP_CHAR
69 if(basename==NULL) {
70 /* Use lenient matching on Windows, which can accept either \ or /
71 This is useful for environments like Win32+CygWin which have both.
72 */
73 basename=uprv_strrchr(filename, U_FILE_ALT_SEP_CHAR);
74 }
75 #endif
76
77 if(basename!=NULL) {
78 return basename+1;
79 } else {
80 return filename;
81 }
82 }
83
84 U_CAPI void U_EXPORT2
uprv_mkdir(const char * pathname,UErrorCode * status)85 uprv_mkdir(const char *pathname, UErrorCode *status) {
86 int retVal = 0;
87 #if defined(U_WINDOWS)
88 retVal = _mkdir(pathname);
89 #else
90 retVal = mkdir(pathname, S_IRWXU | (S_IROTH | S_IXOTH) | (S_IROTH | S_IXOTH));
91 #endif
92 if (retVal && errno != EEXIST) {
93 *status = U_FILE_ACCESS_ERROR;
94 }
95 }
96
97 /* tool memory helper ------------------------------------------------------- */
98
99 struct UToolMemory {
100 char name[64];
101 int32_t capacity, maxCapacity, size, index;
102 void *array;
103 UAlignedMemory staticArray[1];
104 };
105
106 U_CAPI UToolMemory * U_EXPORT2
utm_open(const char * name,int32_t initialCapacity,int32_t maxCapacity,int32_t size)107 utm_open(const char *name, int32_t initialCapacity, int32_t maxCapacity, int32_t size) {
108 UToolMemory *mem;
109
110 if(maxCapacity<initialCapacity) {
111 maxCapacity=initialCapacity;
112 }
113
114 mem=(UToolMemory *)uprv_malloc(sizeof(UToolMemory)+initialCapacity*size);
115 if(mem==NULL) {
116 fprintf(stderr, "error: %s - out of memory\n", name);
117 exit(U_MEMORY_ALLOCATION_ERROR);
118 }
119 mem->array=mem->staticArray;
120
121 uprv_strcpy(mem->name, name);
122 mem->capacity=initialCapacity;
123 mem->maxCapacity=maxCapacity;
124 mem->size=size;
125 mem->index=0;
126 return mem;
127 }
128
129 U_CAPI void U_EXPORT2
utm_close(UToolMemory * mem)130 utm_close(UToolMemory *mem) {
131 if(mem!=NULL) {
132 if(mem->array!=mem->staticArray) {
133 uprv_free(mem->array);
134 }
135 uprv_free(mem);
136 }
137 }
138
139
140 U_CAPI void * U_EXPORT2
utm_getStart(UToolMemory * mem)141 utm_getStart(UToolMemory *mem) {
142 return (char *)mem->array;
143 }
144
145 U_CAPI int32_t U_EXPORT2
utm_countItems(UToolMemory * mem)146 utm_countItems(UToolMemory *mem) {
147 return mem->index;
148 }
149
150
151 static UBool
utm_hasCapacity(UToolMemory * mem,int32_t capacity)152 utm_hasCapacity(UToolMemory *mem, int32_t capacity) {
153 if(mem->capacity<capacity) {
154 int32_t newCapacity;
155
156 if(mem->maxCapacity<capacity) {
157 fprintf(stderr, "error: %s - trying to use more than maxCapacity=%ld units\n",
158 mem->name, (long)mem->maxCapacity);
159 exit(U_MEMORY_ALLOCATION_ERROR);
160 }
161
162 /* try to allocate a larger array */
163 if(capacity>=2*mem->capacity) {
164 newCapacity=capacity;
165 } else if(mem->capacity<=mem->maxCapacity/3) {
166 newCapacity=2*mem->capacity;
167 } else {
168 newCapacity=mem->maxCapacity;
169 }
170
171 if(mem->array==mem->staticArray) {
172 mem->array=uprv_malloc(newCapacity*mem->size);
173 if(mem->array!=NULL) {
174 uprv_memcpy(mem->array, mem->staticArray, mem->index*mem->size);
175 }
176 } else {
177 mem->array=uprv_realloc(mem->array, newCapacity*mem->size);
178 }
179
180 if(mem->array==NULL) {
181 fprintf(stderr, "error: %s - out of memory\n", mem->name);
182 exit(U_MEMORY_ALLOCATION_ERROR);
183 }
184 }
185
186 return TRUE;
187 }
188
189 U_CAPI void * U_EXPORT2
utm_alloc(UToolMemory * mem)190 utm_alloc(UToolMemory *mem) {
191 char *p=(char *)mem->array+mem->index*mem->size;
192 int32_t newIndex=mem->index+1;
193 if(utm_hasCapacity(mem, newIndex)) {
194 mem->index=newIndex;
195 uprv_memset(p, 0, mem->size);
196 }
197 return p;
198 }
199
200 U_CAPI void * U_EXPORT2
utm_allocN(UToolMemory * mem,int32_t n)201 utm_allocN(UToolMemory *mem, int32_t n) {
202 char *p=(char *)mem->array+mem->index*mem->size;
203 int32_t newIndex=mem->index+n;
204 if(utm_hasCapacity(mem, newIndex)) {
205 mem->index=newIndex;
206 uprv_memset(p, 0, n*mem->size);
207 }
208 return p;
209 }
210