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_cmds2.c	1.18 (gritter) 2/17/05";
77
#endif
78
#endif
79
 
80
/* from ex_cmds2.c	7.4 (Berkeley) 6/7/85 */
81
 
82
#include "ex.h"
83
#include "ex_argv.h"
84
#include "ex_temp.h"
85
#include "ex_tty.h"
86
#include "ex_vis.h"
87
 
88
extern bool	pflag, nflag;		/* mjm: extern; also in ex_cmds.c */
89
extern int	poffset;		/* mjm: extern; also in ex_cmds.c */
90
 
91
/*
92
 * Subroutines for major command loop.
93
 */
94
 
95
/*
96
 * Is there a single letter indicating a named buffer next?
97
 */
98
int 
99
cmdreg(void)
100
{
101
	register int c = 0;
102
	register int wh = skipwh();
103
 
104
	if (wh && isalpha(peekchar()))
105
		c = getchar();
106
	return (c);
107
}
108
 
109
/*
110
 * Tell whether the character ends a command
111
 */
112
int 
113
endcmd(int ch)
114
{
115
	switch (ch) {
116
 
117
	case '\n':
118
	case EOF:
119
		endline = 1;
120
		return (1);
121
 
122
	case '|':
123
	case '"':
124
		endline = 0;
125
		return (1);
126
	}
127
	return (0);
128
}
129
 
130
/*
131
 * Insist on the end of the command.
132
 */
133
void 
134
eol(void)
135
{
136
 
137
	if (!skipend())
138
		error(catgets(catd, 1, 28,
139
			"Extra chars|Extra characters at end of command"));
140
	ignnEOF();
141
}
142
 
143
/*
144
 * Guts of the pre-printing error processing.
145
 * If in visual and catching errors, then we dont mung up the internals,
146
 * just fixing up the echo area for the print.
147
 * Otherwise we reset a number of externals, and discard unused input.
148
 */
149
void 
150
error0(void)
151
{
152
 
153
	if (vcatch) {
154
		if (splitw == 0)
155
			fixech();
156
		if (!SO || !SE)
157
			dingdong();
158
		return;
159
	}
160
	if (input && exitoneof) {
161
		input = strend(input) - 1;
162
		if (*input == '\n')
163
			setlastchar('\n');
164
		input = 0;
165
	}
166
	setoutt();
167
	flush();
168
	resetflav();
169
	if (!SO || !SE)
170
		dingdong();
171
	if (inopen) {
172
		/*
173
		 * We are coming out of open/visual ungracefully.
174
		 * Restore TCOLUMNS, undo, and fix tty mode.
175
		 */
176
		TCOLUMNS = OCOLUMNS;
177
		undvis();
178
		ostop(normf);
179
		/* ostop should be doing this
180
		putpad(VE);
181
		putpad(KE);
182
		*/
183
		putnl();
184
	}
185
	inopen = 0;
186
	holdcm = 0;
187
}
188
 
189
/*
190
 * Post error printing processing.
191
 * Close the i/o file if left open.
192
 * If catching in visual then throw to the visual catch,
193
 * else if a child after a fork, then exit.
194
 * Otherwise, in the normal command mode error case,
195
 * finish state reset, and throw to top.
196
 */
197
int 
198
error1(char *str)
199
{
200
	bool die;
201
 
202
	if (io > 0) {
203
		close(io);
204
		io = -1;
205
	}
206
	die = (getpid() != ppid);	/* Only children die */
207
	inappend = inglobal = 0;
208
	globp = NULL, vmacp = NULL, vglobp = NULL;
209
	if (vcatch && !die) {
210
		inopen = 1;
211
		vcatch = 0;
212
		if (str)
213
			noonl();
214
		fixol();
215
		LONGJMP(vreslab,1);
216
	}
217
	if (str && !vcatch)
218
		putNFL();
219
	if (die)
220
		exitex(1);
221
	if (exitoneof)
222
		lseek(0, (off_t)0, SEEK_END);
223
	if (inglobal)
224
		setlastchar('\n');
225
	while (lastchar() != '\n' && lastchar() != EOF)
226
		ignchar();
227
	ungetchar(0);
228
	endline = 1;
229
	reset();
230
}
231
 
