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 *
usrc_createWithHeader(const char * path,const char * filename,const char * generator,const char * header)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
usrc_create(const char * path,const char * filename,const char * generator)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
usrc_createTextData(const char * path,const char * filename,const char * generator)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
usrc_writeArray(FILE * f,const char * prefix,const void * p,int32_t width,int32_t length,const char * postfix)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
usrc_writeUTrie2Arrays(FILE * f,const char * indexPrefix,const char * data32Prefix,const UTrie2 * pTrie,const char * postfix)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
usrc_writeUTrie2Struct(FILE * f,const char * prefix,const UTrie2 * pTrie,const char * indexName,const char * data32Name,const char * postfix)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
usrc_writeArrayOfMostlyInvChars(FILE * f,const char * prefix,const char * p,int32_t length,const char * postfix)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 }
263