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

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

unix.superglobalmegacorp.com

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