home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3500 < prev    next >
Encoding:
Internet Message Format  |  1991-06-20  |  54.5 KB

  1. From: pgf@cayman.COM (Paul Fox)
  2. Newsgroups: alt.sources
  3. Subject: Vile 06/17 - vi feel-alike (multi-window)
  4. Message-ID: <4525@cayman.COM>
  5. Date: 7 Jun 91 22:09:32 GMT
  6.  
  7. #!/bin/sh
  8. # this is vileshar.06 (part 6 of Vile)
  9. # do not concatenate these parts, unpack them in order with /bin/sh
  10. # file evar.h continued
  11. #
  12. if test ! -r _shar_seq_.tmp; then
  13.     echo 'Please unpack part 1 first!'
  14.     exit 1
  15. fi
  16. (read Scheck
  17.  if test "$Scheck" != 6; then
  18.     echo Please unpack part "$Scheck" next!
  19.     exit 1
  20.  else
  21.     exit 0
  22.  fi
  23. ) < _shar_seq_.tmp || exit 1
  24. echo 'x - continuing file evar.h'
  25. sed 's/^X//' << 'SHAR_EOF' >> 'evar.h' &&
  26. X
  27. /*    list of recognized environment variables    */
  28. X
  29. char *envars[] = {
  30. X    "fillcol",        /* current fill column */
  31. X    "pagelen",        /* number of lines used by editor */
  32. X    "curcol",        /* current column pos of cursor */
  33. X    "curline",        /* current line in file */
  34. X    "ram",            /* ram in use by malloc */
  35. X    "flicker",        /* flicker supression */
  36. X    "curwidth",        /* current screen width */
  37. X    "cbufname",        /* current buffer name */
  38. X    "cfname",        /* current file name */
  39. X    "sres",            /* current screen resolution */
  40. X    "debug",        /* macro debugging */
  41. X    "status",        /* returns the status of the last command */
  42. X    "palette",        /* current palette string */
  43. X    "asave",        /* # of chars between auto-saves */
  44. X    "acount",        /* # of chars until next auto-save */
  45. X    "lastkey",        /* last keyboard char struck */
  46. X    "curchar",        /* current character under the cursor */
  47. X    "discmd",        /* display commands on command line */
  48. X    "version",        /* current version number */
  49. X    "progname",        /* returns current prog name - "vile" */
  50. X    "seed",            /* current random number seed */
  51. X    "disinp",        /* display command line input characters */
  52. X    "wline",        /* # of lines in current window */
  53. X    "cwline",        /* current screen line in window */
  54. X    "target",        /* target for line moves */
  55. X    "search",        /* search pattern */
  56. X    "replace",        /* replacement pattern */
  57. X    "match",        /* last matched magic pattern */
  58. X    "kill",            /* kill buffer (read only) */
  59. X    "cmode",        /* mode of current buffer */
  60. X    "gmode",        /* global modes */
  61. X    "tpause",        /* length to pause for paren matching */
  62. X    "pending",        /* type ahead pending flag */
  63. X    "lwidth",        /* width of current line */
  64. X    "line",            /* text of current line */
  65. };
  66. X
  67. #define    NEVARS    sizeof(envars) / sizeof(char *)
  68. X
  69. /*     and its preprocesor definitions        */
  70. X
  71. #define    EVFILLCOL    0
  72. #define    EVPAGELEN    1
  73. #define    EVCURCOL    2
  74. #define    EVCURLINE    3
  75. #define    EVRAM        4
  76. #define    EVFLICKER    5
  77. #define    EVCURWIDTH    6
  78. #define    EVCBUFNAME    7
  79. #define    EVCFNAME    8
  80. #define    EVSRES        9
  81. #define    EVDEBUG        10
  82. #define    EVSTATUS    11
  83. #define    EVPALETTE    12
  84. #define    EVASAVE        13
  85. #define    EVACOUNT    14
  86. #define    EVLASTKEY    15
  87. #define    EVCURCHAR    16
  88. #define    EVDISCMD    17
  89. #define    EVVERSION    18
  90. #define    EVPROGNAME    19
  91. #define    EVSEED        20
  92. #define    EVDISINP    21
  93. #define    EVWLINE        22
  94. #define EVCWLINE    23
  95. #define    EVTARGET    24
  96. #define    EVSEARCH    25
  97. #define    EVREPLACE    26
  98. #define    EVMATCH        27
  99. #define    EVKILL        28
  100. #define    EVCMODE        29
  101. #define    EVGMODE        30
  102. #define    EVTPAUSE    31
  103. #define    EVPENDING    32
  104. #define    EVLWIDTH    33
  105. #define    EVLINE        34
  106. X
  107. /*    list of recognized user functions    */
  108. X
  109. typedef struct UFUNC {
  110. X    char *f_name;    /* name of function */
  111. X    int f_type;    /* 1 = monamic, 2 = dynamic */
  112. } UFUNC;
  113. X
  114. #define    NILNAMIC    0
  115. #define    MONAMIC        1
  116. #define    DYNAMIC        2
  117. #define    TRINAMIC    3
  118. X
  119. UFUNC funcs[] = {
  120. X    "add", DYNAMIC,        /* add two numbers together */
  121. X    "sub", DYNAMIC,        /* subtraction */
  122. X    "tim", DYNAMIC,        /* multiplication */
  123. X    "div", DYNAMIC,        /* division */
  124. X    "mod", DYNAMIC,        /* mod */
  125. X    "neg", MONAMIC,        /* negate */
  126. X    "cat", DYNAMIC,        /* concatinate string */
  127. X    "lef", DYNAMIC,        /* left string(string, len) */
  128. X    "rig", DYNAMIC,        /* right string(string, pos) */
  129. X    "mid", TRINAMIC,    /* mid string(string, pos, len) */
  130. X    "not", MONAMIC,        /* logical not */
  131. X    "equ", DYNAMIC,        /* logical equality check */
  132. X    "les", DYNAMIC,        /* logical less than */
  133. X    "gre", DYNAMIC,        /* logical greater than */
  134. X    "seq", DYNAMIC,        /* string logical equality check */
  135. X    "sle", DYNAMIC,        /* string logical less than */
  136. X    "sgr", DYNAMIC,        /* string logical greater than */
  137. X    "ind", MONAMIC,        /* evaluate indirect value */
  138. X    "and", DYNAMIC,        /* logical and */
  139. X    "or",  DYNAMIC,        /* logical or */
  140. X    "len", MONAMIC,        /* string length */
  141. X    "upp", MONAMIC,        /* uppercase string */
  142. X    "low", MONAMIC,        /* lower case string */
  143. X    "tru", MONAMIC,        /* Truth of the universe logical test */
  144. X    "asc", MONAMIC,        /* char to integer conversion */
  145. X    "chr", MONAMIC,        /* integer to char conversion */
  146. X    "gtk", NILNAMIC,    /* get 1 charater */
  147. X    "rnd", MONAMIC,        /* get a random number */
  148. X    "abs", MONAMIC,        /* absolute value of a number */
  149. X    "sin", DYNAMIC,        /* find the index of one string in another */
  150. X    "env", MONAMIC,        /* retrieve a system environment var */
  151. X    "bin", MONAMIC,        /* loopup what function name is bound to a key */
  152. };
  153. X
  154. #define    NFUNCS    sizeof(funcs) / sizeof(UFUNC)
  155. X
  156. /*     and its preprocesor definitions        */
  157. X
  158. #define    UFADD        0
  159. #define    UFSUB        1
  160. #define    UFTIMES        2
  161. #define    UFDIV        3
  162. #define    UFMOD        4
  163. #define    UFNEG        5
  164. #define    UFCAT        6
  165. #define    UFLEFT        7
  166. #define    UFRIGHT        8
  167. #define    UFMID        9
  168. #define    UFNOT        10
  169. #define    UFEQUAL        11
  170. #define    UFLESS        12
  171. #define    UFGREATER    13
  172. #define    UFSEQUAL    14
  173. #define    UFSLESS        15
  174. #define    UFSGREAT    16
  175. #define    UFIND        17
  176. #define    UFAND        18
  177. #define    UFOR        19
  178. #define    UFLENGTH    20
  179. #define    UFUPPER        21
  180. #define    UFLOWER        22
  181. #define    UFTRUTH        23
  182. #define    UFASCII        24
  183. #define    UFCHR        25
  184. #define    UFGTKEY        26
  185. #define    UFRND        27
  186. #define    UFABS        28
  187. #define    UFSINDEX    29
  188. #define    UFENV        30
  189. #define    UFBIND        31
  190. X
  191. #endif
  192. SHAR_EOF
  193. echo 'File evar.h is complete' &&
  194. chmod 0444 evar.h ||
  195. echo 'restore of evar.h failed'
  196. Wc_c="`wc -c < 'evar.h'`"
  197. test 5247 -eq "$Wc_c" ||
  198.     echo 'evar.h: original size 5247, current size' "$Wc_c"
  199. # ============= exec.c ==============
  200. echo 'x - extracting exec.c (Text)'
  201. sed 's/^X//' << 'SHAR_EOF' > 'exec.c' &&
  202. /*    This file is for functions dealing with execution of
  203. X    commands, command lines, buffers, files and startup files
  204. X
  205. X    written 1986 by Daniel Lawrence                */
  206. X
  207. #include    <stdio.h>
  208. #include    "estruct.h"
  209. #include    "edef.h"
  210. X
  211. /* namedcmd:    execute a named command even if it is not bound */
  212. X
  213. namedcmd(f, n)
  214. int f, n;
  215. {
  216. X    char *fnp;    /* ptr to the name of the cmd to exec */
  217. X    LINE *fromline;    /* first linespec */
  218. X    LINE *toline;    /* second linespec */
  219. X    char lspec[NLINE];
  220. X    int cpos = 0;
  221. X    int s,c,isdfl,zero,flags;
  222. X    char *kbd_engl();
  223. X    CMDFUNC *cfp;        /* function to execute */
  224. X    extern CMDFUNC f_gomark;
  225. X
  226. X    /* prompt the user to type a named command */
  227. X    mlwrite(": ");
  228. X
  229. X    /* and now get the function name to execute */
  230. #if    NeWS
  231. X    newsimmediateon() ;
  232. #endif
  233. X
  234. X    while(1) {
  235. X        c = tgetc();
  236. X        if (c == '\r') {
  237. X            lspec[cpos] = 0;
  238. X            fnp = NULL;
  239. X            break;
  240. X        } else if (c == kcod2key(abortc)) {    /* Bell, abort */
  241. X        isabortc:
  242. X            lspec[0] = '\0';
  243. X            return FALSE;
  244. X        } else if (isbackspace(c)) {
  245. X            if (cpos != 0) {
  246. X                TTputc('\b');
  247. X                TTputc(' ');
  248. X                TTputc('\b');
  249. X                --ttcol;
  250. X                --cpos;
  251. X            } else {
  252. X                lspec[0] = '\0';
  253. X                lineinput = FALSE;
  254. X                return FALSE;
  255. X            }
  256. X
  257. X        } else if (c == kcod2key(killc)) {    /* ^U, kill */
  258. X        iskillc:
  259. X            while (cpos != 0) {
  260. X                TTputc('\b');
  261. X                TTputc(' ');
  262. X                TTputc('\b');
  263. X                --cpos;
  264. X                --ttcol;
  265. X            }
  266. X        } else if (islinespecchar(c) ||
  267. X            /* special test for 'a style mark references */
  268. X                (cpos > 0 &&
  269. X                 lspec[cpos-1] == '\'' &&
  270. X                 (islower(c) || (c == '\'') )
  271. X                )
  272. X             ) {
  273. X            lspec[cpos++] = c;
  274. X            TTputc(c);
  275. X            ++ttcol;
  276. X        } else {
  277. X            int status;
  278. X            tungetc(c);
  279. X            lspec[cpos] = 0;
  280. X            status = kbd_engl_stat(&fnp);
  281. X            if (status == TRUE) {
  282. X                break;
  283. X            } else if (status == SORTOFTRUE) {
  284. X                fnp = NULL;
  285. X                continue;
  286. X            } else {
  287. X                return status;
  288. X            }
  289. X        }
  290. X        TTflush();
  291. X    }
  292. X
  293. X    /* parse the accumulated lspec */
  294. X    if (rangespec(lspec,&fromline,&toline,&isdfl,&zero) != TRUE) {
  295. X        mlwrite("[Improper line range]");
  296. X        return FALSE;
  297. X    }
  298. X
  299. X    /* if range given, and it wasn't "0" and the buffer's empty */
  300. X    if (!isdfl && !zero && (lforw(curbp->b_linep) == curbp->b_linep)) {
  301. X        mlwrite("[No range possible in empty buffer]", fnp);
  302. X        return FALSE;
  303. X    }
  304. X
  305. #if    NeWS
  306. X    newsimmediateoff() ;
  307. #endif
  308. X
  309. X    /* did we get a name? */
  310. X    if (fnp == NULL) {
  311. X        if (isdfl) { /* no range, no function */
  312. X            mlwrite("[No such function]");
  313. X            return FALSE;
  314. X        } else { /* range, no function */
  315. X            cfp = &f_gomark;
  316. X            fnp = "";
  317. X        }
  318. X    } else if ((cfp = engl2fnc(fnp)) == NULL) { /* bad function */
  319. X        mlwrite("[No such function %s]",fnp);
  320. X        return FALSE;
  321. X    }
  322. X    flags = cfp->c_flags;
  323. X    
  324. X    /* bad arguments? */
  325. #ifdef EXRC_FILES
  326. seems like we need one more check here -- is it from a .exrc file?
  327. X        cmd not ok in .exrc         empty file
  328. X    if (!(flags & EXRCOK) && (lforw(curbp->b_linep) == curbp->b_linep)) {
  329. X        mlwrite("[Can't use the \"%s\" command in a %s file.]", 
  330. X                    cmdnames[cmdidx].name, EXRC);
  331. X        return FALSE;
  332. X    }
  333. #endif
  334. X
  335. X    /* was: if (!(flags & (ZERO | EXRCOK)) && fromline == NULL ) { */
  336. X    if (zero) {
  337. X        extern CMDFUNC f_lineputafter, f_opendown, f_insfile;
  338. X        extern CMDFUNC f_lineputbefore, f_openup;
  339. X        if (!(flags & ZERO)) {
  340. X            mlwrite("[Can't use address 0 with \"%s\" command]", fnp);
  341. X            return FALSE;
  342. X        }
  343. X        /*  we're positioned at fromline == curbp->b_linep, so commands
  344. X            must be willing to go _down_ from there.  Seems easiest
  345. X            to special case the commands that prefer going up */
  346. X        if (cfp == &f_insfile) {
  347. X            /* works okay -- acts down normally */
  348. X        } else if (cfp == &f_lineputafter) {
  349. X            cfp = &f_lineputbefore;
  350. X            fromline = lforw(fromline);
  351. X        } else if (cfp == &f_opendown) {
  352. X            cfp = &f_openup;
  353. X            fromline = lforw(fromline);
  354. X        } else {
  355. X            mlwrite("[Configuration error: ZERO]");
  356. X            return FALSE;
  357. X        }
  358. X        flags = cfp->c_flags;
  359. X        toline = fromline;
  360. X    }
  361. X
  362. X    /* if we're not supposed to have a line no., and the line no. isn't
  363. X        the current line, and there's more than one line */
  364. X    if (!(flags & FROM) && fromline != curwp->w_dotp && 
  365. X            (lforw(curbp->b_linep)  != curbp->b_linep) &&
  366. X          (lforw(lforw(curbp->b_linep)) != curbp->b_linep) ) {
  367. X        mlwrite("[Can't use address with \"%s\" command.]", fnp);
  368. X        return FALSE;
  369. X    }
  370. X    /* if we're not supposed to have a second line no., and the line no. 
  371. X        isn't the same as the first line no., and there's more than
  372. X        one line */
  373. X    if (!(flags & TO) && toline != fromline &&
  374. X            (lforw(curbp->b_linep) != curbp->b_linep) &&
  375. X          (lforw(lforw(curbp->b_linep)) != curbp->b_linep) ) {
  376. X        mlwrite("[Can't use a range with \"%s\" command.]", fnp);
  377. X        return FALSE;
  378. X    }
  379. #ifdef NEEDED
  380. X    if (!(flags & EXTRA) && *scan) {
  381. X        mlwrite("[Extra characters after \"%s\" command.]", 
  382. X                        cmdnames[cmdidx].name);
  383. X        return FALSE;
  384. X    }
  385. #endif
  386. #ifdef NEEDED
  387. X    if ((flags & NOSPC) && !(cmd == CMD_READ && (forceit || *scan == '!'))) {
  388. X        build = scan;
  389. #ifndef CRUNCH  /* what is this for? -pgf */
  390. X        if ((flags & PLUS) && *build == '+') {
  391. X            while (*build && !(isspace(*build))) {
  392. X                build++;
  393. X            }
  394. X            while (*build && isspace(*build)) {
  395. X                build++;
  396. X            }
  397. X        }
  398. #endif /* not CRUNCH */
  399. X        for (; *build; build++) {
  400. X            if (isspace(*build)) {
  401. X                mlwrite("[Too many %s to \"%s\" command.]",
  402. X                    (flags & XFILE) ? "filenames" : "arguments",
  403. X                    cmdnames[cmdidx].name);
  404. X                return FALSE;
  405. X            }
  406. X        }
  407. X    }
  408. #endif /* NEEDED */
  409. X
  410. X    /* some commands have special default ranges */
  411. X    if (isdfl) {
  412. X        if (flags & DFLALL) {
  413. X            extern CMDFUNC f_operwrite, f_filewrite, f_operglobals,
  414. X                    f_globals, f_opervglobals, f_vglobals;
  415. X            if (cfp == &f_operwrite) {
  416. X                cfp = &f_filewrite;
  417. #if GLOBALS
  418. X            } else if (cfp == &f_operglobals) {
  419. X                cfp = &f_globals;
  420. X            } else if (cfp == &f_opervglobals) {
  421. X                cfp = &f_vglobals;
  422. #endif
  423. X            } else {
  424. X                mlwrite("[Configuration error: DFLALL]");
  425. X                return FALSE;
  426. X            }
  427. X        } else if (flags & DFLNONE) {
  428. X            extern CMDFUNC f_operfilter, f_spawn;
  429. X            if (cfp == &f_operfilter) {
  430. X                cfp = &f_spawn;
  431. X                setmark();  /* not that it matters */
  432. X            } else {
  433. X                mlwrite("[Configuration error: DFLNONE]");
  434. X                return FALSE;
  435. X            }
  436. X            fromline = toline = NULL;
  437. X        }
  438. X    }
  439. X
  440. #ifdef NEEDED
  441. X    /* write a newline if called from visual mode */
  442. X    if ((flags & NL) && !exmode /* && !exwrote */) {
  443. X        TTputc('\n');
  444. X        /* exrefresh(); */
  445. X    }
  446. #endif
  447. X
  448. X    if (toline || fromline) {  /* assume it's an absolute motion */
  449. X                   /* we could probably do better */
  450. X        curwp->w_ldmkp = curwp->w_dotp;
  451. X        curwp->w_ldmko = curwp->w_doto;
  452. X    }
  453. X    if (toline) {
  454. X        curwp->w_dotp = toline;
  455. X        firstnonwhite();
  456. X        setmark();
  457. X    }
  458. X    if (fromline) {
  459. X        curwp->w_dotp = fromline;
  460. X        firstnonwhite();
  461. X        if (!toline)
  462. X            setmark();
  463. X    }
  464. X
  465. X    /* and then execute the command */
  466. X    isnamedcmd = TRUE;
  467. X    havemotion = &f_gomark;
  468. X    fulllineregions = TRUE;
  469. X
  470. X    s = execute(cfp,f,n);
  471. X
  472. X    havemotion = NULL;
  473. X    isnamedcmd = FALSE;
  474. X    fulllineregions = FALSE;
  475. X
  476. X    return s;
  477. }
  478. X
  479. /* parse an ex-style line spec -- code culled from elvis, file ex.c, by
  480. X    Steve Kirkendall
  481. */
  482. char *
  483. linespec(s, markptr)
  484. register char    *s;        /* start of the line specifier */
  485. LINE        **markptr;    /* where to store the mark's value */
  486. {
  487. X    long        num;
  488. X    LINE        *lp;    /* where the linespec takes us */
  489. X    register char    *t;
  490. X    int        status;
  491. X
  492. X    setmark();
  493. X    lp = NULL;
  494. X
  495. X    /* parse each ;-delimited clause of this linespec */
  496. X    do
  497. X    {
  498. X        /* skip an initial ';', if any */
  499. X        if (*s == ';')
  500. X            s++;
  501. X
  502. X        /* skip leading spaces */
  503. X        while (isspace(*s))
  504. X            s++;
  505. X    
  506. X        /* dot means current position */
  507. X        if (*s == '.') {
  508. X            s++;
  509. X            lp = curwp->w_dotp;
  510. X        } else if (*s == '$') { /* '$' means the last line */
  511. X            s++;
  512. X            status = gotoeob(TRUE,1);
  513. X            if (status) lp = curwp->w_dotp;
  514. X        } else if (isdigit(*s)) {
  515. X            /* digit means an absolute line number */
  516. X            for (num = 0; isdigit(*s); s++) {
  517. X                num = num * 10 + *s - '0';
  518. X            }
  519. X            status = gotoline(TRUE,num);
  520. X            if (status) lp = curwp->w_dotp;
  521. X        } else if (*s == '\'') {
  522. X            /* appostrophe means go to a set mark */
  523. X            s++;
  524. X            status = gonmmark(*s);
  525. X            if (status) lp = curwp->w_dotp;
  526. X            s++;
  527. X        } 
  528. #if PATTERNS
  529. X        else if (*s == '/' || *s == '?') { /* slash means do a search */
  530. X            /* put a '\0' at the end of the search pattern */
  531. X            t = parseptrn(s);
  532. X    
  533. X            /* search for the pattern */
  534. X            lp &= ~(BLKSIZE - 1);
  535. X            if (*s == '/') {
  536. X                pfetch(markline(lp));
  537. X                if (plen > 0)
  538. X                    lp += plen - 1;
  539. X                lp = m_fsrch(lp, s);
  540. X            } else {
  541. X                lp = m_bsrch(lp, s);
  542. X            }
  543. X    
  544. X            /* adjust command string pointer */
  545. X            s = t;
  546. X        }
  547. #endif
  548. X    
  549. X        /* if linespec was faulty, quit now */
  550. X        if (!lp) {
  551. X            *markptr = lp;
  552. X            swapmark();
  553. X            return s;
  554. X        }
  555. X    
  556. X        /* maybe add an offset */
  557. X        t = s;
  558. X        if (*t == '-' || *t == '+') {
  559. X            s++;
  560. X            for (num = 0; *s >= '0' && *s <= '9'; s++) {
  561. X                num = num * 10 + *s - '0';
  562. X            }
  563. X            if (num == 0)
  564. X                num = 1;
  565. X            forwline(TRUE, (*t == '+') ? num : -num);
  566. X            lp = curwp->w_dotp;
  567. X        }
  568. X    } while (*s == ';' || *s == '+' || *s == '-');
  569. X
  570. X    *markptr = lp;
  571. X    swapmark();
  572. X    return s;
  573. }
  574. X
  575. /* parse an ex-style line range -- code culled from elvis, file ex.c, by
  576. X    Steve Kirkendall
  577. */
  578. rangespec(specp,fromlinep,tolinep,isdefaultp,zerop)
  579. char        *specp;    /* string containing a line range */
  580. LINE        **fromlinep;    /* first linespec */
  581. LINE        **tolinep;    /* second linespec */
  582. int        *isdefaultp;
  583. int        *zerop;
  584. {
  585. X    register char    *scan;        /* used to scan thru specp */
  586. X    LINE        *fromline;    /* first linespec */
  587. X    LINE        *toline;    /* second linespec */
  588. X    int        noaddrallowed;
  589. X
  590. X    *zerop = FALSE;
  591. X
  592. X    /* ignore command lines that start with a double-quote */
  593. X    if (*specp == '"') {
  594. X        *fromlinep = *tolinep = curwp->w_dotp;
  595. X        return TRUE;
  596. X    }
  597. X
  598. X    /* permit extra colons at the start of the line */
  599. X    while (isspace(*specp) || *specp == ':') {
  600. X        specp++;
  601. X    }
  602. X
  603. X    /* parse the line specifier */
  604. X    scan = specp;
  605. X    if (lforw(curbp->b_linep) == curbp->b_linep) {
  606. X        fromline = toline = NULL;
  607. X    } else if (*scan == '%') {
  608. X        /* '%' means all lines */
  609. X        fromline = lforw(curbp->b_linep);
  610. X        toline = lback(curbp->b_linep);
  611. X        scan++;
  612. X    } else if (*scan == '0') {
  613. X        fromline = toline = curbp->b_linep; /* _very_ top of buffer */
  614. X        *zerop = TRUE;
  615. X        scan++;
  616. X    } else {
  617. X        scan = linespec(scan, &fromline);
  618. X        if (!fromline)
  619. X            fromline = curwp->w_dotp;
  620. X        toline = fromline;
  621. X        if (*scan == ',') {
  622. X            scan++;
  623. X            scan = linespec(scan, &toline);
  624. X        }
  625. X        if (!toline) {
  626. X            /* faulty line spec -- fault already described */
  627. X            dbgwrite("null toline");
  628. X            return FALSE;
  629. X        }
  630. X    }
  631. X
  632. X    *isdefaultp = (scan == specp);
  633. X
  634. X    /* skip whitespace */
  635. X    while (isspace(*scan))
  636. X        scan++;
  637. X
  638. X    if (*scan) {
  639. X        dbgwrite("crud at end %s",specp);
  640. X        return FALSE;
  641. X    }
  642. X
  643. X    *fromlinep = fromline;
  644. X    *tolinep = toline;
  645. X    
  646. X    return TRUE;
  647. }
  648. X
  649. /* old namedcmd:    execute a named command even if it is not bound */
  650. onamedcmd(f, n)
  651. int f, n;    /* command arguments [passed through to command executed] */
  652. {
  653. X    register char *fnp;    /* ptr to the name of the cmd to exec */
  654. X    char *kbd_engl();
  655. X    int s;
  656. X
  657. X    /* prompt the user to type a named command */
  658. X    mlwrite(": ");
  659. X
  660. X    /* and now get the function name to execute */
  661. #if    NeWS
  662. X    newsimmediateon() ;
  663. #endif
  664. X
  665. X    fnp = kbd_engl();
  666. X
  667. #if    NeWS
  668. X    newsimmediateoff() ;
  669. #endif
  670. X
  671. X    if (fnp == NULL) {
  672. X        mlwrite("[No such function]");
  673. X        return FALSE;
  674. X    }
  675. X
  676. X    /* and then execute the command */
  677. X    isnamedcmd = TRUE;
  678. X    s = docmd(fnp,FALSE,f,n);
  679. X    isnamedcmd = FALSE;
  680. X
  681. X    return s;
  682. }
  683. X
  684. #if NEVER
  685. /*    execcmd:    Execute a command line command by name alone */
  686. execcmd(f, n)
  687. int f, n;    /* default Flag and Numeric argument */
  688. {
  689. X    register int status;        /* status return */
  690. X    char cmdbuf[NSTRING];        /* string holding command to execute */
  691. X
  692. X    /* get the line wanted */
  693. X    cmdbuf[0] = 0;
  694. X    if ((status = mlreply("cmd: ", cmdbuf, NSTRING)) != TRUE)
  695. X        return status;
  696. X
  697. X    execlevel = 0;
  698. X    return docmd(cmdbuf,TRUE,f,n);
  699. }
  700. #endif
  701. X
  702. /*    docmd:    take a passed string as a command line and translate
  703. X        it to be executed as a command. This function will be
  704. X        used by execute-command-line and by all source and
  705. X        startup files.
  706. X
  707. X    format of the command line is:
  708. X
  709. X        {# arg} <command-name> {<argument string(s)>}
  710. X
  711. */
  712. X
  713. docmd(cline,newcle,f,n)
  714. char *cline;    /* command line to execute */
  715. {
  716. X    int status;        /* return status of function */
  717. X    int flags;        /* function flags */
  718. X    int oldcle;        /* old contents of clexec flag */
  719. X    char *oldestr;        /* original exec string */
  720. X    char tkn[NSTRING];    /* next token off of command line */
  721. X    CMDFUNC *cfp;
  722. X    extern CMDFUNC f_godotplus;
  723. X        
  724. X    /* if we are scanning and not executing..go back here */
  725. X    if (execlevel)
  726. X        return TRUE;
  727. X
  728. X    oldestr = execstr;    /* save last ptr to string to execute */
  729. X    execstr = cline;    /* and set this one as current */
  730. X
  731. X    /* first set up the default command values */
  732. X    if (newcle == TRUE) {
  733. X        f = FALSE;
  734. X        n = 1;
  735. X    }
  736. X
  737. X    if ((status = macarg(tkn)) != TRUE) {    /* and grab the first token */
  738. X        execstr = oldestr;
  739. X        return status;
  740. X    }
  741. X
  742. X    /* process leadin argument */
  743. X    if (toktyp(tkn) != TKCMD) {
  744. X        f = TRUE;
  745. X        strcpy(tkn, tokval(tkn));
  746. X        n = atoi(tkn);
  747. X
  748. X        /* and now get the command to execute */
  749. X        if ((status = macarg(tkn)) != TRUE) {
  750. X            execstr = oldestr;
  751. X            return status;    
  752. X        }    
  753. X    }
  754. X
  755. X    /* and match the token to see if it exists */
  756. X    if ((cfp = engl2fnc(tkn)) == NULL) {
  757. X        mlwrite("[No such function %s]",tkn);
  758. X        execstr = oldestr;
  759. X        return FALSE;
  760. X    }
  761. X    
  762. X    /* save the arguments and go execute the command */
  763. X    oldcle = clexec;        /* save old clexec flag */
  764. X    clexec = newcle;        /* in cline execution */
  765. X    status = execute(cfp,f,n);
  766. X    cmdstatus = status;        /* save the status */
  767. X    clexec = oldcle;        /* restore clexec flag */
  768. X    execstr = oldestr;
  769. X    return status;
  770. }
  771. X
  772. /* token:    chop a token off a string
  773. X        return a pointer past the token
  774. */
  775. X
  776. char *
  777. token(src, tok)
  778. char *src, *tok;    /* source string, destination token string */
  779. {
  780. X    register int quotef;    /* is the current string quoted? */
  781. X
  782. X    /* first scan past any whitespace in the source string */
  783. X    while (isspace(*src))
  784. X        ++src;
  785. X
  786. X    /* scan through the source string */
  787. X    quotef = FALSE;
  788. X    while (*src) {
  789. X        /* process special characters */
  790. X        if (*src == '\\') {
  791. X            ++src;
  792. X            if (*src == 0)
  793. X                break;
  794. X            switch (*src++) {
  795. X                case 'r':    *tok++ = '\r'; break;
  796. X                case 'n':    *tok++ = '\n'; break;
  797. X                case 't':    *tok++ = '\t';  break;
  798. X                case 'b':    *tok++ = '\b';  break;
  799. X                case 'f':    *tok++ = '\f'; break;
  800. X                default:    *tok++ = *(src-1);
  801. X            }
  802. X        } else {
  803. X            /* check for the end of the token */
  804. X            if (quotef) {
  805. X                if (*src == '"')
  806. X                    break;
  807. X            } else {
  808. X                if (*src == ' ' || *src == '\t')
  809. X                    break;
  810. X            }
  811. X
  812. X            /* set quote mode if qoute found */
  813. X            if (*src == '"')
  814. X                quotef = TRUE;
  815. X
  816. X            /* record the character */
  817. X            *tok++ = *src++;
  818. X        }
  819. X    }
  820. X
  821. X    /* terminate the token and exit */
  822. X    if (*src)
  823. X        ++src;
  824. X    *tok = 0;
  825. X    return src;
  826. }
  827. X
  828. macarg(tok)    /* get a macro line argument */
  829. char *tok;    /* buffer to place argument */
  830. {
  831. X    int savcle;    /* buffer to store original clexec */
  832. X
  833. X    savcle = clexec;    /* save execution mode */
  834. X    clexec = TRUE;        /* get the argument */
  835. X    /* grab token and advance past */
  836. X    execstr = token(execstr, tok);
  837. X    /* evaluate it */
  838. X    strcpy(tok, tokval(tok));
  839. X    clexec = savcle;    /* restore execution mode */
  840. X    return TRUE;
  841. }
  842. X
  843. /*    nextarg:    get the next argument    */
  844. X
  845. nextarg(buffer)
  846. char *buffer;        /* buffer to put token into */
  847. {
  848. X    /* grab token and advance past */
  849. X    execstr = token(execstr, buffer);
  850. X    /* evaluate it */
  851. X    strcpy(buffer, tokval(buffer));
  852. X    return TRUE;
  853. }
  854. X
  855. /*    storemac:    Set up a macro buffer and flag to store all
  856. X            executed command lines there            */
  857. X
  858. storemac(f, n)
  859. int f;        /* default flag */
  860. int n;        /* macro number to use */
  861. {
  862. X    register struct BUFFER *bp;    /* pointer to macro buffer */
  863. X    char bname[NBUFN];        /* name of buffer to use */
  864. X
  865. X    /* must have a numeric argument to this function */
  866. X    if (f == FALSE) {
  867. X        mlwrite("No macro specified");
  868. X        return FALSE;
  869. X    }
  870. X
  871. X    /* range check the macro number */
  872. X    if (n < 1 || n > 40) {
  873. X        mlwrite("[Macro number out of range]");
  874. X        return FALSE;
  875. X    }
  876. X
  877. X    /* construct the macro buffer name */
  878. X    strcpy(bname, "[Macro xx]");
  879. X    bname[7] = '0' + (n / 10);
  880. X    bname[8] = '0' + (n % 10);
  881. X
  882. X    /* set up the new macro buffer */
  883. X    if ((bp = bfind(bname, OK_CREAT, BFINVS)) == NULL) {
  884. X        mlwrite("[Cannot create macro]");
  885. X        return FALSE;
  886. X    }
  887. X
  888. X    /* and make sure it is empty */
  889. X    bclear(bp);
  890. X
  891. X    /* and set the macro store pointers to it */
  892. X    mstore = TRUE;
  893. X    bstore = bp;
  894. X    return TRUE;
  895. }
  896. X
  897. #if    PROC
  898. /*    storeproc:    Set up a procedure buffer and flag to store all
  899. X            executed command lines there            */
  900. X
  901. storeproc(f, n)
  902. int f;        /* default flag */
  903. int n;        /* macro number to use */
  904. {
  905. X    register struct BUFFER *bp;    /* pointer to macro buffer */
  906. X    register int status;        /* return status */
  907. X    char bname[NBUFN];        /* name of buffer to use */
  908. X
  909. X    /* a numeric argument means its a numbered macro */
  910. X    if (f == TRUE)
  911. X        return storemac(f, n);
  912. X
  913. X    /* get the name of the procedure */
  914. X    bname[1] = 0;
  915. X        if ((status = mlreply("Procedure name: ", &bname[1], NBUFN-2)) != TRUE)
  916. X                return status;
  917. X
  918. X    /* construct the macro buffer name */
  919. X    bname[0] = '[';
  920. X    strcat(bname, "]");
  921. X
  922. X    /* set up the new macro buffer */
  923. X    if ((bp = bfind(bname, OK_CREAT, BFINVS)) == NULL) {
  924. X        mlwrite("[Can not create macro]");
  925. X        return FALSE;
  926. X    }
  927. X
  928. X    /* and make sure it is empty */
  929. X    bclear(bp);
  930. X
  931. X    /* and set the macro store pointers to it */
  932. X    mstore = TRUE;
  933. X    bstore = bp;
  934. X    return TRUE;
  935. }
  936. X
  937. /*    execproc:    Execute a procedure                */
  938. X
  939. execproc(f, n)
  940. int f, n;    /* default flag and numeric arg */
  941. {
  942. X        register BUFFER *bp;        /* ptr to buffer to execute */
  943. X        register int status;        /* status return */
  944. X        static char obufn[NBUFN+2];        /* name of buffer to execute */
  945. X        char bufn[NBUFN+2];        /* name of buffer to execute */
  946. X
  947. X    /* find out what buffer the user wants to execute */
  948. X        if ((status = mlreply("Execute procedure: ", obufn, NBUFN)) != TRUE)
  949. X                return status;
  950. X
  951. X    /* construct the buffer name */
  952. X    bufn[0] = '[';
  953. X    strcat(bufn, obufn);
  954. X    strcat(bufn, "]");
  955. X
  956. X    /* find the pointer to that buffer */
  957. X        if ((bp=bfind(bufn, NO_CREAT, 0)) == NULL) {
  958. X        mlwrite("[No such procedure]");
  959. X                return FALSE;
  960. X        }
  961. X
  962. X    /* and now execute it as asked */
  963. X    while (n-- > 0) {
  964. X        if ((status = dobuf(bp)) != TRUE)
  965. X            return status;
  966. X    }
  967. X    return TRUE;
  968. }
  969. #endif
  970. X
  971. #if ! SMALLER
  972. /*    execbuf:    Execute the contents of a buffer of commands    */
  973. X
  974. execbuf(f, n)
  975. int f, n;    /* default flag and numeric arg */
  976. {
  977. X        register BUFFER *bp;        /* ptr to buffer to execute */
  978. X        register int status;        /* status return */
  979. X        static char bufn[NSTRING];        /* name of buffer to execute */
  980. X
  981. X    /* find out what buffer the user wants to execute */
  982. X        if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE)
  983. X                return status;
  984. X
  985. X    /* find the pointer to that buffer */
  986. X        if ((bp=bfind(bufn, NO_CREAT, 0)) == NULL) {
  987. X        mlwrite("No such buffer");
  988. X                return FALSE;
  989. X        }
  990. X
  991. X    /* and now execute it as asked */
  992. X    while (n-- > 0) {
  993. X        if ((status = dobuf(bp)) != TRUE)
  994. X            return status;
  995. X    }
  996. X    return TRUE;
  997. }
  998. #endif
  999. X
  1000. /*    dobuf:    execute the contents of the buffer pointed to
  1001. X        by the passed BP
  1002. X
  1003. X    Directives start with a "!" and include:
  1004. X
  1005. #if SMALLER
  1006. X    !endm        End a macro
  1007. #else
  1008. X    !endm        End a macro
  1009. X    !if (cond)    conditional execution
  1010. X    !else
  1011. X    !endif
  1012. X    !return        Return (terminating current macro)
  1013. X    !goto <label>    Jump to a label in the current macro
  1014. X    !force        Force macro to continue...even if command fails
  1015. X    !while (cond)    Execute a loop if the condition is true
  1016. X    !endwhile
  1017. X    
  1018. X    Line Labels begin with a "*" as the first nonblank char, like:
  1019. X
  1020. X    *LBL01
  1021. #endif
  1022. X
  1023. */
  1024. X
  1025. dobuf(bp)
  1026. BUFFER *bp;    /* buffer to execute */
  1027. {
  1028. X        register int status;    /* status return */
  1029. X    register LINE *lp;    /* pointer to line to execute */
  1030. X    register LINE *hlp;    /* pointer to line header */
  1031. X    LINE *mp;        /* Macro line storage temp */
  1032. X    int dirnum;        /* directive index */
  1033. X    int linlen;        /* length of line to execute */
  1034. X    int i;            /* index */
  1035. X    int force;        /* force TRUE result? */
  1036. X    WINDOW *wp;        /* ptr to windows to scan */
  1037. X    WHBLOCK *whlist;    /* ptr to !WHILE list */
  1038. X    char *einit;        /* initial value of eline */
  1039. X    char *eline;        /* text of line to execute */
  1040. #if ! SMALLER
  1041. X    WHBLOCK *scanner;    /* ptr during scan */
  1042. X    register LINE *glp;    /* line to goto */
  1043. X    WHBLOCK *whtemp;    /* temporary ptr to a WHBLOCK */
  1044. X    char tkn[NSTRING];    /* buffer to evaluate an expresion in */
  1045. #endif
  1046. X
  1047. #if    DEBUGM
  1048. X    char *sp;            /* temp for building debug string */
  1049. X    register char *ep;    /* ptr to end of outline */
  1050. #endif
  1051. X
  1052. X    /* clear IF level flags/while ptr */
  1053. X    execlevel = 0;
  1054. X    whlist = NULL;
  1055. X    fulllineregions = FALSE;
  1056. X    havemotion = FALSE;
  1057. X
  1058. #if ! SMALLER
  1059. X    scanner = NULL;
  1060. X    /* scan the buffer to execute, building WHILE header blocks */
  1061. X    hlp = bp->b_linep;
  1062. X    lp = hlp->l_fp;
  1063. X    while (lp != hlp) {
  1064. X        /* scan the current line */
  1065. X        eline = lp->l_text;
  1066. X        i = lp->l_used;
  1067. X
  1068. X        /* trim leading whitespace */
  1069. X        while (i-- > 0 && (*eline == ' ' || *eline == '\t'))
  1070. X            ++eline;
  1071. X
  1072. X        /* if theres nothing here, don't bother */
  1073. X        if (i <= 0)
  1074. X            goto nxtscan;
  1075. X
  1076. X        /* if is a while directive, make a block... */
  1077. X        if (eline[0] == '!' && eline[1] == 'w' && eline[2] == 'h') {
  1078. X            whtemp = (WHBLOCK *)malloc(sizeof(WHBLOCK));
  1079. X            if (whtemp == NULL) {
  1080. noram:                mlwrite("%%Out of memory during while scan");
  1081. failexit:            freewhile(scanner);
  1082. X                freewhile(whlist);
  1083. X                mstore = FALSE;
  1084. X                return FALSE;
  1085. X            }
  1086. X            whtemp->w_begin = lp;
  1087. X            whtemp->w_type = BTWHILE;
  1088. X            whtemp->w_next = scanner;
  1089. X            scanner = whtemp;
  1090. X        }
  1091. X
  1092. X        /* if is a BREAK directive, make a block... */
  1093. X        if (eline[0] == '!' && eline[1] == 'b' && eline[2] == 'r') {
  1094. X            if (scanner == NULL) {
  1095. X                mlwrite("%%!BREAK outside of any !WHILE loop");
  1096. X                goto failexit;
  1097. X            }
  1098. X            whtemp = (WHBLOCK *)malloc(sizeof(WHBLOCK));
  1099. X            if (whtemp == NULL)
  1100. X                goto noram;
  1101. X            whtemp->w_begin = lp;
  1102. X            whtemp->w_type = BTBREAK;
  1103. X            whtemp->w_next = scanner;
  1104. X            scanner = whtemp;
  1105. X        }
  1106. X
  1107. X        /* if it is an endwhile directive, record the spot... */
  1108. X        if (eline[0] == '!' && strncmp(&eline[1], "endw", 4) == 0) {
  1109. X            if (scanner == NULL) {
  1110. X                mlwrite("%%!ENDWHILE with no preceding !WHILE in '%s'",
  1111. X                    bp->b_bname);
  1112. X                goto failexit;
  1113. X            }
  1114. X            /* move top records from the scanner list to the
  1115. X               whlist until we have moved all BREAK records
  1116. X               and one WHILE record */
  1117. X            do {
  1118. X                scanner->w_end = lp;
  1119. X                whtemp = whlist;
  1120. X                whlist = scanner;
  1121. X                scanner = scanner->w_next;
  1122. X                whlist->w_next = whtemp;
  1123. X            } while (whlist->w_type == BTBREAK);
  1124. X        }
  1125. X
  1126. nxtscan:    /* on to the next line */
  1127. X        lp = lp->l_fp;
  1128. X    }
  1129. X
  1130. X    /* while and endwhile should match! */
  1131. X    if (scanner != NULL) {
  1132. X        mlwrite("%%!WHILE with no matching !ENDWHILE in '%s'",
  1133. X            bp->b_bname);
  1134. X        goto failexit;
  1135. X    }
  1136. #endif
  1137. X
  1138. X    /* starting at the beginning of the buffer */
  1139. X    hlp = bp->b_linep;
  1140. X    lp = hlp->l_fp;
  1141. X    while (lp != hlp) {
  1142. X        /* allocate eline and copy macro line to it */
  1143. X        linlen = lp->l_used;
  1144. X        if ((einit = eline = malloc(linlen+1)) == NULL) {
  1145. X            mlwrite("%%Out of Memory during macro execution");
  1146. X            freewhile(whlist);
  1147. X            mstore = FALSE;
  1148. X            return FALSE;
  1149. X        }
  1150. X        strncpy(eline, lp->l_text, linlen);
  1151. X        eline[linlen] = 0;    /* make sure it ends */
  1152. X
  1153. X        /* trim leading whitespace */
  1154. X        while (*eline == ' ' || *eline == '\t')
  1155. X            ++eline;
  1156. X
  1157. X        /* dump comments and blank lines */
  1158. X        if (*eline == ';' || *eline == 0)
  1159. X            goto onward;
  1160. X
  1161. #if    DEBUGM
  1162. X        /* if $debug == TRUE, every line to execute
  1163. X           gets echoed and a key needs to be pressed to continue
  1164. X           ^G will abort the command */
  1165. X    
  1166. X        if (macbug) {
  1167. X            strcpy(outline, "<<<");
  1168. X    
  1169. X            /* debug macro name */
  1170. X            strcat(outline, bp->b_bname);
  1171. X            strcat(outline, ":");
  1172. X    
  1173. X            /* debug if levels */
  1174. X            strcat(outline, itoa(execlevel));
  1175. X            strcat(outline, ":");
  1176. X
  1177. X            /* and lastly the line */
  1178. X            strcat(outline, eline);
  1179. X            strcat(outline, ">>>");
  1180. X    
  1181. X            /* change all '%' to ':' so mlwrite won't expect arguments */
  1182. X            sp = outline;
  1183. X            while (*sp)
  1184. X            if (*sp++ == '%') {
  1185. X                /* advance to the end */
  1186. X                ep = --sp;
  1187. X                while (*ep++)
  1188. X                    ;
  1189. X                /* null terminate the string one out */
  1190. X                *(ep + 1) = 0;
  1191. X                /* copy backwards */
  1192. X                while(ep-- > sp)
  1193. X                    *(ep + 1) = *ep;
  1194. X
  1195. X                /* and advance sp past the new % */
  1196. X                sp += 2;                    
  1197. X            }
  1198. X    
  1199. X            /* write out the debug line */
  1200. X            mlforce(outline);
  1201. X            update(TRUE);
  1202. X    
  1203. X            /* and get the keystroke */
  1204. X            if (kbd_key() == abortc) {
  1205. X                mlforce("[Macro aborted]");
  1206. X                freewhile(whlist);
  1207. X                mstore = FALSE;
  1208. X                return FALSE;
  1209. X            }
  1210. X        }
  1211. #endif
  1212. X
  1213. X        /* Parse directives here.... */
  1214. X        dirnum = -1;
  1215. X        if (*eline == '~') {
  1216. X            /* Find out which directive this is */
  1217. X            ++eline;
  1218. X            for (dirnum = 0; dirnum < NUMDIRS; dirnum++)
  1219. X                if (strncmp(eline, dname[dirnum],
  1220. X                            strlen(dname[dirnum])) == 0)
  1221. X                    break;
  1222. X
  1223. X            /* and bitch if it's illegal */
  1224. X            if (dirnum == NUMDIRS) {
  1225. X                mlwrite("%%Unknown Directive");
  1226. X                freewhile(whlist);
  1227. X                mstore = FALSE;
  1228. X                return FALSE;
  1229. X            }
  1230. X
  1231. X            /* service only the !ENDM macro here */
  1232. X            if (dirnum == DENDM) {
  1233. X                mstore = FALSE;
  1234. X                bstore = NULL;
  1235. X                goto onward;
  1236. X            }
  1237. X
  1238. X            /* restore the original eline....*/
  1239. X            --eline;
  1240. X        }
  1241. X
  1242. X        /* if macro store is on, just salt this away */
  1243. X        if (mstore) {
  1244. X            /* allocate the space for the line */
  1245. X            linlen = strlen(eline);
  1246. X            if ((mp=lalloc(linlen)) == NULL) {
  1247. X                mlwrite("%%Out of memory while storing macro");
  1248. X                mstore = FALSE;
  1249. X                return FALSE;
  1250. X            }
  1251. X    
  1252. X            /* copy the text into the new line */
  1253. X            for (i=0; i<linlen; ++i)
  1254. X                lputc(mp, i, eline[i]);
  1255. X    
  1256. X            /* attach the line to the end of the buffer */
  1257. X                   bstore->b_linep->l_bp->l_fp = mp;
  1258. X            mp->l_bp = bstore->b_linep->l_bp;
  1259. X            bstore->b_linep->l_bp = mp;
  1260. X            mp->l_fp = bstore->b_linep;
  1261. X            goto onward;
  1262. X        }
  1263. X    
  1264. X
  1265. X        force = FALSE;
  1266. X
  1267. X        /* dump comments */
  1268. X        if (*eline == '*')
  1269. X            goto onward;
  1270. X
  1271. #if ! SMALLER
  1272. X        /* now, execute directives */
  1273. X        if (dirnum != -1) {
  1274. X            /* skip past the directive */
  1275. X            while (*eline && *eline != ' ' && *eline != '\t')
  1276. X                ++eline;
  1277. X            execstr = eline;
  1278. X
  1279. X            switch (dirnum) {
  1280. X            case DIF:    /* IF directive */
  1281. X                /* grab the value of the logical exp */
  1282. X                if (execlevel == 0) {
  1283. X                    if (macarg(tkn) != TRUE)
  1284. X                        goto eexec;
  1285. X                    if (stol(tkn) == FALSE)
  1286. X                        ++execlevel;
  1287. X                } else
  1288. X                    ++execlevel;
  1289. X                goto onward;
  1290. X
  1291. X            case DWHILE:    /* WHILE directive */
  1292. X                /* grab the value of the logical exp */
  1293. X                if (execlevel == 0) {
  1294. X                    if (macarg(tkn) != TRUE)
  1295. X                        goto eexec;
  1296. X                    if (stol(tkn) == TRUE)
  1297. X                        goto onward;
  1298. X                }
  1299. X                /* drop down and act just like !BREAK */
  1300. X
  1301. X            case DBREAK:    /* BREAK directive */
  1302. X                if (dirnum == DBREAK && execlevel)
  1303. X                    goto onward;
  1304. X
  1305. X                /* jump down to the endwhile */
  1306. X                /* find the right while loop */
  1307. X                whtemp = whlist;
  1308. X                while (whtemp) {
  1309. X                    if (whtemp->w_begin == lp)
  1310. X                        break;
  1311. X                    whtemp = whtemp->w_next;
  1312. X                }
  1313. X            
  1314. X                if (whtemp == NULL) {
  1315. X                    mlwrite("%%Internal While loop error");
  1316. X                    freewhile(whlist);
  1317. X                    mstore = FALSE;
  1318. X                    return FALSE;
  1319. X                }
  1320. X            
  1321. X                /* reset the line pointer back.. */
  1322. X                lp = whtemp->w_end;
  1323. X                goto onward;
  1324. X
  1325. X            case DELSE:    /* ELSE directive */
  1326. X                if (execlevel == 1)
  1327. X                    --execlevel;
  1328. X                else if (execlevel == 0 )
  1329. X                    ++execlevel;
  1330. X                goto onward;
  1331. X
  1332. X            case DENDIF:    /* ENDIF directive */
  1333. X                if (execlevel)
  1334. X                    --execlevel;
  1335. X                goto onward;
  1336. X
  1337. X            case DGOTO:    /* GOTO directive */
  1338. X                /* .....only if we are currently executing */
  1339. X                if (execlevel == 0) {
  1340. X
  1341. X                    /* grab label to jump to */
  1342. X                    eline = token(eline, golabel);
  1343. X                    linlen = strlen(golabel);
  1344. X                    glp = hlp->l_fp;
  1345. X                    while (glp != hlp) {
  1346. X                        if (*glp->l_text == '*' &&
  1347. X                            (strncmp(&glp->l_text[1], golabel,
  1348. X                                    linlen) == 0)) {
  1349. X                            lp = glp;
  1350. X                            goto onward;
  1351. X                        }
  1352. X                        glp = glp->l_fp;
  1353. X                    }
  1354. X                    mlwrite("%%No such label");
  1355. X                    freewhile(whlist);
  1356. X                    mstore = FALSE;
  1357. X                    return FALSE;
  1358. X                }
  1359. X                goto onward;
  1360. X    
  1361. X            case DRETURN:    /* RETURN directive */
  1362. X                if (execlevel == 0)
  1363. X                    goto eexec;
  1364. X                goto onward;
  1365. X
  1366. X            case DENDWHILE:    /* ENDWHILE directive */
  1367. X                if (execlevel) {
  1368. X                    --execlevel;
  1369. X                    goto onward;
  1370. X                } else {
  1371. X                    /* find the right while loop */
  1372. X                    whtemp = whlist;
  1373. X                    while (whtemp) {
  1374. X                        if (whtemp->w_type == BTWHILE &&
  1375. X                            whtemp->w_end == lp)
  1376. X                            break;
  1377. X                        whtemp = whtemp->w_next;
  1378. X                    }
  1379. X        
  1380. X                    if (whtemp == NULL) {
  1381. X                        mlwrite("%%Internal While loop error");
  1382. X                        freewhile(whlist);
  1383. X                        mstore = FALSE;
  1384. X                        return FALSE;
  1385. X                    }
  1386. X        
  1387. X                    /* reset the line pointer back.. */
  1388. X                    lp = whtemp->w_begin->l_bp;
  1389. X                    goto onward;
  1390. X                }
  1391. X
  1392. X            case DFORCE:    /* FORCE directive */
  1393. X                force = TRUE;
  1394. X
  1395. X            }
  1396. X        }
  1397. #endif
  1398. X
  1399. X        /* execute the statement */
  1400. X        status = docmd(eline,TRUE,FALSE,1);
  1401. X        if (force)        /* force the status */
  1402. X            status = TRUE;
  1403. X
  1404. X        /* check for a command error */
  1405. X        if (status != TRUE) {
  1406. X            /* look if buffer is showing */
  1407. X            wp = wheadp;
  1408. X            while (wp != NULL) {
  1409. X                if (wp->w_bufp == bp) {
  1410. X                    /* and point it */
  1411. X                    wp->w_dotp = lp;
  1412. X                    wp->w_doto = 0;
  1413. X                    wp->w_flag |= WFHARD;
  1414. X                }
  1415. X                wp = wp->w_wndp;
  1416. X            }
  1417. X            /* in any case set the buffer . */
  1418. X            bp->b_dotp = lp;
  1419. X            bp->b_doto = 0;
  1420. X            free(einit);
  1421. X            execlevel = 0;
  1422. X            mstore = FALSE;
  1423. X            freewhile(whlist);
  1424. X            return status;
  1425. X        }
  1426. X
  1427. onward:        /* on to the next line */
  1428. X        free(einit);
  1429. X        lp = lp->l_fp;
  1430. X    }
  1431. X
  1432. #if ! SMALLER
  1433. eexec:    /* exit the current function */
  1434. #endif
  1435. X    mstore = FALSE;
  1436. X    execlevel = 0;
  1437. X    freewhile(whlist);
  1438. X        return TRUE;
  1439. }
  1440. X
  1441. freewhile(wp)    /* free a list of while block pointers */
  1442. WHBLOCK *wp;    /* head of structure to free */
  1443. {
  1444. X    if (wp == NULL)
  1445. X        return;
  1446. X    if (wp->w_next)
  1447. X        freewhile(wp->w_next);
  1448. X    free((char *)wp);
  1449. }
  1450. X
  1451. #if ! SMALLER
  1452. execfile(f, n)    /* execute a series of commands in a file */
  1453. int f, n;    /* default flag and numeric arg to pass on to file */
  1454. {
  1455. X    register int status;    /* return status of name query */
  1456. X    static char ofname[NSTRING];    /* name of file to execute */
  1457. X    char fname[NSTRING];    /* name of file to execute */
  1458. X    char *fspec;        /* full file spec */
  1459. X
  1460. X    if ((status = mlreply("File to execute: ", ofname, NSTRING -1)) != TRUE)
  1461. X        return status;
  1462. X    strcpy(fname,ofname);
  1463. X
  1464. #if    1
  1465. X    /* look up the path for the file */
  1466. X    fspec = flook(fname, FL_ANYWHERE);
  1467. X
  1468. X    /* if it isn't around */
  1469. X    if (fspec == NULL)
  1470. X        return FALSE;
  1471. X
  1472. #endif
  1473. X    /* otherwise, execute it */
  1474. X    while (n-- > 0)
  1475. X        if ((status=dofile(fspec)) != TRUE)
  1476. X            return status;
  1477. X
  1478. X    return TRUE;
  1479. }
  1480. #endif
  1481. X
  1482. /*    dofile:    yank a file into a buffer and execute it
  1483. X        if there are no errors, delete the buffer on exit */
  1484. X
  1485. dofile(fname)
  1486. char *fname;    /* file name to execute */
  1487. {
  1488. X    register BUFFER *bp;    /* buffer to place file to exeute */
  1489. X    register int status;    /* results of various calls */
  1490. X    register int odiscmd;
  1491. X    char bname[NBUFN];    /* name of buffer */
  1492. X
  1493. X    makename(bname, fname);        /* derive the name of the buffer */
  1494. X    if ((bp = bfind(bname, OK_CREAT, 0)) == NULL) /* get the needed buffer */
  1495. X        return FALSE;
  1496. X
  1497. X    bp->b_mode = MDVIEW;    /* mark the buffer as read only */
  1498. X    /* and try to read in the file to execute */
  1499. X    if ((status = readin(fname, FALSE, bp, TRUE)) != TRUE) {
  1500. X        return status;
  1501. X    }
  1502. X
  1503. X    /* go execute it! */
  1504. X    odiscmd = discmd;
  1505. X    discmd = FALSE;
  1506. X    status = dobuf(bp);
  1507. X    discmd = odiscmd;
  1508. X    if (status != TRUE)
  1509. X        return status;
  1510. X
  1511. X    /* if not displayed, remove the now unneeded buffer and exit */
  1512. X    if (bp->b_nwnd == 0)
  1513. X        zotbuf(bp);
  1514. X    return TRUE;
  1515. }
  1516. X
  1517. /*    cbuf:    Execute the contents of a numbered buffer    */
  1518. X
  1519. cbuf(f, n, bufnum)
  1520. int f, n;    /* default flag and numeric arg */
  1521. int bufnum;    /* number of buffer to execute */
  1522. {
  1523. X        register BUFFER *bp;        /* ptr to buffer to execute */
  1524. X        register int status;        /* status return */
  1525. X    static char bufname[] = "[Macro xx]";
  1526. X
  1527. X    /* make the buffer name */
  1528. X    bufname[7] = '0' + (bufnum / 10);
  1529. X    bufname[8] = '0' + (bufnum % 10);
  1530. X
  1531. X    /* find the pointer to that buffer */
  1532. X        if ((bp=bfind(bufname, NO_CREAT, 0)) == NULL) {
  1533. X            mlwrite("[Macro not defined]");
  1534. X                return FALSE;
  1535. X        }
  1536. X
  1537. X    /* and now execute it as asked */
  1538. X    while (n-- > 0)
  1539. X        if ((status = dobuf(bp)) != TRUE)
  1540. X            return status;
  1541. X    return TRUE;
  1542. }
  1543. X
  1544. cbuf1(f, n)
  1545. {
  1546. X    cbuf(f, n, 1);
  1547. }
  1548. X
  1549. cbuf2(f, n)
  1550. {
  1551. X    cbuf(f, n, 2);
  1552. }
  1553. X
  1554. cbuf3(f, n)
  1555. {
  1556. X    cbuf(f, n, 3);
  1557. }
  1558. X
  1559. cbuf4(f, n)
  1560. {
  1561. X    cbuf(f, n, 4);
  1562. }
  1563. X
  1564. cbuf5(f, n)
  1565. {
  1566. X    cbuf(f, n, 5);
  1567. }
  1568. X
  1569. cbuf6(f, n)
  1570. {
  1571. X    cbuf(f, n, 6);
  1572. }
  1573. X
  1574. cbuf7(f, n)
  1575. {
  1576. X    cbuf(f, n, 7);
  1577. }
  1578. X
  1579. cbuf8(f, n)
  1580. {
  1581. X    cbuf(f, n, 8);
  1582. }
  1583. X
  1584. cbuf9(f, n)
  1585. {
  1586. X    cbuf(f, n, 9);
  1587. }
  1588. X
  1589. cbuf10(f, n)
  1590. {
  1591. X    cbuf(f, n, 10);
  1592. }
  1593. X
  1594. cbuf11(f, n)
  1595. {
  1596. X    cbuf(f, n, 11);
  1597. }
  1598. X
  1599. cbuf12(f, n)
  1600. {
  1601. X    cbuf(f, n, 12);
  1602. }
  1603. X
  1604. cbuf13(f, n)
  1605. {
  1606. X    cbuf(f, n, 13);
  1607. }
  1608. X
  1609. cbuf14(f, n)
  1610. {
  1611. X    cbuf(f, n, 14);
  1612. }
  1613. X
  1614. cbuf15(f, n)
  1615. {
  1616. X    cbuf(f, n, 15);
  1617. }
  1618. X
  1619. cbuf16(f, n)
  1620. {
  1621. X    cbuf(f, n, 16);
  1622. }
  1623. X
  1624. cbuf17(f, n)
  1625. {
  1626. X    cbuf(f, n, 17);
  1627. }
  1628. X
  1629. cbuf18(f, n)
  1630. {
  1631. X    cbuf(f, n, 18);
  1632. }
  1633. X
  1634. cbuf19(f, n)
  1635. {
  1636. X    cbuf(f, n, 19);
  1637. }
  1638. X
  1639. cbuf20(f, n)
  1640. {
  1641. X    cbuf(f, n, 20);
  1642. }
  1643. X
  1644. cbuf21(f, n)
  1645. {
  1646. X    cbuf(f, n, 21);
  1647. }
  1648. X
  1649. cbuf22(f, n)
  1650. {
  1651. X    cbuf(f, n, 22);
  1652. }
  1653. X
  1654. cbuf23(f, n)
  1655. {
  1656. X    cbuf(f, n, 23);
  1657. }
  1658. X
  1659. cbuf24(f, n)
  1660. {
  1661. X    cbuf(f, n, 24);
  1662. }
  1663. X
  1664. cbuf25(f, n)
  1665. {
  1666. X    cbuf(f, n, 25);
  1667. }
  1668. X
  1669. cbuf26(f, n)
  1670. {
  1671. X    cbuf(f, n, 26);
  1672. }
  1673. X
  1674. cbuf27(f, n)
  1675. {
  1676. X    cbuf(f, n, 27);
  1677. }
  1678. X
  1679. cbuf28(f, n)
  1680. {
  1681. X    cbuf(f, n, 28);
  1682. }
  1683. X
  1684. cbuf29(f, n)
  1685. {
  1686. X    cbuf(f, n, 29);
  1687. }
  1688. X
  1689. cbuf30(f, n)
  1690. {
  1691. X    cbuf(f, n, 30);
  1692. }
  1693. X
  1694. cbuf31(f, n)
  1695. {
  1696. X    cbuf(f, n, 31);
  1697. }
  1698. X
  1699. cbuf32(f, n)
  1700. {
  1701. X    cbuf(f, n, 32);
  1702. }
  1703. X
  1704. cbuf33(f, n)
  1705. {
  1706. X    cbuf(f, n, 33);
  1707. }
  1708. X
  1709. cbuf34(f, n)
  1710. {
  1711. X    cbuf(f, n, 34);
  1712. }
  1713. X
  1714. cbuf35(f, n)
  1715. {
  1716. X    cbuf(f, n, 35);
  1717. }
  1718. X
  1719. cbuf36(f, n)
  1720. {
  1721. X    cbuf(f, n, 36);
  1722. }
  1723. X
  1724. cbuf37(f, n)
  1725. {
  1726. X    cbuf(f, n, 37);
  1727. }
  1728. X
  1729. cbuf38(f, n)
  1730. {
  1731. X    cbuf(f, n, 38);
  1732. }
  1733. X
  1734. cbuf39(f, n)
  1735. {
  1736. X    cbuf(f, n, 39);
  1737. }
  1738. X
  1739. cbuf40(f, n)
  1740. {
  1741. X    cbuf(f, n, 40);
  1742. }
  1743. X
  1744. X
  1745. SHAR_EOF
  1746. chmod 0444 exec.c ||
  1747. echo 'restore of exec.c failed'
  1748. Wc_c="`wc -c < 'exec.c'`"
  1749. test 32572 -eq "$Wc_c" ||
  1750.     echo 'exec.c: original size 32572, current size' "$Wc_c"
  1751. # ============= file.c ==============
  1752. echo 'x - extracting file.c (Text)'
  1753. sed 's/^X//' << 'SHAR_EOF' > 'file.c' &&
  1754. /*    FILE.C:   for MicroEMACS
  1755. X
  1756. X    The routines in this file handle the reading, writing
  1757. X    and lookup of disk files.  All of details about the
  1758. X    reading and writing of the disk are in "fileio.c".
  1759. X
  1760. */
  1761. X
  1762. #include        <stdio.h>
  1763. #include    "estruct.h"
  1764. #include        "edef.h"
  1765. X
  1766. char *strchr();
  1767. char *strrchr();
  1768. X
  1769. extern int fileispipe;
  1770. #if DOSFILES
  1771. extern int dosfile;
  1772. #endif
  1773. X
  1774. /*
  1775. X * Read a file into the current
  1776. X * buffer. This is really easy; all you do it
  1777. X * find the name of the file, and call the standard
  1778. X * "read a file into the current buffer" code.
  1779. X */
  1780. fileread(f, n)
  1781. {
  1782. X        register int    s;
  1783. X        static char fname[NFILEN];
  1784. X
  1785. X        if ((s=mlreply("Replace with file: ", fname, NFILEN)) != TRUE)
  1786. X                return s;
  1787. X    if ((s = glob(fname)) != TRUE)
  1788. X        return FALSE;
  1789. X    /* we want no errors or complaints, so mark it unchanged */
  1790. X    curbp->b_flag &= ~BFCHG;
  1791. X        return readin(fname, TRUE, curbp, TRUE);
  1792. }
  1793. X
  1794. /*
  1795. X * Select a file for editing.
  1796. X * Look around to see if you can find the
  1797. X * file in another buffer; if you can find it
  1798. X * just switch to the buffer. If you cannot find
  1799. X * the file, create a new buffer, read in the
  1800. X * text, and switch to the new buffer.
  1801. X * This is ": e"
  1802. X */
  1803. filefind(f, n)
  1804. {
  1805. X        static char fname[NFILEN];    /* file user wishes to find */
  1806. X    char nfname[NFILEN];
  1807. X    char rnfname[NFILEN];
  1808. X        register int s;        /* status return */
  1809. X    LINE *lp;
  1810. X
  1811. X    if (clexec || isnamedcmd) {
  1812. X            if ((s=mlreply("Find file: ", fname, NFILEN)) != TRUE)
  1813. X                    return s;
  1814. X        } else {
  1815. X        screen_string(fname,NFILEN,_path);
  1816. X        }
  1817. X    if ((s = glob(fname)) != TRUE)
  1818. X        return FALSE;
  1819. X    strcpy (nfname, fname);
  1820. #if TAGS
  1821. X    if (othmode & OTH_LAZY) {
  1822. X        extern BUFFER *filesbp;
  1823. X        lp = NULL;
  1824. X        while (flook(nfname, FL_HERE) == NULL) {
  1825. X            rvstrcpy(rnfname, fname);
  1826. X            if (makeflist() == FALSE || !sortsearch(rnfname, 
  1827. X                    strlen(rnfname), filesbp, FALSE, &lp)) {
  1828. X                /* give up, and try what they asked for */
  1829. X                strcpy (nfname, fname);
  1830. X                break;
  1831. X            }
  1832. X            rvstrncpy(nfname, lp->l_text, llength(lp));
  1833. X        }
  1834. X    }
  1835. #endif
  1836. X    return getfile(nfname, TRUE);
  1837. }
  1838. X
  1839. viewfile(f, n)    /* visit a file in VIEW mode */
  1840. {
  1841. X        char fname[NFILEN];    /* file user wishes to find */
  1842. X        register int s;        /* status return */
  1843. X
  1844. X    fname[0] = 0;
  1845. X        if ((s=mlreply("View file: ", fname, NFILEN)) != TRUE)
  1846. X                return s;
  1847. X    if ((s = glob(fname)) != TRUE)
  1848. X        return FALSE;
  1849. X    s = getfile(fname, FALSE);
  1850. X    if (s == TRUE) {    /* if we succeed, put it in view mode */
  1851. X        curwp->w_bufp->b_mode |= MDVIEW;
  1852. X        markWFMODE(curwp->w_bufp);
  1853. X    }
  1854. X    return s;
  1855. }
  1856. X
  1857. /*
  1858. X * Insert a file into the current
  1859. X * buffer. This is really easy; all you do it
  1860. X * find the name of the file, and call the standard
  1861. X * "insert a file into the current buffer" code.
  1862. X */
  1863. static char insfname[NFILEN];
  1864. X
  1865. insfile(f, n)
  1866. {
  1867. X        register int    s;
  1868. X
  1869. X    if (!calledbefore) {
  1870. X            if ((s=mlreply("Insert file: ", insfname, NFILEN)) != TRUE)
  1871. X                    return s;
  1872. X        if ((s = glob(insfname)) != TRUE)
  1873. X            return FALSE;
  1874. X    }
  1875. X    if (ukb == 0)
  1876. X            return ifile(insfname,TRUE,NULL);
  1877. X    else
  1878. X            return kifile(insfname);
  1879. }
  1880. X
  1881. #if BEFORE
  1882. insfiletop(f, n)
  1883. {
  1884. X        register int    s;
  1885. X        if ((s=mlreply("Insert file: ", insfname, NFILEN)) != TRUE)
  1886. X                return s;
  1887. X    if ((s = glob(insfname)) != TRUE)
  1888. X        return FALSE;
  1889. X    curwp->w_dotp = curbp->b_linep;
  1890. X        return ifile(insfname,TRUE,NULL);
  1891. }
  1892. #endif
  1893. X
  1894. getfile(fname, lockfl)
  1895. char fname[];        /* file name to find */
  1896. int lockfl;        /* check the file for locks? */
  1897. {
  1898. X        register BUFFER *bp;
  1899. X        register LINE   *lp;
  1900. X        register int    i;
  1901. X        register int    s;
  1902. X        char bname[NBUFN];    /* buffer name to put file */
  1903. X
  1904. #if    MSDOS
  1905. X    mklower(fname);        /* msdos isn't case sensitive */
  1906. #endif
  1907. X        if ((bp=bfind(fname, NO_CREAT, 0)) == NULL) {
  1908. X        /* it's not already here by that buffer name */
  1909. X            for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) {
  1910. X            /* is it here by that filename? */
  1911. X                    if (strcmp(bp->b_fname, fname)==0) {
  1912. X                swbuffer(bp);
  1913. X                            lp = curwp->w_dotp;
  1914. X                            i = curwp->w_ntrows/2;
  1915. X                            while (i-- && lback(lp)!=curbp->b_linep)
  1916. X                                    lp = lback(lp);
  1917. X                            curwp->w_linep = lp;
  1918. X                            curwp->w_flag |= WFMODE|WFHARD;
  1919. X                if (fname[0] != '!') {
  1920. X                                mlwrite("[Old buffer]");
  1921. X                } else {
  1922. X                                if (mlyesno(
  1923. X                                 "Old command output -- rerun")) {
  1924. X                            return readin(fname, lockfl, 
  1925. X                                curbp, TRUE);
  1926. X                    }
  1927. X                }
  1928. X                    
  1929. X                            return TRUE;
  1930. X                    }
  1931. X            }
  1932. X        /* it's not here */
  1933. X            makename(bname, fname);            /* New buffer name.     */
  1934. X        /* make sure the buffer name doesn't exist */
  1935. X            while ((bp=bfind(bname, NO_CREAT, 0)) != NULL) {
  1936. X            if ( !(bp->b_flag & BFCHG) && 
  1937. X                    lforw(bp->b_linep) == bp->b_linep ) {
  1938. X                /* empty and unmodiefied -- then its okay 
  1939. X                    to re-use this buffer */
  1940. X                bp->b_active = 0;
  1941. X                return readin(fname, lockfl, bp, TRUE) &&
  1942. X                        swbuffer(bp);;
  1943. X            }
  1944. X            /* old buffer name conflict code */
  1945. X            unqname(bname,TRUE);
  1946. X                    s = mlreply("Will use buffer name: ", bname, NBUFN);
  1947. X                    if (s == ABORT)
  1948. X                            return s;
  1949. X            if (s == FALSE || bname[0] == 0)
  1950. X                        makename(bname, fname);
  1951. X            }
  1952. X        /* okay, we've got a unique name -- create it */
  1953. X            if (bp==NULL && (bp=bfind(bname, OK_CREAT, 0))==NULL) {
  1954. X                    mlwrite("Cannot create buffer");
  1955. X                    return FALSE;
  1956. X            }
  1957. X        /* switch and read it in. */
  1958. X            strcpy(bp->b_fname, fname);
  1959. X    }
  1960. X    return swbuffer(bp);
  1961. }
  1962. X
  1963. /*
  1964. X    Read file "fname" into a buffer, blowing away any text
  1965. X    found there.  Returns the final status of the read.
  1966. */
  1967. X
  1968. readin(fname, lockfl, bp, mflg)
  1969. char    *fname;        /* name of file to read */
  1970. int    lockfl;        /* check for file locks? */
  1971. register BUFFER *bp;    /* read into this buffer */
  1972. int    mflg;        /* print messages? */
  1973. {
  1974. X        register WINDOW *wp;
  1975. X        register int    s;
  1976. X        register int    nline;
  1977. X        int    len;
  1978. X    char *errst;
  1979. X    int flag = 0;
  1980. #if UNIX
  1981. X        int    done_update = FALSE;
  1982. #endif
  1983. #if VMALLOC
  1984. X    extern int doverifys;
  1985. X    int odv;
  1986. #endif
  1987. X
  1988. #if    FILOCK
  1989. X    if (lockfl && lockchk(fname) == ABORT)
  1990. X        return ABORT;
  1991. #endif
  1992. #if    CRYPT
  1993. X    s = resetkey(bp);
  1994. X    if (s != TRUE)
  1995. X        return s;
  1996. #endif
  1997. X        if ((s=bclear(bp)) != TRUE)             /* Might be old.        */
  1998. X                return s;
  1999. X        bp->b_flag &= ~(BFINVS|BFCHG);
  2000. X        strcpy(bp->b_fname, fname);
  2001. X
  2002. X    /* turn off ALL keyboard translation in case we get a dos error */
  2003. X    TTkclose();
  2004. X
  2005. X        if ((s=ffropen(fname)) == FIOERR)       /* Hard file open.      */
  2006. X                goto out;
  2007. X
  2008. X        if (s == FIOFNF) {                      /* File not found.      */
  2009. X                if (mflg) mlwrite("[New file]");
  2010. X                goto out;
  2011. X        }
  2012. X
  2013. X        if (mflg) {
  2014. X         mlwrite("[Reading %s ]", fname);
  2015. X    }
  2016. X
  2017. #if UNIX & before
  2018. X    if (fileispipe)
  2019. X        ttclean(TRUE);
  2020. #endif
  2021. X    /* read the file in */
  2022. X        nline = 0;
  2023. #if VMALLOC
  2024. X    /* we really think this stuff is clean... */
  2025. X    odv = doverifys;
  2026. X    doverifys = 0;
  2027. #endif
  2028. X        while ((s = ffgetline(&len)) == FIOSUC) {
  2029. X        if (addline(bp,fline,len) != TRUE) {
  2030. X                        s = FIOMEM;             /* Keep message on the  */
  2031. X                        break;                  /* display.             */
  2032. X                } else {
  2033. #if UNIX
  2034. X                    /* reading from a pipe, and internal? */
  2035. X            if (fileispipe && !ffhasdata()) {
  2036. X                flag |= WFEDIT;
  2037. X                if (!done_update || bp->b_nwnd > 1)
  2038. X                    flag |= WFHARD;
  2039. X                    for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
  2040. X                            if (wp->w_bufp == bp) {
  2041. X                                    wp->w_linep=lforw(bp->b_linep);
  2042. X                                    wp->w_dotp =lback(bp->b_linep);
  2043. X                                    wp->w_doto = 0;
  2044. X                        wp->w_flag |= flag;
  2045. X                            }
  2046. X                    }
  2047. X                update(FALSE);
  2048. X                done_update = TRUE;
  2049. X                flag = 0;
  2050. X            } else {
  2051. X                flag |= WFHARD;
  2052. X            }
  2053. X            
  2054. X        }
  2055. #endif
  2056. X                ++nline;
  2057. X        }
  2058. #if VMALLOC
  2059. X    doverifys = odv;
  2060. #endif
  2061. X    bp->b_flag &= ~BFCHG;
  2062. #if UNIX & before
  2063. X    if (fileispipe == TRUE) {
  2064. X        ttunclean();
  2065. X            TTflush();
  2066. X            sgarbf = TRUE;
  2067. X    }
  2068. #endif
  2069. #if FINDERR
  2070. X    if (fileispipe == TRUE) {
  2071. X        strncpy(febuff,bp->b_bname,NBUFN);
  2072. X        newfebuff = TRUE;
  2073. X    }
  2074. #endif
  2075. X        ffclose();                              /* Ignore errors.       */
  2076. #if DOSFILES
  2077. X    if (dosfile && (gmode & MDDOS))
  2078. X        bp->b_mode |= MDDOS;
  2079. #endif
  2080. X    if (mflg)
  2081. X        readlinesmsg(nline,s,fname,ffronly(fname));
  2082. X
  2083. X    /* set read-only mode for read-only files */
  2084. X    if (fname[0] == '!' 
  2085. #if RONLYVIEW
  2086. X        || ffronly(fname) 
  2087. #endif
  2088. X    ) {
  2089. X        bp->b_mode |= MDVIEW;
  2090. X    }
  2091. X    
  2092. X    bp->b_active = TRUE;
  2093. X
  2094. X    /* set C mode for C files */
  2095. X    if (gmode & MDCMOD) {
  2096. X        char *cp;
  2097. X        cp = &fname[strlen(fname)-2];
  2098. X        if (cp >= fname && cp[0] == '.' && strchr("chCH",cp[1]) ) {
  2099. X            bp->b_mode |= MDCMOD;
  2100. X        }
  2101. X    }
  2102. X
  2103. out:
  2104. X    TTkopen();    /* open the keyboard again */
  2105. X        for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
  2106. X                if (wp->w_bufp == bp) {
  2107. X                        wp->w_linep = lforw(bp->b_linep);
  2108. X                        wp->w_dotp  = lforw(bp->b_linep);
  2109. X                        wp->w_doto  = 0;
  2110. X                        wp->w_mkp = NULL;
  2111. X                        wp->w_mko = 0;
  2112. X                        wp->w_ldmkp = NULL;
  2113. X                        wp->w_ldmko = 0;
  2114. X                        wp->w_flag |= WFMODE|WFHARD;
  2115. X                }
  2116. X        }
  2117. X        if (s == FIOERR || s == FIOFNF) {    /* False if error.      */
  2118. #if UNIX
  2119. X        extern int sys_nerr, errno;
  2120. X        extern char *sys_errlist[];
  2121. X        if (errno > 0 && errno < sys_nerr)
  2122. X            mlwrite("%s: %s",fname,sys_errlist[errno]);
  2123. #endif
  2124. X                return FALSE;
  2125. X    }
  2126. #if     NeWS
  2127. X        newsreportmodes() ;
  2128. #endif
  2129. X        return TRUE;
  2130. }
  2131. X
  2132. /* utility routine for no. of lines read */
  2133. readlinesmsg(n,s,f,rdonly)
  2134. {
  2135. X    mlwrite("[%sRead %d line%s from \"%s\"%s]",
  2136. X     (s==FIOERR ? "I/O ERROR, " : (s == FIOMEM ? "OUT OF MEMORY, ":"")),
  2137. X    n, n != 1 ? "s":"", f, rdonly ? "  (read-only)":"" );
  2138. }
  2139. X
  2140. /*
  2141. X * Take a file name, and from it
  2142. X * fabricate a buffer name. This routine knows
  2143. X * about the syntax of file names on the target system.
  2144. X * I suppose that this information could be put in
  2145. X * a better place than a line of code.
  2146. X */
  2147. X
  2148. makename(bname, fname)
  2149. char    bname[];
  2150. char    fname[];
  2151. {
  2152. X        register char *cp2;
  2153. X        register char *lastsl;
  2154. X
  2155. X        register char *fcp;
  2156. X        register char *bcp;
  2157. X
  2158. X    fcp = &fname[strlen(fname)];
  2159. X    /* trim trailing whitespace */
  2160. X    while (fcp != fname && (fcp[-1] == ' ' || fcp[-1] == '\t'
  2161. #if UNIX  /* trim trailing slashes as well */
  2162. X                     || fcp[-1] == '/'
  2163. #endif
  2164. X                            ) )
  2165. X                *(--fcp) = '\0';
  2166. X    fcp = fname;
  2167. X    /* trim leading whitespace */
  2168. X    while (*fcp == ' ' || *fcp == '\t')
  2169. X        fcp++;
  2170. X
  2171. #if     AMIGA
  2172. X        while (cp1!=fcp && cp1[-1]!=':' && cp1[-1]!='/')
  2173. X                --cp1;
  2174. #endif
  2175. #if     VMS
  2176. X        while (cp1!=fcp && cp1[-1]!=':' && cp1[-1]!=']')
  2177. X                --cp1;
  2178. #endif
  2179. #if     CPM
  2180. X        while (cp1!=fcp && cp1[-1]!=':')
  2181. X                --cp1;
  2182. #endif
  2183. #if     MSDOS
  2184. X        while (cp1!=fcp && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/')
  2185. X                --cp1;
  2186. #endif
  2187. #if     ST520
  2188. X        while (cp1!=fcp && cp1[-1]!=':' && cp1[-1]!='\\')
  2189. X                --cp1;
  2190. #endif
  2191. #if     UNIX
  2192. X    bcp = bname;
  2193. X    if (*fcp == '!') { /* then it's a shell command.  bname is first word */
  2194. X        *bcp++ = '!';
  2195. X        while (isspace(*++fcp))
  2196. X            ;
  2197. X        while (!isspace(*fcp) && bcp < &bname[NBUFN-1])
  2198. X            *bcp++ = *fcp++;
  2199. X        *bcp = '\0';
  2200. X        return;
  2201. X    }
  2202. X    if (lastsl = strrchr(fcp,'/')) {
  2203. X        strncpy(bcp,lastsl+1,NBUFN);
  2204. X        bcp[NBUFN-1] = '\0';
  2205. X    } else {  /* no slashes, use the filename as is */
  2206. X        strncpy(bcp,fcp,NBUFN);
  2207. X        bcp[NBUFN-1] = '\0';
  2208. X    }
  2209. X    return;
  2210. X
  2211. #else
  2212. X        cp2 = &bname[0];
  2213. X        while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';')
  2214. X                *cp2++ = *cp1++;
  2215. X        *cp2 = 0;
  2216. #endif
  2217. }
  2218. X
  2219. unqname(name,ok_to_ask)    /* make sure a buffer name is unique */
  2220. char *name;    /* name to check on */
  2221. {
  2222. X    register char *sp;
  2223. X
  2224. X    /* check to see if it is in the buffer list */
  2225. X    while (bfind(name, 0, NO_CREAT) != NULL) {
  2226. X
  2227. X        sp = &name[strlen(name)-1];  /* last char */
  2228. X        if (sp - name >= 2 && sp[-1] == '-') {
  2229. X            if (sp[0] == '9')
  2230. X                sp[0] = 'A';
  2231. X            else if (sp[0] == 'Z')
  2232. X                goto choosename;
  2233. X            else if (isdigit(sp[0]) || isupper(sp[0]))
  2234. X                sp[0] += 1;
  2235. X        } else if (sp + 2 < &name[NBUFN-1])  {
  2236. X            strcat(sp, "-1");
  2237. X        } else {
  2238. X        choosename:
  2239. X            if (ok_to_ask) {
  2240. X                do {
  2241. X                    mlreply("Choose a unique buffer name: ",
  2242. X                         name, NBUFN);
  2243. X                } while (name[0] == '\0');
  2244. X            } else { /* can't ask, just overwrite end of name */
  2245. X                sp[-1] = '-';
  2246. X                sp[0] = '1';
  2247. X            }
  2248. X        }
  2249. X    }
  2250. }
  2251. X
  2252. /*
  2253. X * Ask for a file name, and write the
  2254. X * contents of the current buffer to that file.
  2255. X */
  2256. filewrite(f, n)
  2257. {
  2258. X        register int    s;
  2259. X        static char            fname[NFILEN];
  2260. X
  2261. X    strncpy(fname, curbp->b_fname, NFILEN);
  2262. X    
  2263. X    /* HACK -- this implies knowledge of how kbd_engl works! */
  2264. X    if (isnamedcmd && lastkey != '\r') {
  2265. X            if ((s=mlreply("Write to file: ", fname, NFILEN)) != TRUE)
  2266. X                    return s;
  2267. X        if ((s = glob(fname)) != TRUE)
  2268. X            return FALSE;
  2269. X        if (strcmp(fname,curbp->b_fname) &&
  2270. X            fname[0] != '!' && flook(fname,FL_HERE)) {
  2271. X            if (mlyesno("File exists, okay to overwrite") != TRUE) {
  2272. X                mlwrite("File not written");
  2273. X                return FALSE;
  2274. X            }
  2275. X        }
  2276. X        }
  2277. X        if ((s=writeout(fname,curbp,TRUE)) == TRUE) {
  2278. X                curbp->b_flag &= ~BFCHG;
  2279. X        markWFMODE(curbp);
  2280. X        }
  2281. X        return s;
  2282. }
  2283. X
  2284. /*
  2285. X * Save the contents of the current
  2286. X * buffer in its associatd file. Do nothing
  2287. X * if nothing has changed (this may be a bug, not a
  2288. X * feature). Error if there is no remembered file
  2289. X * name for the buffer.
  2290. X */
  2291. filesave(f, n)
  2292. {
  2293. X        register int    s;
  2294. X
  2295. #if its_a_bug
  2296. X        if ((curbp->b_flag&BFCHG) == 0)         /* Return, no changes.  */
  2297. X                return TRUE;
  2298. #endif
  2299. X        if (curbp->b_fname[0] == 0) {           /* Must have a name.    */
  2300. X                mlwrite("No file name");
  2301. X                return FALSE;
  2302. X        }
  2303. X        if ((s=writeout(curbp->b_fname,curbp,TRUE)) == TRUE) {
  2304. X                curbp->b_flag &= ~BFCHG;
  2305. X        markWFMODE(curbp);
  2306. X        }
  2307. X        return s;
  2308. }
  2309. X
  2310. /*
  2311. X * This function performs the details of file
  2312. X * writing. Uses the file management routines in the
  2313. X * "fileio.c" package. The number of lines written is
  2314. X * displayed. Sadly, it looks inside a LINE; provide
  2315. X * a macro for this. Most of the grief is error
  2316. X * checking of some sort.
  2317. X */
  2318. writeout(fn,bp,msgf)
  2319. char    *fn;
  2320. BUFFER *bp;
  2321. {
  2322. X        register LINE   *lp;        /* current line */
  2323. X        register long   numchars;    /* # of chars in file */
  2324. X        REGION region;
  2325. X
  2326. X    /* starting at the beginning of the buffer */
  2327. X        lp = lforw(bp->b_linep);
  2328. X        region.r_linep = lp;
  2329. X        region.r_offset = 0;
  2330. X
  2331. X    /* start counting chars */
  2332. X        numchars = 0;
  2333. X        while (lp != bp->b_linep) {
  2334. X        numchars += llength(lp) + 1;
  2335. X        lp = lforw(lp);
  2336. X        }
  2337. X        region.r_size = numchars;
  2338. X        
  2339. #if DOSFILES
  2340. X    dosfile = bp->b_mode & MDDOS;
  2341. #endif
  2342. X
  2343. X    return writereg(®ion,fn,msgf);
  2344. }
  2345. X
  2346. writeregion(f,n)
  2347. {
  2348. X        REGION region;
  2349. X    int s;
  2350. X        static char fname[NFILEN];
  2351. SHAR_EOF
  2352. true || echo 'restore of file.c failed'
  2353. echo 'End of Vile part 6'
  2354. echo 'File file.c is continued in part 7'
  2355. echo 7 > _shar_seq_.tmp
  2356. exit 0
  2357. -- 
  2358.         paul fox, pgf@cayman.com, (617)494-1999
  2359.         Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139
  2360.