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