home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / stevie.zoo / stevie.6 < prev   
Encoding:
Text File  |  1990-03-14  |  59.7 KB  |  2,866 lines

  1.  
  2. : This is a shar archive.  Extract with sh, not csh.
  3. : The rest of this file will extract:
  4. : dos.c minix.c os2.c unix.c setenv.c ctags.c
  5. echo extracting - dos.c
  6. sed 's/^X//' > dos.c << '!EOR!'
  7. X/* $Header:
  8. X *
  9. X * MSDOS support for Stevie.
  10. X * Many of the functions in this file have two versions:
  11. X *   -    The original version, using ANSI escape sequences
  12. X *    (by Tim Thompson and/or Tony Andrews).
  13. X *    It requires a non-IBM ANSI driver, such as the shareware NANSI.SYS.
  14. X *   -    The BIOS-function version (by Larry A. Shurr).  The BIOS version
  15. X *    doesn't require an enhanced console driver such as NANSI.SYS.
  16. X *    Invoke it by #defining BIOS in ENV.H.
  17. X * Dave Tutelman has incorporated many features of Larry Shurr's BIOS
  18. X * version (such as colors and 43-line mode) into the ANSI version.
  19. X */
  20. X
  21. X#include "stevie.h"
  22. X#include <stdio.h>
  23. X#include <dos.h>
  24. X#include <signal.h>
  25. X
  26. Xchar    *getenv();
  27. X
  28. Xstatic    char    getswitch();
  29. Xstatic    void    setswitch();
  30. X
  31. X#ifdef BIOS
  32. Xvoid bios_t_ed();
  33. Xvoid bios_t_el();
  34. X#endif
  35. X
  36. Xenum hostval_e {hIBMPC, hTIPRO};
  37. Xtypedef enum hostval_e hostval;
  38. Xstatic    hostval    host_type   = 0;    /* Gets host computer type */
  39. X
  40. Xstatic    char    bgn_color   = 0x7;    /* For saving orig color */
  41. Xstatic    char    quitting_now= 0;    /* Set for windexit() */
  42. Xstatic    int    crt_int     = 0;    /* Gets CRT BIOS interrupt */
  43. Xstatic    char    bgn_page    = 0;    /* For saving current page (IBM PC) */
  44. Xstatic    char    bgn_mode    = 0;    /* For saving video mode (IBM PC) */
  45. X
  46. X#ifdef BIOS
  47. Xstatic    int    sav_curattr = 0;    /* For saving cursor attributes */
  48. Xstatic    int    sav_curpos  = 0;    /* For saving cursor position */
  49. X#endif
  50. X
  51. X/*
  52. X * inchar() - get a character from the keyboard
  53. X */
  54. Xint
  55. Xinchar()
  56. X{
  57. X    int    c;
  58. X
  59. X    got_int = FALSE;
  60. X
  61. X    for (;;beep()) {    /* loop until we get a valid character */
  62. X
  63. X        flushbuf();    /* flush any pending output */
  64. X
  65. X        switch (c = getch()) {
  66. X        case 0x1e:
  67. X            return K_CCIRCM;
  68. X        case 0:                /* special key */
  69. X            if (State != NORMAL) {
  70. X                c = getch();    /* throw away next char */
  71. X                continue;    /* and loop for another char */
  72. X            }
  73. X            switch (c = getch()) {
  74. X            case 0x50:
  75. X                return K_DARROW;
  76. X            case 0x48:
  77. X                return K_UARROW;
  78. X            case 0x4b:
  79. X                return K_LARROW;
  80. X            case 0x4d:
  81. X                return K_RARROW;
  82. X            case 0x47:        /* Home key */
  83. X                stuffin("1G");
  84. X                return -1;
  85. X            case 0x4f:        /* End key */
  86. X                stuffin("G");
  87. X                return -1;
  88. X            case 0x51:        /* PgDn key */
  89. X                stuffin(mkstr(CTRL('F')));
  90. X                return -1;
  91. X            case 0x49:        /* PgUp key */
  92. X                stuffin(mkstr(CTRL('B')));
  93. X                return -1;
  94. X            case 0x52:        /* insert key */
  95. X                return K_INSERT;
  96. X            case 0x53:        /* delete key */
  97. X                stuffin("x");
  98. X                return -1;
  99. X            /*
  100. X             * Hard-code some useful function key macros.
  101. X             */
  102. X            case 0x3b: /* F1 */
  103. X                stuffin(":help\n");
  104. X                return -1;
  105. X            case 0x3c: /* F2 */
  106. X                stuffin(":n\n");
  107. X                return -1;
  108. X            case 0x55: /* SF2 */
  109. X                stuffin(":n!\n");
  110. X                return -1;
  111. X            case 0x3d: /* F3 */
  112. X                stuffin(":N\n");
  113. X                return -1;
  114. X            case 0x56: /* SF3 */
  115. X                stuffin(":N!\n");
  116. X                return -1;
  117. X            case 0x3e: /* F4 */
  118. X                stuffin(":e #\n");
  119. X                return -1;
  120. X            case 0x57: /* SF4 */
  121. X                stuffin(":e! #\n");
  122. X                return -1;
  123. X            case 0x3f: /* F5 */
  124. X                stuffin(":rew\n");
  125. X                return -1;
  126. X            case 0x58: /* SF5 */
  127. X                stuffin(":rew!\n");
  128. X                return -1;
  129. X            case 0x40: /* F6 */
  130. X                stuffin("]]");
  131. X                return -1;
  132. X            case 0x59: /* SF6 */
  133. X                stuffin("[[");
  134. X                return -1;
  135. X            case 0x42: /* F8 - Set up global substitute */
  136. X                stuffin(":1,$s/");
  137. X                return -1;
  138. X            case 0x43: /* F9 - declare C variable */
  139. X                stuffin("yyp!!cdecl\n");
  140. X                return -1;
  141. X            case 0x5C: /* SF9 - explain C declaration */
  142. X                stuffin("yyp^iexplain \033!!cdecl\n");
  143. X                return -1;
  144. X            case 0x44: /* F10 - save & quit */
  145. X                stuffin(":x\n");
  146. X                return -1;
  147. X            case 0x5D: /* F10 - quit without saving */
  148. X                stuffin(":q!\n");
  149. X                return -1;
  150. X            default:
  151. X                break;
  152. X            }
  153. X            break;
  154. X
  155. X        default:
  156. X            return c;
  157. X        }
  158. X    }
  159. X}
  160. X
  161. X
  162. Xstatic    int    bpos = 0;
  163. X#ifdef BIOS
  164. X
  165. X#define    BSIZE    256
  166. Xstatic    char    outbuf[BSIZE];
  167. X
  168. X/* Flushbuf() is used a little differently here in the BIOS-only interface
  169. X * than in the case of other systems.  In general, the other systems buffer
  170. X * large amounts of text and screen management data (escape sequences).
  171. X * Here, only text is buffered, screen management is performed using BIOS
  172. X * calls.  Hence, the buffer is much smaller since no more than one line of
  173. X * text is buffered.  Also, screen management calls must assure that the
  174. X * buffered text is output before performing the requested function.
  175. X *
  176. X * O.K.  Now I had better explain the tricky code sequences for IBM PC and
  177. X * TI Pro.  In both cases, the tricks involve: 1) getting the text written
  178. X * to the display as quickly as possible in the desired color and 2) assur-
  179. X * ing that the cursor is positioned immediately following the latest text
  180. X * output.
  181. X *
  182. X * On the IBM PC, we output the first character using the "write character
  183. X * with attribute" function followed by code which outputs the buffer, a
  184. X * character at a time, using the "write tty" function.  The first write
  185. X * sets the display attributes, which are then reused by the "write tty"
  186. X * function.  The "write tty" is then used to quickly write the data while
  187. X * advancing the cursor.  The "write character with attribute" function
  188. X * does not advance the cursor and so cannot be used to write the entire
  189. X * buffer without additional code to advance the cursor in a separate oper-
  190. X * ation.  Even though the first character in each buffer gets written
  191. X * twice, the result is still substantially faster than it would be using a
  192. X * "write character with attribute" - "[re]position cursor" sequence.
  193. X *
  194. X * On the TI Pro, we output the entire buffer using the "write character
  195. X * string with attribute" function which is fast and convenient.  Unfortun-
  196. X * ately, it does not advance the cursor.  Therefore, we include code which
  197. X * determines the current location of the cursor, writes the buffer, then
  198. X * positions the cursor at the end of the new data.
  199. X *
  200. X * I admit it, this is tricky, but it makes display updates much faster
  201. X * than the would be using a more straightforward approach.
  202. X */
  203. X
  204. X
  205. Xvoid
  206. Xflushbuf()                /* Flush buffered output to display */
  207. X{
  208. X    union    REGS    inregs, curregs, outregs;
  209. X
  210. X    if (bpos != 0) {
  211. X        char    *bptr = outbuf;
  212. X
  213. X        switch (host_type) {
  214. X        case hIBMPC:
  215. X            inregs.h.ah = 0x09;
  216. X            inregs.h.al = *bptr;
  217. X            inregs.h.bh = bgn_page;
  218. X            inregs.h.bl = P(P_CO);
  219. X            inregs.x.cx = 1;
  220. X            int86(crt_int, &inregs, &outregs);
  221. X            inregs.h.ah = 0x0E;
  222. X            while (bpos-- > 0) {
  223. X                inregs.h.al = *bptr++;
  224. X                int86(crt_int, &inregs, &outregs);
  225. X            }
  226. X            break;
  227. X        case hTIPRO:
  228. X            curregs.h.ah = 0x03;
  229. X            int86(crt_int, &curregs, &curregs);
  230. X            inregs.h.ah = 0x10;
  231. X            inregs.h.al = P(P_CO);
  232. X            inregs.x.bx = FP_OFF(outbuf);
  233. X            inregs.x.cx = bpos;
  234. X            inregs.x.dx = FP_SEG(outbuf);
  235. X            int86(crt_int, &inregs, &outregs);
  236. X            curregs.h.ah = 0x02;
  237. X            curregs.h.dh += bpos;
  238. X            int86(crt_int, &curregs, &outregs);
  239. X            break;
  240. X        }
  241. X    }
  242. X    bpos = 0;
  243. X}
  244. X
  245. Xvoid
  246. Xwrite_tty(c)                /* Used to execute control chars */
  247. Xchar    c;
  248. X{
  249. X    int    curcol;
  250. X
  251. X    union    REGS    inregs, curregs, outregs;
  252. X
  253. X    flushbuf(); \
  254. X
  255. X    switch (c) {
  256. X    case '\t':
  257. X        inregs.h.ah = 0x09;
  258. X        inregs.h.al = ' ';
  259. X        inregs.h.bh = bgn_page;
  260. X        inregs.h.bl = P(P_CO);
  261. X        inregs.x.cx = 1;
  262. X        int86(crt_int, &inregs, &outregs);
  263. X        inregs.h.ah = 0x0E;
  264. X        int86(crt_int, &inregs, &outregs);
  265. X        curregs.h.ah = 0x03;
  266. X        curregs.h.bh = bgn_page;
  267. X        int86(crt_int, &curregs, &outregs);
  268. X        curcol = host_type == hIBMPC ? outregs.h.dl : outregs.h.dh;
  269. X        while (curcol++ % P(P_TS)) int86(crt_int, &inregs, &outregs);
  270. X        break;
  271. X    case '\n':
  272. X        if (host_type == hTIPRO) bios_t_el();
  273. X        /* No break, fall through to default action. */
  274. X    default:
  275. X        inregs.h.ah = 0x0E;
  276. X        inregs.h.bh = bgn_page;
  277. X        inregs.h.al = c;
  278. X        int86(crt_int, &inregs, &outregs);
  279. X        break;
  280. X    }
  281. X}
  282. X
  283. X#else        /* Not BIOS */
  284. X
  285. X#define    BSIZE    2048
  286. Xstatic    char    outbuf[BSIZE];
  287. X
  288. Xvoid
  289. Xflushbuf()
  290. X{
  291. X    if (bpos != 0)
  292. X        write(1, outbuf, bpos);
  293. X    bpos = 0;
  294. X}
  295. X
  296. X#endif
  297. X
  298. X
  299. X/*
  300. X * Macro to output a character. Used within this file for speed.
  301. X *
  302. X * This macro had to be upgraded for the BIOS-only version because we
  303. X * cannot count on flushbuf() to execute control characters such as
  304. X * end-of-line or tab.  Therefore, when we encounter one, we flush
  305. X * the buffer and call a routine which executes the character.
  306. X */
  307. X
  308. X#ifdef BIOS
  309. X
  310. X#define    outone(cc) {                 \
  311. X  register char ch = cc;             \
  312. X  if (ch >= ' ') {                   \
  313. X    outbuf[bpos++] = ch;             \
  314. X    if (bpos >= BSIZE) flushbuf();   \
  315. X  } else write_tty(ch);              \
  316. X}
  317. X
  318. X#else
  319. X
  320. X#define    outone(c)    outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()
  321. X
  322. X#endif
  323. X
  324. X/*
  325. X * Function version for use outside this file.
  326. X */
  327. X
  328. Xvoid
  329. Xoutchar(c)
  330. Xchar    c;
  331. X{
  332. X    outone(c);
  333. X}
  334. X
  335. X/*
  336. X * outstr(s) - write a string to the console
  337. X */
  338. X
  339. Xvoid
  340. Xoutstr(s)
  341. Xchar    *s;
  342. X{
  343. X    while (*s) {
  344. X        outone(*s++);
  345. X    }
  346. X}
  347. X
  348. Xvoid
  349. Xbeep()
  350. X{
  351. X    if ( P(P_VB) )
  352. X        vbeep();
  353. X    else
  354. X        outchar('\007');
  355. X}
  356. X
  357. Xvbeep()        /* "Visual Bell" - reverse color flash */
  358. X{
  359. X    unsigned char oldcolor, revcolor, temp;
  360. X
  361. X    oldcolor = P(P_CO);
  362. X
  363. X    /* put reverse color in revcolor */
  364. X    revcolor = (P(P_CO) & 0x07) << 4;    /* foregnd -> bkgnd */
  365. X    temp     = (P(P_CO) & 0x70) >> 4;    /* bkgnd -> foregnd */
  366. X    revcolor  |= temp;
  367. X
  368. X    /* Flash revcolor, then back */
  369. X    setcolor (revcolor);
  370. X    flushbuf();
  371. X#ifdef TURBOC
  372. X    delay (100);
  373. X#endif
  374. X    setcolor (oldcolor);
  375. X    windgoto (Cursrow, Curscol);
  376. X    flushbuf();
  377. X}
  378. X
  379. X
  380. X#ifndef TURBOC
  381. Xsleep(n)
  382. Xint    n;
  383. X{
  384. X    /*
  385. X     * Should do something reasonable here.
  386. X     */
  387. X}
  388. X#endif
  389. X
  390. Xvoid
  391. Xpause()
  392. X{
  393. X    long    l;
  394. X
  395. X    flushbuf();
  396. X
  397. X#ifdef TURBOC
  398. X    delay (600);    /* "stop" for a fraction of a second */
  399. X#else
  400. X    /*
  401. X     * Should do something better here...
  402. X     */
  403. X    for (l=0; l < 5000 ;l++)
  404. X        ;
  405. X#endif
  406. X}
  407. X
  408. Xvoid
  409. Xsig()
  410. X{
  411. X    signal(SIGINT, sig);
  412. X
  413. X    got_int = TRUE;
  414. X}
  415. X
  416. Xstatic    char    schar;        /* save original switch character */
  417. X
  418. X/*    While Larry Shurr's addition of color and mode support was
  419. X *    dependent on #define BIOS, there's no reason it needs to be.
  420. X *    The BIOS is always there, even if NANSI.SYS isn't.  We'll
  421. X *    use the BIOS where appropriate, and extend support to
  422. X *    all cases of #define DOS.  This is especially true of the
  423. X *    setup in windinit() and the termination in windexit().
  424. X */
  425. X
  426. Xvoid
  427. Xwindinit()
  428. X{
  429. X    union    REGS    regs;
  430. X    struct    SREGS    sregs;
  431. X
  432. X    /* The "SYSROM..." string is a signature in the TI Pro's ROM which
  433. X     * which we can look for to determine whether or not we're running
  434. X     * on a TI Pro.  If we don't find it at F400:800D,
  435. X     * we assume we're running on an IBM PC or clone.
  436. X     * Unfortunately, the signature is actually
  437. X     * the system ROM's copyright notice though you will note that the
  438. X     * year is omitted.  Still, placing it in this program might
  439. X     * inadvertantly make it appear to be an official copyright notice
  440. X     * for THIS program.  Hence, I have surrounded the signature
  441. X     * string with disclaimers.
  442. X     */
  443. X
  444. X        static    char far *disclaimer1 =
  445. X      "The following is *NOT* a copyright notice for this program: ";
  446. X
  447. X    static    char far *ti_sig =
  448. X          "SYSROM (c) Copyright Texas Instruments Inc.";
  449. X
  450. X    static    char far *disclaimer2[] = {
  451. X      "\nInstead, it is a signature string we look for ",
  452. X      "to distinguish the TI Pro computer.\n",
  453. X      "Actually, this program is in the public domain."
  454. X    };
  455. X
  456. X    static char far    *ti_sig_addr = (char far *)0xF400800D;
  457. X    static int ti_sig_len = sizeof(ti_sig) - 1;
  458. X
  459. X    /* Identify the host type.  Look for signature in TI Pro ROM.  If */
  460. X    /* found, set host type to TI Pro, else assume host is an IBM PC. */
  461. X
  462. X    host_type = strncmp(ti_sig, ti_sig_addr, ti_sig_len) ? hIBMPC : hTIPRO;
  463. X
  464. X    /* Next, perform host-dependent initialization. */
  465. X
  466. X    switch (host_type) {
  467. X    case hIBMPC:
  468. X        /* Get the video mode info */
  469. X        crt_int = 0x10;
  470. X        regs.h.ah = 0x0F;
  471. X        int86(crt_int, ®s, ®s);
  472. X        bgn_page = regs.h.bh;
  473. X        bgn_mode = regs.h.al;
  474. X        Columns = regs.h.ah;
  475. X        /*  Find the starting color, and save to restore later */
  476. X        regs.h.ah = 8;        /* Read char/attr BIOS fn */
  477. X        regs.h.bh = bgn_page;
  478. X        int86(crt_int, ®s, ®s);
  479. X        bgn_color = (int) regs.h.ah;
  480. X        P(P_CO) = bgn_color;
  481. X        break;
  482. X    case hTIPRO:
  483. X        Columns = 80;
  484. X        crt_int = 0x49;
  485. X        P(P_CO) = 0x0F;
  486. X        break;
  487. X
  488. X    default:
  489. X        Columns = 80;
  490. X        break;
  491. X    }
  492. X
  493. X    P(P_LI) = Rows = 25;
  494. X
  495. X    schar = getswitch();
  496. X    setswitch('/');
  497. X
  498. X    signal(SIGINT, sig);
  499. X#ifndef BIOS
  500. X    setraw (1);
  501. X#endif
  502. X}
  503. X
  504. Xvoid
  505. Xwindexit(r)
  506. Xint r;
  507. X{
  508. X
  509. X    union    REGS    regs;
  510. X
  511. X    quitting_now = 1;
  512. X
  513. X    /* Restore original color */
  514. X    setcolor (bgn_color);
  515. X
  516. X    if (host_type == hIBMPC) {
  517. X        /* If we've changed any of the setup, reset the mode.
  518. X         * Otherwise, leave stuff on the screen.
  519. X         */
  520. X        regs.h.ah = 0x0F;    /* "Get-mode" BIOS fn */
  521. X        int86(0x10, ®s, ®s);
  522. X        if (bgn_mode != regs.h.al)
  523. X            set_mode (bgn_mode);
  524. X    }
  525. X
  526. X    flushbuf();
  527. X    setswitch(schar);
  528. X#ifndef BIOS
  529. X    setraw(0);
  530. X#endif
  531. X    exit(r);
  532. X}
  533. X
  534. X
  535. X#ifndef BIOS
  536. X/*    Setraw sets the console driver into raw mode, which makes it run
  537. X *    somewhat faster.  Details of the function:
  538. X *    If r=1, remember current mode, and set into raw mode.
  539. X *       r=0, return to the original mode.
  540. X */
  541. X
  542. Xsetraw (r)
  543. X  int    r;
  544. X{
  545. X    static int origr=0;    /* save the original r */
  546. X    union REGS rr;
  547. X
  548. X    /* Do IOCTL call to get current control info */
  549. X    rr.x.ax = 0x4400;    /* Read IOCTL info - DOS fn */
  550. X    rr.x.bx = 1;        /* Handle for stdout */
  551. X    intdos (&rr, &rr);
  552. X
  553. X    /* Save relevant info, and modify for "set" call */
  554. X    if (r) {
  555. X        origr = rr.h.dl & 0x20;        /* save current "raw" bit */
  556. X        rr.h.dl = rr.h.dl | 0x20;    /* set "raw" bit */
  557. X    }
  558. X    else
  559. X        rr.h.dl = (rr.h.dl & (~0x20)) | (origr & 0x20);
  560. X
  561. X    /* Do IOCTL call to set control info */
  562. X    rr.x.ax = 0x4401;    /* Set IOCTL function call */
  563. X    rr.x.bx = 1;        /* Handle for stdout */
  564. X    rr.h.dh = 0;        /* DL already set up */
  565. X    intdos (&rr, &rr);
  566. X}
  567. X#endif
  568. X
  569. X
  570. Xvoid
  571. Xwindgoto(r, c)                /* Move cursor to r'ow & c'olumn */
  572. Xregister int    r, c;
  573. X{
  574. X#ifdef BIOS
  575. X    union    REGS    inregs, outregs;
  576. X
  577. X    if (bpos > 0) flushbuf();
  578. X
  579. X    inregs.h.ah = 0x02;
  580. X
  581. X    switch (host_type) {
  582. X    case hIBMPC :
  583. X        inregs.h.bh = bgn_page;
  584. X        inregs.h.dh = r;
  585. X        inregs.h.dl = c;
  586. X        break;
  587. X    case hTIPRO:
  588. X        inregs.h.dh = c;
  589. X        inregs.h.dl = r;
  590. X        break;
  591. X    }
  592. X
  593. X    int86(crt_int, &inregs, &outregs);
  594. X
  595. X#else        /* Not BIOS */
  596. X
  597. X    r += 1;
  598. X    c += 1;
  599. X
  600. X    /*
  601. X     * Check for overflow once, to save time.
  602. X     */
  603. X    if (bpos + 8 >= BSIZE)
  604. X        flushbuf();
  605. X
  606. X    outbuf[bpos++] = '\033';
  607. X    outbuf[bpos++] = '[';
  608. X    if (r >= 10)
  609. X        outbuf[bpos++] = r/10 + '0';
  610. X    outbuf[bpos++] = r%10 + '0';
  611. X    outbuf[bpos++] = ';';
  612. X    if (c >= 10)
  613. X        outbuf[bpos++] = c/10 + '0';
  614. X    outbuf[bpos++] = c%10 + '0';
  615. X    outbuf[bpos++] = 'H';
  616. X
  617. X#endif
  618. X}
  619. X
  620. XFILE *
  621. Xfopenb(fname, mode)
  622. Xchar    *fname;
  623. Xchar    *mode;
  624. X{
  625. X    FILE    *fopen();
  626. X    char    modestr[16];
  627. X
  628. X    sprintf(modestr, "%sb", mode);
  629. X    return fopen(fname, modestr);
  630. X}
  631. X
  632. Xstatic    char
  633. Xgetswitch()
  634. X{
  635. X    union    REGS    inregs, outregs;
  636. X
  637. X    inregs.h.ah = 0x37;
  638. X    inregs.h.al = 0;
  639. X
  640. X    intdos(&inregs, &outregs);
  641. X
  642. X    return outregs.h.dl;
  643. X}
  644. X
  645. Xstatic    void
  646. Xsetswitch(c)
  647. Xchar    c;
  648. X{
  649. X    union    REGS    inregs, outregs;
  650. X
  651. X    inregs.h.ah = 0x37;
  652. X    inregs.h.al = 1;
  653. X    inregs.h.dl = c;
  654. X
  655. X    intdos(&inregs, &outregs);
  656. X}
  657. X
  658. X#define    PSIZE    128
  659. X
  660. X/*
  661. X * fixname(s) - fix up a dos name
  662. X *
  663. X * Takes a name like:
  664. X *
  665. X *    \x\y\z\base.ext
  666. X *
  667. X * and trims 'base' to 8 characters, and 'ext' to 3.
  668. X */
  669. Xchar *
  670. Xfixname(s)
  671. Xchar    *s;
  672. X{
  673. X    char    *strchr(), *strrchr();
  674. X    static    char    f[PSIZE];
  675. X    char    base[32];
  676. X    char    ext[32];
  677. X    char    *p;
  678. X    int    i;
  679. X
  680. X    strcpy(f, s);
  681. X
  682. X    for (i=0; i < PSIZE ;i++)
  683. X        if (f[i] == '/')
  684. X            f[i] = '\\';
  685. X
  686. X    /*
  687. X     * Split the name into directory, base, extension.
  688. X     */
  689. X    if ((p = strrchr(f, '\\')) != NULL) {
  690. X        strcpy(base, p+1);
  691. X        p[1] = '\0';
  692. X    } else {
  693. X        strcpy(base, f);
  694. X        f[0] = '\0';
  695. X    }
  696. X
  697. X    if ((p = strchr(base, '.')) != NULL) {
  698. X        strcpy(ext, p+1);
  699. X        *p = '\0';
  700. X    } else
  701. X        ext[0] = '\0';
  702. X
  703. X    /*
  704. X     * Trim the base name if necessary.
  705. X     */
  706. X    if (strlen(base) > 8)
  707. X        base[8] = '\0';
  708. X
  709. X    if (strlen(ext) > 3)
  710. X        ext[3] = '\0';
  711. X
  712. X    /*
  713. X     * Paste it all back together
  714. X     */
  715. X    strcat(f, base);
  716. X    strcat(f, ".");
  717. X    strcat(f, ext);
  718. X
  719. X    return f;
  720. X}
  721. X
  722. Xvoid
  723. Xdoshell(cmd)
  724. Xchar    *cmd;
  725. X{
  726. X    if (cmd == NULL)
  727. X        if ((cmd = getenv ("COMSPEC")) == NULL)
  728. X            cmd = "command.com";
  729. X
  730. X    system(cmd);
  731. X    wait_return();
  732. X}
  733. X
  734. X
  735. X/*
  736. X *    setcolor (color)
  737. X *    Set the screen attributes (basically, color) to value co.
  738. X *    The color attributes for a DOS machine are the BIOS colors
  739. X *    for text.  Where BIOS is not defined, we map the Escape
  740. X *    sequences to the NANSI.SYS equivalents of the BIOS colors.
  741. X */
  742. X
  743. Xsetcolor (color)
  744. X  int    color;
  745. X{
  746. X#ifdef BIOS
  747. X    P(P_CO) = host_type == hIBMPC ? color : ((color & 0x17) | 0x08);
  748. X#else
  749. X    unsigned char work;
  750. X
  751. X    /* Send the ANSI define-attribute sequence */
  752. X    outone('\033');
  753. X    outone('[');
  754. X    outone('0');        /* Normal color */
  755. X    outone(';');
  756. X    /* BIOS-to-NANSI color conversion may look a little bizarre.
  757. X     * They have different bit orderings to represent the
  758. X     * color (BIOS=RGB, NANSI=BGR).
  759. X     *
  760. X     * First put the foreground color.
  761. X     */
  762. X    work = 0;
  763. X    if (color & 1)        work += 4;    /* Blue */
  764. X    if (color & 2)        work += 2;    /* Green */
  765. X    if (color & 4)        work += 1;    /* Red */
  766. X    outone('3');        /* NANSI foreground starts at 30 */
  767. X    outone(work + '0');
  768. X    outone(';');
  769. X    /*  Now the background color */
  770. X    work = 0;
  771. X    if (color & 0x10)    work += 4;    /* Blue */
  772. X    if (color & 0x20)    work += 2;    /* Green */
  773. X    if (color & 0x40)    work += 1;    /* Red */
  774. X    outone('4');        /* NANSI background starts at 40 */
  775. X    outone(work + '0');
  776. X    /*  Do the intensity and blinking, if any  */
  777. X    if (color & 8) {    /* intensity */
  778. X        outone(';');
  779. X        outone('1');
  780. X    }
  781. X    if (color & 0x80) {    /* blink */
  782. X        outone(';');
  783. X        outone('5');
  784. X    }
  785. X    /*  The 'm' suffix means "set graphic rendition"  */
  786. X    outone('m');
  787. X    P(P_CO) = color;
  788. X
  789. X#endif        /* Not BIOS */
  790. X
  791. X    if (!quitting_now) {
  792. X        screenclear();
  793. X        updatescreen();
  794. X    }
  795. X}
  796. X
  797. X
  798. X/*    setrows (r)
  799. X *    Sets the screen to "r" rows, or lines, where "r" is a feasible
  800. X *    value for the IBM PC with some common display.  In this function:
  801. X *   -    We set the mode to 25-line or 43-line mode, assuming the display
  802. X *    supports the requested mode.
  803. X *   -    We set the logical number of lines that Stevie uses to "r",
  804. X *    so that the screen USED may not be the same as the physical screen.
  805. X *
  806. X *    The function returns the number of rows set.
  807. X */
  808. Xsetrows (r)
  809. X  int r;
  810. X{
  811. X    int    rphys, rlog;    /* physical and logical "r" */
  812. X
  813. X    rphys = (r <= 25) ? 25 : 43 ;
  814. X    rlog  = (r <= 50) ? r : 50;
  815. X
  816. X    /* Set the mode to correspond to the number of lines */
  817. X    set_mode (rphys);
  818. X
  819. X    return (rlog);
  820. X}
  821. X
  822. X
  823. Xset_mode (m)
  824. X  int m;
  825. X{
  826. X    set_25 ();
  827. X    if (m == 43)
  828. X        set_43 ();
  829. X}
  830. X
  831. X#ifdef BIOS
  832. X
  833. Xint
  834. Xset_25(lines)            /* Set display to 25 line mode */
  835. Xint    lines;
  836. X{
  837. X    union    REGS    inregs, outregs;
  838. X
  839. X    switch (host_type) {
  840. X    case hIBMPC:
  841. X        inregs.h.ah = 0x00;
  842. X        inregs.h.al = bgn_mode;
  843. X        int86(crt_int, &inregs, &outregs);
  844. X        break;
  845. X    case hTIPRO:
  846. X        windgoto(0, 0);
  847. X        inregs.h.ah = 0x09;
  848. X        inregs.h.al = ' ';
  849. X        inregs.h.bl = P(P_CO);
  850. X        inregs.x.cx = 80 * 25;
  851. X        int86(crt_int, &inregs, &outregs);
  852. X        if (lines > 25) lines = 25;
  853. X        break;
  854. X    }
  855. X
  856. X    return(lines);
  857. X}
  858. X
  859. Xint
  860. Xset_43(lines)            /* Set display to 43/50 line mode */
  861. Xint    lines;
  862. X{
  863. X    union    REGS    inregs, outregs;
  864. X
  865. X    switch (host_type) {
  866. X    case hIBMPC:
  867. X        inregs.x.ax = 0x1112;
  868. X        inregs.h.bl = 0;
  869. X        int86(crt_int, &inregs, &outregs);
  870. X        inregs.x.ax = 0x1200;
  871. X        inregs.h.bl = 0x20;
  872. X        int86(crt_int, &inregs, &outregs);
  873. X        inregs.h.ah = 0x01;
  874. X        inregs.x.cx = 0x0707;
  875. X        int86(crt_int, &inregs, &outregs);
  876. X        break;
  877. X    case hTIPRO:
  878. X        if (lines > 25) lines = 25;
  879. X        break;
  880. X    }
  881. X
  882. X    return(lines);
  883. X}
  884. X
  885. X#else        /* Not BIOS */
  886. X
  887. Xset_25 ()
  888. X{
  889. X    send_setmode (bgn_mode);
  890. X}
  891. X
  892. Xset_43 ()
  893. X{
  894. X    send_setmode (43);
  895. X}
  896. X
  897. Xsend_setmode (m)
  898. X{
  899. X    outone('\033');
  900. X    outone('[');
  901. X
  902. X    /* Convert 2-digit decimal to ASCII */
  903. X    if (m >= 10)
  904. X        outone( m/10 + '0' );
  905. X    outone( m%10 + '0' );
  906. X    outone ('h');
  907. X}
  908. X
  909. X#endif        /* Not BIOS */
  910. X
  911. X#ifdef BIOS
  912. X/*
  913. X *    The rest of the file is BIOS-specific
  914. X */
  915. X
  916. Xvoid
  917. Xbios_t_ci()                /* Make cursor invisible */
  918. X{
  919. X    union    REGS    inregs, outregs;
  920. X
  921. X    if (sav_curattr == 0) {
  922. X        inregs.h.ah = 0x03;
  923. X        inregs.h.bh = bgn_page;
  924. X        int86(crt_int, &inregs, &outregs);
  925. X        sav_curattr = outregs.x.cx;
  926. X        inregs.h.ah = 0x01;
  927. X        inregs.x.cx = 0x2000;
  928. X        int86(crt_int, &inregs, &outregs);
  929. X    }
  930. X}
  931. X
  932. Xvoid
  933. Xbios_t_cv()                /* Make cursor visible */
  934. X{
  935. X    union    REGS    inregs, outregs;
  936. X
  937. X    if (sav_curattr != 0) {
  938. X        inregs.h.ah = 0x01;
  939. X        inregs.h.bh = bgn_page;
  940. X        inregs.x.cx = sav_curattr;
  941. X        int86(crt_int, &inregs, &outregs);
  942. X        sav_curattr = 0;
  943. X    }
  944. X}
  945. X
  946. X/*
  947. X * O.K., I have tried to keep bios.c as "pure" as possible. I.e., I have used
  948. X * BIOS calls for everything instead of going for all-out speed by using
  949. X * direct-video access for updating the display - after all, I named it this
  950. X * module bios.c.  There is one area, however, where using the BIOS is just
  951. X * too much of a compromise... the TI Pro's "scroll display" functions are so
  952. X * slow and ugly that I hate them.  True, they are very flexible, but their
  953. X * poor on-screen appearance and low performance are a liability - you prob-
  954. X * ably think I'm exaggerating, but you're wrong - it is truly bad.  There-
  955. X * fore, I am bypassing them and scrolling the screen myself; something I
  956. X * nearly always do.  From a purist like me, that really says something.
  957. X */
  958. X
  959. Xvoid
  960. Xbios_t_dl(r,l)                /* Delete lines */
  961. Xint r, l;
  962. X{
  963. X    char    far    *end;        /* End ptr for TI Pro screen */
  964. X    char    far    *dst;        /* Dest ptr for scrolling TI Pro scrn */
  965. X    char    far    *src;        /* Src  ptr for scrolling TI Pro scrn */
  966. X
  967. X    union    REGS    inregs, outregs;
  968. X
  969. X    switch (host_type) {
  970. X    case hIBMPC:
  971. X        inregs.h.ah = 0x06;
  972. X        inregs.h.al = l;
  973. X        inregs.h.bh = P(P_CO);
  974. X        inregs.h.ch = r;
  975. X        inregs.h.cl = 0;
  976. X        inregs.h.dh = Rows - 1;
  977. X        inregs.h.dl = Columns - 1;
  978. X        int86(crt_int, &inregs, &outregs);
  979. X        break;
  980. X    case hTIPRO:
  981. X        inregs.h.ah = 0x17;
  982. X        int86(crt_int, &inregs, &outregs);
  983. X        dst = MK_FP(0xDE00, outregs.x.dx + (r * Columns));
  984. X        src = dst + (l * Columns);
  985. X        end = MK_FP(0xDE00, outregs.x.dx + ((Rows - 1) * Columns));
  986. X        while (src < end) *dst++ = *src++;
  987. X        while (dst < end) *dst++ = ' ';
  988. X        break;
  989. X    }
  990. X}
  991. X
  992. Xvoid
  993. Xbios_t_ed()                /* Home cursor, erase display */
  994. X{
  995. X    union    REGS    inregs, outregs;
  996. X
  997. X    windgoto(0, 0);
  998. X
  999. X    inregs.h.ah = 0x09;
  1000. X    inregs.h.al = ' ';
  1001. X    inregs.h.bh = bgn_page;
  1002. X    inregs.h.bl = P(P_CO);
  1003. X    inregs.x.cx = Columns * Rows;
  1004. X    int86(crt_int, &inregs, &outregs);
  1005. X}
  1006. X
  1007. Xvoid
  1008. Xbios_t_el()                /* Erase to end-of-line */
  1009. X{
  1010. X    short    ccol;
  1011. X
  1012. X    union    REGS    inregs, outregs;
  1013. X
  1014. X    inregs.h.ah = 0x03;
  1015. X    inregs.h.bh = bgn_page;
  1016. X    int86(crt_int, &inregs, &outregs);
  1017. X
  1018. X    inregs.h.ah = 0x09;
  1019. X    inregs.h.al = ' ';
  1020. X    inregs.h.bl = P(P_CO);
  1021. X
  1022. X    ccol = host_type == hIBMPC ? outregs.h.dl : outregs.h.dh;
  1023. X
  1024. X    inregs.x.cx = Columns - ccol;
  1025. X    int86(crt_int, &inregs, &outregs);
  1026. X}
  1027. X
  1028. X/* As in the delete-line function, we scroll the TI display ourselves
  1029. X * rather than the use the slow-and-ugly software scroll in the BIOS.  See
  1030. X * the remarks for bios_t_dl() additional information.
  1031. X */
  1032. X
  1033. Xvoid
  1034. Xbios_t_il(r,l)                /* Insert lines */
  1035. Xint r, l;
  1036. X{
  1037. X    char    far    *end;        /* End ptr for TI Pro screen */
  1038. X    char    far    *dst;        /* For scrolling TI Pro screen */
  1039. X    char    far    *src;        /* For scrolling TI Pro screen */
  1040. X
  1041. X    union    REGS    inregs, outregs;
  1042. X
  1043. X    switch (host_type) {
  1044. X    case hIBMPC:
  1045. X        inregs.h.ah = 0x07;
  1046. X        inregs.h.al = l;
  1047. X        inregs.h.bh = P(P_CO);
  1048. X        inregs.h.ch = r;
  1049. X        inregs.h.cl = 0;
  1050. X        inregs.h.dh = Rows - 1;
  1051. X        inregs.h.dl = Columns - 1;
  1052. X        int86(crt_int, &inregs, &outregs);
  1053. X        break;
  1054. X    case hTIPRO:
  1055. X        inregs.h.ah = 0x17;
  1056. X        int86(crt_int, &inregs, &outregs);
  1057. X        dst = MK_FP(0xDE00, outregs.x.dx + (Columns * (Rows - 1)) - 1);
  1058. X        src = dst - (Columns * l);
  1059. X        end = MK_FP(0xDE00, outregs.x.dx + (Columns * r));
  1060. X        while (src >= end) *dst-- = *src--;
  1061. X        src = MK_FP(0xDE00, outregs.x.dx + (r * Columns));
  1062. X        end = src + (l * Columns);
  1063. X        while (src < end) *src++ = ' ';
  1064. X        break;
  1065. X    }
  1066. X}
  1067. X
  1068. Xvoid
  1069. Xbios_t_rc()                /* Restore saved cursor position */
  1070. X{
  1071. X    union    REGS    inregs, outregs;
  1072. X
  1073. X    inregs.h.ah = 0x02;
  1074. X    inregs.h.bh = bgn_page;
  1075. X    inregs.x.dx = sav_curpos;
  1076. X    int86(crt_int, &inregs, &outregs);
  1077. X}
  1078. X
  1079. Xvoid
  1080. Xbios_t_sc()                /* Save cursor position */
  1081. X{
  1082. X    union    REGS    inregs, outregs;
  1083. X
  1084. X    inregs.h.ah = 0x03;
  1085. X    inregs.h.bh = bgn_page;
  1086. X    int86(crt_int, &inregs, &outregs);
  1087. X    sav_curpos = outregs.x.dx;
  1088. X}
  1089. X
  1090. X#endif
  1091. X
  1092. !EOR!
  1093. echo extracting - minix.c
  1094. sed 's/^X//' > minix.c << '!EOR!'
  1095. X/* $Header: /nw/tony/src/stevie/src/RCS/minix.c,v 1.5 89/07/11 21:24:18 tony Exp $
  1096. X *
  1097. X * System-dependent routines for Minix-ST
  1098. X */
  1099. X
  1100. X#include "stevie.h"
  1101. X#include <sgtty.h>
  1102. X#include <signal.h>
  1103. X
  1104. X/*
  1105. X * inchar() - get a character from the keyboard
  1106. X */
  1107. Xint
  1108. Xinchar()
  1109. X{
  1110. X    char    c;
  1111. X
  1112. X    flushbuf();        /* flush any pending output */
  1113. X
  1114. X    while (read(0, &c, 1) != 1)
  1115. X        ;
  1116. X
  1117. X    got_int = FALSE;
  1118. X    return c;
  1119. X}
  1120. X
  1121. X#define    BSIZE    2048
  1122. Xstatic    char    outbuf[BSIZE];
  1123. Xstatic    int    bpos = 0;
  1124. X
  1125. Xvoid
  1126. Xflushbuf()
  1127. X{
  1128. X    if (bpos != 0)
  1129. X        write(1, outbuf, bpos);
  1130. X    bpos = 0;
  1131. X}
  1132. X
  1133. X/*
  1134. X * Macro to output a character. Used within this file for speed.
  1135. X */
  1136. X#define    outone(c)    outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()
  1137. X
  1138. X/*
  1139. X * Function version for use outside this file.
  1140. X */
  1141. Xvoid
  1142. Xoutchar(c)
  1143. Xregister char    c;
  1144. X{
  1145. X    outbuf[bpos++] = c;
  1146. X    if (bpos >= BSIZE)
  1147. X        flushbuf();
  1148. X}
  1149. X
  1150. Xvoid
  1151. Xoutstr(s)
  1152. Xregister char    *s;
  1153. X{
  1154. X    while (*s) {
  1155. X        outone(*s++);
  1156. X    }
  1157. X}
  1158. X
  1159. Xvoid
  1160. Xbeep()
  1161. X{
  1162. X    if ( P(P_VB) )
  1163. X        vbeep();
  1164. X    else
  1165. X        outone('\007');
  1166. X}
  1167. X
  1168. X/*
  1169. X * remove(file) - remove a file
  1170. X */
  1171. Xvoid
  1172. Xremove(file)
  1173. Xchar *file;
  1174. X{
  1175. X    unlink(file);
  1176. X}
  1177. X
  1178. X/*
  1179. X * rename(of, nf) - rename existing file 'of' to 'nf'
  1180. X */
  1181. Xvoid
  1182. Xrename(of, nf)
  1183. Xchar    *of, *nf;
  1184. X{
  1185. X    unlink(nf);
  1186. X    link(of, nf);
  1187. X    unlink(of);
  1188. X}
  1189. X
  1190. Xvoid
  1191. Xpause()
  1192. X{
  1193. X    sleep (1);
  1194. X}
  1195. X
  1196. Xstatic    struct    sgttyb    ostate;
  1197. X
  1198. X/*
  1199. X * Go into cbreak mode
  1200. X */
  1201. Xvoid
  1202. Xset_tty()
  1203. X{
  1204. X    struct    sgttyb    nstate;
  1205. X
  1206. X     ioctl(0, TIOCGETP, &ostate);
  1207. X     nstate = ostate;
  1208. X     nstate.sg_flags &= ~(XTABS|ECHO);
  1209. X     nstate.sg_flags |= CBREAK;
  1210. X     ioctl(0, TIOCSETP, &nstate);
  1211. X}
  1212. X
  1213. X/*
  1214. X * Restore original terminal modes
  1215. X */
  1216. Xvoid
  1217. Xreset_tty()
  1218. X{
  1219. X    ioctl(0, TIOCSETP, &ostate);
  1220. X}
  1221. X
  1222. Xvoid
  1223. Xsig()
  1224. X{
  1225. X    signal(SIGINT, sig);
  1226. X    signal(SIGQUIT, sig);
  1227. X
  1228. X    got_int = TRUE;
  1229. X}
  1230. X
  1231. Xvoid
  1232. Xwindinit()
  1233. X{
  1234. X#ifdef    TERMCAP
  1235. X    if (t_init() != 1) {
  1236. X        fprintf(stderr, "unknown terminal type\n");
  1237. X        exit(1);
  1238. X    }
  1239. X#else
  1240. X    Columns = 80;
  1241. X    P(P_LI) = Rows = 25;
  1242. X#endif
  1243. X    /*
  1244. X     * The code here makes sure that there isn't a window during which
  1245. X     * we could get interrupted and exit with the tty in a weird state.
  1246. X     */
  1247. X    signal(SIGINT, sig);
  1248. X    signal(SIGQUIT, sig);
  1249. X
  1250. X    set_tty();
  1251. X
  1252. X    if (got_int)
  1253. X        windexit(0);
  1254. X}
  1255. X
  1256. Xvoid
  1257. Xwindexit(r)
  1258. Xint r;
  1259. X{
  1260. X    reset_tty();
  1261. X    exit(r);
  1262. X}
  1263. X
  1264. Xvoid
  1265. Xwindgoto(r, c)
  1266. Xregister int    r, c;
  1267. X{
  1268. X#ifdef    TERMCAP
  1269. X    char    *tgoto();
  1270. X#else
  1271. X    r += 1;
  1272. X    c += 1;
  1273. X#endif
  1274. X
  1275. X    /*
  1276. X     * Check for overflow once, to save time.
  1277. X     */
  1278. X    if (bpos + 8 >= BSIZE)
  1279. X        flushbuf();
  1280. X
  1281. X#ifdef    TERMCAP
  1282. X    outstr(tgoto(T_CM, c, r));
  1283. X#else
  1284. X    outbuf[bpos++] = '\033';
  1285. X    outbuf[bpos++] = '[';
  1286. X    if (r >= 10)
  1287. X        outbuf[bpos++] = r/10 + '0';
  1288. X    outbuf[bpos++] = r%10 + '0';
  1289. X    outbuf[bpos++] = ';';
  1290. X    if (c >= 10)
  1291. X        outbuf[bpos++] = c/10 + '0';
  1292. X    outbuf[bpos++] = c%10 + '0';
  1293. X    outbuf[bpos++] = 'H';
  1294. X#endif
  1295. X}
  1296. X
  1297. XFILE *
  1298. Xfopenb(fname, mode)
  1299. Xchar    *fname;
  1300. Xchar    *mode;
  1301. X{
  1302. X    return fopen(fname, mode);
  1303. X}
  1304. X
  1305. Xchar *
  1306. Xstrchr(s, c)
  1307. Xchar    *s;
  1308. Xchar    c;
  1309. X{
  1310. X    char *index();
  1311. X
  1312. X    return index(s, c);
  1313. X}
  1314. X
  1315. Xchar *
  1316. Xfixname(s)
  1317. Xchar    *s;
  1318. X{
  1319. X    return s;
  1320. X}
  1321. X
  1322. X/*
  1323. X * doshell() - run a command or an interactive shell
  1324. X */
  1325. Xvoid
  1326. Xdoshell(cmd)
  1327. Xchar    *cmd;
  1328. X{
  1329. X    char    *cp, *getenv();
  1330. X    char    cline[128];
  1331. X
  1332. X    outstr("\r\n");
  1333. X    flushbuf();
  1334. X
  1335. X    if (cmd == NULL) {
  1336. X        if ((cmd = getenv("SHELL")) == NULL)
  1337. X            cmd = "/bin/sh";
  1338. X        sprintf(cline, "%s -i", cmd);
  1339. X        cmd = cline;
  1340. X    }
  1341. X
  1342. X    reset_tty();
  1343. X    system(cmd);
  1344. X    set_tty();
  1345. X
  1346. X    wait_return();
  1347. X}
  1348. X
  1349. X/*
  1350. X *    FILL IT IN, FOR YOUR SYSTEM, AND SHARE IT!
  1351. X *
  1352. X *    The next couple of functions do system-specific stuff.
  1353. X *    They currently do nothing; I'm not familiar enough with
  1354. X *    system-specific programming on this system.
  1355. X *    If you fill it in for your system, please post the results
  1356. X *    and share with the rest of us.
  1357. X */
  1358. X
  1359. X
  1360. Xsetcolor (c)
  1361. X/*
  1362. X * Set the color to c, using the local system convention for numbering
  1363. X * colors or video attributes.
  1364. X *
  1365. X * If you implement this, remember to note the original color in
  1366. X * windinit(), before you do any setcolor() commands, and
  1367. X * do a setcolor() back to the original as part of windexit().
  1368. X */
  1369. X  int c:
  1370. X{
  1371. X}
  1372. X
  1373. X
  1374. Xsetrows (r)
  1375. X/*
  1376. X * Set the number of lines to r, if possible.  Otherwise
  1377. X * "do the right thing".  Return the number of lines actually set.
  1378. X *
  1379. X * If you implement this, remember to note the original number of rows
  1380. X * in windinit(), before you do any setrows() commands, and
  1381. X * do a setrows() back to the original as part of windexit().
  1382. X */
  1383. X  int r;
  1384. X{
  1385. X    /* Since we do nothing, just return the current number of lines */
  1386. X    return ( P(P_LI) );
  1387. X}
  1388. X
  1389. X
  1390. Xvbeep ()
  1391. X/*
  1392. X * Do a "visual bell".  This generally consists of flashing the screen
  1393. X * once in inverse video.
  1394. X */
  1395. X{
  1396. X    int    color, revco;
  1397. X
  1398. X    color = P( P_CO );        /* get current color */
  1399. X    revco = reverse_color (color);    /* system-specific */
  1400. X    setcolor (revco);
  1401. X    flushbuf ();
  1402. X    pause ();
  1403. X    setcolor (color);
  1404. X    windgoto (Cursrow, Curscol);
  1405. X    flushbuf ();
  1406. X}
  1407. X
  1408. Xreverse_color (co)
  1409. X/*
  1410. X * Returns the inverse video attribute or color of co.
  1411. X * The existing code below is VERY simple-minded.
  1412. X * Replace it with proper code for your system.
  1413. X */
  1414. X int co;
  1415. X{
  1416. X    if (co)        return (0);
  1417. X    else        return (1);
  1418. X}
  1419. X
  1420. X
  1421. X/********** End of do-it-yourself kit **********************/
  1422. X
  1423. !EOR!
  1424. echo extracting - os2.c
  1425. sed 's/^X//' > os2.c << '!EOR!'
  1426. X/* $Header: /nw/tony/src/stevie/src/RCS/os2.c,v 1.7 89/08/07 05:49:19 tony Exp $
  1427. X *
  1428. X * OS/2 System-dependent routines.
  1429. X */
  1430. X
  1431. X#define    INCL_BASE
  1432. X#include <os2.h>
  1433. X#include <signal.h>
  1434. X#include "stevie.h"
  1435. X
  1436. X/*
  1437. X * inchar() - get a character from the keyboard
  1438. X */
  1439. Xint
  1440. Xinchar()
  1441. X{
  1442. X    register int    c;
  1443. X
  1444. X    got_int = FALSE;
  1445. X
  1446. X    for (;;beep()) {    /* loop until we get a valid character */
  1447. X
  1448. X        flushbuf();    /* flush any pending output */
  1449. X
  1450. X        switch (c = getch()) {
  1451. X        case 0x1e:
  1452. X            return K_CCIRCM;
  1453. X        case 0:                /* special key */
  1454. X            if (State != NORMAL) {
  1455. X                c = getch();    /* throw away next char */
  1456. X                continue;    /* and loop for another char */
  1457. X            }
  1458. X            switch (c = getch()) {
  1459. X            case 0x50:
  1460. X                return K_DARROW;
  1461. X            case 0x48:
  1462. X                return K_UARROW;
  1463. X            case 0x4b:
  1464. X                return K_LARROW;
  1465. X            case 0x4d:
  1466. X                return K_RARROW;
  1467. X            case 0x52:
  1468. X                return K_INSERT;
  1469. X            case 0x47:        /* Home key */
  1470. X                stuffin("1G");
  1471. X                return -1;
  1472. X            case 0x4f:        /* End key */
  1473. X                stuffin("G");
  1474. X                return -1;
  1475. X            case 0x51:        /* PgDn key */
  1476. X                stuffin(mkstr(CTRL('F')));
  1477. X                return -1;
  1478. X            case 0x49:        /* PgUp key */
  1479. X                stuffin(mkstr(CTRL('B')));
  1480. X                return -1;
  1481. X            case 0x52:        /* insert key */
  1482. X                return K_INSERT;
  1483. X            case 0x53:        /* delete key */
  1484. X                stuffin("x");
  1485. X                return -1;
  1486. X            /*
  1487. X             * Hard-code some useful function key macros.
  1488. X             */
  1489. X            case 0x3b: /* F1 */
  1490. X                stuffin(":help\n");
  1491. X                return -1;
  1492. X            case 0x3c: /* F2 */
  1493. X                stuffin(":n\n");
  1494. X                return -1;
  1495. X            case 0x55: /* SF2 */
  1496. X                stuffin(":n!\n");
  1497. X                return -1;
  1498. X            case 0x3d: /* F3 */
  1499. X                stuffin(":N\n");
  1500. X                return -1;
  1501. X            case 0x56: /* SF3 */
  1502. X                stuffin(":N!\n");
  1503. X                return -1;
  1504. X            case 0x3e: /* F4 */
  1505. X                stuffin(":e #\n");
  1506. X                return -1;
  1507. X            case 0x57: /* SF4 */
  1508. X                stuffin(":e! #\n");
  1509. X                return -1;
  1510. X            case 0x3f: /* F5 */
  1511. X                stuffin(":rew\n");
  1512. X                return -1;
  1513. X            case 0x58: /* SF5 */
  1514. X                stuffin(":rew!\n");
  1515. X                return -1;
  1516. X            case 0x40: /* F6 */
  1517. X                stuffin("]]");
  1518. X                return -1;
  1519. X            case 0x59: /* SF6 */
  1520. X                stuffin("[[");
  1521. X                return -1;
  1522. X            case 0x42: /* F8 - Set up global substitute */
  1523. X                stuffin(":1,$s/");
  1524. X                return -1;
  1525. X            case 0x43: /* F9 - declare C variable */
  1526. X                stuffin("yyp!!cdecl\n");
  1527. X                return -1;
  1528. X            case 0x5C: /* SF9 - explain C declaration */
  1529. X                stuffin("yyp^iexplain \033!!cdecl\n");
  1530. X                return -1;
  1531. X            case 0x44: /* F10 - save & quit */
  1532. X                stuffin(":x\n");
  1533. X                return -1;
  1534. X            case 0x5D: /* F10 - quit without saving */
  1535. X                stuffin(":q!\n");
  1536. X                return -1;
  1537. X            default:
  1538. X                break;
  1539. X            }
  1540. X            break;
  1541. X
  1542. X        default:
  1543. X            return c;
  1544. X        }
  1545. X    }
  1546. X}
  1547. X
  1548. X#define    BSIZE    2048
  1549. Xstatic    char    outbuf[BSIZE];
  1550. Xstatic    int    bpos = 0;
  1551. X
  1552. Xvoid
  1553. Xflushbuf()
  1554. X{
  1555. X    if (bpos != 0)
  1556. X        write(1, outbuf, bpos);
  1557. X    bpos = 0;
  1558. X}
  1559. X
  1560. X/*
  1561. X * Macro to output a character. Used within this file for speed.
  1562. X */
  1563. X#define    outone(c)    outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()
  1564. X
  1565. X/*
  1566. X * Function version for use outside this file.
  1567. X */
  1568. Xvoid
  1569. Xoutchar(c)
  1570. Xregister char    c;
  1571. X{
  1572. X    outbuf[bpos++] = c;
  1573. X    if (bpos >= BSIZE)
  1574. X        flushbuf();
  1575. X}
  1576. X
  1577. Xstatic    char    cell[2] = { 0, 7 };
  1578. X
  1579. X/*
  1580. X * outstr(s) - write a string to the console
  1581. X *
  1582. X * We implement insert/delete line escape sequences here. This is kind
  1583. X * of a kludge, but at least it's localized to a single point.
  1584. X */
  1585. Xvoid
  1586. Xoutstr(s)
  1587. Xregister char    *s;
  1588. X{
  1589. X    if (strcmp(s, T_DL) == 0) {        /* delete line */
  1590. X        int    r, c;
  1591. X
  1592. X        flushbuf();
  1593. X        VioGetCurPos(&r, &c, 0);
  1594. X        VioScrollUp(r, 0, 100, 100, 1, cell, 0);
  1595. X        return;
  1596. X    }
  1597. X    if (strcmp(s, T_IL) == 0) {        /* insert line */
  1598. X        int    r, c;
  1599. X
  1600. X        flushbuf();
  1601. X        VioGetCurPos(&r, &c, 0);
  1602. X        VioScrollDn(r, 0, 100, 100, 1, cell, 0);
  1603. X        return;
  1604. X    }
  1605. X
  1606. X    while (*s) {
  1607. X        outone(*s++);
  1608. X    }
  1609. X}
  1610. X
  1611. Xvoid
  1612. Xbeep()
  1613. X{
  1614. X    in ( P(P_VB) )
  1615. X        vbeep();
  1616. X    else
  1617. X        outone('\007');
  1618. X}
  1619. X
  1620. Xsleep(n)
  1621. Xint    n;
  1622. X{
  1623. X    DosSleep(1000L * n);
  1624. X}
  1625. X
  1626. Xvoid
  1627. Xpause()
  1628. X{
  1629. X    flushbuf();
  1630. X    DosSleep(300L);
  1631. X}
  1632. X
  1633. Xvoid
  1634. Xsig()
  1635. X{
  1636. X    signal(SIGINT, sig);
  1637. X
  1638. X    got_int = TRUE;
  1639. X}
  1640. X
  1641. Xvoid
  1642. Xwindinit()
  1643. X{
  1644. X    Columns = 80;
  1645. X    P(P_LI) = Rows = 25;
  1646. X
  1647. X    signal(SIGINT, sig);
  1648. X}
  1649. X
  1650. Xvoid
  1651. Xwindexit(r)
  1652. Xint r;
  1653. X{
  1654. X    flushbuf();
  1655. X    exit(r);
  1656. X}
  1657. X
  1658. Xvoid
  1659. Xwindgoto(r, c)
  1660. Xregister int    r, c;
  1661. X{
  1662. X    r += 1;
  1663. X    c += 1;
  1664. X
  1665. X    /*
  1666. X     * Check for overflow once, to save time.
  1667. X     */
  1668. X    if (bpos + 8 >= BSIZE)
  1669. X        flushbuf();
  1670. X
  1671. X    outbuf[bpos++] = '\033';
  1672. X    outbuf[bpos++] = '[';
  1673. X    if (r >= 10)
  1674. X        outbuf[bpos++] = r/10 + '0';
  1675. X    outbuf[bpos++] = r%10 + '0';
  1676. X    outbuf[bpos++] = ';';
  1677. X    if (c >= 10)
  1678. X        outbuf[bpos++] = c/10 + '0';
  1679. X    outbuf[bpos++] = c%10 + '0';
  1680. X    outbuf[bpos++] = 'H';
  1681. X}
  1682. X
  1683. XFILE *
  1684. Xfopenb(fname, mode)
  1685. Xchar    *fname;
  1686. Xchar    *mode;
  1687. X{
  1688. X    FILE    *fopen();
  1689. X    char    modestr[16];
  1690. X
  1691. X    sprintf(modestr, "%sb", mode);
  1692. X    return fopen(fname, modestr);
  1693. X}
  1694. X
  1695. X#define    PSIZE    128
  1696. X
  1697. X/*
  1698. X * fixname(s) - fix up a dos name
  1699. X *
  1700. X * Takes a name like:
  1701. X *
  1702. X *    \x\y\z\base.ext
  1703. X *
  1704. X * and trims 'base' to 8 characters, and 'ext' to 3.
  1705. X */
  1706. Xchar *
  1707. Xfixname(s)
  1708. Xchar    *s;
  1709. X{
  1710. X    char    *strchr(), *strrchr();
  1711. X    static    char    f[PSIZE];
  1712. X    char    base[32];
  1713. X    char    ext[32];
  1714. X    char    *p;
  1715. X    int    i;
  1716. X
  1717. X    strcpy(f, s);
  1718. X
  1719. X    for (i=0; i < PSIZE ;i++)
  1720. X        if (f[i] == '/')
  1721. X            f[i] = '\\';
  1722. X
  1723. X    /*
  1724. X     * Split the name into directory, base, extension.
  1725. X     */
  1726. X    if ((p = strrchr(f, '\\')) != NULL) {
  1727. X        strcpy(base, p+1);
  1728. X        p[1] = '\0';
  1729. X    } else {
  1730. X        strcpy(base, f);
  1731. X        f[0] = '\0';
  1732. X    }
  1733. X
  1734. X    if ((p = strchr(base, '.')) != NULL) {
  1735. X        strcpy(ext, p+1);
  1736. X        *p = '\0';
  1737. X    } else
  1738. X        ext[0] = '\0';
  1739. X
  1740. X    /*
  1741. X     * Trim the base name if necessary.
  1742. X     */
  1743. X    if (strlen(base) > 8)
  1744. X        base[8] = '\0';
  1745. X    
  1746. X    if (strlen(ext) > 3)
  1747. X        ext[3] = '\0';
  1748. X
  1749. X    /*
  1750. X     * Paste it all back together
  1751. X     */
  1752. X    strcat(f, base);
  1753. X    strcat(f, ".");
  1754. X    strcat(f, ext);
  1755. X
  1756. X    return f;
  1757. X}
  1758. X
  1759. Xvoid
  1760. Xdoshell(cmd)
  1761. Xchar    *cmd;
  1762. X{
  1763. X    if (cmd == NULL)
  1764. X        cmd = "cmd.exe";
  1765. X
  1766. X    system(cmd);
  1767. X    wait_return();
  1768. X}
  1769. X
  1770. X/*
  1771. X *    FILL IT IN, FOR YOUR SYSTEM, AND SHARE IT!
  1772. X *
  1773. X *    The next couple of functions do system-specific stuff.
  1774. X *    They currently do nothing; I'm not familiar enough with
  1775. X *    system-specific programming on this system.
  1776. X *    If you fill it in for your system, please post the results
  1777. X *    and share with the rest of us.
  1778. X */
  1779. X
  1780. X
  1781. Xsetcolor (c)
  1782. X/*
  1783. X * Set the color to c, using the local system convention for numbering
  1784. X * colors or video attributes.
  1785. X *
  1786. X * If you implement this, remember to note the original color in
  1787. X * windinit(), before you do any setcolor() commands, and
  1788. X * do a setcolor() back to the original as part of windexit().
  1789. X */
  1790. X  int c:
  1791. X{
  1792. X}
  1793. X
  1794. X
  1795. Xsetrows (r)
  1796. X/*
  1797. X * Set the number of lines to r, if possible.  Otherwise
  1798. X * "do the right thing".  Return the number of lines actually set.
  1799. X *
  1800. X * If you implement this, remember to note the original number of rows
  1801. X * in windinit(), before you do any setrows() commands, and
  1802. X * do a setrows() back to the original as part of windexit().
  1803. X */
  1804. X  int r;
  1805. X{
  1806. X    /* Since we do nothing, just return the current number of lines */
  1807. X    return ( P(P_LI) );
  1808. X}
  1809. X
  1810. X
  1811. Xvbeep ()
  1812. X/*
  1813. X * Do a "visual bell".  This generally consists of flashing the screen
  1814. X * once in inverse video.
  1815. X */
  1816. X{
  1817. X    int    color, revco;
  1818. X
  1819. X    color = P( P_CO );        /* get current color */
  1820. X    revco = reverse_color (color);    /* system-specific */
  1821. X    setcolor (revco);
  1822. X    flushbuf ();
  1823. X    pause ();
  1824. X    setcolor (color);
  1825. X    windgoto (Cursrow, Curscol);
  1826. X    flushbuf ();
  1827. X}
  1828. X
  1829. Xreverse_color (co)
  1830. X/*
  1831. X * Returns the inverse video attribute or color of co.
  1832. X * The existing code below is VERY simple-minded.
  1833. X * Replace it with proper code for your system.
  1834. X */
  1835. X int co;
  1836. X{
  1837. X    if (co)        return (0);
  1838. X    else        return (1);
  1839. X}
  1840. X
  1841. X
  1842. X/********** End of do-it-yourself kit **********************/
  1843. X
  1844. !EOR!
  1845. echo extracting - unix.c
  1846. sed 's/^X//' > unix.c << '!EOR!'
  1847. X/* $Header: /nw/tony/src/stevie/src/RCS/unix.c,v 1.8 89/08/06 09:51:13 tony Exp $
  1848. X *
  1849. X * System-dependent routines for UNIX System V or Berkeley.
  1850. X */
  1851. X
  1852. X#include "stevie.h"
  1853. X#ifdef BSD
  1854. X#include <sgtty.h>
  1855. X#else
  1856. X#include <termio.h>
  1857. X#endif
  1858. X#include <signal.h>
  1859. X
  1860. X/*
  1861. X * inchar() - get a character from the keyboard
  1862. X */
  1863. Xint
  1864. Xinchar()
  1865. X{
  1866. X    char    c;
  1867. X
  1868. X    flushbuf();        /* flush any pending output */
  1869. X
  1870. X    do {
  1871. X        while (read(0, &c, 1) != 1)
  1872. X            ;
  1873. X    } while (c == NUL);
  1874. X
  1875. X    got_int = FALSE;
  1876. X    return c;
  1877. X}
  1878. X
  1879. X#define    BSIZE    2048
  1880. Xstatic    char    outbuf[BSIZE];
  1881. Xstatic    int    bpos = 0;
  1882. X
  1883. Xvoid
  1884. Xflushbuf()
  1885. X{
  1886. X    if (bpos != 0)
  1887. X        write(1, outbuf, bpos);
  1888. X    bpos = 0;
  1889. X}
  1890. X
  1891. X/*
  1892. X * Macro to output a character. Used within this file for speed.
  1893. X */
  1894. X#define    outone(c)    outbuf[bpos++] = c; if (bpos >= BSIZE) flushbuf()
  1895. X
  1896. X/*
  1897. X * Function version for use outside this file.
  1898. X */
  1899. Xvoid
  1900. Xoutchar(c)
  1901. Xchar    c;
  1902. X{
  1903. X    outone(c);
  1904. X}
  1905. X
  1906. Xvoid
  1907. Xoutstr(s)
  1908. Xregister char    *s;
  1909. X{
  1910. X    while (*s) {
  1911. X        outone(*s++);
  1912. X    }
  1913. X}
  1914. X
  1915. Xvoid
  1916. Xbeep()
  1917. X{
  1918. X    if ( P(P_VB) )
  1919. X        vbeep ();
  1920. X    else
  1921. X        outone('\007');
  1922. X}
  1923. X
  1924. X/*
  1925. X * remove(file) - remove a file
  1926. X */
  1927. Xvoid
  1928. Xremove(file)
  1929. Xchar *file;
  1930. X{
  1931. X    unlink(file);
  1932. X}
  1933. X
  1934. X/*
  1935. X * rename(of, nf) - rename existing file 'of' to 'nf'
  1936. X */
  1937. Xvoid
  1938. Xrename(of, nf)
  1939. Xchar    *of, *nf;
  1940. X{
  1941. X    unlink(nf);
  1942. X    link(of, nf);
  1943. X    unlink(of);
  1944. X}
  1945. X
  1946. Xvoid
  1947. Xpause()
  1948. X{
  1949. X    sleep (1);
  1950. X}
  1951. X
  1952. X#ifdef BSD
  1953. Xstatic    struct    sgttyb    ostate;
  1954. X#else
  1955. Xstatic    struct    termio    ostate;
  1956. X#endif
  1957. X
  1958. X/*
  1959. X * Go into cbreak mode
  1960. X */
  1961. Xvoid
  1962. Xset_tty()
  1963. X{
  1964. X#ifdef BSD
  1965. X    struct    sgttyb    nstate;
  1966. X
  1967. X    ioctl(0, TIOCGETP, &ostate);
  1968. X    nstate = ostate;
  1969. X    nstate.sg_flags &= ~(XTABS|CRMOD|ECHO);
  1970. X    nstate.sg_flags |= CBREAK;
  1971. X    ioctl(0, TIOCSETN, &nstate);
  1972. X#else
  1973. X    struct    termio    nstate;
  1974. X
  1975. X    ioctl(0, TCGETA, &ostate);
  1976. X    nstate = ostate;
  1977. X    nstate.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL);
  1978. X    nstate.c_cc[VMIN] = 1;
  1979. X    nstate.c_cc[VTIME] = 0;
  1980. X    ioctl(0, TCSETAW, &nstate);
  1981. X#endif
  1982. X}
  1983. X
  1984. X/*
  1985. X * Restore original terminal modes
  1986. X */
  1987. Xvoid
  1988. Xreset_tty()
  1989. X{
  1990. X#ifdef BSD
  1991. X    ioctl(0, TIOCSETP, &ostate);
  1992. X#else
  1993. X    ioctl(0, TCSETAW, &ostate);
  1994. X#endif
  1995. X}
  1996. X
  1997. Xvoid
  1998. Xsig()
  1999. X{
  2000. X    signal(SIGINT, sig);
  2001. X    signal(SIGQUIT, sig);
  2002. X
  2003. X    got_int = TRUE;
  2004. X}
  2005. X
  2006. Xvoid
  2007. Xwindinit()
  2008. X{
  2009. X#ifdef    TERMCAP
  2010. X    if (t_init() != 1) {
  2011. X        fprintf(stderr, "unknown terminal type\n");
  2012. X        exit(1);
  2013. X    }
  2014. X#else
  2015. X    Columns = 80;
  2016. X    P(P_LI) = Rows = 24;
  2017. X#endif
  2018. X
  2019. X    /*
  2020. X     * The code here makes sure that there isn't a window during which
  2021. X     * we could get interrupted and exit with the tty in a weird state.
  2022. X     */
  2023. X    signal(SIGINT, sig);
  2024. X    signal(SIGQUIT, sig);
  2025. X
  2026. X    set_tty();
  2027. X
  2028. X    if (got_int)
  2029. X        windexit(0);
  2030. X}
  2031. X
  2032. Xvoid
  2033. Xwindexit(r)
  2034. Xint r;
  2035. X{
  2036. X    reset_tty();
  2037. X    exit(r);
  2038. X}
  2039. X
  2040. Xvoid
  2041. Xwindgoto(r, c)
  2042. Xregister int    r, c;
  2043. X{
  2044. X#ifdef    TERMCAP
  2045. X    char    *tgoto();
  2046. X#else
  2047. X    r += 1;
  2048. X    c += 1;
  2049. X#endif
  2050. X
  2051. X    /*
  2052. X     * Check for overflow once, to save time.
  2053. X     */
  2054. X    if (bpos + 8 >= BSIZE)
  2055. X        flushbuf();
  2056. X
  2057. X#ifdef    TERMCAP
  2058. X    outstr(tgoto(T_CM, c, r));
  2059. X#else
  2060. X    outbuf[bpos++] = '\033';
  2061. X    outbuf[bpos++] = '[';
  2062. X    if (r >= 10)
  2063. X        outbuf[bpos++] = r/10 + '0';
  2064. X    outbuf[bpos++] = r%10 + '0';
  2065. X    outbuf[bpos++] = ';';
  2066. X    if (c >= 10)
  2067. X        outbuf[bpos++] = c/10 + '0';
  2068. X    outbuf[bpos++] = c%10 + '0';
  2069. X    outbuf[bpos++] = 'H';
  2070. X#endif
  2071. X}
  2072. X
  2073. XFILE *
  2074. Xfopenb(fname, mode)
  2075. Xchar    *fname;
  2076. Xchar    *mode;
  2077. X{
  2078. X    return fopen(fname, mode);
  2079. X}
  2080. X
  2081. Xchar *
  2082. Xfixname(s)
  2083. Xchar    *s;
  2084. X{
  2085. X    return s;
  2086. X}
  2087. X
  2088. X/*
  2089. X * doshell() - run a command or an interactive shell
  2090. X */
  2091. Xvoid
  2092. Xdoshell(cmd)
  2093. Xchar    *cmd;
  2094. X{
  2095. X    char    *getenv();
  2096. X    char    cline[128];
  2097. X
  2098. X    outstr("\r\n");
  2099. X    flushbuf();
  2100. X
  2101. X    if (cmd == NULL) {
  2102. X        if ((cmd = getenv("SHELL")) == NULL)
  2103. X            cmd = "/bin/sh";
  2104. X        sprintf(cline, "%s -i", cmd);
  2105. X        cmd = cline;
  2106. X    }
  2107. X
  2108. X    reset_tty();
  2109. X    system(cmd);
  2110. X    set_tty();
  2111. X
  2112. X    wait_return();
  2113. X}
  2114. X
  2115. X
  2116. X/*
  2117. X *    FILL IT IN, FOR YOUR SYSTEM, AND SHARE IT!
  2118. X *
  2119. X *    The next couple of functions do system-specific stuff.
  2120. X *    They currently do nothing; I'm not familiar enough with
  2121. X *    system-specific programming on this system.
  2122. X *    If you fill it in for your system, please post the results
  2123. X *    and share with the rest of us.
  2124. X */
  2125. X
  2126. X
  2127. Xsetcolor (c)
  2128. X/*
  2129. X * Set the color to c, using the local system convention for numbering
  2130. X * colors or video attributes.
  2131. X *
  2132. X * If you implement this, remember to note the original color in
  2133. X * windinit(), before you do any setcolor() commands, and
  2134. X * do a setcolor() back to the original as part of windexit().
  2135. X */
  2136. X  int c;
  2137. X{
  2138. X    /* Dummy routine, just return 0 */
  2139. X    return (0);
  2140. X}
  2141. X
  2142. X
  2143. Xsetrows (r)
  2144. X/*
  2145. X * Set the number of lines to r, if possible.  Otherwise
  2146. X * "do the right thing".  Return the number of lines actually set.
  2147. X *
  2148. X * If you implement this, remember to note the original number of rows
  2149. X * in windinit(), before you do any setrows() commands, and
  2150. X * do a setrows() back to the original as part of windexit().
  2151. X */
  2152. X  int r;
  2153. X{
  2154. X    /* Since we do nothing, just return the current number of lines */
  2155. X    return ( P(P_LI) );
  2156. X}
  2157. X
  2158. X
  2159. Xvbeep ()
  2160. X/*
  2161. X * Do a "visual bell".  This generally consists of flashing the screen
  2162. X * once in inverse video.
  2163. X */
  2164. X{
  2165. X    int    color, revco;
  2166. X
  2167. X    color = P( P_CO );        /* get current color */
  2168. X    revco = reverse_color (color);    /* system-specific */
  2169. X    setcolor (revco);
  2170. X    flushbuf ();
  2171. X    pause ();
  2172. X    setcolor (color);
  2173. X    windgoto (Cursrow, Curscol);
  2174. X    flushbuf ();
  2175. X}
  2176. X
  2177. Xreverse_color (co)
  2178. X/*
  2179. X * Returns the inverse video attribute or color of co.
  2180. X * The existing code below is VERY simple-minded.
  2181. X * Replace it with proper code for your system.
  2182. X */
  2183. X int co;
  2184. X{
  2185. X    if (co)        return (0);
  2186. X    else        return (1);
  2187. X}
  2188. X
  2189. X
  2190. X/********** End of do-it-yourself kit **********************/
  2191. !EOR!
  2192. echo extracting - setenv.c
  2193. sed 's/^X//' > setenv.c << '!EOR!'
  2194. X/*****************************************************************************
  2195. X * A program for adding or changing environment variable values for MSDOS.
  2196. X * The "set" command provided by command.com is very limited.  It fails to
  2197. X * provide the ability to use quotation marks and escape characters and
  2198. X * octal/hex constants in the value definition.  Setenv provides these
  2199. X * abilities.
  2200. X *
  2201. X * Usage notes:
  2202. X *
  2203. X *    setenv <symbol> = <value>
  2204. X *
  2205. X *    <symbol> ::= legal MSDOS environment symbol.  Lower case converted
  2206. X *             to uppercase.
  2207. X *
  2208. X *    <value>  ::= environment symbol value in one of three forms:
  2209. X *
  2210. X *             * No quotation marks.  The value is the literal string
  2211. X *               of characters starting IMMEDIATELY after the equal
  2212. X *               sign and extending to the end-of-line.
  2213. X *
  2214. X *             * Single quotation marks (').  The value is the literal
  2215. X *               string enclosed in quotation marks.
  2216. X *
  2217. X *             * Double quotation marks (").  The value is the string
  2218. X *               enclosed in double quotation marks.  Backslash escape
  2219. X *               constructions are processed -- this includes the usual
  2220. X *               C language constructions such as \n for newline and
  2221. X *               \r for carriage return plus octal and hexadecimal
  2222. X *               constants (\ddd & \0xdd, respectively).
  2223. X *****************************************************************************/
  2224. X
  2225. X/*****************************************************************************
  2226. X * Based on a program by Alan J Myrvold (ajmyrvold@violet.waterloo.edu)
  2227. X *
  2228. X * WARNING WARNING WARNING - virtually no error checking is done !!
  2229. X *                           use at own risk !!
  2230. X *
  2231. X * This program by Larry A. Shurr (las@cbema.ATT.COM)
  2232. X *
  2233. X * I added checking for env seg overrun, so now it's a little more robust.
  2234. X *****************************************************************************/
  2235. X
  2236. X/*****************************************************************************
  2237. X *
  2238. X * Notes by Alan J Myrgold:
  2239. X *
  2240. X * Technical information : A program's PSP contains a pointer at
  2241. X * offset 44 (decimal) to a COPY of the parent's environment.
  2242. X * The environment is a set of strings of the form NAME=value,
  2243. X * each terminated by a NULL byte.
  2244. X * An additional NULL byte marks the end of the environment.
  2245. X * The environment area is ALWAYS paragraph aligned
  2246. X * i.e. on a 16 byte boundary.
  2247. X *
  2248. X * Searching backwards from the PSP, I consistently find
  2249. X * two copies of the envronment area.
  2250. X *
  2251. X * The program : finds the two areas
  2252. X *               reads one into memory
  2253. X *               udpates the specified environment variable
  2254. X *               writes updated environment to parent environment
  2255. X *****************************************************************************/
  2256. X
  2257. X#include <stdio.h>
  2258. X#include <stdlib.h>
  2259. X#include <string.h>
  2260. X#include <time.h>
  2261. X#include <process.h>
  2262. X#include <conio.h>
  2263. X#include <dos.h>
  2264. X
  2265. X#define FALSE 0
  2266. X#define TRUE  1
  2267. X
  2268. Xstruct mcb {                /* MSDOS Memory Control Block */
  2269. X  unsigned char tag4D;            /* Tag field must = 0x4D */
  2270. X  unsigned int  next;            /* Segment base for next block */
  2271. X  unsigned int  size;            /* Memory block size in paragraphs */
  2272. X};
  2273. X
  2274. X
  2275. Xunsigned env_size = 0;            /* Maintain size of environment */
  2276. X/***************************************************************************/
  2277. Xint env_size_bytes(unsigned env_seg)
  2278. X/* Determine the length of the environment area in bytes */
  2279. X{
  2280. X    int n;
  2281. X
  2282. X    n = 0;
  2283. X    while (peekb(env_seg,n) != 0) {
  2284. X          while (peekb(env_seg,n) != 0) n++;
  2285. X          n++;
  2286. X    }
  2287. X    return(n);
  2288. X}
  2289. X/***************************************************************************/
  2290. Xint env_size_strings(unsigned env_seg)
  2291. X/* Determine how many strings are in the environment area */
  2292. X{
  2293. X    int k,n;
  2294. X
  2295. X    k = n = 0;
  2296. X    while (peekb(env_seg,n) != 0) {
  2297. X          k++;
  2298. X          while (peekb(env_seg,n) != 0) n++;
  2299. X          n++;
  2300. X    }
  2301. X    return(k);
  2302. X}
  2303. X/***************************************************************************/
  2304. Xint peek_cmp(unsigned seg1,unsigned seg2,int nbytes)
  2305. X/* A trivial compare routine for segement aligned data items */
  2306. X{
  2307. X   int i;
  2308. X
  2309. X   for (i = 0; (i < nbytes) && (peekb(seg1,i) == peekb(seg2,i)); i++);
  2310. X   return(i == nbytes);
  2311. X}
  2312. X/***************************************************************************/
  2313. Xvoid find_env(unsigned seg_ray[2])
  2314. X{
  2315. X    unsigned psp_seg,copy_of_seg,env_seg;
  2316. X    int k,n;
  2317. X
  2318. X/* Find first copy of environment */
  2319. X    psp_seg = _psp;
  2320. X    copy_of_seg = peek(psp_seg,44);
  2321. X
  2322. X/* Set return value to non-garabage */
  2323. X    seg_ray[0] = seg_ray[1] = copy_of_seg;
  2324. X
  2325. X/* Search back to find 2 copies of environment */
  2326. X    env_size = n = env_size_bytes(copy_of_seg);
  2327. X    env_seg = copy_of_seg - 1;
  2328. X    for (k = 0; (env_seg != 0) && (k < 2); k++) {
  2329. X          while ((env_seg != 0) &&
  2330. X                 (peek_cmp(copy_of_seg,env_seg,n) == 0)) {
  2331. X                     env_seg--;
  2332. X          }
  2333. X          if (env_seg != 0) {
  2334. X              seg_ray[k] = env_seg;
  2335. X              env_seg--;
  2336. X          }
  2337. X    }
  2338. X
  2339. X/* If not found, display error message and abort */
  2340. X    if (k != 2) {
  2341. X       fprintf(stderr,"Two copies of the environment were not found\n");
  2342. X       exit(-1);
  2343. X    }
  2344. X}
  2345. X/***************************************************************************/
  2346. Xvoid read_env(unsigned env_seg,int *k,char ***s,char ***t)
  2347. X/* Read environment into a malloc'd array of malloc'd strings */
  2348. X{
  2349. X  int i,j,n;
  2350. X
  2351. X  env_size = env_size_bytes(env_seg);
  2352. X
  2353. X  *k = env_size_strings(env_seg);
  2354. X  *s = (char **) malloc((*k)*sizeof(char *));
  2355. X  *t = (char **) malloc((*k)*sizeof(char *));
  2356. X
  2357. X  n = 0;
  2358. X  for (i = 0; i < *k; i++) {
  2359. X    for (j = 0; peekb(env_seg,n+j) != '='; j++);
  2360. X    (*s)[i] = (char *) malloc(j+1);
  2361. X    for (j = 0; peekb(env_seg,n+j) != '='; j++)
  2362. X      ((*s)[i])[j] = peekb(env_seg,n+j);
  2363. X    ((*s)[i])[j] = 0;
  2364. X    n += j + 1;
  2365. X    for (j = 0; peekb(env_seg,n+j) != 0; j++);
  2366. X    (*t)[i] = (char *) malloc(j+1);
  2367. X    for (j = 0; peekb(env_seg,n+j) != 0; j++)
  2368. X      ((*t)[i])[j] = peekb(env_seg,n+j);
  2369. X    ((*t)[i])[j] = 0;
  2370. X    n += j + 1;
  2371. X  }
  2372. X}
  2373. X/***************************************************************************/
  2374. Xvoid write_env(unsigned env_seg, int k, char **s, char **t)
  2375. X/* Write the environment back out to memory */
  2376. X{
  2377. X  int i,j,n;
  2378. X
  2379. X  struct mcb far *tmcb = (struct mcb far *)((long)(env_seg-1) << 16);
  2380. X
  2381. X  if (tmcb->tag4D == 0x4D) {
  2382. X    unsigned env_seg_siz = tmcb->size << 4;
  2383. X    if (env_size < env_seg_siz) {
  2384. X      for (n = i = 0; i < k; i++) {
  2385. X        char *si = s[i];
  2386. X        char *ti = t[i];
  2387. X    for (j = 0; si[j] != 0; j++) pokeb(env_seg,n++,si[j]);
  2388. X    pokeb(env_seg,n++,'=');
  2389. X    for (j = 0; ti[j] != 0; j++) pokeb(env_seg,n++,ti[j]);
  2390. X    pokeb(env_seg,n++,0);
  2391. X      }
  2392. X      pokeb(env_seg,n,0);
  2393. X    } else {
  2394. X      fprintf(stderr,"Insufficient space in environment\n");
  2395. X      exit(-1);
  2396. X    }
  2397. X  } else {
  2398. X    fprintf(stderr,"Environment memory control block trashed\n");
  2399. X    exit(-1);
  2400. X  }
  2401. X}
  2402. X/***************************************************************************/
  2403. Xchar *get_env_var(int k,char **s,char **t,char *var)
  2404. X/* Return the value of the environment variable or NULL if not found */
  2405. X{
  2406. X    char *val;
  2407. X    int i;
  2408. X
  2409. X    val = NULL;
  2410. X    for (i = 0; i < k; i++) if (stricmp(s[i],var) == 0) val = t[i];
  2411. X
  2412. X    return(val);
  2413. X}
  2414. X
  2415. X/***************************************************************************/
  2416. Xvoid set_env_var(int *k,char ***s,char ***t,char *var,char *val)
  2417. X/* Set a new or existing environment variable to a new value */
  2418. X{
  2419. X  int i,done;
  2420. X
  2421. X  done = 0;
  2422. X  for (i = 0; i < *k; i++) {
  2423. X    if (stricmp((*s)[i],var) == 0) {
  2424. X      /* Existing variable */
  2425. X      done = 1;
  2426. X      env_size -= strlen((*t)[i]);
  2427. X      free((*t)[i]);
  2428. X      (*t)[i] = (char *) malloc(1+strlen(val));
  2429. X      strcpy((*t)[i],val);
  2430. X      env_size += strlen((*t)[i]);
  2431. X    }
  2432. X  }
  2433. X
  2434. X  if (!done) {
  2435. X    /* New environment variable */
  2436. X    (*k)++;
  2437. X    *s = realloc(*s,(*k)*sizeof(char *));
  2438. X    *t = realloc(*t,(*k)*sizeof(char *));
  2439. X    (*s)[*k-1] = (char *) malloc(1+strlen(var));
  2440. X    strcpy((*s)[*k-1],var);
  2441. X    strupr((*s)[*k-1]);
  2442. X    (*t)[*k-1] = (char *) malloc(1+strlen(val));
  2443. X    strcpy((*t)[*k-1],val);
  2444. X    /* Length of name  + length of '=' + length of value + length of '\0' */
  2445. X    env_size += (strlen((*s)[*k-1]) + 1 + strlen((*t)[*k-1]) + 1);
  2446. X  }
  2447. X}
  2448. X/***************************************************************************/
  2449. Xvoid show_env(int k,char **s,char **t)
  2450. X/* Display the array of environment strings */
  2451. X{
  2452. X   int i;
  2453. X   for (i = 0; i < k; i++) printf("%s=%s\n",s[i],t[i]);
  2454. X}
  2455. X/***************************************************************************/
  2456. Xvoid get_cmdline(char *cmd)
  2457. X/* Read raw command line text into string buffer */
  2458. X{
  2459. X    char far *pcmd;
  2460. X
  2461. X    int idx,odx;
  2462. X
  2463. X    pcmd = (char far *)((long)_psp << 16) + 128L;
  2464. X
  2465. X    for (idx = *pcmd++, odx = 0; idx > 0; idx--, odx++) {
  2466. X      cmd[odx] = *pcmd++;
  2467. X    }
  2468. X
  2469. X    cmd[odx] = '\0';
  2470. X}
  2471. X/***************************************************************************/
  2472. Xchar_in(char ch, char *set)
  2473. X/* Determine if a character is in a set of characters */
  2474. X{
  2475. X  do {
  2476. X    if (ch == *set) return(TRUE);
  2477. X  } while ((int)*(++set));
  2478. X  return(FALSE);
  2479. X}
  2480. X/***************************************************************************/
  2481. Xchar get_num(char *cmd, int *pidx)
  2482. X/* Interpret octal or hexadecimal constant in string */
  2483. X{
  2484. X  int   accum  = 0;
  2485. X  char  ch;
  2486. X  int   f_scan = TRUE;
  2487. X  int   idx    = *pidx;
  2488. X  int   limit;
  2489. X  char *nch    = cmd+idx;
  2490. X  char *och    = nch+1;
  2491. X  int   radix;
  2492. X
  2493. X#define HEXDIG "0123456789ABCDEFabcdef"
  2494. X
  2495. X  if (*nch == '0' && char_in(*och,"xX") && char_in(*(och+1),HEXDIG)) {
  2496. X    radix = 16;
  2497. X    limit = 2;
  2498. X    och += 1;
  2499. X  } else {
  2500. X    radix = 8;
  2501. X    limit = 3;
  2502. X    och = nch;
  2503. X  }
  2504. X
  2505. X  while (limit-- > 0 && f_scan) {
  2506. X
  2507. X    f_scan = FALSE;
  2508. X
  2509. X    while ((int)(*nch)) *nch++ = *och++;
  2510. X
  2511. X    nch = cmd+idx;
  2512. X    och = nch+1;
  2513. X
  2514. X    switch (ch = *nch) {
  2515. X      case '0' :
  2516. X      case '1' :
  2517. X      case '2' :
  2518. X      case '3' :
  2519. X      case '4' :
  2520. X      case '5' :
  2521. X      case '6' :
  2522. X      case '7' :
  2523. X      case '8' :
  2524. X      case '9' :
  2525. X    if (ch == 9 && radix == 8) break;
  2526. X    accum = accum * radix + (int)(ch - '0');
  2527. X        f_scan = TRUE;
  2528. X    break;
  2529. X      case 'A' :
  2530. X      case 'B' :
  2531. X      case 'C' :
  2532. X      case 'D' :
  2533. X      case 'E' :
  2534. X      case 'F' :
  2535. X    if (radix == 8) break;
  2536. X    accum = accum * radix + (int)(ch - 'A') + 10;
  2537. X        f_scan = TRUE;
  2538. X    break;
  2539. X      case 'a' :
  2540. X      case 'b' :
  2541. X      case 'c' :
  2542. X      case 'd' :
  2543. X      case 'e' :
  2544. X      case 'f' :
  2545. X    if (radix == 8) break;
  2546. X    accum = accum * radix + (int)(ch - 'a') + 10;
  2547. X        f_scan = TRUE;
  2548. X    break;
  2549. X      default  : break;
  2550. X    }
  2551. X  }
  2552. X
  2553. X  *pidx = idx;
  2554. X  return(accum);
  2555. X}
  2556. X/***************************************************************************/
  2557. Xget_escape(char *cmd, int *pidx, char quote)
  2558. X/* Interpret escape'd (i.e., '\' (backslash) character */
  2559. X{
  2560. X  int   idx = *pidx;
  2561. X
  2562. X  if (quote == '"') {
  2563. X    char *nch = cmd+idx;
  2564. X    char *och = nch+1;
  2565. X    char *xch = nch;
  2566. X    while ((int)(*nch)) *nch++ = *och++;
  2567. X    switch (*xch) {
  2568. X      case 'a' : *xch = '\a'; break;
  2569. X      case 'b' : *xch = '\b'; break;
  2570. X      case 'c' : *xch = '\c'; break;
  2571. X      case 'd' : *xch = '\d'; break;
  2572. X      case 'e' : *xch = '\e'; break;
  2573. X      case 'f' : *xch = '\f'; break;
  2574. X      case 'g' : *xch = '\g'; break;
  2575. X      case 'h' : *xch = '\h'; break;
  2576. X      case 'i' : *xch = '\i'; break;
  2577. X      case 'j' : *xch = '\j'; break;
  2578. X      case 'k' : *xch = '\k'; break;
  2579. X      case 'l' : *xch = '\l'; break;
  2580. X      case 'm' : *xch = '\m'; break;
  2581. X      case 'n' : *xch = '\n'; break;
  2582. X      case 'o' : *xch = '\o'; break;
  2583. X      case 'p' : *xch = '\p'; break;
  2584. X      case 'q' : *xch = '\q'; break;
  2585. X      case 'r' : *xch = '\r'; break;
  2586. X      case 's' : *xch = '\s'; break;
  2587. X      case 't' : *xch = '\t'; break;
  2588. X      case 'u' : *xch = '\u'; break;
  2589. X      case 'v' : *xch = '\v'; break;
  2590. X      case 'w' : *xch = '\w'; break;
  2591. X      case 'x' : *xch = '\x'; break;
  2592. X      case 'y' : *xch = '\y'; break;
  2593. X      case 'z' : *xch = '\z'; break;
  2594. X      case '0' :
  2595. X      case '1' :
  2596. X      case '2' :
  2597. X        *xch = get_num(cmd, &idx);
  2598. X        break;
  2599. X    }
  2600. X  }
  2601. X
  2602. X  *pidx = idx + 1;
  2603. X}
  2604. X/***************************************************************************/
  2605. Xget_qvalue(char *cmd, int idx, char quote, char **value)
  2606. X/* Extract a quoted value part from command line */
  2607. X{
  2608. X  char ch;
  2609. X  int  f_esc;
  2610. X
  2611. X  *value = cmd + (++idx);
  2612. X
  2613. X  do {
  2614. X    while ((int)(ch = cmd[idx]) && ch != '\\' && ch != quote) idx++;
  2615. X    if (!(int)ch) return(-1);
  2616. X    if (ch == '\\') {
  2617. X      f_esc = TRUE;
  2618. X      get_escape(cmd, &idx, quote);
  2619. X    } else f_esc = FALSE;
  2620. X  } while (f_esc);
  2621. X
  2622. X  cmd[idx] = '\0';
  2623. X
  2624. X  for (idx += 1; (int)(ch = cmd[idx]) && ch == ' '; idx++);
  2625. X
  2626. X  if ((int)ch) return(-1);
  2627. X
  2628. X  return(0);
  2629. X}
  2630. X/***************************************************************************/
  2631. Xget_parm(char **name, char **value)
  2632. X/* Extract environment symbol name and value from command line */
  2633. X{
  2634. X    char ch;
  2635. X    int  idx;
  2636. X    int  sdx;
  2637. X
  2638. X    static char cmd[128];
  2639. X
  2640. X    get_cmdline(cmd);
  2641. X
  2642. X    for (idx = 0; (int)(ch = cmd[idx]) && ch  == ' '; idx++);
  2643. X
  2644. X    if (!(int)ch) return(1);
  2645. X
  2646. X    *name = cmd + idx;
  2647. X
  2648. X    for (; (int)(ch = cmd[idx]) && ch != '=' && ch != ' '; idx++);
  2649. X
  2650. X    if (!(int)ch) return(-1);
  2651. X
  2652. X    if (ch == ' ') {
  2653. X      cmd[idx] = '\0';
  2654. X      for (idx += 1; (int)(ch = cmd[idx]) && ch != '='; idx++);
  2655. X    } else cmd[idx] = '\0';
  2656. X
  2657. X    if (!(int)ch) return(-1);
  2658. X
  2659. X    for (sdx = (idx += 1); (int)(ch = cmd[idx]) && ch == ' '; idx++);
  2660. X
  2661. X    /*if (!(int)ch) return(-1);*/
  2662. X
  2663. X    switch (ch) {
  2664. X      case '"'  : return(get_qvalue(cmd, idx, '"', value));
  2665. X      case '\'' : return(get_qvalue(cmd, idx, '\'', value));
  2666. X      default   : *value = cmd + sdx; break;
  2667. X    }
  2668. X
  2669. X    return(0);
  2670. X}
  2671. X/***************************************************************************/
  2672. Xmain(int argc,char **argv)
  2673. X{
  2674. X    unsigned env_seg[2];
  2675. X    char **s,**t;
  2676. X    int k;
  2677. X    long now;
  2678. X    struct tm *local;
  2679. X
  2680. X    static char *name = NULL, *value = NULL;
  2681. X
  2682. X    switch (get_parm(&name,&value)) {
  2683. X
  2684. X    case -1:
  2685. X
  2686. X    fprintf(stderr,"Invalid symbol definition syntax\n");
  2687. X    exit(-1);
  2688. X
  2689. X    case 0:
  2690. X
  2691. X        /* Find and read environment */
  2692. X
  2693. X        find_env(env_seg);
  2694. X        read_env(env_seg[1],&k,&s,&t);
  2695. X
  2696. X    /* Set the variable <name> to <value> */
  2697. X
  2698. X    set_env_var(&k,&s,&t,name,value);
  2699. X
  2700. X    /* Update caller's environment */
  2701. X
  2702. X    write_env(env_seg[0],k,s,t);
  2703. X
  2704. X    break;
  2705. X
  2706. X    case 1:
  2707. X
  2708. X    fprintf(stderr,"Usage: setenv <symbol name> = <value>\n");
  2709. X    break;
  2710. X    }
  2711. X
  2712. X    return(0);
  2713. X}
  2714. X/***************************************************************************/
  2715. X
  2716. !EOR!
  2717. echo extracting - ctags.c
  2718. sed 's/^X//' > ctags.c << '!EOR!'
  2719. X/*
  2720. X * ctags - first cut at a UNIX ctags re-implementation
  2721. X */
  2722. X
  2723. X/*
  2724. X * Caveats:
  2725. X *
  2726. X * Only simple function declarations are recognized, as in:
  2727. X *
  2728. X * type
  2729. X * fname(...)
  2730. X *
  2731. X * where "fname" is the name of the function and must come at the beginning
  2732. X * of a line. This is the form I always use, so the limitation doesn't
  2733. X * bother me.
  2734. X *
  2735. X * Macros (with or without parameters) of the following form are also detected:
  2736. X *
  2737. X * "#" [white space] "define" [white space] NAME
  2738. X *
  2739. X * No sorting or detection of duplicate functions is done.
  2740. X *
  2741. X * If there are no arguments, a list of filenames to be searched is read
  2742. X * from the standard input. Otherwise, all arguments are assumed to be
  2743. X * file names.
  2744. X *
  2745. X * Tony Andrews
  2746. X * August 1987
  2747. X */
  2748. X
  2749. X#include <stdio.h>
  2750. X#include <ctype.h>
  2751. X#include <string.h>
  2752. X
  2753. Xint    ac;
  2754. Xchar    **av;
  2755. X
  2756. Xmain(argc, argv)
  2757. Xint    argc;
  2758. Xchar    *argv[];
  2759. X{
  2760. X    char    *fname, *nextfile();
  2761. X    FILE    *tp, *fopen();
  2762. X
  2763. X    ac = argc;
  2764. X    av = argv;
  2765. X
  2766. X    if ((tp = fopen("tags", "w")) == NULL) {
  2767. X        fprintf(stderr, "Can't create tags file\n");
  2768. X        exit(1);
  2769. X    }
  2770. X
  2771. X    while ((fname = nextfile()) != NULL)
  2772. X        dofile(fname, tp);
  2773. X
  2774. X    fclose(tp);
  2775. X    exit(0);
  2776. X}
  2777. X
  2778. Xchar *
  2779. Xnextfile()    /* returns ptr to next file to be searched, null at end */
  2780. X{
  2781. X    static    char    buf[128];
  2782. X    static    int    ap = 1;
  2783. X    char    *gets();
  2784. X
  2785. X    if (ac <= 1) {        /* read from stdin */
  2786. X        if (feof(stdin))
  2787. X            return (char *) NULL;
  2788. X        return (gets(buf));
  2789. X    } else {
  2790. X        if (ap < ac)
  2791. X            return av[ap++];
  2792. X        else
  2793. X            return (char *) NULL;
  2794. X    }
  2795. X}
  2796. X
  2797. X#define    LSIZE    512    /* max. size of a line */
  2798. X
  2799. X#define    BEGID(c)    (isalpha(c) || (c) == '_')
  2800. X#define    MIDID(c)    (isalpha(c) || isdigit(c) || (c) == '_')
  2801. X
  2802. Xdofile(fn, tp)
  2803. Xchar    *fn;
  2804. XFILE    *tp;
  2805. X{
  2806. X    FILE    *fp, *fopen();
  2807. X    char    *cp, *strchr();
  2808. X    char    lbuf[LSIZE];
  2809. X    char    func[LSIZE];
  2810. X    int    i, j;
  2811. X
  2812. X    if ((fp = fopen(fn, "r")) == NULL) {
  2813. X        fprintf(stderr, "Can't open file '%s' - skipping\n", fn);
  2814. X        return;
  2815. X    }
  2816. X
  2817. X    while (fgets(lbuf, LSIZE, fp) != NULL) {
  2818. X
  2819. X        lbuf[strlen(lbuf)-1] = '\0';    /* bag the newline */
  2820. X
  2821. X        if (BEGID(lbuf[0])) {        /* could be a function */
  2822. X            for (i=0; MIDID(lbuf[i]) ;i++)    /* grab the name */
  2823. X                func[i] = lbuf[i];
  2824. X
  2825. X            func[i] = '\0';        /* null terminate the name */
  2826. X
  2827. X            /*
  2828. X             * We've skipped to the end of what may be a function
  2829. X             * name. Check to see if the next non-whitespace
  2830. X             * char is a paren,
  2831. X             * and make sure the closing paren is here too.
  2832. X             */
  2833. X            while (lbuf[i]==' ' || lbuf[i]=='\t') i++;
  2834. X            if (lbuf[i]=='(' && (((cp = strchr(lbuf,')'))!=NULL))) {
  2835. X                *++cp = '\0';
  2836. X                fprintf(tp, "%s\t%s\t/^%s$/\n", func,fn,lbuf);
  2837. X            }
  2838. X
  2839. X        } else if (lbuf[0] == '#') {    /* could be a define */
  2840. X            for (i=1; isspace(lbuf[i]) ;i++)
  2841. X                ;
  2842. X            if (strncmp(&lbuf[i], "define", 6) != 0)
  2843. X                continue;
  2844. X
  2845. X            i += 6;            /* skip "define" */
  2846. X
  2847. X            for (; isspace(lbuf[i]) ;i++)
  2848. X                ;
  2849. X
  2850. X            if (!BEGID(lbuf[i]))
  2851. X                continue;
  2852. X
  2853. X            for (j=0; MIDID(lbuf[i]) ;i++, j++)
  2854. X                func[j] = lbuf[i];
  2855. X
  2856. X            func[j] = '\0';        /* null terminate the name */
  2857. X            lbuf[i] = '\0';
  2858. X            fprintf(tp, "%s\t%s\t/^%s/\n", func, fn, lbuf);
  2859. X        }
  2860. X    }
  2861. X    fclose(fp);
  2862. X}
  2863. !EOR!
  2864.  
  2865.  
  2866.