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
setdot
defined in line
34; used 14 times
setnoaddr
defined in line
119; used 16 times
- in line 311
- in /usr/src/ucb/ex/ex_cmds.c line
154,
161,
274,
292,
370,
391,
459,
486,
503,
562,
584,
646,
652,
661
- in /usr/src/ucb/ex/ex_set.c line
28
Defined variables
sccsid
defined in line
8;
never used