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