blob: 86b0048201d44d69438f8272412529e85afe7c36 [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[] = {
35 { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' },
36 { NULL, 0, NULL, 0 },
Christian Eglibe149002009-10-09 09:09:07 +000037};
38
39const char version_etc_copyright[] =
Bert Frees92a80352017-09-30 23:01:02 +020040 "Copyright %s %d ViewPlus Technologies, Inc. and JJB Software, Inc.";
Christian Eglibe149002009-10-09 09:09:07 +000041
42#define AUTHORS "John J. Boyer"
43
44static void
Bert Frees92a80352017-09-30 23:01:02 +020045print_help(void) {
46 printf("\
47Usage: %s [OPTIONS] TABLE[,TABLE,...]\n",
48 program_name);
49
50 fputs("\
Christian Eglibe149002009-10-09 09:09:07 +000051Examine and debug Braille translation tables. This program allows you\n\
52to inspect liblouis translation tables and gather information about\n\
53them, such as forward and backward rules, characters and dot patterns,\n\
54specific opcodes, the size of a table, whether a hyphenation\n\
55table is used, how many passes the translation takes and much\n\
Bert Frees92a80352017-09-30 23:01:02 +020056more.\n\n",
57 stdout);
Christian Eglibe149002009-10-09 09:09:07 +000058
Bert Frees92a80352017-09-30 23:01:02 +020059 fputs("\
Christian Eglibe149002009-10-09 09:09:07 +000060 -h, --help display this help and exit\n\
Bert Frees92a80352017-09-30 23:01:02 +020061 -v, --version display version information and exit\n",
62 stdout);
Christian Eglibe149002009-10-09 09:09:07 +000063
Bert Frees92a80352017-09-30 23:01:02 +020064 printf("\n");
65 printf("Report bugs to %s.\n", PACKAGE_BUGREPORT);
Christian Eglidc50af92012-09-27 13:10:51 +000066
67#ifdef PACKAGE_PACKAGER_BUG_REPORTS
Bert Frees92a80352017-09-30 23:01:02 +020068 printf("Report %s bugs to: %s\n", PACKAGE_PACKAGER, PACKAGE_PACKAGER_BUG_REPORTS);
Christian Eglidc50af92012-09-27 13:10:51 +000069#endif
70#ifdef PACKAGE_URL
Bert Frees92a80352017-09-30 23:01:02 +020071 printf("%s home page: <%s>\n", PACKAGE_NAME, PACKAGE_URL);
Christian Eglidc50af92012-09-27 13:10:51 +000072#endif
Christian Eglibe149002009-10-09 09:09:07 +000073}
74
Eitan Isaacson109996e2008-12-20 14:52:53 +000075#define BUFSIZE 256
76
John Boyer16689ac2009-01-12 15:11:39 +000077static const TranslationTableHeader *table;
Eitan Isaacson109996e2008-12-20 14:52:53 +000078static char inputBuffer[BUFSIZE];
79
80static int
Bert Frees92a80352017-09-30 23:01:02 +020081getInput(void) {
82 int inputLength;
83 inputBuffer[0] = 0;
84 if (!fgets(inputBuffer, sizeof(inputBuffer), stdin)) exit(EXIT_FAILURE);
85 inputLength = strlen(inputBuffer) - 1;
86 if (inputLength < 0) /* EOF on script */
87 exit(EXIT_FAILURE);
88 inputBuffer[inputLength] = 0;
89 return inputLength;
John Boyer16689ac2009-01-12 15:11:39 +000090}
91
92static char *
Bert Frees92a80352017-09-30 23:01:02 +020093print_chars(const widechar *buffer, int length) {
94 static uint8_t result_buf[BUFSIZE];
95 size_t result_len = BUFSIZE - 1;
96#ifdef WIDECHARS_ARE_UCS4
97 u32_to_u8(buffer, length, result_buf, &result_len);
98#else
99 u16_to_u8(buffer, length, result_buf, &result_len);
100#endif
101 result_buf[result_len] = 0;
102 return result_buf;
John Boyer16689ac2009-01-12 15:11:39 +0000103}
104
105static int
Bert Frees92a80352017-09-30 23:01:02 +0200106printRule(TranslationTableRule *thisRule, int mode) {
107 printf("Rule: ");
108 printf("opcode=%s, ", _lou_findOpcodeName(thisRule->opcode));
109 if (thisRule->before) printf("before=%x, ", thisRule->before);
110 if (thisRule->after) printf("after=%x, ", thisRule->after);
111 switch (thisRule->opcode) {
112 case CTO_Context:
113 case CTO_Correct:
114 case CTO_SwapCd:
115 case CTO_SwapDd:
116 case CTO_Pass2:
117 case CTO_Pass3:
118 case CTO_Pass4:
119 printf("code=%s ",
120 print_chars(thisRule->charsdots, thisRule->charslen + thisRule->dotslen));
121 break;
John Boyer16689ac2009-01-12 15:11:39 +0000122 default:
Bert Frees92a80352017-09-30 23:01:02 +0200123 if (mode == 0) {
124 printf("chars=%s, ", print_chars(thisRule->charsdots, thisRule->charslen));
125 printf("dots=%s, ", _lou_showDots(&thisRule->charsdots[thisRule->charslen],
126 thisRule->dotslen));
127 } else {
128 printf("dots=%s, ", _lou_showDots(&thisRule->charsdots[thisRule->charslen],
129 thisRule->dotslen));
130 printf("chars=%s, ", print_chars(thisRule->charsdots, thisRule->charslen));
131 }
132 break;
John Boyer16689ac2009-01-12 15:11:39 +0000133 }
Bert Frees92a80352017-09-30 23:01:02 +0200134 return 1;
Eitan Isaacson109996e2008-12-20 14:52:53 +0000135}
136
137static int
Bert Frees92a80352017-09-30 23:01:02 +0200138printCharacter(TranslationTableCharacter *thisChar, int mode) {
139 TranslationTableRule *thisRule;
140 TranslationTableOffset nextRule;
141 if (mode == 0) {
142 printf("Char: ");
143 printf("real=%s, ", print_chars(&thisChar->realchar, 1));
144 printf("upper=%s, ", print_chars(&thisChar->uppercase, 1));
145 printf("lower=%s, ", print_chars(&thisChar->lowercase, 1));
146 } else
147 printf("Dots: real=%s, ", _lou_showDots(&thisChar->realchar, 1));
148 printf("attr=%s, ", _lou_showAttributes(thisChar->attributes));
149 nextRule = thisChar->otherRules;
150 while (nextRule) {
151 thisRule = (TranslationTableRule *)&table->ruleArea[nextRule];
152 if (nextRule == thisChar->definitionRule) printf("definition ");
153 printRule(thisRule, mode);
154 printf("\n");
155 if (mode == 0)
156 nextRule = thisRule->charsnext;
157 else
158 nextRule = thisRule->dotsnext;
Eitan Isaacson109996e2008-12-20 14:52:53 +0000159 }
Bert Frees92a80352017-09-30 23:01:02 +0200160 return 1;
161}
162
163static int
164show_characters(int startHash) {
165 int k;
166 TranslationTableCharacter *thisChar;
167 TranslationTableOffset nextChar;
168 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
169 if (startHash < 0)
170 k = 0;
171 else
172 k = startHash;
173 for (; k < HASHNUM; k++)
174 if (table->characters[k]) {
175 printf("Hash=%d\n", k);
176 nextChar = table->characters[k];
177 while (nextChar) {
178 thisChar = (TranslationTableCharacter *)&table->ruleArea[nextChar];
179 printCharacter(thisChar, 0);
180 printf("=> ");
181 getInput();
182 if (*inputBuffer == 'h') break;
183 if (*inputBuffer == 'e') return 1;
184 nextChar = thisChar->next;
185 }
186 }
187 return 1;
188}
189
190static int
191show_dots(int startHash) {
192 int k;
193 TranslationTableCharacter *thisDots;
194 TranslationTableOffset nextDots;
195 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
196 if (startHash < 0)
197 k = 0;
198 else
199 k = startHash;
200 for (; k < HASHNUM; k++)
201 if (table->dots[k]) {
202 printf("Hash=%d\n", k);
203 nextDots = table->dots[k];
204 while (nextDots) {
205 thisDots = (TranslationTableCharacter *)&table->ruleArea[nextDots];
206 printCharacter(thisDots, 1);
207 printf("=> ");
208 getInput();
209 if (*inputBuffer == 'h') break;
210 if (*inputBuffer == 'e') return 1;
211 nextDots = thisDots->next;
212 }
213 }
214 return 1;
215}
216
217static int
218show_forRules(int startHash) {
219 int k;
220 TranslationTableRule *thisRule;
221 TranslationTableOffset nextRule;
222 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
223 if (startHash < 0)
224 k = 0;
225 else
226 k = startHash;
227 for (; k < HASHNUM; k++)
228 if (table->forRules[k]) {
229 printf("Hash=%d\n", k);
230 nextRule = table->forRules[k];
231 while (nextRule) {
232 thisRule = (TranslationTableRule *)&table->ruleArea[nextRule];
233 printRule(thisRule, 0);
234 printf("=> ");
235 getInput();
236 if (*inputBuffer == 'h') break;
237 if (*inputBuffer == 'e') return 1;
238 nextRule = thisRule->charsnext;
239 }
240 }
241 return 1;
242}
243
244static int
245show_backRules(int startHash) {
246 int k;
247 TranslationTableRule *thisRule;
248 TranslationTableOffset nextRule;
249 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
250 if (startHash < 0)
251 k = 0;
252 else
253 k = startHash;
254 for (; k < HASHNUM; k++)
255 if (table->backRules[k]) {
256 printf("Hash=%d\n", k);
257 nextRule = table->backRules[k];
258 while (nextRule) {
259 thisRule = (TranslationTableRule *)&table->ruleArea[nextRule];
260 printRule(thisRule, 1);
261 printf("=> ");
262 getInput();
263 if (*inputBuffer == 'h') break;
264 if (*inputBuffer == 'e') return 1;
265 nextRule = thisRule->dotsnext;
266 }
267 }
268 return 1;
269}
270
271static int
Christian Egli0cfcd192018-05-08 11:22:46 +0200272print_brailleIndicator(TranslationTableOffset offset, const char *opcode) {
Bert Frees92a80352017-09-30 23:01:02 +0200273 TranslationTableRule *thisRule;
274 if (!offset) return 0;
275 thisRule = (TranslationTableRule *)&table->ruleArea[offset];
276 printf("%s %s\n", opcode, _lou_showDots(&thisRule->charsdots[0], thisRule->dotslen));
277 return 1;
278}
279
280static int
Christian Egli0cfcd192018-05-08 11:22:46 +0200281print_phraseLength(TranslationTableOffset offset, const char *opcode) {
Bert Frees92a80352017-09-30 23:01:02 +0200282 if (!offset) return 0;
Christian Eglida0d2eb2018-05-07 13:41:57 +0200283 printf("%s %u\n", opcode, offset);
Bert Frees92a80352017-09-30 23:01:02 +0200284 return 1;
285}
286
287static int
288show_brailleIndicators(void) {
289 char name[BUFSIZE];
Christian Egli0cfcd192018-05-08 11:22:46 +0200290 const char *emphNames[] = { "begemphphrase %s", "endemphphrase %s before",
Bert Frees92a80352017-09-30 23:01:02 +0200291 "endemphphrase %s after", "begemphword %s", "endemphword %s", "emphletter %s",
292 "begemph %s", "endemph %s", NULL };
Christian Eglid92cec12018-05-08 11:51:17 +0200293 const char *capsNames[] = { "firstwordcaps", "lastwordcapsbefore",
294 "lastwordcapsafter", "begcaps", "endcaps", "capsletter", "capsword",
295 "capswordstop", NULL };
Bert Frees92a80352017-09-30 23:01:02 +0200296
297 // FIXME: update to include all UEB opcodes.
298
299 for (EmphCodeOffset offset = 0; capsNames[offset]; offset++) {
300 print_brailleIndicator(table->emphRules[capsRule][offset], capsNames[offset]);
301 }
302 print_phraseLength(table->emphRules[capsRule][lenPhraseOffset], "lencapsphrase");
303 print_brailleIndicator(table->letterSign, "letsign");
304 print_brailleIndicator(table->numberSign, "numsign");
305
306 for (int i = 0; table->emphClasses[i]; i++) {
307 for (EmphCodeOffset offset = 0; emphNames[offset]; offset++) {
308 snprintf(name, BUFSIZE, emphNames[offset], table->emphClasses[i]);
309 print_brailleIndicator(table->emphRules[emph1Rule][offset], name);
310 }
311 snprintf(name, BUFSIZE, "lenemphphrase %s", table->emphClasses[i]);
312 print_phraseLength(table->emphRules[emph1Rule][lenPhraseOffset], name);
313 }
314 print_brailleIndicator(table->begComp, "begcomp");
315 print_brailleIndicator(table->compBegEmph1, "compbegemph1");
316 print_brailleIndicator(table->compEndEmph1, "compendemph1");
317 print_brailleIndicator(table->compBegEmph2, "compbegemph2");
318 print_brailleIndicator(table->compEndEmph2, "compendemph2");
319 print_brailleIndicator(table->compBegEmph3, "compbegemph3");
320 print_brailleIndicator(table->compEndEmph3, "compendemph3");
321 print_brailleIndicator(table->compCapSign, "compcapsign");
322 print_brailleIndicator(table->compBegCaps, "compbegcaps");
323 print_brailleIndicator(table->compEndCaps, "compendcaps");
324 print_brailleIndicator(table->endComp, "endcomp");
325 return 1;
326}
327
Christian Egli0cfcd192018-05-08 11:22:46 +0200328static const char *
Bert Frees92a80352017-09-30 23:01:02 +0200329pickYN(int a) {
330 if (!a) return "no";
331 return "yes";
332}
333
334static int
335show_misc(void) {
Christian Eglida0d2eb2018-05-07 13:41:57 +0200336 printf("Table size: %u\n", table->tableSize);
337 printf("Bytes used: %u\n", table->bytesUsed);
Bert Frees92a80352017-09-30 23:01:02 +0200338 printf("Number of passes: %d\n", table->numPasses);
339 printf("'correct' opcodes: %s\n", pickYN(table->corrections));
340 printf("'syllable' opcodes: %s\n", pickYN(table->syllables));
341 printf("'capsnocont' opcode: %s\n", pickYN(table->capsNoCont));
342 printf("Hyphenation table: %s\n", pickYN(table->hyphenStatesArray));
343 printf("noletsignbefore %s\n",
344 print_chars(&table->noLetsignBefore[0], table->noLetsignBeforeCount));
345 printf("noletsign %s\n", print_chars(&table->noLetsign[0], table->noLetsignCount));
346 printf("noletsignafter %s\n",
347 print_chars(&table->noLetsignAfter[0], table->noLetsignAfterCount));
348 return 1;
349}
350
351static int
352show_charMap(int startHash) {
353 int k;
354 CharOrDots *thisChar;
355 TranslationTableOffset nextChar;
356 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
357 if (startHash < 0)
358 k = 0;
359 else
360 k = startHash;
361 for (; k < HASHNUM; k++)
362 if (table->charToDots[k]) {
363 printf("Hash=%d\n", k);
364 nextChar = table->charToDots[k];
365 while (nextChar) {
366 thisChar = (CharOrDots *)&table->ruleArea[nextChar];
367 printf("Char: %s ", print_chars(&thisChar->lookFor, 1));
368 printf("dots=%s\n", _lou_showDots(&thisChar->found, 1));
369 printf("=> ");
370 getInput();
371 if (*inputBuffer == 'h') break;
372 if (*inputBuffer == 'e') return 1;
373 nextChar = thisChar->next;
374 }
375 }
376 return 1;
377}
378
379static int
380show_dotsMap(int startHash) {
381 int k;
382 CharOrDots *thisDots;
383 TranslationTableOffset nextDots;
384 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
385 if (startHash < 0)
386 k = 0;
387 else
388 k = startHash;
389 for (; k < HASHNUM; k++)
390 if (table->dotsToChar[k]) {
391 printf("Hash=%d\n", k);
392 nextDots = table->dotsToChar[k];
393 while (nextDots) {
394 thisDots = (CharOrDots *)&table->ruleArea[nextDots];
395 printf("Dots: %s ", _lou_showDots(&thisDots->lookFor, 1));
396 printf("char=%s\n", print_chars(&thisDots->found, 1));
397 printf("=> ");
398 getInput();
399 if (*inputBuffer == 'h') break;
400 if (*inputBuffer == 'e') return 1;
401 nextDots = thisDots->next;
402 }
403 }
404 return 1;
405}
406
407static int
408show_compDots(int startChar) {
409 widechar k;
410 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
411 if (startChar < 0)
412 k = 0;
413 else
414 k = startChar;
415 for (; k < 256; k++)
416 if (table->compdotsPattern[k]) {
417 TranslationTableRule *thisRule =
418 (TranslationTableRule *)&table->ruleArea[table->compdotsPattern[k]];
419 printf("Char: %s ", print_chars(&k, 1));
420 printf("dots=%s\n",
421 _lou_showDots(&thisRule->charsdots[1], thisRule->dotslen));
422 printf("=> ");
423 getInput();
424 if (*inputBuffer == 'e') return 1;
425 }
426 return 1;
427}
428
429static void
430part_paramLetters(void) {
431 printf("show particular hash chains.\n");
432 printf("show-(f)orward-rules, show-(b)ackward-rules, show-(c)haracters, \n");
433 printf("show-(d)ot-patterns, show-(C)har-to-dots, show-(D)ots-tochar\n");
434 printf("(z)-compdots, (h)elp, e(x)it\n");
435}
436
437static void
438particularHelp(void) {
439 part_paramLetters();
440}
441
442static int
443particular(void) {
444 int startHash;
445 widechar parsed[BUFSIZE];
446 part_paramLetters();
447 do {
448 printf("particular: ");
449 getInput();
450 switch (inputBuffer[0]) {
451 case 0:
452 break;
453 case 'h':
454 particularHelp();
455 break;
456 case 'c':
457 printf("-> ");
458 getInput();
459 if (!_lou_extParseChars(inputBuffer, parsed)) break;
460 startHash = _lou_charHash(*parsed);
461 if (table->characters[startHash] == 0) {
462 printf("Character not in table.\n");
463 break;
464 }
465 show_characters(startHash);
466 break;
467 case 'd':
468 printf("-> ");
469 getInput();
470 if (!_lou_extParseDots(inputBuffer, parsed)) break;
471 startHash = _lou_charHash(*parsed);
472 if (table->dots[startHash] == 0) {
473 printf("Dot pattern not in table.\n");
474 break;
475 }
476 show_dots(startHash);
477 break;
478 case 'C':
479 printf("-> ");
480 getInput();
481 if (!_lou_extParseChars(inputBuffer, parsed)) break;
482 startHash = _lou_charHash(*parsed);
483 if (table->charToDots[startHash] == 0) {
484 printf("Character not in table.\n");
485 break;
486 }
487 show_charMap(startHash);
488 break;
489 case 'D':
490 printf("-> ");
491 getInput();
492 if (!_lou_extParseDots(inputBuffer, parsed)) break;
493 startHash = _lou_charHash(*parsed);
494 if (table->dotsToChar[startHash] == 0) {
495 printf("Dot pattern not in table.\n");
496 break;
497 }
498 show_dotsMap(startHash);
499 break;
500 case 'f':
501 printf("-> ");
502 getInput();
503 if (!_lou_extParseChars(inputBuffer, parsed)) break;
504 startHash = _lou_stringHash(parsed);
505 if (table->forRules[startHash] == 0) {
506 printf("Character string not in table.\n");
507 break;
508 }
509 show_forRules(startHash);
510 break;
511 case 'b':
512 printf("-> ");
513 getInput();
514 if (!_lou_extParseDots(inputBuffer, parsed)) break;
515 startHash = _lou_stringHash(parsed);
516 if (table->backRules[startHash] == 0) {
517 printf("Dot pattern not in table.\n");
518 break;
519 }
520 show_backRules(startHash);
521 break;
522 case 'z':
523 printf("-> ");
524 getInput();
525 if (!_lou_extParseChars(inputBuffer, parsed)) break;
526 startHash = _lou_charHash(*parsed);
527 if (*parsed > 255 || table->compdotsPattern[startHash] == 0) {
528 printf("Character not in table.\n");
529 break;
530 }
531 show_compDots(startHash);
532 break;
533 case 'x':
534 return 1;
535 default:
536 printf("Bad choice.\n");
537 break;
538 }
539 } while (inputBuffer[0] != 'x');
540 return 1;
541}
542
543static void
544paramLetters(void) {
545 printf("Press one of the letters in parentheses, then enter.\n");
546 printf("show-(f)orward-rules, show-(b)ackward-rules, show-(c)haracters, \n");
547 printf("show-(d)ot-patterns, show-(C)har-to-dots, show-(D)ots-tochar\n");
548 printf("show-(m)isc, show-(z)-compdots\n");
549 printf("show-braille(i)ndicators, show-(p)articulars\n");
550 printf("(h)elp, (q)uit\n");
551}
552
553static void
554commandHelp(void) {
555 paramLetters();
556}
557
558static int
559getCommands(void) {
560 paramLetters();
561 do {
562 printf("Command: ");
563 getInput();
564 switch (inputBuffer[0]) {
565 case 0:
566 break;
567 case 'h':
568 commandHelp();
569 break;
570 case 'C':
571 show_charMap(-1);
572 break;
573 case 'D':
574 show_dotsMap(-1);
575 break;
576 case 'z':
577 show_compDots(-1);
578 break;
579 case 'c':
580 show_characters(-1);
581 break;
582 case 'd':
583 show_dots(-1);
584 break;
585 case 'f':
586 show_forRules(-1);
587 break;
588 case 'b':
589 show_backRules(-1);
590 break;
591 case 'i':
592 show_brailleIndicators();
593 break;
594 case 'm':
595 show_misc();
596 break;
597 case 'p':
598 particular();
599 break;
600 case 'q':
601 return 1;
602 default:
603 printf("Bad choice.\n");
604 break;
605 }
606 } while (inputBuffer[0] != 'q');
607 return 1;
Eitan Isaacson109996e2008-12-20 14:52:53 +0000608}
609
610int
Bert Frees92a80352017-09-30 23:01:02 +0200611main(int argc, char **argv) {
612 int optc;
Christian Eglibe149002009-10-09 09:09:07 +0000613
Bert Frees92a80352017-09-30 23:01:02 +0200614 set_program_name(argv[0]);
Christian Eglibe149002009-10-09 09:09:07 +0000615
Bert Frees92a80352017-09-30 23:01:02 +0200616 while ((optc = getopt_long(argc, argv, "hv", longopts, NULL)) != -1) switch (optc) {
617 /* --help and --version exit immediately, per GNU coding standards. */
618 case 'v':
619 version_etc(
620 stdout, program_name, PACKAGE_NAME, VERSION, AUTHORS, (char *)NULL);
621 exit(EXIT_SUCCESS);
622 break;
623 case 'h':
624 print_help();
625 exit(EXIT_SUCCESS);
626 break;
627 default:
628 fprintf(stderr, "Try `%s --help' for more information.\n", program_name);
629 exit(EXIT_FAILURE);
630 break;
631 }
Christian Eglibe149002009-10-09 09:09:07 +0000632
Bert Frees92a80352017-09-30 23:01:02 +0200633 if (optind != argc - 1) {
634 /* Print error message and exit. */
635 if (optind < argc - 1)
636 fprintf(stderr, "%s: extra operand: %s\n", program_name, argv[optind + 1]);
637 else
638 fprintf(stderr, "%s: no table specified\n", program_name);
639 fprintf(stderr, "Try `%s --help' for more information.\n", program_name);
640 exit(EXIT_FAILURE);
641 }
Christian Eglibe149002009-10-09 09:09:07 +0000642
Bert Frees92a80352017-09-30 23:01:02 +0200643 if (!(table = lou_getTable(argv[optind]))) {
644 lou_free();
645 exit(EXIT_FAILURE);
646 }
647 getCommands();
648 lou_free();
649 exit(EXIT_SUCCESS);
Eitan Isaacson109996e2008-12-20 14:52:53 +0000650}