Annotation of 41BSD/cmd/ex/ex_addr.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.