tenex.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,873 行 · 第 1/3 页

C
1,873
字号
			return (NULL);		return(context->curbfunc->bname);		}		else		if (dirctr == CMD_ALIAS)			return (getentry(VAR_WD,context,0));		/* Fall through */	case DIR_WD:		/* get a directory entry */		{		register struct direct *dirp;		/* read a directory entry. None: exit. */		if (dirp = readdir (context->dir_fd))		return (dirp -> d_name);		return (NULL);		}	case VAR_WD:		/* get a variable entry */		/* Get next variable in list. None: exit. */		return(NULL);	case HIST_WD:		/*		 Get the next non-negative entry in the history		 list.  Negative entries are "hidden".  None: exit.		*/		do		context->curhist = context->curhist->Hnext;		while (context->curhist && context->curhist->Hnum < 0);		return (context->curhist			? context->curhist->Hlex.next->word			: NULL);	}/* end switch(type) */}/* end getentry() *//*	remove_duplicates	Routine to remove adjacent duplicate entries from	a sorted list and return a count of unique items and	the width of the widest item.	Duplicate entries are moved to the bottom of the list.*/staticremove_duplicates(items, count, widest)char *items[];register int *widest;{	register char **ip, **op;	/* input and output pointers */	register int i = 0;	register char *old_item = NULL;	*widest = 0;		/* clear any old max value */	if (count == 0)		/* no entries: exit. */	return(0);	/*	 afd fix 09:	 old_item starts out as NULL, so we can't do a strcmp on it.	 So, prime the pump with the first item.	*/	ip = op = items;	*op++ = old_item = *ip;	/* copy ip to op and old_item */	*widest = strlen (*ip);	for (ip++; *ip; ip++)	{	/*	 If this is a duplicate, then release it and count	 it, otherwise move it to the proper place in the	 array and bump the output pointer to the next free	 slot; check for wider entry.	*/	if (strcmp(old_item,*ip) == 0)	/* ip is a duplicate */		{		free(*ip);			/* free the duplicate */		i++;			/* and keep a count of it */		}	else		{				/* ip is not a duplicate */		*op++ = old_item = *ip;	/* copy ip to op and old_item */		/* get the current max width */		*widest = max (*widest, strlen (*ip));		}	}/* end for "each item" */	/* copy the array terminator also */	*op++ = *ip;	return (count - i);			/* return number of unique entries */}/* end remove_duplicates *//*	print_by_column	Print columns that are sorted downwards.*/staticprint_by_column (dir, items, count, maxwidth, type)char *dir;register char *items[];{	register int w, i, r, c;	/* various indices */	register int rows;	int columns;	/*	 Add two spaces, one to separate columns and	 one to show the type of the file.  (file type	 only if this is a directory list.	*/	maxwidth += (type == DIR_WD) ? 2 : 1;	/*	 Determine the number of columns and rows.	 If this is a history listing or max item	 width is greater than the screen width,	 then assume one column.	*/	if (type == HIST_WD || maxwidth > SCREEN_WIDTH)	columns = 1;	else	columns = SCREEN_WIDTH / maxwidth;	rows = (count + (columns - 1)) / columns;	for (r = 0; r < rows; r++)	{	for (c = 0; c < columns; c++)		{		i = c * rows + r;		/* if it is valid, then print it */		if (i < count)		{		/* special output for history */		if (type == HIST_WD)			print_history(items[i], maxwidth);		else			{			csh_printf("%s", items[i]);		/* 012 RNF */			w = strlen (items[i]);			/*			 If this is a directory lookup, print			 filename followed by '/' or '*' or ' '			*/			if (type == DIR_WD)			{			putchar (filetype (dir, items[i]));			w++;			}			/* space between columns, if not last */			if (c < (columns - 1))			for (; w < maxwidth; w++)				putchar (' ');			}		}		}/* end for "each column" */	putchar('\n');	}/* end for "each row" */}/* end print_by_column() *//*	print_words	This routine prints the contents of a wordlist up to,	the specified maximum length.  If the wordlist exceeds this	max length, it is truncated and a FALSE value is returned	otherwise the routine returns TRUE.*/staticprint_words(start, end, maxlen)struct wordent *start, *end;register int maxlen;{	register char *wp;	/*	 print each character in the word separated by	 a space, until we exceed the maximum length or	 we run out of words.  Exceeding maximum length	 causes a FALSE return.	*/	for (;;maxlen--)	{	for (wp = start->word; *wp; wp++)		if (--maxlen <= 1)		return (FALSE);		else		putchar(*wp);	start = start->next;	if (start == end)		break;	putchar(' ');	}	return (TRUE);}/* end print_words() *//*	print_history	This routine will print the first history entry found in	the history list, with the rest of the history event text	appearing parentheses after the entry. 	item	points to a history keyword.	maxwidth 	is the width of the widest history keyword.*/staticprint_history(item, maxwidth)register char *item;{#define COLWID	2	register int colw;			/* used for column positioning */	register struct wordent *wp;	/* local word pointer */	register char *ep;			/* local entry pointer */	struct Hist *hp;			/* local history pointer */	/* add spaces to separate history word from contents */	maxwidth += COLWID;	/*	 Search the history list for each item and print 	 the first matching history entry in its entirety.	*/	hp = &Histlist;	do	ep = getentry(HIST_WD, &hp, 0);	while (ep && strcmp(ep,item));	/* If none exit, otherwise print it. */	if (ep == 0)	return;	csh_printf(" %s",ep);	/* print match word */		/* 012 RNF */	/*	 Print the (contents) column, if there is one.	*/	if ((wp = hp->Hlex.next->next) != hp->Hlex.prev)	{	for (colw = strlen(ep); colw < maxwidth; colw++)		putchar(' ');	/* Print as much of the contents as possible. */	putchar('(');	if (!print_words(	wp,				hp->Hlex.prev,				SCREEN_WIDTH - maxwidth - (COLWID + 2)))		csh_printf("...");	/* truncated */		/* 012 RNF */	putchar(')');	}}/* end print_history() *//*	free_items	Deallocate space for the specified item list.	Item list ends with a 0 entry.*/staticfree_items (items)register char **items;{	register int i;	/* free individual items */	for (i = 0; items[i]; i++)	free (items[i]);	/* free the vector itself */	free ((char*)items);}/* end free_items() *//*	FREE_ITEMS	Macro to properly call above.*/#define FREE_ITEMS(items)\{\	int omask;\	omask = sigblock(sigmask(SIGINT));\	free_items (items);\	items = NULL;\	(void) sigsetmask(omask);\}/*	FREE_DIR	Macro to release a directory*/#define FREE_DIR(fd)\{\	int omask;\	omask = sigblock(sigmask(SIGINT));\	closedir (fd);\	fd = NULL;\	(void) sigsetmask(omask);\}/*	get_dir_from_path	Only called when type == CMD_WD.	Get the next directory from the path list;	return ptr to next unstripped directory.	A path list is a list of directory paths separated	by colons or spaces.	Increments dirctr.  If it is non-negative,	then it extracts a directory from the path, otherwise it	just returns the path without change.*/char *get_dir_from_path (path, dir, dirctr, dirflag)char *path, dir[], *dirflag;int *dirctr;{	register char *d = dir;	/* 	 Increment the directory counter, if it	 is negative, then return path w/o change.	*/	if (++(*dirctr) < 0)	return (path);	/* skip past separators */	while (*path && (*path == ' ' || *path == ':'))	path++;	/* Copy the dir name */	while (*path && (*path != ' ' && *path != ':'))	*(d++) = *(path++);	*(d++) = '/';	/* put a trailing slash on the path */	*d = 0;	/* Skip past the next separator */	while (*path && (*path == ' ' || *path == ':'))	path++;	if (*dir == '.')		strcpy (dirflag, " .");	else	{		*dirflag++ = ' ';	if (*dirctr <= 9)		*dirflag++ = '0' + *dirctr;	else		{		*dirflag++ = '0' + *dirctr / 10;		*dirflag++ = '0' + *dirctr % 10;		}	*dirflag++ = '\0';	}	return (path);}/* end get_dir_from_path() *//*	item_search	The heart of the tenex module.	Perform a RECOGNIZE or LIST command on string "word".*/staticitem_search (word, wp, command, routine, max_word_length, looking_for_command)char   *word, *wp;	/* original start and end-of-word */COMMAND command;	/* action: list or recognize */int (*routine) ();{	register numitems,		name_length,	/* Length of prefix (file name) */		findtype;	/* The kind of item to search for */	int 	showpathn;	/* True if we want path number */	struct stat		dot_statb,	/* Stat buffer for "." */		curdir_statb;	/* Stat buffer for current directory */	int	dot_scan,	/* True if scanning "." */		dot_got;	/* True if have scanned dot already */	int  dirctr = 0;	/* -2,-1 (for BUILTINS), 0,1,2 ...(for dirlist pos)*/	char dirflag[5];	/*  ' nn\0' - dir #s -  . 1 2 ... */	char *getentry();	char    tilded_dir[FILSIZ + 1],	 /* dir after ~ expansion */		dir[FILSIZ + 1],	 /* /x/y/z/ part in /x/y/z/f */		name[MAXNAMLEN + 1],	 /* f part in /d/d/d/f */	      extended_name[MAXNAMLEN+1],/* the recognized (extended) name */	        *entry,		/* single directory entry or logname */		*path;		/* hacked PATH environment variable */	union entry_context context;	/* entry context, used all over */	static char **items;		/* list of found entries */	context.dir_fd = NULL;		/* initialize the context */	/* decide what we're looking for */	switch (*word)	{	case '$':			/* variable name */		findtype = VAR_WD;		return(0);		/* NOTREACHED */		break;	case '~':			/* login names */		if (index(word,'/') == NULL)		{		findtype = LNAM_WD;		break;		}		/* Fall through if not LNAM */		default:			/* hist expansion */		/*		 HIST_WD check is processed here because		 HIST is not a constant expression and		 so cannot be part of a case.		*/		if (*word == HIST)		/* hist expansion */		findtype = HIST_WD;		else		if (looking_for_command) /* command position? */			findtype = CMD_WD;		else			findtype = DIR_WD; /* Default: dir search */		break;	}/* end switch (type) */	/*	 If the user has specified a directory then	 don't do command path searching, but do	 normal directory searching.	*/	if (findtype == CMD_WD && index(word,'/'))	findtype = DIR_WD;			/*	 Special setup for command search.	 Setup for BUILTINs and aliases.	*/	if (findtype == CMD_WD)	{	dirctr = CMD_BUILTIN; 	/* set BUILTINS code */	dirflag[0] = NULL;	/* get the current path for command searching */	if ((path = getenv("PATH")) == NULL)		path = "";	}	numitems = 0;	dot_got = FALSE;	/* afd fix 09: This must be explicitly initialized (it wasn't on VAX) */	dot_scan = FALSE;	stat (".", &dot_statb);	do		/* One loop per directory in PATH, if findtype == CMD_WD */	{	/*	 Perform the necessary item source	 initializations.	*/	switch (findtype)		{		case LNAM_WD:		 /* login names */		/*		 Open pw file,		 copy word w/o '~'		*/		setpwent ();		copyn (name, &word[1], MAXNAMLEN);		break;		case DIR_WD:		/* Normal dir search */		/*		 Expand the given directory		 and open it, if valid.		*/		extract_dir_and_name (word, dir, name);		if (!tilde(tilded_dir, dir)			   || !(context.dir_fd = opendir (*tilded_dir ? tilded_dir : ".")))			return (0);		dot_scan = FALSE;		break;		case CMD_WD:		/* Command keyword */		switch (dirctr)			{			case CMD_BUILTIN:			/*			 Set flag, name and context			 for builtin function names.			 Context is set one entry back			 because getentry() always increments			 the context ptr prior to access.			*/			strcpy(dirflag," -");			copyn(name,word,MAXNAMLEN);			context.curbfunc = &bfunc[-1];			bfuncnum = 0;			break;			case CMD_ALIAS:			/*			 Set flag, name and context for			 aliases.  Alise structure is			 identical to variable structure,			 but with a different head.			*/			strcpy(dirflag," +");			copyn(name,word,MAXNAMLEN);			context.curvar = &aliases;			break;			default:			/*			 Expand the passed name,			 open dir, if valid			 get next path dir if not valid.			*/			if (!tilde(tilded_dir, dir)				   || !(context.dir_fd = opendir (*tilded_dir				  				 ? tilded_dir							 : ".")))				continue;			dot_scan = FALSE;			/* Are we searching "."? */			fstat (context.dir_fd->dd_fd, &curdir_statb);			if (curdir_statb.st_dev == dot_statb.st_dev				&& curdir_statb.st_ino == dot_statb.st_ino)				{				if (dot_got)	/* Second time in PATH? */				continue;				dot_scan = TRUE;				dot_got = TRUE;				}			break;			}/* end switch (dirctr) */		break;		case VAR_WD:		/* Variable names */		/*		 Copy name w/o '$'.		 Init the current variable ptr		 to the head of the sorted list.		*/		copyn (name, &word[1], MAXNAMLEN);		context.curvar = &shvhed;		break;		case HIST_WD:		/* History keywords */		/*		 Copy the name w/o HIST char.		 Init the current variable ptr		 to the head of the history list.		 Entries are in "most recent" order.		*/		copyn (name, &word[1], MAXNAMLEN);		context.curhist = &Histlist;		break;		}/* end switch (findtype) */	name_length = strlen (name);	showpathn = findtype == CMD_WD && is_set("listpathnum");	/*	 Search the source lists for items that	 match the user's typed in word.	*/	while (	entry = getentry (findtype, &context, dirctr)) 	{		if (!is_prefix (name, entry))		continue;		/*

⌨️ 快捷键说明

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