232
/*
233
 * Print out the message in the error message file at str,
234
 * with i an integer argument to printf.
235
 */
236
/*VARARGS2*/
237
void
238
error(char *str, ...)
239
{
240
	va_list ap;
241
 
242
	error0();
243
	va_start(ap, str);
244
	vmerror(str, ap);
245
	va_end(ap);
246
 
247
	if (writing) {
248
		serror(catgets(catd, 1, 29,
249
				" [Warning - %s is incomplete]"), file);
250
		writing = 0;
251
	}
252
	error1(str);
253
}
254
 
255
/*
256
 * Same as error(), but using a va_list as argument.
257
 */
258
void
259
verror(char *str, va_list ap)
260
{
261
	error0();
262
	vmerror(str, ap);
263
	error(NULL);
264
 
265
	if (writing) {
266
		serror(catgets(catd, 1, 29,
267
				" [Warning - %s is incomplete]"), file);
268
		writing = 0;
269
	}
270
	error1(str);
271
}
272
 
273
/*
274
 * Rewind the argument list.
275
 */
276
void
277
erewind(void)
278
{
279
 
280
	argc = argc0;
281
	argv = argv0;
282
	args = args0;
283
	if (argc > 1 && !hush) {
284
		printf(mesg(catgets(catd, 1, 30, "%d files@to edit")), argc);
285
		if (inopen)
286
			putchar(' ');
287
		else
288
			putNFL();
289
	}
290
}
291
 
292
void
293
fixol(void)
294
{
295
	if (Outchar != vputchar) {
296
		flush();
297
		if (state == ONEOPEN || state == HARDOPEN)
298
			outline = destline = 0;
299
		Outchar = vputchar;
300
		vcontin(1);
301
	} else {
302
		if (destcol)
303
			vclreol();
304
		vclean();
305
	}
306
}
307
 
308
/*
309
 * Does an ! character follow in the command stream?
310
 */
311
int
312
exclam(void)
313
{
314
 
315
	if (peekchar() == '!') {
316
		ignchar();
317
		return (1);
318
	}
319
	return (0);
320
}
321
 
322
/*
323
 * Make an argument list for e.g. next.
324
 */
325
void
326
makargs(void)
327
{
328
 
329
	gglob(&frob);
330
	argc0 = frob.argc0;
331
	argv0 = frob.argv;
332
	args0 = argv0[0];
333
	erewind();
334
}
335
 
336
/*
337
 * Advance to next file in argument list.
338
 */
339
void
340
next(void)
341
{
342
	extern short isalt;	/* defined in ex_io.c */
343
 
344
	if (argc == 0)
345
		error(catgets(catd, 1, 31, "No more files@to edit"));
346
	morargc = argc;
347
	isalt = (strcmp(altfile, args)==0) + 1;
348
	if (savedfile[0])
349
		strcpy(altfile, savedfile);
350
	safecp(savedfile, args, sizeof savedfile, "File name too long");
351
	argc--;
352
	args = argv ? *++argv : strend(args) + 1;
353
}
354
 
355
/*
356
 * Eat trailing flags and offsets after a command,
357
 * saving for possible later post-command prints.
358
 */
