1: /* Copyright (c) 1981 Regents of the University of California */
2: static char *sccsid = "@(#)ex_addr.c 7.1 7/8/81";
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: }
Defined functions
setdot
defined in line
26; used 14 times
setnoaddr
defined in line
111; used 16 times
- in line 303
- in /usr/src/ucb/ex/ex3/ex_cmds.c line
146,
153,
266,
279,
357,
378,
446,
473,
490,
545,
567,
629,
635,
644
- in /usr/src/ucb/ex/ex3/ex_set.c line
20
Defined variables
sccsid
defined in line
2;
never used