107{
109 {
110 std::cerr <<
"Usage: " <<
argv[0] <<
" <txt_in> <nls_out>" << std::endl;
111 return 1;
112 }
113
115 if (!
input.is_open())
116 {
117 std::cerr <<
"Unable to open " <<
argv[1] << std::endl;
118 return 1;
119 }
120
122 memset(&FileHeader, 0,
sizeof(FileHeader));
123
124 std::string curr_line;
125
127 {
128 std::cerr << "ERROR: File is empty" << std::endl;
129 return 1;
130 }
131
134 if (
token !=
"CODEPAGE")
135 error(
"expected CODEPAGE, got \"" +
token +
"\" instead");
136 try
137 {
139 }
140 catch(const std::invalid_argument& ia)
141 {
143 }
144
145 if (!curr_line.empty())
146 error(
"Garbage after CODEPAGE statement: \"" + curr_line +
"\"");
147
148
150 error(
"Nothing after CODEPAGE statement");
151
153 if (
token !=
"CPINFO")
154 error(
"Expected CPINFO, got \"" +
token +
"\" instead");
155 try
156 {
160 }
161 catch(const std::invalid_argument& ia)
162 {
164 return 1;
165 }
166 if (!curr_line.empty())
167 error(
"Garbage after CPINFO statement: \"" + curr_line +
"\"");
169 error(
"Expected 1 or 2 as max char size in CPINFO, got \"" + std::to_string(FileHeader.
MaximumCharacterSize) +
"\" instead");
171 error(
"Default MB character " + std::to_string(FileHeader.
DefaultChar) +
" doesn't fit in a 8-bit value");
172
173
174 bool has_mbtable = false;
176
177 bool has_wctable = false;
180 {
181 for (
int i = 0;
i < 65536;
i++)
183 }
184 else
185 {
187 for (
int i = 0;
i < 65536;
i++)
189 }
190
194
196 bool has_glyphs = false;
197
198
200 {
202
203 if (
token ==
"ENDCODEPAGE")
204 {
205 if (!curr_line.empty())
206 error(
"Garbage after ENDCODEPAGE statement: \"" + curr_line +
"\"");
207 break;
208 }
209 else if (
token ==
"MBTABLE")
210 {
212 try
213 {
215 }
216 catch(const std::invalid_argument& ia)
217 {
219 }
220 if (has_mbtable)
221 error(
"MBTABLE can only be declared once");
223 error(
"MBTABLE size can't be larger than 256");
224 if (!curr_line.empty())
225 error(
"Garbage after MBTABLE statement: \"" + curr_line +
"\"");
226
227 has_mbtable = true;
229 {
231 error(
"Expected " + std::to_string(
table_size + 1) +
" more lines after MBTABLE token");
232
235
236 try
237 {
240 }
241 catch(const std::invalid_argument& ia)
242 {
244 }
245 if (!curr_line.empty())
246 error(
"Garbage after MBTABLE entry: \"" + curr_line +
"\"");
247 mb_table[mb] = wc;
248 }
249 }
250 else if (
token ==
"WCTABLE")
251 {
253 try
254 {
256 }
257 catch(const std::invalid_argument& ia)
258 {
260 }
261 if (has_wctable)
262 error(
"WCTABLE can only be declared once");
263 if (!curr_line.empty())
264 error(
"Garbage after WCTABLE statement: \"" + curr_line +
"\"");
266 error(
"WCTABLE size can't be larger than 65536");
267
268 has_wctable = true;
269
271 {
273 {
275 error(
"Expected " + std::to_string(
table_size + 1) +
" more lines after WCTABLE token");
276
279
280 try
281 {
284 }
285 catch(const std::invalid_argument& ia)
286 {
288 }
289 if (!curr_line.empty())
290 error(
"Garbage after WCTABLE entry: \"" + curr_line +
"\"");
291 wc_table[wc] = mb;
292 }
293 }
294 else
295 {
298 {
300 error(
"Expected " + std::to_string(
table_size + 1) +
" more lines after WCTABLE token");
303
304 try
305 {
308 }
309 catch(const std::invalid_argument& ia)
310 {
312 }
313 if (!curr_line.empty())
314 error(
"Garbage after MBTABLE entry: \"" + curr_line +
"\"");
315 wc_table_dbcs[wc] = mb;
316 }
317 }
318 }
319 else if (
token ==
"DBCSRANGE")
320 {
321 if (dbcs_range_count != 0)
322 error(
"DBCSRANGE can only be declared once");
323
324 try
325 {
326 tokenize(curr_line, dbcs_range_count);
327 }
328 catch(const std::invalid_argument& ia)
329 {
331 }
334 if (!curr_line.empty())
335 error(
"Garbage after DBCSRANGE token");
336
337 std::size_t current_offset = 0;
338
339 uint16_t range_count = dbcs_range_count;
341 while (range_count--)
342 {
344 error(
"Expected new range after DBCSRANGE");
345
347 try
348 {
351 }
352 catch(const std::invalid_argument& ia)
353 {
355 }
356 if (!curr_line.empty())
357 error(
"Garbage after DBCS range declaration");
358
359 if (RangeStart > RangeEnd)
360 error(
"Invalid range specified for DBCSRANGE");
361
362 FileHeader.
LeadByte[current_range*2] = RangeStart;
363 FileHeader.
LeadByte[current_range*2+1] = RangeEnd;
364 current_range++;
365
367
368 for (
uint8_t LeadByte = RangeStart; LeadByte <= RangeEnd; LeadByte++)
369 {
371 error(
"Expected new DBCSTABLE after DBCS range declaration");
372
374 if (
token !=
"DBCSTABLE")
375 error(
"Expected new DBCSTABLE after DBCS range declaration");
376
378 try
379 {
381 }
382 catch(const std::invalid_argument& ia)
383 {
385 }
387 error(
"DBCSTABLE can't have more than 256 entries");
389 {
391 error(
"Expected " + std::to_string(
table_size + 1) +
" more lines after DBCSTABLE token");
392
395
396 try
397 {
400 }
401 catch(const std::invalid_argument& ia)
402 {
404 }
405 if (!curr_line.empty())
406 error(
"Garbage after DBCSTABLE entry: \"" + curr_line +
"\"");
407
409 }
410 current_offset += 256;
411
412 lb_offsets[LeadByte] = current_offset;
413 }
414 }
415 }
416 else if (
token ==
"GLYPHTABLE")
417 {
419 try
420 {
422 }
423 catch(const std::invalid_argument& ia)
424 {
426 }
427 if (has_glyphs)
428 error(
"GLYPHTABLE can only be declared once");
430 error(
"GLYPHTABLE size can't be larger than 256");
431 if (!curr_line.empty())
432 error(
"Garbage after GLYPHTABLE statement: \"" + curr_line +
"\"");
433 has_glyphs = true;
434
436 {
438 error(
"Expected " + std::to_string(
table_size + 1) +
" more lines after GLYPHTABLE token");
439
442
443 try
444 {
447 }
448 catch(const std::invalid_argument& ia)
449 {
451 }
452 if (!curr_line.empty())
453 error(
"Garbage after GLYPHTABLE entry: \"" + curr_line +
"\"");
454 glyph_table[mb] = wc;
455 }
456 }
457 else
458 {
460 }
461 }
462
463 if (
token !=
"ENDCODEPAGE")
464 error(
"Expected last token to be \"ENDCODEPAGE\"");
465
467
468
469 if (!has_mbtable)
470 error(
"File has no MBTABLE statement");
471 if (!has_wctable)
472 error(
"File has no WCTABLE statement");
473
474
475 if (has_glyphs)
476 {
477 for(
int i = 0;
i < 256;
i++)
478 {
479 if (glyph_table[
i] == 0)
480 glyph_table[
i] = mb_table[
i];
481 }
482 }
483
484
486 {
489 }
490 else
491 {
493 {
496 error(
"Default MB char is not translatable!");
498 }
499 else
500 {
502 }
505 }
507
508 std::ofstream output(
argv[2], std::ios_base::binary);
509
510 output.write(reinterpret_cast<char*>(&FileHeader), sizeof(FileHeader));
511
513 + 1
514 + (has_glyphs ? 256 : 0)
515 + 1
516 + (dbcs_range_count ? 256 : 0)
518 + 1;
519
520 output.write(reinterpret_cast<char*>(&wc_table_offset), sizeof(wc_table_offset));
521
522 output.write(reinterpret_cast<char*>(mb_table), sizeof(mb_table));
523
524 uint16_t glyph_table_size = has_glyphs ? 256 : 0;
525 output.write(reinterpret_cast<char*>(&glyph_table_size), sizeof(glyph_table_size));
526 if (has_glyphs)
527 output.write(reinterpret_cast<char*>(glyph_table), sizeof(glyph_table));
528
529 output.write(reinterpret_cast<char*>(&dbcs_range_count), sizeof(dbcs_range_count));
530 if (dbcs_range_count)
531 {
532 output.write(reinterpret_cast<char*>(lb_offsets), sizeof(lb_offsets));
533 }
535 {
537 }
538
540 output.write(reinterpret_cast<char*>(&unknown_flag), sizeof(unknown_flag));
541
543
544 output.close();
545 delete[] wc_table;
546
547 return 0;
548}
unsigned short int uint16_t
GLenum GLenum GLenum input
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
#define MAXIMUM_LEADBYTES
static std::istream & get_clean_line(std::istream &stream, std::string &str)
static void tokenize(std::string &str, std::string &token)