2 * lmo - Lua Machine Objects - PO to LMO conversion tool
4 * Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org>
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "template_lmo.h"
21 static void die(const char *msg
)
23 fprintf(stderr
, "Error: %s\n", msg
);
27 static void usage(const char *name
)
29 fprintf(stderr
, "Usage: %s input.po output.lmo\n", name
);
33 static void print(const void *ptr
, size_t size
, size_t nmemb
, FILE *stream
)
35 if( fwrite(ptr
, size
, nmemb
, stream
) == 0 )
36 die("Failed to write stdout");
39 static int extract_string(const char *src
, char *dest
, int len
)
45 for( pos
= 0; (pos
< strlen(src
)) && (pos
< len
); pos
++ )
47 if( (off
== -1) && (src
[pos
] == '"') )
62 dest
[pos
-off
] = src
[pos
];
65 else if( src
[pos
] == '\\' )
67 dest
[pos
-off
] = src
[pos
];
70 else if( src
[pos
] != '"' )
72 dest
[pos
-off
] = src
[pos
];
82 return (off
> -1) ? strlen(dest
) : -1;
85 static int cmp_index(const void *a
, const void *b
)
87 uint32_t x
= ((const lmo_entry_t
*)a
)->key_id
;
88 uint32_t y
= ((const lmo_entry_t
*)b
)->key_id
;
98 static void print_uint32(uint32_t x
, FILE *out
)
100 uint32_t y
= htonl(x
);
101 print(&y
, sizeof(uint32_t), 1, out
);
104 static void print_index(void *array
, int n
, FILE *out
)
108 qsort(array
, n
, sizeof(*e
), cmp_index
);
110 for (e
= array
; n
> 0; n
--, e
++)
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
);
119 int main(int argc
, char *argv
[])
130 lmo_entry_t
*entry
= NULL
;
131 uint32_t key_id
, val_id
;
136 if( (argc
!= 3) || ((in
= fopen(argv
[1], "r")) == NULL
) || ((out
= fopen(argv
[2], "w")) == NULL
) )
139 memset(line
, 0, sizeof(key
));
140 memset(key
, 0, sizeof(val
));
141 memset(val
, 0, sizeof(val
));
143 while( (NULL
!= fgets(line
, sizeof(line
), in
)) || (state
>= 2 && feof(in
)) )
145 if( state
== 0 && strstr(line
, "msgid \"") == line
)
147 switch(extract_string(line
, key
, sizeof(key
)))
150 die("Syntax error in msgid");
158 else if( state
== 1 || state
== 2 )
160 if( strstr(line
, "msgstr \"") == line
|| state
== 2 )
162 switch(extract_string(line
, val
, sizeof(val
)))
173 switch(extract_string(line
, tmp
, sizeof(tmp
)))
183 else if( state
== 3 )
185 switch(extract_string(line
, tmp
, sizeof(tmp
)))
197 if( strlen(key
) > 0 && strlen(val
) > 0 )
199 key_id
= sfh_hash(key
, strlen(key
));
200 val_id
= sfh_hash(val
, strlen(val
));
202 if( key_id
!= val_id
)
205 array
= realloc(array
, n_entries
* sizeof(lmo_entry_t
));
206 entry
= (lmo_entry_t
*)array
+ n_entries
- 1;
209 die("Out of memory");
211 entry
->key_id
= key_id
;
212 entry
->val_id
= val_id
;
213 entry
->offset
= offset
;
214 entry
->length
= strlen(val
);
216 length
= strlen(val
) + ((4 - (strlen(val
) % 4)) % 4);
218 print(val
, length
, 1, out
);
224 memset(key
, 0, sizeof(key
));
225 memset(val
, 0, sizeof(val
));
228 memset(line
, 0, sizeof(line
));
231 print_index(array
, n_entries
, out
);
235 print_uint32(offset
, out
);