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