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