359
void
360
newline(void)
361
{
362
	register int c;
363
 
364
	resetflav();
365
	for (;;) {
366
		c = getchar();
367
		switch (c) {
368
 
369
		case '^':
370
		case '-':
371
			poffset--;
372
			break;
373
 
374
		case '+':
375
			poffset++;
376
			break;
377
 
378
		case 'l':
379
			listf++;
380
			break;
381
 
382
		case '#':
383
			nflag++;
384
			break;
385
 
386
		case 'p':
387
			listf = 0;
388
			break;
389
 
390
		case ' ':
391
		case '\t':
392
			continue;
393
 
394
		case '"':
395
			comment();
396
			setflav();
397
			return;
398
 
399
		default:
400
			if (!endcmd(c))
401
serror(catgets(catd, 1, 32,
402
	"Extra chars|Extra characters at end of \"%s\" command"), Command);
403
			if (c == EOF)
404
				ungetchar(c);
405
			setflav();
406
			return;
407
		}
408
		pflag++;
409
	}
410
}
411
 
412
/*
413
 * Before quit or respec of arg list, check that there are
414
 * no more files in the arg list.
415
 */
416
void
417
nomore(void)
418
{
419
 
420
	if (argc == 0 || morargc == argc)
421
		return;
422
	morargc = argc;
423
	merror(catgets(catd, 1, 33, "%d more file"), argc);
424
	serror(catgets(catd, 1, 34, "%s@to edit"), plural((long) argc));
425
}
426
 
427
/*
428
 * Before edit of new file check that either an ! follows
429
 * or the file has not been changed.
430
 */
431
int
432
quickly(void)
433
{
434
 
435
	if (exclam())
436
		return (1);
437
	if (chng && dol > zero) {
438
/*
439
		chng = 0;
440
*/
441
		xchng = 0;
442
		error(catgets(catd, 1, 35,
443
		"No write@since last change (:%s! overrides)"), Command);
444
	}
445
	return (0);
446
}
447
 
448
/*
449
 * Reset the flavor of the output to print mode with no numbering.
450
 */
451
void
452
resetflav(void)
453
{
454
 
455
	if (inopen)
456
		return;
457
	listf = 0;
458
	nflag = 0;
459
	pflag = 0;
460
	poffset = 0;
461
	setflav();
462
}
463
 
464
/*
465
 * Print an error message with a %s type argument to printf.
466
 * Message text comes from error message file.
467
 */
468
void
469
serror(char *str, ...)
470
{
471
	va_list ap;
472
 
473
	if (str == NULL)
474
		return;
475
	va_start(ap, str);
476
	error0();
477
	vsmerror(str, ap);
478
	error1(str);
479
	va_end(ap);
480
}
481
 
482
/*
483
 * Set the flavor of the output based on the flags given
484
 * and the number and list options to either number or not number lines
485
 * and either use normally decoded (ARPAnet standard) characters or list mode,
486
 * where end of lines are marked and tabs print as ^I.
487
 */
488
void
489
setflav(void)
490
{
491
 
492
	if (inopen)
493
		return;
494
	setnumb(nflag || value(NUMBER));
495
	setlist(listf || value(LIST));
496
	setoutt();
497
}
498
 
499
/*
500
 * Skip white space and tell whether command ends then.
501
 */
502
int
503
skipend(void)
504
{
505
 
506
	pastwh();
507
	return (endcmd(peekchar()) && peekchar() != '"');
508
}
509
 
510
/*
511
 * Set the command name for non-word commands.
512
 */
513
void
514
tailspec(int c)
515
{
516
	static char foocmd[2];
517
 
518
	foocmd[0] = c;
519
	Command = foocmd;
520
}
521
 
522
/*
523
 * Try to read off the rest of the command word.
524
 * If alphabetics follow, then this is not the command we seek.
525
 */
526
void
527
tail(char *comm)
528
{
529
 
530
	tailprim(comm, 1, 0);
531
}
532
 
533
void
534
tail2of(char *comm)
535
{
536
 
537
	tailprim(comm, 2, 0);
538
}
539
 
540
char	tcommand[20];
541
 
