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
00029
00030
00031
00032
00033
00034
00035
00036 #ifdef _WIN32_WCE
00037
00038
00039 #include <windows.h>
00040 #else
00041 #include <time.h>
00042 #endif
00043 #include <stdio.h>
00044 #include <string.h>
00045 #include <assert.h>
00046
00047
00048 #include "err.h"
00049 #include "pio.h"
00050 #include "ckd_alloc.h"
00051 #include "prim_type.h"
00052 #include "strfuncs.h"
00053 #include "hash_table.h"
00054
00055 #include "fsg_model.h"
00056
00057
00058 #define FSG_MODEL_BEGIN_DECL "FSG_BEGIN"
00059 #define FSG_MODEL_END_DECL "FSG_END"
00060 #define FSG_MODEL_N_DECL "N"
00061 #define FSG_MODEL_NUM_STATES_DECL "NUM_STATES"
00062 #define FSG_MODEL_S_DECL "S"
00063 #define FSG_MODEL_START_STATE_DECL "START_STATE"
00064 #define FSG_MODEL_F_DECL "F"
00065 #define FSG_MODEL_FINAL_STATE_DECL "FINAL_STATE"
00066 #define FSG_MODEL_T_DECL "T"
00067 #define FSG_MODEL_TRANSITION_DECL "TRANSITION"
00068 #define FSG_MODEL_COMMENT_CHAR '#'
00069
00070
00071 static int32
00072 nextline_str2words(FILE * fp, int32 * lineno,
00073 char **lineptr, char ***wordptr)
00074 {
00075 for (;;) {
00076 size_t len;
00077 int32 n;
00078
00079 ckd_free(*lineptr);
00080 if ((*lineptr = fread_line(fp, &len)) == NULL)
00081 return -1;
00082
00083 (*lineno)++;
00084
00085 if ((*lineptr)[0] == FSG_MODEL_COMMENT_CHAR)
00086 continue;
00087
00088 n = str2words(*lineptr, NULL, 0);
00089 if (n == 0)
00090 continue;
00091
00092
00093 if (*wordptr == NULL)
00094 *wordptr = ckd_calloc(n, sizeof(**wordptr));
00095 else
00096 *wordptr = ckd_realloc(*wordptr, n * sizeof(**wordptr));
00097 return str2words(*lineptr, *wordptr, n);
00098 }
00099 }
00100
00101 void
00102 fsg_model_trans_add(fsg_model_t * fsg,
00103 int32 from, int32 to, int32 logp, int32 wid)
00104 {
00105 fsg_link_t *link;
00106 gnode_t *gn;
00107
00108
00109 for (gn = fsg->trans[from][to]; gn; gn = gnode_next(gn)) {
00110 link = (fsg_link_t *) gnode_ptr(gn);
00111
00112 if (link->wid == wid) {
00113 if (link->logs2prob < logp)
00114 link->logs2prob = logp;
00115 return;
00116 }
00117 }
00118
00119
00120 link = listelem_malloc(fsg->link_alloc);
00121 link->from_state = from;
00122 link->to_state = to;
00123 link->logs2prob = logp;
00124 link->wid = wid;
00125
00126 fsg->trans[from][to] =
00127 glist_add_ptr(fsg->trans[from][to], (void *) link);
00128 }
00129
00130 int32
00131 fsg_model_null_trans_add(fsg_model_t * fsg, int32 from, int32 to, int32 logp)
00132 {
00133 fsg_link_t *link;
00134
00135
00136 if (logp > 0) {
00137 E_FATAL("Null transition prob must be <= 1.0 (state %d -> %d)\n",
00138 from, to);
00139 }
00140
00141
00142 if (from == to)
00143 return -1;
00144
00145
00146 link = fsg->null_trans[from][to];
00147 if (link) {
00148 assert(link->wid < 0);
00149 if (link->logs2prob < logp) {
00150 link->logs2prob = logp;
00151 return 0;
00152 }
00153 else
00154 return -1;
00155 }
00156
00157
00158 link = listelem_malloc(fsg->link_alloc);
00159 link->from_state = from;
00160 link->to_state = to;
00161 link->logs2prob = logp;
00162 link->wid = -1;
00163
00164 fsg->null_trans[from][to] = link;
00165
00166 return 1;
00167 }
00168
00169 glist_t
00170 fsg_model_null_trans_closure(fsg_model_t * fsg, glist_t nulls)
00171 {
00172 gnode_t *gn1, *gn2;
00173 int updated;
00174 fsg_link_t *tl1, *tl2;
00175 int32 k, n;
00176
00177 E_INFO("Computing transitive closure for null transitions\n");
00178
00179 if (nulls == NULL) {
00180 int i, j;
00181
00182 for (i = 0; i < fsg->n_state; ++i) {
00183 for (j = 0; j < fsg->n_state; ++j) {
00184 if (fsg->null_trans[i][j])
00185 nulls = glist_add_ptr(nulls, fsg->null_trans[i][j]);
00186 }
00187 }
00188 }
00189
00190
00191
00192
00193
00194 n = 0;
00195 do {
00196 updated = FALSE;
00197
00198 for (gn1 = nulls; gn1; gn1 = gnode_next(gn1)) {
00199 tl1 = (fsg_link_t *) gnode_ptr(gn1);
00200 assert(tl1->wid < 0);
00201
00202 for (gn2 = nulls; gn2; gn2 = gnode_next(gn2)) {
00203 tl2 = (fsg_link_t *) gnode_ptr(gn2);
00204
00205 if (tl1->to_state == tl2->from_state) {
00206 k = fsg_model_null_trans_add(fsg,
00207 tl1->from_state,
00208 tl2->to_state,
00209 tl1->logs2prob +
00210 tl2->logs2prob);
00211 if (k >= 0) {
00212 updated = TRUE;
00213 if (k > 0) {
00214 nulls =
00215 glist_add_ptr(nulls,
00216 (void *) fsg->
00217 null_trans[tl1->
00218 from_state][tl2->
00219 to_state]);
00220 n++;
00221 }
00222 }
00223 }
00224 }
00225 }
00226 } while (updated);
00227
00228 E_INFO("%d null transitions added\n", n);
00229
00230 return nulls;
00231 }
00232
00233 int
00234 fsg_model_word_id(fsg_model_t *fsg, char const *word)
00235 {
00236 int wid;
00237
00238
00239 for (wid = 0; wid < fsg->n_word; ++wid) {
00240 if (0 == strcmp(fsg->vocab[wid], word))
00241 break;
00242 }
00243
00244 if (wid == fsg->n_word)
00245 return -1;
00246 return wid;
00247 }
00248
00249 int
00250 fsg_model_word_add(fsg_model_t *fsg, char const *word)
00251 {
00252 int wid;
00253
00254
00255 wid = fsg_model_word_id(fsg, word);
00256
00257 if (wid == -1) {
00258 wid = fsg->n_word;
00259 if (fsg->n_word == fsg->n_word_alloc) {
00260 fsg->n_word_alloc += 10;
00261 fsg->vocab = ckd_realloc(fsg->vocab,
00262 fsg->n_word_alloc * sizeof(*fsg->vocab));
00263 if (fsg->silwords)
00264 fsg->silwords = bitvec_realloc(fsg->silwords, fsg->n_word_alloc);
00265 if (fsg->altwords)
00266 fsg->altwords = bitvec_realloc(fsg->altwords, fsg->n_word_alloc);
00267 }
00268 ++fsg->n_word;
00269 fsg->vocab[wid] = ckd_salloc(word);
00270 }
00271 return wid;
00272 }
00273
00274 int
00275 fsg_model_add_silence(fsg_model_t * fsg, char const *silword,
00276 int state, float32 silprob)
00277 {
00278 int32 logsilp;
00279 int n_trans, silwid, src;
00280
00281 E_INFO("Adding silence transitions for %s to FSG\n", silword);
00282
00283 silwid = fsg_model_word_add(fsg, silword);
00284 logsilp = (int32) (logmath_log(fsg->lmath, silprob) * fsg->lw);
00285 if (fsg->silwords == NULL)
00286 fsg->silwords = bitvec_alloc(fsg->n_word_alloc);
00287 bitvec_set(fsg->silwords, silwid);
00288
00289 n_trans = 0;
00290 if (state == -1) {
00291 for (src = 0; src < fsg->n_state; src++) {
00292 fsg_model_trans_add(fsg, src, src, logsilp, silwid);
00293 ++n_trans;
00294 }
00295 }
00296 else {
00297 fsg_model_trans_add(fsg, state, state, logsilp, silwid);
00298 ++n_trans;
00299 }
00300
00301 E_INFO("Added %d silence word transitions\n", n_trans);
00302 return n_trans;
00303 }
00304
00305 int
00306 fsg_model_add_alt(fsg_model_t * fsg, char const *baseword,
00307 char const *altword)
00308 {
00309 int i, j, basewid, altwid;
00310 int ntrans;
00311
00312
00313 for (basewid = 0; basewid < fsg->n_word; ++basewid)
00314 if (0 == strcmp(fsg->vocab[basewid], baseword))
00315 break;
00316 if (basewid == fsg->n_word) {
00317 E_ERROR("Base word %s not present in FSG vocabulary!\n", baseword);
00318 return -1;
00319 }
00320 altwid = fsg_model_word_add(fsg, altword);
00321 if (fsg->altwords == NULL)
00322 fsg->altwords = bitvec_alloc(fsg->n_word_alloc);
00323 bitvec_set(fsg->altwords, altwid);
00324
00325 E_INFO("Adding alternate word transitions (%s,%s) to FSG\n",
00326 baseword, altword);
00327
00328
00329
00330 ntrans = 0;
00331 for (i = 0; i < fsg->n_state; ++i) {
00332 for (j = 0; j < fsg->n_state; ++j) {
00333 glist_t trans;
00334 gnode_t *gn;
00335
00336 trans = fsg->trans[i][j];
00337 for (gn = trans; gn; gn = gnode_next(gn)) {
00338 fsg_link_t *fl = gnode_ptr(gn);
00339 if (fl->wid == basewid) {
00340 fsg_link_t *link;
00341
00342
00343 link = listelem_malloc(fsg->link_alloc);
00344 link->from_state = i;
00345 link->to_state = j;
00346 link->logs2prob = fl->logs2prob;
00347 link->wid = altwid;
00348
00349 trans =
00350 glist_add_ptr(trans, (void *) link);
00351 ++ntrans;
00352 }
00353 }
00354 fsg->trans[i][j] = trans;
00355 }
00356 }
00357
00358 E_INFO("Added %d alternate word transitions\n", ntrans);
00359 return ntrans;
00360 }
00361
00362
00363 fsg_model_t *
00364 fsg_model_init(char const *name, logmath_t *lmath, float32 lw, int32 n_state)
00365 {
00366 fsg_model_t *fsg;
00367
00368
00369 fsg = ckd_calloc(1, sizeof(*fsg));
00370 fsg->refcount = 1;
00371 fsg->link_alloc = listelem_alloc_init(sizeof(fsg_link_t));
00372 fsg->lmath = lmath;
00373 fsg->name = name ? ckd_salloc(name) : NULL;
00374 fsg->n_state = n_state;
00375 fsg->lw = lw;
00376
00377
00378 fsg->trans = ckd_calloc_2d(fsg->n_state, fsg->n_state,
00379 sizeof(glist_t));
00380
00381 fsg->null_trans = ckd_calloc_2d(fsg->n_state, fsg->n_state,
00382 sizeof(fsg_link_t *));
00383 return fsg;
00384 }
00385
00386 fsg_model_t *
00387 fsg_model_read(FILE * fp, logmath_t *lmath, float32 lw)
00388 {
00389 fsg_model_t *fsg;
00390 hash_table_t *vocab;
00391 hash_iter_t *itor;
00392 int32 lastwid;
00393 char **wordptr;
00394 char *lineptr;
00395 char *fsgname;
00396 int32 lineno;
00397 int32 n, i, j;
00398 int n_state, n_trans, n_null_trans;
00399 glist_t nulls;
00400 float32 p;
00401
00402 lineno = 0;
00403 vocab = hash_table_new(32, FALSE);
00404 wordptr = NULL;
00405 lineptr = NULL;
00406 nulls = NULL;
00407 fsgname = NULL;
00408 fsg = NULL;
00409
00410
00411 for (;;) {
00412 n = nextline_str2words(fp, &lineno, &lineptr, &wordptr);
00413 if (n < 0) {
00414 E_ERROR("%s declaration missing\n", FSG_MODEL_BEGIN_DECL);
00415 goto parse_error;
00416 }
00417
00418 if ((strcmp(wordptr[0], FSG_MODEL_BEGIN_DECL) == 0)) {
00419 if (n > 2) {
00420 E_ERROR("Line[%d]: malformed FSG_BEGIN declaration\n",
00421 lineno);
00422 goto parse_error;
00423 }
00424 break;
00425 }
00426 }
00427
00428
00429
00430 if (n == 2) {
00431 fsgname = ckd_salloc(wordptr[1]);
00432 } else {
00433 E_WARN ("FSG name is missing\n");
00434 fsgname = ckd_salloc("unknown");
00435 }
00436
00437
00438 n = nextline_str2words(fp, &lineno, &lineptr, &wordptr);
00439 if ((n != 2)
00440 || ((strcmp(wordptr[0], FSG_MODEL_N_DECL) != 0)
00441 && (strcmp(wordptr[0], FSG_MODEL_NUM_STATES_DECL) != 0))
00442 || (sscanf(wordptr[1], "%d", &n_state) != 1)
00443 || (n_state <= 0)) {
00444 E_ERROR
00445 ("Line[%d]: #states declaration line missing or malformed\n",
00446 lineno);
00447 goto parse_error;
00448 }
00449
00450
00451 fsg = fsg_model_init(fsgname, lmath, lw, n_state);
00452 ckd_free(fsgname);
00453 fsgname = NULL;
00454
00455
00456 n = nextline_str2words(fp, &lineno, &lineptr, &wordptr);
00457 if ((n != 2)
00458 || ((strcmp(wordptr[0], FSG_MODEL_S_DECL) != 0)
00459 && (strcmp(wordptr[0], FSG_MODEL_START_STATE_DECL) != 0))
00460 || (sscanf(wordptr[1], "%d", &(fsg->start_state)) != 1)
00461 || (fsg->start_state < 0)
00462 || (fsg->start_state >= fsg->n_state)) {
00463 E_ERROR
00464 ("Line[%d]: start state declaration line missing or malformed\n",
00465 lineno);
00466 goto parse_error;
00467 }
00468
00469
00470 n = nextline_str2words(fp, &lineno, &lineptr, &wordptr);
00471 if ((n != 2)
00472 || ((strcmp(wordptr[0], FSG_MODEL_F_DECL) != 0)
00473 && (strcmp(wordptr[0], FSG_MODEL_FINAL_STATE_DECL) != 0))
00474 || (sscanf(wordptr[1], "%d", &(fsg->final_state)) != 1)
00475 || (fsg->final_state < 0)
00476 || (fsg->final_state >= fsg->n_state)) {
00477 E_ERROR
00478 ("Line[%d]: final state declaration line missing or malformed\n",
00479 lineno);
00480 goto parse_error;
00481 }
00482
00483
00484 lastwid = 0;
00485 n_trans = n_null_trans = 0;
00486 for (;;) {
00487 int32 wid, tprob;
00488
00489 n = nextline_str2words(fp, &lineno, &lineptr, &wordptr);
00490 if (n <= 0) {
00491 E_ERROR("Line[%d]: transition or FSG_END statement expected\n",
00492 lineno);
00493 goto parse_error;
00494 }
00495
00496 if ((strcmp(wordptr[0], FSG_MODEL_END_DECL) == 0)) {
00497 break;
00498 }
00499
00500 if ((strcmp(wordptr[0], FSG_MODEL_T_DECL) == 0)
00501 || (strcmp(wordptr[0], FSG_MODEL_TRANSITION_DECL) == 0)) {
00502
00503
00504 if (((n != 4) && (n != 5))
00505 || (sscanf(wordptr[1], "%d", &i) != 1)
00506 || (sscanf(wordptr[2], "%d", &j) != 1)
00507 || (i < 0) || (i >= fsg->n_state)
00508 || (j < 0) || (j >= fsg->n_state)) {
00509 E_ERROR
00510 ("Line[%d]: transition spec malformed; Expecting: from-state to-state trans-prob [word]\n",
00511 lineno);
00512 goto parse_error;
00513 }
00514
00515 p = atof_c(wordptr[3]);
00516 if ((p <= 0.0) || (p > 1.0)) {
00517 E_ERROR
00518 ("Line[%d]: transition spec malformed; Expecting float as transition probability\n",
00519 lineno);
00520 goto parse_error;
00521 }
00522 }
00523 else {
00524 E_ERROR("Line[%d]: transition or FSG_END statement expected\n",
00525 lineno);
00526 goto parse_error;
00527 }
00528
00529 tprob = (int32)(logmath_log(lmath, p) * fsg->lw);
00530
00531 if (n > 4) {
00532 if (hash_table_lookup_int32(vocab, wordptr[4], &wid) < 0) {
00533 (void)hash_table_enter_int32(vocab, ckd_salloc(wordptr[4]), lastwid);
00534 wid = lastwid;
00535 ++lastwid;
00536 }
00537 fsg_model_trans_add(fsg, i, j, tprob, wid);
00538 ++n_trans;
00539 }
00540 else {
00541 if (fsg_model_null_trans_add(fsg, i, j, tprob) == 1) {
00542 ++n_null_trans;
00543 nulls = glist_add_ptr(nulls, fsg->null_trans[i][j]);
00544 }
00545 }
00546 }
00547
00548 E_INFO("FSG: %d states, %d unique words, %d transitions (%d null)\n",
00549 fsg->n_state, hash_table_inuse(vocab), n_trans, n_null_trans);
00550
00551
00552 nulls = fsg_model_null_trans_closure(fsg, nulls);
00553 glist_free(nulls);
00554
00555
00556 fsg->n_word = hash_table_inuse(vocab);
00557 fsg->n_word_alloc = fsg->n_word + 10;
00558 fsg->vocab = ckd_calloc(fsg->n_word_alloc, sizeof(*fsg->vocab));
00559 for (itor = hash_table_iter(vocab); itor; itor = hash_table_iter_next(itor)) {
00560 char const *word = hash_entry_key(itor->ent);
00561 int32 wid = (int32)(long)hash_entry_val(itor->ent);
00562 fsg->vocab[wid] = (char *)word;
00563 }
00564 hash_table_free(vocab);
00565 ckd_free(lineptr);
00566 ckd_free(wordptr);
00567
00568 return fsg;
00569
00570 parse_error:
00571 for (itor = hash_table_iter(vocab); itor; itor = hash_table_iter_next(itor))
00572 ckd_free((char *)hash_entry_key(itor->ent));
00573 glist_free(nulls);
00574 hash_table_free(vocab);
00575 ckd_free(fsgname);
00576 ckd_free(lineptr);
00577 ckd_free(wordptr);
00578 fsg_model_free(fsg);
00579 return NULL;
00580 }
00581
00582
00583 fsg_model_t *
00584 fsg_model_readfile(const char *file, logmath_t *lmath, float32 lw)
00585 {
00586 FILE *fp;
00587 fsg_model_t *fsg;
00588
00589 if ((fp = fopen(file, "r")) == NULL) {
00590 E_ERROR("fopen(%s,r) failed\n", file);
00591 return NULL;
00592 }
00593 fsg = fsg_model_read(fp, lmath, lw);
00594 fclose(fp);
00595 return fsg;
00596 }
00597
00598 fsg_model_t *
00599 fsg_model_retain(fsg_model_t *fsg)
00600 {
00601 ++fsg->refcount;
00602 return fsg;
00603 }
00604
00605 int
00606 fsg_model_free(fsg_model_t * fsg)
00607 {
00608 int i, j;
00609
00610 if (fsg == NULL)
00611 return 0;
00612
00613 if (--fsg->refcount > 0)
00614 return fsg->refcount;
00615
00616 for (i = 0; i < fsg->n_word; ++i)
00617 ckd_free(fsg->vocab[i]);
00618 for (i = 0; i < fsg->n_state; ++i)
00619 for (j = 0; j < fsg->n_state; ++j)
00620 glist_free(fsg->trans[i][j]);
00621 ckd_free(fsg->vocab);
00622 listelem_alloc_free(fsg->link_alloc);
00623 bitvec_free(fsg->silwords);
00624 bitvec_free(fsg->altwords);
00625 ckd_free_2d(fsg->trans);
00626 ckd_free_2d(fsg->null_trans);
00627 ckd_free(fsg->name);
00628 ckd_free(fsg);
00629 return 0;
00630 }
00631
00632
00633 void
00634 fsg_model_write(fsg_model_t * fsg, FILE * fp)
00635 {
00636 int32 i, j;
00637 gnode_t *gn;
00638 fsg_link_t *tl;
00639
00640 fprintf(fp, "%s %s\n", FSG_MODEL_BEGIN_DECL, fsg->name ? fsg->name : "");
00641 fprintf(fp, "%s %d\n", FSG_MODEL_NUM_STATES_DECL, fsg->n_state);
00642 fprintf(fp, "%s %d\n", FSG_MODEL_START_STATE_DECL, fsg->start_state);
00643 fprintf(fp, "%s %d\n", FSG_MODEL_FINAL_STATE_DECL, fsg->final_state);
00644
00645 for (i = 0; i < fsg->n_state; i++) {
00646 for (j = 0; j < fsg->n_state; j++) {
00647
00648 for (gn = fsg->trans[i][j]; gn; gn = gnode_next(gn)) {
00649 tl = (fsg_link_t *) gnode_ptr(gn);
00650
00651 fprintf(fp, "%s %d %d %f %s\n", FSG_MODEL_TRANSITION_DECL,
00652 tl->from_state, tl->to_state,
00653 logmath_exp(fsg->lmath, (int32)(tl->logs2prob / fsg->lw)),
00654 (tl->wid < 0) ? "" : fsg_model_word_str(fsg, tl->wid));
00655 }
00656
00657
00658 tl = fsg->null_trans[i][j];
00659 if (tl) {
00660 fprintf(fp, "%s %d %d %f\n",
00661 FSG_MODEL_TRANSITION_DECL,
00662 tl->from_state, tl->to_state,
00663 logmath_exp(fsg->lmath, (int32)(tl->logs2prob / fsg->lw)));
00664 }
00665 }
00666 }
00667
00668 fprintf(fp, "%s\n", FSG_MODEL_END_DECL);
00669
00670 fflush(fp);
00671 }
00672
00673 void
00674 fsg_model_writefile(fsg_model_t *fsg, char const *file)
00675 {
00676 FILE *fp;
00677
00678 assert(fsg);
00679
00680 E_INFO("Writing FSG file '%s'\n", file);
00681
00682 if ((fp = fopen(file, "w")) == NULL) {
00683 E_ERROR("fopen(%s,r) failed\n", file);
00684 return;
00685 }
00686
00687 fsg_model_write(fsg, fp);
00688
00689 fclose(fp);
00690 }
00691
00692 static void
00693 fsg_model_write_fsm_trans(fsg_model_t *fsg, int i, FILE *fp)
00694 {
00695 int j;
00696
00697 for (j = 0; j < fsg->n_state; j++) {
00698 gnode_t *gn;
00699 fsg_link_t *tl;
00700
00701
00702 for (gn = fsg->trans[i][j]; gn; gn = gnode_next(gn)) {
00703 tl = (fsg_link_t *) gnode_ptr(gn);
00704
00705 fprintf(fp, "%d %d %s %f\n",
00706 tl->from_state, tl->to_state,
00707 (tl->wid < 0) ? "<eps>" : fsg_model_word_str(fsg, tl->wid),
00708 -logmath_log_to_ln(fsg->lmath, tl->logs2prob / fsg->lw));
00709 }
00710
00711
00712 tl = fsg->null_trans[i][j];
00713 if (tl) {
00714 fprintf(fp, "%d %d <eps> %f\n",
00715 tl->from_state, tl->to_state,
00716 -logmath_log_to_ln(fsg->lmath, tl->logs2prob / fsg->lw));
00717 }
00718 }
00719 }
00720
00721 void
00722 fsg_model_write_fsm(fsg_model_t * fsg, FILE * fp)
00723 {
00724 int i;
00725
00726
00727 fsg_model_write_fsm_trans(fsg, fsg_model_start_state(fsg), fp);
00728
00729
00730 for (i = 0; i < fsg->n_state; i++) {
00731 if (i == fsg_model_start_state(fsg))
00732 continue;
00733 fsg_model_write_fsm_trans(fsg, i, fp);
00734 }
00735
00736
00737 fprintf(fp, "%d 0\n", fsg_model_final_state(fsg));
00738
00739 fflush(fp);
00740 }
00741
00742 void
00743 fsg_model_writefile_fsm(fsg_model_t *fsg, char const *file)
00744 {
00745 FILE *fp;
00746
00747 assert(fsg);
00748
00749 E_INFO("Writing FSM file '%s'\n", file);
00750
00751 if ((fp = fopen(file, "w")) == NULL) {
00752 E_ERROR("fopen(%s,r) failed\n", file);
00753 return;
00754 }
00755
00756 fsg_model_write_fsm(fsg, fp);
00757
00758 fclose(fp);
00759 }
00760
00761 void
00762 fsg_model_write_symtab(fsg_model_t *fsg, FILE *file)
00763 {
00764 int i;
00765
00766 fprintf(file, "<eps> 0\n");
00767 for (i = 0; i < fsg_model_n_word(fsg); ++i) {
00768 fprintf(file, "%s %d\n", fsg_model_word_str(fsg, i), i + 1);
00769 }
00770 fflush(file);
00771 }
00772
00773 void
00774 fsg_model_writefile_symtab(fsg_model_t *fsg, char const *file)
00775 {
00776 FILE *fp;
00777
00778 assert(fsg);
00779
00780 E_INFO("Writing FSM symbol table '%s'\n", file);
00781
00782 if ((fp = fopen(file, "w")) == NULL) {
00783 E_ERROR("fopen(%s,r) failed\n", file);
00784 return;
00785 }
00786
00787 fsg_model_write_symtab(fsg, fp);
00788
00789 fclose(fp);
00790 }