1/*---------------------------------------------------------------------------*
2 *  srec_tokens.c  *
3 *                                                                           *
4 *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
5 *                                                                           *
6 *  Licensed under the Apache License, Version 2.0 (the 'License');          *
7 *  you may not use this file except in compliance with the License.         *
8 *                                                                           *
9 *  You may obtain a copy of the License at                                  *
10 *      http://www.apache.org/licenses/LICENSE-2.0                           *
11 *                                                                           *
12 *  Unless required by applicable law or agreed to in writing, software      *
13 *  distributed under the License is distributed on an 'AS IS' BASIS,        *
14 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15 *  See the License for the specific language governing permissions and      *
16 *  limitations under the License.                                           *
17 *                                                                           *
18 *---------------------------------------------------------------------------*/
19
20#include"srec.h"
21#include"srec_tokens.h"
22#include "passert.h"
23#include "portable.h"
24
25
26/* we do no expect dump_core() to ever be called */
27static void dump_core(char *msg)
28{
29  PLogError ( msg );
30  ASSERT(0);
31}
32
33/*
34 * fsmarc_token management
35 */
36
37int count_fsmarc_token_list(srec* rec, stokenID token_index)
38{
39  int count = 0;
40
41  while (token_index != MAXstokenID)
42  {
43    fsmarc_token* stoken = &rec->fsmarc_token_array[token_index];
44    token_index = stoken->next_token_index;
45    count++;
46    ASSERT(count < 5000);
47  }
48  return count;
49}
50
51/* static int num_fsmarc_tokens_allocated = 0; */
52
53void initialize_free_fsmarc_tokens(srec *rec)
54{
55  stokenID i;
56
57  /* num_fsmarc_tokens_allocated = 0; */
58  for (i = 0;i < rec->fsmarc_token_array_size - 1;i++)
59  {
60    rec->fsmarc_token_array[i].next_token_index = i + 1;
61  }
62  rec->fsmarc_token_array[rec->fsmarc_token_array_size-1].next_token_index = MAXstokenID;
63  rec->fsmarc_token_freelist = 0;
64}
65
66/*allocates the token and sets it up for a given arc*/
67stokenID setup_free_fsmarc_token(srec *rec, FSMarc* arc, arcID fsm_arc_index, miscdata what_to_do_if_fails)
68{
69  int i;
70  stokenID token_to_return;
71  fsmarc_token *token;
72
73  if (rec->fsmarc_token_freelist ==  MAXstokenID)
74  {
75    if (what_to_do_if_fails == EXIT_IF_NO_TOKENS)
76    {
77      /*FIX - replace with crec error handling*/
78      dump_core("setup_free_fsmarc_token: ran out of tokens\n");
79    }
80    if (what_to_do_if_fails == NULL_IF_NO_TOKENS)
81    {
82      return MAXstokenID;
83    }
84    else
85    { /*no other conditions for now, so just exit*/
86      /*FIX - replace with crec error handling*/
87      dump_core("setup_free_fsmarc_token: ran out of tokens\n");
88    }
89  }
90
91  ASSERT(rec->fsmarc_token_freelist < rec->fsmarc_token_array_size);
92  token_to_return = rec->fsmarc_token_freelist;
93  token = &(rec->fsmarc_token_array[token_to_return]);
94
95  token->FSMarc_index = fsm_arc_index;
96  arc = &(rec->context->FSMarc_list[fsm_arc_index]);
97  token->num_hmm_states = rec->context->hmm_info_for_ilabel[arc->ilabel].num_states;
98
99  for (i = 0;i < token->num_hmm_states;i++)
100  {
101    token->cost[i] = MAXcostdata;
102    token->word[i] = MAXwordID;
103    token->word_backtrace[i] = MAXwtokenID;
104    token->duration[i] = MAXframeID;
105    token->aword_backtrace[i] = AWTNULL;
106  }
107
108  rec->fsmarc_token_freelist = token->next_token_index;
109
110  /* num_fsmarc_tokens_allocated++; */
111  return token_to_return;
112}
113
114
115void free_fsmarc_token(srec *rec, stokenID old_token_index)
116{
117  fsmarc_token* stoken;
118  ASSERT(old_token_index < rec->fsmarc_token_array_size);
119  stoken = &rec->fsmarc_token_array[old_token_index];
120  stoken->next_token_index = rec->fsmarc_token_freelist;
121  rec->fsmarc_token_freelist = old_token_index;
122  { int i;
123    for (i = 0; i < stoken->num_hmm_states; i++)
124      if (stoken->aword_backtrace[i] != AWTNULL)
125        free_altword_token_batch(rec, stoken->aword_backtrace[i]);
126  }
127}
128
129void sort_fsmarc_token_list(srec* rec, stokenID* ptoken_index)
130{};
131
132/*
133 * word_token management
134 */
135
136void initialize_free_word_tokens(srec *rec)
137{
138  wtokenID i;
139  word_token* wtoken = NULL;
140
141  for (i = 0;i < rec->word_token_array_size;i++)
142  {
143    wtoken = &rec->word_token_array[i];
144    wtoken->next_token_index = i + 1;
145  }
146  /* last one must point nowhere */
147  wtoken->next_token_index = MAXwtokenID;
148  rec->word_token_freelist = 0;
149}
150
151wtokenID get_free_word_token(srec *rec, miscdata what_to_do_if_fails)
152{
153  wtokenID token_to_return;
154  word_token* wtoken;
155
156  if (rec->word_token_freelist ==  MAXwtokenID)
157  {
158    if (what_to_do_if_fails == EXIT_IF_NO_TOKENS)
159    {
160      /*FIX - replace with crec error handling*/
161      dump_core("get_free_word_token: ran out of tokens\n");
162    }
163    if (what_to_do_if_fails == NULL_IF_NO_TOKENS)
164    {
165      return MAXwtokenID;
166    }
167    else
168    { /*no other conditions for now, so just exit*/
169      /*FIX - replace with crec error handling*/
170      dump_core("get_free_word_token: ran out of tokens\n");
171    }
172  }
173
174  token_to_return = rec->word_token_freelist;
175  wtoken =  &rec->word_token_array[token_to_return];
176  rec->word_token_freelist = wtoken->next_token_index;
177
178  /*note that we are returning without setting any contents of the token (including next_token_index)
179   leave it for the calling program to take care of that*/
180
181  return token_to_return;
182}
183
184
185
186
187/*
188 * fsmnode_token management
189 */
190
191int count_fsmnode_token_list(srec* rec, ftokenID token_index)
192{
193  int count = 0;
194
195  while (token_index != MAXftokenID)
196  {
197    fsmnode_token* ftoken = &rec->fsmnode_token_array[token_index];
198    token_index = ftoken->next_token_index;
199    count++;
200  }
201  return count;
202}
203
204void initialize_free_fsmnode_tokens(srec *rec)
205{
206  ftokenID i;
207  fsmnode_token* ftoken = NULL;
208
209  for (i = 0;i < rec->fsmnode_token_array_size;i++)
210  {
211    ftoken = &rec->fsmnode_token_array[i];
212    ftoken->next_token_index = i + 1;
213  }
214  /* last one must point nowhere */
215  ftoken->next_token_index = MAXftokenID;
216  rec->fsmnode_token_freelist = 0;
217}
218
219ftokenID get_free_fsmnode_token(srec *rec, miscdata what_to_do_if_fails)
220{
221  ftokenID token_to_return;
222  fsmnode_token* ftoken;
223
224  if (rec->fsmnode_token_freelist ==  MAXftokenID)
225  {
226    if (what_to_do_if_fails == EXIT_IF_NO_TOKENS)
227    {
228      /*FIX - replace with crec error handling*/
229      dump_core("get_free_fsmnode_token: ran out of tokens\n");
230    }
231    if (what_to_do_if_fails == NULL_IF_NO_TOKENS)
232    {
233      return MAXftokenID;
234    }
235    else
236    { /*no other conditions for now, so just exit*/
237      /*FIX - replace with crec error handling*/
238      dump_core("get_free_fsmnode_token: ran out of tokens\n");
239    }
240  }
241
242  token_to_return = rec->fsmnode_token_freelist;
243  ftoken =  &rec->fsmnode_token_array[token_to_return];
244  rec->fsmnode_token_freelist = ftoken->next_token_index;
245
246  /*note that we are returning without setting any contents of the token
247    (including next_token_index)
248    leave it for the calling program to take care of that */
249
250  return token_to_return;
251}
252
253void free_fsmnode_token(srec *rec, ftokenID old_token_index)
254{
255  fsmnode_token* ftoken;
256  ASSERT(old_token_index < rec->fsmnode_token_array_size);
257  ftoken = &rec->fsmnode_token_array[old_token_index];
258  ftoken->next_token_index = rec->fsmnode_token_freelist;
259  ftoken->cost = MAXcostdata;
260  rec->fsmnode_token_freelist = old_token_index;
261  if (ftoken->aword_backtrace != AWTNULL)
262    free_altword_token_batch(rec, ftoken->aword_backtrace);
263}
264
265/*
266 *  altword token management
267 */
268
269void initialize_free_altword_tokens(srec *rec)
270{
271  wtokenID i;
272  altword_token* awtoken = NULL;
273  for (i = 0;i < rec->altword_token_array_size;i++)
274  {
275    awtoken = rec->altword_token_array + i;
276    awtoken->next_token = awtoken + 1;
277    awtoken->costdelta  = MAXcostdata;
278    awtoken->refcount   = 0;
279    awtoken->costbasis  = 0;
280  }
281  /* last one must point nowhere */
282  awtoken->next_token = NULL;
283  rec->altword_token_freelist = &rec->altword_token_array[0];
284  rec->altword_token_freelist_len = rec->altword_token_array_size;
285}
286
287
288int count_altword_token(srec* rec, altword_token* b)
289{
290  int num = 0;
291  for (; b; b = b->next_token) {
292	  num++;
293      // if(num>9999) ASSERT(0);
294  }
295  return num;
296}
297
298
299/* get a free altword token, handle out of memory later!! */
300altword_token* get_free_altword_token(srec* rec, miscdata what_to_do_if_fails)
301{
302  altword_token* awtoken = rec->altword_token_freelist;
303  /* what_to_do_if_fails ... we do not ever expect failure because
304     all get_free's are preceded by repruning, but if there should
305     ever be a failure, we will return NULL and handle it in the
306     caller */
307  if (!awtoken /*&& what_to_do_if_fails==NULL_IF_NO_TOKENS*/)
308    return awtoken;
309  awtoken->refcount = 1;
310  rec->altword_token_freelist = awtoken->next_token;
311  rec->altword_token_freelist_len--;
312  return awtoken;
313}
314
315/* release an altword token */
316int free_altword_token(srec* rec, altword_token* old_token)
317{
318  ASSERT(old_token->refcount >= 1);
319  if (--old_token->refcount <= 0)
320  {
321    old_token->next_token = rec->altword_token_freelist;
322    old_token->costdelta  = MAXcostdata;
323    rec->altword_token_freelist = old_token;
324    rec->altword_token_freelist_len++;
325  }
326  return old_token->refcount; /* return zero if truly freed */
327}
328
329altword_token* free_altword_token_batch(srec* rec, altword_token* old_token)
330{
331  /* char dd[128], *ddp = &dd[0]; */
332  ASSERT(old_token->refcount >= 1);
333  if (--old_token->refcount <= 0)
334  {
335    altword_token *awtoken, *next_awtoken;
336    for (awtoken = old_token; awtoken != AWTNULL; awtoken = next_awtoken)
337    {
338      next_awtoken = awtoken->next_token;
339      /* *(ddp++) = '0' + awtoken->refcount; */
340      awtoken->costdelta  = MAXcostdata;
341      awtoken->next_token = rec->altword_token_freelist;
342      rec->altword_token_freelist = awtoken;
343      rec->altword_token_freelist_len++;
344    }
345  }
346  return AWTNULL;
347}
348
349