1 /* -*-C-*-
2 *******************************************************************************
3 *
4 * File: bible.c
5 * RCS: $Header: /home/matthew/cvs/bible-kjv-4.10/bible.c,v 2.7 2008/03/11 20:48:41 matthew Exp $
6 * Description: Write Bible text to stdout.
7 * Author: Chip Chapin, Hewlett Packard Company
8 * Created: Jan 21 1989
9 * Modified: Mon Apr 26 11:11:45 1993 (Chip Chapin) chip@hpclbis
10 * Language: C
11 * Package: Bible Retrieval System
12 * Status: Experimental (Do Not Distribute)
13 *
14 *******************************************************************************
15 *
16 * Revisions:
17 *
18 * Mon Apr 26 11:09:58 1993 (Chip Chapin) chip@hpclbis
19 * Print welcome message when invoked interactively.
20 * Fri Apr 23 12:57:34 1993 (Chip Chapin) chip@hpclbis
21 * Changed fflush( NULL ) to fflush( stdout ) to make SunOS happy.
22 * Thu Apr 22 11:20:56 1993 (Chip Chapin) chip@hpclbis
23 * Support non-POSIX sprintf.
24 * Tue Jan 5 17:10:01 1993 (Chip Chapin) chip@hpclbis
25 * Removed printverse(), might as well call brl_printverse().
26 * get_verse() is now commented out. Nobody uses it anymore.
27 * Allow leading white space on input lines.
28 * Tue Jan 5 10:46:17 1993 (Chip Chapin) chip@hpclbis
29 * Added line formatting to cmd_list output.
30 * Added ?w command.
31 * Mon Jan 4 15:41:26 1993 (Chip Chapin) chip@hpclbis
32 * Added ?or and ?in commands. Some big changes here.
33 * Thu Dec 24 11:04:04 1992 (Chip Chapin) chip@hpclbis
34 * Added prompter function.
35 * Wed Dec 23 13:19:22 1992 (Chip Chapin) chip@hpclbis
36 * Add release version to help output.
37 * Rewrite help text.
38 * Fix bug in command processing "?".
39 * Minor tweaks to eliminate compile warnings.
40 * Mon Dec 21 19:12:30 1992 (Chip Chapin) chip@hpclbis
41 * Added interactive command processing and concordance.
42 *******************************************************************************
43 *
44 * $Log: bible.c,v $
45 * Revision 2.7 2008/03/11 20:48:41 matthew
46 * #include <string.h> (enables compilation on Mac OS) - closes Debian
47 * bug 439735
48 *
49 * Revision 2.6 2005/01/23 11:14:25 matthew
50 * explicit casts
51 *
52 * Revision 2.5 2005/01/22 18:52:48 matthew
53 * No longer write over strings
54 *
55 * Revision 2.4 2005/01/21 18:55:33 matthew
56 * make pretty_print toggling a bit clearer.
57 * Remove unused variables.
58 * add undeclared functions to brl.h
59 * include readline/history.h
60 * make main return
61 *
62 * Revision 2.3 2005/01/21 18:32:25 matthew
63 * Remove #defines to bible.h and include that
64 *
65 * Revision 2.2 2005/01/21 18:24:03 matthew
66 * prototype all functions
67 *
68 * Revision 2.1 2003/01/08 15:50:53 matthew
69 * applied debian patch
70 *
71 * Revision 2.0 2003/01/08 15:29:51 matthew
72 * versions collected from the net
73 *
74 * Revision 1.19 93/04/26 11:17:27 11:17:27 chip (Chip Chapin)
75 * Release 4.00
76 * Public release of portable datafile version.
77 *
78 * Revision 1.18 93/04/23 13:07:58 13:07:58 chip (Chip Chapin)
79 * PORTABILITY RELEASE
80 * This version supports portable data files, usable on machines with
81 * differing native byte-orders.
82 * Also, this version compiles and runs on non-HPUX systems. It has been
83 * tested on SunOS 4.? and ULTRIX 4.?, using SPARC and DEC 3100 hardware
84 * respectively. Note that the data file format has rolled again.
85 *
86 * Revision 1.17 93/01/05 19:03:13 19:03:13 chip (Chip Chapin)
87 * Release 3.00: (not for distribution)
88 * Fixed errors (blank lines) in bible.data file. Data file is not compatible
89 * with previous (1.x and 2.x) distributions. Further changes pending.
90 * Rewrote context handling, and added "<" and ">" commands.
91 * Tools for building brl-index are now part of release.
92 *
93 * Revision 1.16 93/01/05 11:31:34 11:31:34 chip (Chip Chapin)
94 * Release 2.2c: Minor tweaks.
95 *
96 * Revision 1.15 93/01/05 11:19:02 11:19:02 chip (Chip Chapin)
97 * Release 2.2b: Another cmd fix.
98 *
99 * Revision 1.14 93/01/05 11:02:01 11:02:01 chip (Chip Chapin)
100 * Release 2.2a: Fix command bug.
101 *
102 * Revision 1.13 93/01/05 10:49:07 10:49:07 chip (Chip Chapin)
103 * Release 2.2, Added ?w command and line formatting to ?l output.
104 *
105 * Revision 1.12 93/01/04 16:20:55 16:20:55 chip (Chip Chapin)
106 * Release 2.1, implements ?in and ?or commands.
107 *
108 * Revision 1.11 92/12/24 11:09:11 11:09:11 chip (Chip Chapin)
109 * Release 2.04. Include verse ref in prompt line.
110 *
111 * Revision 1.10 92/12/23 14:10:14 14:10:14 chip (Chip Chapin)
112 * Release 2.03: minor tweaks and bug fixes.
113 *
114 * Revision 1.9 92/12/22 18:17:04 18:17:04 chip (Chip Chapin)
115 * Minor tweaks for release 2.02.
116 *
117 * Revision 1.8 92/12/22 11:28:30 11:28:30 chip (Chip Chapin)
118 * Minor release 2.01 -- fix a couple of bugs.
119 *
120 * Revision 1.7 92/12/21 20:00:45 20:00:45 chip (Chip Chapin)
121 * Release 2.0. This release adds the concordance, and some small fixes.
122 *
123 * Revision 1.6 89/10/02 22:19:55 22:19:55 chip (Chip Chapin)
124 * Fix bug in processing "-l 2peter" sorts of things.
125 *
126 * Revision 1.5 89/10/02 14:24:42 14:24:42 chip (Chip Chapin)
127 * Revised usage text.
128 *
129 * Revision 1.4 89/09/14 20:33:35 20:33:35 chip (Chip Chapin)
130 * Release 1-2. Supports -f and -l options for formatting the output.
131 * Updates primarily brl.c, bible.c, and bible.1.
132 *
133 * Revision 1.3 89/09/13 21:48:26 21:48:26 chip (Chip Chapin)
134 * Implement -f and -l options for pretty-printing and linewidth limitation.
135 *
136 * Revision 1.2 89/09/08 09:00:26 09:00:26 chip (Chip Chapin)
137 * Bug fix and simplification: send whole input lines or arguments to BRL,
138 * and let BRL worry about multiple references. We don't care.
139 *
140 * Revision 1.1 89/09/05 17:47:27 17:47:27 chip (Chip Chapin)
141 * Initial revision
142 *
143 */
144
145
146 /*----------------------------------------------------------------------
147 | NAME:
148 | bible.c
149 |
150 | PURPOSE:
151 | Reads verse specs from the command line or from stdin and
152 | writes Bible verses to stdout. Uses the Bible Retrieval
153 | Library for all text access functions.
154 |
155 | FUNCTIONS:
156 | main
157 |
158 | HISTORY:
159 | 890121 cc Initial Creation
160 | 890824 cc Updated to use new brl_verse_text.
161 | 890829 cc Updated to think about buffer size.
162 | 921221 cc See Revision list above for further history...
163 |
164 \*----------------------------------------------------------------------*/
165
166 #include <ctype.h>
167 #include <stdio.h>
168 #include <stdlib.h>
169 #include <string.h>
170 #include <readline/readline.h>
171 #include <readline/history.h>
172 #include "tsl.h"
173 #include "brl.h"
174 #include "version.h"
175 #include "bible.h"
176
177 char help_text[]="\n\
178 -Bible verse specifications:\n\
179 Verses may be specified using various standard abbreviations and \n\
180 notations, including both single verses and verse ranges.\n\
181 E.g. Jn3:16, jn3:16,17 ps1:1-6\n\
182 Partial specs are interpreted in the context of the previous verse.\n\
183 E.g. \"Rev3:20\" followed by \"15\" prints Rev3:15.\n\
184 -Concordance (word search) commands:\n\
185 ??word Find all verses containing \"word\".\n\
186 Creates a \"ref list\" for subsequent use.\n\
187 ?list List the references in ref list. (abbrev ?l)\n\
188 ?view View text of verses in ref list. (abbrev ?v)\n\
189 ?and word Combine ref list w/MATCHING refs for \"word\". (abbrev ?a)\n\
190 ?or word Combine ref list w/ALL refs for \"word\". (abbrev ?o)\n\
191 ?in <verse range> Limit ref list to range of verses.\n\
192 ?in all Reset ref list limit.\n\
193 To get a list of refs, each containing multiple words, start with:\n\
194 ??word for the first word, followed by\n\
195 ?and word for each following word.The order of the words doesn't matter.\n\
196 -A few miscellaneous program control commands.\n\
197 ?, ?h, ?help -- Prints this help text.\n\
198 <, > -- Change direction through text.\n\
199 ?w file -- Begin writing (appending) output to \"file\".\n\
200 ?w -- Stop writing output to a file.\n\
201 ?f -- Toggles output formatting modes.\n\
202 q, ?bye, ?exit, ?quit, ?q -- End this program.\n\
203 Note that a blank line will advance one verse in current direction.\n\
204 ";
205
206
207
do_concordance(char * word,ref_t * buf)208 int do_concordance(char *word,ref_t *buf )
209 /*----------------------------------------------------------------------
210 | NAME:
211 | do_concordance
212 |
213 | ALGORITHM:
214 | Utility/wrapper function for tsl_scan_concordance.
215 | Prints results of search. Called from all concordance
216 | command functions.
217 |
218 | HISTORY:
219 | 930104 cc Initial creation.
220 |
221 \*----------------------------------------------------------------------*/
222 {
223 int cnt;
224 char *ref_word;
225 char range_str[VSPECSZ];
226 char vref1[REFSZ], vref2[REFSZ];
227
228 printf( " Searching for '%s'...", word );
229 if (outf != NULL)
230 fprintf( outf, " Searching for '%s'...", word );
231 fflush( stdout );
232
233 if (inrange_start) {
234 sprintf( range_str, " in %s-%s",
235 brl_num_to_ref(vref1, &inrange_start),
236 brl_num_to_ref(vref2, &inrange_end) );
237 } else {
238 range_str[0] = '\0';
239 }
240
241 if ((cnt=tsl_scan_concordance( word, buf, inrange_start, inrange_end )) == 0) {
242 printf( " not found%s.\n", range_str );
243 if (outf != NULL)
244 fprintf( outf, " not found%s.\n", range_str );
245 } else {
246 if (cnt == 1) ref_word = "ref";
247 else ref_word = "refs";
248 printf( " [%d %s%s]\n", cnt, ref_word, range_str );
249 if (outf != NULL)
250 fprintf( outf, " [%d %s%s]\n", cnt, ref_word, range_str );
251 }
252 return (cnt);
253 } /* do_concordance */
254
255
256
cmd_ANDconcordance(char * word)257 void cmd_ANDconcordance(char *word)
258 /*----------------------------------------------------------------------
259 | NAME:
260 | cmd_ANDconcordance
261 |
262 | ALGORITHM:
263 | Look up a word in the concordance, if found, combine ref list
264 | with current ref list using logical AND.
265 |
266 | HISTORY:
267 | 921218 cc Initial creation.
268 |
269 \*----------------------------------------------------------------------*/
270 {
271 int cnt;
272 int i, j, k;
273 ref_t sbuf[SELECTSZ]; /* List of selected verses */
274 ref_t tbuf[SELECTSZ]; /* temp buff of selected verses */
275
276 if (select_count < 1) {
277 fprintf( stderr, "No references. Use '??word'.\n" );
278 return;
279 }
280 if (*word == '\0') {
281 fprintf( stderr, "To AND-search for a word use '?and word'\n" );
282 return;
283 }
284
285 if ((cnt = do_concordance( word, sbuf )) == 0) return;
286
287 /* AND with existing list */
288 i = j = k = 0;
289 while ((i < select_count) && (j < cnt)) {
290 if (selectbuf[i] == sbuf[j]) {
291 tbuf[k++] = sbuf[j++];
292 i++;
293 }
294 else if (selectbuf[i] > sbuf[j]) j++;
295 else if (selectbuf[i] < sbuf[j]) i++;
296 }
297
298 /* Update global list */
299 select_count = k;
300 for (i=0; i<cnt; i++) selectbuf[i] = tbuf[i];
301 printf( " [%d refs in combined list]\n", select_count );
302 if (outf != NULL)
303 fprintf( outf, " [%d refs in combined list]\n", select_count );
304
305 if (list_always)
306 /* Go ahead and display the refs */
307 cmd_list();
308 } /* cmd_ANDconcordance */
309
310
311
cmd_ORconcordance(char * word)312 void cmd_ORconcordance(char *word)
313 /*----------------------------------------------------------------------
314 | NAME:
315 | cmd_ORconcordance
316 |
317 | ALGORITHM:
318 | Look up a word in the concordance, if found, combine ref list
319 | with current ref list using logical OR.
320 |
321 | HISTORY:
322 | 930104 cc Initial creation.
323 |
324 \*----------------------------------------------------------------------*/
325 {
326 int cnt;
327 int i, j, k;
328 ref_t sbuf[SELECTSZ]; /* List of selected verses */
329 ref_t tbuf[SELECTSZ]; /* temp buff of selected verses */
330
331 if (*word == '\0') {
332 fprintf( stderr, "To OR-search for a word use '?OR word'\n" );
333 return;
334 }
335
336 if ((cnt = do_concordance( word, sbuf )) == 0) return;
337
338 /* OR with existing list (i.e. merge the lists) */
339 i = j = k = 0;
340 while ((i < select_count) && (j < cnt)) {
341 if (selectbuf[i] < sbuf[j]) {
342 tbuf[k++] = selectbuf[i++];
343 } else if (selectbuf[i] == sbuf[j]) {
344 tbuf[k++] = selectbuf[i++];
345 j++;
346 } else if (selectbuf[i] > sbuf[j]) {
347 tbuf[k++] = sbuf[j++];
348 }
349 }
350 /* One of the lists probably has remaining elements.
351 Only ONE of the following loops will execute.
352 */
353 while (i < select_count) {
354 tbuf[k++] = selectbuf[i++];
355 }
356 while (j < cnt) {
357 tbuf[k++] = sbuf[j++];
358 }
359
360 /* Update global list */
361 select_count = k;
362 for (i=0; i<select_count; i++) selectbuf[i] = tbuf[i];
363 printf( " [%d refs in combined list]\n", select_count );
364 if (outf != NULL)
365 fprintf( outf, " [%d refs in combined list]\n", select_count );
366
367 if (list_always)
368 /* Go ahead and display the refs */
369 cmd_list();
370 } /* cmd_ORconcordance */
371
372
373
cmd_concordance(char * word)374 void cmd_concordance(char *word)
375 /*----------------------------------------------------------------------
376 | NAME:
377 | cmd_concordance
378 |
379 | ALGORITHM:
380 | Look up a word in the concordance.
381 |
382 | HISTORY:
383 | 921217 cc Initial creation.
384 |
385 \*----------------------------------------------------------------------*/
386 {
387 if (*word == '\0') {
388 fprintf( stderr, "To search for a word type '??word'\n" );
389 return;
390 }
391
392 select_count = do_concordance( word, selectbuf );
393
394 if (list_always)
395 /* Go ahead and display the refs */
396 cmd_list();
397 } /* cmd_concordance */
398
399
400
cmd_help(void)401 void cmd_help(void)
402 /*----------------------------------------------------------------------
403 | NAME:
404 | cmd_help
405 |
406 | ALGORITHM:
407 | Print Help message for this program.
408 |
409 | HISTORY:
410 | 921217 cc Initial creation.
411 | 921223 cc Added release_version.
412 |
413 \*----------------------------------------------------------------------*/
414
415 {
416 printf( "%s: %s\n", myname, release_version );
417 printf( "%s", help_text );
418 if (outf != NULL) {
419 fprintf( outf, "%s: %s\n", myname, release_version );
420 fprintf( outf, "%s", help_text );
421 }
422 fflush( stdout );
423 } /* cmd_help */
424
425
426
cmd_inrange(char * range)427 void cmd_inrange(char *range)
428 /*----------------------------------------------------------------------
429 | NAME:
430 | cmd_inrange
431 |
432 | ALGORITHM:
433 | Limit concordance ref list to a certain verse range. The
434 | limit range will be applied immediately to modify the
435 | current ref list (if any), and will apply to all
436 | subsequent searches.
437 |
438 | If the specified verse range is "all", then the limits are
439 | removed.
440 |
441 | HISTORY:
442 | 930104 cc Initial creation.
443 |
444 \*----------------------------------------------------------------------*/
445 {
446 ref_t start; /* starting verse */
447 int count; /* number of verses */
448 ref_t tbuf[SELECTSZ]; /* temp buffer */
449 int i;
450 char vref1[REFSZ], vref2[REFSZ];
451
452 if (strcmp(range, "all") == 0) {
453 /* Reset limits */
454 inrange_start = inrange_end = 0;
455 return;
456 }
457 /*Assignment used as truth value*/
458 if ((start = brl_verse_spec( &range, &count ))) {
459 inrange_start = start;
460 inrange_end = start + count -1;
461
462 if (select_count) {
463 /* Edit current ref list */
464 for (count=i=0; i < select_count; i++) {
465 if (selectbuf[i] > inrange_end) break;
466 if (inrange_start <= selectbuf[i]) tbuf[count++]=selectbuf[i];
467 }
468 /* Update global list */
469 select_count = count;
470 for (i=0; i < count; i++) selectbuf[i] = tbuf[i];
471 printf( " [%d refs in range %s-%s]\n", select_count,
472 brl_num_to_ref(vref1, &inrange_start),
473 brl_num_to_ref(vref2, &inrange_end) );
474 if (outf != NULL) {
475 fprintf( outf, " [%d refs in range %s-%s]\n", select_count,
476 brl_num_to_ref(vref1, &inrange_start),
477 brl_num_to_ref(vref2, &inrange_end) );
478 }
479 } else {
480 printf( " [range is %s-%s]\n",
481 brl_num_to_ref(vref1, &inrange_start),
482 brl_num_to_ref(vref2, &inrange_end) );
483 if (outf != NULL) {
484 fprintf( outf, " [range is %s-%s]\n",
485 brl_num_to_ref(vref1, &inrange_start),
486 brl_num_to_ref(vref2, &inrange_end) );
487 }
488 }
489 }
490 } /* cmd_inrange */
491
492
493
cmd_list(void)494 void cmd_list(void)
495 /*----------------------------------------------------------------------
496 | NAME:
497 | cmd_list
498 |
499 | ALGORITHM:
500 | List references found in previous search.
501 | List is formatted using line_width.
502 |
503 | HISTORY:
504 | 921217 cc Initial creation.
505 | 930105 cc Format output into lines.
506 |
507 \*----------------------------------------------------------------------*/
508
509 {
510 char vref[REFSZ]; /* verse ref buffer */
511 int cnt;
512 char lbuf[LINESZ]; /* line buffer */
513 int lcnt; /* count of chars in line */
514 int i;
515
516 if (select_count < 1) {
517 printf( "No references. Use '??word' first.\n" );
518 return;
519 }
520 sprintf( lbuf, " References [%d]: ", select_count );
521 /* Support non-POSIX sprintf */
522 lcnt = strlen(lbuf);
523
524 for (cnt=0; cnt < select_count; cnt++) {
525 brl_num_to_ref(vref, &selectbuf[cnt]);
526 i = strlen(vref);
527 if ((lcnt + i +1)> line_width) {
528 puts( lbuf );
529 if (outf != NULL) {
530 fputs( lbuf, outf );
531 putc( '\n', outf );
532 }
533 lbuf[0] = '\0'; lcnt = 0;
534 } else {
535 strcat( lbuf, " " );
536 lcnt++;
537 }
538 strcat( lbuf, vref );
539 lcnt += i;
540 }
541 puts( lbuf );
542 if (outf != NULL) {
543 fputs( lbuf, outf );
544 putc( '\n', outf );
545 }
546 } /* cmd_list */
547
548
549
cmd_pretty_print(int verbose)550 void cmd_pretty_print(int verbose)
551 /*----------------------------------------------------------------------
552 | NAME:
553 | cmd_pretty_print
554 |
555 | ALGORITHM:
556 | Toggle pretty-printing modes
557 |
558 | HISTORY:
559 | 921217 cc Initial creation.
560 |
561 \*----------------------------------------------------------------------*/
562
563 {
564 char *s;
565 /*invert the pretty_printing setting*/
566 pretty_printing=pretty_printing ? FALSE : TRUE;
567
568 if (pretty_printing) {
569 if (line_width == 0) {
570 /*
571 This forces pretty_printing to be done with a
572 restricted line width. If somebody doesn't like that,
573 they can use "-l999" or something.
574 */
575 if ((s=getenv("COLUMNS")) == NULL)
576 line_width = 79; /* Take a guess. Oh well */
577 else {
578 line_width = atoi(s) -1;
579 if (line_width > LINESZ) line_width = LINESZ -1;
580 }
581 }
582 } else {
583 /* If pretty_printing is being turned off, they probably don't
584 want line breaks either */
585 line_width = 0;
586 }
587 if (verbose) {
588 printf( "Output formatting %s\n", pretty_printing?"ON":"OFF" );
589 if (outf != NULL)
590 fprintf( outf, "Output formatting %s\n", pretty_printing?"ON":"OFF" );
591 }
592 } /* cmd_pretty_print */
593
594
595
cmd_view(void)596 void cmd_view(void)
597 /*----------------------------------------------------------------------
598 | NAME:
599 | cmd_view
600 |
601 | ALGORITHM:
602 | View full text of refs found in previous search.
603 |
604 | HISTORY:
605 | 921217 cc Initial creation.
606 |
607 \*----------------------------------------------------------------------*/
608
609 {
610 char vref[REFSZ];
611 int cnt;
612
613 if (select_count < 1) {
614 fprintf( stderr, "No references. Use '??word' first.\n" );
615 return;
616 }
617 printf( "Viewing References [%d]: \n", select_count );
618 if (outf != NULL)
619 fprintf( outf, "Viewing References [%d]: \n", select_count );
620
621 for (cnt=0; cnt < select_count; cnt++) {
622 /* Print refs without updating current context */
623 brl_num_to_ref( vref, &selectbuf[cnt] );
624 brl_printverse( vref, pretty_printing, line_width, outf );
625 }
626 } /* cmd_view */
627
628
629
cmd_write(char * fname)630 void cmd_write(char *fname)
631 /*----------------------------------------------------------------------
632 | NAME:
633 | cmd_write
634 |
635 | ALGORITHM:
636 | Begin writing a copy of program output to a file. If we
637 | are already writing to a file, then close it, and open a
638 | new one. The file is opened in "append" mode.
639 |
640 | fname -- String with name of file.
641 |
642 | If fname is null then close current file (if any) and
643 | stop writing.
644 |
645 | HISTORY:
646 | 930105 cc Initial creation.
647 |
648 \*----------------------------------------------------------------------*/
649 {
650 if (outf != NULL) {
651 fclose( outf );
652 outf = NULL;
653 printf( "%s: Output file closed.\n", myname );
654 }
655 if (*fname) {
656 if ((outf = fopen( fname, "a" )) == NULL) {
657 fprintf( stderr, "%s: Cannot append to file '%s'\n",
658 myname, fname );
659 }
660 printf( "%s: Writing to %s.\n", myname, fname );
661 }
662 } /* cmd_write */
663
664
665
do_command(char * cmd)666 void do_command(char *cmd)
667 /*----------------------------------------------------------------------
668 | NAME:
669 | do_command
670 |
671 | ALGORITHM:
672 | Handle a control command.
673 | For now, all control commands begin with "?".
674 |
675 | HISTORY:
676 | 921217 cc Initial creation
677 |
678 \*----------------------------------------------------------------------*/
679 {
680 int n;
681 char w[VSPECSZ];
682 char *p;
683
684 /* Convert to lower case */
685 for (p=cmd; *p; p++) {
686 if (isupper((int)*p)) *p =tolower((int)*p);
687 }
688 n=sscanf(cmd, "?%s", w);
689
690 if ((n <= 0) ||
691 /* HELP */
692 (strcmp(w, "") == 0) ||
693 (strcmp(w, "h") == 0) ||
694 (strcmp(w, "help") == 0))
695 {
696 cmd_help();
697 } else if (*w == '?') {
698 /* Concordance (word search) */
699 if (w[1] == '\0') {
700 /* Support "?? word" (with space) */
701 w[0] = '\0'; /* ensure correctness for plain "??" */
702 p = cmd + 2;
703 n=sscanf(p, "%s", w);
704 cmd_concordance( w );
705 } else {
706 cmd_concordance( w+1 );
707 }
708 } else if ((strcmp(w, "a") == 0) ||
709 (strcmp(w, "and") == 0)) {
710 /* "and" word search */
711 p = cmd + strlen(w) +1;
712 n=sscanf(p, "%s", w);
713 cmd_ANDconcordance( w );
714 } else if ((strcmp(w, "f") == 0)) {
715 /* Toggle pretty-print modes */
716 cmd_pretty_print(TRUE);
717 } else if (strcmp(w, "in") == 0) {
718 /* IN -- limit ref list to a verse range */
719 p = cmd + strlen(w) +1;
720 n=sscanf(p, "%s", w);
721 cmd_inrange( w );
722 } else if ((strcmp(w, "l") == 0) ||
723 (strcmp(w, "list") == 0)) {
724 /* LIST refs from previous search */
725 cmd_list();
726 } else if ((strcmp(w, "o") == 0) ||
727 (strcmp(w, "or") == 0)) {
728 /* "or" word search */
729 p = cmd + strlen(w) +1;
730 n=sscanf(p, "%s", w);
731 cmd_ORconcordance( w );
732 } else if ((strcmp(w, "v") == 0) ||
733 (strcmp(w, "view") == 0)) {
734 /* VIEW text of refs from previous search */
735 cmd_view();
736 } else if (*w == 'w') {
737 /* WRITE to a file */
738 if (w[1] == '\0') {
739 /* Support "?w file" (with space) */
740 w[0] = '\0'; /* ensure correctness for plain "?w" */
741 p = cmd + 2;
742 n=sscanf(p, "%s", w);
743 cmd_write( w );
744 } else {
745 /* Support "?wfile" (no space) */
746 cmd_write( w+1 );
747 }
748 } else if ((strcmp(w, "bye") == 0) ||
749 (strcmp(w, "exit") == 0) ||
750 (strcmp(w, "q") == 0) ||
751 (strcmp(w, "quit") == 0)) {
752 /* Let's go home */
753 brl_close();
754 exit( 0 );
755 } else {
756 /* Hmmm... */
757 fprintf( stderr, "%s: Unrecognized command '%s'\n", myname, w);
758 cmd_help();
759 }
760 } /* do_command */
761
762
763
user_input(char * cmd)764 void user_input(char *cmd)
765 /*----------------------------------------------------------------------
766 | NAME:
767 | user_input
768 |
769 | ALGORITHM:
770 | Process a user command.
771 | Commands could be:
772 | 1) A Bible verse spec, e.g. "Jn3:16-18", or even "3"
773 | (context sensitive).
774 | 2) A control command, e.g. "?"
775 |
776 | HISTORY:
777 | 921217 cc Initial creation.
778 |
779 \*----------------------------------------------------------------------*/
780 {
781 char vs[REFSZ];
782
783 get_nonblank(cmd);
784
785 /* Is it a control command?
786 For now, all control commands start with "?". */
787 if (*cmd == '?') {
788 /* Control Command */
789 do_command( cmd );
790 } else if (*cmd == '>' || *cmd == '<' || *cmd == '\0') {
791 if (*cmd == '>') skip_inc = 1;
792 if (*cmd == '<') skip_inc = -1;
793
794 /* Print next verse and update context. */
795 brl_cur_vnum += skip_inc;
796 brl_printverse( brl_num_to_ref(vs, &brl_cur_vnum),
797 pretty_printing, line_width, outf );
798 } else {
799 /* Verse Spec.
800 Print it and update context.
801 */
802 brl_cur_vnum = brl_printverse( cmd, pretty_printing, line_width, outf );
803 }
804 } /* user_input */
805
806
807
getprompt(void)808 char *getprompt(void)
809 /*----------------------------------------------------------------------
810 | NAME:
811 | getprompt
812 |
813 | ALGORITHM:
814 | Get prompt for interactive user.
815 |
816 | HISTORY:
817 | 921224 cc Initial creation.
818 | 020707 dm Change prompter to getprompt for readline.
819 |
820 \*----------------------------------------------------------------------*/
821
822 {
823 char vbuf[REFSZ];
824 static char promptbuf[LINESZ];
825
826 sprintf(promptbuf, "%s(%s) [%s]%s ", myname,
827 brl_textname, brl_num_to_ref(vbuf, &brl_cur_vnum),
828 (skip_inc > 0 ? ">" : "<") );
829 return promptbuf;
830 } /* getprompt */
831
832
833
usage(void)834 void usage(void)
835 /*----------------------------------------------------------------------
836 | NAME:
837 | usage
838 |
839 | ALGORITHM:
840 | Print usage message to stderr, then exit program.
841 |
842 | HISTORY:
843 | 890830 cc Created.
844 | 890912 cc Added -f, -l.
845 | 891002 cc Tinkered with help text.
846 |
847 \*----------------------------------------------------------------------*/
848
849 {
850 fprintf( stderr, "Usage: %s [-f][-l[cols]][-m mem][-p path][-d file][<verse spec>...]\n",
851 myname );
852 fprintf( stderr, "\n\
853 -d file Override default datafile name\n\
854 -f Format the output (implies -l)\n\
855 -l[cols] Set line width (default value: COLUMNS env. variable)\n\
856 -m mem Specify maximum buffer memory usage\n\
857 in Kbytes. Defaults to 1024K.\n\
858 -p path Override default datafile search path.\n\
859 \n" );
860 exit(1);
861 } /* usage */
862
863
864
main(int argc,char ** argv)865 int main(int argc,char **argv)
866 /*----------------------------------------------------------------------
867 | NAME:
868 | main
869 |
870 | ALGORITHM:
871 | Main Program.
872 |
873 | Handle command line options.
874 | Initialize the Bible Retrieval Library.
875 | Read user commands from the command line or from stdin.
876 |
877 | HISTORY:
878 | 890830 cc Added options processing.
879 | 890908 cc Send whole lines to printverse instead of
880 | partially parsing them.
881 | 890912 cc Added -f, -l options.
882 |
883 \*----------------------------------------------------------------------*/
884 {
885 char *line;
886 char *dfname, *dfpath, *s;
887 char ch;
888 char def_verse[]="Gen1:1";
889
890 mem_limit = 1024; /* Default 1024K of buffer space */
891 dfname = dfpath = NULL; /* Use library's default values */
892
893 myname = s = *argv++; argc--; /* Program name */
894 while (*s) {
895 if (*s == '/') myname = s+1;
896 s++;
897 }
898
899 cmd_pretty_print(FALSE); /* Kind of hokey -- this calls turns it on */
900
901 #define ARGVAL() (*++(*argv) || (--argc && *++argv))
902 for (;argc && **argv == '-'; argc--, argv++) {
903 /* Got an option flag */
904 while (*++(*argv)) {
905 /* Process all flags in this argument */
906 switch (**argv) {
907 case 'd':
908 if (!ARGVAL()) {
909 fprintf( stderr, "%s: -d Missing datafile-name\n", myname );
910 usage();
911 }
912 dfname = *argv;
913 goto nextarg;
914 case 'f':
915 cmd_pretty_print(FALSE);
916 break;
917 case 'l':
918 if (isdigit((int)*(*argv+1))) {
919 line_width = atoi(++(*argv));
920 if (line_width > LINESZ) line_width = LINESZ -1;
921 goto nextarg;
922 } else if (--argc
923 && isdigit((int)*(argv[1]))
924 && ((ch= *(argv[1]+1)) == '\0' || isdigit((int)ch))) {
925 line_width = atoi(*++argv);
926 if (line_width > LINESZ) line_width = LINESZ -1;
927 goto nextarg;
928 } else {
929 argc++; /* hack-alert! Fix error from above */
930 /* Set line width to COLUMNS-1. Avoids auto-newline. */
931 if ((s=getenv("COLUMNS")) == NULL)
932 line_width = 79; /* Take a guess. Oh well */
933 else {
934 line_width = atoi(s) -1;
935 if (line_width > LINESZ) line_width = LINESZ -1;
936 }
937 }
938 break;
939 case 'm':
940 if (!ARGVAL() || !isdigit((int)**argv)) {
941 fprintf(stderr, "%s: -m Missing memory-limit\n", myname);
942 usage();
943 }
944 mem_limit = atoi(*argv);
945 goto nextarg;
946 case 'p':
947 if (!ARGVAL()) {
948 fprintf( stderr, "%s: -p Missing path-list\n", myname );
949 usage();
950 }
951 dfpath = *argv;
952 goto nextarg;
953 default:
954 fprintf(stderr, "%s: Unknown flag: '%c'\n", myname, **argv);
955 usage();
956 } /* switch */
957 } /* while */
958 nextarg: continue;
959 } /* for */
960
961 brl_init( dfname, dfpath, mem_limit ); /* Initialize Bible Retrieval Lib */
962
963 if (argc) {
964 /* read from command line */
965 list_always = TRUE;
966 while (argc--) {
967 user_input( *argv++ );
968 }
969 } else {
970 /* read from stdin */
971 printf( "%s: %s\n", myname, release_version );
972 printf( "Hit '?' for help.\n" );
973 rl_bind_key('\t', rl_insert);
974 brl_printverse( def_verse, pretty_printing, line_width, outf );
975 while((line = readline(getprompt())) != NULL) {
976 user_input( line );
977 if (*line != '\0') add_history(line);
978 free(line);
979 }
980 printf( "\n" );
981 }
982
983 brl_close();
984 return(0);
985 } /* main */
986