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

Defined functions

getnum defined in line 86; used 5 times
setCNL defined in line 301; used 6 times
setNAEOL defined in line 308; used 2 times
setall defined in line 99; used 5 times
setcount defined in line 63; used 4 times
setdot defined in line 34; used 14 times
setdot1 defined in line 46; used 4 times
setnoaddr defined in line 119; used 16 times

Defined variables

bigmove defined in line 29; used 5 times
sccsid defined in line 8; never used
Last modified: 1985-06-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1482
Valid CSS Valid XHTML 1.0 Strict