106{
108 {
109 std::cerr <<
"Usage: " <<
argv[0] <<
" <txt_in> <nls_out>" << std::endl;
110 return 1;
111 }
112
114 if (!
input.is_open())
115 {
116 std::cerr <<
"Unable to open " <<
argv[1] << std::endl;
117 return 1;
118 }
119
121 memset(&FileHeader, 0,
sizeof(FileHeader));
122
123 std::string curr_line;
124
126 {
127 std::cerr << "ERROR: File is empty" << std::endl;
128 return 1;
129 }
130
133 if (
token !=
"CODEPAGE")
134 error(
"expected CODEPAGE, got \"" +
token +
"\" instead");
135 try
136 {
138 }
139 catch(const std::invalid_argument& ia)
140 {
142 }
143
144 if (!curr_line.empty())
145 error(
"Garbage after CODEPAGE statement: \"" + curr_line +
"\"");
146
147
149 error(
"Nothing after CODEPAGE statement");
150
152 if (
token !=
"CPINFO")
153 error(
"Expected CPINFO, got \"" +
token +
"\" instead");
154 try
155 {
159 }
160 catch(const std::invalid_argument& ia)
161 {
163 return 1;
164 }
165 if (!curr_line.empty())
166 error(
"Garbage after CPINFO statement: \"" + curr_line +
"\"");
168 error(
"Expected 1 or 2 as max char size in CPINFO, got \"" + std::to_string(FileHeader.
MaximumCharacterSize) +
"\" instead");
170 error(
"Default MB character " + std::to_string(FileHeader.
DefaultChar) +
" doesn't fit in a 8-bit value");
171
172
173 bool has_mbtable = false;
175
176 bool has_wctable = false;
179 {
180 for (
int i = 0;
i < 65536;
i++)
182 }
183 else
184 {
186 for (
int i = 0;
i < 65536;
i++)
188 }
189
193
195 bool has_glyphs = false;
196
197
199 {
201
202 if (
token ==
"ENDCODEPAGE")
203 {
204 if (!curr_line.empty())
205 error(
"Garbage after ENDCODEPAGE statement: \"" + curr_line +
"\"");
206 break;
207 }
208 else if (
token ==
"MBTABLE")
209 {
211 try
212 {
214 }
215 catch(const std::invalid_argument& ia)
216 {
218 }
219 if (has_mbtable)
220 error(
"MBTABLE can only be declared once");
222 error(
"MBTABLE size can't be larger than 256");
223 if (!curr_line.empty())
224 error(
"Garbage after MBTABLE statement: \"" + curr_line +
"\"");
225
226 has_mbtable = true;
228 {
230 error(
"Expected " + std::to_string(
table_size + 1) +
" more lines after MBTABLE token");
231
234
235 try
236 {
239 }
240 catch(const std::invalid_argument& ia)
241 {
243 }
244 if (!curr_line.empty())
245 error(
"Garbage after MBTABLE entry: \"" + curr_line +
"\"");
246 mb_table[mb] = wc;
247 }
248 }
249 else if (
token ==
"WCTABLE")
250 {
252 try
253 {
255 }
256 catch(const std::invalid_argument& ia)
257 {
259 }
260 if (has_wctable)
261 error(
"WCTABLE can only be declared once");
262 if (!curr_line.empty())
263 error(
"Garbage after WCTABLE statement: \"" + curr_line +
"\"");
265 error(
"WCTABLE size can't be larger than 65536");
266
267 has_wctable = true;
268
270 {
272 {
274 error(
"Expected " + std::to_string(
table_size + 1) +
" more lines after WCTABLE token");
275
278
279 try
280 {
283 }
284 catch(const std::invalid_argument& ia)
285 {
287 }
288 if (!curr_line.empty())
289 error(
"Garbage after WCTABLE entry: \"" + curr_line +
"\"");
290 wc_table[wc] = mb;
291 }
292 }
293 else
294 {
297 {
299 error(
"Expected " + std::to_string(
table_size + 1) +
" more lines after WCTABLE token");
302
303 try
304 {
307 }
308 catch(const std::invalid_argument& ia)
309 {
311 }
312 if (!curr_line.empty())
313 error(
"Garbage after MBTABLE entry: \"" + curr_line +
"\"");
314 wc_table_dbcs[wc] = mb;
315 }
316 }
317 }
318 else if (
token ==
"DBCSRANGE")
319 {
320 if (dbcs_range_count != 0)
321 error(
"DBCSRANGE can only be declared once");
322
323 try
324 {
325 tokenize(curr_line, dbcs_range_count);
326 }
327 catch(const std::invalid_argument& ia)
328 {
330 }
333 if (!curr_line.empty())
334 error(
"Garbage after DBCSRANGE token");
335
336 std::size_t current_offset = 0;
337
338 uint16_t range_count = dbcs_range_count;
340 while (range_count--)
341 {
343 error(
"Expected new range after DBCSRANGE");
344
346 try
347 {
350 }
351 catch(const std::invalid_argument& ia)
352 {
354 }
355 if (!curr_line.empty())
356 error(
"Garbage after DBCS range declaration");
357
358 if (RangeStart > RangeEnd)
359 error(
"Invalid range specified for DBCSRANGE");
360
361 FileHeader.
LeadByte[current_range*2] = RangeStart;
362 FileHeader.
LeadByte[current_range*2+1] = RangeEnd;
363 current_range++;
364
366
367 for (
uint8_t LeadByte = RangeStart; LeadByte <= RangeEnd; LeadByte++)
368 {
370 error(
"Expected new DBCSTABLE after DBCS range declaration");
371
373 if (
token !=
"DBCSTABLE")
374 error(
"Expected new DBCSTABLE after DBCS range declaration");
375
377 try
378 {
380 }
381 catch(const std::invalid_argument& ia)
382 {
384 }
386 error(
"DBCSTABLE can't have more than 256 entries");
388 {
390 error(
"Expected " + std::to_string(
table_size + 1) +
" more lines after DBCSTABLE token");
391
394
395 try
396 {
399 }
400 catch(const std::invalid_argument& ia)
401 {
403 }
404 if (!curr_line.empty())
405 error(
"Garbage after DBCSTABLE entry: \"" + curr_line +
"\"");
406
408 }
409 current_offset += 256;
410
411 lb_offsets[LeadByte] = current_offset;
412 }
413 }
414 }
415 else if (
token ==
"GLYPHTABLE")
416 {
418 try
419 {
421 }
422 catch(const std::invalid_argument& ia)
423 {
425 }
426 if (has_glyphs)
427 error(
"GLYPHTABLE can only be declared once");
429 error(
"GLYPHTABLE size can't be larger than 256");
430 if (!curr_line.empty())
431 error(
"Garbage after GLYPHTABLE statement: \"" + curr_line +
"\"");
432 has_glyphs = true;
433
435 {
437 error(
"Expected " + std::to_string(
table_size + 1) +
" more lines after GLYPHTABLE token");
438
441
442 try
443 {
446 }
447 catch(const std::invalid_argument& ia)
448 {
450 }
451 if (!curr_line.empty())
452 error(
"Garbage after GLYPHTABLE entry: \"" + curr_line +
"\"");
453 glyph_table[mb] = wc;
454 }
455 }
456 else
457 {
459 }
460 }
461
462 if (
token !=
"ENDCODEPAGE")
463 error(
"Expected last token to be \"ENDCODEPAGE\"");
464
466
467
468 if (!has_mbtable)
469 error(
"File has no MBTABLE statement");
470 if (!has_wctable)
471 error(
"File has no WCTABLE statement");
472
473
474 if (has_glyphs)
475 {
476 for(
int i = 0;
i < 256;
i++)
477 {
478 if (glyph_table[
i] == 0)
479 glyph_table[
i] = mb_table[
i];
480 }
481 }
482
483
485 {
488 }
489 else
490 {
492 {
495 error(
"Default MB char is not translatable!");
497 }
498 else
499 {
501 }
504 }
506
507 std::ofstream output(
argv[2], std::ios_base::binary);
508
509 output.write(reinterpret_cast<char*>(&FileHeader), sizeof(FileHeader));
510
512 + 1
513 + (has_glyphs ? 256 : 0)
514 + 1
515 + (dbcs_range_count ? 256 : 0)
517 + 1;
518
519 output.write(reinterpret_cast<char*>(&wc_table_offset), sizeof(wc_table_offset));
520
521 output.write(reinterpret_cast<char*>(mb_table), sizeof(mb_table));
522
523 uint16_t glyph_table_size = has_glyphs ? 256 : 0;
524 output.write(reinterpret_cast<char*>(&glyph_table_size), sizeof(glyph_table_size));
525 if (has_glyphs)
526 output.write(reinterpret_cast<char*>(glyph_table), sizeof(glyph_table));
527
528 output.write(reinterpret_cast<char*>(&dbcs_range_count), sizeof(dbcs_range_count));
529 if (dbcs_range_count)
530 {
531 output.write(reinterpret_cast<char*>(lb_offsets), sizeof(lb_offsets));
532 }
534 {
536 }
537
539 output.write(reinterpret_cast<char*>(&unknown_flag), sizeof(unknown_flag));
540
542
543 output.close();
544 delete[] wc_table;
545
546 return 0;
547}
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)