Merge pull request #1005 from kdarbyshirebryant/miniupnpenable
[project/luci.git] / modules / luci-base / src / po2lmo.c
1 /*
2  * lmo - Lua Machine Objects - PO to LMO conversion tool
3  *
4  *   Copyright (C) 2009-2012 Jo-Philipp Wich <jow@openwrt.org>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  */
18
19 #include "template_lmo.h"
20
21 static void die(const char *msg)
22 {
23         fprintf(stderr, "Error: %s\n", msg);
24         exit(1);
25 }
26
27 static void usage(const char *name)
28 {
29         fprintf(stderr, "Usage: %s input.po output.lmo\n", name);
30         exit(1);
31 }
32
33 static void print(const void *ptr, size_t size, size_t nmemb, FILE *stream)
34 {
35         if( fwrite(ptr, size, nmemb, stream) == 0 )
36                 die("Failed to write stdout");
37 }
38
39 static int extract_string(const char *src, char *dest, int len)
40 {
41         int pos = 0;
42         int esc = 0;
43         int off = -1;
44
45         for( pos = 0; (pos < strlen(src)) && (pos < len); pos++ )
46         {
47                 if( (off == -1) && (src[pos] == '"') )
48                 {
49                         off = pos + 1;
50                 }
51                 else if( off >= 0 )
52                 {
53                         if( esc == 1 )
54                         {
55                                 switch (src[pos])
56                                 {
57                                 case '"':
58                                 case '\\':
59                                         off++;
60                                         break;
61                                 }
62                                 dest[pos-off] = src[pos];
63                                 esc = 0;
64                         }
65                         else if( src[pos] == '\\' )
66                         {
67                                 dest[pos-off] = src[pos];
68                                 esc = 1;
69                         }
70                         else if( src[pos] != '"' )
71                         {
72                                 dest[pos-off] = src[pos];
73                         }
74                         else
75                         {
76                                 dest[pos-off] = '\0';
77                                 break;
78                         }
79                 }
80         }
81
82         return (off > -1) ? strlen(dest) : -1;
83 }
84
85 static int cmp_index(const void *a, const void *b)
86 {
87         uint32_t x = ((const lmo_entry_t *)a)->key_id;
88         uint32_t y = ((const lmo_entry_t *)b)->key_id;
89
90         if (x < y)
91                 return -1;
92         else if (x > y)
93                 return 1;
94
95         return 0;
96 }
97
98 static void print_uint32(uint32_t x, FILE *out)
99 {
100         uint32_t y = htonl(x);
101         print(&y, sizeof(uint32_t), 1, out);
102 }
103
104 static void print_index(void *array, int n, FILE *out)
105 {
106         lmo_entry_t *e;
107
108         qsort(array, n, sizeof(*e), cmp_index);
109
110         for (e = array; n > 0; n--, e++)
111         {
112                 print_uint32(e->key_id, out);
113                 print_uint32(e->val_id, out);
114                 print_uint32(e->offset, out);
115                 print_uint32(e->length, out);
116         }
117 }
118
119 int main(int argc, char *argv[])
120 {
121         char line[4096];
122         char key[4096];
123         char val[4096];
124         char tmp[4096];
125         int state  = 0;
126         int offset = 0;
127         int length = 0;
128         int n_entries = 0;
129         void *array = NULL;
130         lmo_entry_t *entry = NULL;
131         uint32_t key_id, val_id;
132
133         FILE *in;
134         FILE *out;
135
136         if( (argc != 3) || ((in = fopen(argv[1], "r")) == NULL) || ((out = fopen(argv[2], "w")) == NULL) )
137                 usage(argv[0]);
138
139         memset(line, 0, sizeof(key));
140         memset(key, 0, sizeof(val));
141         memset(val, 0, sizeof(val));
142
143         while( (NULL != fgets(line, sizeof(line), in)) || (state >= 2 && feof(in)) )
144         {
145                 if( state == 0 && strstr(line, "msgid \"") == line )
146                 {
147                         switch(extract_string(line, key, sizeof(key)))
148                         {
149                                 case -1:
150                                         die("Syntax error in msgid");
151                                 case 0:
152                                         state = 1;
153                                         break;
154                                 default:
155                                         state = 2;
156                         }
157                 }
158                 else if( state == 1 || state == 2 )
159                 {
160                         if( strstr(line, "msgstr \"") == line || state == 2 )
161                         {
162                                 switch(extract_string(line, val, sizeof(val)))
163                                 {
164                                         case -1:
165                                                 state = 4;
166                                                 break;
167                                         default:
168                                                 state = 3;
169                                 }
170                         }
171                         else
172                         {
173                                 switch(extract_string(line, tmp, sizeof(tmp)))
174                                 {
175                                         case -1:
176                                                 state = 2;
177                                                 break;
178                                         default:
179                                                 strcat(key, tmp);
180                                 }
181                         }
182                 }
183                 else if( state == 3 )
184                 {
185                         switch(extract_string(line, tmp, sizeof(tmp)))
186                         {
187                                 case -1:
188                                         state = 4;
189                                         break;
190                                 default:
191                                         strcat(val, tmp);
192                         }
193                 }
194
195                 if( state == 4 )
196                 {
197                         if( strlen(key) > 0 && strlen(val) > 0 )
198                         {
199                                 key_id = sfh_hash(key, strlen(key));
200                                 val_id = sfh_hash(val, strlen(val));
201
202                                 if( key_id != val_id )
203                                 {
204                                         n_entries++;
205                                         array = realloc(array, n_entries * sizeof(lmo_entry_t));
206                                         entry = (lmo_entry_t *)array + n_entries - 1;
207
208                                         if (!array)
209                                                 die("Out of memory");
210
211                                         entry->key_id = key_id;
212                                         entry->val_id = val_id;
213                                         entry->offset = offset;
214                                         entry->length = strlen(val);
215
216                                         length = strlen(val) + ((4 - (strlen(val) % 4)) % 4);
217
218                                         print(val, length, 1, out);
219                                         offset += length;
220                                 }
221                         }
222
223                         state = 0;
224                         memset(key, 0, sizeof(key));
225                         memset(val, 0, sizeof(val));
226                 }
227
228                 memset(line, 0, sizeof(line));
229         }
230
231         print_index(array, n_entries, out);
232
233         if( offset > 0 )
234         {
235                 print_uint32(offset, out);
236                 fsync(fileno(out));
237                 fclose(out);
238         }
239         else
240         {
241                 fclose(out);
242                 unlink(argv[2]);
243         }
244
245         fclose(in);
246         return(0);
247 }