|
|
1.1 ! root 1: /* Copyright (c) 1981 Regents of the University of California */ ! 2: static char *sccsid = "@(#)ex_cmds2.c 7.1 7/8/81"; ! 3: #include "ex.h" ! 4: #include "ex_argv.h" ! 5: #include "ex_temp.h" ! 6: #include "ex_tty.h" ! 7: #include "ex_vis.h" ! 8: ! 9: extern bool pflag, nflag; /* mjm: extern; also in ex_cmds.c */ ! 10: extern int poffset; /* mjm: extern; also in ex_cmds.c */ ! 11: ! 12: /* ! 13: * Subroutines for major command loop. ! 14: */ ! 15: ! 16: /* ! 17: * Is there a single letter indicating a named buffer next? ! 18: */ ! 19: cmdreg() ! 20: { ! 21: register int c = 0; ! 22: register int wh = skipwh(); ! 23: ! 24: if (wh && isalpha(peekchar())) ! 25: c = getchar(); ! 26: return (c); ! 27: } ! 28: ! 29: /* ! 30: * Tell whether the character ends a command ! 31: */ ! 32: endcmd(ch) ! 33: int ch; ! 34: { ! 35: switch (ch) { ! 36: ! 37: case '\n': ! 38: case EOF: ! 39: endline = 1; ! 40: return (1); ! 41: ! 42: case '|': ! 43: case '"': ! 44: endline = 0; ! 45: return (1); ! 46: } ! 47: return (0); ! 48: } ! 49: ! 50: /* ! 51: * Insist on the end of the command. ! 52: */ ! 53: eol() ! 54: { ! 55: ! 56: if (!skipend()) ! 57: error("Extra chars|Extra characters at end of command"); ! 58: ignnEOF(); ! 59: } ! 60: ! 61: /* ! 62: * Print out the message in the error message file at str, ! 63: * with i an integer argument to printf. ! 64: */ ! 65: /*VARARGS2*/ ! 66: error(str, i) ! 67: #ifdef lint ! 68: register char *str; ! 69: #else ! 70: register int str; ! 71: #endif ! 72: int i; ! 73: { ! 74: ! 75: error0(); ! 76: merror(str, i); ! 77: if (writing) { ! 78: serror(" [Warning - %s is incomplete]", file); ! 79: writing = 0; ! 80: } ! 81: error1(str); ! 82: } ! 83: ! 84: /* ! 85: * Rewind the argument list. ! 86: */ ! 87: erewind() ! 88: { ! 89: ! 90: argc = argc0; ! 91: argv = argv0; ! 92: args = args0; ! 93: if (argc > 1 && !hush) { ! 94: printf(mesg("%d files@to edit"), argc); ! 95: if (inopen) ! 96: putchar(' '); ! 97: else ! 98: putNFL(); ! 99: } ! 100: } ! 101: ! 102: /* ! 103: * Guts of the pre-printing error processing. ! 104: * If in visual and catching errors, then we dont mung up the internals, ! 105: * just fixing up the echo area for the print. ! 106: * Otherwise we reset a number of externals, and discard unused input. ! 107: */ ! 108: error0() ! 109: { ! 110: ! 111: if (laste) { ! 112: #ifdef VMUNIX ! 113: tlaste(); ! 114: #endif ! 115: laste = 0; ! 116: sync(); ! 117: } ! 118: if (vcatch) { ! 119: if (splitw == 0) ! 120: fixech(); ! 121: if (!SO || !SE) ! 122: dingdong(); ! 123: return; ! 124: } ! 125: if (input) { ! 126: input = strend(input) - 1; ! 127: if (*input == '\n') ! 128: setlastchar('\n'); ! 129: input = 0; ! 130: } ! 131: setoutt(); ! 132: flush(); ! 133: resetflav(); ! 134: if (!SO || !SE) ! 135: dingdong(); ! 136: if (inopen) { ! 137: /* ! 138: * We are coming out of open/visual ungracefully. ! 139: * Restore COLUMNS, undo, and fix tty mode. ! 140: */ ! 141: COLUMNS = OCOLUMNS; ! 142: undvis(); ! 143: ostop(normf); ! 144: /* ostop should be doing this ! 145: putpad(VE); ! 146: putpad(KE); ! 147: */ ! 148: putnl(); ! 149: } ! 150: inopen = 0; ! 151: holdcm = 0; ! 152: } ! 153: ! 154: /* ! 155: * Post error printing processing. ! 156: * Close the i/o file if left open. ! 157: * If catching in visual then throw to the visual catch, ! 158: * else if a child after a fork, then exit. ! 159: * Otherwise, in the normal command mode error case, ! 160: * finish state reset, and throw to top. ! 161: */ ! 162: error1(str) ! 163: char *str; ! 164: { ! 165: bool die; ! 166: ! 167: if (io > 0) { ! 168: close(io); ! 169: io = -1; ! 170: } ! 171: die = (getpid() != ppid); /* Only children die */ ! 172: inappend = inglobal = 0; ! 173: globp = vglobp = vmacp = 0; ! 174: if (vcatch && !die) { ! 175: inopen = 1; ! 176: vcatch = 0; ! 177: if (str) ! 178: noonl(); ! 179: fixol(); ! 180: longjmp(vreslab,1); ! 181: } ! 182: if (str && !vcatch) ! 183: putNFL(); ! 184: if (die) ! 185: exit(1); ! 186: lseek(0, 0L, 2); ! 187: if (inglobal) ! 188: setlastchar('\n'); ! 189: while (lastchar() != '\n' && lastchar() != EOF) ! 190: ignchar(); ! 191: ungetchar(0); ! 192: endline = 1; ! 193: reset(); ! 194: } ! 195: ! 196: fixol() ! 197: { ! 198: if (Outchar != vputchar) { ! 199: flush(); ! 200: if (state == ONEOPEN || state == HARDOPEN) ! 201: outline = destline = 0; ! 202: Outchar = vputchar; ! 203: vcontin(1); ! 204: } else { ! 205: if (destcol) ! 206: vclreol(); ! 207: vclean(); ! 208: } ! 209: } ! 210: ! 211: /* ! 212: * Does an ! character follow in the command stream? ! 213: */ ! 214: exclam() ! 215: { ! 216: ! 217: if (peekchar() == '!') { ! 218: ignchar(); ! 219: return (1); ! 220: } ! 221: return (0); ! 222: } ! 223: ! 224: /* ! 225: * Make an argument list for e.g. next. ! 226: */ ! 227: makargs() ! 228: { ! 229: ! 230: glob(&frob); ! 231: argc0 = frob.argc0; ! 232: argv0 = frob.argv; ! 233: args0 = argv0[0]; ! 234: erewind(); ! 235: } ! 236: ! 237: /* ! 238: * Advance to next file in argument list. ! 239: */ ! 240: next() ! 241: { ! 242: extern short isalt; /* defined in ex_io.c */ ! 243: ! 244: if (argc == 0) ! 245: error("No more files@to edit"); ! 246: morargc = argc; ! 247: isalt = (strcmp(altfile, args)==0) + 1; ! 248: if (savedfile[0]) ! 249: CP(altfile, savedfile); ! 250: CP(savedfile, args); ! 251: argc--; ! 252: args = argv ? *++argv : strend(args) + 1; ! 253: } ! 254: ! 255: /* ! 256: * Eat trailing flags and offsets after a command, ! 257: * saving for possible later post-command prints. ! 258: */ ! 259: newline() ! 260: { ! 261: register int c; ! 262: ! 263: resetflav(); ! 264: for (;;) { ! 265: c = getchar(); ! 266: switch (c) { ! 267: ! 268: case '^': ! 269: case '-': ! 270: poffset--; ! 271: break; ! 272: ! 273: case '+': ! 274: poffset++; ! 275: break; ! 276: ! 277: case 'l': ! 278: listf++; ! 279: break; ! 280: ! 281: case '#': ! 282: nflag++; ! 283: break; ! 284: ! 285: case 'p': ! 286: listf = 0; ! 287: break; ! 288: ! 289: case ' ': ! 290: case '\t': ! 291: continue; ! 292: ! 293: case '"': ! 294: comment(); ! 295: setflav(); ! 296: return; ! 297: ! 298: default: ! 299: if (!endcmd(c)) ! 300: serror("Extra chars|Extra characters at end of \"%s\" command", Command); ! 301: if (c == EOF) ! 302: ungetchar(c); ! 303: setflav(); ! 304: return; ! 305: } ! 306: pflag++; ! 307: } ! 308: } ! 309: ! 310: /* ! 311: * Before quit or respec of arg list, check that there are ! 312: * no more files in the arg list. ! 313: */ ! 314: nomore() ! 315: { ! 316: ! 317: if (argc == 0 || morargc == argc) ! 318: return; ! 319: morargc = argc; ! 320: merror("%d more file", argc); ! 321: serror("%s@to edit", plural((long) argc)); ! 322: } ! 323: ! 324: /* ! 325: * Before edit of new file check that either an ! follows ! 326: * or the file has not been changed. ! 327: */ ! 328: quickly() ! 329: { ! 330: ! 331: if (exclam()) ! 332: return (1); ! 333: if (chng && dol > zero) { ! 334: /* ! 335: chng = 0; ! 336: */ ! 337: xchng = 0; ! 338: error("No write@since last change (:%s! overrides)", Command); ! 339: } ! 340: return (0); ! 341: } ! 342: ! 343: /* ! 344: * Reset the flavor of the output to print mode with no numbering. ! 345: */ ! 346: resetflav() ! 347: { ! 348: ! 349: if (inopen) ! 350: return; ! 351: listf = 0; ! 352: nflag = 0; ! 353: pflag = 0; ! 354: poffset = 0; ! 355: setflav(); ! 356: } ! 357: ! 358: /* ! 359: * Print an error message with a %s type argument to printf. ! 360: * Message text comes from error message file. ! 361: */ ! 362: serror(str, cp) ! 363: #ifdef lint ! 364: register char *str; ! 365: #else ! 366: register int str; ! 367: #endif ! 368: char *cp; ! 369: { ! 370: ! 371: error0(); ! 372: smerror(str, cp); ! 373: error1(str); ! 374: } ! 375: ! 376: /* ! 377: * Set the flavor of the output based on the flags given ! 378: * and the number and list options to either number or not number lines ! 379: * and either use normally decoded (ARPAnet standard) characters or list mode, ! 380: * where end of lines are marked and tabs print as ^I. ! 381: */ ! 382: setflav() ! 383: { ! 384: ! 385: if (inopen) ! 386: return; ! 387: setnumb(nflag || value(NUMBER)); ! 388: setlist(listf || value(LIST)); ! 389: setoutt(); ! 390: } ! 391: ! 392: /* ! 393: * Skip white space and tell whether command ends then. ! 394: */ ! 395: skipend() ! 396: { ! 397: ! 398: pastwh(); ! 399: return (endcmd(peekchar()) && peekchar() != '"'); ! 400: } ! 401: ! 402: /* ! 403: * Set the command name for non-word commands. ! 404: */ ! 405: tailspec(c) ! 406: int c; ! 407: { ! 408: static char foocmd[2]; ! 409: ! 410: foocmd[0] = c; ! 411: Command = foocmd; ! 412: } ! 413: ! 414: /* ! 415: * Try to read off the rest of the command word. ! 416: * If alphabetics follow, then this is not the command we seek. ! 417: */ ! 418: tail(comm) ! 419: char *comm; ! 420: { ! 421: ! 422: tailprim(comm, 1, 0); ! 423: } ! 424: ! 425: tail2of(comm) ! 426: char *comm; ! 427: { ! 428: ! 429: tailprim(comm, 2, 0); ! 430: } ! 431: ! 432: char tcommand[20]; ! 433: ! 434: tailprim(comm, i, notinvis) ! 435: register char *comm; ! 436: int i; ! 437: bool notinvis; ! 438: { ! 439: register char *cp; ! 440: register int c; ! 441: ! 442: Command = comm; ! 443: for (cp = tcommand; i > 0; i--) ! 444: *cp++ = *comm++; ! 445: while (*comm && peekchar() == *comm) ! 446: *cp++ = getchar(), comm++; ! 447: c = peekchar(); ! 448: if (notinvis || isalpha(c)) { ! 449: /* ! 450: * Of the trailing lp funny business, only dl and dp ! 451: * survive the move from ed to ex. ! 452: */ ! 453: if (tcommand[0] == 'd' && any(c, "lp")) ! 454: goto ret; ! 455: if (tcommand[0] == 's' && any(c, "gcr")) ! 456: goto ret; ! 457: while (cp < &tcommand[19] && isalpha(peekchar())) ! 458: *cp++ = getchar(); ! 459: *cp = 0; ! 460: if (notinvis) ! 461: serror("What?|%s: No such command from open/visual", tcommand); ! 462: else ! 463: serror("What?|%s: Not an editor command", tcommand); ! 464: } ! 465: ret: ! 466: *cp = 0; ! 467: } ! 468: ! 469: /* ! 470: * Continue after a : command from open/visual. ! 471: */ ! 472: vcontin(ask) ! 473: bool ask; ! 474: { ! 475: ! 476: if (vcnt > 0) ! 477: vcnt = -vcnt; ! 478: if (inopen) { ! 479: if (state != VISUAL) { ! 480: /* ! 481: * We don't know what a shell command may have left on ! 482: * the screen, so we move the cursor to the right place ! 483: * and then put out a newline. But this makes an extra ! 484: * blank line most of the time so we only do it for :sh ! 485: * since the prompt gets left on the screen. ! 486: * ! 487: * BUG: :!echo longer than current line \\c ! 488: * will screw it up, but be reasonable! ! 489: */ ! 490: if (state == CRTOPEN) { ! 491: termreset(); ! 492: vgoto(WECHO, 0); ! 493: } ! 494: if (!ask) { ! 495: putch('\r'); ! 496: putch('\n'); ! 497: } ! 498: return; ! 499: } ! 500: if (ask) { ! 501: merror("[Hit return to continue] "); ! 502: flush(); ! 503: } ! 504: #ifndef CBREAK ! 505: vraw(); ! 506: #endif ! 507: if (ask) { ! 508: #ifdef EATQS ! 509: /* ! 510: * Gobble ^Q/^S since the tty driver should be eating ! 511: * them (as far as the user can see) ! 512: */ ! 513: while (peekkey() == CTRL(Q) || peekkey() == CTRL(S)) ! 514: ignore(getkey()); ! 515: #endif ! 516: if(getkey() == ':') { ! 517: /* Ugh. Extra newlines, but no other way */ ! 518: putch('\n'); ! 519: outline = WECHO; ! 520: ungetkey(':'); ! 521: } ! 522: } ! 523: vclrech(1); ! 524: if (Peekkey != ':') { ! 525: putpad(TI); ! 526: tostart(); ! 527: /* replaced by ostart. ! 528: putpad(VS); ! 529: putpad(KS); ! 530: */ ! 531: } ! 532: } ! 533: } ! 534: ! 535: /* ! 536: * Put out a newline (before a shell escape) ! 537: * if in open/visual. ! 538: */ ! 539: vnfl() ! 540: { ! 541: ! 542: if (inopen) { ! 543: if (state != VISUAL && state != CRTOPEN && destline <= WECHO) ! 544: vclean(); ! 545: else ! 546: vmoveitup(1, 0); ! 547: vgoto(WECHO, 0); ! 548: vclrbyte(vtube[WECHO], WCOLS); ! 549: tostop(); ! 550: /* replaced by the ostop above ! 551: putpad(VE); ! 552: putpad(KE); ! 553: */ ! 554: } ! 555: flush(); ! 556: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.