blob: 150a48561ac3a8b11da0460674eca18954a53f9a [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
272print_brailleIndicator(TranslationTableOffset offset, char *opcode) {
273 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
281print_phraseLength(TranslationTableOffset offset, char *opcode) {
282 if (!offset) return 0;
283 printf("%s %d\n", opcode, offset);
284 return 1;
285}
286
287static int
288show_brailleIndicators(void) {
289 char name[BUFSIZE];
290 char *emphNames[] = { "begemphphrase %s", "endemphphrase %s before",
291 "endemphphrase %s after", "begemphword %s", "endemphword %s", "emphletter %s",
292 "begemph %s", "endemph %s", NULL };
293 char *capsNames[] = { "firstwordcaps", "lastwordcapsbefore", "lastwordcapsafter",
294 "begcaps", "endcaps", "capsletter", "capsword", "capswordstop", NULL };
295
296 // FIXME: update to include all UEB opcodes.
297
298 for (EmphCodeOffset offset = 0; capsNames[offset]; offset++) {
299 print_brailleIndicator(table->emphRules[capsRule][offset], capsNames[offset]);
300 }
301 print_phraseLength(table->emphRules[capsRule][lenPhraseOffset], "lencapsphrase");
302 print_brailleIndicator(table->letterSign, "letsign");
303 print_brailleIndicator(table->numberSign, "numsign");
304
305 for (int i = 0; table->emphClasses[i]; i++) {
306 for (EmphCodeOffset offset = 0; emphNames[offset]; offset++) {
307 snprintf(name, BUFSIZE, emphNames[offset], table->emphClasses[i]);
308 print_brailleIndicator(table->emphRules[emph1Rule][offset], name);
309 }
310 snprintf(name, BUFSIZE, "lenemphphrase %s", table->emphClasses[i]);
311 print_phraseLength(table->emphRules[emph1Rule][lenPhraseOffset], name);
312 }
313 print_brailleIndicator(table->begComp, "begcomp");
314 print_brailleIndicator(table->compBegEmph1, "compbegemph1");
315 print_brailleIndicator(table->compEndEmph1, "compendemph1");
316 print_brailleIndicator(table->compBegEmph2, "compbegemph2");
317 print_brailleIndicator(table->compEndEmph2, "compendemph2");
318 print_brailleIndicator(table->compBegEmph3, "compbegemph3");
319 print_brailleIndicator(table->compEndEmph3, "compendemph3");
320 print_brailleIndicator(table->compCapSign, "compcapsign");
321 print_brailleIndicator(table->compBegCaps, "compbegcaps");
322 print_brailleIndicator(table->compEndCaps, "compendcaps");
323 print_brailleIndicator(table->endComp, "endcomp");
324 return 1;
325}
326
327static char *
328pickYN(int a) {
329 if (!a) return "no";
330 return "yes";
331}
332
333static int
334show_misc(void) {
335 printf("Table size: %d\n", table->tableSize);
336 printf("Bytes used: %d\n", table->bytesUsed);
337 printf("Number of passes: %d\n", table->numPasses);
338 printf("'correct' opcodes: %s\n", pickYN(table->corrections));
339 printf("'syllable' opcodes: %s\n", pickYN(table->syllables));
340 printf("'capsnocont' opcode: %s\n", pickYN(table->capsNoCont));
341 printf("Hyphenation table: %s\n", pickYN(table->hyphenStatesArray));
342 printf("noletsignbefore %s\n",
343 print_chars(&table->noLetsignBefore[0], table->noLetsignBeforeCount));
344 printf("noletsign %s\n", print_chars(&table->noLetsign[0], table->noLetsignCount));
345 printf("noletsignafter %s\n",
346 print_chars(&table->noLetsignAfter[0], table->noLetsignAfterCount));
347 return 1;
348}
349
350static int
351show_charMap(int startHash) {
352 int k;
353 CharOrDots *thisChar;
354 TranslationTableOffset nextChar;
355 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
356 if (startHash < 0)
357 k = 0;
358 else
359 k = startHash;
360 for (; k < HASHNUM; k++)
361 if (table->charToDots[k]) {
362 printf("Hash=%d\n", k);
363 nextChar = table->charToDots[k];
364 while (nextChar) {
365 thisChar = (CharOrDots *)&table->ruleArea[nextChar];
366 printf("Char: %s ", print_chars(&thisChar->lookFor, 1));
367 printf("dots=%s\n", _lou_showDots(&thisChar->found, 1));
368 printf("=> ");
369 getInput();
370 if (*inputBuffer == 'h') break;
371 if (*inputBuffer == 'e') return 1;
372 nextChar = thisChar->next;
373 }
374 }
375 return 1;
376}
377
378static int
379show_dotsMap(int startHash) {
380 int k;
381 CharOrDots *thisDots;
382 TranslationTableOffset nextDots;
383 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
384 if (startHash < 0)
385 k = 0;
386 else
387 k = startHash;
388 for (; k < HASHNUM; k++)
389 if (table->dotsToChar[k]) {
390 printf("Hash=%d\n", k);
391 nextDots = table->dotsToChar[k];
392 while (nextDots) {
393 thisDots = (CharOrDots *)&table->ruleArea[nextDots];
394 printf("Dots: %s ", _lou_showDots(&thisDots->lookFor, 1));
395 printf("char=%s\n", print_chars(&thisDots->found, 1));
396 printf("=> ");
397 getInput();
398 if (*inputBuffer == 'h') break;
399 if (*inputBuffer == 'e') return 1;
400 nextDots = thisDots->next;
401 }
402 }
403 return 1;
404}
405
406static int
407show_compDots(int startChar) {
408 widechar k;
409 printf("Press enter for next or (e)xit, next-(h)ash, then enter\n");
410 if (startChar < 0)
411 k = 0;
412 else
413 k = startChar;
414 for (; k < 256; k++)
415 if (table->compdotsPattern[k]) {
416 TranslationTableRule *thisRule =
417 (TranslationTableRule *)&table->ruleArea[table->compdotsPattern[k]];
418 printf("Char: %s ", print_chars(&k, 1));
419 printf("dots=%s\n",
420 _lou_showDots(&thisRule->charsdots[1], thisRule->dotslen));
421 printf("=> ");
422 getInput();
423 if (*inputBuffer == 'e') return 1;
424 }
425 return 1;
426}
427
428static void
429part_paramLetters(void) {
430 printf("show particular hash chains.\n");
431 printf("show-(f)orward-rules, show-(b)ackward-rules, show-(c)haracters, \n");
432 printf("show-(d)ot-patterns, show-(C)har-to-dots, show-(D)ots-tochar\n");
433 printf("(z)-compdots, (h)elp, e(x)it\n");
434}
435
436static void
437particularHelp(void) {
438 part_paramLetters();
439}
440
441static int
442particular(void) {
443 int startHash;
444 widechar parsed[BUFSIZE];
445 part_paramLetters();
446 do {
447 printf("particular: ");
448 getInput();
449 switch (inputBuffer[0]) {
450 case 0:
451 break;
452 case 'h':
453 particularHelp();
454 break;
455 case 'c':
456 printf("-> ");
457 getInput();
458 if (!_lou_extParseChars(inputBuffer, parsed)) break;
459 startHash = _lou_charHash(*parsed);
460 if (table->characters[startHash] == 0) {
461 printf("Character not in table.\n");
462 break;
463 }
464 show_characters(startHash);
465 break;
466 case 'd':
467 printf("-> ");
468 getInput();
469 if (!_lou_extParseDots(inputBuffer, parsed)) break;
470 startHash = _lou_charHash(*parsed);
471 if (table->dots[startHash] == 0) {
472 printf("Dot pattern not in table.\n");
473 break;
474 }
475 show_dots(startHash);
476 break;
477 case 'C':
478 printf("-> ");
479 getInput();
480 if (!_lou_extParseChars(inputBuffer, parsed)) break;
481 startHash = _lou_charHash(*parsed);
482 if (table->charToDots[startHash] == 0) {
483 printf("Character not in table.\n");
484 break;
485 }
486 show_charMap(startHash);
487 break;
488 case 'D':
489 printf("-> ");
490 getInput();
491 if (!_lou_extParseDots(inputBuffer, parsed)) break;
492 startHash = _lou_charHash(*parsed);
493 if (table->dotsToChar[startHash] == 0) {
494 printf("Dot pattern not in table.\n");
495 break;
496 }
497 show_dotsMap(startHash);
498 break;
499 case 'f':
500 printf("-> ");
501 getInput();
502 if (!_lou_extParseChars(inputBuffer, parsed)) break;
503 startHash = _lou_stringHash(parsed);
504 if (table->forRules[startHash] == 0) {
505 printf("Character string not in table.\n");
506 break;
507 }
508 show_forRules(startHash);
509 break;
510 case 'b':
511 printf("-> ");
512 getInput();
513 if (!_lou_extParseDots(inputBuffer, parsed)) break;
514 startHash = _lou_stringHash(parsed);
515 if (table->backRules[startHash] == 0) {
516 printf("Dot pattern not in table.\n");
517 break;
518 }
519 show_backRules(startHash);
520 break;
521 case 'z':
522 printf("-> ");
523 getInput();
524 if (!_lou_extParseChars(inputBuffer, parsed)) break;
525 startHash = _lou_charHash(*parsed);
526 if (*parsed > 255 || table->compdotsPattern[startHash] == 0) {
527 printf("Character not in table.\n");
528 break;
529 }
530 show_compDots(startHash);
531 break;
532 case 'x':
533 return 1;
534 default:
535 printf("Bad choice.\n");
536 break;
537 }
538 } while (inputBuffer[0] != 'x');
539 return 1;
540}
541
542static void
543paramLetters(void) {
544 printf("Press one of the letters in parentheses, then enter.\n");
545 printf("show-(f)orward-rules, show-(b)ackward-rules, show-(c)haracters, \n");
546 printf("show-(d)ot-patterns, show-(C)har-to-dots, show-(D)ots-tochar\n");
547 printf("show-(m)isc, show-(z)-compdots\n");
548 printf("show-braille(i)ndicators, show-(p)articulars\n");
549 printf("(h)elp, (q)uit\n");
550}
551
552static void
553commandHelp(void) {
554 paramLetters();
555}
556
557static int
558getCommands(void) {
559 paramLetters();
560 do {
561 printf("Command: ");
562 getInput();
563 switch (inputBuffer[0]) {
564 case 0:
565 break;
566 case 'h':
567 commandHelp();
568 break;
569 case 'C':
570 show_charMap(-1);
571 break;
572 case 'D':
573 show_dotsMap(-1);
574 break;
575 case 'z':
576 show_compDots(-1);
577 break;
578 case 'c':
579 show_characters(-1);
580 break;
581 case 'd':
582 show_dots(-1);
583 break;
584 case 'f':
585 show_forRules(-1);
586 break;
587 case 'b':
588 show_backRules(-1);
589 break;
590 case 'i':
591 show_brailleIndicators();
592 break;
593 case 'm':
594 show_misc();
595 break;
596 case 'p':
597 particular();
598 break;
599 case 'q':
600 return 1;
601 default:
602 printf("Bad choice.\n");
603 break;
604 }
605 } while (inputBuffer[0] != 'q');
606 return 1;
Eitan Isaacson109996e2008-12-20 14:52:53 +0000607}
608
609int
Bert Frees92a80352017-09-30 23:01:02 +0200610main(int argc, char **argv) {
611 int optc;
Christian Eglibe149002009-10-09 09:09:07 +0000612
Bert Frees92a80352017-09-30 23:01:02 +0200613 set_program_name(argv[0]);
Christian Eglibe149002009-10-09 09:09:07 +0000614
Bert Frees92a80352017-09-30 23:01:02 +0200615 while ((optc = getopt_long(argc, argv, "hv", longopts, NULL)) != -1) switch (optc) {
616 /* --help and --version exit immediately, per GNU coding standards. */
617 case 'v':
618 version_etc(
619 stdout, program_name, PACKAGE_NAME, VERSION, AUTHORS, (char *)NULL);
620 exit(EXIT_SUCCESS);
621 break;
622 case 'h':
623 print_help();
624 exit(EXIT_SUCCESS);
625 break;
626 default:
627 fprintf(stderr, "Try `%s --help' for more information.\n", program_name);
628 exit(EXIT_FAILURE);
629 break;
630 }
Christian Eglibe149002009-10-09 09:09:07 +0000631
Bert Frees92a80352017-09-30 23:01:02 +0200632 if (optind != argc - 1) {
633 /* Print error message and exit. */
634 if (optind < argc - 1)
635 fprintf(stderr, "%s: extra operand: %s\n", program_name, argv[optind + 1]);
636 else
637 fprintf(stderr, "%s: no table specified\n", program_name);
638 fprintf(stderr, "Try `%s --help' for more information.\n", program_name);
639 exit(EXIT_FAILURE);
640 }
Christian Eglibe149002009-10-09 09:09:07 +0000641
Bert Frees92a80352017-09-30 23:01:02 +0200642 if (!(table = lou_getTable(argv[optind]))) {
643 lou_free();
644 exit(EXIT_FAILURE);
645 }
646 getCommands();
647 lou_free();
648 exit(EXIT_SUCCESS);
Eitan Isaacson109996e2008-12-20 14:52:53 +0000649}