1 /**
2 * Yudit Unicode Editor Source File
3 *
4 * GNU Copyright (C) 1997-2006 Gaspar Sinai <gaspar@yudit.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2,
8 * dated June 1991. See file COPYYING for details.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20
21 #include "stoolkit/SBMap.h"
22 #include "stoolkit/STypes.h"
23 #include "stoolkit/SUtil.h"
24 #include "ProcessFile.h"
25
26 #include <string.h>
27 #include <stdlib.h>
28
29 #include <time.h>
30
31 /* They'll stone me for this */
32 #include <stdio.h>
33
34 #ifdef USE_WINAPI
35 #include <windows.h>
36 #else
37 #include <unistd.h>
38 #endif
39
40 unsigned int hexVle (char in);
41 char hexStr (SS_WORD64, int nibble);
42 int encode(void* buffer, char* input, int bytesize);
43
44 void decode(char* buffer, void* input, int bytesize, int len);
45 int doBenchMark(SBMap* map, int index);
46
47 #define ISHEX(a) ((a>='A' && a<='F') || (a>='a' && a<='f') || (a>='0' && a<='9'))
48
49 #define MAX_INPUT_FILES 256
50 typedef enum {KMAP, RKMAP, UNI, RUNI, MYS, RMYS } MapType;
51
52 typedef struct
53 {
54 MapType type;
55 int from;
56 int to;
57 const char* name;
58 SBMapItemVector* item;
59 } InputFiles;
60
61 char shortComment[MAX_COMMENT_SIZE];
62
63 InputFiles inputFiles[MAX_INPUT_FILES];
64 int inputFileCount=0;
65 char inputName[32];
66 int inputType = -1;
67
68 char nameb[1024];
69 char commentb[1024];
70 char in[1024];
71 char enc[1024];
72
73 int strip=0;
74 int info=0;
75 int test=0;
76 int stateEnc = 0;
77 int stateDec = 0;
78 int mapType = -1;
79 char* mapName = 0;
80 char* mapComment = 0;
81 char* file=0;
82 char* mapFile=0;
83 int showKeys=0;
84 int benchmark=0;
85 int circle=-1;
86 int highLow=0;
87 int keySize=1;
88 int nocomment=0;
89
90 SFileFormat outformat=SS_BINARY;
91
92 static void usage();
93 static void print_version ();
94
95 #define BUFFER_SIZE 512
96 char readBuffer[BUFFER_SIZE];
97
98 /**
99 * @author Gaspar Sinai <gsinai@iname.com> 1999-12-18
100 * @version 1.0
101 * This is a program to create, convert and test character maps.
102 */
103 int
main(int argc,char * argv[])104 main (int argc, char* argv[])
105 {
106 int i, j;
107
108 if (argc < 2)
109 {
110 usage();
111 exit (1);
112 }
113
114 if (argc==3 && strcmp ("-installdir", argv[1])==0)
115 {
116 SString pref(argv[2]);
117 SDir d (pref);
118 bool ret = false;
119 if (d.exists() && d.readable())
120 {
121 ret = setPrefix (pref);
122 }
123 else
124 {
125 fprintf (stderr, "Can not read directory [%*.*s]\n", SSARGS(pref));
126 }
127 return (ret);
128 }
129
130 /**
131 * This option puts everything in a tmp file and
132 * calls the program with agruents specified after cmd,
133 * with the filename as the last argument.
134 * when porgram exists remove the tmp file.
135 */
136 if (argc>=3 && strcmp ("-pipecmd", argv[1])==0)
137 {
138 FILE* input=stdin;
139 SString tmpfile = getTemporaryFileName ();
140 if (tmpfile.size()==0)
141 {
142 fprintf (stderr, "Can not create tmp file.\n");
143 return (1);
144 }
145 tmpfile.append ((char)0);
146 FILE* output=stdout;
147 #ifdef USE_WINAPI
148 if ((output = fopen (tmpfile.array(), "wb")) == 0)
149 #else
150 if ((output = fopen (tmpfile.array(), "w")) == 0)
151 #endif
152 {
153 fprintf (stderr, "mytool: can not open '%s' to write.\n",
154 tmpfile.array());
155 return 1;
156 }
157 int len;
158 while (!feof(input) && (len=fread(readBuffer, 1, BUFFER_SIZE, input))>0)
159 {
160 int wlen = fwrite(readBuffer, 1, len, output);
161 if (wlen!= len)
162 {
163 fprintf (stderr, "mytool: failed to write %*.*s.\n", SSARGS(tmpfile));
164 return 1;
165 }
166 }
167 fclose (output);
168 /* call argv[2]...argc - with this file */
169 SStringVector vargs;
170 /* on linux it is foreground by default */
171 for (int i=2; i<argc; i++)
172 {
173 SString arg (argv[i]);
174 arg.insert (0, "\"");
175 arg.append ("\"");
176 vargs.append (arg);
177 }
178
179 SString farg (tmpfile.array());
180 farg.insert (0, "\"");
181 farg.append ("\"");
182 vargs.append (farg);
183
184 SPipe pipe (vargs.join (" "));
185 {
186 /* we have to use input stream if we want to wait. Hack in SIO.cpp */
187 SInputStream is = pipe.getInputStream();
188 is.close();
189 }
190
191 /* wait till it exits */
192 int ret = pipe.wait();
193 /* remove tmp file after it openend it */
194 #ifdef USE_WINAPI
195 Sleep(10 * 1000);
196 #else
197 sleep (10);
198 #endif
199 unlink (tmpfile.array());
200 return ret;
201 }
202
203 SBMap map;
204
205 for (i=1; i<argc; i++)
206 {
207 if (inputFileCount >= MAX_INPUT_FILES)
208 {
209 fprintf (stderr, "mytool: maximum % input files can be specified.\n",
210 MAX_INPUT_FILES);
211 exit (1);
212 }
213 if (strcmp (argv[i],"-info")==0)
214 {
215 info=1;
216 continue;
217 }
218 if (strcmp (argv[i],"-test")==0)
219 {
220 test=1;
221 continue;
222 }
223 if (strcmp (argv[i],"-benchmark")==0)
224 {
225 benchmark=1;
226 continue;
227 }
228 if (strcmp (argv[i],"-strip")==0)
229 {
230 strip=1;
231 continue;
232 }
233 if (strcmp (argv[i],"-version")==0)
234 {
235 print_version ();
236 exit (0);
237 }
238 if (strcmp (argv[i],"-encode")==0)
239 {
240 stateEnc=1;
241 continue;
242 }
243 if (strcmp (argv[i],"-decode")==0)
244 {
245 stateDec=1;
246 continue;
247 }
248 if (strcmp (argv[i],"-high")==0)
249 {
250 highLow=1;
251 continue;
252 }
253 if (strcmp (argv[i],"-8")==0)
254 {
255 keySize=0;
256 continue;
257 }
258 if (strcmp (argv[i],"-low")==0)
259 {
260 highLow=-1;
261 continue;
262 }
263 if (strcmp (argv[i],"-showkeys")==0)
264 {
265 showKeys=1;
266 continue;
267 }
268 if (strcmp (argv[i],"-nocomment")==0)
269 {
270 nocomment=1;
271 continue;
272 }
273 if (i < argc-1 && strcmp (argv[i],"-kmap")==0)
274 {
275 inputFiles [inputFileCount].name = argv[++i];
276 inputFiles [inputFileCount].type = KMAP;
277 inputFileCount++;
278 continue;
279 }
280 if (i < argc-1 && strcmp (argv[i],"-rkmap")==0)
281 {
282 inputFiles [inputFileCount].name = argv[++i];
283 inputFiles [inputFileCount].type = RKMAP;
284 inputFileCount++;
285 continue;
286 }
287 if (i < argc-1 && strcmp (argv[i],"-mys")==0)
288 {
289 inputFiles [inputFileCount].name = argv[++i];
290 inputFiles [inputFileCount].type = MYS;
291 inputFileCount++;
292 continue;
293 }
294 if (i < argc-1 && strcmp (argv[i],"-rmys")==0)
295 {
296 inputFiles [inputFileCount].name = argv[++i];
297 inputFiles [inputFileCount].type = RMYS;
298 inputFileCount++;
299 continue;
300 }
301 if (i < argc-1 && sscanf (argv[i],"-uni:%d,%d",
302 &inputFiles[inputFileCount].from,
303 &inputFiles[inputFileCount].to)==2)
304 {
305 inputFiles [inputFileCount].name = argv[++i];
306 inputFiles [inputFileCount].type = UNI;
307 inputFileCount++;
308 continue;
309 }
310 if (i < argc-1 && sscanf (argv[i],"-runi:%d,%d",
311 &inputFiles[inputFileCount].from,
312 &inputFiles[inputFileCount].to)==2)
313 {
314 inputFiles [inputFileCount].name = argv[++i];
315 inputFiles [inputFileCount].type = RUNI;
316 inputFileCount++;
317 continue;
318 }
319
320 if (i < argc-1 && strcmp (argv[i],"-write")==0)
321 {
322 if (file != 0)
323 {
324 fprintf (stderr, "mytool: only one '-write' option can be specified.\n");
325 exit (1);
326 }
327 file = argv[++i];
328 continue;
329 }
330 if (i < argc-1 && strcmp (argv[i],"-type")==0)
331 {
332 i++;
333 if (strcmp (argv[i], "kmap")==0)
334 {
335 mapType = 1;
336 }
337 else if (strcmp (argv[i], "clkmap")==0)
338 {
339 mapType = 4;
340 }
341 else if (strcmp (argv[i], "fontmap")==0)
342 {
343 mapType = 2;
344 }
345 else
346 {
347 fprintf (stderr, "mytool: unknown maptype '%s'\n", argv[i]);
348 exit (1);
349 }
350
351 continue;
352 }
353 if (i < argc-1 && strcmp (argv[i],"-name")==0)
354 {
355 mapName = argv[++i];
356 continue;
357 }
358 if (i < argc-1 && strcmp (argv[i],"-comment")==0)
359 {
360 mapComment = argv[++i];
361 continue;
362 }
363 if (i < argc-1 && strcmp (argv[i],"-my")==0)
364 {
365 if (mapFile != 0)
366 {
367 fprintf (stderr, "mytool: only one '-my' option can be specified.\n");
368 exit (1);
369 }
370 mapFile = argv[++i];
371 continue;
372 }
373 if (i < argc-1 && strcmp (argv[i],"-convert")==0)
374 {
375 i++;
376 if (strcmp (argv[i],"my")==0)
377 {
378 outformat = SS_BINARY;
379 }
380 else if (strcmp (argv[i],"mys")==0)
381 {
382 outformat = SS_TEXT_MAP;
383 }
384 else if (strcmp (argv[i],"myc")==0)
385 {
386 outformat = SS_CTEXT;
387 }
388 else if (strcmp (argv[i],"bumap")==0)
389 {
390 outformat = SS_BUMAP;
391 }
392 else if (strcmp (argv[i],"cumap")==0)
393 {
394 outformat = SS_CUMAP;
395 }
396 else
397 {
398 usage ();
399 return (1);
400 }
401 continue;
402 }
403 usage ();
404 exit (1);
405 }
406
407 if (mapFile!=0)
408 {
409 SFile f(mapFile);
410 map.setFileImage (f.getFileImage());
411 if (f.size() < 0 || !map.getStatus())
412 {
413 if (mapFile==0)
414 {
415 usage ();
416 return (1);
417 }
418 fprintf (stderr, "mytool: can not find valid '%s' map file\n", mapFile);
419 return (1);
420 }
421 if (strip)
422 {
423 map.strip ();
424 }
425 }
426
427 // Process input files
428 for (i=0; i<inputFileCount; i++)
429 {
430 inputFiles[i].item = 0;
431 }
432 shortComment[0] = 0;
433 inputName[0] = 0;
434 inputType = -1;
435
436
437 for (i=0; i<inputFileCount; i++)
438 {
439 SFile in(inputFiles[i].name);
440 if (in.size() < 0)
441 {
442 do {
443 if (inputFiles[i].item!=0)
444 {
445 for (j=0; j<inputFiles[i].item->count; j++)
446 {
447 delete inputFiles[i].item->maps[j];
448 }
449 delete inputFiles[i].item;
450 inputFiles[i].item = 0;
451 }
452 } while (i-->0);
453 fprintf (stderr, "mytool: can not read '%s'.\n", inputFiles[i].name);
454 return (1);
455 }
456 SInputStream is = in.getInputStream();
457 switch (inputFiles[i].type)
458 {
459 case KMAP:
460 inputFiles[i].item = processKMap (inputFiles[i].name, is, nocomment, 0, shortComment, inputName, &inputType);
461 break;
462 case RKMAP:
463 inputFiles[i].item = processKMap (inputFiles[i].name, is, nocomment, 1, shortComment, inputName, &inputType);
464 break;
465 case MYS:
466 inputFiles[i].item = processMYS (inputFiles[i].name, is, nocomment, 0, shortComment, inputName, &inputType);
467 break;
468 case RMYS:
469 inputFiles[i].item = processMYS (inputFiles[i].name, is, nocomment, 1, shortComment, inputName, &inputType);
470 break;
471 case UNI:
472 inputFiles[i].item = processUNI (inputFiles[i].name, is, nocomment, keySize, highLow, inputFiles[i].from, inputFiles[i].to, 0, shortComment, inputName, &inputType);
473 break;
474 case RUNI:
475 inputFiles[i].item = processUNI (inputFiles[i].name, is, nocomment, keySize, highLow, inputFiles[i].from, inputFiles[i].to, 1, shortComment, inputName, &inputType);
476 break;
477 default:
478 fprintf (stderr, "mytool: internal error: %d \n", inputFiles[i].type);
479 break;
480 }
481
482 if (inputFiles[i].item==0)
483 {
484 fprintf (stderr, "mytool: bad source file '%s'.\n", inputFiles[i].name);
485 do {
486 if (inputFiles[i].item!=0)
487 {
488 delete inputFiles[i].item;
489 inputFiles[i].item = 0;
490 }
491 } while (i-->0);
492 return (1);
493 }
494 }
495 if (mapComment != 0)
496 {
497 map.setComment ((const unsigned char*) mapComment, strlen (mapComment));
498 }
499 else if (shortComment[0] != 0)
500 {
501 map.setComment ((const unsigned char*) shortComment, strlen (shortComment));
502 }
503 else if (inputFileCount)
504 {
505 time_t tim;
506 char *source_date_epoch = getenv ("SOURCE_DATE_EPOCH");
507 if (source_date_epoch == NULL || (tim = (time_t)strtol (source_date_epoch, NULL, 10)) <= 0)
508 tim = time(0);
509 struct tm* ts = localtime (&tim);
510 sprintf (shortComment, "created by mytool %04d-%02d-%02d",
511 ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday);
512 map.setComment ((const unsigned char*) shortComment,
513 strlen (shortComment));
514 }
515
516 if (mapType > 0)
517 {
518 map.setType (mapType);
519 }
520 else if (inputType > 0)
521 {
522 map.setType (inputType);
523 }
524
525 if (mapName != 0)
526 {
527 map.setName ((const unsigned char*) mapName);
528 }
529 else if (inputName[0] != 0)
530 {
531 map.setName ((const unsigned char*) inputName);
532 }
533
534 for (i=0; i<inputFileCount; i++)
535 {
536 // ownership is passed to map
537 for (j=0; j<inputFiles[i].item->count; j++)
538 {
539 map.add (inputFiles[i].item->maps[j]);
540 inputFiles[i].item->maps[j] = 0;
541 }
542 delete inputFiles[i].item;
543 inputFiles[i].item = 0;
544 }
545
546 // Build encoding state machine.
547 if (stateEnc)
548 {
549 for (i=0; i<map.getSize(); i++)
550 {
551 if (map.getType(i)==SBMap::SBMap_DECODE) continue;
552 map.buildStateMachine (i);
553 }
554 }
555
556 if (stateDec)
557 {
558 for (i=0; i<map.getSize(); i++)
559 {
560 if (map.getType(i)==SBMap::SBMap_ENCODE) continue;
561 map.buildStateMachine (i);
562 }
563 }
564 if (info)
565 {
566 const char* type = 0;
567 if (map.mapType==1) type="kmap";
568 if (map.mapType==4) type="clkmap";
569 if (map.mapType==2) type="fontmap";
570 if (type==0)
571 {
572 fprintf (stdout, "type...: undefined (%d)\n", map.mapType);
573 }
574 else
575 {
576 fprintf (stdout, "type...: %s\n", type);
577 }
578 fprintf (stdout, "size...: %d\n", map.getSize());
579 map.getName (nameb, 1024);
580 fprintf (stdout, "name...: [%s]\n", nameb);
581 map.getComment (commentb, 1024);
582 fprintf (stdout, "comment: [%s]\n", commentb);
583 int integ;
584 for (i=0; i<map.getSize(); i++)
585 {
586 SBMapItem* mp = map.getItem(i);
587 fprintf (stdout, "info:----------------: map[%d]\n", i);
588 map.getName (nameb, 1024, i);
589 fprintf (stdout, "%d.name...............: [%s]\n", i, nameb);
590 map.getComment (commentb, 1024, i);
591 fprintf (stdout, "%d.comment............: [%s]\n", i, commentb);
592 type = "unknown";
593 if (mp->itemType == SBMapItem::SBMapNToN)
594 type = "my";
595 if (mp->itemType == SBMapItem::SBMapBumap)
596 type = "bumap";
597
598 fprintf (stdout, "%d.itemType...........: %s\n", i, type);
599 fprintf (stdout, "%d.size...............: %d matches \n",
600 i, map.getSize(i));
601 type="unknown";
602 if (map.getType(i)==SBMap::SBMap_DECODE) type="decode";
603 if (map.getType(i)==SBMap::SBMap_ENCODE) type="encode";
604 fprintf (stdout, "%d.type...............: %s\n",i, type);
605
606 type = (map.getStateMachine(i) ==0) ? "no" : "yes";
607 fprintf (stdout, "%d.state machine based: %s\n",i, type);
608 integ = 8 << map.getInWordSize(i);
609 fprintf (stdout, "%d.input..............: %d bits\n", i, integ);
610 integ = 8 << map.getOutWordSize(i);
611 fprintf (stdout, "%d.output.............: %d bits\n", i, integ);
612 if (showKeys)
613 {
614 char buf[256];
615 int k;
616 const unsigned char* tmp;
617 unsigned int len;
618 unsigned int matched;
619 for (k=0; k<map.getSize(i); k++)
620 {
621 tmp = mp->getKey (k, &len, &matched);
622 memcpy (buf, tmp, len);
623 buf[len] = 0;
624 fprintf (stdout, "%d.keys............: [%d] |%s|\n" ,i, k, buf);
625 }
626 }
627 if (benchmark)
628 {
629 fprintf (stdout, "%d.benchmark.speed......: %d\n", i, doBenchMark (&map, i));
630 }
631
632 }
633 if (benchmark)
634 {
635 fprintf (stdout, "encode.benchmark.speed.: %d\n",
636 doBenchMark (&map, -1-(int)SBMap::SBMap_ENCODE));
637 fprintf (stdout, "decode.benchmark.speed.: %d\n",
638 doBenchMark (&map, -1-(int)SBMap::SBMap_DECODE));
639 }
640 }
641 else if (benchmark)
642 {
643 for (i=0; i<map.getSize(); i++)
644 {
645 fprintf(stdout, "%d.benchmark.speed......: %d\n", i,
646 doBenchMark (&map, i));
647 }
648 if (benchmark)
649 {
650 fprintf (stderr, "encode.benchmark.speed.: %d\n",
651 doBenchMark (&map, -1-(int)SBMap::SBMap_ENCODE));
652 fprintf(stderr, "decode.benchmark.speed.: %d\n",
653 doBenchMark (&map, -1-(int)SBMap::SBMap_DECODE));
654 }
655 }
656
657
658 if (test)
659 {
660 char ce[256];
661
662 fprintf (stdout, "Enter map-index-or-d-or-e in-bytesize out-bytesize: ");
663 fflush (stdout);;
664
665 int index, in_bytesize, out_bytesize;
666 int len, in_bytesize_orig, out_bytesize_orig;
667 ce[255] = 0;
668 if (fscanf (stdin, "%255s", ce) == 0) {
669 fprintf (stderr, "Can not parse line.\n");
670 return (1);
671 }
672 index = 0;
673 if (ce[0] == 'd')
674 {
675 circle = (int) SBMap::SBMap_DECODE;
676 for (i=0; i<map.getSize(); i++)
677 {
678 if (map.getType(i)==circle)
679 {
680 index = i;
681 break;
682 }
683 }
684 }
685 else if (ce[0] == 'e')
686 {
687 circle = (int) SBMap::SBMap_ENCODE;
688 index = 0;
689 for (i=0; i<map.getSize(); i++)
690 {
691 if (map.getType(i)==circle)
692 {
693 index = i;
694 break;
695 }
696 }
697 }
698 else
699 {
700 index = atoi(ce);
701 }
702 if (fscanf (stdin, "%d", &in_bytesize_orig) == 0) {
703 fprintf (stderr, "Can not parse line.\n");
704 return (1);
705 }
706 if (fscanf (stdin, "%d", &out_bytesize_orig) == 0) {
707 fprintf (stderr, "Can not parse line.\n");
708 return (1);
709 }
710
711 switch (in_bytesize_orig)
712 {
713 case 1: in_bytesize=0; break;
714 case 8: in_bytesize=0; break;
715 case 16: in_bytesize=1; break;
716 case 32: in_bytesize=2; break;
717 case 64: in_bytesize=3; break;
718 default:
719 fprintf (stderr, "Bad argument for in_bytesize. Should be {1|8|16|32|64}\n");
720 return (1);
721 }
722 switch (out_bytesize_orig)
723 {
724 case 1: out_bytesize=0; break;
725 case 8: out_bytesize=0; break;
726 case 16: out_bytesize=1; break;
727 case 32: out_bytesize=2; break;
728 case 64: out_bytesize=3; break;
729 default:
730 fprintf (stderr, "Bad argument for out_bytesize. Should be {1|8|16|32|64}\n");
731 return (1);
732 }
733 if (index < 0 || index >= map.getSize())
734 {
735 fprintf (stderr, "Bad argument for index. Should be [0..%d]\n", (int) map.getSize()-1);
736 return (1);
737 }
738
739 SStateModel model (in_bytesize, map.getInWordSize (index),
740 map.getOutWordSize (index), out_bytesize);
741 while (!feof(stdin))
742 {
743 if (in_bytesize_orig==1)
744 {
745 fprintf (stdout, "Enter bytestring: ");
746 }
747 else
748 {
749 fprintf (stdout, "Enter hex bytestring nibbles: ");
750 }
751 fflush (stdout);
752 in[1023] = 0;
753 if (fscanf (stdin, "%1023s", in) == 0) {
754 fprintf (stdout, "Can not parse line");
755 return (1);
756 }
757 if (in_bytesize_orig==1)
758 {
759 len = strlen (in);
760 memcpy (enc, in, len);
761 }
762 else
763 {
764 len = encode (enc, in, in_bytesize);
765 }
766 if (circle>=0)
767 {
768 fprintf (stderr, "circle..\n");
769 len = map.circle ((SBMap::SBMapType)circle, enc, len, &model, 1);
770 }
771 else
772 {
773 len = map.encode (index, enc, len, &model, 1);
774 }
775 switch (len)
776 {
777 case SS_REJECT:
778 model.reset();
779 fprintf(stdout, "reposnse: REJECT\n");
780 break;
781 case SS_ACCEPT:
782 fprintf(stdout, "reposnse: ACCEPT\n");
783 break;
784 default:
785 fprintf (stdout, "result: MATCH length %d -> %d:",
786 len, model.out.length);
787 switch (out_bytesize)
788 {
789 case 0:
790 memcpy (enc, model.out.u.u8, model.out.length);
791 break;
792 case 1:
793 memcpy (enc, model.out.u.u16, model.out.length*2);
794 break;
795 case 2:
796 memcpy (enc, model.out.u.u32, model.out.length*4);
797 break;
798 case 3:
799 memcpy (enc, model.out.u.u64, model.out.length*64);
800 break;
801 default:
802 // Debug it..
803 return (1);
804 }
805 if (out_bytesize_orig==1)
806 {
807 memcpy (in, enc, model.out.length);
808 in[model.out.length] = 0;
809 }
810 else
811 {
812 decode (in, enc, out_bytesize, model.out.length);
813 }
814 fprintf (stdout, "'%s'\n", in);
815 model.reset();
816 }
817 }
818 }
819
820 if (file != 0)
821 {
822 SFile f(file);
823 SOutputStream os = f.getOutputStream();
824 if (!os.isOK())
825 {
826 fprintf (stderr, "mytool: can not open file: '%s'\n",file);
827 return (1);
828 }
829 int size = map.serialize (os, outformat);
830 if (size <= 0)
831 {
832 fprintf (stderr, "mytool: can serialize map into file: '%s'\n", file);
833 return (1);
834 }
835 }
836
837 return (0);
838 }
839
840 int
encode(void * buffer,char * input,int bytesize)841 encode(void* buffer, char* input, int bytesize)
842 {
843 SS_WORD8 o8[1024];
844 SS_WORD16 o16[1024];
845 SS_WORD32 o32[1024];
846 SS_WORD64 o64[1024];
847 int i, index;
848 SS_WORD64 result;
849
850 index = 0; i=0; result=0;
851 switch (bytesize)
852 {
853 case 0:
854 for (i=0; input[i]!=0; i++)
855 {
856 if (!ISHEX(input[i])) continue;
857 result = (result << 4) + hexVle(input[i]);
858 index++;
859 if ((index%2)==0)
860 {
861 o8[index/2-1] = (SS_WORD8) result;
862 result = 0;
863 }
864 }
865 memcpy (buffer, o8, index/2);
866 return index/2;
867 case 1:
868 for (i=0; input[i]!=0; i++)
869 {
870 if (!ISHEX(input[i])) continue;
871 result = (result << 4) + hexVle(input[i]);
872 index++;
873 if ((index%4)==0)
874 {
875 o16[index/4-1] = (SS_WORD16) result;
876 result = 0;
877 }
878 }
879 memcpy (buffer, o16, index/2);
880 return index/4;
881 case 2:
882 for (i=0; input[i]!=0; i++)
883 {
884 if (!ISHEX(input[i])) continue;
885 result = (result << 4) + hexVle(input[i]);
886 index++;
887 if ((index%8)==0)
888 {
889 o32[index/8-1] = (SS_WORD32) result;
890 result = 0;
891 }
892 }
893 memcpy (buffer, o32, index/2);
894 return index/8;
895 case 3:
896 for (i=0; input[i]!=0; i++)
897 {
898 if (!ISHEX(input[i])) continue;
899 result = (result << 4) + hexVle(input[i]);
900 index++;
901 if ((index%16)==0)
902 {
903 o64[index/16-1] = (SS_WORD32) result;
904 result = 0;
905 }
906 }
907 memcpy (buffer, o64, index/2);
908 return index/16;
909 default:
910 break;
911 }
912 return 0;
913 }
914
915 void
decode(char * buffer,void * input,int bytesize,int len)916 decode(char* buffer, void* input, int bytesize, int len)
917 {
918 int i;
919 int index;
920 SS_WORD64 word;
921 unsigned char* in = (unsigned char*) input;
922 switch (bytesize)
923 {
924 case 0:
925 index=0;
926 for (i=0; i<len; i++)
927 {
928 word = (SS_WORD64) (((SS_WORD8*)in)[i]);
929 buffer[index++] = hexStr(word, 1);
930 buffer[index++] = hexStr(word, 0);
931 buffer[index++] = ' ';
932 }
933 buffer[index++] = 0;
934 break;
935 case 1:
936 index=0;
937 for (i=0; i<len; i++)
938 {
939 word = (SS_WORD64) (((SS_WORD16*)in)[i]);
940 buffer[index++] = hexStr(word, 3);
941 buffer[index++] = hexStr(word, 2);
942 buffer[index++] = hexStr(word, 1);
943 buffer[index++] = hexStr(word, 0);
944 buffer[index++] = ' ';
945 }
946 buffer[index++] = 0;
947 break;
948 case 2:
949 index=0;
950 for (i=0; i<len; i++)
951 {
952 word = (SS_WORD64) (((SS_WORD32*)in)[i]);
953 buffer[index++] = hexStr(word, 7);
954 buffer[index++] = hexStr(word, 6);
955 buffer[index++] = hexStr(word, 5);
956 buffer[index++] = hexStr(word, 4);
957 buffer[index++] = hexStr(word, 3);
958 buffer[index++] = hexStr(word, 2);
959 buffer[index++] = hexStr(word, 1);
960 buffer[index++] = hexStr(word, 0);
961 buffer[index++] = ' ';
962 }
963 buffer[index++] = 0;
964 break;
965 case 3:
966 index=0;
967 for (i=0; i<len; i++)
968 {
969 word = (SS_WORD64) (((SS_WORD64*)in)[i]);
970 buffer[index++] = hexStr(word, 15);
971 buffer[index++] = hexStr(word, 14);
972 buffer[index++] = hexStr(word, 13);
973 buffer[index++] = hexStr(word, 12);
974 buffer[index++] = hexStr(word, 11);
975 buffer[index++] = hexStr(word, 10);
976 buffer[index++] = hexStr(word, 9);
977 buffer[index++] = hexStr(word, 8);
978 buffer[index++] = hexStr(word, 7);
979 buffer[index++] = hexStr(word, 6);
980 buffer[index++] = hexStr(word, 5);
981 buffer[index++] = hexStr(word, 4);
982 buffer[index++] = hexStr(word, 3);
983 buffer[index++] = hexStr(word, 2);
984 buffer[index++] = hexStr(word, 1);
985 buffer[index++] = hexStr(word, 0);
986 buffer[index++] = ' ';
987 }
988 buffer[index++] = 0;
989 break;
990 default:
991 buffer[0] = 0;
992 break;
993 }
994 }
995
996 unsigned int
hexVle(char in)997 hexVle (char in)
998 {
999 if (in>='0' && in<='9') return in-'0';
1000 if (in>='a' && in<='z') return in-'a'+10;
1001 if (in>='A' && in<='Z') return in-'A'+10;
1002 return 256;
1003 }
1004 char
hexStr(SS_WORD64 in,int nibble)1005 hexStr (SS_WORD64 in, int nibble)
1006 {
1007 SS_WORD64 newIn;
1008 newIn = (in>>(4*nibble))&0x0f;
1009 if (newIn < 10) return (char) (newIn + '0');
1010 return (char) (newIn + 'A' - 10);
1011 }
1012
1013 int
doBenchMark(SBMap * map,int index)1014 doBenchMark(SBMap* map, int index)
1015 {
1016 SS_WORD16 in;
1017 SS_WORD16 input[256];
1018 int ind;
1019
1020 int count = 0;
1021 time_t t0, t1;
1022 int len;
1023 t0 = time(0);
1024 ind=0;
1025 in = 0;
1026 int i;
1027
1028 int which=index;
1029
1030 if (which < 0)
1031 {
1032 for (i=0; i<map->getSize(); i++)
1033 {
1034 if (map->getType(i) == (SBMap::SBMapType)(-index-1))
1035 {
1036 which = i;
1037 break;
1038 }
1039 }
1040 }
1041 if (which < 0)
1042 {
1043 return 0;
1044 }
1045 SStateModel model (1, map->getInWordSize (which),
1046 map->getOutWordSize (which), 1);
1047 while (1)
1048 {
1049 input[ind]++;
1050 if (input[ind]==0 && ind>0)
1051 {
1052 ind--;
1053 }
1054 model.reset();
1055 if (index<0)
1056 {
1057 len = map->circle ((SBMap::SBMapType)(-index-1), input, ind+1, &model, 1);
1058 }
1059 else
1060 {
1061 len = map->encode (index, input, ind+1, &model, 1);
1062 }
1063 switch (len)
1064 {
1065 case SS_REJECT:
1066 break;
1067
1068 case 0:
1069 if (index<0) fprintf (stderr, "Match 0.\n");
1070 default:
1071 if (ind<255)
1072 {
1073 ind++;
1074 input[ind] = 0;
1075 }
1076 break;
1077 }
1078 in++;
1079 if ((in&0x0f)==0)
1080 {
1081 count++;
1082 t1 = time(0);
1083 if (t1-t0 > 5 || t0-t1 > 5)
1084 {
1085 break;
1086 }
1087 }
1088 }
1089 return count;
1090 }
1091
1092 static void
print_version()1093 print_version ()
1094 {
1095 fprintf (stderr, "mytool version %s GNU (C) Gaspar Sinai\n", SD_YUDIT_VERSION);
1096 }
1097
1098 static void
usage()1099 usage ()
1100 {
1101 fprintf (stderr, "usage: mytool [-convert {myc|mys|my|bumap|cumap} [-info [-showkeys]] [-test] [-encode] [-decode]");
1102 fprintf (stderr, " [-write new-map] [-name map-name] [-nocomment] [-comment comment] [-type map-type]");
1103 fprintf (stderr, " [-my binary-mapfile] [-benchmark] [-high|-low]");
1104 fprintf (stderr, " [-uni:1,2 plainfile [-8]] [-runi:1,2 plainfile [-8]]");
1105 fprintf (stderr, " [-mys mapfile] [-rmys reverse-map-file]");
1106 fprintf (stderr, " [-kmap keymap-file] [-rkmap reverse-keymap-file]\n");
1107 fprintf (stderr, " [-installdir \"Install Dir\"] [-pipecmd command [args]]\n");
1108 fprintf (stderr, " -info print out useful info about the map.\n");
1109 fprintf (stderr, " -test print out useful info about the map and test it.\n");
1110 fprintf (stderr, " -strip delete the state machine, before doing anything else.\n");
1111 fprintf (stderr, " -name Assign a max 32-byte-long name.\n");
1112 fprintf (stderr, " -comment Assign a comment of arbitrary length.\n");
1113 fprintf (stderr, " -type Assign a map type. 0=None, 1=Font, 2=kmap - not used.\n");
1114 fprintf (stderr, " -encode build a state machine for all encoding maps.\n");
1115 fprintf (stderr, " -decode build a state machine for all decoding maps.\n");
1116 fprintf (stderr, " -write write out the latest map before exiting.\n");
1117 fprintf (stderr, " -convert {mys|c|my} convert the file to 'c' or 'my' \n");
1118 fprintf (stderr, " -uni:local,unicode a 16 bit file format with columns precified.\n");
1119 fprintf (stderr, " -runi:local,unicode a 16 bit file format in reverse with columns precified.\n");
1120 fprintf (stderr, " -my assign a fully specified binary mapfile to input.\n");
1121 fprintf (stderr, " -mys assign a fully specified mapfile source to input.\n");
1122 fprintf (stderr, " -rmys same as mys but key - value pairs will be reversed.\n");
1123 fprintf (stderr, " -kmap assign a fully specified keymap file source to input.\n");
1124 fprintf (stderr, " -rkmap same as kmap but key - value pairs will be reversed.\n");
1125 }
1126