示例#1
0
/** 
 * Look up a word on dictionary by string.
 * 
 * @param keyword [in] keyword to search
 * @param winfo [in] word dictionary
 * 
 * @return the word id if found, or WORD_INVALID if not found.
 */
WORD_ID
voca_lookup_wid(char *keyword, WORD_INFO *winfo)
{
  WORD_ID i, found;
  int plen,totallen;
  boolean numflag = TRUE;
  int wid;
  char *c;

  if (keyword == NULL) return WORD_INVALID;
  
  if (keyword[0] == '#') {
    
    for(i=1;i<strlen(keyword);i++) {
      if (keyword[i] < '0' || keyword[i] > '9') {
	numflag = FALSE;
	break;
      }
    }
    if (numflag) {
      wid = atoi(&(keyword[1]));
      if (wid < 0 || wid >= winfo->num) {
	return(WORD_INVALID);
      } else {
	return(wid);
      }
    } else {
      return(WORD_INVALID);
    }
  }
      
  found = WORD_INVALID;
  totallen = strlen(keyword);
  if ((c = strchr(keyword, '[')) != NULL) {
    plen = c - keyword;
    for (i=0;i<winfo->num;i++) {
      if (strnmatch(keyword,winfo->wname[i], plen)
	  && strnmatch(c+1, winfo->woutput[i], totallen-plen-2)) {
	if (found == WORD_INVALID) {
	  found = i;
	} else {
	  jlog("Warning: voca_lookup: several \"%s\" found in dictionary, use the first one..\n");
	  break;
	}
      }
    }
  } else {
    for (i=0;i<winfo->num;i++) {
      if (strmatch(keyword,winfo->wname[i])) {
	if (found == WORD_INVALID) {
	  found = i;
	} else {
	  jlog("Warning: voca_lookup: several \"%s\" found in dictionary, use the first one..\n");
	  break;
	}
      }
    }
  }
  return found;
}
示例#2
0
mBOOL DLLINTERNAL MConfig::load(const char *fn) {
	FILE *fp;
	char loadfile[PATH_MAX];
	char line[MAX_CONF_LEN];
	char *optname, *optval;
	option_t *optp;
	int ln;

	// Make full pathname (from gamedir if relative, collapse "..",
	// backslashes, etc).
	full_gamedir_path(fn, loadfile);

	fp=fopen(loadfile, "r");
	if(!fp) {
		META_WARNING("unable to open config file '%s': %s", loadfile, 
				strerror(errno));
		RETURN_ERRNO(mFALSE, ME_NOFILE);
	}

	META_DEBUG(2, ("Loading from config file: %s", loadfile));
	for(ln=1; !feof(fp) && fgets(line, sizeof(line), fp); ln++) {
		if(line[0]=='#')
			continue;
		if(line[0]==';')
			continue;
		if(strnmatch(line, "//", 2))
			continue;
		if(!(optname=strtok(line, " \t\r\n"))) {
			META_WARNING("'%s' line %d: bad config format: missing option", 
					loadfile, ln);
			continue;
		}
		if(!(optval=strtok(NULL, "\r\n"))) {
			META_WARNING("'%s' line %d: bad config format: missing value", 
					loadfile, ln);
			continue;
		}

		if(!(optp=find(optname))) {
			META_WARNING("'%s' line %d: unknown option name '%s'", 
					loadfile, ln, optname);
			continue;
		}

		if(!set(optp, optval)) {
			META_WARNING("'%s' line %d: unable to set option '%s' value '%s'", 
					loadfile, ln, optname, optval);
			continue;
		}
	}
	filename=strdup(loadfile);
	fclose(fp);
	return(mTRUE);
}
示例#3
0
void FuncShowMaps(edict_t *pEntity)
{
	FILE *file = NULL;
	const char *path = "AdminMod/maps.txt";
	char fullpath[PATH_MAX];
	char line[MAX_CONF_LEN];
	char buf[MAX_CONF_LEN];

	sup_gamedir_path(path, fullpath);

	file = fopen(fullpath, "r");
	if(!file)
	{
		UTIL_LogPrintf("Unable to open map list file '%s': %s", fullpath, strerror(errno));
		if(pEntity)
			CLIENT_PRINTF(pEntity, print_console, "\nUnable to load map list\n");
		return;
	}

	for(int i = 1, j = 0; !feof(file); i++)
	{
		if(!fgets(line, sizeof(line), file))
		{
			UTIL_LogPrintf("Unable to read %d line", i);
			if(pEntity)
				CLIENT_PRINTF(pEntity, print_console, "\nUnable to load map list\n");
			fclose(file);
			break;
		}

		if(line[0] == '#' || line[0] == ';')
			continue;
		if(strnmatch(line, "//", 2))
			continue;

		j = strlen(line) - 1;
		if(line[j] == '\n')
			line[j] = '\0';

		if(!pEntity)
			LOG_CONSOLE(NULL, "%d) %s", i, line);
		else
		{
			sup_make_str(buf, sizeof(buf), "%d) %s\n", i, line);
			CLIENT_PRINTF(pEntity, print_console, buf);
		}
	}
	fclose(file);
}
/** 
 * Set number of N-gram entries, for reading the first LR 2-gram.
 * 
 * @param fp [in] file pointer
 * @param numlist [out] set the values to this buffer (malloc)
 *
 * @return the value of N, or -1 on error.
 */
