main machine.c
  1/* Copyright (c) 1985 Ceriel J.H. Jacobs */
  2
  3#include <ctype.h>
  4#include "in_all.h"
  5#include "machine.h"
  6#include "getline.h"
  7#include "assert.h"
  8
  9/*
 10 * Add part of finite state machine to recognize the string s.
 11 */
 12
 13static int
 14addtomach(char *s, int cnt, struct state **list)
 15{
 16
 17	struct state *l;
 18	int i = FSM_OKE; /* Return value */
 19	int j;
 20
 21	for (;;) {
 22		l = *list;
 23		if (!l) {
 24			/*
 25			 * Create new list element
 26			 */
 27			*list = l = (struct state *)alloc(sizeof(*l));
 28			l->s_char = *s;
 29			l->s_endstate = 0;
 30			l->s_match = 0;
 31			l->s_next = 0;
 32		}
 33		if (l->s_char == *s) {
 34			/*
 35			 * Continue with next character
 36			 */
 37			if (!*++s) {
 38				/*
 39				 * No next character
 40				 */
 41				j = l->s_endstate;
 42				l->s_endstate = 1;
 43				if (l->s_match || j) {
 44					/*
 45					 * If the state already was an endstate,
 46					 * or has a successor, the currently
 47					 * added string is a prefix of an
 48					 * already recognized string
 49					 */
 50					return FSM_ISPREFIX;
 51				}
 52				l->s_cnt = cnt;
 53				return i;
 54			}
 55			if (l->s_endstate) {
 56				/*
 57				 * In this case, the currently added string has
 58				 * a prefix that is an already recognized
 59				 * string.
 60				 */
 61				i = FSM_HASPREFIX;
 62			}
 63			list = &(l->s_match);
 64			continue;
 65		}
 66		list = &(l->s_next);
 67	}
 68	/* NOTREACHED */
 69}
 70
 71/*
 72 * Add a string to the FSM.
 73 */
 74
 75int
 76addstring(char *s, int cnt, struct state **machine)
 77{
 78
 79	if (!s || !*s) {
 80		return FSM_ISPREFIX;
 81	}
 82	return addtomach(s, cnt, machine);
 83}
 84
 85/*
 86 * Match string s with the finite state machine.
 87 * If it matches, the number of characters actually matched is returned,
 88 * and the count is put in the word pointed to by i.
 89 * If the string is a prefix of a string that could be matched,
 90 * FSM_ISPREFIX is returned. Otherwise, 0 is returned.
 91 */
 92
 93int
 94match(char *s, int *i, struct state *mach)
 95{
 96
 97	char *s1 = s; /* Walk through string */
 98	struct state *mach1 = 0;
 99	/* Keep track of previous state */
100
101	while (mach && *s1) {
102		if (mach->s_char == *s1) {
103			/*
104			 * Current character matches. Carry on with next
105			 * character and next state
106			 */
107			mach1 = mach;
108			mach = mach->s_match;
109			s1++;
110			continue;
111		}
112		mach = mach->s_next;
113	}
114	if (!mach1) {
115		/*
116		 * No characters matched
117		 */
118		return 0;
119	}
120	if (mach1->s_endstate) {
121		/*
122		 * The string matched
123		 */
124		*i = mach1->s_cnt;
125		return s1 - s;
126	}
127	if (!*s1) {
128		/*
129		 * The string matched a prefix
130		 */
131		return FSM_ISPREFIX;
132	}
133	return 0;
134}