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: }

Defined functions

getnum defined in line 77; used 5 times
setCNL defined in line 287; used 6 times
setNAEOL defined in line 294; used 2 times
setcount defined in line 54; used 4 times
setdot1 defined in line 37; used 4 times
setnoaddr defined in line 110; used 12 times

Defined variables

bigmove defined in line 20; used 5 times
Last modified: 1980-09-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 940
Valid CSS Valid XHTML 1.0 Strict