|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: #include "ex.h" ! 3: #include "ex_re.h" ! 4: ! 5: /* ! 6: * Routines for address parsing and assignment and checking of address bounds ! 7: * in command mode. The routine address is called from ex_cmds.c ! 8: * to parse each component of a command (terminated by , ; or the beginning ! 9: * of the command itself. It is also called by the scanning routine ! 10: * in ex_voperate.c from within open/visual. ! 11: * ! 12: * Other routines here manipulate the externals addr1 and addr2. ! 13: * These are the first and last lines for the current command. ! 14: * ! 15: * The variable bigmove remembers whether a non-local glitch of . was ! 16: * involved in an address expression, so we can set the previous context ! 17: * mark '' when such a motion occurs. ! 18: */ ! 19: ! 20: static bool bigmove; ! 21: ! 22: /* ! 23: * Set up addr1 and addr2 for commands whose default address is dot. ! 24: */ ! 25: setdot() ! 26: { ! 27: ! 28: setdot1(); ! 29: if (bigmove) ! 30: markDOT(); ! 31: } ! 32: ! 33: /* ! 34: * Call setdot1 to set up default addresses without ever ! 35: * setting the previous context mark. ! 36: */ ! 37: setdot1() ! 38: { ! 39: ! 40: if (addr2 == 0) ! 41: addr1 = addr2 = dot; ! 42: if (addr1 > addr2) { ! 43: notempty(); ! 44: error("Addr1 > addr2|First address exceeds second"); ! 45: } ! 46: } ! 47: ! 48: /* ! 49: * Ex allows you to say ! 50: * delete 5 ! 51: * to delete 5 lines, etc. ! 52: * Such nonsense is implemented by setcount. ! 53: */ ! 54: setcount() ! 55: { ! 56: register int cnt; ! 57: ! 58: pastwh(); ! 59: if (!isdigit(peekchar())) { ! 60: setdot(); ! 61: return; ! 62: } ! 63: addr1 = addr2; ! 64: setdot(); ! 65: cnt = getnum(); ! 66: if (cnt <= 0) ! 67: error("Bad count|Nonzero count required"); ! 68: addr2 += cnt - 1; ! 69: if (addr2 > dol) ! 70: addr2 = dol; ! 71: nonzero(); ! 72: } ! 73: ! 74: /* ! 75: * Parse a number out of the command input stream. ! 76: */ ! 77: getnum() ! 78: { ! 79: register int cnt; ! 80: ! 81: for (cnt = 0; isdigit(peekcd());) ! 82: cnt = cnt * 10 + getchar() - '0'; ! 83: return (cnt); ! 84: } ! 85: ! 86: /* ! 87: * Set the default addresses for commands which use the whole ! 88: * buffer as default, notably write. ! 89: */ ! 90: setall() ! 91: { ! 92: ! 93: if (addr2 == 0) { ! 94: addr1 = one; ! 95: addr2 = dol; ! 96: if (dol == zero) { ! 97: dot = zero; ! 98: return; ! 99: } ! 100: } ! 101: /* ! 102: * Don't want to set previous context mark so use setdot1(). ! 103: */ ! 104: setdot1(); ! 105: } ! 106: ! 107: /* ! 108: * No address allowed on, e.g. the file command. ! 109: */ ! 110: setnoaddr() ! 111: { ! 112: ! 113: if (addr2 != 0) ! 114: error("No address allowed@on this command"); ! 115: } ! 116: ! 117: /* ! 118: * Parse an address. ! 119: * Just about any sequence of address characters is legal. ! 120: * ! 121: * If you are tricky you can use this routine and the = command ! 122: * to do simple addition and subtraction of cardinals less ! 123: * than the number of lines in the file. ! 124: */ ! 125: line * ! 126: address(inline) ! 127: char *inline; ! 128: { ! 129: register line *addr; ! 130: register int offset, c; ! 131: short lastsign; ! 132: ! 133: bigmove = 0; ! 134: lastsign = 0; ! 135: offset = 0; ! 136: addr = 0; ! 137: for (;;) { ! 138: if (isdigit(peekcd())) { ! 139: if (addr == 0) { ! 140: addr = zero; ! 141: bigmove = 1; ! 142: } ! 143: loc1 = 0; ! 144: addr += offset; ! 145: offset = getnum(); ! 146: if (lastsign >= 0) ! 147: addr += offset; ! 148: else ! 149: addr -= offset; ! 150: lastsign = 0; ! 151: offset = 0; ! 152: } ! 153: switch (c = getcd()) { ! 154: ! 155: case '?': ! 156: case '/': ! 157: case '$': ! 158: case '\'': ! 159: case '\\': ! 160: bigmove++; ! 161: case '.': ! 162: if (addr || offset) ! 163: error("Badly formed address"); ! 164: } ! 165: offset += lastsign; ! 166: lastsign = 0; ! 167: switch (c) { ! 168: ! 169: case ' ': ! 170: case '\t': ! 171: continue; ! 172: ! 173: case '+': ! 174: lastsign = 1; ! 175: if (addr == 0) ! 176: addr = dot; ! 177: continue; ! 178: ! 179: case '^': ! 180: case '-': ! 181: lastsign = -1; ! 182: if (addr == 0) ! 183: addr = dot; ! 184: continue; ! 185: ! 186: case '\\': ! 187: case '?': ! 188: case '/': ! 189: c = compile(c, 1); ! 190: notempty(); ! 191: savere(scanre); ! 192: addr = dot; ! 193: if (inline && execute(0, dot)) { ! 194: if (c == '/') { ! 195: while (loc1 <= inline) ! 196: if (!execute(1)) ! 197: goto nope; ! 198: break; ! 199: } else if (loc1 < inline) { ! 200: char *last; ! 201: doques: ! 202: ! 203: do { ! 204: last = loc1; ! 205: if (!execute(1)) ! 206: break; ! 207: } while (loc1 < inline); ! 208: loc1 = last; ! 209: break; ! 210: } ! 211: } ! 212: nope: ! 213: for (;;) { ! 214: if (c == '/') { ! 215: addr++; ! 216: if (addr > dol) { ! 217: if (value(WRAPSCAN) == 0) ! 218: error("No match to BOTTOM|Address search hit BOTTOM without matching pattern"); ! 219: addr = zero; ! 220: } ! 221: } else { ! 222: addr--; ! 223: if (addr < zero) { ! 224: if (value(WRAPSCAN) == 0) ! 225: error("No match to TOP|Address search hit TOP without matching pattern"); ! 226: addr = dol; ! 227: } ! 228: } ! 229: if (execute(0, addr)) { ! 230: if (inline && c == '?') { ! 231: inline = &linebuf[LBSIZE]; ! 232: goto doques; ! 233: } ! 234: break; ! 235: } ! 236: if (addr == dot) ! 237: error("Fail|Pattern not found"); ! 238: } ! 239: continue; ! 240: ! 241: case '$': ! 242: addr = dol; ! 243: continue; ! 244: ! 245: case '.': ! 246: addr = dot; ! 247: continue; ! 248: ! 249: case '\'': ! 250: c = markreg(getchar()); ! 251: if (c == 0) ! 252: error("Marks are ' and a-z"); ! 253: addr = getmark(c); ! 254: if (addr == 0) ! 255: error("Undefined mark@referenced"); ! 256: break; ! 257: ! 258: default: ! 259: ungetchar(c); ! 260: if (offset) { ! 261: if (addr == 0) ! 262: addr = dot; ! 263: addr += offset; ! 264: loc1 = 0; ! 265: } ! 266: if (addr == 0) { ! 267: bigmove = 0; ! 268: return (0); ! 269: } ! 270: if (addr != zero) ! 271: notempty(); ! 272: addr += lastsign; ! 273: if (addr < zero) ! 274: error("Negative address@- first buffer line is 1"); ! 275: if (addr > dol) ! 276: error("Not that many lines@in buffer"); ! 277: return (addr); ! 278: } ! 279: } ! 280: } ! 281: ! 282: /* ! 283: * Abbreviations to make code smaller ! 284: * Left over from squashing ex version 1.1 into ! 285: * 11/34's and 11/40's. ! 286: */ ! 287: setCNL() ! 288: { ! 289: ! 290: setcount(); ! 291: newline(); ! 292: } ! 293: ! 294: setNAEOL() ! 295: { ! 296: ! 297: setnoaddr(); ! 298: eol(); ! 299: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.