138 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* Copyright (c) 1985 Ceriel J.H. Jacobs */
 | 
						|
 | 
						|
# ifndef lint
 | 
						|
static char rcsid[] = "$Header$";
 | 
						|
# endif
 | 
						|
 | 
						|
# define _MACHINE_
 | 
						|
 | 
						|
# include <ctype.h>
 | 
						|
# include "in_all.h"
 | 
						|
# include "machine.h"
 | 
						|
# include "getline.h"
 | 
						|
# include "assert.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * Add part of finite state machine to recognize the string s.
 | 
						|
 */
 | 
						|
 | 
						|
STATIC int
 | 
						|
addtomach(s, cnt, list) char *s; struct state **list; {
 | 
						|
 | 
						|
	register struct state *l;
 | 
						|
	register int i = FSM_OKE;	/* Return value */
 | 
						|
	register int j;
 | 
						|
 | 
						|
	for (;;) {
 | 
						|
		l = *list;
 | 
						|
		if (!l) {
 | 
						|
			/*
 | 
						|
			 * Create new list element
 | 
						|
			 */
 | 
						|
			*list = l = (struct state *) alloc(sizeof(*l), 0);
 | 
						|
			l->s_char = *s;
 | 
						|
			l->s_endstate = 0;
 | 
						|
			l->s_match = 0;
 | 
						|
			l->s_next = 0;
 | 
						|
		}
 | 
						|
		if (l->s_char == *s) {
 | 
						|
			/*
 | 
						|
			 * Continue with next character
 | 
						|
			 */
 | 
						|
			if (!*++s) {
 | 
						|
				/*
 | 
						|
				 * No next character
 | 
						|
				 */
 | 
						|
				j = l->s_endstate;
 | 
						|
				l->s_endstate = 1;
 | 
						|
				if (l->s_match || j) {
 | 
						|
					/*
 | 
						|
					 * If the state already was an endstate,
 | 
						|
					 * or has a successor, the currently
 | 
						|
					 * added string is a prefix of an
 | 
						|
					 * already recognized string
 | 
						|
					 */
 | 
						|
					return FSM_ISPREFIX;
 | 
						|
				}
 | 
						|
				l->s_cnt = cnt;
 | 
						|
				return i;
 | 
						|
			}
 | 
						|
			if (l->s_endstate) {
 | 
						|
				/*
 | 
						|
				 * In this case, the currently added string has
 | 
						|
				 * a prefix that is an already recognized
 | 
						|
				 * string.
 | 
						|
				 */
 | 
						|
				i = FSM_HASPREFIX;
 | 
						|
			}
 | 
						|
			list = &(l->s_match);
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		list = &(l->s_next);
 | 
						|
	}
 | 
						|
	/* NOTREACHED */
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Add a string to the FSM.
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
addstring(s,cnt,machine) register char *s; struct state **machine; {
 | 
						|
 | 
						|
	if (!s || !*s) {
 | 
						|
		return FSM_ISPREFIX;
 | 
						|
	}
 | 
						|
	return addtomach(s,cnt,machine);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Match string s with the finite state machine.
 | 
						|
 * If it matches, the number of characters actually matched is returned,
 | 
						|
 * and the count is put in the word pointed to by i.
 | 
						|
 * If the string is a prefix of a string that could be matched,
 | 
						|
 * FSM_ISPREFIX is returned. Otherwise, 0 is returned.
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
match(s,i,mach) char *s; int *i; register struct state *mach; {
 | 
						|
 | 
						|
	register char *s1 = s;	/* Walk through string */
 | 
						|
	register struct state *mach1 = 0;
 | 
						|
				/* Keep track of previous state */
 | 
						|
 | 
						|
	while (mach && *s1) {
 | 
						|
		if (mach->s_char == *s1) {
 | 
						|
			/*
 | 
						|
			 * Current character matches. Carry on with next
 | 
						|
			 * character and next state
 | 
						|
			 */
 | 
						|
			mach1 = mach;
 | 
						|
			mach = mach->s_match;
 | 
						|
			s1++;
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
		mach = mach->s_next;
 | 
						|
	}
 | 
						|
	if (!mach1) {
 | 
						|
		/*
 | 
						|
		 * No characters matched
 | 
						|
		 */
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	if (mach1->s_endstate) {
 | 
						|
		/*
 | 
						|
		 * The string matched
 | 
						|
		 */
 | 
						|
		*i = mach1->s_cnt;
 | 
						|
		return s1 - s;
 | 
						|
	}
 | 
						|
	if (!*s1) {
 | 
						|
		/*
 | 
						|
		 * The string matched a prefix
 | 
						|
		 */
 | 
						|
		return FSM_ISPREFIX;
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 |