* Copyright (c) 1992 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Rodney Ruddock of the University of Guelph.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)main.c 5.4 (Berkeley) %G%";
* This is where all of the "global" variables are declared. They are
* set for extern in the ed.h header file (so everyone can get them).
int nn_max
, nn_max_flag
, start_default
, End_default
, address_flag
;
int zsnum
, filename_flag
, add_flag
=0, join_flag
=0;
LINE
*nn_max_start
, *nn_max_end
;
struct MARK mark_matrix
[26]; /* in init set all to null */
char *filename_current
, *prompt_string
=NULL
, help_msg
[130];
int prompt_str_flg
=0, start_up_flag
=0, name_set
=0;
LINE
*top
, *current
, *bottom
, *start
, *End
;
LINE
*u_current
, *u_top
, *u_bottom
;
regmatch_t RE_match
[RE_SEC
];
int ss
; /* for the getc() */
int explain_flag
=1, g_flag
=0, GV_flag
=0, printsfx
=0;
jmp_buf ctrl_position
, ctrl_position2
; /* For SIGnal handling. */
int sigint_flag
, sighup_flag
, sigspecial
=0, sigspecial2
=0;
static void sigint_handler
__P((int));
static void sighup_handler
__P((int));
* Starts the whole show going. Set things up as the arguments spec
* in the shell and set a couple of the global variables.
* Note naming viol'n with errnum for consistancy.
int l_num
, errnum
= 0, l_err
= 0;
char *l_fnametmp
, *l_col
;
line_length
= ((l_col
= getenv("COLUMNS")) == NULL
? 0 : atoi(l_col
));
if (line_length
== 0 && isatty(STDOUT_FILENO
) &&
ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &win
) != -1)
line_length
= win
.ws_col
;
nn_max_start
= nn_max_end
= NULL
;
l_fnametmp
= calloc(FILENAME_LEN
, sizeof(char));
text
= calloc(NN_MAX_START
+ 2, sizeof(char));
start_default
= End_default
= 0;
zsnum
= 22; /* for the 'z' command */
u_current
= u_top
= u_bottom
= NULL
;
u_set
= 0; /* for in d after a j */
/* Process the command line options */
switch (argv
[l_num
][0]) {
switch (argv
[l_num
][1]) {
case '\0': /* this is why 'getopt' not used */
calloc(strlen(argv
[l_num
]),
if (prompt_string
== NULL
)
strcpy(prompt_string
, argv
[l_num
]);
strcpy(l_fnametmp
, argv
[l_num
]);
filename_current
= l_fnametmp
;
prompt_string
= (char *) calloc(3, sizeof(char));
strcpy(prompt_string
, "*");
cmd_loop(stdin
, &errnum
);
* The command loop. What the command is that the user has specified
* is determined here. This is not just for commands coming from
* the terminal but any standard i/o stream; see the global commands.
* Some of the commands are handled within here (i.e. 'H') while most
* are handled in their own functions (as called).
l_last
= 0; /* value in l_last may be clobbered (reset to = 0) by longjump, but that's okay */
if (g_flag
== 0) { /* big, BIG trouble if we don't check! think. */
/* set the jump point for the signals */
l_jmp_flag
= setjmp(ctrl_position
);
signal(SIGINT
, sigint_handler
);
signal(SIGHUP
, sighup_handler
);
/* Some general cleanup not specific to the jmp pt. */
GV_flag
= 0; /* safest place to do these flags */
case HANGUP
: /* shouldn't get here. */
(void)fprintf(stderr
, "Signal jump problem\n");
/* simulate the 'e' at startup */
(void)printf("%s", prompt_string
);
l_tempp
= start
= End
= NULL
;
start_default
= End_default
= 1;
* This isn't nice and alphabetical mainly because of
* restrictions with 'G' and 'V' (see ed(1)).
"command `%c' illegal in G/V", ss
);
(void)printf("%s\n", help_msg
);
printf("%?: %s\n", help_msg
);
set_mark(inputt
, errnum
);
/* In POSIX-land 'P' toggles the prompt. */
prompt_str_flg
= prompt_str_flg
? 0 : 1;
/* For 'p' to consume. */
if ((current
== bottom
) && (End
== NULL
)) {
strcpy(help_msg
, "at end of buffer");
current
= current
->below
;
* An EOF means 'q' unless we're still in the middle
* of a global command, in which case it was just the
* end of the command list found.
* Control of address forms from here down.
* It's a head-game to understand why ";" and "," look
* as they do below, but a lot of it has to do with ";"
* and "," being special address pair forms themselves
* and the compatibility for address "chains".
if (End_default
== 1 && start_default
== 1) {
start_default
= End_default
= 0;
* Note address ".,x" where x is a cmd is legal; not a
* bug - for backward compatability.
if (End_default
== 1 && start_default
== 1) {
start_default
= End_default
= 0;
"'%' is an address pair");
start_default
= End_default
= 0;
* Within address_conv => l_last = '+', foobar, but
* historical and now POSIX...
if (start_default
== 0 && End_default
== 0) {
l_tempp
= address_conv(l_tempp
, inputt
, errnum
);
*errnum
= address_check(start
, End
);
strcpy(help_msg
, "unknown command");
/* Things came out okay with the last command. */
/* Do the suffixes if there were any. */
/* Unlikely it's needed, but... */
/* There was a problem with the last command. */
errmsg
: while (((ss
= getc(inputt
)) != '\n') &&
printf("%?: %s\n", help_msg
);
* Exits ed and prints an appropriate message about the command line
* being malformed (see below).
(void)fprintf(stderr
, "ed: illegal option\n");
(void)fprintf(stderr
, "ed: missing promptstring\n");
(void)fprintf(stderr
, "ed: too many filenames\n");
(void)fprintf(stderr
, "ed: out of memory error\n");
(void)fprintf(stderr
, "ed: unable to create buffer\n");
(void)fprintf(stderr
, "ed: command line error\n");
"ed: ed [ -s ] [ -p promptstring ] [ filename ]\n");
* SIGINT is never turned off. We flag it happened and then pay attention
* to it at certain logical locations in the code we don't do more here
* cause some of our buffer pointer's may be in an inbetween state at the
* time of the SIGINT. So we flag it happened, let the local fn handle it
* and do a jump back to the cmd_loop
(void)fprintf(stderr
,"\n SIGHUP \n");