1 /* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
2 * This software is quasi-public; it may be used freely with
3 * like software, but may NOT be sold or made part of licensed
4 * products without permission of the author.
7 * EEMAIN ELLE Main Command Loop
16 #include "eesigs.h" /* Use this on V6 system */
19 char *argfile
[MAXARGFILES
]; /* Filename args at startup */
21 extern int (*sbm_debug
)();
22 extern int (*sbv_debug
)();
23 int (*vfy_vec
)(); /* If non-zero, routine to verify data
24 * after each main-loop command */
30 register int c
; /* Current command character */
35 extern int sun_rdevf
; /* from EESUN */
38 char stackm
[STKMEM
]; /* Allocate some unused stack space */
41 sbv_debug
= errsbm
; /* Load with addrs of routine to */
42 sbm_debug
= errsbm
; /* process SB and SBM errors. */
45 sbm_init(&stackm
[0],(SBMO
)STKMEM
); /* Initialize mem alloc rtns */
48 sun_main(&argc
, argv
); /* On SUN, invoke window startup */
51 setbuf(stdout
, (char *)NULL
); /* Remove all stdio buffering */
52 setbuf(stderr
, (char *)NULL
); /* in case of error reports. */
54 waitct
= 0; /* debugging */
55 doargs(argc
,argv
); /* Set up args */
56 initialize (); /* Initialize the editor */
58 if (argfile
[0]) /* shell line arg */
59 find_file(argfile
[0]);
62 { f_2winds(); /* Make 2 windows, go to 2nd */
65 for (; i
< MAXARGFILES
; ++i
)
66 #endif /* > 2 files */
67 find_file(argfile
[i
]); /* Get further file(s) */
68 f_othwind(); /* Move back to 1st window */
72 redp(RD_SCREEN
|RD_MODE
); /* Clear and show mode line */
73 setexit(0); /* catch for ints, ^G throws */
75 /* -----------------------------------------------------------
81 /* First set up default arg unless last cmd specified it */
82 if(this_cmd
!= ARGCMD
)
83 { exp
= 1; /* Default arg is 1 */
84 exp_p
= 0; /* Say no explicit arg */
89 askclr(); /* If stuff asked, say to clear it */
93 redisplay(); /* Redisplay if needed and no input */
95 sun_rdevf
= 1; /* Allow mouse events on this input */
97 c
= cmd_read(); /* Read an editor command */
98 sayclr(); /* Ask to clear echo area cleverly */
101 if(c
!= -1) /* SUN may not have real input */
102 #endif /* if mouse event happened. */
103 cmd_xct(c
); /* Execute the command char! */
105 if(vfy_vec
) /* If debugging, */
106 (*vfy_vec
)(1); /* verify data structs right away */
110 char *prof_file
; /* Can specify user profile filename */
115 { register int cnt
, c
;
124 #if V6 /* V6 doesn't have environment thus no TERM var */
125 /* Hack to force terminal type; analyze pgm name to get
126 * possible ".type" suffix.
128 if(cnt
&& (c
= strlen(*av
)))
132 tv_stype
= &av
[0][c
+1];
143 if(*av
[0] != '-') /* If not switch, */
144 { /* assume it's an input filename */
145 if (argfiles
< MAXARGFILES
)
146 argfile
[argfiles
++] = *av
;
151 c
= upcase(av
[0][1]);
152 switch(c
) /* Switches without args */
153 { case 'I': /* Allow debug ints */
156 case '8': /* Ask for 8-bit input */
159 case '7': /* Ask for 7-bit input */
163 case 'R': /* Debug redisplay stuff */
171 switch(c
) /* Switches with args */
172 { case 'T': /* Terminal type */
181 stop
: printf("ELLE: bad switch: %s\n",*av
);
185 { printf("ELLE: more than %d file args, %d ignored.\n",
186 MAXARGFILES
, argsignored
);
187 sleep(2); /* Complain but continue after pause */
191 int f_throw(); /* throw function */
192 int bite_bag(); /* Error handling routine */
193 int hup_exit(); /* Hangup handling routine */
195 struct majmode ifunmode
= { "Fundamental" };
197 initialize () /* Initialization */
200 extern int sun_winfd
;
202 cur_mode
= fun_mode
= &ifunmode
; /* Set current major mode */
207 extern char *logdir();
210 homedir
= getenv("HOME");
214 sbx_tset((chroff
)0,0); /* Create swapout file */
215 /* (Temporary hack, fix up later) */
216 hoard(); /* Hoard a FD for write purposes */
218 redp_init(); /* Set up the display routines */
219 init_buf(); /* Set up initial buffers */
220 set_profile(prof_file
); /* Set up user profile */
223 if(sun_winfd
) sun_init();
226 /* Set up signal handlers */
227 #if 0 /* not really used */
228 signal (SIGQUIT
, f_throw
); /* Quit - on ^G */
231 signal (SIGSYS
, bite_bag
); /* Bad arg to Sys call */
233 signal (SIGSEGV
, bite_bag
); /* Segmentation Violation */
235 signal (SIGILL
, bite_bag
); /* Illegal Instruction interrupt */
236 signal (SIGBUS
, bite_bag
); /* Bus Error interrupt */
238 #if !(TOPS20) /* T20 just detaches job */
239 signal (SIGHUP
, hup_exit
); /* Terminal Hangup interrupt */
244 /* NOTE: This routine is not actually used, because ELLE does not
245 * allow interrupts to do anything.
247 /* EFUN: "Error Throw" */
248 f_throw () /* abort whatever is going on */
251 curs_lin
= -1000; /* make t_curpos do something */
252 redp(RD_MOVE
); /* crock: cursor seems to move, so fix it */
253 signal(SIGQUIT
, f_throw
); /* rearm signal */
254 /* unwind_stack(main); */
255 reset(1); /* throw to main loop */
258 /* RING_BELL - General-purpose feeper when something goes wrong with
262 { t_bell(); /* Tell user something's wrong */
265 f_ekmac(); /* Stop collecting keyboard macro if any */
269 /* EFUN: "Return to Superior"
270 * Behavior here is somewhat system-dependent. If it is possible to
271 * suspend the process and continue later, we do not ask about modified
272 * buffers. Otherwise, we do. Questioning can always be forced by using
274 * Note that here we try to be very careful about not letting the user
275 * exit while buffers are still modified, since UNIX flushes the process
276 * if we exit. Also, the code here conspires with sel_mbuf to rotate
277 * through all modified buffers, complaining about a different one each time,
278 * so that the user need not even know how to select a buffer!
281 { register char *reply
;
283 register struct buffer
*b
, *b2
;
284 extern struct buffer
*sel_mbuf();
285 extern int tsf_pause
;
287 /* If we have capability of pausing and later continuing, do that,
288 * except if CTRL-U forces us into question/save/quit behavior.
290 if(tsf_pause
&& (exp_p
!= 4))
291 { clean_exit(); /* Return TTY to normal mode */
292 ts_pause(); /* Pause this inferior */
293 set_tty(); /* Continued, return to edit mode */
298 /* Sigh, do more typical "Are you sure" questioning prior to
299 * killing the editor permanently.
302 if((b
= sel_mbuf(b
)) || (b
= sel_mbuf((struct buffer
*)0)) )
303 { if(b2
= sel_mbuf(b
))
305 "Quit: buffers %s, %s,... still have changes - forget them? ",
306 b
->b_name
, b2
->b_name
);
309 "Quit: buffer %s still has changes - forget them? ",
315 #if IMAGEN /* Do not ask further if nothing modified */
320 reply
= ask("Quit? ");
325 return; /* Aborted, just return */
327 c
= upcase(*reply
); /* Get 1st char of reply */
338 case 'S': /* Suspend command for debugging */
342 default: /* Complain */
345 if(b
) /* B set if we have any modified buffers */
348 saynow("Use ^X ^S to save buffer");
349 else saynow("Use ^X ^W to write out buffer");
356 /* EFUN: "Write File Exit" (not EMACS) - from IMAGEN config */
359 exp_p
= 1; /* Ensure f_savefiles asks no questions */
360 if (! f_savefiles()) /* Save all modified buffers, but */
361 return; /* stay here if any save fails */
368 /* Subprocess-handling stuff; put here for time being. */
370 /* EFUN: "Push to Inferior" */
372 #include <frkxec.h> /* Support for KCC forkexec() call */
377 register int (*sav2
)(), (*sav3
)();
384 sav2
= signal(SIGINT
, SIG_IGN
); /* Ignore TTY interrupts */
385 sav3
= signal(SIGQUIT
, SIG_IGN
); /* Ditto TTY "quit"s */
386 clean_exit(); /* Restore normal TTY modes */
391 fx
.fx_flags
= FX_WAIT
| FX_T20_PGMNAME
;
392 fx
.fx_name
= "SYS:EXEC.EXE";
393 fx
.fx_argv
= fx
.fx_envp
= NULL
;
394 if (forkexec(&fx
) < 0)
395 writerr("Cannot run EXEC");
400 writerr("Cannot fork");
402 case 0: /* We're the child */
403 for(res
= 3; res
< 20;) /* Don't let inf hack fd's */
406 execl("/bin/sh","-sh",0);
408 signal(SIGINT
, SIG_DFL
); /* V7 shell wants this?? */
409 signal(SIGQUIT
, SIG_DFL
); /* */
411 if((shellname
= getenv("SHELL")) == 0)
413 strcpy(fullshell
, "/bin/");
414 strcat(fullshell
, shellname
);
415 shellname
= fullshell
;
417 if((shellname
= getenv("SHELL")) == 0)
418 shellname
= "/bin/sh";
421 if((shellname
= getenv("SHELL")) == 0)
422 shellname
= "/bin/sh";
423 execl(shellname
, shellname
, 0);
425 writerr("No shell!");
429 while((res
= wait(&status
)) != pid
&& res
!= -1);
434 signal(SIGINT
, sav2
); /* Restore signal settings */
435 signal(SIGQUIT
, sav3
);
436 set_tty(); /* Restore editor TTY modes */
437 redp(RD_SCREEN
|RD_MODE
); /* Done, redisplay */
440 /* Miscellaneous utility routines - memory alloc/free and string hacking.
441 * If this page becomes overly large, it can be split off into a separate
442 * file called E_MISC.
446 char *s
; /* Note that STRCPY's return val must be its 1st arg */
448 return(strcpy(memalloc((SBMO
)(strlen(s
)+1)), s
));
455 extern SBMA
sbx_malloc();
457 if ((ptr
= (SBMA
)sbx_malloc(size
)) != 0)
459 barf("ELLE: No memory left");
461 return(0); /* If we dare to continue... */
468 { errbarf("Something overwrote an allocated block!");
474 /* USTRCMP - Uppercase String Compare.
475 * Returns 0 if mismatch,
477 * -1 if str1 runs out first (partial match)
481 { register char *s1
, *s2
;
483 s1
= str1
; s2
= str2
;
485 { if(c
!= *s2
&& upcase(c
) != upcase(*s2
))
489 return(c
== *s2
? 1 : -1);
493 /* WRITERR(str) - Output string to standard error output.
494 ** This is a separate routine to save a little space on calls.
498 { return(writez(2, str
));
501 /* WRITEZ(fd, str) - Miscellaneous general-purpose string output.
509 write(fd
,acp
,cp
-acp
-1);