1 1.18 rillig /* $NetBSD: parse.c,v 1.18 2021/05/02 12:50:43 rillig Exp $ */ 2 1.3 cgd 3 1.1 cgd /* 4 1.3 cgd * Copyright (c) 1983, 1993 5 1.3 cgd * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.13 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.5 lukem #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.3 cgd #if 0 35 1.4 tls static char sccsid[] = "@(#)parse.c 8.2 (Berkeley) 4/28/95"; 36 1.3 cgd #else 37 1.18 rillig __RCSID("$NetBSD: parse.c,v 1.18 2021/05/02 12:50:43 rillig Exp $"); 38 1.3 cgd #endif 39 1.6 lukem #endif /* not lint */ 40 1.1 cgd 41 1.4 tls #include "extern.h" 42 1.1 cgd 43 1.11 jsm #define HASHSIZE 256 44 1.11 jsm #define HASHMUL 81 45 1.11 jsm #define HASHMASK (HASHSIZE - 1) 46 1.11 jsm 47 1.14 jsm static int hash(const char *); 48 1.14 jsm static void install(struct wlist *); 49 1.14 jsm static struct wlist *lookup(const char *); 50 1.11 jsm 51 1.11 jsm static struct wlist *hashtab[HASHSIZE]; 52 1.10 jsm 53 1.5 lukem void 54 1.15 jmc wordinit(void) 55 1.1 cgd { 56 1.5 lukem struct wlist *w; 57 1.1 cgd 58 1.1 cgd for (w = wlist; w->string; w++) 59 1.1 cgd install(w); 60 1.1 cgd } 61 1.1 cgd 62 1.10 jsm static int 63 1.15 jmc hash(const char *s) 64 1.1 cgd { 65 1.6 lukem int hashval = 0; 66 1.1 cgd 67 1.1 cgd while (*s) { 68 1.1 cgd hashval += *s++; 69 1.1 cgd hashval *= HASHMUL; 70 1.1 cgd hashval &= HASHMASK; 71 1.1 cgd } 72 1.1 cgd return hashval; 73 1.1 cgd } 74 1.1 cgd 75 1.10 jsm static struct wlist * 76 1.15 jmc lookup(const char *s) 77 1.1 cgd { 78 1.5 lukem struct wlist *wp; 79 1.1 cgd 80 1.1 cgd for (wp = hashtab[hash(s)]; wp != NULL; wp = wp->next) 81 1.1 cgd if (*s == *wp->string && strcmp(s, wp->string) == 0) 82 1.1 cgd return wp; 83 1.1 cgd return NULL; 84 1.1 cgd } 85 1.1 cgd 86 1.10 jsm static void 87 1.15 jmc install(struct wlist *wp) 88 1.1 cgd { 89 1.6 lukem int hashval; 90 1.1 cgd 91 1.1 cgd if (lookup(wp->string) == NULL) { 92 1.1 cgd hashval = hash(wp->string); 93 1.1 cgd wp->next = hashtab[hashval]; 94 1.1 cgd hashtab[hashval] = wp; 95 1.1 cgd } else 96 1.1 cgd printf("Multiply defined %s.\n", wp->string); 97 1.1 cgd } 98 1.1 cgd 99 1.5 lukem void 100 1.15 jmc parse(void) 101 1.1 cgd { 102 1.5 lukem struct wlist *wp; 103 1.6 lukem int n; 104 1.8 jsm int flag; 105 1.1 cgd 106 1.6 lukem wordnumber = 0; /* for cypher */ 107 1.1 cgd for (n = 0; n <= wordcount; n++) { 108 1.1 cgd if ((wp = lookup(words[n])) == NULL) { 109 1.1 cgd wordvalue[n] = -1; 110 1.1 cgd wordtype[n] = -1; 111 1.1 cgd } else { 112 1.6 lukem wordvalue[n] = wp->value; 113 1.6 lukem wordtype[n] = wp->article; 114 1.1 cgd } 115 1.8 jsm } 116 1.9 jsm /* We never use adjectives for anything, so yank them all. */ 117 1.9 jsm for (n = 1; n < wordcount; n++) 118 1.9 jsm if (wordtype[n] == ADJS) { 119 1.9 jsm int i; 120 1.9 jsm for (i = n + 1; i < wordcount; i++) { 121 1.9 jsm wordtype[i - 1] = wordtype[i]; 122 1.9 jsm wordvalue[i - 1] = wordvalue[i]; 123 1.17 fox strlcpy(words[i - 1], words[i], WORDLEN); 124 1.9 jsm } 125 1.9 jsm wordcount--; 126 1.9 jsm } 127 1.8 jsm /* Don't let a comma mean AND if followed by a verb. */ 128 1.8 jsm for (n = 0; n < wordcount; n++) 129 1.8 jsm if (wordvalue[n] == AND && words[n][0] == ',' 130 1.8 jsm && wordtype[n + 1] == VERB) { 131 1.8 jsm wordvalue[n] = -1; 132 1.8 jsm wordtype[n] = -1; 133 1.8 jsm } 134 1.8 jsm /* Trim "AND AND" which can happen naturally at the end of a 135 1.8 jsm * comma-delimited list. 136 1.8 jsm */ 137 1.8 jsm for (n = 1; n < wordcount; n++) 138 1.8 jsm if (wordvalue[n - 1] == AND && wordvalue[n] == AND) { 139 1.8 jsm int i; 140 1.8 jsm for (i = n + 1; i < wordcount; i++) { 141 1.8 jsm wordtype[i - 1] = wordtype[i]; 142 1.8 jsm wordvalue[i - 1] = wordvalue[i]; 143 1.17 fox strlcpy(words[i - 1], words[i], WORDLEN); 144 1.8 jsm } 145 1.8 jsm wordcount--; 146 1.8 jsm } 147 1.8 jsm 148 1.8 jsm /* If there is a sequence (NOUN | OBJECT) AND EVERYTHING 149 1.8 jsm * then move all the EVERYTHINGs to the beginning, since that's where 150 1.8 jsm * they're expected. We can't get rid of the NOUNs and OBJECTs in 151 1.12 wiz * case they aren't in EVERYTHING (i.e. not here or nonexistent). 152 1.8 jsm */ 153 1.8 jsm flag = 1; 154 1.8 jsm while (flag) { 155 1.8 jsm flag = 0; 156 1.8 jsm for (n = 1; n < wordcount; n++) 157 1.18 rillig if ((wordtype[n - 1] == NOUNS || 158 1.15 jmc wordtype[n - 1] == OBJECT) && 159 1.18 rillig wordvalue[n] == AND && 160 1.15 jmc wordvalue[n + 1] == EVERYTHING) { 161 1.8 jsm char tmpword[WORDLEN]; 162 1.8 jsm wordvalue[n + 1] = wordvalue[n - 1]; 163 1.8 jsm wordvalue[n - 1] = EVERYTHING; 164 1.8 jsm wordtype[n + 1] = wordtype[n - 1]; 165 1.8 jsm wordtype[n - 1] = OBJECT; 166 1.8 jsm strcpy(tmpword, words[n - 1]); 167 1.17 fox strlcpy(words[n - 1], words[n + 1], WORDLEN); 168 1.8 jsm strcpy(words[n + 1], tmpword); 169 1.8 jsm flag = 1; 170 1.8 jsm } 171 1.8 jsm /* And trim EVERYTHING AND EVERYTHING. */ 172 1.8 jsm for (n = 1; n < wordcount; n++) 173 1.8 jsm if (wordvalue[n - 1] == EVERYTHING && 174 1.18 rillig wordvalue[n] == AND && 175 1.15 jmc wordvalue[n + 1] == EVERYTHING) { 176 1.8 jsm int i; 177 1.8 jsm for (i = n + 1; i < wordcount; i++) { 178 1.8 jsm wordtype[i - 1] = wordtype[i + 1]; 179 1.8 jsm wordvalue[i - 1] = wordvalue[i + 1]; 180 1.17 fox strlcpy(words[i - 1], words[i + 1], WORDLEN); 181 1.8 jsm } 182 1.8 jsm wordcount--; 183 1.8 jsm wordcount--; 184 1.8 jsm flag = 1; 185 1.8 jsm } 186 1.1 cgd } 187 1.1 cgd } 188