home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / micrognu / part05 < prev    next >
Encoding:
Internet Message Format  |  1987-01-26  |  56.2 KB

  1. Subject:  v08i012:  A Micro-Emacs variant that resembles GNU Emacs
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: Bob Larson <seismo!usc-oberon!blarson>
  6. Mod.sources: Volume 8, Issue 12
  7. Archive-name: micrognu/Part05
  8.  
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create the files:
  15. #    tty/termcap/ttykbd.c
  16. #    sys/bsd/Makefile
  17. #    sys/bsd/fileio.c
  18. #    sys/bsd/spawn.c
  19. #    sys/bsd/sysdef.h
  20. #    sys/bsd/ttyio.c
  21. #    sys/sysv/Makefile
  22. #    sys/sysv/fileio.c
  23. #    sys/sysv/spawn.c
  24. #    sys/sysv/ttyio.c
  25. #    sys/sysv/sysdef.h
  26. #    sys/osk/readme.osk
  27. #    sys/osk/sysdef.h
  28. #    sys/osk/varargs.h
  29. #    sys/osk/fileio.c
  30. #    sys/osk/spawn.c
  31. #    sys/osk/ttyio.c
  32. #    sys/osk/makefile
  33. # This archive created: Sat Nov 15 15:16:30 1986
  34. export PATH; PATH=/bin:$PATH
  35. if test ! -d sys/bsd
  36. then
  37. mkdir sys/bsd
  38. fi
  39. if test ! -d sys/sysv
  40. then
  41. mkdir sys/sysv
  42. fi
  43. if test ! -d sys/osk
  44. then
  45. mkdir sys/osk
  46. fi
  47. if test -f 'tty/termcap/ttykbd.c'
  48. then
  49.     echo shar: will not over-write existing file "'tty/termcap/ttykbd.c'"
  50. else
  51. cat << \SHAR_EOF > 'tty/termcap/ttykbd.c'
  52. /*
  53.  * Name:    MicroEmacs
  54.  * Version:    30
  55.  *        Termcap keyboard driver
  56.  * Created:    21-Aug-1986
  57.  *        Mic Kaczmarczik ...!ihnp4!seismo!ut-sally!ut-ngp!mic
  58.  * Last edit:    03-Sep-86
  59.  *
  60.  * [ Several of the nasty comments about the XKEYS code are
  61.  *   by me.  [Bob Larson (usc-oberon!blarson)]  It is my opinion
  62.  *   that function keys cannot be made to work with standard
  63.  *   emacs keybindings except on a very limited set of terminals.
  64.  *   I just work with to many that do not fit the assumptions Mic's
  65.  *   XKEYS code makes to consider it useful to me, and think that
  66.  *   others considering using this code should look and see what
  67.  *   it realy does first.
  68.  * ]
  69.  *
  70.  * If XKEYS is defined this routine looks for the following 
  71.  * termcap sequences, which are obtained by "tty.c":
  72.  *
  73.  *    ks    -- start using the function keypad
  74.  *    ke    -- finish using the function keypad
  75.  *    kh    -- home key
  76.  *    ku    -- up arrow
  77.  *    kd    -- down arrow
  78.  *    kl    -- left arrow
  79.  *    kr    -- right arrow
  80.  *    k0-k9    -- standard termcap function keys
  81.  *    l0-l9    -- labels for termcap function keys
  82.  *    (nonstandard)
  83.  *    K0-K9    -- extra keys that we look for -- the get mapped
  84.  *           internally to F10-F19
  85.  *    L0-L9    -- labels for same.
  86.  *
  87.  * Bugs/features/problems:
  88.  *
  89.  *    XKEYS and DPROMPT do not work together well.
  90.  *
  91.  *    If the META introducer is used as the initial character of
  92.  *    a function key sequence, what should the key parser do when the
  93.  *    user wants to type a META-ed key, or just the META introducer
  94.  *    alone?    This is of practical importance on DEC terminals, where
  95.  *    the META introducer is the Escape key.  Even worse things happen
  96.  *    on terminals that have something (or more than one thing) other
  97.  *    than the META introducer as the inital character of a function
  98.  *    sequence.
  99.  *
  100.  *    The approach I took was that if the META introducer is the first
  101.  *    character in a function sequence, and the second character c
  102.  *    isn't part of a function key sequence, the parser returns
  103.  *    (KMETA | c).  If it sees two META introducers in a row, it
  104.  *    returns one instance of METACH.   This approach is subject to
  105.  *    discussion and debate, but it works.  [In at lease some cases.]
  106.  *
  107.  *    If the META introducer is NOT the first character in a function
  108.  *    sequence (including arrow keys) this code has a very nasty
  109.  *    side effect of eating that key.  For example, on an Adds viewpoint
  110.  *    60, six normal control characters are eaten if you have defined
  111.  *    XKEYS and put the keys in the termcap.  More than a little 
  112.  *    creativity is needed because ^U is one of the arrow keys, and
  113.  *    prefixes aren't bindable.
  114.  *
  115.  *    [ From a quick look at the code, it seems that a single character
  116.  *      funciton key won't work, but it is still put in the table.
  117.  *    ]
  118.  */
  119. #include    "def.h"
  120.  
  121. /*
  122.  * Default key name table.  Can be overridden by
  123.  * definitions of l0-l9 in the termcap entry.  You
  124.  * can't redefine the names for the arrow keys
  125.  * and the home key.
  126.  */
  127.  
  128. #ifdef    XKEYS
  129. /* key sequences (from tty.c) */
  130. extern    char    *K[], *L[], *KS, *KE, *KH, *KU, *KD, *KL, *KR;
  131. extern    int    putpad();    /* also from tty.c */
  132. char    *keystrings[] = {
  133.     NULL,        "Home",        "Down-Arrow",    "Up-Arrow",
  134.     "Left-Arrow",    "Right-Arrow",    "F0",        "F1",
  135.     "F2",        "F3",        "F4",        "F5",
  136.     "F6",        "F7",        "F8",        "F9",
  137.     "F10",        "F11",        "F12",        "F13",
  138.     "F14",        "F15",        "F16",        "F17",
  139.     "F18",        "F19",        NULL,        NULL,
  140.     NULL,        NULL,        NULL,        NULL
  141. };
  142. #else
  143. char    *keystrings[] = {
  144.     NULL,        NULL,        NULL,        NULL,
  145.     NULL,        NULL,        NULL,        NULL,
  146.     NULL,        NULL,        NULL,        NULL,
  147.     NULL,        NULL,        NULL,        NULL,
  148.     NULL,        NULL,        NULL,        NULL,
  149.     NULL,        NULL,        NULL,        NULL,
  150.     NULL,        NULL,        NULL,        NULL,
  151.     NULL,        NULL,        NULL,        NULL
  152. };
  153. #endif
  154.  
  155. #ifdef    XKEYS
  156. /*
  157.  * Type declarations for data structure we
  158.  * use to parse for function key sequences
  159.  */
  160. #define    NODE        0    /* internal node        */
  161. #define    VALUE        1    /* internal key code value    */
  162. #define SENTINEL    2    /* sentinel value        */
  163.  
  164. typedef struct trienode {
  165.     int type;    /* one of NODE, LEAF */
  166.     struct trienode *sibling, *child;
  167.     KEY value;
  168. } TRIENODE, *TRIE;
  169.  
  170. TRIE keywords, sentinel, talloc(), tinsert();
  171. #endif
  172.  
  173. /*
  174.  * Get keyboard character, and interpret
  175.  * any special keys on the keyboard.  If XKEYS is
  176.  * #defined, use a dictionary organized as a
  177.  * trie to keep the parsing overhead down.
  178.  *
  179.  * To keep the function call overhead down, do the
  180.  * first level of parse() inside getkbd().
  181.  *
  182.  * Also, since ESC (the usual value of METACH) is
  183.  * the first character in many function key sequences,
  184.  * we  return (KMETA | ch) if METACH-<ch> is not
  185.  * the start of an escape sequence.  Blecch.  Furthermore,
  186.  * if we see METACH-METACH, we return the value METACH.
  187.  * Phhhht.
  188.  */
  189. getkbd() {
  190. #ifndef    XKEYS
  191.     return (ttgetc());
  192. #else
  193.     register TRIE    t;
  194.     register int    c;
  195.     KEY        code;
  196.  
  197.     c = ttgetc();
  198.     for (t = keywords; t->type == NODE; t = t->sibling)
  199.         if (t->value == c) {    /* possible function key sequence  */
  200.             if (c != METACH)
  201.                 return (parse(t->child));
  202.             else {        /* maybe sequence, maybe META char */
  203.                 c = ttgetc();
  204.                 for (t = t->child; t->type == NODE; t = t->sibling)
  205.                     if (t->value == c)
  206.                         return (parse(t->child));
  207.                 /* METACH-METACH -> METACH */
  208.                 if (c == METACH)
  209.                     return (METACH);
  210.                 /* Else make c into a META character */
  211.                 if (ISLOWER(c) != FALSE)
  212.                     c = TOUPPER(c);
  213.                 if (c>=0x00 && c<=0x1F)
  214.                     c = KCTRL | (c+'@');
  215.                 return (KMETA | c);
  216.             }
  217.         }
  218.     return (c);
  219. #endif
  220. }
  221.  
  222. #ifdef    XKEYS
  223. static parse(first)
  224. TRIE first;
  225. {
  226.     register TRIE    t;
  227.     register int    c;
  228.  
  229.     if (first->type == VALUE)        /* found a match!    */
  230.         return (first->value);
  231.  
  232.     c = ttgetc();
  233.     for (t = first; t->type == NODE; t = t->sibling)/* look thru list   */
  234.         if (t->value == c)
  235.             return (parse(t->child));    /* try next level   */
  236.     return (c);    /* nothing matched */
  237. }
  238. #endif
  239.  
  240. /*
  241.  * If XKEYS is defined, get key definitions from the termcap 
  242.  * entry and put them in the parse table.
  243.  */
  244. ttykeymapinit()
  245. {
  246. #ifdef    XKEYS
  247.     register int    i;
  248.     register int    s;
  249.     register char    *cp;
  250.     register SYMBOL    *sp;
  251.  
  252.     if (KS && *KS)            /* turn on keypad    */
  253.         putpad(KS);        
  254.  
  255.     tinit();            /* set up initial trie */
  256.  
  257.     for (i = 0; i < NFKEYS; i++) {
  258.         if (K[i] && *K[i])
  259.             adddict(K[i], (KEY) (KF0 + i));
  260.         if (L[i] && *L[i])    /* record new name */
  261.             keystrings[(KF0-KFIRST)+i] = L[i];
  262.     }
  263.  
  264.     /*
  265.      * Add the home and arrow keys
  266.      */
  267.     if (KH && *KH)
  268.         adddict(KH, (KEY) KHOME);
  269.     if (KU && *KU)
  270.         adddict(KU, (KEY) KUP);
  271.     if (KD && *KD)
  272.         adddict(KD, (KEY) KDOWN);
  273.     if (KL && *KL)
  274.         adddict(KL, (KEY) KLEFT);
  275.     if (KR && *KR)
  276.         adddict(KR, (KEY) KRIGHT);
  277.  
  278.     /*
  279.      * Bind things to the movement keys
  280.      */
  281.     keydup(KHOME,    "beginning-of-buffer");    /* for now */
  282.     keydup(KUP,    "previous-line");
  283.     keydup(KDOWN,    "next-line");
  284.     keydup(KLEFT,    "backward-char");
  285.     keydup(KRIGHT,    "forward-char");
  286.  
  287.     /*
  288.      * These bindings sort of go with the termcap I use for my vt220
  289.      * clone, which is why they're #ifdef'd.  I don't really use
  290.      * them, but it gives you an example of what to do...
  291.      */
  292. #ifdef    MPK
  293.     keydup((KEY)KF0, "describe-key-briefly");    /* Help        */
  294.     keydup((KEY)KF1, "execute-extended-command");    /* Do        */
  295.     keydup((KEY)KF2, "search-forward");        /* Find        */
  296.     keydup((KEY)KF3, "yank");            /* Insert here    */
  297.     keydup((KEY)KF4, "kill-region");        /* Remove    */
  298.     keydup((KEY)KF5, "set-mark-command");        /* Select    */
  299.     keydup((KEY)KF6, "scroll-down");        /* Prev Screen    */
  300.     keydup((KEY)KF7, "scroll-up");            /* Next Screen    */
  301.  
  302.     /* Don't expect these to make much sense, I'm just filling in    */
  303.     /* the keymap B-]                        */
  304.     keydup((KEY)KF10, "suspend-emacs");        /* PF1        */
  305.     keydup((KEY)KF11, "query-replace");        /* PF2        */
  306.     keydup((KEY)KF12, "call-last-kbd-macro");    /* PF3        */
  307.     keydup((KEY)KF13, "save-buffers-kill-emacs");    /* PF4        */
  308. #endif    MPK
  309. #endif    XKEYS
  310. }
  311.  
  312. #ifdef    XKEYS
  313. /*
  314.  * Clean up the keyboard -- called by tttidy()
  315.  */
  316. ttykeymaptidy()
  317. {
  318.     tdelete(keywords);    /* get rid of parse tree    */
  319.     free(sentinel);        /* remove sentinel value    */
  320.     if (KE && *KE)
  321.         putpad(KE);    /* turn off keypad        */
  322. }
  323.  
  324. /*
  325.  * * * * * * * * Dictionary management * * * * * * * * *
  326.  */
  327.  
  328. /*
  329.  * Add a key string to the dictionary.
  330.  */
  331.  
  332. static adddict(kstr, kcode)
  333. char *kstr;
  334. KEY kcode;
  335. {
  336.     keywords = tinsert(kstr, kcode, keywords);
  337. }
  338.  
  339. /*
  340.  * Initialize the parse tree by creating the sentinel value
  341.  */
  342.  
  343. static tinit()
  344. {
  345.     keywords = sentinel = talloc();
  346.     sentinel->type = SENTINEL;
  347.     sentinel->value = (KEY) -1;
  348.     sentinel->sibling = sentinel->child = sentinel;    /* set up a loop */
  349. }
  350.  
  351. /*
  352.  * Deallocate all the space used by the trie --
  353.  * Tell all the siblings to deallocate space, then
  354.  * all the children.
  355.  */
  356.  
  357. static tdelete(t)
  358. register TRIE t;
  359. {
  360.     if (t->type != SENTINEL) {
  361.         tdelete(t->sibling);
  362.         tdelete(t->child);
  363.         free(t);
  364.     }
  365. }
  366.  
  367. /*
  368.  * Insert a dictionary key string and a value into the dictionary,
  369.  * returning as the value the first sibling in the current sublevel,
  370.  * which may have been changed by an insertion into the list of siblings.
  371.  */
  372.  
  373. static TRIE tinsert(kstring, kcode, first)
  374. register char *kstring;
  375. register KEY kcode;
  376. TRIE first;
  377. {
  378.     register TRIE    match;
  379.     register TRIE    p;
  380.     
  381.     if (!*kstring) {    /* base case -- return a value node */
  382.         p = talloc();
  383.         p->type = VALUE;
  384.         p->value = kcode;
  385.         p->sibling = p->child = sentinel;
  386.         return (p);
  387.     }
  388.     /* recursive case -- insert rest of string in trie */
  389.  
  390.     /* search for sibling that matches the current character */
  391.     match = NULL;
  392.     for (p = first; p->type == NODE; p = p->sibling)
  393.         if (p->value == *kstring) {
  394.             match = p;
  395.             break;
  396.         }
  397.  
  398.     if (match == NULL) {    /* if not, add it to beginning of the list */
  399.         match = talloc();
  400.         match->type = NODE;
  401.         match->value = *kstring;
  402.         match->sibling = first;
  403.         match->child = sentinel;
  404.         first = match;
  405.     }
  406.     /* add rest of string to this child's subtrie */
  407.     match->child = tinsert(kstring+1, kcode, match->child);
  408.     return (first);
  409. }
  410.  
  411. /*
  412.  * Allocate a trie node
  413.  */
  414. static TRIE talloc()
  415. {
  416.     char *malloc();
  417.     TRIE t;
  418.  
  419.     if ((t = (TRIE) malloc(sizeof(TRIENODE))) == NULL)
  420.         panic("talloc: can't allocate trie node!");
  421.     return (t);
  422. }
  423. #endif
  424. SHAR_EOF
  425. fi # end of overwriting check
  426. if test -f 'sys/bsd/Makefile'
  427. then
  428.     echo shar: will not over-write existing file "'sys/bsd/Makefile'"
  429. else
  430. cat << \SHAR_EOF > 'sys/bsd/Makefile'
  431. # Makefile for MicroEMACS.
  432. # Is there a better way to do the rebuilds, other than using
  433. # the links?
  434.  
  435. SYS    = bsd
  436. TTY    = termcap
  437. LIBS    = -ltermcap
  438. # CDEFS gets defines, and gets passed to lint. CFLAGS gets flags, and doesn't
  439. # get passed to lint.
  440. CDEFS    =  -DDO_METAKEY -DSTARTUP
  441. CFLAGS    = -g $(CDEFS)
  442.  
  443. OBJ =    basic.o buffer.o cinfo.o display.o echo.o extend.o file.o kbd.o \
  444.     line.o main.o match.o random.o region.o search.o symbol.o version.o \
  445.     window.o paragraph.o prefix.o \
  446.     word.o fileio.o spawn.o ttyio.o tty.o ttykbd.o
  447. OSRCS = fileio.c spawn.c ttyio.c tty.c ttykbd.c
  448. SRCS =    basic.c buffer.c cinfo.c display.c echo.c extend.c file.c kbd.c \
  449.     line.c main.c match.c random.c region.c search.c symbol.c version.c \
  450.     window.c word.c paragraph.c prefix.c
  451. OINCS =    ttydef.h sysdef.h
  452. INCS =    def.h
  453.  
  454. mg:        $(OBJ)
  455.     cc $(CFLAGS) -o mg $(OBJ) $(LIBS)
  456.  
  457. # the v arg to lint turns off all the complaints about args f, n & k.
  458. # It's a good idea to take that out and rerun make lint after getting
  459. # a clean lint, just to verify that f, n & k are the ONLY unused args.
  460. lint: $(SRCS) $(OSRCS)
  461.     lint -ahb $(CDEFS) $(SRCS) $(OSRCS)
  462.  
  463. $(OBJ):        def.h sysdef.h ttydef.h
  464.  
  465. sysdef.h:    sys/$(SYS)/sysdef.h    # Update links, if needed.
  466.     rm -f sysdef.h
  467.     ln sys/$(SYS)/sysdef.h .
  468.  
  469. ttydef.h:    tty/$(TTY)/ttydef.h
  470.     rm -f ttydef.h
  471.     ln tty/$(TTY)/ttydef.h .
  472.  
  473. fileio.c:    sys/$(SYS)/fileio.c
  474.     rm -f fileio.c
  475.     ln sys/$(SYS)/fileio.c .
  476.  
  477. spawn.c:    sys/$(SYS)/spawn.c
  478.     rm -f spawn.c
  479.     ln sys/$(SYS)/spawn.c .
  480.  
  481. tty.c:        tty/$(TTY)/tty.c
  482.     rm -f tty.c
  483.     ln tty/$(TTY)/tty.c .
  484.  
  485. ttyio.c:    sys/$(SYS)/ttyio.c
  486.     rm -f ttyio.c
  487.     ln sys/$(SYS)/ttyio.c .
  488.  
  489. ttykbd.c:    tty/$(TTY)/ttykbd.c
  490.     rm -f ttykbd.c
  491.     ln tty/$(TTY)/ttykbd.c .
  492.  
  493. port: $(SRCS) $(INCS)
  494.     rm -f port
  495.     tar cfb port 1 $?
  496.  
  497. clean:;    rm -f $(OBJ) $(OSRCS) $(OINCS)
  498.  
  499. SHAR_EOF
  500. fi # end of overwriting check
  501. if test -f 'sys/bsd/fileio.c'
  502. then
  503.     echo shar: will not over-write existing file "'sys/bsd/fileio.c'"
  504. else
  505. cat << \SHAR_EOF > 'sys/bsd/fileio.c'
  506. /*
  507.  *         bsd (4.2, others?) and Ultrix-32 file I/O.
  508.  */
  509. #include    "def.h"
  510.  
  511. static    FILE    *ffp;
  512. extern    char    *getenv();
  513.  
  514. /*
  515.  * handle C-shell style names
  516.  */
  517. static char *bsd(fn, buf, bufsiz) char *fn, *buf; int bufsiz;
  518. {
  519.     if (*fn != '~')
  520.         return (fn);
  521.     else {    /* C-shell $HOME-relative names */
  522.         strncpy(buf, getenv("HOME"), bufsiz);
  523.         strncat(buf, fn + 1, bufsiz);
  524.         return (buf);
  525.     }
  526. }
  527.  
  528. /*
  529.  * Open a file for reading.
  530.  */
  531. ffropen(fn) char *fn; {
  532.     char buf[NFILEN];
  533.     fn = bsd(fn, buf, sizeof(buf));
  534.     if ((ffp=fopen(fn, "r")) == NULL)
  535.         return (FIOFNF);
  536.     return (FIOSUC);
  537. }
  538.  
  539. /*
  540.  * Open a file for writing.
  541.  * Return TRUE if all is well, and
  542.  * FALSE on error (cannot create).
  543.  */
  544. ffwopen(fn) char *fn; {
  545.     char buf[NFILEN];
  546.     fn = bsd(fn, buf, sizeof(buf));
  547.     if ((ffp=fopen(fn, "w")) == NULL) {
  548.         ewprintf("Cannot open file for writing");
  549.         return (FIOERR);
  550.     }
  551.     return (FIOSUC);
  552. }
  553.  
  554. /*
  555.  * Close a file.
  556.  * Should look at the status.
  557.  */
  558. ffclose() {
  559.     (VOID) fclose(ffp);
  560.     return (FIOSUC);
  561. }
  562.  
  563. /*
  564.  * Write a line to the already
  565.  * opened file. The "buf" points to the
  566.  * buffer, and the "nbuf" is its length, less
  567.  * the free newline. Return the status.
  568.  * Check only at the newline.
  569.  */
  570. ffputline(buf, nbuf) register char buf[]; {
  571.     register int    i;
  572.  
  573.     /* What's with putc? */
  574.     for (i=0; i<nbuf; ++i)
  575.         putc(buf[i]&0xFF, ffp);
  576.     putc('\n', ffp);
  577.     if (ferror(ffp) != FALSE) {
  578.         ewprintf("Write I/O error");
  579.         return (FIOERR);
  580.     }
  581.     return (FIOSUC);
  582. }
  583.  
  584. /*
  585.  * Read a line from a file, and store the bytes
  586.  * in the supplied buffer. Stop on end of file or end of
  587.  * line. Don't get upset by files that don't have an end of
  588.  * line on the last line; this seem to be common on CP/M-86 and
  589.  * MS-DOS (the suspected culprit is VAX/VMS kermit, but this
  590.  * has not been confirmed. If this is sufficiently researched
  591.  * it may be possible to pull this kludge). Delete any CR
  592.  * followed by an LF. This is mainly for runoff documents,
  593.  * both on VMS and on Ultrix (they get copied over from
  594.  * VMS systems with DECnet).
  595.  */
  596. ffgetline(buf, nbuf) register char buf[]; {
  597.     register int    c;
  598.     register int    i;
  599.  
  600.     i = 0;
  601.     for (;;) {
  602.         c = getc(ffp);
  603.         if (c == '\r') {        /* Delete any non-stray    */
  604.             c = getc(ffp);        /* carriage returns.    */
  605.             if (c != '\n') {
  606.                 if (i >= nbuf-1) {
  607.                     ewprintf("File has long line");
  608.                     return (FIOERR);
  609.                 }
  610.                 buf[i++] = '\r';
  611.             }
  612.         }
  613.         if (c==EOF || c=='\n')        /* End of line.        */
  614.             break;
  615.         if (i >= nbuf-1) {
  616.             ewprintf("File has long line");
  617.             return (FIOERR);
  618.         }
  619.         buf[i++] = c;
  620.     }
  621.     if (c == EOF) {                /* End of file.        */
  622.         if (ferror(ffp) != FALSE) {
  623.             ewprintf("File read error");
  624.             return (FIOERR);
  625.         }
  626.         if (i == 0)            /* Don't get upset if    */
  627.             return (FIOEOF);    /* no newline at EOF.    */
  628.     }
  629.     buf[i] = 0;
  630.     return (FIOSUC);
  631. }
  632.  
  633. #if    BACKUP
  634. /*
  635.  * Rename the file "fname" into a backup
  636.  * copy. On Unix the backup has the same name as the
  637.  * original file, with a "~" on the end; this seems to
  638.  * be newest of the new-speak. The error handling is
  639.  * all in "file.c". The "unlink" is perhaps not the
  640.  * right thing here; I don't care that much as
  641.  * I don't enable backups myself.
  642.  */
  643. fbackupfile(fn) char *fn; {
  644.     register char    *nname;
  645.     char        *malloc();
  646.     char        buf[NFILEN];
  647.  
  648.     fn = bsd(fn, buf, sizeof(buf));
  649.     if ((nname=malloc(strlen(fn)+1+1)) == NULL) {
  650.         ewprintf("Can't get %d bytes", strlen(fn) + 1);
  651.         return (ABORT);
  652.     }
  653.     (void) strcpy(nname, fn);
  654.     (void) strcat(nname, "~");
  655.     (void) unlink(nname);            /* Ignore errors.    */
  656.     if (rename(fn, nname) < 0) {
  657.         free(nname);
  658.         return (FALSE);
  659.     }
  660.     free(nname);
  661.     return (TRUE);
  662. }
  663. #endif
  664. /*
  665.  * The string "fn" is a file name.
  666.  * Perform any required case adjustments. All sustems
  667.  * we deal with so far have case insensitive file systems.
  668.  * We zap everything to lower case. The problem we are trying
  669.  * to solve is getting 2 buffers holding the same file if
  670.  * you visit one of them with the "caps lock" key down.
  671.  * On UNIX file names are dual case, so we leave
  672.  * everything alone.
  673.  */
  674. /*ARGSUSED*/
  675. adjustcase(fn) register char *fn; {
  676. #if    0
  677.     register int    c;
  678.  
  679.     while ((c = *fn) != 0) {
  680.         if (c>='A' && c<='Z')
  681.             *fn = c + 'a' - 'A';
  682.         ++fn;
  683.     }
  684. #endif
  685. }
  686.  
  687. #ifdef    STARTUP
  688. #include <sys/file.h>
  689. /*
  690.  * find the users startup file, and return it's name. Check for
  691.  * $HOME/.mg then for $HOME/.emacs, then give up.
  692.  */
  693. char *
  694. startupfile() {
  695.     register char    *file;
  696.     static char    home[NFILEN];
  697.     char        *getenv();
  698.  
  699.     if ((file = getenv("HOME")) == NULL) return NULL;
  700.     if (strlen(file)+7 >= NFILEN - 1) return NULL;
  701.     (VOID) strcpy(home, file);
  702.     file = &(home[strlen(home)]);
  703.     *file++ = '/';
  704.  
  705.     (VOID) strcpy(file, ".mg");
  706.     if (access(home, F_OK ) == 0) return home;
  707.  
  708.     (VOID) strcpy(file, ".emacs");
  709.     if (access(home, F_OK) == 0) return home;
  710.  
  711.     return NULL;
  712. }
  713. #endif
  714. SHAR_EOF
  715. fi # end of overwriting check
  716. if test -f 'sys/bsd/spawn.c'
  717. then
  718.     echo shar: will not over-write existing file "'sys/bsd/spawn.c'"
  719. else
  720. cat << \SHAR_EOF > 'sys/bsd/spawn.c'
  721. /*
  722.  * Spawn. New version, which
  723.  * interracts with the job control stuff
  724.  * in the 4.X BSD C shell.
  725.  * Last edit:  Wed Aug 27 11:16:07 PDT 1986
  726.  * By:           rtech!daveb, to use stop for ksh.
  727.  */
  728. #include    "def.h"
  729.  
  730. #include    <sgtty.h>
  731. #include    <signal.h>
  732.  
  733. char    *shellp    = NULL;            /* Saved "SHELL" name.        */
  734.  
  735. extern    struct    sgttyb    oldtty;        /* There really should be a    */
  736. extern    struct    sgttyb    newtty;        /* nicer way of doing this, so    */
  737. extern    struct    sgttyb    oldtchars;    /* spawn does not need to know    */
  738. extern    struct    sgttyb    newtchars;    /* about the insides of the    */
  739. extern    struct    sgttyb    oldltchars;    /* terminal I/O code.        */
  740. extern    struct    sgttyb    newltchars;
  741.  
  742. extern    char    *getenv();
  743.  
  744. /*
  745.  * This code does a one of 2 different
  746.  * things, depending on what version of the shell
  747.  * you are using. If you are using the C shell, which
  748.  * implies that you are using job control, then MicroEMACS
  749.  * moves the cursor to a nice place and sends itself a
  750.  * stop signal. If you are using the Bourne shell it runs
  751.  * a subshell using fork/exec. Bound to "C-C", and used
  752.  * as a subcommand by "C-Z".
  753.  *
  754.  * Daveb -- changed sense of test so that we only spawn if you
  755.  *        are explicitly using /bin/sh.  This makes it stop
  756.  *        work with the ksh.
  757.  */
  758. /*ARGSUSED*/
  759. spawncli(f, n, k) {
  760.     register int    pid, wpid, (*oqsig)(), (*oisig)(), omask;
  761.     int        status;
  762.  
  763.     if (shellp == NULL) {
  764.         shellp = getenv("SHELL");
  765.         if (shellp == NULL)
  766.             shellp = getenv("shell");
  767.         if (shellp == NULL)
  768.             shellp = "/bin/sh";    /* Safer.        */
  769.     }
  770.     ttcolor(CTEXT);
  771.     ttnowindow();
  772.     if (strcmp(shellp, "/bin/csh") == 0) {
  773.         if (epresf != FALSE) {
  774.             ttmove(nrow-1, 0);
  775.             tteeol();
  776.             epresf = FALSE;
  777.         }                /* Csh types a "\n"    */
  778.         ttmove(nrow-2, 0);        /* before "Stopped".    */
  779.     } else {
  780.         ttmove(nrow-1, 0);
  781.         if (epresf != FALSE) {
  782.             tteeol();
  783.             epresf = FALSE;
  784.         }
  785.     }
  786.     ttflush();
  787.     if (ioctl(0, TIOCSLTC, (char *) &oldltchars) < 0
  788.     ||  ioctl(0, TIOCSETC, (char *) &oldtchars)  < 0
  789.     ||  ioctl(0, TIOCSETP, (char *) &oldtty)     < 0) {
  790.         ewprintf("IOCTL #1 to terminal failed");
  791.         return (FALSE);
  792.     }
  793.     if (strcmp(shellp, "/bin/sh") != 0) {    /* C shell, ksh        */
  794.         omask = sigsetmask(0);
  795.         (void) kill(0, SIGTSTP);
  796.         setttysize() ;
  797.         (void) sigsetmask(omask);
  798.     } else {                /* Bourne shell.    */
  799.         oqsig = signal(SIGQUIT, SIG_IGN);
  800.         oisig = signal(SIGINT,  SIG_IGN);
  801.         if ((pid=fork()) < 0) {
  802.             (void) signal(SIGQUIT, oqsig);
  803.             (void) signal(SIGINT,  oisig);
  804.             ewprintf("Failed to create process");
  805.             return (FALSE);
  806.         }
  807.         if (pid == 0) {
  808.             execl(shellp, "sh", "-i", NULL);
  809.             _exit(0);        /* Should do better!    */
  810.         }
  811.         while ((wpid=wait(&status))>=0 && wpid!=pid)
  812.             ;
  813.         (void) signal(SIGQUIT, oqsig);
  814.         (void) signal(SIGINT,  oisig);
  815.     }
  816.     sgarbf = TRUE;                /* Force repaint.    */
  817.     if (ioctl(0, TIOCSETP, (char *) &newtty)     < 0
  818.     ||  ioctl(0, TIOCSETC, (char *) &newtchars)  < 0
  819.     ||  ioctl(0, TIOCSLTC, (char *) &newltchars) < 0) {
  820.         ewprintf("IOCTL #2 to terminal failed");
  821.         return (FALSE);
  822.     }
  823.     return (TRUE);
  824. }
  825. SHAR_EOF
  826. fi # end of overwriting check
  827. if test -f 'sys/bsd/sysdef.h'
  828. then
  829.     echo shar: will not over-write existing file "'sys/bsd/sysdef.h'"
  830. else
  831. cat << \SHAR_EOF > 'sys/bsd/sysdef.h'
  832. /*
  833.  *        Ultrix-32 system header file.
  834.  */
  835. #define    PCC    1            /* "[]" gets an error.        */
  836. #define    KBLOCK    8192            /* Kill grow.            */
  837. #define    GOOD    0            /* Good exit status.        */
  838.  
  839. typedef int    RSIZE;            /* Type for file/region sizes    */
  840. typedef short    KEY;            /* Type for internal keystrokes    */
  841.  
  842. /*
  843.  * Macros used by the buffer name making code.
  844.  * Start at the end of the file name, scan to the left
  845.  * until BDC1 (or BDC2, if defined) is reached. The buffer
  846.  * name starts just to the right of that location, and
  847.  * stops at end of string (or at the next BDC3 character,
  848.  * if defined). BDC2 and BDC3 are mainly for VMS.
  849.  */
  850. #define    BDC1    '/'            /* Buffer names.        */
  851. SHAR_EOF
  852. fi # end of overwriting check
  853. if test -f 'sys/bsd/ttyio.c'
  854. then
  855.     echo shar: will not over-write existing file "'sys/bsd/ttyio.c'"
  856. else
  857. cat << \SHAR_EOF > 'sys/bsd/ttyio.c'
  858. /*
  859.  *        Ultrix-32 and Unix terminal I/O.
  860.  * The functions in this file
  861.  * negotiate with the operating system for
  862.  * keyboard characters, and write characters to
  863.  * the display in a barely buffered fashion.
  864.  */
  865. #include    "def.h"
  866.  
  867. #include    <sgtty.h>
  868.  
  869. #define    NOBUF    512            /* Output buffer size.        */
  870.  
  871. char    obuf[NOBUF];            /* Output buffer.        */
  872. int    nobuf;
  873. struct    sgttyb    oldtty;            /* V6/V7 stty data.        */
  874. struct    sgttyb    newtty;
  875. struct    tchars    oldtchars;        /* V7 editing.            */
  876. struct    tchars    newtchars;
  877. struct    ltchars oldltchars;        /* 4.2 BSD editing.        */
  878. struct    ltchars    newltchars;
  879. #ifdef    TIOCGWINSZ
  880. struct    winsize    winsize;        /* 4.3 BSD window sizing    */
  881. #endif
  882. int    nrow;                /* Terminal size, rows.        */
  883. int    ncol;                /* Terminal size, columns.    */
  884.  
  885. /*
  886.  * This function gets called once, to set up
  887.  * the terminal channel. On Ultrix is's tricky, since
  888.  * we want flow control, but we don't want any characters
  889.  * stolen to send signals. Use CBREAK mode, and set all
  890.  * characters but start and stop to 0xFF.
  891.  */
  892. ttopen() {
  893.         register char *tv_stype;
  894.         char *getenv(), *tgetstr(), tcbuf[1024], err_str[72];
  895.  
  896.     if (ioctl(0, TIOCGETP, (char *) &oldtty) < 0)
  897.         panic("ttopen can't get sgtty");
  898.     newtty.sg_ospeed = oldtty.sg_ospeed;
  899.     newtty.sg_ispeed = oldtty.sg_ispeed;
  900.     newtty.sg_erase  = oldtty.sg_erase;
  901.     newtty.sg_kill   = oldtty.sg_kill;
  902.     newtty.sg_flags  = oldtty.sg_flags;
  903.     newtty.sg_flags &= ~(ECHO|CRMOD);    /* Kill echo, CR=>NL.    */
  904. #ifdef FLOWCONTROL
  905.     newtty.sg_flags |= CBREAK;        /* Half-cooked mode.    */
  906. #else
  907.     newtty.sg_flags |= RAW|ANYP;        /* raw mode for 8 bit path.*/
  908. #endif
  909.     if (ioctl(0, TIOCSETP, (char *) &newtty) < 0)
  910.         panic("ttopen can't set sgtty");
  911.     if (ioctl(0, TIOCGETC, (char *) &oldtchars) < 0)
  912.         panic("ttopen can't get chars");
  913.     newtchars.t_intrc  = 0xFF;        /* Interrupt.        */
  914.     newtchars.t_quitc  = 0xFF;        /* Quit.        */
  915. #if FLOWCONTROL
  916.     newtchars.t_startc = 0x11;        /* ^Q, for terminal.    */
  917.     newtchars.t_stopc  = 0x13;        /* ^S, for terminal.    */
  918. #else
  919.     newtchars.t_startc = 0xFF;        /* ^Q, for terminal.    */
  920.     newtchars.t_stopc  = 0xFF;        /* ^S, for terminal.    */
  921. #endif
  922.     newtchars.t_eofc   = 0xFF;
  923.     newtchars.t_brkc   = 0xFF;
  924.     if (ioctl(0, TIOCSETC, (char *) &newtchars) < 0)
  925.         panic("ttopen can't set chars");
  926.     if (ioctl(0, TIOCGLTC, (char *) &oldltchars) < 0)
  927.         panic("ttopen can't get ltchars");
  928.     newltchars.t_suspc  = 0xFF;        /* Suspend #1.        */
  929.     newltchars.t_dsuspc = 0xFF;        /* Suspend #2.        */
  930.     newltchars.t_rprntc = 0xFF;
  931.     newltchars.t_flushc = 0xFF;        /* Output flush.    */
  932.     newltchars.t_werasc = 0xFF;
  933.     newltchars.t_lnextc = 0xFF;        /* Literal next.    */
  934.     if (ioctl(0, TIOCSLTC, (char *) &newltchars) < 0)
  935.         panic("ttopen can't set ltchars");
  936.  
  937. /* do this the REAL way */
  938.         if ((tv_stype = getenv("TERM")) == NULL)
  939.         {
  940.                 puts("Environment variable TERM not defined!");
  941.                 exit(1);
  942.         }
  943.  
  944.         if((tgetent(tcbuf, tv_stype)) != 1)
  945.         {
  946.                 (void) sprintf(err_str, "Unknown terminal type %s!", tv_stype);
  947.                 puts(err_str);
  948.                 exit(1);
  949.         }
  950.  
  951.     setttysize() ;
  952. }
  953.  
  954. /*
  955.  * This function gets called just
  956.  * before we go back home to the shell. Put all of
  957.  * the terminal parameters back.
  958.  */
  959. ttclose() {
  960.     ttflush();
  961.     if (ioctl(0, TIOCSLTC, (char *) &oldltchars) < 0)
  962.         panic("ttclose can't set ltchars");
  963.     if (ioctl(0, TIOCSETC, (char *) &oldtchars) < 0)
  964.         panic("ttclose can't set chars");
  965.     if (ioctl(0, TIOCSETP, (char *) &oldtty) < 0)
  966.         panic("ttclose can't set sgtty");
  967. }
  968.  
  969. /*
  970.  * Write character to the display.
  971.  * Characters are buffered up, to make things
  972.  * a little bit more efficient.
  973.  */
  974. ttputc(c) {
  975.     if (nobuf >= NOBUF)
  976.         ttflush();
  977.     obuf[nobuf++] = c;
  978. }
  979.  
  980. /*
  981.  * Flush output.
  982.  */
  983. ttflush() {
  984.     if (nobuf != 0) {
  985.         if (write(1, obuf, nobuf) != nobuf)
  986.             panic("ttflush write failed");
  987.         nobuf = 0;
  988.     }
  989. }
  990.  
  991. /*
  992.  * Read character from terminal.
  993.  * All 8 bits are returned, so that you can use
  994.  * a multi-national terminal.
  995.  */
  996. ttgetc() {
  997.     char    buf[1];
  998.  
  999.     while (read(0, &buf[0], 1) != 1)
  1000.         ;
  1001.     return (buf[0] & 0xFF);
  1002. }
  1003. /*
  1004.  * set the tty size. Functionized for 43BSD.
  1005.  */
  1006. setttysize() {
  1007.  
  1008. #ifdef    TIOCGWINSZ
  1009.     if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
  1010.         nrow = winsize . ws_row;
  1011.         ncol = winsize . ws_col;
  1012.     } else nrow = 0;
  1013.      if(nrow<=0 || ncol<=0)
  1014. #endif
  1015.     if ((nrow=tgetnum ("li")) <= 0
  1016.     || (ncol=tgetnum ("co")) <= 0) {
  1017.         nrow = 24;
  1018.         ncol = 80;
  1019.     }
  1020.     if (nrow > NROW)            /* Don't crash if the    */
  1021.         nrow = NROW;            /* termcap entry is    */
  1022.     if (ncol > NCOL)            /* too big.        */
  1023.         ncol = NCOL;
  1024. }
  1025.  
  1026. /*
  1027.  * typeahead returns TRUE if there are characters available to be read
  1028.  * in.
  1029.  */
  1030. typeahead() {
  1031.     int    x;
  1032.  
  1033.     return((ioctl(0, FIONREAD, (char *) &x) < 0) ? 0 : x);
  1034. }
  1035.  
  1036. /*
  1037.  * panic - just exit, as quickly as we can.
  1038.  */
  1039. panic(s) char *s; {
  1040.     printf(stderr, "panic: %s\n", s);
  1041.     abort();        /* To leave a core image. */
  1042. }
  1043. SHAR_EOF
  1044. fi # end of overwriting check
  1045. if test -f 'sys/sysv/Makefile'
  1046. then
  1047.     echo shar: will not over-write existing file "'sys/sysv/Makefile'"
  1048. else
  1049. cat << \SHAR_EOF > 'sys/sysv/Makefile'
  1050. # Makefile for MicroEMACS.
  1051. # Is there a better way to do the rebuilds, other than using
  1052. # the links?
  1053.  
  1054. SYS    = sysv
  1055. TTY    = termcap
  1056. # you may not need (or have) termlib...
  1057. LIBS    = -lcurses -ltermlib
  1058. # CDEFS gets defines, and gets passed to lint. CFLAGS gets flags, and doesn't
  1059. # get passed to lint.
  1060. CDEFS    = -DDO_METAKEY
  1061. CFLAGS    = -g $(CDEFS)
  1062.  
  1063. OBJ =    basic.o buffer.o cinfo.o display.o echo.o extend.o file.o kbd.o \
  1064.     line.o main.o match.o random.o region.o search.o symbol.o version.o \
  1065.     window.o paragraph.o prefix.o \
  1066.     word.o fileio.o spawn.o ttyio.o tty.o ttykbd.o
  1067. OSRCS = fileio.c spawn.c ttyio.c tty.c ttykbd.c
  1068. SRCS =    basic.c buffer.c cinfo.c display.c echo.c extend.c file.c kbd.c \
  1069.     line.c main.c match.o random.c region.c search.c symbol.c version.c \
  1070.     window.c word.c paragraph.c prefix.c
  1071. OINCS =    ttydef.h sysdef.h
  1072. INCS =    def.h
  1073.  
  1074. mg:        $(OBJ)
  1075.         cc $(CFLAGS) -o mg $(OBJ) $(LIBS)
  1076.  
  1077. # for AT&T UNIX-PC
  1078. mg.7300:    $(OBJ)
  1079.         ld /lib/crt0s.o /lib/shlib.ifile $(OBJ) -o mg.7300
  1080.  
  1081. lint: $(SRCS) $(OSRCS)
  1082.         lint $(CDEFS) $(SRCS) $(OSRCS)
  1083.  
  1084. $(OBJ):        def.h sysdef.h ttydef.h
  1085.  
  1086. sysdef.h:    sys/$(SYS)/sysdef.h    # Update links, if needed.
  1087.         rm -f sysdef.h
  1088.         ln sys/$(SYS)/sysdef.h .
  1089.  
  1090. ttydef.h:    tty/$(TTY)/ttydef.h
  1091.         rm -f ttydef.h
  1092.         ln tty/$(TTY)/ttydef.h .
  1093.  
  1094. fileio.c:    sys/$(SYS)/fileio.c
  1095.         rm -f fileio.c
  1096.         ln sys/$(SYS)/fileio.c .
  1097.  
  1098. spawn.c:    sys/$(SYS)/spawn.c
  1099.         rm -f spawn.c
  1100.         ln sys/$(SYS)/spawn.c .
  1101.  
  1102. tty.c:        tty/$(TTY)/tty.c
  1103.         rm -f tty.c
  1104.         ln tty/$(TTY)/tty.c .
  1105.  
  1106. ttyio.c:    sys/$(SYS)/ttyio.c
  1107.         rm -f ttyio.c
  1108.         ln sys/$(SYS)/ttyio.c .
  1109.  
  1110. ttykbd.c:    tty/$(TTY)/ttykbd.c
  1111.         rm -f ttykbd.c
  1112.         ln tty/$(TTY)/ttykbd.c .
  1113.  
  1114. clean:;        rm -f $(OBJ) $(OSRCS) $(OINCS)
  1115. SHAR_EOF
  1116. fi # end of overwriting check
  1117. if test -f 'sys/sysv/fileio.c'
  1118. then
  1119.     echo shar: will not over-write existing file "'sys/sysv/fileio.c'"
  1120. else
  1121. cat << \SHAR_EOF > 'sys/sysv/fileio.c'
  1122. /*
  1123.  * Name:    MicroEMACS
  1124.  *         System V file I/O
  1125.  */
  1126. #include    "def.h"
  1127.  
  1128. # ifndef F_OK
  1129. # define F_OK    0
  1130. # define X_OK    1
  1131. # define W_OK    2
  1132. # define R_OK    4
  1133. # endif
  1134.  
  1135. /*
  1136.  * Move bytes, overlaps OK (daveb).
  1137.  *
  1138.  * Doesn't really belong here, but it's system specific since it
  1139.  * is in assembler in some C libraries.
  1140.  */
  1141. bcopy( from, to, cnt )
  1142. char *from;
  1143. char *to;
  1144. int cnt;
  1145. {
  1146.     if ( from == to )
  1147.         return;
  1148.  
  1149.     if( from > to )
  1150.     {
  1151.         while( cnt-- )
  1152.             *to++ = *from++;
  1153.     }
  1154.     else
  1155.     {
  1156.         to += cnt;
  1157.         from += cnt;
  1158.         while( cnt-- )
  1159.             *--to = *--from;
  1160.     }
  1161. }
  1162.  
  1163.  
  1164. static    FILE    *ffp;
  1165.  
  1166. /*
  1167.  * Open a file for reading.
  1168.  */
  1169. ffropen(fn)
  1170. char    *fn;
  1171. {
  1172.     if ((ffp=fopen(fn, "r")) == NULL)
  1173.         return (FIOFNF);
  1174.     return (FIOSUC);
  1175. }
  1176.  
  1177. /*
  1178.  * Open a file for writing.
  1179.  * Return TRUE if all is well, and
  1180.  * FALSE on error (cannot create).
  1181.  */
  1182. ffwopen(fn)
  1183. char    *fn;
  1184. {
  1185.     if ((ffp=fopen(fn, "w")) == NULL) {
  1186.         ewprintf("Cannot open file for writing");
  1187.         return (FIOERR);
  1188.     }
  1189.     return (FIOSUC);
  1190. }
  1191.  
  1192. /*
  1193.  * Close a file.
  1194.  * Should look at the status.
  1195.  */
  1196. ffclose()
  1197. {
  1198.     (VOID) fclose(ffp);
  1199.     return (FIOSUC);
  1200. }
  1201.  
  1202. /*
  1203.  * Write a line to the already
  1204.  * opened file. The "buf" points to the
  1205.  * buffer, and the "nbuf" is its length, less
  1206.  * the free newline. Return the status.
  1207.  * Check only at the newline.
  1208.  */
  1209. ffputline(buf, nbuf)
  1210. register char    buf[];
  1211. {
  1212.     register int    i;
  1213.  
  1214.     for (i=0; i<nbuf; ++i)
  1215.         putc(buf[i]&0xFF, ffp);
  1216.     putc('\n', ffp);
  1217.     if (ferror(ffp) != FALSE) {
  1218.         ewprintf("Write I/O error");
  1219.         return (FIOERR);
  1220.     }
  1221.     return (FIOSUC);
  1222. }
  1223.  
  1224. /*
  1225.  * Read a line from a file, and store the bytes
  1226.  * in the supplied buffer. Stop on end of file or end of
  1227.  * line. Don't get upset by files that don't have an end of
  1228.  * line on the last line; this seem to be common on CP/M-86 and
  1229.  * MS-DOS (the suspected culprit is VAX/VMS kermit, but this
  1230.  * has not been confirmed. If this is sufficiently researched
  1231.  * it may be possible to pull this kludge). Delete any CR
  1232.  * followed by an LF. This is mainly for runoff documents,
  1233.  * both on VMS and on Ultrix (they get copied over from
  1234.  * VMS systems with DECnet).
  1235.  */
  1236. ffgetline(buf, nbuf)
  1237. register char    buf[];
  1238. {
  1239.     register int    c;
  1240.     register int    i;
  1241.  
  1242.     i = 0;
  1243.     for (;;) {
  1244.         c = getc(ffp);
  1245.         if (c == '\r') {        /* Delete any non-stray    */
  1246.             c = getc(ffp);        /* carriage returns.    */
  1247.             if (c != '\n') {
  1248.                 if (i >= nbuf-1) {
  1249.                     ewprintf("File has long line");
  1250.                     return (FIOERR);
  1251.                 }
  1252.                 buf[i++] = '\r';
  1253.             }
  1254.         }
  1255.         if (c==EOF || c=='\n')        /* End of line.        */
  1256.             break;
  1257.         if (i >= nbuf-1) {
  1258.             ewprintf("File has long line");
  1259.             return (FIOERR);
  1260.         }
  1261.         buf[i++] = c;
  1262.     }
  1263.     if (c == EOF) {                /* End of file.        */
  1264.         if (ferror(ffp) != FALSE) {
  1265.             ewprintf("File read error");
  1266.             return (FIOERR);
  1267.         }
  1268.         if (i == 0)            /* Don't get upset if    */
  1269.             return (FIOEOF);    /* no newline at EOF.    */
  1270.     }
  1271.     buf[i] = 0;
  1272.     return (FIOSUC);
  1273. }
  1274.  
  1275. #if    BACKUP
  1276. /*
  1277.  * Rename the file "fname" into a backup
  1278.  * copy. On Unix the backup has the same name as the
  1279.  * original file, with a "~" on the end; this seems to
  1280.  * be newest of the new-speak. The error handling is
  1281.  * all in "file.c". The "unlink" is perhaps not the
  1282.  * right thing here; I don't care that much as
  1283.  * I don't enable backups myself.
  1284.  */
  1285. fbackupfile(fname)
  1286. char    *fname;
  1287. {
  1288.     register char    *nname;
  1289.  
  1290.     if ((nname=malloc(strlen(fname)+1+1)) == NULL)
  1291.         return (ABORT);
  1292.     (void) strcpy(nname, fname);
  1293.     (void) strcat(nname, "~");
  1294.     (void) unlink(nname);            /* Ignore errors.    */
  1295.  
  1296.     /* no rename on System V, so do it dangerous way. */
  1297.     if ( link(fname, nname) < 0 || unlink(fname) < 0 ) {
  1298.         free(nname);
  1299.         return (FALSE);
  1300.     }
  1301.     free(nname);
  1302.     return (TRUE);
  1303. }
  1304. #endif
  1305.  
  1306. /*
  1307.  * The string "fn" is a file name.
  1308.  * Perform any required case adjustments. All sustems
  1309.  * we deal with so far have case insensitive file systems.
  1310.  * We zap everything to lower case. The problem we are trying
  1311.  * to solve is getting 2 buffers holding the same file if
  1312.  * you visit one of them with the "caps lock" key down.
  1313.  * On UNIX file names are dual case, so we leave
  1314.  * everything alone.
  1315.  */
  1316. /*ARGSUSED*/
  1317. adjustcase(fn)
  1318. register char    *fn;
  1319. {
  1320. #if    0
  1321.     register int    c;
  1322.  
  1323.     while ((c = *fn) != 0) {
  1324.         if (c>='A' && c<='Z')
  1325.             *fn = c + 'a' - 'A';
  1326.         ++fn;
  1327.     }
  1328. #endif
  1329. }
  1330.  
  1331.  
  1332.  
  1333. #ifdef    STARTUP
  1334. #include <sys/types.h>
  1335. #include <sys/file.h>
  1336. /*
  1337.  * find the users startup file, and return it's name. Check for
  1338.  * $HOME/.mg then for $HOME/.emacs, then give up.
  1339.  */
  1340. char *
  1341. startupfile() 
  1342. {
  1343.     register char    *file;
  1344.     static char    home[NFILEN];
  1345.     char        *getenv();
  1346.  
  1347.     if ( (file = getenv("HOME")) == NULL 
  1348.          || strlen(file)+7 >= NFILEN - 1 ) 
  1349.         return NULL;
  1350.     (VOID) strcpy(home, file);
  1351.     file = &(home[strlen(home)]);
  1352.     *file++ = '/';
  1353.  
  1354.     (VOID) strcpy(file, ".mg");
  1355.     if (access(home, F_OK ) == 0) return home;
  1356.  
  1357.     (VOID) strcpy(file, ".emacs");
  1358.     if (access(home, F_OK) == 0) return home;
  1359.  
  1360.     return NULL;
  1361. }
  1362. #endif
  1363. SHAR_EOF
  1364. fi # end of overwriting check
  1365. if test -f 'sys/sysv/spawn.c'
  1366. then
  1367.     echo shar: will not over-write existing file "'sys/sysv/spawn.c'"
  1368. else
  1369. cat << \SHAR_EOF > 'sys/sysv/spawn.c'
  1370. /*
  1371.  * Name:    MicroEMACS
  1372.  *        Spawn CLI for System V.
  1373.  * Version:    0
  1374.  * Last edit:    17-Apr-86
  1375.  * By:        gonzo!daveb
  1376.  *        {sun, amdahl, mtxinu}!rtech!daveb
  1377.  *
  1378.  * Spawn for System V.
  1379.  */
  1380. #include    "def.h"
  1381.  
  1382. #include    <signal.h>
  1383.  
  1384. char    *shellp    = NULL;            /* Saved "SHELL" program.    */
  1385. char    *shname = NULL;            /* Saved shell name        */
  1386.  
  1387. extern    char    *getenv();
  1388.  
  1389. /*
  1390.  * On System V, we no gots job control, so always run
  1391.  * a subshell using fork/exec. Bound to "C-C", and used
  1392.  * as a subcommand by "C-Z". (daveb)
  1393.  *
  1394.  * Returns 0 if the shell executed OK, something else if
  1395.  * we couldn't start shell or it exited badly.
  1396.  */
  1397. spawncli(f, n, k)
  1398. {
  1399.     extern char    *strrchr();
  1400.     register int    pid;
  1401.     register int    wpid;
  1402.     register int    (*oqsig)();
  1403.     register int    (*oisig)();
  1404.     int        status;
  1405.     int        errp = FALSE;
  1406.  
  1407.     if (shellp == NULL) {
  1408.         shellp = getenv("SHELL");
  1409.         if (shellp == NULL)
  1410.             shellp = getenv("shell");
  1411.         if (shellp == NULL)
  1412.             shellp = "/bin/sh";    /* Safer.        */
  1413.         shname = strrchr( shellp, '/' ); 
  1414.         shname = shname ? shname++ : shellp;
  1415.         
  1416.     }
  1417.     ttcolor(CTEXT);
  1418.     ttnowindow();
  1419.     ttmove(nrow-1, 0);
  1420.     if (epresf != FALSE) {
  1421.         tteeol();
  1422.         epresf = FALSE;
  1423.     }
  1424.     ttclose();
  1425.     sgarbf = TRUE;                /* Force repaint.    */
  1426.     oqsig = signal(SIGQUIT, SIG_IGN);
  1427.     oisig = signal(SIGINT,  SIG_IGN);
  1428.     if ((pid=fork()) == 0) {
  1429.         execlp(shellp, shname, "-i", NULL);
  1430.         _exit(1);            /* Should do better!    */
  1431.     }
  1432.     else if (pid > 0) {
  1433.         while ((wpid=wait(&status))>=0 && wpid!=pid)
  1434.             ;
  1435.     }
  1436.     else errp = TRUE;
  1437.  
  1438.     signal(SIGINT,  oisig);
  1439.     ttopen();
  1440.     if(errp)
  1441.         ewprintf("Failed to create process");
  1442.  
  1443.     return ( errp | status );
  1444. }
  1445. SHAR_EOF
  1446. fi # end of overwriting check
  1447. if test -f 'sys/sysv/ttyio.c'
  1448. then
  1449.     echo shar: will not over-write existing file "'sys/sysv/ttyio.c'"
  1450. else
  1451. cat << \SHAR_EOF > 'sys/sysv/ttyio.c'
  1452. /*
  1453.  * Name:    MicroEMACS
  1454.  *        System V terminal I/O.
  1455.  * Version:    0
  1456.  * Last edit:    Tue Aug 26 23:57:57 PDT 1986
  1457.  * By:        gonzo!daveb
  1458.  *        {sun, amdahl, mtxinu}!rtech!gonzo!daveb
  1459.  *
  1460.  * The functions in this file
  1461.  * negotiate with the operating system for
  1462.  * keyboard characters, and write characters to
  1463.  * the display in a barely buffered fashion.
  1464.  *
  1465.  * This version goes along with tty/termcap/tty.c.
  1466.  * Terminal size is determined there, rather than here, and
  1467.  * this does not open the termcap file
  1468.  */
  1469. #include    "def.h"
  1470.  
  1471. #include    <sys/types.h>
  1472. #include    <fcntl.h>
  1473. #include    <termio.h>
  1474.  
  1475. #define    NOBUF    512            /* Output buffer size.        */
  1476.  
  1477. char    obuf[NOBUF];            /* Output buffer.        */
  1478. int    nobuf;                /* buffer count            */
  1479.  
  1480. static struct termio    ot;        /* entry state of the terminal    */
  1481. static struct termio    nt;        /* editor's terminal state    */
  1482.  
  1483. static int ttyactivep = FALSE;        /* terminal in editor mode?    */
  1484. static int ttysavedp = FALSE;        /* terminal state saved?    */
  1485.  
  1486. int    nrow;                /* Terminal size, rows.        */
  1487. int    ncol;                /* Terminal size, columns.    */
  1488.  
  1489. /* These are used to implement typeahead on System V */
  1490.  
  1491. int kbdflgs;            /* saved keyboard fd flags    */
  1492. int kbdpoll;            /* in O_NDELAY mode            */
  1493. int kbdqp;            /* there is a char in kbdq    */
  1494. char kbdq;            /* char we've already read    */
  1495.  
  1496. /*
  1497.  * This function gets called once, to set up
  1498.  * the terminal channel.  This version turns off flow
  1499.  * control.  This may be wrong for your system, but no
  1500.  * good solution has really been found (daveb).
  1501.  */
  1502. ttopen()
  1503. {
  1504.     register char    *cp;
  1505.     extern char    *getenv();
  1506.  
  1507.     if (ttyactivep)
  1508.         return;
  1509.  
  1510.     if( !ttysavedp )
  1511.     {
  1512.         if (ioctl(0, TCGETA, &ot) < 0)
  1513.             abort();
  1514.         nt = ot;        /* save entry state        */
  1515.         nt.c_cc[VMIN] = 1;    /* one character read is OK    */
  1516.         nt.c_cc[VTIME] = 0;    /* Never time out.        */
  1517.         nt.c_iflag |= IGNBRK;
  1518.         nt.c_iflag &= ~( ICRNL | INLCR | ISTRIP | IXON | IXOFF );
  1519.         nt.c_oflag &= ~OPOST;
  1520.         nt.c_cflag |= CS8;    /* allow 8th bit on input    */
  1521.         nt.c_cflag &= ~PARENB;    /* Don't check parity        */
  1522.         nt.c_lflag &= ~( ECHO | ICANON | ISIG );
  1523.  
  1524.         kbdflgs = fcntl( 0, F_GETFL, 0 );
  1525.         kbdpoll = FALSE;
  1526.     
  1527.         ttysavedp = TRUE;
  1528.     }
  1529.     
  1530.     if (ioctl(0, TCSETAF, &nt) < 0)
  1531.         abort();
  1532.  
  1533.     /* This really belongs in tty/termcap... */
  1534.  
  1535.     if ((cp=getenv("TERMCAP")) == NULL
  1536.     || (nrow=getvalue(cp, "li")) <= 0
  1537.     || (ncol=getvalue(cp, "co")) <= 0) {
  1538.         nrow = 24;
  1539.         ncol = 80;
  1540.     }
  1541.     if (nrow > NROW)            /* Don't crash if the    */
  1542.         nrow = NROW;            /* termcap entry is    */
  1543.     if (ncol > NCOL)            /* too big.        */
  1544.         ncol = NCOL;
  1545.  
  1546.     ttyactivep = TRUE;
  1547. }
  1548.  
  1549. /*
  1550.  * This routine scans a string, which is
  1551.  * actually the return value of a getenv call for the TERMCAP
  1552.  * variable, looking for numeric parameter "name". Return the value
  1553.  * if found. Return -1 if not there. Assume that "name" is 2
  1554.  * characters long. This limited use of the TERMCAP lets us find
  1555.  * out the size of a window on the X display.
  1556.  */
  1557. getvalue(cp, name)
  1558. register char    *cp;
  1559. register char    *name;
  1560. {
  1561.     for (;;) {
  1562.         while (*cp!=0 && *cp!=':')
  1563.             ++cp;
  1564.         if (*cp++ == 0)            /* Not found.        */
  1565.             return (-1);
  1566.         if (cp[0]==name[0] && cp[1]==name[1] && cp[2]=='#')
  1567.             return (atoi(cp+3));    /* Stops on ":".    */
  1568.     }
  1569. }
  1570.  
  1571. /*
  1572.  * This function gets called just
  1573.  * before we go back home to the shell. Put all of
  1574.  * the terminal parameters back.
  1575.  */
  1576. ttclose()
  1577. {
  1578.     if(!ttysavedp || !ttyactivep)
  1579.         return;
  1580.     ttflush();
  1581.     if (ioctl(0, TCSETAF, &ot) < 0 || fcntl( 0, F_SETFL, kbdflgs ) < 0)
  1582.         abort();
  1583.     ttyactivep = FALSE;
  1584. }
  1585.  
  1586. /*
  1587.  * Write character to the display.
  1588.  * Characters are buffered up, to make things
  1589.  * a little bit more efficient.
  1590.  */
  1591. ttputc(c)
  1592. {
  1593.     if (nobuf >= NOBUF)
  1594.         ttflush();
  1595.     obuf[nobuf++] = c;
  1596. }
  1597.  
  1598. /*
  1599.  * Flush output.
  1600.  */
  1601. ttflush()
  1602. {
  1603.     if (nobuf != 0) {
  1604.         write(1, obuf, nobuf);
  1605.         nobuf = 0;
  1606.     }
  1607. }
  1608.  
  1609. /*
  1610.  * Read character from terminal.
  1611.  * All 8 bits are returned, so that you can use
  1612.  * a multi-national terminal.
  1613.  *
  1614.  * If keyboard 'queue' already has typeahead from a typeahead() call,
  1615.  * just return it.  Otherwise, make sure we are in blocking i/o mode
  1616.  * and read a character.
  1617.  */
  1618. ttgetc()
  1619. {
  1620.     if( kbdqp )
  1621.         kbdqp = FALSE;
  1622.     else
  1623.     {
  1624.         if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 )
  1625.             abort();
  1626.         kbdpoll = FALSE;
  1627.         while (read(0, &kbdq, 1) != 1)
  1628.             ;
  1629.     }
  1630.     return ( kbdq & 0xff );
  1631. }
  1632.  
  1633. /*
  1634.  * Return non-FALSE if typeahead is pending.
  1635.  *
  1636.  * If already got unread typeahead, do nothing.
  1637.  * Otherwise, set keyboard to O_NDELAY if not already, and try
  1638.  * a one character read.
  1639.  */
  1640. typeahead()
  1641. {
  1642.     if( !kbdqp )
  1643.     {
  1644.         if( !kbdpoll && fcntl( 0, F_SETFL, kbdflgs | O_NDELAY ) < 0 )
  1645.             abort();
  1646.         kbdqp = (1 == read( 0, &kbdq, 1 ));
  1647.     }
  1648.     return ( kbdqp );
  1649. }
  1650.  
  1651.  
  1652. /*
  1653.  * panic:  print error and die, leaving core file.
  1654.  * Don't know why this is needed (daveb).
  1655.  */
  1656. panic(s)
  1657. char *s;
  1658. {
  1659.     fprintf(stderr, "%s\r\n", s);
  1660.     abort();
  1661. }
  1662.  
  1663.  
  1664. /*
  1665. ** This should check the size of the window, and reset if needed.
  1666. */
  1667.  
  1668. setttysize()
  1669. {
  1670. #ifdef    TIOCGWINSZ
  1671.     if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
  1672.         nrow = winsize . ws_row;
  1673.         ncol = winsize . ws_col;
  1674.     } else
  1675. #endif
  1676.     if ((nrow=tgetnum ("li")) <= 0
  1677.     || (ncol=tgetnum ("co")) <= 0) {
  1678.         nrow = 24;
  1679.         ncol = 80;
  1680.     }
  1681.     if (nrow > NROW)            /* Don't crash if the    */
  1682.         nrow = NROW;            /* termcap entry is    */
  1683.     if (ncol > NCOL)            /* too big.        */
  1684.         ncol = NCOL;
  1685. }
  1686.  
  1687. SHAR_EOF
  1688. fi # end of overwriting check
  1689. if test -f 'sys/sysv/sysdef.h'
  1690. then
  1691.     echo shar: will not over-write existing file "'sys/sysv/sysdef.h'"
  1692. else
  1693. cat << \SHAR_EOF > 'sys/sysv/sysdef.h'
  1694. /*
  1695.  * Name:    MicroEMACS
  1696.  *        Ultrix-32 system header file same for System V.
  1697.  * Version:    29
  1698.  * Last edit:    05-Feb-86
  1699.  * By:        rex::conroy
  1700.  *        decvax!decwrl!dec-rhea!dec-rex!conroy
  1701.  */
  1702. #define    PCC    1            /* "[]" gets an error.        */
  1703. #define    KBLOCK    8192            /* Kill grow.            */
  1704. #define    GOOD    0            /* Good exit status.        */
  1705.  
  1706. typedef int    RSIZE;            /* Type for file/region sizes    */
  1707. typedef short    KEY;            /* Type for internal keystrokes    */
  1708.  
  1709. /*
  1710.  * Macros used by the buffer name making code.
  1711.  * Start at the end of the file name, scan to the left
  1712.  * until BDC1 (or BDC2, if defined) is reached. The buffer
  1713.  * name starts just to the right of that location, and
  1714.  * stops at end of string (or at the next BDC3 character,
  1715.  * if defined). BDC2 and BDC3 are mainly for VMS.
  1716.  */
  1717. #define    BDC1    '/'            /* Buffer names.        */
  1718. SHAR_EOF
  1719. fi # end of overwriting check
  1720. if test -f 'sys/osk/readme.osk'
  1721. then
  1722.     echo shar: will not over-write existing file "'sys/osk/readme.osk'"
  1723. else
  1724. cat << \SHAR_EOF > 'sys/osk/readme.osk'
  1725. readme.osk for MicroGnuEmacs 1a                Nov 10, 1986
  1726.  
  1727. Copy sys/osk/makefile to .
  1728.  
  1729. copy sys/osk/varargs.h to /dd/defs/varargs.h if you don't have one.
  1730. (I think version 2.1 of the C compiler will include mine.)
  1731.  
  1732. Look at makefile for personal preference options and terminal selection.
  1733.  
  1734. Use make to compile.
  1735.  
  1736. Currently defined for termcap, assuming a termlib library exists.
  1737. (I've heard there will be one with version 2.1 of the C compiler.  I
  1738. can't distribute the one I have.)
  1739.  
  1740. Baud should be set correctly in tmode/xmode even if it is set in
  1741. hardware as it is on a QT+.  This is used for display optimization
  1742. and padding.
  1743.  
  1744. All files are indented assuming tabs every eight columns, and mg
  1745. itself uses tabs there.  I have no idea why Microware decided not to
  1746. follow this defacto industry standard, but at least they allow you to
  1747. change your system to whatever you want.
  1748.  
  1749. The enviornment variable TERM is used to determine your terminal type,
  1750. and HOME is used to find the .mg startup file.
  1751. SHAR_EOF
  1752. fi # end of overwriting check
  1753. if test -f 'sys/osk/sysdef.h'
  1754. then
  1755.     echo shar: will not over-write existing file "'sys/osk/sysdef.h'"
  1756. else
  1757. cat << \SHAR_EOF > 'sys/osk/sysdef.h'
  1758. /*
  1759.  * Os9/68K specific definitions for micrognuemacs
  1760.  */
  1761. #define    PCC            /* "[]" gets an error.            */
  1762. #define    KBLOCK    1024        /* Kill grow.                */
  1763. #define    GOOD    0        /* Good exit status.            */
  1764. #define    VARARGS            /* use my varargs.h rather than        */
  1765.                 /* the non-portable code supplied    */
  1766. #define NO_VOID_TYPE        /* void not supported yet        */
  1767. #define    SEOL    '\l'        /* used in search (because \r==\n)    */
  1768. #define PC PC_            /* compiler can't handle variable called PC */
  1769. #define SR SR_            /* or SR                */
  1770. #define NO_RESIZE        /* terminal doesn't change size        */
  1771.  
  1772. /* typedefs for gnu version */
  1773. typedef int    RSIZE;        /* Type for file/region sizes    */
  1774. typedef short    KEY;        /* Type for internal keystrokes    */
  1775.  
  1776. /*
  1777.  * Macros used by the buffer name making code.
  1778.  * Start at the end of the file name, scan to the left
  1779.  * until BDC1 (or BDC2, if defined) is reached. The buffer
  1780.  * name starts just to the right of that location, and
  1781.  * stops at end of string (or at the next BDC3 character,
  1782.  * if defined). BDC2 and BDC3 are mainly for VMS.
  1783.  */
  1784. #define    BDC1    '/'            /* Buffer names.        */
  1785.  
  1786. /*
  1787.  * Needed for lots of small mallocs on os9/68k.  _memmins should be 
  1788.  * (maximum malloced memory)/16.  (defalt _memmins is 4096) 
  1789.  * Note that malloc may now fail if there isn't _memmins bytes 
  1790.  * contiguous free memory.  _memins could be reduced and the malloc 
  1791.  * tried again.  (Not currently implemented.)
  1792.  */
  1793. #ifdef MAXMEM
  1794. #  define SYSINIT    {extern int _memmins;    _memmins=MAXMEM*64; }
  1795. #else
  1796. #  define SYSINIT    {extern int _memmins;    _memmins=32768; }
  1797. #endif
  1798.  
  1799. /* see "caveates" in the osk C manual on _strass */
  1800. #define bcopy(from,to,len)    _strass(to,from,len)
  1801.  
  1802. /* see comments on these in display.c.  OSK can't stand the wasted memory
  1803.  * without making the score array "remote", which generates lousy code.  
  1804.  * Besides, I don't have an extra 100kb of memory for the score array.
  1805.  */
  1806. #define    XCHAR    char
  1807. #define XSHORT    short
  1808. SHAR_EOF
  1809. fi # end of overwriting check
  1810. if test -f 'sys/osk/varargs.h'
  1811. then
  1812.     echo shar: will not over-write existing file "'sys/osk/varargs.h'"
  1813. else
  1814. cat << \SHAR_EOF > 'sys/osk/varargs.h'
  1815. /* varargs.h for os9/68k by Robert A. Larson    */
  1816. /* version 0 for os9/68k C 2.0 04/20/86        */
  1817. /* varargs is a "portable" way to write a routine that takes a variable */
  1818. /* number of arguements.  This implemination agrees with both the 4.2bsd*/
  1819. /* and Sys V documentation of varargs.  Note that just because varargs.h*/
  1820. /* is used does not mean that it is used properly.            */
  1821. /* Ignore the "expression with little effect" warnings.  (Seems to be a */
  1822. /* compiler bug.)                            */
  1823.  
  1824. #define va_alist    _va_arg1, _va_arg2, _va_arg3
  1825.  
  1826. #define va_dcl        unsigned _va_arg1, _va_arg2, _va_arg3;
  1827.  
  1828. typedef    struct {
  1829.       unsigned _va_at;  /* number of arguments used, 0, 1, or more  */
  1830.                             /* (double as first arg counts as 2)        */
  1831.       union {
  1832.         struct {
  1833.           unsigned _va_uns1, _va_uns2;
  1834.         } _va_uuns;
  1835.         double _va_udouble;
  1836.       } _va_union;
  1837.       char *_va_pointer;
  1838.         } va_list;
  1839.  
  1840. #define    va_start(pvar)    ( (pvar)._va_at = 0,                \
  1841.               (pvar)._va_union._va_uuns._va_uns1 = _va_arg1,\
  1842.               (pvar)._va_union._va_uuns._va_uns2 = _va_arg2,\
  1843.               (pvar)._va_pointer = (char *) &_va_arg3    \
  1844.             )
  1845.  
  1846. #define va_arg(pvar, type)    (                \
  1847.     ((pvar)._va_at++) ? (                    \
  1848.         ((pvar)._va_at == 2) ? (            \
  1849.             (sizeof(type) == 8) ? (            \
  1850.                 *(((type *)((pvar)._va_pointer))++)    \
  1851.             ) : (type)(                \
  1852.                 (pvar)._va_union._va_uuns._va_uns2    \
  1853.             )                    \
  1854.         ) : (                        \
  1855.  
  1856.             *(((type *)((pvar)._va_pointer))++)    \
  1857.         )                        \
  1858.     ) : (                            \
  1859.         (sizeof(type) == 8) ? (type)(            \
  1860.             (pvar)._va_at++,            \
  1861.             (pvar)._va_union._va_udouble        \
  1862.         ) : (type)(                    \
  1863.             (pvar)._va_union._va_uuns._va_uns1    \
  1864.         )                        \
  1865.     )                            \
  1866. )
  1867.  
  1868. #define va_end(pvar)                /* va_end is simple */
  1869. SHAR_EOF
  1870. fi # end of overwriting check
  1871. if test -f 'sys/osk/fileio.c'
  1872. then
  1873.     echo shar: will not over-write existing file "'sys/osk/fileio.c'"
  1874. else
  1875. cat << \SHAR_EOF > 'sys/osk/fileio.c'
  1876. /*
  1877.  * Os9/68k fileio.c for MicroGnuEmacs by Robert A. Larson
  1878.  *     system dependent file io routines
  1879.  */
  1880. #include    "def.h"
  1881.  
  1882. char    *getenv();
  1883.  
  1884. static    FILE    *ffp;
  1885.  
  1886. /*
  1887.  * Open a file for reading.
  1888.  */
  1889. ffropen(fn)
  1890. char    *fn;
  1891. {
  1892.     if ((ffp=fopen(fn, "r")) == NULL)
  1893.         return (FIOFNF);
  1894.     return (FIOSUC);
  1895. }
  1896.  
  1897. /*
  1898.  * Open a file for writing.
  1899.  * Return TRUE if all is well, and
  1900.  * FALSE on error (cannot create).
  1901.  */
  1902. ffwopen(fn)
  1903. char    *fn;
  1904. {
  1905.     if ((ffp=fopen(fn, "w")) == NULL) {
  1906.         ewprintf("Cannot open file for writing");
  1907.         return (FIOERR);
  1908.     }
  1909.     return (FIOSUC);
  1910. }
  1911.  
  1912. /*
  1913.  * Close a file.
  1914.  * Should look at the status.
  1915.  */
  1916. ffclose()
  1917. {
  1918.     fclose(ffp);
  1919.     return (FIOSUC);
  1920. }
  1921.  
  1922. /*
  1923.  * Write a line to the already
  1924.  * opened file. The "buf" points to the
  1925.  * buffer, and the "nbuf" is its length, less
  1926.  * the free newline. Return the status.
  1927.  * Check only at the newline.
  1928.  */
  1929. ffputline(buf, nbuf)
  1930. register char    buf[];
  1931. {
  1932.     register int    i;
  1933.  
  1934.     for (i=0; i<nbuf; ++i)
  1935.         putc(buf[i]&0xFF, ffp);
  1936.     putc('\n', ffp);
  1937.     if (ferror(ffp) != FALSE) {
  1938.         ewprintf("Write I/O error");
  1939.         return (FIOERR);
  1940.     }
  1941.     return (FIOSUC);
  1942. }
  1943.  
  1944. /*
  1945.  * Read a line from a file, and store the bytes
  1946.  * in the supplied buffer. Stop on end of file or end of
  1947.  * line. Don't get upset by files that don't have an end of
  1948.  * line on the last line; this seem to be common on CP/M-86 and
  1949.  * MS-DOS (the suspected culprit is VAX/VMS kermit, but this
  1950.  * has not been confirmed. If this is sufficiently researched
  1951.  * it may be possible to pull this kludge). 
  1952.  */
  1953. ffgetline(buf, nbuf)
  1954. register char    *buf;
  1955. {
  1956.     register int    c;
  1957.     register int    i;
  1958.  
  1959.     i = 0;
  1960.     for (;;) {
  1961.         c = getc(ffp);
  1962.         if (c==EOF || c=='\n')        /* End of line.        */
  1963.             break;
  1964.         if (i >= nbuf-1) {
  1965.             ewprintf("File has long line");
  1966.             return (FIOERR);
  1967.         }
  1968.         buf[i++] = c;
  1969.     }
  1970.     if (c == EOF) {                /* End of file.        */
  1971.         if (ferror(ffp) != FALSE) {
  1972.             ewprintf("File read error");
  1973.             return (FIOERR);
  1974.         }
  1975.         if (i == 0)            /* Don't get upset if    */
  1976.             return (FIOEOF);    /* no newline at EOF.    */
  1977.     }
  1978.     buf[i] = 0;
  1979.     return (FIOSUC);
  1980. }
  1981.  
  1982. #ifdef BACKUP
  1983. /*
  1984.  * Rename the file "fname" into a backup copy.
  1985.  * The backup copy is the same name with ".BAK" appended unless the file
  1986.  * name is to long.  If your file name is 28 characters long ending in ".BAK"
  1987.  * you lose.  The error handling is all in "file.c". 
  1988.  */
  1989. fbackupfile(fname)
  1990. char    *fname;
  1991. {
  1992.     register char    *params;
  1993.     int    status;
  1994.     register char    *fn;
  1995.     register int    fnamel;
  1996.     register int    fnl;
  1997.     char    *rindex();
  1998.  
  1999.     if((fn = rindex(fname, '/')) == NULL) fn = fname; else fn++;
  2000.     fnamel = strlen(fname);
  2001.     fnl = strlen(fn);
  2002.     if((params = malloc(strlen(fname)+strlen(fn)+6)) == NULL) 
  2003.         return(ABORT);
  2004. /* delete the old backup */
  2005.     strcpy(params, fname);
  2006.     if(fnl < 25) strcat(params, ".BAK");
  2007.         else strcpy(params+(fnamel-fnl+24), ".BAK");
  2008.     unlink(params);                /* ignore errors */
  2009. /* now do the rename (This is rather akward) */
  2010.     strcpy(params, fname);
  2011.     strcat(params, " ");
  2012.     strcat(params, fn);
  2013.     if(fnl < 25) strcat(params, ".BAK");
  2014.         else strcpy(params+fnamel+1+24, ".BAK");
  2015.     if(os9fork("rename", strlen(params)+1, params, 0, 0, 0, 0)==-1) {
  2016.         free(params);
  2017.         return (FALSE);
  2018.     }
  2019.     wait(&status);
  2020.     free(params);
  2021.     return ((status & 0xffff)==0);
  2022. }
  2023. #endif
  2024.  
  2025. /*
  2026.  * The string "fn" is a file name.
  2027.  * Perform any required case adjustments. All sustems
  2028.  * we deal with so far have case insensitive file systems.
  2029.  * We zap everything to lower case.  The problem we are trying
  2030.  * to solve is getting 2 buffers holding the same file if
  2031.  * you visit one of them with the "caps lock" key down.
  2032.  * On UNIX file names are dual case, so we leave
  2033.  * everything alone.  Os9's dual case storage but non-case sensitivity 
  2034.  * does not seem to be accounted for here.  I'm treating it as a 
  2035.  * mono-case system, but it would be better to beleive the file (if found)
  2036.  * or the user (if not).
  2037.  */
  2038. adjustcase(fn)
  2039. register char    *fn;
  2040. {
  2041.     register int    c;
  2042.  
  2043.     while ((c = *fn) != 0) {
  2044.         if (c>='A' && c<='Z')
  2045.             *fn = c + 'a' - 'A';
  2046.         ++fn;
  2047.     }
  2048. }
  2049.  
  2050. #ifndef MICRO
  2051. char *startupfile()
  2052. {
  2053.     static char startname[64];
  2054.     char *cp;
  2055.   
  2056.     if ((cp = getenv("HOME")) == NULL) return ".mg";
  2057.     strncpy(startname, cp, 64 - 4);
  2058.     strcat(startname, "/.mg");
  2059.     return startname;
  2060. }
  2061. #endif
  2062. SHAR_EOF
  2063. fi # end of overwriting check
  2064. if test -f 'sys/osk/spawn.c'
  2065. then
  2066.     echo shar: will not over-write existing file "'sys/osk/spawn.c'"
  2067. else
  2068. cat << \SHAR_EOF > 'sys/osk/spawn.c'
  2069. /*
  2070.  * Name:    MicroEMACS
  2071.  *        OS9/68k Spawn Shell
  2072.  * Version:    29ral
  2073.  * Last edit:    04/20/86
  2074.  * By:        Blarson@Usc-Ecl.Arpa
  2075.  *
  2076.  */
  2077. #include    "def.h"
  2078.  
  2079. #include    <sgstat.h>
  2080.  
  2081. extern    struct    sgbuf    oldtty;        /* There really should be a    */
  2082. extern    struct    sgbuf    newtty;        /* nicer way of doing this, so    */
  2083.  
  2084. spawncli(f, n, k)
  2085.                     /* what are f, n, and k?  They     */
  2086.                     /* arn't used by ultrix, so I    */
  2087.                     /* ignore them too.        */
  2088. {
  2089.     register int    pid;
  2090.     register int    wpid;
  2091.     int        status;
  2092.  
  2093.     ttcolor(CTEXT);
  2094.     ttnowindow();
  2095.     ttmove(nrow-1, 0);
  2096.     if (epresf != FALSE) {
  2097.         tteeol();
  2098.         epresf = FALSE;
  2099.     }
  2100.     ttflush();
  2101.     if(_ss_opt(0, &oldtty) == -1) {
  2102.         ewprintf("_ss_opt #1 to terminal failed");
  2103.         return (FALSE);
  2104.     }
  2105.     if((pid=os9fork("shell", 0, "", 0, 0, 0, 0)) == -1) {
  2106.         ewprintf("Failed to create process");
  2107.         return (FALSE);
  2108.     }
  2109.     while ((wpid=wait(&status))>=0 && wpid!=pid)
  2110.         ;
  2111.     sgarbf = TRUE;                /* Force repaint.    */
  2112.     if(_ss_opt(0, &newtty) == -1) {
  2113.         ewprintf("_ss_opt #2 to terminal failed");
  2114.         return (FALSE);
  2115.     }
  2116.     return (TRUE);
  2117. }
  2118. SHAR_EOF
  2119. fi # end of overwriting check
  2120. if test -f 'sys/osk/ttyio.c'
  2121. then
  2122.     echo shar: will not over-write existing file "'sys/osk/ttyio.c'"
  2123. else
  2124. cat << \SHAR_EOF > 'sys/osk/ttyio.c'
  2125. /*
  2126.  *    sys/osk/ttyio.c    by Robert A. Larson
  2127.  *
  2128.  * The functions in this file
  2129.  * negotiate with the operating system for
  2130.  * keyboard characters, and write characters to
  2131.  * the display in a barely buffered fashion.
  2132.  */
  2133. #include    "def.h"
  2134.  
  2135. #include    <sgstat.h>
  2136. #ifdef    DPROMPT
  2137. #  include    <varargs.h>
  2138. #  define S_RDY 2437            /* arbitrary user signal */
  2139. #endif
  2140.  
  2141. #define    NOBUF    512            /* Output buffer size.        */
  2142.  
  2143. char    obuf[NOBUF];            /* Output buffer.        */
  2144. int    nobuf;
  2145. struct    sgbuf    oldtty, newtty;
  2146. int    nrow;                /* Terminal size, rows.        */
  2147. int    ncol;                /* Terminal size, columns.    */
  2148. short    ospeed;                /* Terminal speed, for termlib.l */
  2149.  
  2150. #ifdef    DPROMPT
  2151. wakeup(signum)
  2152. int signum;
  2153. {
  2154.     /* ignore the signal */
  2155. }
  2156. #endif
  2157.  
  2158. /*
  2159.  * This function gets called once, to set up
  2160.  * the terminal channel.
  2161.  */
  2162.  
  2163. ttopen()
  2164. {
  2165.     if(_gs_opt(0, &oldtty) == -1) panic("can't get options");
  2166.     ospeed = oldtty.sg_baud;
  2167.     _strass(&newtty, &oldtty, sizeof(newtty));    /* newtty=oldtty; */
  2168.     if(oldtty.sg_class == 0) {             /* scf */
  2169.         newtty.sg_backsp=
  2170.         newtty.sg_delete=
  2171.         newtty.sg_echo  =
  2172.         newtty.sg_alf   =
  2173.         newtty.sg_pause =
  2174.         newtty.sg_bspch =
  2175.         newtty.sg_dlnch =
  2176.         newtty.sg_eorch =
  2177.         newtty.sg_eofch =
  2178.         newtty.sg_rlnch =
  2179.         newtty.sg_dulnch=
  2180.         newtty.sg_psch  =
  2181.         newtty.sg_kbich =
  2182.         newtty.sg_kbach = 0;
  2183. #ifndef    xon_xoff
  2184.         newtty.sg_xon   =
  2185.         newtty.sg_xoff  = 0;
  2186. #endif
  2187.         if(_ss_opt(0, &newtty) == -1) panic("can't set options");
  2188.         nrow = oldtty.sg_page == 0 ? NROW : oldtty.sg_page;
  2189.     } else {                /* not scf, fake it */
  2190.         nrow = NROW;
  2191.     }
  2192.     ncol = NCOL;
  2193. #ifdef    DPROMPT
  2194.     intercept(wakeup);        /* ignore signals */
  2195. #endif
  2196. }
  2197.  
  2198. /*
  2199.  * This function gets called just
  2200.  * before we go back home to the shell. Put all of
  2201.  * the terminal parameters back.
  2202.  */
  2203. ttclose()
  2204. {
  2205.     ttflush();
  2206.     if(_ss_opt(0, &oldtty) == -1) panic("can't reset options");
  2207. }
  2208.  
  2209. /*
  2210.  * Write character to the display.
  2211.  * Characters are buffered up, to make things
  2212.  * a little bit more efficient.
  2213.  */
  2214. ttputc(c)
  2215. {
  2216.     if (nobuf >= NOBUF)
  2217.         ttflush();
  2218.     obuf[nobuf++] = c;
  2219. }
  2220.  
  2221. /*
  2222.  * Flush output.
  2223.  */
  2224. ttflush()
  2225. {
  2226.     if (nobuf != 0) {
  2227.         write(1, obuf, nobuf);
  2228.         nobuf = 0;
  2229.     }
  2230. }
  2231.  
  2232. /*
  2233.  * Read character from terminal.
  2234.  * All 8 bits are returned, so that you can use
  2235.  * a multi-national terminal.
  2236.  */
  2237. ttgetc()
  2238. {
  2239.     char    buf[1];
  2240.  
  2241.     while (read(0, &buf[0], 1) != 1)
  2242.         ;
  2243.     return (buf[0] & 0xFF);
  2244. }
  2245.  
  2246. int typeahead()
  2247. {
  2248.   return _gs_rdy(0) > 0;
  2249. }
  2250.  
  2251. panic(s) char *s; {
  2252.   _ss_opt(0, &oldtty);            /*  ignore errors */
  2253.   fputs("Panic: ", stdout);        /* avoid printf, don't load all that */
  2254.   puts(s);
  2255.   exit(1);
  2256. }
  2257.  
  2258. #ifdef    DPROMPT
  2259. ttwait() {
  2260.   if(_gs_rdy(0) > 0) return FALSE;    /* already something waiting */
  2261.   _ss_ssig(0, S_RDY);            /* wake me when you have something */
  2262.   if(sleep(2)!=0) return FALSE;        /* sleep interupted */
  2263.   _ss_rel(0);
  2264.   return TRUE;
  2265. }
  2266. #endif
  2267. SHAR_EOF
  2268. fi # end of overwriting check
  2269. if test -f 'sys/osk/makefile'
  2270. then
  2271.     echo shar: will not over-write existing file "'sys/osk/makefile'"
  2272. else
  2273. cat << \SHAR_EOF > 'sys/osk/makefile'
  2274. # Makefile for OSK MicroGnuEMACS by Robert A. Larson
  2275. #    07/12/86    MicroGnuEMACS version
  2276. # Copy ./sys/osk/makefile to . before making.  Check
  2277. # OPTS and LIBS.
  2278. #
  2279. # mg is short for micrognuemacs.  Call it what you want.
  2280. NAME = mg
  2281. # terminal type or termcap
  2282. TERM = TERMCAP
  2283. # opts is for user definable options, such as:
  2284. #    BACKUP    define for automatic backups
  2285. #    CVMVAS    define for ^V and M-V to work in pages
  2286. #    MAXMEM    memory available to malloc in kbytes.  Default 512 (OSK only)
  2287. #    NLINE    maximum line length, default 256.  If big, use -m in LFLAGS.
  2288. #    DPROMPT    print delayed prompt strings for ESC, ^X, etc.
  2289. #    STARTUP startup file handling
  2290. #    PREFIXREGION    functions for prefixing a region
  2291. OPTS = -dBACKUP -dMAXMEM=320 -dNLINE=2048 -dDPROMPT -dSTARTUP
  2292. # termlib is needed for termcap.
  2293. LFLAGS = -l=/dd/lib/termlib.l -m=4
  2294. OBJ = basic.r \
  2295.  buffer.r \
  2296.  cinfo.r \
  2297.  display.r \
  2298.  echo.r \
  2299.  extend.r \
  2300.  file.r \
  2301.  kbd.r \
  2302.  line.r \
  2303.  main.r \
  2304.  match.r \
  2305.  paragraph.r \
  2306.  prefix.r \
  2307.  random.r \
  2308.  region.r \
  2309.  search.r \
  2310.  symbol.r \
  2311.  version.r \
  2312.  window.r \
  2313.  word.r
  2314. # these files are listed individually below
  2315. SYSOBJ = SYS/OSK/fileio.r \
  2316.  SYS/OSK/spawn.r \
  2317.  SYS/OSK/ttyio.r
  2318. # ditto
  2319. TERMOBJ = TTY/$(TERM)/tty.r \
  2320.  TTY/$(TERM)/ttykbd.r
  2321. #
  2322. $(NAME): $(OBJ) $(SYSOBJ) $(TERMOBJ) makefile
  2323.  cc -i -t=/r0 -f=$(NAME) $(LFLAGS) $(OBJ) $(SYSOBJ) $(TERMOBJ)
  2324. $(OBJ): def.h sysdef.h ttydef.h makefile
  2325.  cc -r -t=/r0 $(OPTS) $*.c
  2326. SYS/OSK/fileio.r: SYS/OSK/fileio.c def.h sysdef.h ttydef.h makefile
  2327.  cc -r=SYS/OSK -t=/r0 $(OPTS) SYS/OSK/fileio.c
  2328. SYS/OSK/spawn.r: SYS/OSK/spawn.c def.h sysdef.h ttydef.h makefile
  2329.  cc -r=SYS/OSK -t=/r0 $(OPTS) SYS/OSK/spawn.c
  2330. SYS/OSK/ttyio.r: SYS/OSK/ttyio.c def.h sysdef.h ttydef.h makefile
  2331.  cc -r=SYS/OSK -t=/r0 $(OPTS) SYS/OSK/ttyio.c
  2332. TTY/$(TERM)/tty.r: TTY/$(TERM)/tty.c def.h sysdef.h ttydef.h makefile
  2333.  cc -r=TTY/$(TERM) -t=/r0 $(OPTS) TTY/$(TERM)/tty.c
  2334. TTY/$(TERM)/ttykbd.r: TTY/$(TERM)/ttykbd.c def.h sysdef.h ttydef.h makefile
  2335.  cc -r=TTY/$(TERM) -t=/r0 $(OPTS) TTY/$(TERM)/ttykbd.c
  2336. # The touch commands are needed to update the modified time.
  2337. sysdef.h: SYS/OSK/sysdef.h
  2338.  copy -r -b=16 -w=. SYS/OSK/sysdef.h
  2339.  touch sysdef.h
  2340. ttydef.h: TTY/$(TERM)/ttydef.h makefile
  2341.  copy -r -b=16 -w=. TTY/$(TERM)/ttydef.h
  2342.  touch ttydef.h
  2343. SHAR_EOF
  2344. fi # end of overwriting check
  2345. #    End of shell archive
  2346. exit 0
  2347.  
  2348.