home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume04 / sp2 < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  31.6 KB

  1. From decwrl!labrea!agate!pasteur!ames!mailrus!cwjcc!hal!ncoast!allbery Sat Oct 22 16:52:06 PDT 1988
  2. Article 675 of comp.sources.misc:
  3. Path: granite!decwrl!labrea!agate!pasteur!ames!mailrus!cwjcc!hal!ncoast!allbery
  4. From: predict%charon.unm.edu@ariel.unm.edu (Andrew R. Large)
  5. Newsgroups: comp.sources.misc
  6. Subject: v04i133: visual spelling checker
  7. Message-ID: <5794.8810210202@charon.unm.edu>
  8. Date: 22 Oct 88 01:35:06 GMT
  9. Sender: allbery@ncoast.UUCP
  10. Reply-To: predict%charon.unm.edu@ariel.unm.edu (Andrew R. Large)
  11. Lines: 1211
  12. Approved: allbery@ncoast.UUCP
  13.  
  14. Posting-number: Volume 4, Issue 133
  15. Submitted-by: "Andrew R. Large" <predict%charon.unm.edu@ariel.unm.edu>
  16. Archive-name: sp2
  17.  
  18. Here is a newer version of my visual spelling checker.  Added an ifdef for SYSV
  19. compatibility (don't define BSD in the Makefile).  Also fixed a bug:  When you
  20. (used to) exit a document without looking at all the words, null strings were
  21. passes to ex.  Could have wierd effects.  I also re-organized the code based on
  22. my current programming techniques.
  23.  
  24.  
  25.  -=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
  26.    *                          Andrew R. Large                              *
  27.   **  (work) 505/255-8611 ------|     Univ of New Mexico EECE Department   **
  28.  ***  (home) 505/888-4010       |---> Management Sciences, Inc. [MSI]      ***
  29. ****                            _Babooshka!_                               ****
  30.  ***  Usenet: {convex,gatech,ucbvax,csu-cs,anl-mcs}!unmvax!charon!predict  ***
  31.   **  Internet: predict@charon.UNM.EDU                                     **
  32.    *          If I am quoted, my employers will deny my existence.         *
  33.  -=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
  34.  
  35. #!/bin/sh
  36. # shar:    Shell Archiver
  37. #    Run the following text with /bin/sh to create:
  38. #    sp
  39. # This archive created: Thu Oct 20 19:42:29 1988
  40. # By:    Andrew R. Large (Management Sciences, Inc.)
  41. echo shar: creating directory sp
  42. mkdir sp
  43. cd sp
  44. echo shar: extracting Makefile '(599 characters)'
  45. sed 's/^XX//' << \SHAR_EOF > Makefile
  46. XX#! /bin/sh
  47. XX#
  48. XX# Makefile for sp
  49. XX# Written by Andrew Large
  50. XX#
  51. XX# Edit BIN, MAN, CC and CFLAGS
  52. XX#
  53. XX
  54. XXBIN = /u1/staff/andy/bin
  55. XXMAN = /u1/staff/andy/man
  56. XX
  57. XXEXEC = sp
  58. XXMANPAGE = $(EXEC).1
  59. XXHDRS = $(EXEC).h
  60. XX
  61. XXOBJS = $(EXEC).o add_local.o doc_correct.o externs.o parse.o spell.o tools.o\
  62. XX    user_input.o user_tools.o
  63. XXLIBS = -lcurses -ltermlib
  64. XXCC = cc
  65. XX
  66. XX#
  67. XX# If you are a BSD system, then BSD
  68. XX# CFLAGS = -O
  69. XXCFLAGS = -O -DBSD
  70. XX
  71. XX$(EXEC): $(OBJS)
  72. XX    $(CC) $(CFLAGS) $(OBJS) -o $@ $(LIBS)
  73. XX
  74. XXinstall: $(EXEC)
  75. XX    strip $(EXEC)
  76. XX    cp $(EXEC) $(BIN)
  77. XX    cp $(MANPAGE) $(MAN)/man1
  78. XX
  79. XX$(OBJS): $(HDRS)
  80. XX
  81. XXclean:
  82. XX    /bin/rm -f $(EXEC) core *.o *.out
  83. SHAR_EOF
  84. if test 599 -ne "`wc -c Makefile`"
  85. then
  86. echo shar: error transmitting Makefile '(should have been 599 characters)'
  87. fi
  88. echo shar: extracting README '(1681 characters)'
  89. sed 's/^XX//' << \SHAR_EOF > README
  90. XX** SP **
  91. XX
  92. XXSp is a visual spelling program that is based upon existing UN*X utilites.
  93. XXIt may be run on one or more files, and for each file, it presents a
  94. XXword-by-word list of the words received from spell(1).  You may then take
  95. XXany of a host of actions.
  96. XX
  97. XXThis program has come through many stages during its development.  When it was
  98. XXoriginally written, it was designed around a shell script posted in net.sources
  99. XXin 1985 that put all misspelled words into a file, had you correct the file,
  100. XXand then, from the difference between the files, made the corrections.
  101. XX
  102. XXThe current version is so different from the original shell script that I don't
  103. XXcredit the original authors any more.  After completing this program, I have
  104. XXnoticed a resemblance to both `ispell' and `correct'.  However, this was written
  105. XXbefore I ever saw either of those programs, and no code was taken from either
  106. XXone when writing this.
  107. XX
  108. XXTo install:
  109. XX
  110. XX    1) Edit `sp.h' to reflect your current situation (mainly locations
  111. XX    of system programs).
  112. XX
  113. XX    2) Edit Makefile and change `BIN', `MAN', `CC', and `CFLAGS' to
  114. XX    their proper values.
  115. XX
  116. XX    3) Type `make'.
  117. XX
  118. XX    4) If everything test out ok, type `make install'.
  119. XX
  120. XXCopyright (C) 1988 Andrew Large
  121. XX
  122. XXThis software may be used and/or modified on any machine by anyone, as long
  123. XXas you don't violate the following conditions:
  124. XX
  125. XX    1) This copyright notice and the one in the program are left intact.
  126. XX
  127. XX    2) You credit me with original authorship.
  128. XX
  129. XX    3) No monetary gain is made by selling or distributing this software.
  130. XX
  131. XXI will be more than willing to try and support any additions/bug-fixes, but I
  132. XXWILL NOT ACCEPT RESPONSIBILITY FOR ANY HARM CAUSED DIRECTLY OR INDIRECTLY BY
  133. XXTHIS PROGRAM.
  134. SHAR_EOF
  135. if test 1681 -ne "`wc -c README`"
  136. then
  137. echo shar: error transmitting README '(should have been 1681 characters)'
  138. fi
  139. echo shar: extracting parse.c '(1264 characters)'
  140. sed 's/^XX//' << \SHAR_EOF > parse.c
  141. XX# include    "sp.h"
  142. XX
  143. XX/*
  144. XX** parse
  145. XX** Parse input for -d option and establish whether
  146. XX** or not a personal dictionary exists
  147. XX*/
  148. XXparse (argc, argv, place)
  149. XXint    argc, *place;
  150. XXchar    *argv[];
  151. XX{
  152. XX    extern    char    *optarg, *local_dict;
  153. XX    extern    int    optind;
  154. XX    extern    boolean    local;
  155. XX    char    *getenv (), getopt ();
  156. XX    int    option;
  157. XX
  158. XX    if (argc < 2) usage (argv[0]);
  159. XX
  160. XX    local = False;
  161. XX    while ((option = getopt (argc, argv, "d:")) != EOF)
  162. XX        switch (option) {
  163. XX            case 'd':
  164. XX                local_dict =
  165. XX                    sfalloc ((unsigned) strlen (optarg) + 1);
  166. XX                strcpy (local_dict, optarg);
  167. XX                local = True;
  168. XX                break;
  169. XX            case '?':
  170. XX            default:
  171. XX                usage (argv[0]);
  172. XX        }
  173. XX
  174. XX    if (argv[optind] == NULL)
  175. XX        usage (argv[0]);
  176. XX
  177. XX    if (!local)
  178. XX        if (getenv ("DICT") != NULL)
  179. XX            local_dict = getenv ("DICT");
  180. XX        else
  181. XX            local_dict = "./spelldict";
  182. XX
  183. XX    switch (check_dict ()) {
  184. XX        case 1:
  185. XX            local = True;
  186. XX            break;
  187. XX        case 0:
  188. XX            local = False;
  189. XX            printf ("\nYour local dictionary %s does not exist.",
  190. XX                local_dict);
  191. XX            printf ("\nI may try to create it later ...");
  192. XX            fflush (stdout);
  193. XX            sleep (1);
  194. XX            break;
  195. XX        case -1:
  196. XX            local = False;
  197. XX            printf ("\nYour local dictionary %s is not readable.",
  198. XX                local_dict);
  199. XX            printf ("\nI may try to write to it later ...");
  200. XX            fflush (stdout);
  201. XX            sleep (1);
  202. XX            break;
  203. XX    }
  204. XX    *place = optind;
  205. XX}
  206. SHAR_EOF
  207. if test 1264 -ne "`wc -c parse.c`"
  208. then
  209. echo shar: error transmitting parse.c '(should have been 1264 characters)'
  210. fi
  211. echo shar: extracting sp.1 '(3724 characters)'
  212. sed 's/^XX//' << \SHAR_EOF > sp.1
  213. XX.\"
  214. XX.\" Copyright (C) 1988 Andrew Large
  215. XX.\"
  216. XX.TH SP 1 "Version 3.5"
  217. XX.DA 17 October 1988
  218. XX.SH NAME
  219. XXsp \- check spelling of a document and fix any mistakes
  220. XX.SH SYNOPSIS
  221. XX.B sp
  222. XX[
  223. XX.B \-d
  224. XX.B dictionary
  225. XX]
  226. XX.B file
  227. XX[
  228. XX.B file2
  229. XX.B ...
  230. XX]
  231. XX.SH DESCRIPTION
  232. XX.IR sp
  233. XXcalls spell(1) to check the spelling of a document.  If you specify a
  234. XXpersonal dictionary (with the \-d option), this is searched in addition
  235. XXto the system dictionary for proper spellings of words.  If you do not
  236. XXspecify a personal dictionary,
  237. XX.IR sp
  238. XXchecks for an environment variable called DICT.  If it exists, it is taken
  239. XXto be the full path to your personal dictionary.  If you do not
  240. XXspecify a personal dictionary or have $DICT defined, the file ``spelldict''
  241. XXin your current directory will be established as your personal dictionary.
  242. XX.PP
  243. XXOnce the mis-spelled words are identified, you are prompted word by
  244. XXword for an action to take.  Your choices are given in brackets and
  245. XXexplained below.
  246. XX.IP A
  247. XXMark the word for addition to your personal dictionary.
  248. XX.IP C
  249. XXMark the word for correction.  You will be asked for the correct spelling.
  250. XX.IP I
  251. XXIgnore the word in question.  This is the default option and is
  252. XXgenerally used when a word is spelled correctly for its usage, but
  253. XXyou don't want it added to your personal dictionary.
  254. XX.IP L
  255. XXLook up a string in the system dictionary.  This is appropriate for
  256. XXobtaining the proper spelling of the word.  You will be prompted for a string
  257. XXthat look(1) will use on the system dictionary.
  258. XX.IP W
  259. XXShow where the word occurs in the document.  Runs grep(1) on the document
  260. XXfile searching for occurrences of the word and prints out lines that
  261. XXcontain the word.
  262. XX.IP ^
  263. XXGo to previous document (given on command line).  If your current document
  264. XXis the first given on the command line, this will re-run spell(1) on your
  265. XXcurrent document.  If you have marked any words for correction or
  266. XXaddition to your personal dictionary, you will be
  267. XXasked whether or not you want to save your changes.
  268. XX.IP #
  269. XXGo to next document (given on command line).  If your current document is
  270. XXthe last given on the command line, this exits the program.  If you
  271. XXhave marked any words for correction or addition to your personal
  272. XXdictionary, you will be asked whether or not you want to save your changes.
  273. XX.IP +
  274. XXGo to next word.  If you haven't taken action with the current word, this
  275. XXoption is equivalent to an ignore (don't correct or add to personal
  276. XXdictionary).  Otherwise, previous actions hold true, i.e. if you correct
  277. XXa word, hit a '-' to go back to it, and hit a '+' to skip forward past it,
  278. XXthe correction would still be the course taken.  However, if you hit an
  279. XX'I' to skip forward past it, no correction would take place.
  280. XX.IP -
  281. XXGo to previous word.  This is the course of action to take if you
  282. XXmess up a correction or change your mind in some way.
  283. XX.IP ?
  284. XXThis will display a short help menu.
  285. XX.IP ^L
  286. XXThis will redraw the screen (as in vi(1)).
  287. XX.PP
  288. XXAfter you have processed all the words, you are prompted for an
  289. XXadditional action.  You may go to either the previous or the next document.
  290. XXIn either case, you will be asked whether or not you wish to save your changes.
  291. XXIn this manner, you can make corrections to a file, and then back up to check
  292. XXyour corrections.  Corrections are made to the documents via
  293. XX.B ex(1).
  294. XX.PP
  295. XXThe spelling checking is done one file at a time, so if you have the same
  296. XXmis-spelled word in several files, you will have to correct it for each file.
  297. XXHowever, the personal dictionary is updated between the checks on each file,
  298. XXso additions to it will be available when the next file is checked.
  299. XX.SH AUTHOR
  300. XXAndrew Large
  301. XX.SH FILES
  302. XX.nf
  303. XX$DICT, spelldict -- default personal dictionaries
  304. XX.fi
  305. XX.SH "SEE ALSO"
  306. XXex(1), grep(1), look(1), spell(1)
  307. SHAR_EOF
  308. if test 3724 -ne "`wc -c sp.1`"
  309. then
  310. echo shar: error transmitting sp.1 '(should have been 3724 characters)'
  311. fi
  312. echo shar: extracting sp.c '(1416 characters)'
  313. sed 's/^XX//' << \SHAR_EOF > sp.c
  314. XX# include    "sp.h"
  315. XX
  316. XX/*
  317. XX** sp main program
  318. XX** Uses spell(1) to check the spelling of a document.
  319. XX** The user is prompted with each of the mis-spelled words and
  320. XX** can ignore them, add them to a personal dictionary, correct
  321. XX** them, look up words in the dictionary, or find out where in
  322. XX** the file the word is found.  Corrections are made to the
  323. XX** document via ex(1).
  324. XX**
  325. XX** Author: Andrew Large
  326. XX**    December 1986    (First Edition)
  327. XX**    October 1988    (Current Version)
  328. XX*/
  329. XX
  330. XXmain (argc, argv)
  331. XXint    argc;
  332. XXchar    *argv[];
  333. XX{
  334. XX    extern    int    exit_val;
  335. XX    extern    char    *spell_doc;
  336. XX    int    spell_val, start_pos;
  337. XX    register int    pos;
  338. XX
  339. XX    /*
  340. XX    ** Parse input arguments and initialize
  341. XX    ** curses and signals
  342. XX    */
  343. XX    parse (argc, argv, &start_pos);
  344. XX    init ();
  345. XX
  346. XX    /*
  347. XX    ** Main loop.  Keep going until user leaves the last document.
  348. XX    */
  349. XX    pos = start_pos;
  350. XX    while (pos < argc) {
  351. XX        reset_data ();        /* Clean lists and reset globals */
  352. XX        spell_doc = argv[pos];
  353. XX
  354. XX        if ( (spell_val = spell ()) >= 0 ) {
  355. XX            switch (user_input ()) {
  356. XX                case -1:    /* previous doc, save */
  357. XX                    rest_ignore ();
  358. XX                    save (spell_val);
  359. XX                case -2:    /* previous doc, no save */
  360. XX                    if (pos > start_pos) --pos;
  361. XX                    break;
  362. XX                case 0:        /* normal exit with save */
  363. XX                case 1:        /* early exit with save */
  364. XX                    rest_ignore ();
  365. XX                    save (spell_val);
  366. XX                case 2:        /* early exit, no save */
  367. XX                default:
  368. XX                    ++pos;
  369. XX                    break;
  370. XX            }
  371. XX        }
  372. XX        else {
  373. XX            ++pos;
  374. XX            exit_val = Error;
  375. XX        }
  376. XX    }
  377. XX    leave ();
  378. XX}
  379. SHAR_EOF
  380. if test 1416 -ne "`wc -c sp.c`"
  381. then
  382. echo shar: error transmitting sp.c '(should have been 1416 characters)'
  383. fi
  384. echo shar: extracting spell.c '(2016 characters)'
  385. sed 's/^XX//' << \SHAR_EOF > spell.c
  386. XX# include    "sp.h"
  387. XX
  388. XX/*
  389. XX** spell
  390. XX** Run spell(1) on the file and check personal dictionary also.
  391. XX** Establishes the original list of mis-spelled words
  392. XX*/
  393. XXspell () {
  394. XX    extern    char    *bad_words[], *spell_doc, *local_dict;
  395. XX    extern    int    num_bad;
  396. XX    extern    boolean    local;
  397. XX    FILE    *popen (), *fopen (), *spell_out;
  398. XX    char    command[256];
  399. XX    int    ypos, xpos, ret_val;
  400. XX    register int    i;
  401. XX
  402. XX    clear (); fname ();
  403. XX
  404. XX    if (access (spell_doc, 0) != 0) {    /* Check for existence */
  405. XX        sprintf (command, "Cannot access file %s!", spell_doc);
  406. XX        message (True, command);
  407. XX        return (-1);
  408. XX    }
  409. XX
  410. XX    ret_val = 0;
  411. XX    if (access (spell_doc, 6) != 0) {        /* Read and write */
  412. XX        if (access (spell_doc, 4) != 0) {    /* Read */
  413. XX            sprintf (command, "You are unable to read %s!",
  414. XX                spell_doc);
  415. XX            message (True, command);
  416. XX            return (-1);
  417. XX        }
  418. XX        mvaddstr (3, 0, "You are unable to write to this file");
  419. XX        mvaddstr (4, 0, "I will check spelling, but you will not be ");
  420. XX        addstr ("able to save any corrections");
  421. XX        ret_val = 1;
  422. XX        move (0,0); refresh (); sleep (3); fname ();
  423. XX    }
  424. XX
  425. XX    mvaddstr (3,0, "Checking spelling ..."); refresh ();
  426. XX
  427. XX    /*
  428. XX    ** Get the list of mis-spelled words
  429. XX    */
  430. XX    if (local)
  431. XX        sprintf (command, "%s %s | %s -v -f %s", SPELL, spell_doc,
  432. XX            FGREP, local_dict);
  433. XX    else
  434. XX        sprintf (command, "%s %s", SPELL, spell_doc);
  435. XX
  436. XX    spell_out = popen (command, "r");
  437. XX
  438. XX    for (i = 0; i < MAX_WORDS; i++) {
  439. XX        bad_words[i] = sfalloc ((unsigned) MAX_WORD_LEN);
  440. XX        if (fgets (bad_words[i], MAX_WORD_LEN, spell_out) == NULL)
  441. XX            break;
  442. XX        else
  443. XX            bad_words[i][strlen (bad_words[i]) - 1] = '\0';
  444. XX    }
  445. XX    fclose (spell_out);
  446. XX
  447. XX    if ((num_bad = i) >= MAX_WORDS) {
  448. XX        getyx (stdscr, ypos, xpos);
  449. XX        sprintf (command, "You have more than %d mis-spelled words.",
  450. XX            MAX_WORDS);
  451. XX        mvaddstr (5, 10, command);
  452. XX        strcpy (command, "Run this again after corrections are made.");
  453. XX        mvaddstr (6, 10, command);
  454. XX        move (ypos, xpos); refresh (); sleep (2);
  455. XX    }
  456. XX
  457. XX    addstr (" done"); refresh ();
  458. XX
  459. XX    if (num_bad <= 0) {
  460. XX        mvaddstr (5,0, "No spelling errors.");
  461. XX        move (0,0); refresh (); sleep (1);
  462. XX    }
  463. XX    return (ret_val);
  464. XX}
  465. SHAR_EOF
  466. if test 2016 -ne "`wc -c spell.c`"
  467. then
  468. echo shar: error transmitting spell.c '(should have been 2016 characters)'
  469. fi
  470. echo shar: extracting user_input.c '(2007 characters)'
  471. sed 's/^XX//' << \SHAR_EOF > user_input.c
  472. XX# include    "sp.h"
  473. XX
  474. XX/*
  475. XX** user_input -- user interface for correcting mis-spelled words
  476. XX*/
  477. XXuser_input () {
  478. XX    extern    char    *bad_words[], *good_words[];
  479. XX    extern    int    num_bad;
  480. XX    char    string[MAX_WORD_LEN];
  481. XX    boolean    done;
  482. XX    register int    loop;
  483. XX
  484. XX    for (loop = 0; loop < num_bad; loop++) {
  485. XX        page_clear (loop + 1, False);
  486. XX        sprintf (string, "Word ``%s'' is not in the dictionary",
  487. XX            bad_words[loop]);
  488. XX        mvaddstr (3, 0, string); refresh ();
  489. XX
  490. XX        done = False;
  491. XX        do {
  492. XX            sprintf (string, "(%s) [ilwac^#+-?] ", bad_words[loop]);
  493. XX            mvaddstr (5, 0, string); refresh ();
  494. XX
  495. XX            switch (getch ()) {
  496. XX                case 'I':
  497. XX                case 'i':
  498. XX                case ' ':
  499. XX                case '\n':
  500. XX                case '\r':
  501. XX                    addstr ("Ignore"); refresh ();
  502. XX                    done = True; ignore (loop);
  503. XX                    break;
  504. XX                case 'L':
  505. XX                case 'l':
  506. XX                    addstr ("Lookup"); refresh ();
  507. XX                    lookup (loop);
  508. XX                    break;
  509. XX                case 'W':
  510. XX                case 'w':
  511. XX                    addstr ("Where"); refresh ();
  512. XX                    where (loop);
  513. XX                    break;
  514. XX                case 'A':
  515. XX                case 'a':
  516. XX                    addstr ("Add"); refresh ();
  517. XX                    done = True; add (loop);
  518. XX                    break;
  519. XX                case 'C':
  520. XX                case 'c':
  521. XX                    addstr ("Correct"); refresh ();
  522. XX                    done = True; word_correct (loop);
  523. XX                    break;
  524. XX                case '^':
  525. XX                    addstr ("Previous Document");
  526. XX                    refresh ();
  527. XX                    if (ask_save (loop) == 1)
  528. XX                        return (-1);
  529. XX                    else
  530. XX                        return (-2);
  531. XX                case '#':
  532. XX                    addstr ("Next Document");
  533. XX                    refresh ();
  534. XX                    if (ask_save (loop) == 1)
  535. XX                        return (1);
  536. XX                    else
  537. XX                        return (2);
  538. XX                case '+':
  539. XX                    addstr ("Next Word");
  540. XX                    refresh ();
  541. XX                    done = True;
  542. XX                    if (good_words[loop] == NULL)
  543. XX                        ignore (loop);
  544. XX                    break;
  545. XX                case '-':
  546. XX                    addstr ("Previous Word");
  547. XX                    refresh ();
  548. XX                    done = True;
  549. XX                    if (loop > 0) loop -=2;
  550. XX                    else --loop;
  551. XX                    break;
  552. XX                case 'H':
  553. XX                case 'h':
  554. XX                case '?':
  555. XX                    addstr ("Help!"); refresh ();
  556. XX                    help (loop);
  557. XX                    break;
  558. XX                case CTRL_L:
  559. XX                case CTRL_R:
  560. XX                    page_clear (loop + 1, True);
  561. XX                    break;
  562. XX                default:
  563. XX                    page_clear (loop + 1, False);
  564. XX                    break;
  565. XX            }
  566. XX        } while (!done);
  567. XX    }
  568. XX    return (ask_action ());
  569. XX}
  570. SHAR_EOF
  571. if test 2007 -ne "`wc -c user_input.c`"
  572. then
  573. echo shar: error transmitting user_input.c '(should have been 2007 characters)'
  574. fi
  575. echo shar: extracting MANIFEST '(729 characters)'
  576. sed 's/^XX//' << \SHAR_EOF > MANIFEST
  577. XXFile        Explanation
  578. XX------------------------------------------------------------------------------
  579. XXMANIFEST    This file -- list of files in package
  580. XXMakefile    For compiling ``sp''.
  581. XXREADME        Read this first for installation and copyright information
  582. XXadd_local.c    Routine for adding words to personal dictionary
  583. XXdoc_correct.c    Routine for correcting the document
  584. XXexterns.c    Declarations of global data structures
  585. XXparse.c        Command line parser (uses getopt)
  586. XXsp.1        Manual page
  587. XXsp.c        Main program
  588. XXsp.h        Include file (may need editing)
  589. XXspell.c        Runs spell(1) and fgrep(1) to get initial mis-spelling list
  590. XXtools.c        General tools used througout program
  591. XXuser_input.c    Get user input for corrections
  592. XXuser_tools.c    Process option selected in user_input
  593. SHAR_EOF
  594. if test 729 -ne "`wc -c MANIFEST`"
  595. then
  596. echo shar: error transmitting MANIFEST '(should have been 729 characters)'
  597. fi
  598. echo shar: extracting tools.c '(4218 characters)'
  599. sed 's/^XX//' << \SHAR_EOF > tools.c
  600. XX# include    "sp.h"
  601. XX# include    <signal.h>
  602. XX
  603. XX
  604. XX/*
  605. XX** ask_more
  606. XX** Prompt the user to continue.
  607. XX*/
  608. XXask_more () {
  609. XX    standout ();
  610. XX    mvaddstr (23, 29, "Hit any key to continue");
  611. XX    standend ();
  612. XX    refresh (); getch ();
  613. XX}
  614. XX
  615. XX
  616. XX/*
  617. XX** check_dict
  618. XX** Check for existence/read permission on dictionary.
  619. XX*/
  620. XXcheck_dict () {
  621. XX    extern    char    *local_dict;
  622. XX
  623. XX    if ( access (local_dict, 4) == 0 )        /* Read permission */
  624. XX        return (1);
  625. XX    else
  626. XX        if ( access (local_dict, 0) != 0 )    /* Existence check */
  627. XX            return (0);
  628. XX        else
  629. XX            return (-1);
  630. XX}
  631. XX
  632. XX
  633. XX/*
  634. XX** curse_die
  635. XX** Die with an explanation when inside of curses
  636. XX*/
  637. XXcurse_die (string)
  638. XXchar    *string;
  639. XX{
  640. XX    extern    int    errno, exit_val;
  641. XX    extern    char    *sys_errlist[];
  642. XX    char    line[256];
  643. XX
  644. XX    sprintf (line, "Fatal Error, %s:%s", string, sys_errlist[errno]);
  645. XX    message (True, line);
  646. XX    exit_val = Error; leave ();
  647. XX}
  648. XX
  649. XX
  650. XX/*
  651. XX** fname
  652. XX** Print out the page header (file name, etc.)
  653. XX*/
  654. XXfname () {
  655. XX    extern    char    *spell_doc;
  656. XX    erase ();
  657. XX    mvaddstr (0, (65 - strlen (spell_doc)) / 2, /* (80-overhead-len) / 2 */
  658. XX        "[ --- ");
  659. XX    standout ();
  660. XX    addch (' '); addstr (spell_doc); addch (' ');
  661. XX    standend ();
  662. XX    addstr (" --- ]");
  663. XX}
  664. XX
  665. XX
  666. XX/*
  667. XX** init
  668. XX** Initialize the screen and take care of nasty signals
  669. XX*/
  670. XXinit () {
  671. XX    extern    char    *bad_words[], *good_words[], *add_words[];
  672. XX    register int    i;
  673. XX
  674. XX    for (i=0; i < MAX_WORDS; i++) {
  675. XX        bad_words[i] = good_words[i] = add_words[i] = NULL;
  676. XX    }
  677. XX
  678. XX    signal (SIGINT, leave); signal (SIGQUIT, leave);
  679. XX
  680. XX    initscr (); crmode (); noecho ();
  681. XX
  682. XX    mvaddstr ( 9,30, VERSION1);
  683. XX    mvaddstr (10,28, VERSION2);
  684. XX    mvaddstr (11,31, VERSION3);
  685. XX
  686. XX    move (0,0); refresh ();
  687. XX}
  688. XX
  689. XX
  690. XX/*
  691. XX** leave
  692. XX** Clean up curses and exit.
  693. XX*/
  694. XXvoid    leave () {
  695. XX    extern    char    *tmp_file;
  696. XX    extern    int    exit_val;
  697. XX
  698. XX    unlink (tmp_file);
  699. XX    clear (); move (23,0); refresh (); endwin ();
  700. XX    exit (exit_val);
  701. XX}
  702. XX
  703. XX
  704. XX/*
  705. XX** message
  706. XX** Write message on the screen
  707. XX*/
  708. XXmessage (error, line)
  709. XXboolean    error;
  710. XXchar    *line;
  711. XX{
  712. XX    page_clear (0, False);
  713. XX
  714. XX    if (error) {
  715. XX        addch ('\07');
  716. XX        mvaddstr (3, (78 - strlen (line)) / 2, line);
  717. XX        move (0,0);
  718. XX        refresh (); sleep (2);
  719. XX    }
  720. XX    else {
  721. XX        mvaddstr (3, (78 - strlen (line)) / 2, line);
  722. XX        refresh (); sleep (1);
  723. XX    }
  724. XX}
  725. XX
  726. XX
  727. XX/*
  728. XX** page_clear
  729. XX** Clear part of the screen and display the number
  730. XX** of the current word
  731. XX*/
  732. XXpage_clear (word_num, cls)
  733. XXint    word_num;
  734. XXboolean    cls;
  735. XX{
  736. XX    extern    int    num_bad;
  737. XX    char    str[20];
  738. XX
  739. XX    if (cls)
  740. XX        clear ();
  741. XX    fname ();
  742. XX    if (word_num) {
  743. XX        sprintf (str, "Word #%d of %d", word_num, num_bad);
  744. XX        mvaddstr (23, 79 - strlen (str), str);
  745. XX        mvaddstr (23, 0, VERSION1);
  746. XX    }
  747. XX    move (3, 0);
  748. XX    refresh ();
  749. XX}
  750. XX
  751. XX
  752. XX/*
  753. XX** reset_data
  754. XX** Reset all global data
  755. XX*/
  756. XXreset_data () {
  757. XX    extern    char    *bad_words[], *good_words[], *add_words[];
  758. XX    extern    int    num_bad, num_added, num_ignored;
  759. XX    register int    i;
  760. XX
  761. XX    for (i = 0; i < MAX_WORDS; i++) {
  762. XX        if (bad_words[i] != NULL) {
  763. XX            free (bad_words[i]); bad_words[i] = NULL;
  764. XX        }
  765. XX        if (good_words[i] != NULL) {
  766. XX            free (good_words[i]); good_words[i] = NULL;
  767. XX        }
  768. XX        if (add_words[i] != NULL) {
  769. XX            free (add_words[i]); add_words[i] = NULL;
  770. XX        }
  771. XX    }
  772. XX
  773. XX    num_bad = num_added = num_ignored = 0;
  774. XX}
  775. XX
  776. XX
  777. XX/*
  778. XX** safe_copy
  779. XX** A pre-malloc'd copy from one string to another
  780. XX*/
  781. XXsafe_copy (string1, string2)
  782. XXchar    **string1,
  783. XX    *string2;
  784. XX{
  785. XX    if (*string1 == NULL)
  786. XX        *string1 = sfalloc ((unsigned) strlen (string2) + 1);
  787. XX    strcpy (*string1, string2);
  788. XX}
  789. XX
  790. XX
  791. XX/*
  792. XX** save
  793. XX** Save changes made to document
  794. XX*/
  795. XXsave (spell_val)
  796. XXint    spell_val;
  797. XX{
  798. XX    extern    int    num_bad, num_added, num_ignored;
  799. XX
  800. XX    if (num_added)
  801. XX        add_local ();
  802. XX    if (num_bad == (num_added + num_ignored))
  803. XX        message (False, "No corrections made");
  804. XX    else
  805. XX        if (spell_val == 0) doc_correct ();
  806. XX}
  807. XX
  808. XX
  809. XX/*
  810. XX** rest_ignore
  811. XX** When user exits before viewing all the words, set the rest
  812. XX** of the words to ignore.
  813. XX*/
  814. XXrest_ignore () {
  815. XX    extern    char    *bad_words[], *good_words[];
  816. XX    extern    int    num_bad;
  817. XX    register int    i;
  818. XX
  819. XX    for (i = num_bad - 1; !good_words[i]; ignore (i--));
  820. XX}
  821. XX
  822. XX
  823. XX/*
  824. XX** sfalloc
  825. XX** A safe malloc ()
  826. XX*/
  827. XXchar    *sfalloc (num_bytes)
  828. XXunsigned    num_bytes;
  829. XX{
  830. XX    char    *calloc (), *hold;
  831. XX
  832. XX    if (num_bytes == 0) return ((char *) NULL);
  833. XX
  834. XX    if ( (hold = calloc (1, num_bytes)) == NULL)
  835. XX        curse_die ("calloc");
  836. XX
  837. XX    return (hold);
  838. XX}
  839. XX
  840. XX
  841. XX/*
  842. XX** usage
  843. XX** Print out program usage statement and exit.
  844. XX*/
  845. XXusage (name)
  846. XXchar    *name;
  847. XX{
  848. XX    fprintf (stderr, "Usage: %s [ -d dictionary ] file [ file2 ... ]\n",
  849. XX        name);
  850. XX    exit (1);
  851. XX}
  852. SHAR_EOF
  853. if test 4218 -ne "`wc -c tools.c`"
  854. then
  855. echo shar: error transmitting tools.c '(should have been 4218 characters)'
  856. fi
  857. echo shar: extracting sp.h '(910 characters)'
  858. sed 's/^XX//' << \SHAR_EOF > sp.h
  859. XX/*
  860. XX** Configuration information for sp
  861. XX*/
  862. XX
  863. XX# include    <curses.h>
  864. XX
  865. XX# define    True    1
  866. XX# define    False    0
  867. XX
  868. XX# define    Error    1
  869. XX# define    Okay    0
  870. XX
  871. XX# define    VERSION1    "Sp Version 3.5"
  872. XX# define    VERSION2    "Copyright (C) 1988"
  873. XX# define    VERSION3    "Andrew Large"
  874. XX
  875. XX/*
  876. XX** Lookup dictionary -- use /usr/dict/web2 if you have it
  877. XX*/
  878. XX# define    LOOK_DICT    "/usr/dict/words"
  879. XX
  880. XX/*
  881. XX** Location of common programs
  882. XX*/
  883. XX# define    EX    "/usr/ucb/ex"
  884. XX# define    FGREP    "/usr/bin/fgrep"
  885. XX# define    GREP    "/bin/grep"
  886. XX# define    LOOK    "/usr/bin/look"
  887. XX# define    MORE    "/usr/ucb/more"
  888. XX# define    SORT    "/usr/bin/sort"
  889. XX# define    SPELL    "/usr/bin/spell"
  890. XX
  891. XX/*
  892. XX** Constant sizes
  893. XX*/
  894. XX# define    MAX_WORDS    512    /* Max words corrected on one pass */
  895. XX# define    MAX_WORD_LEN    256    /* Max length of a word */
  896. XX
  897. XX# define    CTRL_R        022    /* Ascii value of ^R -- for redraw */
  898. XX# define    CTRL_L        014    /* Ascii value of ^L -- for redraw */
  899. XX
  900. XXtypedef    unsigned char    boolean;
  901. XX
  902. XXvoid    leave ();
  903. XXchar    *sfalloc ();
  904. SHAR_EOF
  905. if test 910 -ne "`wc -c sp.h`"
  906. then
  907. echo shar: error transmitting sp.h '(should have been 910 characters)'
  908. fi
  909. echo shar: extracting user_tools.c '(3905 characters)'
  910. sed 's/^XX//' << \SHAR_EOF > user_tools.c
  911. XX# include    "sp.h"
  912. XX
  913. XX
  914. XX/*
  915. XX** add
  916. XX** Add an entry into list of words to be added to personal dict
  917. XX*/
  918. XXadd (word_num)
  919. XXint    word_num;
  920. XX{
  921. XX    extern    char    *add_words[], *bad_words[], *good_words[];
  922. XX    extern    int    num_added;
  923. XX
  924. XX    safe_copy (& (add_words[num_added++]), bad_words[word_num]);
  925. XX    safe_copy (& (good_words[word_num]), bad_words[word_num]);
  926. XX}
  927. XX
  928. XX
  929. XX/*
  930. XX** ask_action
  931. XX** Ask the user what to do after processing words
  932. XX*/
  933. XXask_action () {
  934. XX    extern    int    num_bad;
  935. XX    boolean    done;
  936. XX
  937. XX    done = False;
  938. XX    while (!done) {
  939. XX        page_clear (0, False);
  940. XX        mvaddstr (3, 0, "Action? [#^?] ");
  941. XX        refresh ();
  942. XX
  943. XX        switch (getch ()) {
  944. XX            case ' ': case '\n': case '\r':
  945. XX            case '#':
  946. XX                done = True;
  947. XX                addstr ("Next Document"); refresh ();
  948. XX                if (ask_save (num_bad) == 1) return (0);
  949. XX                else return (2);
  950. XX            case '^':
  951. XX                done = True;
  952. XX                addstr ("Previous Document"); refresh ();
  953. XX                if (ask_save (num_bad) == 1) return (-1);
  954. XX                else return (-2);
  955. XX            case '?':
  956. XX                addstr ("Help!"); refresh ();
  957. XX                mvaddstr (5, 10, "# --- Go to next document (or exit)");
  958. XX                mvaddstr (6, 10, "^ --- Go to previous document (or re-spell this one)");
  959. XX                mvaddstr (7, 10, "? --- This help message");
  960. XX                ask_more ();
  961. XX            default:
  962. XX                break;
  963. XX        }
  964. XX    }
  965. XX    return (0);
  966. XX}
  967. XX
  968. XX
  969. XX/*
  970. XX** ask_save
  971. XX** Ask user if he/she wants to save these changes
  972. XX*/
  973. XXask_save (word_num)
  974. XXint    word_num;
  975. XX{
  976. XX    extern    int    num_ignored;
  977. XX    char    ch;
  978. XX
  979. XX    if (word_num == num_ignored) return (0);
  980. XX    mvaddstr (7, 0, "Do you wish to save your changes? [y] ");
  981. XX    refresh ();
  982. XX    if ( (ch = getch ()) == 'n' || ch == 'N' ) return (0);
  983. XX    return (1);
  984. XX}
  985. XX
  986. XX
  987. XX/*
  988. XX** correct
  989. XX** Get correct spelling for a word
  990. XX*/
  991. XXword_correct (word_num)
  992. XXint    word_num;
  993. XX{
  994. XX    extern    char        *good_words[];
  995. XX
  996. XX    mvaddstr (7, 0, "****** Proper spelling: ");
  997. XX
  998. XX    nocrmode (); echo (); refresh ();
  999. XX
  1000. XX    if (good_words[word_num] == NULL)
  1001. XX        good_words[word_num] = sfalloc ((unsigned) MAX_WORD_LEN + 1);
  1002. XX    gets (good_words[word_num]);
  1003. XX
  1004. XX    crmode (); noecho ();
  1005. XX    ask_more (); page_clear (word_num + 1, True);
  1006. XX}
  1007. XX
  1008. XX
  1009. XX/*
  1010. XX** help
  1011. XX** Give user some help with commands
  1012. XX*/
  1013. XXhelp (word_num)
  1014. XXint    word_num;
  1015. XX{
  1016. XX    mvaddstr ( 7, 10, "     I --- Ignore all occurrences of word");
  1017. XX    mvaddstr ( 8, 10, "     L --- Lookup a sub-string in the dictionary");
  1018. XX    mvaddstr ( 9, 10, "     W --- show Where word occurs in the document");
  1019. XX    mvaddstr (10, 10, "     A --- Add word to your personal dictionary");
  1020. XX    mvaddstr (11, 10, "     C --- Correct all occurrences of the word");
  1021. XX    mvaddstr (12, 10, "     ^ --- go to previous document (or re-spell this one)");
  1022. XX    mvaddstr (13, 10, "     # --- go to next document (or exit)");
  1023. XX    mvaddstr (14, 10, "     + --- go to next word");
  1024. XX    mvaddstr (15, 10, "     - --- go to previous word");
  1025. XX    mvaddstr (16, 10, " ?,  H --- this help message");
  1026. XX    mvaddstr (17, 10, "^R, ^L --- redraw the screen");
  1027. XX    ask_more ();
  1028. XX    page_clear (word_num + 1, False);
  1029. XX}
  1030. XX
  1031. XX
  1032. XX/*
  1033. XX** ignore
  1034. XX** Ignore the word (i.e. don't substitute for it)
  1035. XX*/
  1036. XXignore (word_num)
  1037. XXint    word_num;
  1038. XX{
  1039. XX    extern    char    *good_words[], *bad_words[];
  1040. XX    extern    int    num_ignored;
  1041. XX
  1042. XX    safe_copy (& (good_words[word_num]), bad_words[word_num]);
  1043. XX    num_ignored++;
  1044. XX}
  1045. XX
  1046. XX
  1047. XX/*
  1048. XX** lookup
  1049. XX** Look up string in the dictionary
  1050. XX*/
  1051. XXlookup (word_num)
  1052. XXint    word_num;
  1053. XX{
  1054. XX    char    hold_str[MAX_WORD_LEN + 1],
  1055. XX        command[BUFSIZ];
  1056. XX
  1057. XX    mvaddstr (7, 0, "****** Lookup string: ");
  1058. XX    refresh ();
  1059. XX
  1060. XX    echo (); nocrmode (); gets (hold_str);
  1061. XX    move (8, 0); clrtobot (); move (8, 0); refresh ();
  1062. XX
  1063. XX    sprintf (command, "%s -df %s %s | %s", LOOK, hold_str, LOOK_DICT,
  1064. XX        MORE);
  1065. XX    system (command);
  1066. XX
  1067. XX    crmode (); noecho (); ask_more ();
  1068. XX    page_clear (word_num + 1, True);
  1069. XX}
  1070. XX
  1071. XX
  1072. XX/*
  1073. XX** where
  1074. XX** Show where a word occurs in the document
  1075. XX*/
  1076. XXwhere (word_num)
  1077. XXint    word_num;
  1078. XX{
  1079. XX    extern    char    *bad_words[], *spell_doc;
  1080. XX    char    command[BUFSIZ];
  1081. XX
  1082. XX    move (7, 0); clrtobot (); move (7, 0); echo (); nocrmode (); refresh ();
  1083. XX    sprintf (command, "%s -w %s %s | %s", GREP, bad_words[word_num],
  1084. XX        spell_doc, MORE);
  1085. XX    system (command);
  1086. XX
  1087. XX    crmode (); noecho (); ask_more ();
  1088. XX    page_clear (word_num + 1, True);
  1089. XX}
  1090. SHAR_EOF
  1091. if test 3905 -ne "`wc -c user_tools.c`"
  1092. then
  1093. echo shar: error transmitting user_tools.c '(should have been 3905 characters)'
  1094. fi
  1095. echo shar: extracting doc_correct.c '(767 characters)'
  1096. sed 's/^XX//' << \SHAR_EOF > doc_correct.c
  1097. XX# include    "sp.h"
  1098. XX
  1099. XX/*
  1100. XX** doc_correct
  1101. XX** Correct the document, based upon the difference between the
  1102. XX** original list and the new list of words.  Uses EX to make the
  1103. XX** corrections.
  1104. XX*/
  1105. XXdoc_correct () {
  1106. XX    extern    char    *bad_words[], *good_words[], *spell_doc;
  1107. XX    extern    int    num_bad;
  1108. XX    FILE    *fopen (), *popen (), *ex_ptr;
  1109. XX    char    command[256];
  1110. XX    register int    loop;
  1111. XX
  1112. XX    page_clear (0, False);
  1113. XX    mvaddstr (3, 0, "Making changes ..."); refresh ();
  1114. XX
  1115. XX    sprintf (command, "%s - %s", EX, spell_doc);
  1116. XX    ex_ptr = popen (command, "w");
  1117. XX
  1118. XX    for (loop = 0; loop < num_bad; loop++)
  1119. XX        if (strcmp (bad_words[loop], good_words[loop]) != 0)
  1120. XX            fprintf (ex_ptr, "%%s/\\<%s\\>/%s/g\n", bad_words[loop],
  1121. XX                good_words[loop]);
  1122. XX    fprintf (ex_ptr, "w\nq\n"); fclose (ex_ptr);
  1123. XX
  1124. XX    addstr (" done"); refresh ();
  1125. XX}
  1126. SHAR_EOF
  1127. if test 767 -ne "`wc -c doc_correct.c`"
  1128. then
  1129. echo shar: error transmitting doc_correct.c '(should have been 767 characters)'
  1130. fi
  1131. echo shar: extracting externs.c '(703 characters)'
  1132. sed 's/^XX//' << \SHAR_EOF > externs.c
  1133. XX# include    "sp.h"
  1134. XX
  1135. XX/*
  1136. XX** Global data use throughout the program
  1137. XX*/
  1138. XX
  1139. XXchar    *id = "@(#)SP\t3.5\t10/17/88";    /* Identification string for what(1) */
  1140. XX
  1141. XXchar    *bad_words[MAX_WORDS],        /* Words obtained from spell(1) */
  1142. XX    *good_words[MAX_WORDS],        /* Words to correct in document */
  1143. XX    *add_words[MAX_WORDS],        /* Words to add to local dictionary */
  1144. XX    *local_dict,            /* Local dictionary */
  1145. XX    *spell_doc,            /* Document we are currently spelling */
  1146. XX    *tmp_file = "/tmp/spXXXXXX";
  1147. XX
  1148. XXint    num_bad,            /* Number of bad words */
  1149. XX    num_added,            /* Number added to local dict */
  1150. XX    num_ignored,            /* Number bad words ignored */
  1151. XX    exit_val;            /* Program exit value (for leave ()) */
  1152. XX
  1153. XXboolean    local;                /* If the local dict is available */
  1154. SHAR_EOF
  1155. if test 703 -ne "`wc -c externs.c`"
  1156. then
  1157. echo shar: error transmitting externs.c '(should have been 703 characters)'
  1158. fi
  1159. echo shar: extracting add_local.c '(1248 characters)'
  1160. sed 's/^XX//' << \SHAR_EOF > add_local.c
  1161. XX# include    "sp.h"
  1162. XX
  1163. XX/*
  1164. XX** add_local
  1165. XX** Add all words in correct list to personal dictionary
  1166. XX** and sort the dictionary.
  1167. XX*/
  1168. XXadd_local () {
  1169. XX    extern    char    *add_words[], *local_dict, *tmp_file;
  1170. XX    extern    int    num_added;
  1171. XX    extern    boolean    local;
  1172. XX    char    *mktemp (), string[256];
  1173. XX    FILE    *fopen (), *tmp_ptr;
  1174. XX    register int    loop;
  1175. XX
  1176. XX    if ( access (local_dict, 0) == 0 && access (local_dict, 2) != 0 ) {
  1177. XX        sprintf (string,
  1178. XX            "Your local dictionary \"%s\" is not writable!",
  1179. XX            local_dict);
  1180. XX        message (True, string);
  1181. XX        return;
  1182. XX    }
  1183. XX
  1184. XX    if ((tmp_ptr = fopen (mktemp (tmp_file), "w")) == NULL) {
  1185. XX        sprintf (string,
  1186. XX            "Your local dictionary \"%s\" is not writable!",
  1187. XX            local_dict);
  1188. XX        message (True, string);
  1189. XX        return;
  1190. XX    }
  1191. XX
  1192. XX    for (loop = 0; loop < num_added; loop++)
  1193. XX        fprintf (tmp_ptr, "%s\n", add_words[loop]);
  1194. XX    fclose (tmp_ptr);
  1195. XX
  1196. XX# ifdef BSD
  1197. XX    if (vfork () == 0) {
  1198. XX# else
  1199. XX    if (fork () == 0) {
  1200. XX# endif
  1201. XX        if (local)
  1202. XX            execl (SORT, "sort", "-f", "-m", "-o", local_dict,
  1203. XX                local_dict, tmp_file, (char *) NULL);
  1204. XX        else
  1205. XX            execl (SORT, "sort", "-f", "-m", "-o", local_dict,
  1206. XX                tmp_file, (char *) NULL);
  1207. XX        perror (SORT);
  1208. XX        _exit (-1);
  1209. XX    }
  1210. XX
  1211. XX    wait (0);
  1212. XX    sprintf (string, "%d %s added to %s", num_added,
  1213. XX        (num_added == 1 ? "word" : "words"), local_dict);
  1214. XX    message (False, string);
  1215. XX}
  1216. SHAR_EOF
  1217. if test 1248 -ne "`wc -c add_local.c`"
  1218. then
  1219. echo shar: error transmitting add_local.c '(should have been 1248 characters)'
  1220. fi
  1221. echo shar: done with directory sp
  1222. cd ..
  1223. #    End of shell archive
  1224. exit 0
  1225.  
  1226.  
  1227.