fix for portability on systems with big uids. THIS CHANGES TEMP
[unix-history] / usr / src / usr.bin / ex / ex_cmds2.c
CommitLineData
299f2784
MH
1/* Copyright (c) 1981 Regents of the University of California */
2static char *sccsid = "@(#)ex_cmds2.c 7.1 %G%";
7df0b7cf
MH
3#include "ex.h"
4#include "ex_argv.h"
5#include "ex_temp.h"
6#include "ex_tty.h"
7#include "ex_vis.h"
8
299f2784
MH
9extern bool pflag, nflag; /* mjm: extern; also in ex_cmds.c */
10extern int poffset; /* mjm: extern; also in ex_cmds.c */
7df0b7cf
MH
11
12/*
13 * Subroutines for major command loop.
14 */
15
16/*
17 * Is there a single letter indicating a named buffer next?
18 */
19cmdreg()
20{
21 register int c = 0;
22 register int wh = skipwh();
23
24 if (wh && isalpha(peekchar()))
25 c = getchar();
26 return (c);
27}
28
29/*
30 * Tell whether the character ends a command
31 */
32endcmd(ch)
33 int ch;
34{
35 switch (ch) {
36
37 case '\n':
38 case EOF:
39 endline = 1;
40 return (1);
41
42 case '|':
d266c416 43 case '"':
7df0b7cf
MH
44 endline = 0;
45 return (1);
46 }
47 return (0);
48}
49
50/*
51 * Insist on the end of the command.
52 */
53eol()
54{
55
56 if (!skipend())
57 error("Extra chars|Extra characters at end of command");
58 ignnEOF();
59}
60
61/*
62 * Print out the message in the error message file at str,
63 * with i an integer argument to printf.
64 */
65/*VARARGS2*/
66error(str, i)
67#ifdef lint
68 register char *str;
69#else
70 register int str;
71#endif
72 int i;
73{
74
75 error0();
76 merror(str, i);
04379bab
MH
77 if (writing) {
78 serror(" [Warning - %s is incomplete]", file);
79 writing = 0;
80 }
7df0b7cf
MH
81 error1(str);
82}
83
84/*
85 * Rewind the argument list.
86 */
87erewind()
88{
89
90 argc = argc0;
91 argv = argv0;
92 args = args0;
93 if (argc > 1 && !hush) {
94 printf(mesg("%d files@to edit"), argc);
95 if (inopen)
96 putchar(' ');
97 else
98 putNFL();
99 }
100}
101
102/*
103 * Guts of the pre-printing error processing.
104 * If in visual and catching errors, then we dont mung up the internals,
105 * just fixing up the echo area for the print.
106 * Otherwise we reset a number of externals, and discard unused input.
107 */
108error0()
109{
110
d266c416 111 if (laste) {
7c4625ef
MH
112#ifdef VMUNIX
113 tlaste();
114#endif
d266c416
MH
115 laste = 0;
116 sync();
117 }
7df0b7cf
MH
118 if (vcatch) {
119 if (splitw == 0)
120 fixech();
121 if (!SO || !SE)
122 dingdong();
123 return;
124 }
125 if (input) {
126 input = strend(input) - 1;
127 if (*input == '\n')
128 setlastchar('\n');
129 input = 0;
130 }
131 setoutt();
132 flush();
133 resetflav();
7df0b7cf
MH
134 if (!SO || !SE)
135 dingdong();
136 if (inopen) {
137 /*
138 * We are coming out of open/visual ungracefully.
139 * Restore COLUMNS, undo, and fix tty mode.
140 */
141 COLUMNS = OCOLUMNS;
142 undvis();
143 ostop(normf);
d266c416 144 /* ostop should be doing this
7df0b7cf
MH
145 putpad(VE);
146 putpad(KE);
d266c416 147 */
7df0b7cf
MH
148 putnl();
149 }
150 inopen = 0;
151 holdcm = 0;
152}
153
154/*
155 * Post error printing processing.
156 * Close the i/o file if left open.
157 * If catching in visual then throw to the visual catch,
158 * else if a child after a fork, then exit.
159 * Otherwise, in the normal command mode error case,
160 * finish state reset, and throw to top.
161 */
162error1(str)
163 char *str;
164{
165 bool die;
166
167 if (io > 0) {
168 close(io);
169 io = -1;
170 }
171 die = (getpid() != ppid); /* Only children die */
d266c416 172 inappend = inglobal = 0;
887e3e0d 173 globp = vglobp = vmacp = 0;
7df0b7cf 174 if (vcatch && !die) {
7df0b7cf
MH
175 inopen = 1;
176 vcatch = 0;
887e3e0d
MH
177 if (str)
178 noonl();
7df0b7cf
MH
179 fixol();
180 longjmp(vreslab,1);
181 }
182 if (str && !vcatch)
183 putNFL();
184 if (die)
185 exit(1);
186 lseek(0, 0L, 2);
187 if (inglobal)
188 setlastchar('\n');
7df0b7cf
MH
189 while (lastchar() != '\n' && lastchar() != EOF)
190 ignchar();
191 ungetchar(0);
192 endline = 1;
193 reset();
194}
195
196fixol()
197{
198 if (Outchar != vputchar) {
199 flush();
200 if (state == ONEOPEN || state == HARDOPEN)
201 outline = destline = 0;
202 Outchar = vputchar;
203 vcontin(1);
204 } else {
205 if (destcol)
206 vclreol();
207 vclean();
208 }
209}
210
211/*
212 * Does an ! character follow in the command stream?
213 */
214exclam()
215{
216
217 if (peekchar() == '!') {
218 ignchar();
219 return (1);
220 }
221 return (0);
222}
223
224/*
225 * Make an argument list for e.g. next.
226 */
227makargs()
228{
229
230 glob(&frob);
231 argc0 = frob.argc0;
232 argv0 = frob.argv;
233 args0 = argv0[0];
234 erewind();
235}
236
237/*
238 * Advance to next file in argument list.
239 */
240next()
241{
d266c416 242 extern short isalt; /* defined in ex_io.c */
7df0b7cf
MH
243
244 if (argc == 0)
245 error("No more files@to edit");
246 morargc = argc;
d266c416 247 isalt = (strcmp(altfile, args)==0) + 1;
7df0b7cf
MH
248 if (savedfile[0])
249 CP(altfile, savedfile);
250 CP(savedfile, args);
251 argc--;
252 args = argv ? *++argv : strend(args) + 1;
253}
254
255/*
256 * Eat trailing flags and offsets after a command,
257 * saving for possible later post-command prints.
258 */
259newline()
260{
261 register int c;
262
263 resetflav();
264 for (;;) {
265 c = getchar();
266 switch (c) {
267
268 case '^':
269 case '-':
270 poffset--;
271 break;
272
273 case '+':
274 poffset++;
275 break;
276
277 case 'l':
278 listf++;
279 break;
280
281 case '#':
282 nflag++;
283 break;
284
285 case 'p':
286 listf = 0;
287 break;
288
289 case ' ':
290 case '\t':
291 continue;
292
d266c416
MH
293 case '"':
294 comment();
295 setflav();
296 return;
297
7df0b7cf
MH
298 default:
299 if (!endcmd(c))
300serror("Extra chars|Extra characters at end of \"%s\" command", Command);
301 if (c == EOF)
302 ungetchar(c);
303 setflav();
304 return;
305 }
306 pflag++;
307 }
308}
309
310/*
311 * Before quit or respec of arg list, check that there are
312 * no more files in the arg list.
313 */
314nomore()
315{
316
317 if (argc == 0 || morargc == argc)
318 return;
319 morargc = argc;
320 merror("%d more file", argc);
321 serror("%s@to edit", plural((long) argc));
322}
323
324/*
325 * Before edit of new file check that either an ! follows
326 * or the file has not been changed.
327 */
328quickly()
329{
330
331 if (exclam())
332 return (1);
333 if (chng && dol > zero) {
334/*
335 chng = 0;
336*/
337 xchng = 0;
338 error("No write@since last change (:%s! overrides)", Command);
339 }
340 return (0);
341}
342
343/*
344 * Reset the flavor of the output to print mode with no numbering.
345 */
346resetflav()
347{
348
349 if (inopen)
350 return;
351 listf = 0;
352 nflag = 0;
353 pflag = 0;
354 poffset = 0;
355 setflav();
356}
357
358/*
359 * Print an error message with a %s type argument to printf.
360 * Message text comes from error message file.
361 */
362serror(str, cp)
363#ifdef lint
364 register char *str;
365#else
366 register int str;
367#endif
368 char *cp;
369{
370
371 error0();
372 smerror(str, cp);
373 error1(str);
374}
375
376/*
377 * Set the flavor of the output based on the flags given
378 * and the number and list options to either number or not number lines
379 * and either use normally decoded (ARPAnet standard) characters or list mode,
380 * where end of lines are marked and tabs print as ^I.
381 */
382setflav()
383{
384
385 if (inopen)
386 return;
387 setnumb(nflag || value(NUMBER));
388 setlist(listf || value(LIST));
389 setoutt();
390}
391
392/*
393 * Skip white space and tell whether command ends then.
394 */
395skipend()
396{
397
398 pastwh();
d266c416 399 return (endcmd(peekchar()) && peekchar() != '"');
7df0b7cf
MH
400}
401
402/*
403 * Set the command name for non-word commands.
404 */
405tailspec(c)
406 int c;
407{
408 static char foocmd[2];
409
410 foocmd[0] = c;
411 Command = foocmd;
412}
413
414/*
415 * Try to read off the rest of the command word.
416 * If alphabetics follow, then this is not the command we seek.
417 */
418tail(comm)
419 char *comm;
420{
421
422 tailprim(comm, 1, 0);
423}
424
425tail2of(comm)
426 char *comm;
427{
428
429 tailprim(comm, 2, 0);
430}
431
432char tcommand[20];
433
434tailprim(comm, i, notinvis)
435 register char *comm;
436 int i;
437 bool notinvis;
438{
439 register char *cp;
440 register int c;
441
442 Command = comm;
443 for (cp = tcommand; i > 0; i--)
444 *cp++ = *comm++;
445 while (*comm && peekchar() == *comm)
446 *cp++ = getchar(), comm++;
447 c = peekchar();
448 if (notinvis || isalpha(c)) {
449 /*
450 * Of the trailing lp funny business, only dl and dp
451 * survive the move from ed to ex.
452 */
453 if (tcommand[0] == 'd' && any(c, "lp"))
454 goto ret;
455 if (tcommand[0] == 's' && any(c, "gcr"))
456 goto ret;
457 while (cp < &tcommand[19] && isalpha(peekchar()))
458 *cp++ = getchar();
459 *cp = 0;
460 if (notinvis)
461 serror("What?|%s: No such command from open/visual", tcommand);
462 else
463 serror("What?|%s: Not an editor command", tcommand);
464 }
465ret:
466 *cp = 0;
467}
468
469/*
887e3e0d 470 * Continue after a : command from open/visual.
7df0b7cf
MH
471 */
472vcontin(ask)
473 bool ask;
474{
475
476 if (vcnt > 0)
477 vcnt = -vcnt;
478 if (inopen) {
479 if (state != VISUAL) {
887e3e0d
MH
480 /*
481 * We don't know what a shell command may have left on
482 * the screen, so we move the cursor to the right place
483 * and then put out a newline. But this makes an extra
484 * blank line most of the time so we only do it for :sh
485 * since the prompt gets left on the screen.
486 *
487 * BUG: :!echo longer than current line \\c
488 * will screw it up, but be reasonable!
489 */
490 if (state == CRTOPEN) {
491 termreset();
492 vgoto(WECHO, 0);
493 }
494 if (!ask) {
495 putch('\r');
496 putch('\n');
497 }
7df0b7cf
MH
498 return;
499 }
500 if (ask) {
501 merror("[Hit return to continue] ");
502 flush();
503 }
504#ifndef CBREAK
505 vraw();
506#endif
507 if (ask) {
887e3e0d 508#ifdef EATQS
7df0b7cf
MH
509 /*
510 * Gobble ^Q/^S since the tty driver should be eating
511 * them (as far as the user can see)
512 */
513 while (peekkey() == CTRL(Q) || peekkey() == CTRL(S))
514 ignore(getkey());
887e3e0d
MH
515#endif
516 if(getkey() == ':') {
517 /* Ugh. Extra newlines, but no other way */
518 putch('\n');
519 outline = WECHO;
7df0b7cf 520 ungetkey(':');
887e3e0d
MH
521 }
522 }
523 vclrech(1);
d266c416 524 if (Peekkey != ':') {
887e3e0d 525 putpad(TI);
d266c416
MH
526 tostart();
527 /* replaced by ostart.
887e3e0d
MH
528 putpad(VS);
529 putpad(KS);
d266c416 530 */
7df0b7cf 531 }
7df0b7cf
MH
532 }
533}
534
535/*
536 * Put out a newline (before a shell escape)
537 * if in open/visual.
538 */
539vnfl()
540{
541
542 if (inopen) {
543 if (state != VISUAL && state != CRTOPEN && destline <= WECHO)
544 vclean();
545 else
546 vmoveitup(1, 0);
547 vgoto(WECHO, 0);
548 vclrbyte(vtube[WECHO], WCOLS);
d266c416
MH
549 tostop();
550 /* replaced by the ostop above
7df0b7cf
MH
551 putpad(VE);
552 putpad(KE);
d266c416 553 */
7df0b7cf
MH
554 }
555 flush();
556}