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