|
1 /* |
|
2 ******************************************************************************* |
|
3 * |
|
4 * Copyright (C) 2005-2012, International Business Machines |
|
5 * Corporation and others. All Rights Reserved. |
|
6 * |
|
7 ******************************************************************************* |
|
8 * file name: writesrc.c |
|
9 * encoding: US-ASCII |
|
10 * tab size: 8 (not used) |
|
11 * indentation:4 |
|
12 * |
|
13 * created on: 2005apr23 |
|
14 * created by: Markus W. Scherer |
|
15 * |
|
16 * Helper functions for writing source code for data. |
|
17 */ |
|
18 |
|
19 #include <stdio.h> |
|
20 #include <time.h> |
|
21 #include "unicode/utypes.h" |
|
22 #include "unicode/putil.h" |
|
23 #include "utrie2.h" |
|
24 #include "cstring.h" |
|
25 #include "writesrc.h" |
|
26 |
|
27 static FILE * |
|
28 usrc_createWithHeader(const char *path, const char *filename, |
|
29 const char *generator, const char *header) { |
|
30 char buffer[1024]; |
|
31 const char *p; |
|
32 char *q; |
|
33 FILE *f; |
|
34 char c; |
|
35 |
|
36 if(path==NULL) { |
|
37 p=filename; |
|
38 } else { |
|
39 /* concatenate path and filename, with U_FILE_SEP_CHAR in between if necessary */ |
|
40 uprv_strcpy(buffer, path); |
|
41 q=buffer+uprv_strlen(buffer); |
|
42 if(q>buffer && (c=*(q-1))!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) { |
|
43 *q++=U_FILE_SEP_CHAR; |
|
44 } |
|
45 uprv_strcpy(q, filename); |
|
46 p=buffer; |
|
47 } |
|
48 |
|
49 f=fopen(p, "w"); |
|
50 if(f!=NULL) { |
|
51 char year[8]; |
|
52 const struct tm *lt; |
|
53 time_t t; |
|
54 |
|
55 time(&t); |
|
56 lt=localtime(&t); |
|
57 strftime(year, sizeof(year), "%Y", lt); |
|
58 if(generator==NULL) { |
|
59 strftime(buffer, sizeof(buffer), "%Y-%m-%d", lt); |
|
60 fprintf(f, header, year, filename, buffer); |
|
61 } else { |
|
62 fprintf(f, header, year, filename, generator); |
|
63 } |
|
64 } else { |
|
65 fprintf( |
|
66 stderr, |
|
67 "usrc_create(%s, %s): unable to create file\n", |
|
68 path!=NULL ? path : "", filename); |
|
69 } |
|
70 return f; |
|
71 } |
|
72 |
|
73 U_CAPI FILE * U_EXPORT2 |
|
74 usrc_create(const char *path, const char *filename, const char *generator) { |
|
75 static const char *header= |
|
76 "/*\n" |
|
77 " * Copyright (C) 1999-%s, International Business Machines\n" |
|
78 " * Corporation and others. All Rights Reserved.\n" |
|
79 " *\n" |
|
80 " * file name: %s\n" |
|
81 " *\n" |
|
82 " * machine-generated by: %s\n" |
|
83 " */\n\n"; |
|
84 return usrc_createWithHeader(path, filename, generator, header); |
|
85 } |
|
86 |
|
87 U_CAPI FILE * U_EXPORT2 |
|
88 usrc_createTextData(const char *path, const char *filename, const char *generator) { |
|
89 static const char *header= |
|
90 "# Copyright (C) 1999-%s, International Business Machines\n" |
|
91 "# Corporation and others. All Rights Reserved.\n" |
|
92 "#\n" |
|
93 "# file name: %s\n" |
|
94 "#\n" |
|
95 "# machine-generated by: %s\n" |
|
96 "#\n\n"; |
|
97 return usrc_createWithHeader(path, filename, generator, header); |
|
98 } |
|
99 |
|
100 U_CAPI void U_EXPORT2 |
|
101 usrc_writeArray(FILE *f, |
|
102 const char *prefix, |
|
103 const void *p, int32_t width, int32_t length, |
|
104 const char *postfix) { |
|
105 const uint8_t *p8; |
|
106 const uint16_t *p16; |
|
107 const uint32_t *p32; |
|
108 uint32_t value; |
|
109 int32_t i, col; |
|
110 |
|
111 p8=NULL; |
|
112 p16=NULL; |
|
113 p32=NULL; |
|
114 switch(width) { |
|
115 case 8: |
|
116 p8=(const uint8_t *)p; |
|
117 break; |
|
118 case 16: |
|
119 p16=(const uint16_t *)p; |
|
120 break; |
|
121 case 32: |
|
122 p32=(const uint32_t *)p; |
|
123 break; |
|
124 default: |
|
125 fprintf(stderr, "usrc_writeArray(width=%ld) unrecognized width\n", (long)width); |
|
126 return; |
|
127 } |
|
128 if(prefix!=NULL) { |
|
129 fprintf(f, prefix, (long)length); |
|
130 } |
|
131 for(i=col=0; i<length; ++i, ++col) { |
|
132 if(i>0) { |
|
133 if(col<16) { |
|
134 fputc(',', f); |
|
135 } else { |
|
136 fputs(",\n", f); |
|
137 col=0; |
|
138 } |
|
139 } |
|
140 switch(width) { |
|
141 case 8: |
|
142 value=p8[i]; |
|
143 break; |
|
144 case 16: |
|
145 value=p16[i]; |
|
146 break; |
|
147 case 32: |
|
148 value=p32[i]; |
|
149 break; |
|
150 default: |
|
151 value=0; /* unreachable */ |
|
152 break; |
|
153 } |
|
154 fprintf(f, value<=9 ? "%lu" : "0x%lx", (unsigned long)value); |
|
155 } |
|
156 if(postfix!=NULL) { |
|
157 fputs(postfix, f); |
|
158 } |
|
159 } |
|
160 |
|
161 U_CAPI void U_EXPORT2 |
|
162 usrc_writeUTrie2Arrays(FILE *f, |
|
163 const char *indexPrefix, const char *data32Prefix, |
|
164 const UTrie2 *pTrie, |
|
165 const char *postfix) { |
|
166 if(pTrie->data32==NULL) { |
|
167 /* 16-bit trie */ |
|
168 usrc_writeArray(f, indexPrefix, pTrie->index, 16, pTrie->indexLength+pTrie->dataLength, postfix); |
|
169 } else { |
|
170 /* 32-bit trie */ |
|
171 usrc_writeArray(f, indexPrefix, pTrie->index, 16, pTrie->indexLength, postfix); |
|
172 usrc_writeArray(f, data32Prefix, pTrie->data32, 32, pTrie->dataLength, postfix); |
|
173 } |
|
174 } |
|
175 |
|
176 U_CAPI void U_EXPORT2 |
|
177 usrc_writeUTrie2Struct(FILE *f, |
|
178 const char *prefix, |
|
179 const UTrie2 *pTrie, |
|
180 const char *indexName, const char *data32Name, |
|
181 const char *postfix) { |
|
182 if(prefix!=NULL) { |
|
183 fputs(prefix, f); |
|
184 } |
|
185 if(pTrie->data32==NULL) { |
|
186 /* 16-bit trie */ |
|
187 fprintf( |
|
188 f, |
|
189 " %s,\n" /* index */ |
|
190 " %s+%ld,\n" /* data16 */ |
|
191 " NULL,\n", /* data32 */ |
|
192 indexName, |
|
193 indexName, |
|
194 (long)pTrie->indexLength); |
|
195 } else { |
|
196 /* 32-bit trie */ |
|
197 fprintf( |
|
198 f, |
|
199 " %s,\n" /* index */ |
|
200 " NULL,\n" /* data16 */ |
|
201 " %s,\n", /* data32 */ |
|
202 indexName, |
|
203 data32Name); |
|
204 } |
|
205 fprintf( |
|
206 f, |
|
207 " %ld,\n" /* indexLength */ |
|
208 " %ld,\n" /* dataLength */ |
|
209 " 0x%hx,\n" /* index2NullOffset */ |
|
210 " 0x%hx,\n" /* dataNullOffset */ |
|
211 " 0x%lx,\n" /* initialValue */ |
|
212 " 0x%lx,\n" /* errorValue */ |
|
213 " 0x%lx,\n" /* highStart */ |
|
214 " 0x%lx,\n" /* highValueIndex */ |
|
215 " NULL, 0, FALSE, FALSE, 0, NULL\n", |
|
216 (long)pTrie->indexLength, (long)pTrie->dataLength, |
|
217 (short)pTrie->index2NullOffset, (short)pTrie->dataNullOffset, |
|
218 (long)pTrie->initialValue, (long)pTrie->errorValue, |
|
219 (long)pTrie->highStart, (long)pTrie->highValueIndex); |
|
220 if(postfix!=NULL) { |
|
221 fputs(postfix, f); |
|
222 } |
|
223 } |
|
224 |
|
225 U_CAPI void U_EXPORT2 |
|
226 usrc_writeArrayOfMostlyInvChars(FILE *f, |
|
227 const char *prefix, |
|
228 const char *p, int32_t length, |
|
229 const char *postfix) { |
|
230 int32_t i, col; |
|
231 int prev2, prev, c; |
|
232 |
|
233 if(prefix!=NULL) { |
|
234 fprintf(f, prefix, (long)length); |
|
235 } |
|
236 prev2=prev=-1; |
|
237 for(i=col=0; i<length; ++i, ++col) { |
|
238 c=(uint8_t)p[i]; |
|
239 if(i>0) { |
|
240 /* Break long lines. Try to break at interesting places, to minimize revision diffs. */ |
|
241 if( |
|
242 /* Very long line. */ |
|
243 col>=32 || |
|
244 /* Long line, break after terminating NUL. */ |
|
245 (col>=24 && prev2>=0x20 && prev==0) || |
|
246 /* Medium-long line, break before non-NUL, non-character byte. */ |
|
247 (col>=16 && (prev==0 || prev>=0x20) && 0<c && c<0x20) |
|
248 ) { |
|
249 fputs(",\n", f); |
|
250 col=0; |
|
251 } else { |
|
252 fputc(',', f); |
|
253 } |
|
254 } |
|
255 fprintf(f, c<0x20 ? "%u" : "'%c'", c); |
|
256 prev2=prev; |
|
257 prev=c; |
|
258 } |
|
259 if(postfix!=NULL) { |
|
260 fputs(postfix, f); |
|
261 } |
|
262 } |