static int
get_total_info(FILE *fp, NNID **numlist)
{
  char *p;
  int n;
  int maxn;
  unsigned long entry_num;
  int numnum;

  maxn = 0;

  numnum = 10;
  *numlist = (NNID *)mymalloc(sizeof(NNID) * numnum);

  while (getl(buf, sizeof(buf), fp) != NULL && buf[0] != '\\') {
    if (strnmatch(buf, "ngram", 5)) { /* n-gram num */
      //p = strtok(buf, " =");
      //n = atoi(p);
      //p = strtok(NULL, " =");
      //entry_num = atol(p);
      //sscanf(p, "%lu", &entry_num);
      sscanf(buf, "ngram %d = %lu", &n, &entry_num);
      /* check maximum number */
      if (entry_num > NNID_MAX) {
	jlog("Error: too big %d-gram (exceeds %d bit)\n", n, sizeof(NNID) * 8);
	return -1;
      }
      /* ignore empty entry */
      if (entry_num == 0) {
	jlog("Warning: empty %d-gram, skipped\n", n);
      } else {
	if (maxn < n) maxn = n;
	if (n >= numnum) {
	  numnum *= 2;
	  *numlist = (NNID *)myrealloc(*numlist, sizeof(NNID) * numnum);
	}
	(*numlist)[n-1] = entry_num;
      }
    }
  }

  return(maxn);
}
示例#5
0
bool FuncValidMap(const char *map)
{
	FILE *file = NULL;
	const char *path = "AdminMod/maps.txt";
	char fullpath[PATH_MAX];
	char line[MAX_CONF_LEN];

	sup_gamedir_path(path, fullpath);

	file = fopen(fullpath, "r");
	if(!file)
	{
		UTIL_LogPrintf("Unable to open map list file '%s': %s", fullpath, strerror(errno));
		return false;
	}

	for(int i = 1, j = 0; !feof(file); i++)
	{
		if(!fgets(line, sizeof(line), file))
		{
			UTIL_LogPrintf("Unable to read %d line", i);
			break;
		}

		if(line[0] == '#' || line[0] == ';')
			continue;
		if(strnmatch(line, "//", 2))
			continue;

		j = strlen(line) - 1;
		if(line[j] == '\n')
			line[j] = '\0';

		if(!strcmp(map, line))
		{
			fclose(file);
			return true;
		}
	}
	fclose(file);
	return false;
}
示例#6
0
char* FuncGetMap(int id)
{
	FILE *file = NULL;
	const char *path = "AdminMod/maps.txt";
	char fullpath[PATH_MAX];
	static char line[36];

	sup_gamedir_path(path, fullpath);

	file = fopen(fullpath, "r");
	if(!file)
	{
		UTIL_LogPrintf("Unable to open map list file '%s': %s", fullpath, strerror(errno));
		return NULL;
	}

	for(int i = 1, j = 0; !feof(file); i++)
	{
		if(!fgets(line, sizeof(line), file))
		{
			UTIL_LogPrintf("Unable to read %d line", i);
			fclose(file);
			break;
		}

		if(line[0] == '#' || line[0] == ';')
			continue;
		if(strnmatch(line, "//", 2))
			continue;

		j++;
		if(j != id)
			continue;
		break;
	}
	
	if(line[strlen(line) - 1] == '\n')
		line[strlen(line) - 1] = '\0';
	fclose(file);
	return line;
}
示例#7
0
bool FuncIsBanned(const char *name, int &minutes)
{
	FILE *file = NULL;
	const char *path = "AdminMod/banned.txt";
	char fullpath[PATH_MAX];
	char line[MAX_CONF_LEN];
	char *banned = NULL, *date = NULL, *cur = NULL;

	time_t clock = time(NULL);
	tm *ltm = localtime(&clock);

	sup_gamedir_path(path, fullpath);
	LOG_CONSOLE(NULL, "path - %s", fullpath);

	file = fopen(fullpath, "r");
	if(!file)
	{
		UTIL_LogPrintf("Unable to open banned list file '%s': %s", fullpath, strerror(errno));
		return false;
	}

	for(int i = 1, j = 0; !feof(file); i++)
	{
		if(!fgets(line, sizeof(line), file))
		{
			UTIL_LogPrintf("Unable to read %d line in file %s", i, fullpath);
			fclose(file);
			return false;
		}

		if(line[0] == '#' || line[0] == ';')
			continue;
		if(strnmatch(line, "//", 2))
			continue;

		j = strlen(line) - 1;
		if(line[j] == '\n')
			line[j] = '\0';

		banned = strtok(line, "\"");
		if(!banned)
		{
			UTIL_LogPrintf("Invalid parameters at line %d in file %s", i, fullpath);
			fclose(file);
			return false;
		}
		sup_del_quotes(banned);

		if(strcmp(banned, name) == 0)
		{
			minutes = 0;
			date = strtok(NULL, "\n");
			for(USHORT k = 0; k < strlen(date); k++)
				if(date[k] != ' ' && date[k] != '\t')
				{
					STRNCPY(date, date + k, strlen(date));
					break;
				}
			if(date[0] == '-')
			{
				fclose(file);
				return true;
			}

			cur = strtok(date, ":");
			minutes += sup_str_to_int(cur) - ltm->tm_min;
			cur = strtok(NULL, " ");
			minutes += 60 * (sup_str_to_int(cur) - ltm->tm_hour);
			cur = strtok(NULL, ":");
			minutes += 60 * 24 * (sup_str_to_int(cur) - ltm->tm_yday);
			cur = strtok(NULL, ":");
			minutes += 60 * 24 * 30 * (sup_str_to_int(cur) - ltm->tm_year);

			fclose(file);
			if(minutes <= 0)
			{
				FuncRemoveFromBanned(banned);
				return false;
			}
			else return true;
		}
	}

	fclose(file);
	return false;
}
示例#8
0
bool FuncRemoveFromBanned(const char *name)
{
	FILE *file = NULL;
	const char *path = "AdminMod/banned.txt";
	char fullpath[PATH_MAX];
	char line[MAX_CONF_LEN];
	char *banned = NULL;
	int offset = 0, cur = 0;

	sup_gamedir_path(path, fullpath);

	file = fopen(fullpath, "r+");
	if(!file)
	{
		UTIL_LogPrintf("Unable to open banned list file '%s': %s", fullpath, strerror(errno));
		return false;
	}

	for(int i = 1, j = 0; !feof(file); i++)
	{
		if(!fgets(line, sizeof(line), file))
		{
			UTIL_LogPrintf("Unable to read %d line in file %s", i, fullpath);
			fclose(file);
			return false;
		}

		if(line[0] == '#' || line[0] == ';')
			continue;
		if(strnmatch(line, "//", 2))
			continue;

		j = strlen(line) - 1;
		if(line[j] == '\n')
			line[j] = '\0';

		offset = strlen(line);
		banned = strtok(line, "\"");
		if(!banned)
		{
			UTIL_LogPrintf("Invalid parameters at line %d in file %s", i, fullpath);
			fclose(file);
			return false;
		}
		sup_del_quotes(banned);

		LOG_CONSOLE(NULL, "banned - %s; list name - %s", banned, name);
		if(strcmp(banned, name) == 0)
		{
			LOG_CONSOLE(NULL, "size of offset - %d", offset);

			while(1)
			{
				if(fgets(line, sizeof(line), file) == NULL)
				{
					fseek(file, -(offset + 3), SEEK_CUR);
					fputs("\n", file);
					chsize(fileno(file), ftell(file));
					fclose(file);
					return true;
				}
				if(feof(file))
					break;
				LOG_CONSOLE(NULL, "read line - %s", line);
				cur = strlen(line);
				fseek(file, -(cur + offset + 3), SEEK_CUR);
				fputs(line, file);
				fseek(file, offset + 2, SEEK_CUR);
			}

			LOG_CONSOLE(NULL, "read line - %s", line);
			cur = strlen(line);
			fseek(file, -(cur + offset + 2), SEEK_CUR);
			fputs(line, file);
			chsize(fileno(file), ftell(file));
			break;
		}
	}

	fclose(file);
	return true;
}
示例#9
0
uint8_t *_IVParse(SplineFont *sf, char *text, int *len,
		void (*IVError) (void *, char *, int), void *iv) {
   short numberstack[256];
   int npos=0, nread, i;
   int push_left=0, push_size=0;
   char *pt;
   char *end, *bend, *brack;
   int icnt=0, imax=strlen(text)/2, val, temp;
   uint8_t *instrs=malloc(imax);

   for (pt=text; *pt; ++pt) {
      npos=0;
      while (npos<256) {
	 while (*pt==' ' || *pt=='\t')
	    ++pt;
	 if (isdigit(*pt) || *pt=='-') {
	    val=strtol(pt, &end, 0);
	    if (val>32767 || val<-32768) {
	       IVError(iv,"A value must be between [-32768,32767]",
		       pt-text);
	       return (NULL);
	    }

	    pt=end;

	    if (*pt=='@') {	/* a delta control byte */
	       if (val>8 || val<-8 || val==0) {
		  IVError(iv,"A value must be between [-8,-1] or [1,8]",
			  pt-text);
		  return (NULL);
	       }

	       pt++;

	       if (!isdigit(*pt)) {
		  IVError(iv,"Number expected",pt-text);
		  return (NULL);
	       }

	       temp=val;
	       val=strtol(pt, &end, 0);

	       if (val>15 || val<0) {
		  IVError(iv,"A value must be between [0,15]",pt-text);
		  return (NULL);
	       }

	       val *= 16;
	       if (temp<0)
		  temp += 8;
	       else
		  temp += 7;
	       val += temp;
	       pt=end;
	    }

	    numberstack[npos++]=val;
	 } else if (strnmatch(pt, "cvt", 3)==0) {
	    pt += 3;
	    while (*pt==' ' || *pt=='\t')
	       ++pt;
	    if (*pt != '(') {
	       IVError(iv,
		       "Missing left parenthesis in command to get a cvt index",
		       pt-text);
	       return (NULL);
	    }
	    temp=strtol(pt+1, &end, 0);
	    pt=end;
	    while (*pt==' ' || *pt=='\t')
	       ++pt;
	    if (*pt != ')') {
	       IVError(iv,
		       "Missing right paren in command to get a cvt index",
		       pt-text);
	       return (NULL);
	    }
	    numberstack[npos++]=TTF__getcvtval(sf, temp);
	    ++pt;
	 } else
	    break;
      }
      while (*pt==' ' || *pt=='\t')
	 ++pt;
      if (npos==0 && (*pt=='\n' || *pt=='\0'))
	 continue;
      nread=0;
      if (push_left==-1) {
	 /* we need a push count */
	 if (npos==0)
	    IVError(iv, "Expected a number for a push count", pt-text);
	 else if (numberstack[0]>255 || numberstack[0] <= 0) {
	    IVError(iv,
		    "The push count must be a number between 0 and 255",
		    pt-text);
	    return (NULL);
	 } else {
	    nread=1;
	    instrs[icnt++]=numberstack[0];
	    push_left=numberstack[0];
	 }
      }
      if (push_left != 0 && push_left<npos-nread
	  && (*pt=='\n' || *pt=='\0')) {
	 IVError(iv, "More pushes specified than needed", pt-text);
	 return (NULL);
      }
      while (push_left>0 && nread<npos) {
	 if (push_size==2) {
	    instrs[icnt++]=numberstack[nread] >> 8;
	    instrs[icnt++]=numberstack[nread++]&0xff;
	 } else if (numberstack[0]>255 || numberstack[0]<0) {
	    IVError(iv,
		    "A value to be pushed by a byte push must be between 0 and 255",
		    pt-text);
	    return (NULL);
	 } else
	    instrs[icnt++]=numberstack[nread++];
	 --push_left;
      }
示例#10
0
// Parse a player name, userid, wonid, and team,
//    or a Team name,
//    or "World".
//
// Returns an allocated event_player_t struct, which should be freed by the
// main thread after it's no longer needed.  But note that the strings
// contained in the struct refer to the "buf" in the parent event_args_t
// and should _not_ be freed directly; instead, the buf itself should be
// freed when the event_args_t struct is freed by the main thread.
event_player_t *parse_player(char *start, int *retlen) {
	char *cp, *begin, *end;
	int len;
	event_player_t *pl;

	// Create and init the event_player struct
	pl=(event_player_t *) malloc(sizeof(event_player_t));
	if(!pl) 
		return(NULL);
	memset(pl, 0, sizeof(event_player_t));

	cp=start;
	*retlen=0;
	cp+=strspn(cp, " ");

	// ... World ...
	if(strnmatch(cp, "World", 5)) {
		// store team "World"
		begin=cp;
		end=begin+5;
		len=end-begin;

		*end='\0';
		pl->team=begin;
		*retlen=end-start+strspn(end, " ");
		return(pl);
	}
	// ... Team "TERRORIST" ...
	else if(strnmatch(cp, "Team ", 5)) {
		// find team
		begin=strchr(cp+5, '"')+1;
		end=strchr(begin, '"');
		len=end-begin;
		if(len <= 0)
			return(pl);

		// store team
		*end='\0';
		pl->team=begin;
		*retlen=end-start+strspn(end, " ");
		return(pl);
	}
	// ... "Joe<15><785><TERRORIST>" ...
	else if(cp[0] == '"') {
		// find player name
		begin=cp+1;
		end=strchr(begin, '<');
		len=end-begin;
		if(len <= 0) {
			*retlen=begin-1-start;
			return(pl);
		}
		// store player name
		*end='\0';
		pl->name=begin;

		// find userid
		begin=end+1;
		end=strchr(begin, '>');
		len=end-begin;
		if(len <= 0) {
			*retlen=begin-1-start;
			return(pl);
		}
		// store userid
		*end='\0';
		pl->userid=atoi(begin);

		// find wonid
		begin=strchr(end+1, '<')+1;
		end=strchr(begin, '>');
		len=end-begin;
		if(len <= 0) {
			*retlen=begin-1-start;
			return(pl);
		}
		// store wonid
		*end='\0';
		pl->wonid=atoi(begin);

		// find team
		begin=strchr(end+1, '<')+1;
		end=strchr(begin, '>');
		len=end-begin;
		if(len <= 0) {
			*retlen=begin-1-start;
			return(pl);
		}
		// store team
		*end='\0';
		pl->team=begin;

		*retlen=end-start+strspn(end, " ");
		return(pl);
	}
	else {
		// No player strings found, so we go ahead and free the struct we
		// malloc'd at the beginning.
		free(pl);
		return(NULL);
	}
}
示例#11
0
// Pre-parse logmsg line for args and to determine some possible type of
// event.
//
// Returns an allocated event_args_t struct, which should be freed by the
// main thread after it's no longer needed.  Note that this struct gets
// passed to (possibly) multiple hooks.
event_args_t *parse_event_args(const char *logline) {
	event_args_t *args;
	char *cp, *begin, *end;
	int len;

	// Create and init the event_args struct.
	args=(event_args_t *) malloc(sizeof(event_args_t));
	if(!args) 
		return(NULL);
	memset(args, 0, sizeof(*args));

	// Make a copy of the logline, as we're going to be setting NULLs in
	// the string to mark ends of various substrings.
	args->buf=strdup(logline);
	if(!args->buf) 
		return(NULL);
	cp=args->buf;

	// Grab the player name and attributes, or "world" or "team" name, ie:
	//    Joe<15><785><CT>
	//    World
	//    Team "CT"
	args->player=parse_player(cp, &len);
	cp+=len;

	// Look for one of several pre-determined actions that we recognize.

	// ... triggered "some action" ...
	// ie:   "Joe<15><785><CT>" triggered "Killed_A_Hostage"
	if(strnmatch(cp, "triggered ", 10)) {
		cp+=10;
		args->action=parse_quoted(cp, &len);
		cp+=len;
	}
	// ... killed Joe<15><785><CT> ...
	// ie:    "Joe<15><785><CT>" killed "Sam<17><197><TERRORIST>" with "sg552"
	else if(strnmatch(cp, "killed ", 7)) {
		cp+=7;
		args->target=parse_player(cp, &len);
		if(strmatch(args->player->team, args->target->team)) {
			args->action="team_kill";
			args->evtype=EV_TEAM_KILL;
		}
		else {
			args->action="kill";
		}
		cp+=len;
	}
	// ... committed suicide ...
	// ie:   "Joe<15><785><CT>" committed suicide with "worldspawn"
	else if(strnmatch(cp, "committed suicide", 17)) {
		cp+=17;
		args->action="suicide";
		cp+=strspn(cp, " ");
		args->evtype=EV_PLAYER_SUICIDE;
	}
	// ... joined team "someteam" ...
	// ie:   "Joe<15><785><>" joined team "CT"
	else if(strnmatch(cp, "joined team ", 12)) {
		cp+=12;
		args->action="join_team";
		args->target=(event_player_t *) malloc(sizeof(event_player_t));
		// Note:
		//    old team is in:   args->player->team
		//    new team is in:   args->target->team
		if(args->target) {
			memset(args->target, 0, sizeof(event_player_t));
			args->target->team=parse_quoted(cp, &len);
			cp+=len;
		}
		args->evtype=EV_PLAYER_JOIN_TEAM;
	}
	// ... changed role to "something" ...
	// from TFC, ie:   "Joe<15><785><Red>" changed role to "Pyro"
	else if(strnmatch(cp, "changed role to ", 16)) {
		cp+=16;
		args->action="change_role";
		// Note:
		//    new role is in:   args->with
		args->with=parse_quoted(cp, &len);
		cp+=len;
		args->evtype=EV_PLAYER_CHANGE_ROLE;
	}
	// ... scored ...
	// ie: Team "CT" scored "7" with "2" players
	else if(strnmatch(cp, "scored ", 7)) {
		cp+=7;
		if(args->player && args->player->team && !args->player->name) {
			args->action="team_score";
			args->evtype=EV_TEAM_SCORE;
		}
		else {
			args->action="score";
		}
		cp+=strspn(cp, " ");
	}
	// anything else...
	// Consider any words up to a quote (") to be the 'action'.
	else {
		begin=cp;
		end=strchr(begin, '"')-1;
		len=end-begin;
		if(len > 0) {
			*end='\0';
			args->action=begin;
			cp=end+1;
			cp+=strspn(cp, " ");
		}
	}

	// Look for associated phrases...

	// ... against ...
	// ie:   "Joe<15><785><Red>" triggered "Medic_Heal" against "Bob<27><954><Red>"
	if(strnmatch(cp, "against ", 8)) {
		cp+=8;
		args->target=parse_player(cp, &len);
		cp+=len;
	}

	// ... with ...
	// ie:    "Joe<15><785><CT>" killed "Sam<17><197><TERRORIST>" with "sg552"
	// or:    "Joe<15><785><Blue>" triggered "Sentry_Destroyed" against "Sam<17><197><Red>" with "mirvgrenade"
	if(strnmatch(cp, "with ", 5)) {
		cp+=5;
		args->with=parse_quoted(cp, &len);
		if(strmatch(args->action, "kill")) {
			args->action="weapon_kill";
			args->evtype=EV_WEAPON_KILL;
		}
		cp+=len;
	}

	return(args);
}
示例#12
0
/** 
 * Check header to see whether the version matches.
 * 
 * @param fp [in] file pointer
 */
static boolean
check_header(FILE *fp)
{
  char buf[BINGRAM_HDSIZE], *p;

  rdn(fp, buf, 1, BINGRAM_HDSIZE);
  p = buf;
#ifdef WORDS_INT
  need_conv = FALSE;
#endif

  /* version check */
  if (strnmatch(p, BINGRAM_IDSTR, strlen(BINGRAM_IDSTR))) {
    /* bingram file made by mkbingram before 3.4.2 */
    file_version = 3;
    p += strlen(BINGRAM_IDSTR) + 1;
  } else if (strnmatch(p, BINGRAM_IDSTR_V4, strlen(BINGRAM_IDSTR_V4))) {
    /* bingram file made by mkbingram later than 3.5 */
    file_version = 4;
    p += strlen(BINGRAM_IDSTR_V4) + 1;
  } else if (strnmatch(p, BINGRAM_IDSTR_V5, strlen(BINGRAM_IDSTR_V5))) {
    /* bingram file made by JuliusLib-4 and later */
    file_version = 5;
    p += strlen(BINGRAM_IDSTR_V5) + 1;
  } else {
    /* not a bingram file */
    jlog("Error: ngram_read_bin: invalid header\n");
    return FALSE;
  }
  /* word size check (for bingram build by mkbingram 3.3p5 and later */
  if (strnmatch(p, BINGRAM_SIZESTR_HEAD, strlen(BINGRAM_SIZESTR_HEAD))) {
    p += strlen(BINGRAM_SIZESTR_HEAD);
    if (! strnmatch(p, BINGRAM_SIZESTR_BODY, strlen(BINGRAM_SIZESTR_BODY))) {
      /* word size does not match (int / short) */
#ifdef WORDS_INT
      if (strnmatch(p, BINGRAM_SIZESTR_BODY_2BYTE, strlen(BINGRAM_SIZESTR_BODY_2BYTE))) {
	/* this is 2-byte word ID, will convert while reading */
	jlog("Warning: ngram_read_bin: 2-bytes bingram, converting to 4 bytes\n");
	need_conv = TRUE;
	p += strlen(BINGRAM_SIZESTR_BODY_2BYTE) + 1;
      } else {
	jlog("Error: ngram_read_bin: unknown word byte size!\n");
	return FALSE;
      }
#else
      if (strnmatch(p, BINGRAM_SIZESTR_BODY_4BYTE, strlen(BINGRAM_SIZESTR_BODY_4BYTE))) {
	/*** 4bytes to 2bytes not implemented, just terminate here... ***/
	jlog("Error: ngram_read_bin: cannot handle 4-bytes bingram\n");
	jlog("Error: ngram_read_bin: please use Julius compiled with --enable-words-int\n");
	return FALSE;
	//p += strlen(BINGRAM_SIZESTR_BODY_4BYTE) + 1;
      } else {
	jlog("Error: ngram_read_bin: unknown word byte size!\n");
	return FALSE;
      }
#endif
    } else {
      p += strlen(BINGRAM_SIZESTR_BODY) + 1;
    }

    /* byte order check (v4 (rev.3.5) and later) */
    if (file_version >= 4) {
      if (!strnmatch(p, BINGRAM_BYTEORDER_HEAD, strlen(BINGRAM_BYTEORDER_HEAD))) {
	jlog("Error: ngram_read_bin: no information for byte order??\n");
	return FALSE;
      }
      p += strlen(BINGRAM_BYTEORDER_HEAD);
      if (! strnmatch(p, BINGRAM_NATURAL_BYTEORDER, strlen(BINGRAM_NATURAL_BYTEORDER))) {
	/* file endian and running endian is different, need swapping */
	need_swap = TRUE;
      } else {
	need_swap = FALSE;
      }
      p += strlen(BINGRAM_NATURAL_BYTEORDER) + 1;
    }
  } /* if no BINGRAM_SIZESTR_HEAD found, just pass it */

  /* in case of V3 bingram file, the unit size of word_id and its byte order
     cannot be determined from the header.  In that case, we assume 
     byteorder to be a BIG ENDIAN.  The word_id unit size (2byte in normal,
     or 4byte if bingram generated with mkbingram with --enable-words-int)
     will be automagically detected.
     */

  if (file_version < 4) {
    /* assume input as big endian */
#ifdef WORDS_BIGENDIAN
    need_swap = FALSE;
#else
    need_swap = TRUE;
#endif
  }
    
  /*jlog("%s",buf);*/

  return TRUE;
}
/**
 * Sub function to Add a dictionary entry line to the word dictionary.
 *
 * @param buf [i/o] buffer to hold the input string, will be modified in this function
 * @param vnum_p [in] current number of words in @a winfo
 * @param linenum [in] current line number of the input
 * @param winfo [out] pointer to word dictionary to append the data.
 * @param hmminfo [in] HTK %HMM definition data.  if NULL, phonemes are ignored.
 * @param do_conv [in] TRUE if performing triphone conversion
 * @param ok_flag [out] will be set to FALSE if an error occured for this input.
 * @param headphone [in] word head silence model name
 * @param tailphone [in] word tail silence model name
 * @param contextphone [in] silence context name to be used at head and tail
 *
 * @return FALSE if buf == "DICEND", else TRUE will be returned.
 */
boolean
voca_load_wordlist_line(char *buf, WORD_ID *vnum_p, int linenum, WORD_INFO *winfo, HTK_HMM_INFO *hmminfo, boolean do_conv, boolean *ok_flag, char *headphone, char *tailphone, char *contextphone)
{
    char *ptmp, *lp = NULL, *p;
    static char cbuf[MAX_HMMNAME_LEN];
    static HMM_Logical **tmpwseq = NULL;
    static int tmpmaxlen;
    int len;
    HMM_Logical *tmplg;
    boolean pok, first;
    int vnum;

    vnum = *vnum_p;

    if (strmatch(buf, "DICEND")) return FALSE;

    /* allocate temporal work area for the first call */
    if (tmpwseq == NULL) {
        tmpmaxlen = PHONEMELEN_STEP;
        tmpwseq = (HMM_Logical **)mymalloc(sizeof(HMM_Logical *) * tmpmaxlen);
    }

    /* backup whole line for debug output */
    strcpy(bufbak, buf);

    /* Output string */
    if ((ptmp = mystrtok_quote(buf, " \t\n")) == NULL) {
        jlog("Error: voca_load_wordlist: line %d: corrupted data:\n> %s\n", linenum, bufbak);
        winfo->errnum++;
        *ok_flag = FALSE;
        return TRUE;
    }
    winfo->wname[vnum] = strcpy((char *)mybmalloc2(strlen(ptmp)+1, &(winfo->mroot)), ptmp);

    /* reset transparent flag */
    winfo->is_transparent[vnum] = FALSE;

    /* just move pointer to next token */
    if ((ptmp = mystrtok_movetonext(NULL, " \t\n")) == NULL) {
        jlog("Error: voca_load_wordlist: line %d: corrupted data:\n> %s\n", linenum, bufbak);
        winfo->errnum++;
        *ok_flag = FALSE;
        return TRUE;
    }
#ifdef CLASS_NGRAM
    winfo->cprob[vnum] = 0.0;	/* prob = 1.0, logprob = 0.0 */
#endif

    if (ptmp[0] == '@') {		/* class N-gram prob */
#ifdef CLASS_NGRAM
        /* word probability within the class (for class N-gram) */
        /* format: classname @classprob wordname [output] phoneseq */
        /* classname equals to wname, and wordname will be omitted */
        /* format: @%f (log scale) */
        /* if "@" not found or "@0", it means class == word */
        if ((ptmp = mystrtok(NULL, " \t\n")) == NULL) {
            jlog("Error: voca_load_wordlist: line %d: corrupted data:\n> %s\n", linenum, bufbak);
            winfo->errnum++;
            *ok_flag = FALSE;
            return TRUE;
        }
        if (ptmp[1] == '\0') {	/* space between '@' and figures */
            jlog("Error: voca_load_wordlist: line %d: value after '@' missing, maybe wrong space?\n> %s\n", linenum, bufbak);
            winfo->errnum++;
            *ok_flag = FALSE;
            return TRUE;
        }
        winfo->cprob[vnum] = atof(&(ptmp[1]));
        if (winfo->cprob[vnum] != 0.0) winfo->cwnum++;
        /* read next word entry (just skip them) */
        if ((ptmp = mystrtok(NULL, " \t\n")) == NULL) {
            jlog("Error: voca_load_wordlist: line %d: corrupted data:\n> %s\n", linenum,bufbak);
            winfo->errnum++;
            *ok_flag = FALSE;
            return TRUE;
        }
        /* move to the next word entry */
        if ((ptmp = mystrtok_movetonext(NULL, " \t\n")) == NULL) {
            jlog("Error: voca_load_wordlist: line %d: corrupted data:\n> %s\n", linenum, bufbak);
            winfo->errnum++;
            *ok_flag = FALSE;
            return TRUE;
        }
#else  /* ~CLASS_NGRAM */
        jlog("Error: voca_load_wordlist: line %d: cannot handle in-class word probability\n> %s\n", linenum, ptmp, bufbak);
        winfo->errnum++;
        *ok_flag = FALSE;
        return TRUE;
#endif /* CLASS_NGRAM */
    }

    /* OutputString */
    switch(ptmp[0]) {
    case '[':			/* ignore transparency */
        ptmp = mystrtok_quotation(NULL, " \t\n", '[', ']', 0);
        break;
    case '{':			/* ignore transparency */
        ptmp = mystrtok_quotation(NULL, " \t\n", '{', '}', 0);
        break;
    default:
        /* ALLOW no entry for output */
        /* same as wname is used */
        ptmp = winfo->wname[vnum];
    }
    if (ptmp == NULL) {
        jlog("Error: voca_load_htkdict: line %d: corrupted data:\n> %s\n", linenum, bufbak);
        winfo->errnum++;
        *ok_flag = FALSE;
        return TRUE;
    }
    winfo->woutput[vnum] = strcpy((char *)mybmalloc2(strlen(ptmp)+1, &(winfo->mroot)), ptmp);

    /* phoneme sequence */
    if (hmminfo == NULL) {
        /* don't read */
        winfo->wseq[vnum] = NULL;
        winfo->wlen[vnum] = 0;
    } else {

        len = 0;
        first = TRUE;
        pok = TRUE;

        for (;;) {
            if (do_conv) {
                if (first) {
                    /* init phone cycler */
                    cycle_triphone(NULL);
                    /* insert head phone at beginning of word */
                    if (contextphone) {
                        if (strlen(contextphone) >= MAX_HMMNAME_LEN) {
                            jlog("Error: voca_load_htkdict: line %d: too long phone name: %s\n", linenum, contextphone);
                            winfo->errnum++;
                            *ok_flag = FALSE;
                            return TRUE;
                        }
                        cycle_triphone(contextphone);
                    } else {
                        cycle_triphone("NULL_C");
                    }
                    if ((lp = mystrtok(NULL, " \t\n")) == NULL) {
                        jlog("Error: voca_load_wordlist: line %d: word %s has no phoneme:\n> %s\n", linenum, winfo->wname[vnum], bufbak);
                        winfo->errnum++;
                        *ok_flag = FALSE;
                        return TRUE;
                    }
                    if (strlen(lp) >= MAX_HMMNAME_LEN) {
                        jlog("Error: voca_load_htkdict: line %d: too long phone name: %s\n", linenum, lp);
                        winfo->errnum++;
                        *ok_flag = FALSE;
                        return TRUE;
                    }
                    p = cycle_triphone(lp);
                    first = FALSE;
                } else {		/* do_conv, not first */
                    if (lp != NULL) {	/* some token processed at last loop */
                        lp = mystrtok(NULL, " \t\n");
                        if (lp != NULL) {
                            /* token exist */
                            if (strlen(lp) >= MAX_HMMNAME_LEN) {
                                jlog("Error: voca_load_htkdict: line %d: too long phone name: %s\n", linenum, lp);
                                winfo->errnum++;
                                *ok_flag = FALSE;
                                return TRUE;
                            }
                            p = cycle_triphone(lp);
                        } else {
                            /* no more token, insert tail phone at end of word */
                            if (contextphone) {
                                if (strlen(contextphone) >= MAX_HMMNAME_LEN) {
                                    jlog("Error: voca_load_htkdict: line %d: too long phone name: %s\n", linenum, contextphone);
                                    winfo->errnum++;
                                    *ok_flag = FALSE;
                                    return TRUE;
                                }
                                p = cycle_triphone(contextphone);
                            } else {
                                p = cycle_triphone("NULL_C");
                            }
                        }
                    } else {		/* no more token at last input  */
                        /* flush tone cycler */
                        p = cycle_triphone_flush();
                    }
                }
            } else {			/* not do_conv */
                if (first) {
                    p = lp = headphone;
                    first = FALSE;
                } else {
                    if (lp != NULL) {	/* some token processed at last loop */
                        p = lp = mystrtok(NULL, " \t\n");
                        /* if no more token, use tailphone */
                        if (lp == NULL) p = tailphone;
                    } else {
                        /* no more token at last input, exit loop */
                        p = NULL;
                    }
                }
            }
            if (p == NULL) break;
            /* for headphone and tailphone, their context should not be handled */
            /* and when they appear as context they should be replaced by contextphone */
            if (do_conv) {
                center_name(p, cbuf);
                if (contextphone) {
                    if (strmatch(cbuf, contextphone)) {
                        if (len == 0) {
                            p = headphone;
                        } else if (lp == NULL) {
                            p = tailphone;
                        }
                    }
                } else {
                    if (strmatch(cbuf, "NULL_C")) {
                        if (len == 0) {
                            p = headphone;
                        } else if (lp == NULL) {
                            p = tailphone;
                        }
                    } else {
                        if (strnmatch(p, "NULL_C", 6)) {
                            if (strnmatch(&(p[strlen(p)-6]), "NULL_C", 6)) {
                                p = cbuf;
                            } else {
                                p = rightcenter_name(p, cbuf);
                            }
                        } else if (strnmatch(&(p[strlen(p)-6]), "NULL_C", 6)) {
                            p = leftcenter_name(p, cbuf);
                        }
                    }
                }
            }
            //printf("[[%s]]\n", p);

            /* both defined/pseudo phone is allowed */
            tmplg = htk_hmmdata_lookup_logical(hmminfo, p);
            if (tmplg == NULL) {
                /* not found */
                if (do_conv) {
                    /* logical phone was not found */
                    jlog("Error: voca_load_wordlist: line %d: logical phone \"%s\" not found\n", linenum, p);
                    snprintf(cbuf,MAX_HMMNAME_LEN,"%s", p);
                } else {
                    jlog("Error: voca_load_wordlist: line %d: phone \"%s\" not found\n", linenum, p);
                    snprintf(cbuf, MAX_HMMNAME_LEN, "%s", p);
                }
                add_to_error(winfo, cbuf);
                pok = FALSE;
            } else {
                /* found */
                if (len >= tmpmaxlen) {
                    /* expand wseq area by PHONEMELEN_STEP */
                    tmpmaxlen += PHONEMELEN_STEP;
                    tmpwseq = (HMM_Logical **)myrealloc(tmpwseq, sizeof(HMM_Logical *) * tmpmaxlen);
                }
                /* store to temporal buffer */
                tmpwseq[len] = tmplg;
            }
            len++;
        }
        if (!pok) {			/* error in phoneme */
            jlog("Error: voca_load_wordlist: the line content was: %s\n", bufbak);
            winfo->errnum++;
            *ok_flag = FALSE;
            return TRUE;
        }
        if (len == 0) {
            jlog("Error: voca_load_wordlist: line %d: no phone specified:\n> %s\n", linenum, bufbak);
            winfo->errnum++;
            *ok_flag = FALSE;
            return TRUE;
        }
        /* store to winfo */
        winfo->wseq[vnum] = (HMM_Logical **)mybmalloc2(sizeof(HMM_Logical *) * len, &(winfo->mroot));
        memcpy(winfo->wseq[vnum], tmpwseq, sizeof(HMM_Logical *) * len);
        winfo->wlen[vnum] = len;
        winfo->wton[vnum] = 0;
    }

    vnum++;
    *vnum_p = vnum;

    return(TRUE);
}
/*
** A "local" function of MatchFilter().  Returns 1 or 0 depending on whether or
** not #item# contains the first attribute specified by #filter#.  Updates
** #filter# to point to the next attribute.
*/
static int
MatchFilterAndUpdate(const char *item,
                     const char **filter) {

  char firstChar;
  const char *itemAttribute;
  char operator;
  int returnValue;
  char simpleName[127 + 1];
  char simplePattern[127 + 1];
  const char *value;
  const char *valueEnd;
  size_t valueLen;

  /* Allow leading and trailing spaces for legibility. */
  while(**filter == ' ')
    (*filter)++;
  firstChar = **filter;

  if(firstChar == '(') {
    /* Nested pattern. */
    (*filter)++;
    returnValue = MatchFilterAndUpdate(item, filter);
    if(**filter == ')')
      (*filter)++;
  }
  else if((firstChar == '!') || (firstChar == '|') || (firstChar == '&')) {
    /* Prefix operator: unary not, n-ary or, n-ary and */
    (*filter)++;
    if(firstChar == '!') {
      returnValue = !MatchFilterAndUpdate(item, filter);
    }
    else {
      returnValue = firstChar == '&';
      /* To advance filter correctly we must avoid short-circuit matches. */
      while((**filter != '\0') && (**filter != ')')) {
        if(MatchFilterAndUpdate(item, filter)) {
          if(firstChar == '|')
            returnValue = 1;
        }
        else if(firstChar == '&')
          returnValue = 0;
      }
    }
  }
  else {
    /* Grab the individual parts of the <attribute><op><pattern> pair. */
    if(!GETTOK(simpleName, *filter, "<=>~", filter))
      FAIL1("MatchFilterAndUpdate: parse error in %s\n", filter);
    strcat(simpleName, ":");
    operator = **filter;
    if(operator != '=') {
      (*filter)++; /* Skip < > or ~ */
      if(**filter != '=')
        FAIL1("MatchFilterAndUpdate: parse error in %s\n", filter);
    }
    (*filter)++; /* Skip '=' */
    if(!GETTOK(simplePattern, *filter, ") ", filter))
      FAIL1("MatchFilterAndUpdate: parse error in %s\n", filter);
    /* Now match against the value of each occurence of <attribute> in item. */
    for(itemAttribute = strstr(item, simpleName); itemAttribute != NULL;
        itemAttribute = strstr(itemAttribute + 1, simpleName)) {
      value = itemAttribute + strlen(simpleName);
      valueEnd = strchr(value, '\t');
      valueLen = (valueEnd == NULL) ? strlen(value) : (valueEnd - value);
      if((operator == '=') && strnmatch(value, simplePattern, valueLen))
        break;
      else if((operator == '<') &&
              (strncmp(value, simplePattern, valueLen) <= 0))
        break;
      else if((operator == '>') &&
              (strncmp(value, simplePattern, valueLen) >= 0))
        break;
      else if((operator == '~') && strnmatch(value, simplePattern, valueLen))
        /* We recognize ~= but treat it as simple = */
        break;
    }
    returnValue = itemAttribute != NULL;
  }

  while(**filter == ' ')
    (*filter)++;
  return returnValue;

}