Subversion Repositories planix.SVN

Rev

Rev 108 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
105 7u83 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
#if	!defined(lint) && defined(DOSCCS)
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
 */
108 7u83 63
void
105 7u83 64
setcount()
65
{
66
	register int cnt;
67
 
68
	pastwh();
69
	if (!isdigit(peekchar())) {
70
		setdot();
71
		return;
72
	}
73
	addr1 = addr2;
74
	setdot();
75
	cnt = getnum();
76
	if (cnt <= 0)
77
		error("Bad count|Nonzero count required");
78
	addr2 += cnt - 1;
79
	if (addr2 > dol)
80
		addr2 = dol;
81
	nonzero();
82
}
83
 
84
/*
85
 * Parse a number out of the command input stream.
86
 */
87
getnum()
88
{
89
	register int cnt;
90
 
91
	for (cnt = 0; isdigit(peekcd());)
92
		cnt = cnt * 10 + getchar() - '0';
93
	return (cnt);
94
}
95
 
96
/*
97
 * Set the default addresses for commands which use the whole
98
 * buffer as default, notably write.
99
 */
108 7u83 100
void
105 7u83 101
setall()
102
{
103
 
104
	if (addr2 == 0) {
105
		addr1 = one;
106
		addr2 = dol;
107
		if (dol == zero) {
108
			dot = zero;
109
			return;
110
		}
111
	}
112
	/*
113
	 * Don't want to set previous context mark so use setdot1().
114
	 */
115
	setdot1();
116
}
117
 
118
/*
119
 * No address allowed on, e.g. the file command.
120
 */
121
setnoaddr()
122
{
123
	if (addr2 != 0)
124
		error("No address allowed@on this command");
125
}
126
 
127
/*
128
 * Parse an address.
129
 * Just about any sequence of address characters is legal.
130
 *
131
 * If you are tricky you can use this routine and the = command
132
 * to do simple addition and subtraction of cardinals less
133
 * than the number of lines in the file.
134
 */
135
line *
136
address(in_line)
137
	char *in_line;
138
{
139
	register line *addr;
140
	register int offset, c;
141
	short lastsign;
142
 
143
	bigmove = 0;
144
	lastsign = 0;
145
	offset = 0;
146
	addr = 0;
147
	for (;;) {
148
		if (isdigit(peekcd())) {
149
			if (addr == 0) {
150
				addr = zero;
151
				bigmove = 1;
152
			}
153
			loc1 = 0;
154
			addr += offset;
155
			offset = getnum();
156
			if (lastsign >= 0)
157
				addr += offset;
158
			else
159
				addr -= offset;
160
			lastsign = 0;
161
			offset = 0;
162
		}
163
		switch (c = getcd()) {
164
 
165
		case '?':
166
		case '/':
167
		case '$':
168
		case '\'':
169
		case '\\':
170
			bigmove++;
171
		case '.':
172
			if (addr || offset)
173
				error("Badly formed address");
174
		}
175
		offset += lastsign;
176
		lastsign = 0;
177
		switch (c) {
178
 
179
		case ' ':
180
		case '\t':
181
			continue;
182
 
183
		case '+':
184
			lastsign = 1;
185
			if (addr == 0)
186
				addr = dot;
187
			continue;
188
 
189
		case '^':
190
		case '-':
191
			lastsign = -1;
192
			if (addr == 0)
193
				addr = dot;
194
			continue;
195
 
196
		case '\\':
197
		case '?':
198
		case '/':
199
			c = compile(c, 1);
200
			notempty();
201
			savere(scanre);
202
			addr = dot;
203
			if (in_line && execute(0, dot)) {
204
				if (c == '/') {
205
					while (loc1 <= in_line) {
206
						if (loc1 == loc2)
207
							loc2++;
208
						if (!execute(1))
209
							goto nope;
210
					}
211
					break;
212
				} else if (loc1 < in_line) {
213
					char *last;
214
doques:
215
 
216
					do {
217
						last = loc1;
218
						if (loc1 == loc2)
219
							loc2++;
220
						if (!execute(1))
221
							break;
222
					} while (loc1 < in_line);
223
					loc1 = last;
224
					break;
225
				}
226
			}
227
nope:
228
			for (;;) {
229
				if (c == '/') {
230
					addr++;
231
					if (addr > dol) {
232
						if (value(WRAPSCAN) == 0)
233
error("No match to BOTTOM|Address search hit BOTTOM without matching pattern");
234
						addr = zero;
235
					}
236
				} else {
237
					addr--;
238
					if (addr < zero) {
239
						if (value(WRAPSCAN) == 0)
240
error("No match to TOP|Address search hit TOP without matching pattern");
241
						addr = dol;
242
					}
243
				}
244
				if (execute(0, addr)) {
245
					if (in_line && c == '?') {
246
						in_line = &linebuf[LBSIZE];
247
						goto doques;
248
					}
249
					break;
250
				}
251
				if (addr == dot)
252
					error("Fail|Pattern not found");
253
			}
254
			continue;
255
 
256
		case '$':
257
			addr = dol;
258
			continue;
259
 
260
		case '.':
261
			addr = dot;
262
			continue;
263
 
264
		case '\'':
265
			c = markreg(getchar());
266
			if (c == 0)
267
				error("Marks are ' and a-z");
268
			addr = getmark(c);
269
			if (addr == 0)
270
				error("Undefined mark@referenced");
271
			break;
272
 
273
		default:
274
			ungetchar(c);
275
			if (offset) {
276
				if (addr == 0)
277
					addr = dot;
278
				addr += offset;
279
				loc1 = 0;
280
			}
281
			if (addr == 0) {
282
				bigmove = 0;
283
				return (0);
284
			}
285
			if (addr != zero)
286
				notempty();
287
			addr += lastsign;
288
			if (addr < zero)
289
				error("Negative address@- first buffer line is 1");
290
			if (addr > dol)
291
				error("Not that many lines@in buffer");
292
			return (addr);
293
		}
294
	}
295
}
296
 
297
/*
298
 * Abbreviations to make code smaller
299
 * Left over from squashing ex version 1.1 into
300
 * 11/34's and 11/40's.
301
 */
302
setCNL()
303
{
304
 
305
	setcount();
306
	newline();
307
}
308
 
309
setNAEOL()
310
{
311
 
312
	setnoaddr();
313
	eol();
314
}