00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00051 #include <gsp.h>
00052 #include <adt/hash_table.h>
00053 #include <stdlib.h>
00054 #include <stdio.h>
00055
00056 #define TRANS_TABLE_CHAINS 256
00057
00058
00059
00060
00061
00062 static hash_index_t trans_op_hash(unsigned long key[]);
00063 static int trans_op_compare(unsigned long key[], hash_count_t keys,
00064 link_t *item);
00065 static void trans_op_remove_callback(link_t *item);
00066
00067 static hash_table_operations_t trans_ops = {
00068 .hash = trans_op_hash,
00069 .compare = trans_op_compare,
00070 .remove_callback = trans_op_remove_callback
00071 };
00072
00073 static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input);
00074 static void trans_insert(gsp_t *p, gsp_trans_t *t);
00075 static gsp_trans_t *trans_new(void);
00076
00078 void gsp_init(gsp_t *p)
00079 {
00080 p->states = 1;
00081 hash_table_create(&p->trans, TRANS_TABLE_CHAINS, 2, &trans_ops);
00082 }
00083
00092 int gsp_insert_defs(gsp_t *p, const int *defs)
00093 {
00094 unsigned mods, key;
00095 const int *dp;
00096 int rc;
00097
00098 dp = defs;
00099
00100 while (1) {
00101
00102 mods = *dp++;
00103 key = *dp++;
00104 if (key == 0) break;
00105
00106
00107 rc = gsp_insert_seq(p, dp, mods, key);
00108 if (rc != 0)
00109 return rc;
00110
00111
00112 while (*dp != GSP_END)
00113 ++dp;
00114 ++dp;
00115 }
00116
00117 return 0;
00118 }
00119
00127 int gsp_insert_seq(gsp_t *p, const int *seq, unsigned mods, unsigned key)
00128 {
00129 int state;
00130 gsp_trans_t *t;
00131
00132 state = 0;
00133 t = NULL;
00134
00135
00136 if (*seq == GSP_END)
00137 return -1;
00138
00139 while (*(seq + 1) != GSP_END) {
00140 t = trans_lookup(p, state, *seq);
00141 if (t == NULL) {
00142
00143 t = trans_new();
00144 t->old_state = state;
00145 t->input = *seq;
00146 t->new_state = p->states++;
00147
00148 t->out_mods = 0;
00149 t->out_key = 0;
00150
00151 trans_insert(p, t);
00152 }
00153 state = t->new_state;
00154 ++seq;
00155 }
00156
00157
00158 t = trans_lookup(p, state, *seq);
00159 if (t != NULL) {
00160 exit(1);
00161 return -1;
00162 }
00163
00164 t = trans_new();
00165 t->old_state = state;
00166 t->input = *seq;
00167 t->new_state = 0;
00168
00169 t->out_mods = mods;
00170 t->out_key = key;
00171
00172 trans_insert(p, t);
00173
00174 return 0;
00175 }
00176
00189 int gsp_step(gsp_t *p, int state, int input, unsigned *mods, unsigned *key)
00190 {
00191 gsp_trans_t *t;
00192
00193 t = trans_lookup(p, state, input);
00194 if (t == NULL) {
00195 t = trans_lookup(p, state, GSP_DEFAULT);
00196 }
00197
00198 if (t == NULL) {
00199 printf("gsp_step: not found\n");
00200 *mods = 0;
00201 *key = 0;
00202 return 0;
00203 }
00204
00205 *mods = t->out_mods;
00206 *key = t->out_key;
00207 return t->new_state;
00208 }
00209
00221 static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input)
00222 {
00223 link_t *item;
00224 unsigned long key[2];
00225
00226 key[0] = state;
00227 key[1] = input;
00228
00229 item = hash_table_find(&p->trans, key);
00230 if (item == NULL) return NULL;
00231
00232 return hash_table_get_instance(item, gsp_trans_t, link);
00233 }
00234
00240 static void trans_insert(gsp_t *p, gsp_trans_t *t)
00241 {
00242 unsigned long key[2];
00243
00244 key[0] = t->old_state;
00245 key[1] = t->input;
00246
00247 hash_table_insert(&p->trans, key, &t->link);
00248 }
00249
00251 static gsp_trans_t *trans_new(void)
00252 {
00253 gsp_trans_t *t;
00254
00255 t = malloc(sizeof(gsp_trans_t));
00256 if (t == NULL) {
00257 printf("Memory allocation failed.\n");
00258 exit(1);
00259 }
00260
00261 return t;
00262 }
00263
00264
00265
00266
00267
00268 static hash_index_t trans_op_hash(unsigned long key[])
00269 {
00270 return (key[0] * 17 + key[1]) % TRANS_TABLE_CHAINS;
00271 }
00272
00273 static int trans_op_compare(unsigned long key[], hash_count_t keys,
00274 link_t *item)
00275 {
00276 gsp_trans_t *t;
00277
00278 t = hash_table_get_instance(item, gsp_trans_t, link);
00279 return ((key[0] == (unsigned long) t->old_state)
00280 && (key[1] == (unsigned long) t->input));
00281 }
00282
00283 static void trans_op_remove_callback(link_t *item)
00284 {
00285 }
00286