blob: 938deafe50bbc1b1d389ff74915c4d632cea3474 [file] [log] [blame]
Eitan Isaacson109996e2008-12-20 14:52:53 +00001/* liblouis Braille Translation and Back-Translation Library
2
3 Based on BRLTTY, copyright (C) 1999-2006 by
4 The BRLTTY Team
5
Christian Egli08d96a72009-10-08 08:49:13 +00006 Copyright (C) 2004, 2005, 2006, 2009
7 ViewPlus Technologies, Inc. www.viewplus.com and
Eitan Isaacson109996e2008-12-20 14:52:53 +00008 JJB Software, Inc. www.jjb-software.com
9
Christian Egli08d96a72009-10-08 08:49:13 +000010 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
Bert Frees92a80352017-09-30 23:01:02 +020014
Christian Egli08d96a72009-10-08 08:49:13 +000015 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
Bert Frees92a80352017-09-30 23:01:02 +020019
Eitan Isaacson109996e2008-12-20 14:52:53 +000020 You should have received a copy of the GNU General Public License
Christian Egli08d96a72009-10-08 08:49:13 +000021 along with this program. If not, see <http://www.gnu.org/licenses/>.
Bert Frees312affd2017-09-30 19:49:15 +020022*/
Eitan Isaacson109996e2008-12-20 14:52:53 +000023
Bert Frees92a80352017-09-30 23:01:02 +020024#include <config.h>
Eitan Isaacson109996e2008-12-20 14:52:53 +000025#include <stdio.h>
26#include <string.h>
27#include <stdlib.h>
Davy Kagerff52a4f2017-04-26 22:01:10 +020028#include "internal.h"
Christian Eglibe149002009-10-09 09:09:07 +000029#include <getopt.h>
30#include "progname.h"
Christian Egli4b193942016-06-21 17:57:26 +020031#include "unistr.h"
Christian Eglibe149002009-10-09 09:09:07 +000032#include "version-etc.h"
33
Bert Frees92a80352017-09-30 23:01:02 +020034static const struct option longopts[] = {
Christian Egli585c6762019-06-05 15:19:10 +020035 { "help", no_argument, NULL, 'h' },
36 { "version", no_argument, NULL, 'v' },
Bert Frees92a80352017-09-30 23:01:02 +020037 { NULL, 0, NULL, 0 },
Christian Eglibe149002009-10-09 09:09:07 +000038};
39
40const char version_etc_copyright[] =
Bert Frees92a80352017-09-30 23:01:02 +020041 "Copyright %s %d ViewPlus Technologies, Inc. and JJB Software, Inc.";
Christian Eglibe149002009-10-09 09:09:07 +000042
43#define AUTHORS "John J. Boyer"
44
45static void
Bert Frees92a80352017-09-30 23:01:02 +020046print_help(void) {
47 printf("\
48Usage: %s [OPTIONS] TABLE[,TABLE,...]\n",
49 program_name);
50
51 fputs("\
Christian Eglibe149002009-10-09 09:09:07 +000052Examine and debug Braille translation tables. This program allows you\n\
53to inspect liblouis translation tables and gather information about\n\
54them, such as forward and backward rules, characters and dot patterns,\n\
55specific opcodes, the size of a table, whether a hyphenation\n\
56table is used, how many passes the translation takes and much\n\
Bert Frees92a80352017-09-30 23:01:02 +020057more.\n\n",
58 stdout);
Christian Eglibe149002009-10-09 09:09:07 +000059
Bert Frees92a80352017-09-30 23:01:02 +020060 fputs("\
Christian Eglibe149002009-10-09 09:09:07 +000061 -h, --help display this help and exit\n\
Bert Frees92a80352017-09-30 23:01:02 +020062 -v, --version display version information and exit\n",
63 stdout);
Christian Eglibe149002009-10-09 09:09:07 +000064
Bert Frees92a80352017-09-30 23:01:02 +020065 printf("\n");
66 printf("Report bugs to %s.\n", PACKAGE_BUGREPORT);
Christian Eglidc50af92012-09-27 13:10:51 +000067
68#ifdef PACKAGE_PACKAGER_BUG_REPORTS
Bert Frees92a80352017-09-30 23:01:02 +020069 printf("Report %s bugs to: %s\n", PACKAGE_PACKAGER, PACKAGE_PACKAGER_BUG_REPORTS);
Christian Eglidc50af92012-09-27 13:10:51 +000070#endif
71#ifdef PACKAGE_URL
Bert Frees92a80352017-09-30 23:01:02 +020072 printf("%s home page: <%s>\n", PACKAGE_NAME, PACKAGE_URL);
Christian Eglidc50af92012-09-27 13:10:51 +000073#endif
Christian Eglibe149002009-10-09 09:09:07 +000074}
75
Eitan Isaacson109996e2008-12-20 14:52:53 +000076#define BUFSIZE 256
77
John Boyer16689ac2009-01-12 15:11:39 +000078static const TranslationTableHeader *table;
Bert Freesc3223682019-07-09 23:18:43 +020079static const DisplayTableHeader *displayTable;
Eitan Isaacson109996e2008-12-20 14:52:53 +000080static char inputBuffer[BUFSIZE];
81
82static int
Bert Frees92a80352017-09-30 23:01:02 +020083getInput(void) {
84 int inputLength;
85 inputBuffer[0] = 0;
86 if (!fgets(inputBuffer, sizeof(inputBuffer), stdin)) exit(EXIT_FAILURE);
87 inputLength = strlen(inputBuffer) - 1;
88 if (inputLength < 0) /* EOF on script */
89 exit(EXIT_FAILURE);
90 inputBuffer[inputLength] = 0;
91 return inputLength;
John Boyer16689ac2009-01-12 15:11:39 +000092}
93
94static char *
Bert Frees92a80352017-09-30 23:01:02 +020095print_chars(const widechar *buffer, int length) {
96 static uint8_t result_buf[BUFSIZE];
97 size_t result_len = BUFSIZE - 1;
98#ifdef WIDECHARS_ARE_UCS4
99 u32_to_u8(buffer, length, result_buf, &result_len);
100#else
101 u16_to_u8(buffer, length, result_buf, &result_len);
102#endif
103 result_buf[result_len] = 0;
104 return result_buf;
John Boyer16689ac2009-01-12 15:11:39 +0000105}
106
107static int
Bert Frees92a80352017-09-30 23:01:02 +0200108printRule(TranslationTableRule *thisRule, int mode) {
109 printf("Rule: ");
110 printf("opcode=%s, ", _lou_findOpcodeName(thisRule->opcode));
111 if (thisRule->before) printf("before=%x, ", thisRule->before);
112 if (thisRule->after) printf("after=%x, ", thisRule->after);
113 switch (thisRule->opcode) {
114 case CTO_Context:
115 case CTO_Correct:
116 case CTO_SwapCd:
117 case CTO_SwapDd:
118 case CTO_Pass2:
119 case CTO_Pass3:
120 case CTO_Pass4:
121 printf("code=%s ",
122 print_chars(thisRule->charsdots, thisRule->charslen + thisRule->dotslen));
123 break;
John Boyer16689ac2009-01-12 15:11:39 +0000124 default:
Bert Frees92a80352017-09-30 23:01:02 +0200125 if (mode == 0) {
126 printf("chars=%s, ", print_chars(thisRule->charsdots, thisRule->charslen));
Christian Egli585c6762019-06-05 15:19:10 +0200127 printf("dots=%s, ",
128 _lou_showDots(
129 &thisRule->charsdots[thisRule->charslen], thisRule->dotslen));
Bert Frees92a80352017-09-30 23:01:02 +0200130 } else {
Christian Egli585c6762019-06-05 15:19:10 +0200131 printf("dots=%s, ",
132 _lou_showDots(
133 &thisRule->charsdots[thisRule->charslen], thisRule->dotslen));
Bert Frees92a80352017-09-30 23:01:02 +0200134 printf("chars=%s, ", print_chars(thisRule->charsdots, thisRule->charslen));
135 }
136 break;
John Boyer16689ac2009-01-12 15:11:39 +0000137 }
Bert Frees92a80352017-09-30 23:01:02 +0200138 return 1;
Eitan Isaacson109996e2008-12-20 14:52:53 +0000139}
140
141static int
Bert Frees92a80352017-09-30 23:01:02 +0200142printCharacter(TranslationTableCharacter *thisChar, int mode) {
143 TranslationTableRule *thisRule;
144 TranslationTableOffset nextRule;
145 if (mode == 0) {
146 printf("Char: ");
147 printf("real=%s, ", print_chars(&thisChar->realchar, 1));
148 printf("upper=%s, ", print_chars(&thisChar->uppercase, 1));
149 printf("lower=%s, ", print_chars(&thisChar->lowercase, 1));
150 } else
151 printf("Dots: real=%s, ", _lou_showDots(&thisChar->realchar, 1));
152 printf("attr=%s, ", _lou_showAttributes(thisChar->attributes));
153 nextRule = thisChar->otherRules;
154 while (nextRule) {
155 thisRule = (TranslationTableRule *)&table->ruleArea[nextRule];
156 if (nextRule == thisChar->definitionRule) printf("definition ");
157 printRule(thisRule, mode);
158 printf("\n");
159 if (mode == 0)
160 nextRule = thisRule->charsnext;
161 else
162 nextRule = thisRule->dotsnext;
Eitan Isaacson109996e2008-12-20 14:52:53 +0000163 }
Bert Frees92a80352017-09-30 23:01:02 +0200164 return 1;
165}
166
167static int
168show_characters(int startHash) {
169 int k;
170 TranslationTableCharacter *thisChar;
171 TranslationTableOffset nextChar;
172 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
173 if (startHash < 0)
174 k = 0;
175 else
176 k = startHash;
177 for (; k < HASHNUM; k++)
178 if (table->characters[k]) {
179 printf("Hash=%d\n", k);
180 nextChar = table->characters[k];
181 while (nextChar) {
182 thisChar = (TranslationTableCharacter *)&table->ruleArea[nextChar];
183 printCharacter(thisChar, 0);
184 printf("=> ");
185 getInput();
186 if (*inputBuffer == 'h') break;
187 if (*inputBuffer == 'e') return 1;
188 nextChar = thisChar->next;
189 }
190 }
191 return 1;
192}
193
194static int
195show_dots(int startHash) {
196 int k;
197 TranslationTableCharacter *thisDots;
198 TranslationTableOffset nextDots;
199 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
200 if (startHash < 0)
201 k = 0;
202 else
203 k = startHash;
204 for (; k < HASHNUM; k++)
205 if (table->dots[k]) {
206 printf("Hash=%d\n", k);
207 nextDots = table->dots[k];
208 while (nextDots) {
209 thisDots = (TranslationTableCharacter *)&table->ruleArea[nextDots];
210 printCharacter(thisDots, 1);
211 printf("=> ");
212 getInput();
213 if (*inputBuffer == 'h') break;
214 if (*inputBuffer == 'e') return 1;
215 nextDots = thisDots->next;
216 }
217 }
218 return 1;
219}
220
221static int
222show_forRules(int startHash) {
223 int k;
224 TranslationTableRule *thisRule;
225 TranslationTableOffset nextRule;
226 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
227 if (startHash < 0)
228 k = 0;
229 else
230 k = startHash;
231 for (; k < HASHNUM; k++)
232 if (table->forRules[k]) {
233 printf("Hash=%d\n", k);
234 nextRule = table->forRules[k];
235 while (nextRule) {
236 thisRule = (TranslationTableRule *)&table->ruleArea[nextRule];
237 printRule(thisRule, 0);
238 printf("=> ");
239 getInput();
240 if (*inputBuffer == 'h') break;
241 if (*inputBuffer == 'e') return 1;
242 nextRule = thisRule->charsnext;
243 }
244 }
245 return 1;
246}
247
248static int
249show_backRules(int startHash) {
250 int k;
251 TranslationTableRule *thisRule;
252 TranslationTableOffset nextRule;
253 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
254 if (startHash < 0)
255 k = 0;
256 else
257 k = startHash;
258 for (; k < HASHNUM; k++)
259 if (table->backRules[k]) {
260 printf("Hash=%d\n", k);
261 nextRule = table->backRules[k];
262 while (nextRule) {
263 thisRule = (TranslationTableRule *)&table->ruleArea[nextRule];
264 printRule(thisRule, 1);
265 printf("=> ");
266 getInput();
267 if (*inputBuffer == 'h') break;
268 if (*inputBuffer == 'e') return 1;
269 nextRule = thisRule->dotsnext;
270 }
271 }
272 return 1;
273}
274
275static int
Christian Egli0cfcd192018-05-08 11:22:46 +0200276print_brailleIndicator(TranslationTableOffset offset, const char *opcode) {
Bert Frees92a80352017-09-30 23:01:02 +0200277 TranslationTableRule *thisRule;
278 if (!offset) return 0;
279 thisRule = (TranslationTableRule *)&table->ruleArea[offset];
280 printf("%s %s\n", opcode, _lou_showDots(&thisRule->charsdots[0], thisRule->dotslen));
281 return 1;
282}
283
284static int
Christian Egli0cfcd192018-05-08 11:22:46 +0200285print_phraseLength(TranslationTableOffset offset, const char *opcode) {
Bert Frees92a80352017-09-30 23:01:02 +0200286 if (!offset) return 0;
Christian Eglida0d2eb2018-05-07 13:41:57 +0200287 printf("%s %u\n", opcode, offset);
Bert Frees92a80352017-09-30 23:01:02 +0200288 return 1;
289}
290
291static int
292show_brailleIndicators(void) {
293 char name[BUFSIZE];
Christian Egli0cfcd192018-05-08 11:22:46 +0200294 const char *emphNames[] = { "begemphphrase %s", "endemphphrase %s before",
Bert Frees92a80352017-09-30 23:01:02 +0200295 "endemphphrase %s after", "begemphword %s", "endemphword %s", "emphletter %s",
296 "begemph %s", "endemph %s", NULL };
Christian Eglid92cec12018-05-08 11:51:17 +0200297 const char *capsNames[] = { "firstwordcaps", "lastwordcapsbefore",
298 "lastwordcapsafter", "begcaps", "endcaps", "capsletter", "capsword",
299 "capswordstop", NULL };
Bert Frees92a80352017-09-30 23:01:02 +0200300
301 // FIXME: update to include all UEB opcodes.
302
303 for (EmphCodeOffset offset = 0; capsNames[offset]; offset++) {
304 print_brailleIndicator(table->emphRules[capsRule][offset], capsNames[offset]);
305 }
306 print_phraseLength(table->emphRules[capsRule][lenPhraseOffset], "lencapsphrase");
307 print_brailleIndicator(table->letterSign, "letsign");
308 print_brailleIndicator(table->numberSign, "numsign");
309
310 for (int i = 0; table->emphClasses[i]; i++) {
311 for (EmphCodeOffset offset = 0; emphNames[offset]; offset++) {
312 snprintf(name, BUFSIZE, emphNames[offset], table->emphClasses[i]);
313 print_brailleIndicator(table->emphRules[emph1Rule][offset], name);
314 }
315 snprintf(name, BUFSIZE, "lenemphphrase %s", table->emphClasses[i]);
316 print_phraseLength(table->emphRules[emph1Rule][lenPhraseOffset], name);
317 }
318 print_brailleIndicator(table->begComp, "begcomp");
319 print_brailleIndicator(table->compBegEmph1, "compbegemph1");
320 print_brailleIndicator(table->compEndEmph1, "compendemph1");
321 print_brailleIndicator(table->compBegEmph2, "compbegemph2");
322 print_brailleIndicator(table->compEndEmph2, "compendemph2");
323 print_brailleIndicator(table->compBegEmph3, "compbegemph3");
324 print_brailleIndicator(table->compEndEmph3, "compendemph3");
325 print_brailleIndicator(table->compCapSign, "compcapsign");
326 print_brailleIndicator(table->compBegCaps, "compbegcaps");
327 print_brailleIndicator(table->compEndCaps, "compendcaps");
328 print_brailleIndicator(table->endComp, "endcomp");
329 return 1;
330}
331
Christian Egli0cfcd192018-05-08 11:22:46 +0200332static const char *
Bert Frees92a80352017-09-30 23:01:02 +0200333pickYN(int a) {
334 if (!a) return "no";
335 return "yes";
336}
337
338static int
339show_misc(void) {
Christian Eglida0d2eb2018-05-07 13:41:57 +0200340 printf("Table size: %u\n", table->tableSize);
341 printf("Bytes used: %u\n", table->bytesUsed);
Bert Frees92a80352017-09-30 23:01:02 +0200342 printf("Number of passes: %d\n", table->numPasses);
343 printf("'correct' opcodes: %s\n", pickYN(table->corrections));
344 printf("'syllable' opcodes: %s\n", pickYN(table->syllables));
345 printf("'capsnocont' opcode: %s\n", pickYN(table->capsNoCont));
346 printf("Hyphenation table: %s\n", pickYN(table->hyphenStatesArray));
347 printf("noletsignbefore %s\n",
348 print_chars(&table->noLetsignBefore[0], table->noLetsignBeforeCount));
349 printf("noletsign %s\n", print_chars(&table->noLetsign[0], table->noLetsignCount));
350 printf("noletsignafter %s\n",
351 print_chars(&table->noLetsignAfter[0], table->noLetsignAfterCount));
352 return 1;
353}
354
355static int
356show_charMap(int startHash) {
357 int k;
Bert Freesb2b67422020-03-08 22:31:58 +0100358 CharDotsMapping *thisChar;
Bert Frees92a80352017-09-30 23:01:02 +0200359 TranslationTableOffset nextChar;
360 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
361 if (startHash < 0)
362 k = 0;
363 else
364 k = startHash;
365 for (; k < HASHNUM; k++)
Bert Freesc3223682019-07-09 23:18:43 +0200366 if (displayTable->charToDots[k]) {
Bert Frees92a80352017-09-30 23:01:02 +0200367 printf("Hash=%d\n", k);
Bert Freesc3223682019-07-09 23:18:43 +0200368 nextChar = displayTable->charToDots[k];
Bert Frees92a80352017-09-30 23:01:02 +0200369 while (nextChar) {
Bert Freesb2b67422020-03-08 22:31:58 +0100370 thisChar = (CharDotsMapping *)&displayTable->ruleArea[nextChar];
Bert Frees92a80352017-09-30 23:01:02 +0200371 printf("Char: %s ", print_chars(&thisChar->lookFor, 1));
372 printf("dots=%s\n", _lou_showDots(&thisChar->found, 1));
373 printf("=> ");
374 getInput();
375 if (*inputBuffer == 'h') break;
376 if (*inputBuffer == 'e') return 1;
377 nextChar = thisChar->next;
378 }
379 }
380 return 1;
381}
382
383static int
384show_dotsMap(int startHash) {
385 int k;
Bert Freesb2b67422020-03-08 22:31:58 +0100386 CharDotsMapping *thisDots;
Bert Frees92a80352017-09-30 23:01:02 +0200387 TranslationTableOffset nextDots;
388 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
389 if (startHash < 0)
390 k = 0;
391 else
392 k = startHash;
393 for (; k < HASHNUM; k++)
Bert Freesc3223682019-07-09 23:18:43 +0200394 if (displayTable->dotsToChar[k]) {
Bert Frees92a80352017-09-30 23:01:02 +0200395 printf("Hash=%d\n", k);
Bert Freesc3223682019-07-09 23:18:43 +0200396 nextDots = displayTable->dotsToChar[k];
Bert Frees92a80352017-09-30 23:01:02 +0200397 while (nextDots) {
Bert Freesb2b67422020-03-08 22:31:58 +0100398 thisDots = (CharDotsMapping *)&displayTable->ruleArea[nextDots];
Bert Frees92a80352017-09-30 23:01:02 +0200399 printf("Dots: %s ", _lou_showDots(&thisDots->lookFor, 1));
400 printf("char=%s\n", print_chars(&thisDots->found, 1));
401 printf("=> ");
402 getInput();
403 if (*inputBuffer == 'h') break;
404 if (*inputBuffer == 'e') return 1;
405 nextDots = thisDots->next;
406 }
407 }
408 return 1;
409}
410
411static int
412show_compDots(int startChar) {
413 widechar k;
414 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
415 if (startChar < 0)
416 k = 0;
417 else
418 k = startChar;
419 for (; k < 256; k++)
420 if (table->compdotsPattern[k]) {
421 TranslationTableRule *thisRule =
422 (TranslationTableRule *)&table->ruleArea[table->compdotsPattern[k]];
423 printf("Char: %s ", print_chars(&k, 1));
424 printf("dots=%s\n",
425 _lou_showDots(&thisRule->charsdots[1], thisRule->dotslen));
426 printf("=> ");
427 getInput();
428 if (*inputBuffer == 'e') return 1;
429 }
430 return 1;
431}
432
433static void
434part_paramLetters(void) {
435 printf("show particular hash chains.\n");
436 printf("show-(f)orward-rules, show-(b)ackward-rules, show-(c)haracters, \n");
437 printf("show-(d)ot-patterns, show-(C)har-to-dots, show-(D)ots-tochar\n");
438 printf("(z)-compdots, (h)elp, e(x)it\n");
439}
440
441static void
442particularHelp(void) {
443 part_paramLetters();
444}
445
446static int
447particular(void) {
448 int startHash;
449 widechar parsed[BUFSIZE];
450 part_paramLetters();
451 do {
452 printf("particular: ");
453 getInput();
454 switch (inputBuffer[0]) {
455 case 0:
456 break;
457 case 'h':
458 particularHelp();
459 break;
460 case 'c':
461 printf("-> ");
462 getInput();
463 if (!_lou_extParseChars(inputBuffer, parsed)) break;
464 startHash = _lou_charHash(*parsed);
465 if (table->characters[startHash] == 0) {
466 printf("Character not in table.\n");
467 break;
468 }
469 show_characters(startHash);
470 break;
471 case 'd':
472 printf("-> ");
473 getInput();
474 if (!_lou_extParseDots(inputBuffer, parsed)) break;
475 startHash = _lou_charHash(*parsed);
476 if (table->dots[startHash] == 0) {
477 printf("Dot pattern not in table.\n");
478 break;
479 }
480 show_dots(startHash);
481 break;
482 case 'C':
483 printf("-> ");
484 getInput();
485 if (!_lou_extParseChars(inputBuffer, parsed)) break;
486 startHash = _lou_charHash(*parsed);
Bert Freesc3223682019-07-09 23:18:43 +0200487 if (displayTable->charToDots[startHash] == 0) {
Bert Frees92a80352017-09-30 23:01:02 +0200488 printf("Character not in table.\n");
489 break;
490 }
491 show_charMap(startHash);
492 break;
493 case 'D':
494 printf("-> ");
495 getInput();
496 if (!_lou_extParseDots(inputBuffer, parsed)) break;
497 startHash = _lou_charHash(*parsed);
Bert Freesc3223682019-07-09 23:18:43 +0200498 if (displayTable->dotsToChar[startHash] == 0) {
Bert Frees92a80352017-09-30 23:01:02 +0200499 printf("Dot pattern not in table.\n");
500 break;
501 }
502 show_dotsMap(startHash);
503 break;
504 case 'f':
505 printf("-> ");
506 getInput();
507 if (!_lou_extParseChars(inputBuffer, parsed)) break;
Bert Freesd4b7a8e2019-06-04 13:56:07 +0200508 startHash = _lou_stringHash(parsed, 0, NULL);
Bert Frees92a80352017-09-30 23:01:02 +0200509 if (table->forRules[startHash] == 0) {
510 printf("Character string not in table.\n");
511 break;
512 }
513 show_forRules(startHash);
514 break;
515 case 'b':
516 printf("-> ");
517 getInput();
518 if (!_lou_extParseDots(inputBuffer, parsed)) break;
Bert Freesd4b7a8e2019-06-04 13:56:07 +0200519 startHash = _lou_stringHash(parsed, 0, NULL);
Bert Frees92a80352017-09-30 23:01:02 +0200520 if (table->backRules[startHash] == 0) {
521 printf("Dot pattern not in table.\n");
522 break;
523 }
524 show_backRules(startHash);
525 break;
526 case 'z':
527 printf("-> ");
528 getInput();
529 if (!_lou_extParseChars(inputBuffer, parsed)) break;
530 startHash = _lou_charHash(*parsed);
531 if (*parsed > 255 || table->compdotsPattern[startHash] == 0) {
532 printf("Character not in table.\n");
533 break;
534 }
535 show_compDots(startHash);
536 break;
537 case 'x':
538 return 1;
539 default:
540 printf("Bad choice.\n");
541 break;
542 }
543 } while (inputBuffer[0] != 'x');
544 return 1;
545}
546
547static void
548paramLetters(void) {
549 printf("Press one of the letters in parentheses, then enter.\n");
550 printf("show-(f)orward-rules, show-(b)ackward-rules, show-(c)haracters, \n");
551 printf("show-(d)ot-patterns, show-(C)har-to-dots, show-(D)ots-tochar\n");
552 printf("show-(m)isc, show-(z)-compdots\n");
553 printf("show-braille(i)ndicators, show-(p)articulars\n");
554 printf("(h)elp, (q)uit\n");
555}
556
557static void
558commandHelp(void) {
559 paramLetters();
560}
561
562static int
563getCommands(void) {
564 paramLetters();
565 do {
566 printf("Command: ");
567 getInput();
568 switch (inputBuffer[0]) {
569 case 0:
570 break;
571 case 'h':
572 commandHelp();
573 break;
574 case 'C':
575 show_charMap(-1);
576 break;
577 case 'D':
578 show_dotsMap(-1);
579 break;
580 case 'z':
581 show_compDots(-1);
582 break;
583 case 'c':
584 show_characters(-1);
585 break;
586 case 'd':
587 show_dots(-1);
588 break;
589 case 'f':
590 show_forRules(-1);
591 break;
592 case 'b':
593 show_backRules(-1);
594 break;
595 case 'i':
596 show_brailleIndicators();
597 break;
598 case 'm':
599 show_misc();
600 break;
601 case 'p':
602 particular();
603 break;
604 case 'q':
605 return 1;
606 default:
607 printf("Bad choice.\n");
608 break;
609 }
610 } while (inputBuffer[0] != 'q');
611 return 1;
Eitan Isaacson109996e2008-12-20 14:52:53 +0000612}
613
614int
Bert Frees92a80352017-09-30 23:01:02 +0200615main(int argc, char **argv) {
616 int optc;
Christian Eglibe149002009-10-09 09:09:07 +0000617
Bert Frees92a80352017-09-30 23:01:02 +0200618 set_program_name(argv[0]);
Christian Eglibe149002009-10-09 09:09:07 +0000619
Bert Frees92a80352017-09-30 23:01:02 +0200620 while ((optc = getopt_long(argc, argv, "hv", longopts, NULL)) != -1) switch (optc) {
621 /* --help and --version exit immediately, per GNU coding standards. */
622 case 'v':
623 version_etc(
624 stdout, program_name, PACKAGE_NAME, VERSION, AUTHORS, (char *)NULL);
625 exit(EXIT_SUCCESS);
626 break;
627 case 'h':
628 print_help();
629 exit(EXIT_SUCCESS);
630 break;
631 default:
632 fprintf(stderr, "Try `%s --help' for more information.\n", program_name);
633 exit(EXIT_FAILURE);
634 break;
635 }
Christian Eglibe149002009-10-09 09:09:07 +0000636
Bert Frees92a80352017-09-30 23:01:02 +0200637 if (optind != argc - 1) {
638 /* Print error message and exit. */
639 if (optind < argc - 1)
640 fprintf(stderr, "%s: extra operand: %s\n", program_name, argv[optind + 1]);
641 else
642 fprintf(stderr, "%s: no table specified\n", program_name);
643 fprintf(stderr, "Try `%s --help' for more information.\n", program_name);
644 exit(EXIT_FAILURE);
645 }
Christian Eglibe149002009-10-09 09:09:07 +0000646
Bert Frees47e69112019-08-22 13:09:36 +0200647 _lou_getTable(argv[optind], argv[optind], &table, &displayTable);
648 if (!table) {
Bert Frees92a80352017-09-30 23:01:02 +0200649 lou_free();
650 exit(EXIT_FAILURE);
651 }
652 getCommands();
653 lou_free();
654 exit(EXIT_SUCCESS);
Eitan Isaacson109996e2008-12-20 14:52:53 +0000655}