542
void
543
tailprim(register char *comm, int xi, bool notinvis)
544
{
545
	register char *cp;
546
	register int c;
547
	int	i = xi;
548
 
549
	Command = comm;
550
	for (cp = tcommand; i > 0; i--)
551
		*cp++ = *comm++;
552
	while (*comm && peekchar() == *comm)
553
		*cp++ = getchar(), comm++;
554
	c = peekchar();
555
	if (notinvis || isalpha(c)
556
#ifdef	BIT8
557
			|| xi == 0 && (c&(0200|QUOTE)) == 0200
558
#endif
559
			) {
560
		/*
561
		 * Of the trailing lp funny business, only dl and dp
562
		 * survive the move from ed to ex.
563
		 */
564
		if (tcommand[0] == 'd' && any(c, "lp"))
565
			goto ret;
566
		if (tcommand[0] == 's' && any(c, "gcr"))
567
			goto ret;
568
		while (cp < &tcommand[19] && (c = peekchar(),
569
				isalpha(c)
570
#ifdef	BIT8
571
				|| xi == 0 && (c&(0200|QUOTE)) == 0200
572
#endif
573
				))
574
			*cp++ = getchar();
575
		*cp = 0;
576
		if (notinvis)
577
			serror(catgets(catd, 1, 36,
578
		"What?|%s: No such command from open/visual"), tcommand);
579
		else
580
			serror(catgets(catd, 1, 37,
581
				"What?|%s: Not an editor command"), tcommand);
582
	}
583
ret:
584
	*cp = 0;
585
}
586
 
587
/*
588
 * Continue after a : command from open/visual.
589
 */
590
void
591
vcontin(bool ask)
592
{
593
 
594
	if (vcnt > 0)
595
		vcnt = -vcnt;
596
	if (inopen) {
597
		if (state != VISUAL) {
598
			/*
599
			 * We don't know what a shell command may have left on
600
			 * the screen, so we move the cursor to the right place
601
			 * and then put out a newline.  But this makes an extra
602
			 * blank line most of the time so we only do it for :sh
603
			 * since the prompt gets left on the screen.
604
			 *
605
			 * BUG: :!echo longer than current line \\c
606
			 * will screw it up, but be reasonable!
607
			 */
608
			if (state == CRTOPEN) {
609
				termreset();
610
				vgoto(WECHO, 0);
611
			}
612
			if (!ask) {
613
				putch('\r');
614
				putch('\n');
615
			}
616
			return;
617
		}
618
		if (ask) {
619
			merror(catgets(catd, 1, 38,
620
					"[Hit return to continue] "));
621
			flush();
622
		}
623
		if (ask) {
624
#ifdef EATQS
625
			/*
626
			 * Gobble ^Q/^S since the tty driver should be eating
627
			 * them (as far as the user can see)
628
			 */
629
			while (peekkey(0) == CTRL('Q')
630
					|| peekkey() == CTRL('S'))
631
				ignore(getkey());
632
#endif
633
			if(getkey() == ':') {
634
				/* Ugh. Extra newlines, but no other way */
635
				putch('\n');
636
				outline = WECHO;
637
				ungetkey(':');
638
			}
639
		}
640
		vclrech(1);
641
		if (Peekkey != ':') {
642
			putpad(TI);
643
			tostart();
644
			/* replaced by ostart.
645
			putpad(VS);
646
			putpad(KS);
647
			*/
648
		}
649
	}
650
}
651
 
652
/*
653
 * Put out a newline (before a shell escape)
654
 * if in open/visual.
655
 */
656
void
657
vnfl(void)
658
{
659
 
660
	if (inopen) {
661
		if (state != VISUAL && state != CRTOPEN && destline <= WECHO)
662
			vclean();
663
		else
664
			vmoveitup(1, 0);
665
		vgoto(WECHO, 0);
666
		vclrcell(vtube[WECHO], WCOLS);
667
		tostop();
668
		/* replaced by the ostop above
669
		putpad(VE);
670
		putpad(KE);
671
		*/
672
	}
673
	flush();
674
}