1 /* $Id$ */ |
1 /* $Id$ */ |
2 |
2 |
3 #define STRGEN |
3 #if defined(WIN32) || defined(WIN64) || defined(__CYGWIN__) |
|
4 #define WIN32 |
|
5 #else |
|
6 #define UNIX |
|
7 #endif |
4 |
8 |
5 #include "../stdafx.h" |
9 #include "../stdafx.h" |
6 #include "../macros.h" |
10 #include "../macros.h" |
|
11 #include "../string.h" |
7 #include <stdio.h> |
12 #include <stdio.h> |
8 #include <string.h> |
13 #include <string.h> |
9 #include <stdlib.h> |
14 #include <stdlib.h> |
10 #include <stdarg.h> |
15 #include <stdarg.h> |
11 |
16 |
12 #if (!defined(WIN32) && !defined(WIN64)) || defined(__CYGWIN__) |
17 #if (!defined(WIN32) && !defined(WIN64)) || defined(__CYGWIN__) |
13 #include <unistd.h> |
18 #include <unistd.h> |
14 #endif |
19 #endif |
|
20 |
|
21 #if defined WIN32 || defined __WATCOMC__ |
|
22 #include <direct.h> |
|
23 #endif /* WIN32 || __WATCOMC__ */ |
15 |
24 |
16 #ifdef __MORPHOS__ |
25 #ifdef __MORPHOS__ |
17 #ifdef stderr |
26 #ifdef stderr |
18 #undef stderr |
27 #undef stderr |
19 #endif |
28 #endif |
20 #define stderr stdout |
29 #define stderr stdout |
21 #endif // __MORPHOS__ |
30 #endif /* __MORPHOS__ */ |
22 |
31 |
23 #ifdef __WATCOMC__ |
32 #ifdef __WATCOMC__ |
24 uint _map_log_x; // an unpleasant hack required because Watcom is insisting on |
33 uint _map_log_x; // an unpleasant hack required because Watcom is insisting on |
25 uint _map_size_x; // these variables being valid references in map.h |
34 uint _map_size_x; // these variables being valid references in map.h |
26 uint _map_size_y; |
35 uint _map_size_y; |
27 uint _map_tile_mask; |
36 uint _map_tile_mask; |
28 uint _map_size; |
37 uint _map_size; |
29 #endif |
38 #endif /* __WATCOMC__ */ |
30 |
39 |
31 /* Compiles a list of strings into a compiled string list */ |
40 /* Compiles a list of strings into a compiled string list */ |
32 |
41 |
33 typedef void (*ParseCmdProc)(char *buf, int value); |
42 typedef void (*ParseCmdProc)(char *buf, int value); |
34 |
43 |
182 static void NORETURN CDECL Fatal(const char *s, ...) |
191 static void NORETURN CDECL Fatal(const char *s, ...) |
183 { |
192 { |
184 char buf[1024]; |
193 char buf[1024]; |
185 va_list va; |
194 va_list va; |
186 va_start(va, s); |
195 va_start(va, s); |
187 vsprintf(buf, s, va); |
196 vsnprintf(buf, lengthof(buf), s, va); |
188 va_end(va); |
197 va_end(va); |
189 fprintf(stderr, "%s" LINE_NUM_FMT ": FATAL: %s\n", _file, _cur_line, buf); |
198 fprintf(stderr, "%s" LINE_NUM_FMT ": FATAL: %s\n", _file, _cur_line, buf); |
190 exit(1); |
199 exit(1); |
191 } |
200 } |
192 |
|
193 |
|
194 static void ttd_strlcpy(char *dst, const char *src, size_t len) |
|
195 { |
|
196 assert(len > 0); |
|
197 while (--len > 0 && *src != '\0') *dst++ = *src++; |
|
198 *dst = '\0'; |
|
199 } |
|
200 |
|
201 |
201 |
202 static void PutByte(byte c) |
202 static void PutByte(byte c) |
203 { |
203 { |
204 if (_put_pos == lengthof(_put_buf)) Fatal("Put buffer too small"); |
204 if (_put_pos == lengthof(_put_buf)) Fatal("Put buffer too small"); |
205 _put_buf[_put_pos++] = c; |
205 _put_buf[_put_pos++] = c; |
1203 |
1203 |
1204 fputc(0, f); |
1204 fputc(0, f); |
1205 fclose(f); |
1205 fclose(f); |
1206 } |
1206 } |
1207 |
1207 |
|
1208 /** Multi-OS mkdirectory function */ |
|
1209 static inline void ottd_mkdir(const char *directory) |
|
1210 { |
|
1211 #if defined(WIN32) || defined(__WATCOMC__) |
|
1212 mkdir(directory); |
|
1213 #else |
|
1214 mkdir(directory, 0755); |
|
1215 #endif |
|
1216 } |
|
1217 |
|
1218 /** Create a path consisting of an already existing path, a possible |
|
1219 * path seperator and the filename. The seperator is only appended if the path |
|
1220 * does not already end with a seperator */ |
|
1221 static inline char *mkpath(char *buf, size_t buflen, const char *path, const char *file) |
|
1222 { |
|
1223 char *p; |
|
1224 ttd_strlcpy(buf, path, buflen); // copy directory into buffer |
|
1225 |
|
1226 p = strchr(buf, '\0'); // add path seperator if necessary |
|
1227 if (p[-1] != PATHSEPCHAR && (size_t)(p - buf) + 1 < buflen) *p++ = PATHSEPCHAR; |
|
1228 ttd_strlcpy(p, file, buflen - (size_t)(p - buf)); // catenate filename at end of buffer |
|
1229 return buf; |
|
1230 } |
|
1231 |
1208 |
1232 |
1209 int CDECL main(int argc, char* argv[]) |
1233 int CDECL main(int argc, char* argv[]) |
1210 { |
1234 { |
|
1235 char pathbuf[256]; |
|
1236 const char *src_dir, *dest_dir; |
|
1237 |
1211 int show_todo = 0; |
1238 int show_todo = 0; |
1212 |
1239 |
1213 if (argc > 1 && (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "--version") == 0)) { |
1240 if (argc > 1 && (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "--version") == 0)) { |
1214 puts("$Revision$"); |
1241 puts("$Revision$"); |
1215 return 0; |
1242 return 0; |
1216 } |
1243 } |
1217 |
1244 |
1218 if (argc > 1 && |
1245 if (argc > 1 && (strcmp(argv[1], "-t") == 0 || strcmp(argv[1], "--todo") == 0)) { |
1219 (strcmp(argv[1], "-t") == 0 || strcmp(argv[1], "--todo") == 0)) { |
|
1220 show_todo = 1; |
1246 show_todo = 1; |
1221 argc--, argv++; |
1247 argc--, argv++; |
1222 } |
1248 } |
1223 |
1249 |
1224 if (argc > 1 && |
1250 if (argc > 1 && (strcmp(argv[1], "-w") == 0 || strcmp(argv[1], "--warning") == 0)) { |
1225 (strcmp(argv[1], "-w") == 0 || strcmp(argv[1], "--warning") == 0)) { |
|
1226 show_todo = 2; |
1251 show_todo = 2; |
1227 argc--, argv++; |
1252 argc--, argv++; |
1228 } |
1253 } |
1229 |
1254 |
1230 if (argc > 1 && ( |
1255 if (argc > 1 && ( |
1233 strcmp(argv[1], "-?") == 0 |
1258 strcmp(argv[1], "-?") == 0 |
1234 )) { |
1259 )) { |
1235 puts( |
1260 puts( |
1236 "strgen - $Revision$\n" |
1261 "strgen - $Revision$\n" |
1237 " -v | --version print version information and exit\n" |
1262 " -v | --version print version information and exit\n" |
1238 " -h | -? | --help print this help message and exit\n" |
|
1239 " -t | --todo replace any untranslated strings with '<TODO>'\n" |
1263 " -t | --todo replace any untranslated strings with '<TODO>'\n" |
1240 " -w | --warning print a warning for any untranslated strings\n" |
1264 " -w | --warning print a warning for any untranslated strings\n" |
1241 " Run without parameters strgen will search for lang/english.txt and\n" |
1265 " -h | -? | --help print this help message and exit\n" |
1242 " parse it. Passing an argument, strgen will translate that language\n" |
1266 " -s | --source_dir search for english.txt in the specified directory\n" |
1243 " file with lang/english.txt as a reference." |
1267 " -d | --dest_dir put output file in the specified directory, create if needed\n" |
|
1268 " Run without parameters and strgen will search for english.txt and parse it,\n" |
|
1269 " creating strings.h. Passing an argument, strgen will translate that language\n" |
|
1270 " file using english.txt as a reference and output <language>.lng." |
1244 ); |
1271 ); |
1245 return 0; |
1272 return 0; |
1246 } |
1273 } |
1247 |
1274 |
|
1275 src_dir = dest_dir = "."; |
|
1276 if (argc > 2 && (strcmp(argv[1], "-s") == 0 || strcmp(argv[1], "--source_dir") == 0)) { |
|
1277 src_dir = dest_dir = argv[2]; // if dest_dir is not specified, it equals src_dir |
|
1278 argc -= 2, argv += 2; |
|
1279 } |
|
1280 |
|
1281 if (argc > 2 && (strcmp(argv[1], "-d") == 0 || strcmp(argv[1], "--dest_dir") == 0)) { |
|
1282 dest_dir = argv[2]; |
|
1283 argc -= 2, argv += 2; |
|
1284 } |
|
1285 |
|
1286 /* strgen has two modes of operation. If no (free) arguments are passed |
|
1287 * strgen generates strings.h to the destination directory. If it is supplied |
|
1288 * with a (free) parameter the program will translate that language to destination |
|
1289 * directory. As input english.txt is parsed from the source directory */ |
1248 if (argc == 1) { |
1290 if (argc == 1) { |
|
1291 mkpath(pathbuf, lengthof(pathbuf), src_dir, "english.txt"); |
|
1292 |
|
1293 /* parse master file */ |
1249 _masterlang = true; |
1294 _masterlang = true; |
1250 // parse master file |
1295 ParseFile(pathbuf, true); |
1251 ParseFile("lang/english.txt", true); |
|
1252 MakeHashOfStrings(); |
1296 MakeHashOfStrings(); |
1253 if (_errors) return 1; |
1297 if (_errors) return 1; |
1254 |
1298 |
1255 // write english.lng and strings.h |
1299 /* write strings.h */ |
1256 |
1300 ottd_mkdir(dest_dir); |
1257 WriteLangfile("lang/english.lng", 0); |
1301 mkpath(pathbuf, lengthof(pathbuf), dest_dir, "strings.h"); |
1258 WriteStringsH("table/strings.h"); |
1302 WriteStringsH(pathbuf); |
1259 } else if (argc == 2) { |
1303 } else if (argc == 2) { |
1260 char buf[256]; |
1304 char *r; |
1261 char* r; |
1305 |
1262 |
1306 mkpath(pathbuf, lengthof(pathbuf), src_dir, "english.txt"); |
|
1307 |
|
1308 /* parse master file and check if target file is correct */ |
1263 _masterlang = false; |
1309 _masterlang = false; |
1264 ParseFile("lang/english.txt", true); |
1310 ParseFile(pathbuf, true); |
1265 MakeHashOfStrings(); |
1311 MakeHashOfStrings(); |
1266 ParseFile(argv[1], false); |
1312 ParseFile(argv[1], false); // target file |
1267 |
|
1268 if (_errors) return 1; |
1313 if (_errors) return 1; |
1269 |
1314 |
1270 strcpy(buf, argv[1]); |
1315 /* get the targetfile, strip any directories and append to destination path */ |
1271 r = strrchr(buf, '.'); |
1316 r = strrchr(argv[1], PATHSEPCHAR); |
1272 if (r == NULL || strcmp(r, ".txt") != 0) r = strchr(buf, 0); |
1317 mkpath(pathbuf, lengthof(pathbuf), dest_dir, (r != NULL) ? &r[1] : argv[1]); |
1273 strcpy(r, ".lng"); |
1318 |
1274 WriteLangfile(buf, show_todo); |
1319 /* rename the .txt (input-extension) to .lng */ |
|
1320 r = strrchr(pathbuf, '.'); |
|
1321 if (r == NULL || strcmp(r, ".txt") != 0) r = strchr(pathbuf, '\0'); |
|
1322 ttd_strlcpy(r, ".lng", (size_t)(r - pathbuf)); |
|
1323 WriteLangfile(pathbuf, show_todo); |
1275 } else { |
1324 } else { |
1276 fprintf(stderr, "invalid arguments\n"); |
1325 fprintf(stderr, "Invalid arguments\n"); |
1277 } |
1326 } |
1278 |
1327 |
1279 return 0; |
1328 return 0; |
1280 } |
1329 } |