⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 extend.c

📁 早期freebsd实现
💻 C
字号:
/*************************************************************************** * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE * * is provided to you without charge, and with no warranty.  You may give  * * away copies of JOVE, including sources, provided that this notice is    * * included in all the files.                                              * ***************************************************************************/#include "jove.h"#include "fp.h"#include "termcap.h"#include "ctype.h"#include "chars.h"#include "disp.h"#include "re.h"#ifdef	IPROCS# include <signal.h>#endif#ifdef	MAC# include "mac.h"#else# ifdef	STDARGS#  include <stdarg.h># else#  include <varargs.h># endif#endif#ifdef	MSDOS# include <process.h>#endifprivate void	DefAutoExec proto((struct data_obj *(*proc) ptrproto((const char *))));private int	match proto((char **, char *));int	InJoverc = 0;/* Auto execute code */#define NEXECS	20private struct {	char	*a_pattern;	data_obj	*a_cmd;} AutoExecs[NEXECS];	/* must be initialized by system to 0 */private int	ExecIndex = 0;/* Command auto-execute. */voidCAutoExec(){	DefAutoExec(findcom);}/* Macro auto-execute. */voidMAutoExec(){	DefAutoExec(findmac);}private voidDefAutoExec(proc)data_obj	*(*proc) ptrproto((const char *));{	data_obj	*d;	char	*pattern;	int	i;	if (ExecIndex >= NEXECS)		complain("Too many auto-executes, max %d.", NEXECS);	if ((d = (*proc)(ProcFmt)) == NULL)		return;	pattern = do_ask("\r\n", (bool (*) ptrproto((int))) NULL, (char *) NULL, ": %f %s ",		d->Name);	for (i = 0; i < ExecIndex; i++) {	    if (AutoExecs[i].a_cmd == d) {		char    *ipat = AutoExecs[i].a_pattern;		if ((pattern == NULL || ipat == NULL)?		    (pattern == ipat) : (strcmp(pattern, ipat) == 0))			return;		/* eliminate duplicates */	    }	}	AutoExecs[ExecIndex].a_pattern = copystr(pattern);	AutoExecs[ExecIndex].a_cmd = d;	ExecIndex += 1;}/* DoAutoExec: NEW and OLD are file names, and if NEW and OLD aren't the   same kind of file (i.e., match the same pattern) or OLD is NULL and it   matches, OR if the pattern is NULL (none was specified) then, we execute   the command associated with that kind of file. */voidDoAutoExec(new, old)register char	*new,		*old;{	register int	i;	set_arg_value(1);	for (i = 0; i < ExecIndex; i++)		if ((AutoExecs[i].a_pattern == NULL) ||		    ((new != NULL && LookingAt(AutoExecs[i].a_pattern, new, 0)) &&		     (old == NULL || !LookingAt(AutoExecs[i].a_pattern, old, 0))))			ExecCmd(AutoExecs[i].a_cmd);}intaddgetc(){	int	c;	if (!InJoverc) {		Asking = YES;		AskingWidth = strlen(mesgbuf);		c = getch();		Asking = NO;		add_mess("%p ", c);	} else {		c = getch();		if (c == '\n')			return EOF;	/* this isn't part of the sequence */		else if (c == '\\') {			if ((c = getch()) == LF)				complain("[Premature end of line]");		} else if (c == '^') {			if ((c = getch()) == '?')				c = RUBOUT;			else if (jisalpha(c) || strchr("@[\\]^_", c))				c = CTL(c);			else				complain("[Unknown control character]");		}	}	return c;}voidExtend(){	data_obj	*d;	if ((d = findcom(": ")) != NULL)		ExecCmd(d);}/* Read a positive integer from CP.  It must be in base BASE, and   complains if it isn't.  If allints is nonzero, all the characters   in the string must be integers or we return -1; otherwise we stop   reading at the first nondigit. */intchr_to_int(cp, base, allints, result)register char	*cp;int	base,	allints;register int	*result;{	register int	c;	int	value = 0,		sign;	if ((c = *cp) == '-') {		sign = -1;		cp += 1;	} else		sign = 1;	while ((c = *cp++) != '\0') {		if (!jisdigit(c)) {			if (allints == YES)				return INT_BAD;			break;		}		c = c - '0';		if (c >= base)			complain("You must specify in base %d.", base);		value = value * base + c;	}	*result = value * sign;	return INT_OKAY;}intask_int(prompt, base)char	*prompt;int	base;{	char	*val = ask((char *)NULL, prompt);	int	value;	if (chr_to_int(val, base, YES, &value) == INT_BAD)		complain("That's not a number!");	return value;}voidvpr_aux(vp, buf, size)register const struct variable	*vp;char	*buf;size_t	size;{	switch (vp->v_flags & V_TYPEMASK) {	case V_BASE10:		swritef(buf, size, "%d", *((int *) vp->v_value));		break;	case V_BASE8:		swritef(buf, size, "%o", *((int *) vp->v_value));		break;	case V_BOOL:		swritef(buf, size, (*((int *) vp->v_value)) ? "on" : "off");		break;	case V_STRING:	case V_FILENAME:		swritef(buf, size, "%s", vp->v_value);		break;	case V_CHAR:		swritef(buf, size, "%p", *((int *) vp->v_value));		break;	}}voidPrVar(){	struct variable	*vp;	char	prbuf[256];	if ((vp = (struct variable *) findvar(ProcFmt)) == NULL)		return;	vpr_aux(vp, prbuf, sizeof(prbuf));	s_mess(": %f %s => %s", vp->Name, prbuf);}voidSetVar(){	struct variable	*vp;	char	prompt[128];	if ((vp = (struct variable *) findvar(ProcFmt)) == NULL)		return;	swritef(prompt, sizeof(prompt), ": %f %s ", vp->Name);	switch (vp->v_flags & V_TYPEMASK) {	case V_BASE10:	case V_BASE8:		*((int *) vp->v_value) = ask_int(prompt,		    ((vp->v_flags & V_TYPEMASK) == V_BASE10)? 10 : 8);		break;	case V_BOOL:	    {		char	*def = *((bool *) vp->v_value) ? "off" : "on",			*on_off;		bool	value;		on_off = ask(def, prompt);		if (casecmp(on_off, "on") == 0)			value = ON;		else if (casecmp(on_off, "off") == 0)			value = OFF;		else {			complain("Boolean variables must be ON or OFF.");			/* NOTREACHED */		}		*((bool *) vp->v_value) = value;#ifdef	MAC		MarkVar(vp,-1,0);	/* mark the menu item */#endif		s_mess("%s%s", prompt, value ? "on" : "off");		break;	    }	case V_FILENAME:	    {		char	fbuf[FILESIZE];		size_t	pl = strlen(prompt);		swritef(&prompt[pl], sizeof(prompt)-pl, "(default %s) ",			(char *)vp->v_value);		(void) ask_file(prompt, (char *) vp->v_value, fbuf);		strcpy((char *) vp->v_value, fbuf);		break;	    }	case V_STRING:	    {		char	*str;		/* Do_ask() so you can set string to "" if you so desire. */		str = do_ask("\r\n", (bool (*) ptrproto((int))) NULL,			(char *) vp->v_value, prompt);		if (str == NULL)			str = NullStr;		strcpy((char *) vp->v_value, str);		/* ... and hope there is enough room. */		break;	    }	case V_CHAR:		f_mess(prompt);		*((int *) vp->v_value) = addgetc();		break;	}	if (vp->v_flags & V_MODELINE)		UpdModLine = YES;	if (vp->v_flags & V_CLRSCREEN) {#ifdef	IBMPC		setcolor(Fgcolor, Bgcolor);#endif	/* IBMPC */		ClAndRedraw();	}	if (vp->v_flags & V_TTY_RESET)		tty_reset();}/* Command completion - possible is an array of strings, prompt is   the prompt to use, and flags are ... well read jove.h.   If flags are RET_STATE, and the user hits <return> what they typed   so far is in the Minibuf string. */private char	**Possible;private int	comp_value,		comp_flags;private boolaux_complete(c)int	c;{	int	command,		i;	if (comp_flags & CASEIND) {		char	*lp;		for (lp = linebuf; *lp != '\0'; lp++)			if (jisupper(*lp))				*lp = jtolower(*lp);	}	switch (c) {	case EOF:		comp_value = -1;		return FALSE;	case '\r':	case '\n':		command = match(Possible, linebuf);		if (command >= 0) {			comp_value = command;			return FALSE;	/* tells ask to stop */		}		if (eolp() && bolp()) {			comp_value = NULLSTRING;			return FALSE;		}		if (comp_flags & RET_STATE) {			comp_value = command;			return FALSE;		}		if (InJoverc)			complain("[\"%s\" unknown]", linebuf);		rbell();		break;	case '\t':	case ' ':	    {		int	minmatch = 1000,			maxmatch = 0,			numfound = 0,			lastmatch = -1,			len = strlen(linebuf);		for (i = 0; Possible[i] != 0; i++) {			int	this_len;			this_len = numcomp(Possible[i], linebuf);			maxmatch = max(maxmatch, this_len);			if (this_len >= len) {				if (numfound)					minmatch = min(minmatch, numcomp(Possible[lastmatch], Possible[i]));				else					minmatch = strlen(Possible[i]);				numfound += 1;				lastmatch = i;				if (strcmp(linebuf, Possible[i]) == 0)					break;			}		}		if (numfound == 0) {			rbell();			if (InJoverc)				complain("[\"%s\" unknown]", linebuf);			/* If we're not in the .joverc then			   let's do something helpful for the			   user. */			if (maxmatch < len) {				char	*cp;				cp = linebuf + maxmatch;				*cp = '\0';				Eol();			}			break;		}		if (c != '\t' && numfound == 1) {			comp_value = lastmatch;			return FALSE;		}		null_ncpy(linebuf, Possible[lastmatch], (size_t) minmatch);		Eol();		if (minmatch == len)	/* No difference */			rbell();		break;	    }	case '?':		{		int	len;		if (InJoverc)			complain((char *)NULL);		/* kludge: in case we're using UseBuffers, in which case		   linebuf gets written all over */		strcpy(Minibuf, linebuf);		len = strlen(Minibuf);		TOstart("Completion", TRUE);	/* for now ... */		for (i = 0; Possible[i]; i++)			if (numcomp(Possible[i], Minibuf) >= len) {				Typeout(Possible[i]);				if (TOabort)					break;			}		TOstop();		}		break;	}	return TRUE;}intcomplete(possible, prompt, flags)register char	*possible[];const char	*prompt;int	flags;{	/* protect static "Possible" from being overwritten due to recursion */	if (InRealAsk)		complain((char *) NULL);	Possible = possible;	comp_flags = flags;	(void) do_ask("\r\n \t?", aux_complete, NullStr, prompt);	return comp_value;}private intmatch(choices, what)register char	**choices,		*what;{	register size_t	len;	int	i,		found = 0,		save = ORIGINAL,		exactmatch = -1;	len = strlen(what);	if (len == 0)		return NULLSTRING;	for (i = 0; choices[i]; i++) {		if (strncmp(what, choices[i], len) == 0) {			if (choices[i][len] == '\0')				exactmatch = i;			save = i;			found += 1;	/* found one */		}	}	if (found > 1) {		if (exactmatch != -1)			save = exactmatch;		else			save = AMBIGUOUS;	}	return save;}voidSource(){	char	*com,		buf[FILESIZE];#ifndef	MSDOS	swritef(buf, sizeof(buf), "%s/.joverc", HomeDir);#else	/* MSDOS */	if (com = getenv("JOVERC"))		strcpy(buf, com);	else		strcpy(buf, Joverc);#endif	/* MSDOS */	com = ask_file((char *)NULL, buf, buf);	if (!joverc(buf))		complain(IOerr("read", com));}voidBufPos(){	register Line	*lp = curbuf->b_first;	register int	i,			dotline;	long	dotchar,		nchars;	for (i = nchars = 0; lp != NULL; i++, lp = lp->l_next) {		if (lp == curline) {			dotchar = nchars + curchar;			dotline = i + 1;		}		nchars += length(lp) + (lp->l_next != NULL); /* include the NL */	}	s_mess("[\"%s\" line %d/%d, char %D/%D (%d%%), cursor = %d/%d]",	       filename(curbuf), dotline, i, dotchar, nchars,	       (nchars == 0) ? 100 : (int) (((long) dotchar * 100) / nchars),	       calc_pos(linebuf, curchar),	       calc_pos(linebuf, (int)strlen(linebuf)));}#ifndef	MACprivate intdo_if(cmd)char	*cmd;{	int status;	char	*args[12];	{		char	*cp = cmd,			**ap = args;		for (;;) {			while (*cp == ' ')			    cp++;			*ap++ = cp;			if ((cp = strchr(cp, ' ')) == NULL)				break;			*cp++ = '\0';		}		ap[-1] = NULL;	}#ifndef	MSDOS	{		int	pid;		switch (pid = fork()) {		case -1:			complain("[Fork failed: if: %s]", strerror(errno));			/*NOTREACHED*/		case 0:			close(0);	/*	we want reads to fail */			/* close(1);	 but not writes or ioctl's			close(2);    */			(void) execvp(args[0], (const char **)args);			_exit(-10);	/* signals exec error (see below) */			/*NOTREACHED*/		}#ifdef	IPROCS		SigHold(SIGCHLD);#endif		dowait(pid, &status);#ifdef	IPROCS		SigRelse(SIGCHLD);#endif		if (status == -10)			complain("[Exec failed]");		if (status < 0)			complain("[Exit %d]", status);	}#else	/* MSDOS */	if ((status = spawnvp(0, args[0], args)) < 0)		complain("[Spawn failed: if]");#endif	/* MSDOS */	return (status == 0);	/* 0 means successful */}#endif	/* MAC */booljoverc(file)char	*file;{	char	buf[LBSIZE],		lbuf[LBSIZE];	jmp_buf	savejmp;	volatile int	lnum = 0;	File	*volatile fp;	volatile bool	eof;	volatile unsigned int	/* bitstrings */			finger = 1,			skipping = 0,			inelse = 0;	fp = open_file(file, buf, F_READ, NO, YES);	if (fp == NULL)		return NO;	/* joverc returns an integer */	/* Catch any errors, here, and do the right thing with them,	   and then restore the error handle to whoever did a setjmp	   last. */	InJoverc += 1;	push_env(savejmp);	if (setjmp(mainjmp)) {		Buffer	*savebuf = curbuf;		SetBuf(do_select((Window *)NULL, "RC errors"));		ins_str(sprint("%s:%d:%s", pr_name(file, YES), lnum, lbuf), NO);		ins_str(sprint("\t%s\n", mesgbuf), NO);		unmodify();		SetBuf(savebuf);		Asking = NO;	}	do {		/* This peculiar delayed EOF testing allows the last line to		 * end without a NL.  We add NL later, so we leave room for it.		 */		eof = f_gets(fp, lbuf, sizeof(lbuf)-1);		lnum += 1;		Inputp = lbuf;		while (*Inputp == ' ' || *Inputp == '\t')			Inputp += 1;	/* skip white space */		if (*Inputp == '#') {			/* a comment */#ifndef	MAC		} else if (casencmp(Inputp, "if", (size_t)2) == 0) {			finger <<= 1;			if (finger == 0)				complain("[`if' nested too deeply]");			if (LookingAt("ifenv\\>[ \t]*\\<\\([^ \t][^ \t]*\\)\\>[ \t]\\(.*\\)$", Inputp, 0)) {				if (skipping == 0) {					char	envname[128],						envpat[128],						*envval;					putmatch(1, envname, sizeof envname);					putmatch(2, envpat, sizeof envpat);					envval = getenv(envname);					if (envval==NULL || !LookingAt(envpat, envval, 0))						skipping |= finger;				}			} else if (LookingAt("if\\>[ \t]*\\(.*\\)$", Inputp, 0)) {				char	cmd[128];				putmatch(1, cmd, sizeof cmd);				if (skipping == 0 && !do_if(cmd))					skipping |= finger;			} else {				complain("[`if' syntax error]");			}		} else if (casecmp(Inputp, "else") == 0) {			if (finger == 1 || (inelse & finger))				complain("[Unexpected `else']");			inelse |= finger;			skipping ^= finger;		} else if (casecmp(Inputp, "endif") == 0) {			if (finger == 1)				complain("[Unexpected `endif']");			inelse &= ~finger;			skipping &= ~finger;			finger >>= 1;#endif		} else if (skipping == 0) {			(void) strcat(Inputp, "\n");			Extend();			if (Inputp) {				while (*Inputp == ' ' || *Inputp == '\t')					Inputp += 1;	/* skip white space */				if (*Inputp!='\0' && *Inputp!='\n')					complain("[junk at end of line]");			}		}	} while (!eof);	f_close(fp);	pop_env(savejmp);	Inputp = NULL;	Asking = NO;	InJoverc -= 1;	if (finger != 1)		complain("[Missing endif]");	return YES;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -