Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
99 7u83 1
/*
2
 * This code contains changes by
3
 *      Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
4
 *
5
 * Conditions 1, 2, and 4 and the no-warranty notice below apply
6
 * to these changes.
7
 *
8
 *
9
 * Copyright (c) 1980, 1993
10
 * 	The Regents of the University of California.  All rights reserved.
11
 *
12
 * Redistribution and use in source and binary forms, with or without
13
 * modification, are permitted provided that the following conditions
14
 * are met:
15
 * 1. Redistributions of source code must retain the above copyright
16
 *    notice, this list of conditions and the following disclaimer.
17
 * 2. Redistributions in binary form must reproduce the above copyright
18
 *    notice, this list of conditions and the following disclaimer in the
19
 *    documentation and/or other materials provided with the distribution.
20
 * 3. All advertising materials mentioning features or use of this software
21
 *    must display the following acknowledgement:
22
 * 	This product includes software developed by the University of
23
 * 	California, Berkeley and its contributors.
24
 * 4. Neither the name of the University nor the names of its contributors
25
 *    may be used to endorse or promote products derived from this software
26
 *    without specific prior written permission.
27
 *
28
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38
 * SUCH DAMAGE.
39
 *
40
 *
41
 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
42
 *
43
 * Redistribution and use in source and binary forms, with or without
44
 * modification, are permitted provided that the following conditions
45
 * are met:
46
 *   Redistributions of source code and documentation must retain the
47
 *    above copyright notice, this list of conditions and the following
48
 *    disclaimer.
49
 *   Redistributions in binary form must reproduce the above copyright
50
 *    notice, this list of conditions and the following disclaimer in the
51
 *    documentation and/or other materials provided with the distribution.
52
 *   All advertising materials mentioning features or use of this software
53
 *    must display the following acknowledgement:
54
 *      This product includes software developed or owned by Caldera
55
 *      International, Inc.
56
 *   Neither the name of Caldera International, Inc. nor the names of
57
 *    other contributors may be used to endorse or promote products
58
 *    derived from this software without specific prior written permission.
59
 *
60
 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
61
 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
62
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
63
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64
 * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
65
 * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
66
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
67
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
68
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
69
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
70
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
71
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72
 */
73
 
74
#ifndef	lint
75
#ifdef	DOSCCS
76
static char sccsid[] = "@(#)ex_addr.c	1.10 (gritter) 2/17/05";
77
#endif
78
#endif /* not lint */
79
 
80
/* from ex_addr.c	7.3 (Berkeley) 6/7/85 */
81
 
82
#include "ex.h"
83
#include "ex_re.h"
84
 
85
/*
86
 * Routines for address parsing and assignment and checking of address bounds
87
 * in command mode.  The routine address is called from ex_cmds.c
88
 * to parse each component of a command (terminated by , ; or the beginning
89
 * of the command itself.  It is also called by the scanning routine
90
 * in ex_voperate.c from within open/visual.
91
 *
92
 * Other routines here manipulate the externals addr1 and addr2.
93
 * These are the first and last lines for the current command.
94
 *
95
 * The variable bigmove remembers whether a non-local glitch of . was
96
 * involved in an address expression, so we can set the previous context
97
 * mark '' when such a motion occurs.
98
 */
99
 
100
static	bool bigmove;
101
 
102
/*
103
 * Set up addr1 and addr2 for commands whose default address is dot.
104
 */
105
void 
106
setdot(void)
107
{
108
 
109
	setdot1();
110
	if (bigmove)
111
		markDOT();
112
}
113
 
114
/*
115
 * Call setdot1 to set up default addresses without ever
116
 * setting the previous context mark.
117
 */
118
void 
119
setdot1(void)
120
{
121
 
122
	if (addr2 == 0)
123
		addr1 = addr2 = dot;
124
	if (addr1 > addr2) {
125
		notempty();
126
		failed = 1;
127
		error(catgets(catd, 1, 6,
128
			"Addr1 > addr2|First address exceeds second"));
129
	}
130
}
131
 
132
/*
133
 * Ex allows you to say
134
 *	delete 5
135
 * to delete 5 lines, etc.
136
 * Such nonsense is implemented by setcount.
137
 */
138
void 
139
setcount(void)
140
{
141
	register int cnt;
142
 
143
	pastwh();
144
	if (!isdigit(peekchar())) {
145
		setdot();
146
		return;
147
	}
148
	addr1 = addr2;
149
	setdot();
150
	cnt = getnum();
151
	if (cnt <= 0)
152
		error(catgets(catd, 1, 7, "Bad count|Nonzero count required"));
153
	addr2 += cnt - 1;
154
	if (addr2 > dol)
155
		addr2 = dol;
156
	nonzero();
157
}
158
 
159
/*
160
 * Parse a number out of the command input stream.
161
 */
162
int 
163
getnum(void)
164
{
165
	register int cnt;
166
 
167
	for (cnt = 0; isdigit(peekcd());)
168
		cnt = cnt * 10 + getchar() - '0';
169
	return (cnt);
170
}
171
 
172
/*
173
 * Set the default addresses for commands which use the whole
174
 * buffer as default, notably write.
175
 */
176
void 
177
setall(void)
178
{
179
 
180
	if (addr2 == 0) {
181
		addr1 = one;
182
		addr2 = dol;
183
		if (dol == zero) {
184
			dot = zero;
185
			return;
186
		}
187
	}
188
	/*
189
	 * Don't want to set previous context mark so use setdot1().
190
	 */
191
	setdot1();
192
}
193
 
194
/*
195
 * No address allowed on, e.g. the file command.
196
 */
197
void 
198
setnoaddr(void)
199
{
200
 
201
	if (addr2 != 0) {
202
		failed = 1;
203
		error(catgets(catd, 1, 8,
204
				"No address allowed@on this command"));
205
	}
206
}
207
 
208
/*
209
 * Parse an address.
210
 * Just about any sequence of address characters is legal.
211
 *
212
 * If you are tricky you can use this routine and the = command
213
 * to do simple addition and subtraction of cardinals less
214
 * than the number of lines in the file.
215
 */
216
line *
217
address(char *in_line)
218
{
219
	register line *addr;
220
	register int offset, c;
221
	short lastsign;
222
 
223
	bigmove = 0;
224
	lastsign = 0;
225
	offset = 0;
226
	addr = 0;
227
	for (;;) {
228
		if (isdigit(peekcd())) {
229
			if (addr == 0) {
230
				addr = zero;
231
				bigmove = 1;
232
			}
233
			loc1 = 0;
234
			addr += offset;
235
			offset = getnum();
236
			if (lastsign >= 0)
237
				addr += offset;
238
			else
239
				addr -= offset;
240
			lastsign = 0;
241
			offset = 0;
242
		}
243
		switch (c = getcd()) {
244
 
245
		case '?':
246
		case '/':
247
		case '$':
248
		case '\'':
249
		case '\\':
250
			bigmove++;
251
		case '.':
252
			if (addr || offset)
253
				error(catgets(catd, 1, 9,
254
						"Badly formed address"));
255
		}
256
		offset += lastsign;
257
		lastsign = 0;
258
		switch (c) {
259
 
260
		case ' ':
261
		case '\t':
262
			continue;
263
 
264
		case '+':
265
			lastsign = 1;
266
			if (addr == 0)
267
				addr = dot;
268
			continue;
269
 
270
		case '^':
271
		case '-':
272
			lastsign = -1;
273
			if (addr == 0)
274
				addr = dot;
275
			continue;
276
 
277
		case '\\':
278
		case '?':
279
		case '/':
280
			c = compile(c, 1);
281
			notempty();
282
			savere(&scanre);
283
			addr = dot;
284
			if (in_line && execute(0, dot)) {
285
				if (c == '/') {
286
					while (loc1 <= in_line) {
287
						if (loc1 == loc2)
288
							loc2++;
289
						if (!execute(1, NULL))
290
							goto nope;
291
					}
292
					break;
293
				} else if (loc1 < in_line) {
294
					char *last;
295
doques:
296
 
297
					do {
298
						last = loc1;
299
						if (loc1 == loc2)
300
							loc2++;
301
						if (!execute(1, NULL))
302
							break;
303
					} while (loc1 < in_line);
304
					loc1 = last;
305
					break;
306
				}
307
			}
308
nope:
309
			for (;;) {
310
				if (c == '/') {
311
					addr++;
312
					if (addr > dol) {
313
						if (value(WRAPSCAN) == 0)
314
error(catgets(catd, 1, 10, "No match to BOTTOM|Address search hit BOTTOM without matching pattern"));
315
						addr = zero;
316
					}
317
				} else {
318
					addr--;
319
					if (addr < zero) {
320
						if (value(WRAPSCAN) == 0)
321
error(catgets(catd, 1, 11, "No match to TOP|Address search hit TOP without matching pattern"));
322
						addr = dol;
323
					}
324
				}
325
				if (execute(0, addr)) {
326
					if (in_line && c == '?') {
327
						in_line = &linebuf[LBSIZE];
328
						goto doques;
329
					}
330
					break;
331
				}
332
				if (addr == dot)
333
					error(catgets(catd, 1, 12,
334
						"Fail|Pattern not found"));
335
			}
336
			continue;
337
 
338
		case '$':
339
			addr = dol;
340
			continue;
341
 
342
		case '.':
343
			addr = dot;
344
			continue;
345
 
346
		case '\'':
347
			c = markreg(getchar());
348
			if (c == 0)
349
				error(catgets(catd, 1, 13,
350
						"Marks are ' and a-z"));
351
			addr = getmark(c);
352
			if (addr == 0)
353
				error(catgets(catd, 1, 14,
354
						"Undefined mark@referenced"));
355
			break;
356
 
357
		default:
358
			ungetchar(c);
359
			if (offset) {
360
				if (addr == 0)
361
					addr = dot;
362
				addr += offset;
363
				loc1 = 0;
364
			}
365
			if (addr == 0) {
366
				bigmove = 0;
367
				return (0);
368
			}
369
			if (addr != zero)
370
				notempty();
371
			addr += lastsign;
372
			if (addr < zero) {
373
				failed = 1;
374
				error(catgets(catd, 1, 15,
375
				"Negative address@- first buffer line is 1"));
376
			}
377
			if (addr > dol) {
378
				failed = 1;
379
				error(catgets(catd, 1, 16,
380
					"Not that many lines@in buffer"));
381
			}
382
			return (addr);
383
		}
384
	}
385
}
386
 
387
/*
388
 * Abbreviations to make code smaller
389
 * Left over from squashing ex version 1.1 into
390
 * 11/34's and 11/40's.
391
 */
392
void 
393
setCNL(void)
394
{
395
 
396
	setcount();
397
	newline();
398
}
399
 
400
void 
401
setNAEOL(void)
402
{
403
 
404
	setnoaddr();
405
	eol();
406
}