示例#1
0
文件: header.c 项目: tridge/junkcode
/* read in the headers */
void header_load(FILE *f)
{
    char line[1024];

    header_clear();

    while (1) {
        char *p;

        if (!fgets_strip(line, sizeof(line)-1, f)) {
            errmsg("Failed to read header %d\n", num_headers);
            exit_cleanup(1);
        }

        /* it may be the end of the headers */
        if (line[0] == 0) break;

        p = strchr(line,':');
        if (!p) {
            errmsg("no colon in header?!? [%s]\n", line);
            exit_cleanup(1);
        }

        *p++ = 0;
        while (*p && isspace(*p)) p++;

        header_add(line, p);
    }
}
示例#2
0
voice_t *LoadVoice(const char *vname, int control)
{//===============================================
// control, bit 0  1= no_default
//          bit 1  1 = change tone only, not language
//          bit 2  1 = don't report error on LoadDictionary
//          bit 4  1 = vname = full path

	FILE *f_voice = NULL;
	char *p;
	int  key;
	int  ix;
	int  n;
	int  value;
	int  value2;
	int  langix = 0;
	int  tone_only = control & 2;
	int  language_set = 0;
	int  phonemes_set = 0;
	int  stress_amps_set = 0;
	int  stress_lengths_set = 0;
	int  stress_add_set = 0;
	int  conditional_rules = 0;
	LANGUAGE_OPTIONS *langopts = NULL;

	Translator *new_translator = NULL;

	char voicename[40];
	char language_name[40];
	char translator_name[40];
	char new_dictionary[40];
	char phonemes_name[40];
	char option_name[40];
	const char *language_type;
	char buf[sizeof(path_home)+30];
	char path_voices[sizeof(path_home)+12];

	int dict_min = 0;
	int stress_amps[8];
	int stress_lengths[8];
	int stress_add[8];
	char names[8][40];
	char name1[40];
	char name2[80];
	const char *voice_dir;

	int pitch1;
	int pitch2;

	static char voice_identifier[40];  // file name for  current_voice_selected
	static char voice_name[40];        // voice name for current_voice_selected
	static char voice_languages[100];  // list of languages and priorities for current_voice_selected

	// which directory to look for a named voice. List of voice names, must end in a space.
	static const char *voices_asia =
		"az bn fa fa-pin gu hi hy hy-west id ka kn ku ml ms ne pa ta te tr vi vi-hue vi-sgn zh zh-yue ";
	static const char *voices_europe =
		"an bg bs ca cs cy da de el en en-us es et eu fi fr fr-be ga hr hu is it lt lv mk nl no pl pt-pt ro ru sk sq sr sv ";


	strncpy0(voicename, vname, sizeof(voicename));
	if(control & 0x10)
	{
		strcpy(buf,vname);
		if(GetFileLength(buf) <= 0)
			return(NULL);
	}
	else
	{
		if(voicename[0]==0)
			strcpy(voicename,"default");

		sprintf(path_voices,"%s%cvoices%c",path_home,PATHSEP,PATHSEP);
		sprintf(buf,"%s%s",path_voices,voicename);  // first, look in the main voices directory

		if(GetFileLength(buf) <= 0)
		{
			// then look in the appropriate subdirectory
			if((voicename[0]=='m') && (voicename[1]=='b'))
			{
				voice_dir = "mb";   // mbrola voices
			}
			else
			{
				sprintf(name2, "%s ", voicename);
				if(strstr(voices_europe, voicename) != NULL)
					voice_dir = "europe";
				else if(strstr(voices_asia, voicename) != NULL)
					voice_dir = "asia";
				else
					voice_dir = "other";

				sprintf(buf,"%s%s%c%s", path_voices,voice_dir,PATHSEP,voicename);

				if(GetFileLength(buf) <= 0)
				{
					// if not found, look in "test" sub-directory
					sprintf(buf,"%stest%c%s",path_voices,PATHSEP,voicename);
				}
			}
		}
	}

	f_voice = fopen(buf,"r");

	language_type = "en";    // default
	if(f_voice == NULL)
	{
		if(control & 3)
			return(NULL);  // can't open file

		if(SelectPhonemeTableName(voicename) >= 0)
			language_type = voicename;
	}

	if(!tone_only && (translator != NULL))
	{
		DeleteTranslator(translator);
		translator = NULL;
	}

	strcpy(translator_name,language_type);
	strcpy(new_dictionary,language_type);
	strcpy(phonemes_name,language_type);


	if(!tone_only)
	{
		voice = &voicedata;
		strncpy0(voice_identifier,vname,sizeof(voice_identifier));
		voice_name[0] = 0;
		voice_languages[0] = 0;

		current_voice_selected.identifier = voice_identifier;
		current_voice_selected.name = voice_name;
		current_voice_selected.languages = voice_languages;
	}
	else
	{
		// append the variant file name to the voice identifier
		if((p = strchr(voice_identifier,'+')) != NULL)
			*p = 0;    // remove previous variant name
		sprintf(buf,"+%s",&vname[3]);    // omit  !v/  from the variant filename
		strcat(voice_identifier,buf);
		langopts = &translator->langopts;
	}
	VoiceReset(tone_only);

	if(!tone_only)
		SelectPhonemeTableName(phonemes_name);  // set up phoneme_tab


	while((f_voice != NULL) && (fgets_strip(buf,sizeof(buf),f_voice) != NULL))
	{
		// isolate the attribute name
		for(p=buf; (*p != 0) && !isspace(*p); p++);
		*p++ = 0;

		if(buf[0] == 0) continue;

		key = LookupMnem(keyword_tab, buf);

		switch(key)
		{
		case V_LANGUAGE:
		{
			unsigned int len;
			int priority;

			if(tone_only)
				break;

			priority = DEFAULT_LANGUAGE_PRIORITY;
			language_name[0] = 0;

			sscanf(p,"%s %d",language_name,&priority);
			if(strcmp(language_name,"variant") == 0)
				break;

			len = strlen(language_name) + 2;
			// check for space in languages[]
			if(len < (sizeof(voice_languages)-langix-1))
			{
				voice_languages[langix] = priority;

				strcpy(&voice_languages[langix+1],language_name);
				langix += len;
			}

			// only act on the first language line
			if(language_set == 0)
			{
				language_type = strtok(language_name,"-");
				language_set = 1;
				strcpy(translator_name,language_type);
				strcpy(new_dictionary,language_type);
				strcpy(phonemes_name,language_type);
				SelectPhonemeTableName(phonemes_name);

				if(new_translator != NULL)
					DeleteTranslator(new_translator);

				new_translator = SelectTranslator(translator_name);
				langopts = &new_translator->langopts;
				strncpy0(voice->language_name, language_name, sizeof(voice->language_name));
			}
		}
		break;

		case V_NAME:
			if(tone_only == 0)
			{
				while(isspace(*p)) p++;
				strncpy0(voice_name,p,sizeof(voice_name));
			}
			break;

		case V_GENDER:
		{
			int age = 0;
			char vgender[80];
			sscanf(p,"%s %d",vgender,&age);
			current_voice_selected.gender = LookupMnem(genders,vgender);
			current_voice_selected.age = age;
		}
		break;

		case V_TRANSLATOR:
			if(tone_only) break;

			sscanf(p,"%s",translator_name);

			if(new_translator != NULL)
				DeleteTranslator(new_translator);

			new_translator = SelectTranslator(translator_name);
			langopts = &new_translator->langopts;
			break;

		case V_DICTIONARY:        // dictionary
			sscanf(p,"%s",new_dictionary);
			break;

		case V_PHONEMES:        // phoneme table
			sscanf(p,"%s",phonemes_name);
			break;

		case V_FORMANT:
			VoiceFormant(p);
			break;

		case V_PITCH:
		{
			double factor;
			// default is  pitch 82 118
			n = sscanf(p,"%d %d",&pitch1,&pitch2);
			voice->pitch_base = (pitch1 - 9) << 12;
			voice->pitch_range = (pitch2 - pitch1) * 108;
			factor = (double)(pitch1 - 82)/82;
			voice->formant_factor = (int)((1+factor/4) * 256);  // nominal formant shift for a different voice pitch
		}
		break;

		case V_STRESSLENGTH:   // stressLength
			stress_lengths_set = Read8Numbers(p,stress_lengths);
			break;

		case V_STRESSAMP:   // stressAmp
			stress_amps_set = Read8Numbers(p,stress_amps);
			break;

		case V_STRESSADD:   // stressAdd
			stress_add_set = Read8Numbers(p,stress_add);
			break;

		case V_INTONATION:   // intonation
			sscanf(p,"%d %d",&option_tone_flags,&option_tone2);
			if((option_tone_flags & 0xff) != 0)
				langopts->intonation_group = option_tone_flags & 0xff;
			break;

		case V_TUNES:
			n = sscanf(p,"%s %s %s %s %s %s",names[0],names[1],names[2],names[3],names[4],names[5]);
			langopts->intonation_group = 0;
			for(ix=0; ix<n; ix++)
			{
				if(strcmp(names[ix],"NULL")==0)
					continue;

				if((value = LookupTune(names[ix])) < 0)
					fprintf(stderr,"Unknown tune '%s'\n",names[ix]);
				else
					langopts->tunes[ix] = value;
			}
			break;

		case V_DICTRULES:   // conditional dictionary rules and list entries
		case V_NUMBERS:
		case V_STRESSOPT:
			// expect a list of numbers
			while(*p != 0)
			{
				while(isspace(*p)) p++;
				n = -1;
				if((n = atoi(p)) > 0)
				{
					p++;
					if(n < 32)
					{
						if(key==V_DICTRULES)
							conditional_rules |= (1 << n);
						else if(key==V_NUMBERS)
							langopts->numbers |= (1 << n);
						else if(key==V_STRESSOPT)
							langopts->stress_flags |= (1 << n);
					}
					else
					{
						if((key==V_NUMBERS) && (n < 64))
							langopts->numbers |= (1 << (n-32));
						else
							fprintf(stderr,"Bad option number %d\n", n);
					}
				}
				while(isalnum(*p)) p++;
			}
			ProcessLanguageOptions(langopts);
			break;

		case V_REPLACE:
			if(phonemes_set == 0)
			{
				// must set up a phoneme table before we can lookup phoneme mnemonics
				SelectPhonemeTableName(phonemes_name);
				phonemes_set = 1;
			}
			PhonemeReplacement(key,p);
			break;

		case V_WORDGAP:   // words
			sscanf(p,"%d %d",&langopts->word_gap, &langopts->vowel_pause);
			break;

		case V_STRESSRULE:
			sscanf(p,"%d %d %d %d",&langopts->stress_rule,
				   &langopts->stress_flags,
				   &langopts->unstressed_wd1,
				   &langopts->unstressed_wd2);
			break;

		case V_CHARSET:
			if((sscanf(p,"%d",&value)==1) && (value < N_CHARSETS))
				new_translator->charset_a0 = charsets[value];
			break;

		case V_OPTION:
			value2 = 0;
			if(((sscanf(p,"%s %d %d",option_name,&value,&value2) >= 2) && ((ix = LookupMnem(options_tab, option_name)) >= 0)) ||
				((sscanf(p,"%d %d %d",&ix,&value,&value2) >= 2) && (ix < N_LOPTS)))
			{
				langopts->param[ix] = value;
				langopts->param2[ix] = value2;
			}
			else
			{
				fprintf(stderr,"Bad voice option: %s %s\n",buf,p);
			}
			break;

		case V_ECHO:
			// echo.  suggest: 135mS  11%
			value = 0;
			voice->echo_amp = 0;
			sscanf(p,"%d %d",&voice->echo_delay,&voice->echo_amp);
			break;

		case V_FLUTTER:   // flutter
			if(sscanf(p,"%d",&value)==1)
				voice->flutter = value * 32;
			break;

		case V_ROUGHNESS:   // roughness
			if(sscanf(p,"%d",&value)==1)
				voice->roughness = value;
			break;

		case V_CLARITY:  // formantshape
			if(sscanf(p,"%d",&value)==1)
			{
				if(value > 4)
				{
					voice->peak_shape = 1;  // squarer formant peaks
					value = 4;
				}
				voice->n_harmonic_peaks = 1+value;
			}
			break;

		case V_TONE:
		{
			int tone_data[12];
			ReadTonePoints(p,tone_data);
			SetToneAdjust(voice,tone_data);
		}
		break;

		case V_VOICING:
			if(sscanf(p,"%d",&value)==1)
				voice->voicing = (value * 64)/100;
			break;

		case V_BREATH:
			voice->breath[0] = Read8Numbers(p,&voice->breath[1]);
			for(ix=1; ix<8; ix++)
			{
				if(ix % 2)
					voice->breath[ix] = -voice->breath[ix];
			}
			break;

		case V_BREATHW:
			voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]);
			break;

		case V_CONSONANTS:
			value = sscanf(p,"%d %d",&voice->consonant_amp, &voice->consonant_ampv);
			break;

		case V_SPEED:
			sscanf(p,"%d",&voice->speed_percent);
			break;

		case V_MBROLA:
		{
			int srate = 16000;

			name2[0] = 0;
			sscanf(p,"%s %s %d",name1,name2,&srate);
			if(LoadMbrolaTable(name1,name2,srate) != EE_OK)
			{
				fprintf(stderr,"mbrola voice not found\n");
			}
			voice->samplerate = srate;
		}
		break;

		case V_KLATT:
			voice->klattv[0] = 1;  // default source: IMPULSIVE
			Read8Numbers(p,voice->klattv);
			voice->klattv[KLATT_Kopen] -= 40;
			break;

		case V_FAST:
			Read8Numbers(p,speed.fast_settings);
			SetSpeed(3);
			break;

		case V_DICTMIN:
			sscanf(p,"%d",&dict_min);
			break;

		case V_ALPHABET2:
			{
				ALPHABET *alphabet;
				name1[0] = name2[0] = 0;
				sscanf(p, "%s %s", name1, name2);

				if(strcmp(name1, "latin") == 0)
				{
					strncpy0(langopts->ascii_language,name2,sizeof(langopts->ascii_language));
				}
				else if((alphabet = AlphabetFromName(name1)) != 0)
				{
					langopts->alt_alphabet = alphabet->offset;
					langopts->alt_alphabet_lang = StringToWord2(name2);
				}
				else
				{
					fprintf(stderr,"alphabet name '%s' not found\n", name1);
				}
			}
			break;

		case V_DICTDIALECT:
			// specify a dialect to use for foreign words, eg, en-us for _^_EN
			if(sscanf(p, "%s", name1) == 1)
			{
				if((ix = LookupMnem(dict_dialects, name1)) > 0)
				{
					langopts->dict_dialect |= (1 << ix);
				}
				else
				{
					fprintf(stderr, "dictdialect name '%s' not recognized\n", name1);
				}
			}
			break;

		default:
			if((key & 0xff00) == 0x100)
			{
				sscanf(p,"%d",&langopts->param[key &0xff]);
			}
			else
			{
				fprintf(stderr,"Bad voice attribute: %s\n",buf);
			}
			break;
		}
	}
	if(f_voice != NULL)
		fclose(f_voice);

	if((new_translator == NULL) && (!tone_only))
	{
		// not set by language attribute
		new_translator = SelectTranslator(translator_name);
	}

	SetSpeed(3);   // for speed_percent

	for(ix=0; ix<N_PEAKS; ix++)
	{
		voice->freq2[ix] = voice->freq[ix];
		voice->height2[ix] = voice->height[ix];
		voice->width2[ix] = voice->width[ix];
	}

	if(tone_only)
	{
		new_translator = translator;
	}
	else
	{
		if((ix = SelectPhonemeTableName(phonemes_name)) < 0)
		{
			fprintf(stderr,"Unknown phoneme table: '%s'\n",phonemes_name);
			ix = 0;
		}
		voice->phoneme_tab_ix = ix;
		new_translator->phoneme_tab_ix = ix;
		new_translator->dict_min_size = dict_min;
		LoadDictionary(new_translator, new_dictionary, control & 4);
		if(dictionary_name[0]==0)
			return(NULL);   // no dictionary loaded

		new_translator->dict_condition = conditional_rules;

		voice_languages[langix] = 0;
	}

	langopts = &new_translator->langopts;


	if((value = langopts->param[LOPT_LENGTH_MODS]) != 0)
	{
		SetLengthMods(new_translator,value);
	}

	voice->width[0] = (voice->width[0] * 105)/100;

	if(!tone_only)
	{
		translator = new_translator;
	}


	// relative lengths of different stress syllables
	for(ix=0; ix<stress_lengths_set; ix++)
	{
		translator->stress_lengths[ix] = stress_lengths[ix];
	}
	for(ix=0; ix<stress_add_set; ix++)
	{
		translator->stress_lengths[ix] += stress_add[ix];
	}
	for(ix=0; ix<stress_amps_set; ix++)
	{
		translator->stress_amps[ix] = stress_amps[ix];
		translator->stress_amps_r[ix] = stress_amps[ix] -1;
	}

	return(voice);
}  //  end of LoadVoice
示例#3
0
static espeak_VOICE *ReadVoiceFile(FILE *f_in, const char *fname, const char*leafname)
{//===================================================================================
// Read a Voice file, allocate a VOICE_DATA and set data from the
// file's  language, gender, name  lines

	char linebuf[120];
	char vname[80];
	char vgender[80];
	char vlanguage[80];
	char languages[300];  // allow space for several alternate language names and priorities


	unsigned int len;
	int langix = 0;
	int n_languages = 0;
	char *p;
	espeak_VOICE *voice_data;
	int priority;
	int age;
	int n_variants = 4;    // default, number of variants of this voice before using another voice
	int gender;

#ifdef PLATFORM_WINDOWS
	char fname_buf[sizeof(path_home)+15];
	if(memcmp(leafname,"mb-",3) == 0)
	{
		// check whether the mbrola speech data is present for this voice
		memcpy(vname,&leafname[3],3);
		vname[3] = 0;
		sprintf(fname_buf,"%s/mbrola/%s",path_home,vname);

		if(GetFileLength(fname_buf) <= 0)
			return(0);
	}
#endif

	vname[0] = 0;
	vgender[0] = 0;
	age = 0;

	while(fgets_strip(linebuf,sizeof(linebuf),f_in) != NULL)
	{
		if(memcmp(linebuf,"name",4)==0)
		{
			p = &linebuf[4];
			while(isspace(*p)) p++;
			strncpy0(vname,p,sizeof(vname));
		}
		else if(memcmp(linebuf,"language",8)==0)
		{
			priority = DEFAULT_LANGUAGE_PRIORITY;
			vlanguage[0] = 0;

			sscanf(&linebuf[8],"%s %d",vlanguage,&priority);
			len = strlen(vlanguage) + 2;
			// check for space in languages[]
			if(len < (sizeof(languages)-langix-1))
			{
				languages[langix] = priority;

				strcpy(&languages[langix+1],vlanguage);
				langix += len;
				n_languages++;
			}
		}
		else if(memcmp(linebuf,"gender",6)==0)
		{
			sscanf(&linebuf[6],"%s %d",vgender,&age);
		}
		else if(memcmp(linebuf,"variants",8)==0)
		{
			sscanf(&linebuf[8],"%d",&n_variants);
		}
	}
	languages[langix++] = 0;

	gender = LookupMnem(genders,vgender);

	if(n_languages == 0)
	{
		return(NULL);    // no language lines in the voice file
	}

	p = (char *)calloc(sizeof(espeak_VOICE) + langix + strlen(fname) + strlen(vname) + 3, 1);
	voice_data = (espeak_VOICE *)p;
	p = &p[sizeof(espeak_VOICE)];

	memcpy(p,languages,langix);
	voice_data->languages = p;

	strcpy(&p[langix],fname);
	voice_data->identifier = &p[langix];
	voice_data->name = &p[langix];

	if(vname[0] != 0)
	{
		langix += strlen(fname)+1;
		strcpy(&p[langix],vname);
		voice_data->name = &p[langix];
	}

	voice_data->age = age;
	voice_data->gender = gender;
	voice_data->variant = 0;
	voice_data->xx1 = n_variants;
	return(voice_data);
}  // end of ReadVoiceFile
示例#4
0
文件: voices.c 项目: Jalakas/navit
voice_t *LoadVoice(const char *vname, int control)
{//===============================================
// control, bit 0  1= no_default
//          bit 1  1 = change tone only, not language
//          bit 2  1 = don't report error on LoadDictionary
//          bit 4  1 = vname = full path

	FILE *f_voice = NULL;
	keywtab_t *k;
	char *p;
	int  key;
	int  ix;
	int  n;
	int  value;
	int  error = 0;
	int  langix = 0;
	int  tone_only = control & 2;
	int  language_set = 0;
	int  phonemes_set = 0;
	int  stress_amps_set = 0;
	int  stress_lengths_set = 0;
	int  stress_add_set = 0;
	int  conditional_rules = 0;
	LANGUAGE_OPTIONS *langopts = NULL;

	Translator *new_translator = NULL;

	char voicename[40];
	char language_name[40];
	char translator_name[40];
	char new_dictionary[40];
	char phonemes_name[40];
	const char *language_type;
	char buf[200];
	char path_voices[sizeof(path_home)+12];
	char langname[4];

	int stress_amps[8];
	int stress_lengths[8];
	int stress_add[8];

	int pitch1;
	int pitch2;

	static char voice_identifier[40];  // file name for  voice_selected
	static char voice_name[40];        // voice name for voice_selected
	static char voice_languages[100];  // list of languages and priorities for voice_selected

	strcpy(voicename,vname);
	if(voicename[0]==0)
		strcpy(voicename,"default");

	if(control & 0x10)
	{
		strcpy(buf,vname);
		if(GetFileLength(buf) <= 0)
			return(NULL);
	}
	else
	{
		sprintf(path_voices,"%s%cvoices%c",path_home,PATHSEP,PATHSEP);
		sprintf(buf,"%s%s",path_voices,voicename);

		if(GetFileLength(buf) <= 0)
		{
			// look for the voice in a sub-directory of the language name
			langname[0] = voicename[0];
			langname[1] = voicename[1];
			langname[2] = 0;
			sprintf(buf,"%s%s%c%s",path_voices,langname,PATHSEP,voicename);

			if(GetFileLength(buf) <= 0)
			{
				// look in "test" sub-directory
				sprintf(buf,"%stest%c%s",path_voices,PATHSEP,voicename);
			}
		}
	}

	f_voice = fopen(buf,"r");

	language_type = "en";    // default
	if(f_voice == NULL)
	{
		if(control & 3)
			return(NULL);  // can't open file

		if(SelectPhonemeTableName(voicename) >= 0)
			language_type = voicename;
	}

	if(!tone_only && (translator != NULL))
	{
		DeleteTranslator(translator);
		translator = NULL;
	}

	strcpy(translator_name,language_type);
	strcpy(new_dictionary,language_type);
	strcpy(phonemes_name,language_type);


	if(!tone_only)
	{
		voice = &voicedata;
		strncpy0(voice_identifier,vname,sizeof(voice_identifier));
		voice_name[0] = 0;
		voice_languages[0] = 0;

		voice_selected.identifier = voice_identifier;
		voice_selected.name = voice_name;
		voice_selected.languages = voice_languages;
	}
	else
	{
		// append the variant file name to the voice identifier
		if((p = strchr(voice_identifier,'+')) != NULL)
			*p = 0;    // remove previous variant name
		sprintf(buf,"+%s",&vname[3]);    // omit  !v/  from the variant filename
		strcat(voice_identifier,buf);
		langopts = &translator->langopts;
	}
	VoiceReset(tone_only);

	if(!tone_only)
		SelectPhonemeTableName(phonemes_name);  // set up phoneme_tab


	while((f_voice != NULL) && (fgets_strip(buf,sizeof(buf),f_voice) != NULL))
	{
		// isolate the attribute name
		for(p=buf; (*p != 0) && !isspace(*p); p++);
		*p++ = 0;

		if(buf[0] == 0) continue;

		key = 0;
		for(k=keyword_tab; k->mnem != NULL; k++)
		{
			if(strcmp(buf,k->mnem)==0)
			{
				key = k->data;
				break;
			}
		}

		switch(key)
		{
		case V_LANGUAGE:
			{
				unsigned int len;
				int priority;

				if(tone_only)
					break;
	
				priority = DEFAULT_LANGUAGE_PRIORITY;
				language_name[0] = 0;
	
				sscanf(p,"%s %d",language_name,&priority);
				if(strcmp(language_name,"variant") == 0)
					break;
	
				len = strlen(language_name) + 2;
				// check for space in languages[]
				if(len < (sizeof(voice_languages)-langix-1))
				{
					voice_languages[langix] = priority;
	
					strcpy(&voice_languages[langix+1],language_name);
					langix += len;
				}
	
				// only act on the first language line
				if(language_set == 0)
				{
					language_type = strtok(language_name,"-");
					language_set = 1;
					strcpy(translator_name,language_type);
					strcpy(new_dictionary,language_type);
					strcpy(phonemes_name,language_type);
					SelectPhonemeTableName(phonemes_name);
		
					if(new_translator != NULL)
							DeleteTranslator(new_translator);
		
					new_translator = SelectTranslator(translator_name);
					langopts = &new_translator->langopts;
				}
			}
			break;

		case V_NAME:
			if(tone_only == 0)
			{
				while(isspace(*p)) p++;
				strncpy0(voice_name,p,sizeof(voice_name));
			}
			break;

		case V_GENDER:
			{
				int age;
				char vgender[80];
				sscanf(p,"%s %d",vgender,&age);
				voice_selected.gender = LookupMnem(genders,vgender);
				voice_selected.age = age;
			}
			break;

		case V_TRANSLATOR:
			if(tone_only) break;

			sscanf(p,"%s",translator_name);

			if(new_translator != NULL)
					DeleteTranslator(new_translator);

			new_translator = SelectTranslator(translator_name);
			langopts = &new_translator->langopts;
			break;

		case V_DICTIONARY:        // dictionary
			sscanf(p,"%s",new_dictionary);
			break;

		case V_PHONEMES:        // phoneme table
			sscanf(p,"%s",phonemes_name);
			break;

		case V_FORMANT:
			VoiceFormant(p);
			break;

		case V_PITCH:
			{
				double factor;
				// default is  pitch 82 118
				n = sscanf(p,"%d %d",&pitch1,&pitch2);
				voice->pitch_base = (pitch1 - 9) << 12;
				voice->pitch_range = (pitch2 - pitch1) * 108;
				factor = double(pitch1 - 82)/82;
				voice->formant_factor = (int)((1+factor/4) * 256);  // nominal formant shift for a different voice pitch
			}
			break;

		case V_STRESSLENGTH:   // stressLength
			stress_lengths_set = Read8Numbers(p,stress_lengths);
			break;

		case V_STRESSAMP:   // stressAmp
			stress_amps_set = Read8Numbers(p,stress_amps);
			break;

		case V_STRESSADD:   // stressAdd
			stress_add_set = Read8Numbers(p,stress_add);
			break;

		case V_INTONATION:   // intonation
			sscanf(p,"%d %d",&option_tone_flags,&option_tone2);
			if((option_tone_flags & 0xff) != 0)
				langopts->intonation_group = option_tone_flags & 0xff;
			break;

		case V_DICTRULES:   // conditional dictionary rules and list entries
			while(*p != 0)
			{
				while(isspace(*p)) p++;
				n = -1;
				if(((n = atoi(p)) > 0) && (n < 32))
				{
					p++;
					conditional_rules |= (1 << n);
				}
				while(isalnum(*p)) p++;
			}
			break;

		case V_REPLACE:
			if(phonemes_set == 0)
			{
				// must set up a phoneme table before we can lookup phoneme mnemonics
				SelectPhonemeTableName(phonemes_name);
				phonemes_set = 1;
			}
			PhonemeReplacement(key,p);
			break;

		case V_WORDGAP:   // words
			sscanf(p,"%d %d",&langopts->word_gap, &langopts->vowel_pause);
			break;

		case V_STRESSRULE:
			sscanf(p,"%d %d %d %d",&langopts->stress_rule,
				&langopts->stress_flags,
				&langopts->unstressed_wd1,
				&langopts->unstressed_wd2);
			break;

		case V_CHARSET:
			if((sscanf(p,"%d",&value)==1) && (value < N_CHARSETS))
				new_translator->charset_a0 = charsets[value];
			break;

		case V_NUMBERS:
			sscanf(p,"%d %d",&langopts->numbers,&langopts->numbers2);
			break;

		case V_OPTION:
			if(sscanf(p,"%d %d",&ix,&value) == 2)
			{
				if((ix >= 0) && (ix < N_LOPTS))
					langopts->param[ix] = value;
			}
			break;

		case V_ECHO:
			// echo.  suggest: 135mS  11%
			value = 0;
			voice->echo_amp = 0;
			sscanf(p,"%d %d",&voice->echo_delay,&voice->echo_amp);
			break;

		case V_FLUTTER:   // flutter
			if(sscanf(p,"%d",&value)==1)
				voice->flutter = value * 32;
			break;

		case V_ROUGHNESS:   // roughness
			if(sscanf(p,"%d",&value)==1)
				voice->roughness = value;
			break;

		case V_CLARITY:  // formantshape
			if(sscanf(p,"%d",&value)==1)
			{
				if(value > 4)
				{
					voice->peak_shape = 1;  // squarer formant peaks
					value = 4;
				}
				voice->n_harmonic_peaks = 1+value;
			}
			break;

		case V_TONE:
			{
				int tone_data[12];
				ReadTonePoints(p,tone_data);
				SetToneAdjust(voice,tone_data);
			}
			break;

		case V_VOICING:
			if(sscanf(p,"%d",&value)==1)
				voice->voicing = (value * 64)/100;
			break;

		case V_BREATH:
				voice->breath[0] = Read8Numbers(p,&voice->breath[1]);
				for(ix=1; ix<8; ix++)
				{
					if(ix % 2)
						voice->breath[ix] = -voice->breath[ix];
				}
			break;

		case V_BREATHW:
				voice->breathw[0] = Read8Numbers(p,&voice->breathw[1]);
			break;

		case V_CONSONANTS:
			value = sscanf(p,"%d %d",&voice->consonant_amp, &voice->consonant_ampv);
			break;

		case V_MBROLA:
			{
				int srate = 16000;
				char name[40];
				char phtrans[40];

				phtrans[0] = 0;
				sscanf(p,"%s %s %d",name,phtrans,&srate);
				LoadMbrolaTable(name,phtrans,srate);
			}
			break;

		case V_KLATT:
			voice->klattv[0] = 1;  // default source: IMPULSIVE
			Read8Numbers(p,voice->klattv);
			voice->klattv[KLATT_Kopen] -= 40;
			break;

		case V_FAST:
			Read8Numbers(p,speed.fast_settings);
			SetSpeed(2);
			break;

		default:
			if((key & 0xff00) == 0x100)
			{
				sscanf(p,"%d",&langopts->param[key &0xff]);
			}
			else
			{
				fprintf(stderr,"Bad voice attribute: %s\n",buf);
			}
			break;
		}
	}
	if(f_voice != NULL)
		fclose(f_voice);

	if((new_translator == NULL) && (!tone_only))
	{
		// not set by language attribute
		new_translator = SelectTranslator(translator_name);
	}

	for(ix=0; ix<N_PEAKS; ix++)
	{
		voice->freq2[ix] = voice->freq[ix];
		voice->height2[ix] = voice->height[ix];
		voice->width2[ix] = voice->width[ix];
	}

	if(tone_only)
	{
		new_translator = translator;
	}
	else
	{
		if((ix = SelectPhonemeTableName(phonemes_name)) < 0)
		{
			fprintf(stderr,"Unknown phoneme table: '%s'\n",phonemes_name);
		}
		voice->phoneme_tab_ix = ix;
		error = LoadDictionary(new_translator, new_dictionary, control & 4);
		if(dictionary_name[0]==0)
			return(NULL);   // no dictionary loaded

		new_translator->dict_condition = conditional_rules;

		voice_languages[langix] = 0;
	}

	langopts = &new_translator->langopts;


	if((value = langopts->param[LOPT_LENGTH_MODS]) != 0)
	{
		SetLengthMods(new_translator,value);
	}

	voice->width[0] = (voice->width[0] * 105)/100;

	if(!tone_only)
	{
		translator = new_translator;
	}

	// relative lengths of different stress syllables
	for(ix=0; ix<stress_lengths_set; ix++)
	{
		translator->stress_lengths[ix] = stress_lengths[ix];
	}
	for(ix=0; ix<stress_add_set; ix++)
	{
		translator->stress_lengths[ix] += stress_add[ix];
	}
	for(ix=0; ix<stress_amps_set; ix++)
	{
		translator->stress_amps[ix] = stress_amps[ix];
		translator->stress_amps_r[ix] = stress_amps[ix] -1;
	}

	return(voice);
}  //  end of LoadVoice
示例#5
0
/*
 *	Read the configuration file.
 *	If parameter "all" == 0 then ignore everything except path info
 *	Return -1 if any error.
 *	Error messages generated.
 */
static int do_read(int all, char *force_ver, char *base_dir, char *conf_file, int depth)
{
#define MAX_LEVEL 20
    FILE *fin;
    GLOB_LIST g;
    int i;
    int assgn;
    int drop_default_paths = 1;
    int lineno = 0;
    int ret = 0;
    int state[MAX_LEVEL + 1]; /* nested "if" */
    int level = 0;
    int sizebuf;
    char *buf = NULL;
    char tmpline[PATH_MAX];
    char **pathp;
    char *envpath;
    char *version;
    char *type;
    char **glb;
    char old_name[] = "/etc/conf.modules";
    int conf_file_specified = 0;

    /*
     * The configuration file is optional.
     * No error is printed if it is missing.
     * If it is missing the following content is assumed.
     *
     * path[boot]=/lib/modules/boot
     *
     * path[toplevel]=/lib/modules/`uname -r`
     *
     * path[toplevel]=/lib/modules/`kernelversion`
     *   (where kernelversion gives the major kernel version: "2.0", "2.2"...)
     *
     * path[toplevel]=/lib/modules/default
     *
     * path[kernel]=/lib/modules/kernel
     * path[fs]=/lib/modules/fs
     * path[net]=/lib/modules/net
     * path[scsi]=/lib/modules/scsi
     * path[block]=/lib/modules/block
     * path[cdrom]=/lib/modules/cdrom
     * path[ipv4]=/lib/modules/ipv4
     * path[ipv6]=/lib/modules/ipv6
     * path[sound]=/lib/modules/sound
     * path[fc4]=/lib/modules/fc4
     * path[video]=/lib/modules/video
     * path[misc]=/lib/modules/misc
     * path[pcmcia]=/lib/modules/pcmcia
     * path[atm]=/lib/modules/atm
     * path[usb]=/lib/modules/usb
     * path[ide]=/lib/modules/ide
     * path[ieee1394]=/lib/modules/ieee1394
     * path[mtd]=/lib/modules/mtd
     *
     * The idea is that modprobe will look first if the
     * modules are compiled for the current release of the kernel.
     * If not found, it will look for modules that fit for the
     * general kernelversion (2.0, 2.2 and so on).
     * If still not found, it will look into the default release.
     * And if still not found, it will look in the other directories.
     *
     * The strategy should be like this:
     * When you install a new linux kernel, the modules should go
     * into a directory related to the release (version) of the kernel.
     * Then you can do a symlink "default" to this directory.
     *
     * Each time you compile a new kernel, the make modules_install
     * will create a new directory, but it won't change thee default.
     *
     * When you get a module unrelated to the kernel distribution
     * you can place it in one of the last three directory types.
     *
     * This is the default strategy. Of course you can overide
     * this in /etc/modules.conf.
     *
     * 2.3.15 added a new file tree walk algorithm which made it possible to
     * point at a top level directory and get the same behaviour as earlier
     * versions of modutils.  2.3.16 takes this one stage further, it
     * removes all the individual directory names from most of the scans,
     * only pointing at the top level directory.  The only exception is the
     * last ditch scan, scanning all of /lib/modules would be a bad idea(TM)
     * so the last ditch scan still runs individual directory names under
     * /lib/modules.
     *
     * Additional syntax:
     *
     * [add] above module module1 ...
     *	Specify additional modules to pull in on top of a module
     *
     * [add] below module module1 ...
     *	Specify additional modules needed to be able to load a module
     *
     * [add] prune filename ...
     *
     * [add] probe name module1 ...
     *	When "name" is requested, modprobe tries to install each
     *	module in the list until it succeeds.
     *
     * [add] probeall name module1 ...
     *	When "name" is requested, modprobe tries to install all
     *	modules in the list.
     *	If any module is installed, the command has succeeded.
     *
     * [add] options module option_list
     *
     * For all of the above, the optional "add" prefix is used to
     * add to a list instead of replacing the contents.
     *
     * include FILE_TO_INCLUDE
     *	This does what you expect. No limitation on include levels.
     *
     * persistdir=persist_directory
     *	Name the directory to save persistent data from modules.
     *
     * In the following WORD is a sequence if non-white characters.
     * If ' " or ` is found in the string, all characters up to the
     * matching ' " or ` will also be included, even whitespace.
     * Every WORD will then be expanded w.r.t. meta-characters.
     * If the expanded result gives more than one word, then only
     * the first word of the result will be used.
     *
     *
     * define CODE WORD
     *		Do a putenv("CODE=WORD")
     *
     * EXPRESSION below can be:
     *	WORD compare_op WORD
     *		where compare_op is one of == != < <= >= >
     *		The string values of the WORDs are compared
     * or
     *	-n WORD compare_op WORD
     *		where compare_op is one of == != < <= >= >
     *		The numeric values of the WORDs are compared
     * or
     *	WORD
     *		if the expansion of WORD fails, or if the
     *		expansion is "0" (zero), "false" or "" (empty)
     *		then the expansion has the value FALSE.
     *		Otherwise the expansion has the value TRUE
     * or
     *	-f FILENAME
     *		Test if the file FILENAME exists
     * or
     *	-k
     *		Test if "autoclean" (i.e. called from the kernel)
     * or
     *	! EXPRESSION
     *		A negated expression is also an expression
     *
     * if EXPRESSION
     *	any config line
     *	...
     * elseif EXPRESSION
     *	any config line
     *	...
     * else
     *	any config line
     *	...
     * endif
     *
     * The else and elseif keywords are optional.
     * "if"-statements nest up to 20 levels.
     */

    state[0] = 1;

    if (force_ver)
        version = force_ver;
    else
        version = uts_info.release;

    config_version = xstrdup(version);

    /* Only read the default entries on the first file */
    if (depth == 0) {
        maxpath = 100;
        modpath = (struct PATH_TYPE *)xmalloc(maxpath * sizeof(struct PATH_TYPE));
        nmodpath = 0;

        maxexecs = 10;
        execs = (struct EXEC_TYPE *)xmalloc(maxexecs * sizeof(struct EXEC_TYPE));
        nexecs = 0;

        /*
         * Build predef options
         */
        if (all && optlist[0])
            n_opt_list = build_list(optlist, &opt_list, version, 1);

        /*
         * Build predef above
         */
        if (all && above[0])
            n_abovelist = build_list(above, &abovelist, version, 0);

        /*
         * Build predef below
         */
        if (all && below[0])
            n_belowlist = build_list(below, &belowlist, version, 0);

        /*
         * Build predef prune list
         */
        if (prune[0])
            n_prunelist = build_list(prune, &prunelist, version, 0);

        /*
         * Build predef aliases
         */
        if (all && aliaslist[0])
            n_aliases = build_list(aliaslist, &aliases, version, 0);

        /* Order and priority is now: (MODPATH + modules.conf) || (predefs + modules.conf) */
        if ((envpath = getenv("MODPATH")) != NULL && !safemode) {
            size_t len;
            char *p;
            char *path;

            /* Make a copy so's we can mung it with strtok.  */
            len = strlen(envpath) + 1;
            p = alloca(len);
            memcpy(p, envpath, len);
            path = alloca(PATH_MAX);

            for (p = strtok(p, ":"); p != NULL; p = strtok(NULL, ":")) {
                len = snprintf(path, PATH_MAX, p, version);
                modpath[nmodpath].path = xstrdup(path);
                if ((type = strrchr(path, '/')) != NULL)
                    type += 1;
                else
                    type = "misc";
                modpath[nmodpath].type = xstrdup(type);
                if (++nmodpath >= maxpath) {
                    maxpath += 100;
                    modpath = (struct PATH_TYPE *)xrealloc(modpath,
                                                           maxpath * sizeof(struct PATH_TYPE));
                }

            }
        } else {
            /*
             * Build the default "path[type]" configuration
             */
            int n;
            char *k;

            /* The first entry in the path list */
            modpath[nmodpath].type = xstrdup("boot");
            snprintf(tmpline, sizeof(tmpline), "%s/lib/modules/boot", base_dir);
            modpath[nmodpath].path = xstrdup(tmpline);
            ++nmodpath;

            /* The second entry in the path list, `uname -r` */
            modpath[nmodpath].type = xstrdup("toplevel");
            snprintf(tmpline, sizeof(tmpline), "%s/lib/modules/%s", base_dir, version);
            modpath[nmodpath].path = xstrdup(tmpline);
            ++nmodpath;

            /* The third entry in the path list, `kernelversion` */
            modpath[nmodpath].type = xstrdup("toplevel");
            for (n = 0, k = version; *k; ++k) {
                if (*k == '.' && ++n == 2)
                    break;
            }
            snprintf(tmpline, sizeof(tmpline), "%s/lib/modules/%.*s", base_dir,
                     (/* typecast for Alpha */ int)(k - version), version);
            modpath[nmodpath].path = xstrdup(tmpline);
            ++nmodpath;

            /* The rest of the entries in the path list */
            for (pathp = tbpath; *pathp; ++pathp) {
                char **type;

                for (type = tbtype; *type; ++type) {
                    char path[PATH_MAX];

                    snprintf(path, sizeof(path), "%s%s/%s", base_dir, *pathp, *type);
                    if (meta_expand(path, &g, NULL, version, ME_ALL)) {
                        ret = -1;
                        goto out;
                    }

                    for (glb = g.pathv; glb && *glb; ++glb) {
                        modpath[nmodpath].type = xstrdup(*type);
                        modpath[nmodpath].path = *glb;
                        if (++nmodpath >= maxpath) {
                            maxpath += 100;
                            modpath = (struct PATH_TYPE *)xrealloc(modpath,
                                                                   maxpath * sizeof(struct PATH_TYPE));
                        }
                    }
                }
            }
        }

        /* Environment overrides for testing only, undocumented */
        for (i = 0; i < gen_file_count; ++i)
            gen_file_env(gen_file+i);

    }	/* End of depth == 0 */

    if (conf_file ||
            ((conf_file = getenv("MODULECONFIG")) != NULL && *conf_file && !safemode)) {
        if (!(fin = fopen(conf_file, "r"))) {
            error("Can't open %s", conf_file);
            ret = -1;
            goto out;
        }
        conf_file_specified = 1;
    } else {
        if (!(fin = fopen((conf_file = ETC_MODULES_CONF), "r"))) {
            /* Fall back to non-standard name */
            if ((fin = fopen((conf_file = old_name), "r"))) {
                fprintf(stderr,
                        "Warning: modutils is reading from %s because\n"
                        "         %s does not exist.  The use of %s is\n"
                        "         deprecated, please rename %s to %s\n"
                        "         as soon as possible.  Command\n"
                        "         mv %s %s\n",
                        old_name, ETC_MODULES_CONF,
                        old_name, old_name, ETC_MODULES_CONF,
                        old_name, ETC_MODULES_CONF);
            }
            /* So what... use the default configuration */
        }
    }

    if (fin) {
        struct stat statbuf1, statbuf2;
        if (fstat(fileno(fin), &statbuf1) == 0)
            config_mtime = statbuf1.st_mtime;
        config_file = xstrdup(conf_file);	/* Save name actually used */
        if (!conf_file_specified &&
                stat(ETC_MODULES_CONF, &statbuf1) == 0 &&
                stat(old_name, &statbuf2) == 0) {
            /* Both /etc files exist */
            if (statbuf1.st_dev == statbuf2.st_dev &&
                    statbuf1.st_ino == statbuf2.st_ino) {
                if (lstat(ETC_MODULES_CONF, &statbuf1) == 0 &&
                        S_ISLNK(statbuf1.st_mode))
                    fprintf(stderr,
                            "Warning: You do not need a link from %s to\n"
                            "         %s.  The use of %s is deprecated,\n"
                            "         please remove %s and rename %s\n"
                            "         to %s as soon as possible.  Commands.\n"
                            "           rm %s\n"
                            "           mv %s %s\n",
                            ETC_MODULES_CONF, old_name,
                            old_name, ETC_MODULES_CONF, old_name, ETC_MODULES_CONF,
                            ETC_MODULES_CONF,
                            old_name, ETC_MODULES_CONF);
                else {
#ifndef NO_WARN_ON_OLD_LINK
                    fprintf(stderr,
                            "Warning: You do not need a link from %s to\n"
                            "         %s.  The use of %s is deprecated,\n"
                            "         please remove %s as soon as possible.  Command\n"
                            "           rm %s\n",
                            old_name, ETC_MODULES_CONF,
                            old_name, old_name,
                            old_name);
#endif
                }
            }
            else
                fprintf(stderr,
                        "Warning: modutils is reading from %s and\n"
                        "         ignoring %s.  The use of %s is deprecated,\n"
                        "         please remove %s as soon as possible.  Command\n"
                        "           rm %s\n",
                        ETC_MODULES_CONF, old_name,
                        old_name, old_name,
                        old_name);
        }
    }

    /*
     * Finally, decode the file
     */
    while (fin && fgets_strip(&buf, &sizebuf, fin, &lineno) != NULL) {
        char *arg2;
        char *parm = buf;
        char *arg;
        int one_err = 0;
        int adding;

        while (isspace(*parm))
            parm++;

        if (strncmp(parm, "add", 3) == 0) {
            adding = 1;
            parm += 3;
            while (isspace(*parm))
                parm++;
        } else
            adding = 0;

        arg = parm;

        if (*parm == '\0')
            continue;

        one_err = 1;

        while (*arg > ' ' && *arg != '=')
            arg++;

        if (*arg == '=')
            assgn = 1;
        else
            assgn = 0;
        *arg++ = '\0';
        while (isspace(*arg))
            arg++;

        /*
         * endif
         */
        if (!assgn && strcmp(parm, "endif") == 0) {
            if (level > 0)
                --level;
            else {
                error("unmatched endif in line %d", lineno);
                ret = -1;
                goto out;
            }
            continue;
        }

        /*
         * else
         */
        if (!assgn && strcmp(parm, "else") == 0) {
            if (level <= 0) {
                error("else without if in line %d", lineno);
                ret = -1;
                goto out;
            }
            state[level] = !state[level];
            continue;
        }

        /*
         * elseif
         */
        if (!assgn && strcmp(parm, "elseif") == 0) {
            if (level <= 0) {
                error("elseif without if in line %d", lineno);
                ret = -1;
                goto out;
            }
            if (state[level] != 0) {
                /*
                 * We have already found a TRUE
                 * if statement in this "chain".
                 * That's what "2" means.
                 */
                state[level] = 2;
                continue;
            }
            /* else: No TRUE if has been found, cheat */
            /*
             * The "if" handling increments level,
             * but this is the _same_ level as before.
             * So, compensate for it.
             */
            --level;
            parm = "if";
            /* Fallthru to "if" */
        }

        /*
         * if
         */
        if (strcmp(parm, "if") == 0) {
            char *cmp;
            int not = 0;
            int numeric = 0;

            if (level >= MAX_LEVEL) {
                error("Too many nested if's in line %d\n", lineno);
                ret = -1;
                goto out;
            }
            state[++level] = 0; /* default false */

            if (*arg == '!') {
                not = 1;
                arg = next_word(arg);
            }

            if (strncmp(arg, "-k", 2) == 0) {
                state[level] = flag_autoclean;
                continue;
            }

            if (strncmp(arg, "-f", 2) == 0) {
                char *file = next_word(arg);
                meta_expand(file, &g, NULL, version, ME_ALL);
                if (access(g.pathc ? g.pathv[0] : file, R_OK) == 0)
                    state[level] = !not;
                else
                    state[level] = not;
                continue;
            }

            if (strncmp(arg, "-n", 2) == 0) {
                numeric = 1;
                arg = next_word(arg);
            }


            cmp = next_word(arg);
            if (*cmp) {
                GLOB_LIST g2;
                long n1 = 0;
                long n2 = 0;
                char *w1 = "";
                char *w2 = "";

                arg2 = next_word(cmp);

                meta_expand(arg, &g, NULL, version, ME_ALL);
                if (g.pathc && g.pathv[0])
                    w1 = g.pathv[0];

                meta_expand(arg2, &g2, NULL, version, ME_ALL);
                if (g2.pathc && g2.pathv[0])
                    w2 = g2.pathv[0];

                if (numeric) {
                    n1 = strtol(w1, NULL, 0);
                    n2 = strtol(w2, NULL, 0);
                }

                if (strcmp(cmp, "==") == 0 ||
                        strcmp(cmp, "=") == 0) {
                    if (numeric)
                        state[level] = (n1 == n2);
                    else
                        state[level] = strcmp(w1, w2) == 0;
                } else if (strcmp(cmp, "!=") == 0) {
                    if (numeric)
                        state[level] = (n1 != n2);
                    else
                        state[level] = strcmp(w1, w2) != 0;
                } else if (strcmp(cmp, ">=") == 0) {
                    if (numeric)
                        state[level] = (n1 >= n2);
                    else
                        state[level] = strcmp(w1, w2) >= 0;
                } else if (strcmp(cmp, "<=") == 0) {
                    if (numeric)
                        state[level] = (n1 <= n2);
                    else
                        state[level] = strcmp(w1, w2) <= 0;
                } else if (strcmp(cmp, ">") == 0) {
                    if (numeric)
                        state[level] = (n1 > n2);
                    else
                        state[level] = strcmp(w1, w2) > 0;
                } else if (strcmp(cmp, "<") == 0) {
                    if (numeric)
                        state[level] = (n1 < n2);
                    else
                        state[level] = strcmp(w1, w2) < 0;
                }
            } else { /* Check defined value, if any */
                /* undef or defined as
                 *	"" or "0" or "false" => false
                 *  defined => true
                 */
                if (!meta_expand(arg, &g, NULL, version, ME_ALL) &&
                        g.pathc > 0 &&
                        strcmp(g.pathv[0], "0") != 0 &&
                        strcmp(g.pathv[0], "false") != 0 &&
                        strlen(g.pathv[0]) != 0)
                    state[level] = 1; /* true */
            }
            if (not)
                state[level] = !state[level];

            continue;
        }

        /*
         * Should we bother?
         */
        if (state[level] != 1)
            continue;

        /*
         * define
         */
        if (!assgn && strcmp(parm, "define") == 0) {
            char env[PATH_MAX];

            arg2 = next_word(arg);
            meta_expand(arg2, &g, NULL, version, ME_ALL);
            snprintf(env, sizeof(env), "%s=%s", arg, (g.pathc ? g.pathv[0] : ""));
            putenv(xstrdup(env));
            one_err = 0;
        }

        /*
         * include
         */
        if (!assgn && strcmp(parm, "include") == 0) {
            int inc_idx = 0;

            while (*arg) {
                arg2=next_word(arg);
                meta_expand(arg, &g, NULL, version, ME_ALL);

                if (g.pathc>0) {
                    for ( ; inc_idx<g.pathc; inc_idx++) {
                        if (!do_read(all, version, base_dir, g.pathv[inc_idx], depth+1))
                            one_err = 0;
                        else
                            error("include %s failed\n", g.pathv[inc_idx]);
                    }
                }
                else {
                    if (!do_read(all, version, base_dir, g.pathc ? g.pathv[0] : arg, depth+1))
                        one_err = 0;
                    else
                        error("include %s failed\n", arg);
                }

                arg = arg2;
            }
        }

        /*
         * above
         */
        else if (all && !assgn && strcmp(parm, "above") == 0) {
            decode_list(&n_abovelist, &abovelist, arg, adding, version, 0);
            one_err = 0;
        }

        /*
         * below
         */
        else if (all && !assgn && strcmp(parm, "below") == 0) {
            decode_list(&n_belowlist, &belowlist, arg, adding, version, 0);
            one_err = 0;
        }

        /*
         * prune
         */
        else if (!assgn && strcmp(parm, "prune") == 0) {
            decode_list(&n_prunelist, &prunelist, arg, adding, version, 0);
            one_err = 0;
        }

        /*
         * probe
         */
        else if (all && !assgn && strcmp(parm, "probe") == 0) {
            decode_list(&n_probe_list, &probe_list, arg, adding, version, 0);
            one_err = 0;
        }

        /*
         * probeall
         */
        else if (all && !assgn && strcmp(parm, "probeall") == 0) {
            decode_list(&n_probeall_list, &probeall_list, arg, adding, version, 0);
            one_err = 0;
        }

        /*
         * options
         */
        else if (all && !assgn && strcmp(parm, "options") == 0) {
            decode_list(&n_opt_list, &opt_list, arg, adding, version, 1);
            one_err = 0;
        }

        /*
         * alias
         */
        else if (all && !assgn && strcmp(parm, "alias") == 0) {
            /*
             * Replace any previous (default) definitions
             * for the same module
             */
            decode_list(&n_aliases, &aliases, arg, 0, version, 0);
            one_err = 0;
        }

        /*
         * Specification: /etc/modules.conf
         * The format of the commands in /etc/modules.conf are:
         *
         *	pre-install module command
         *	install module command
         *	post-install module command
         *	pre-remove module command
         *	remove module command
         *	post-remove module command
         *
         * The different words are separated by tabs or spaces.
         */
        /*
         * pre-install
         */
        else if (all && !assgn && (strcmp(parm, "pre-install") == 0)) {
            decode_exec(arg, EXEC_PRE_INSTALL);
            one_err = 0;
        }

        /*
         * install
         */
        else if (all && !assgn && (strcmp(parm, "install") == 0)) {
            decode_exec(arg, EXEC_INSTALL);
            one_err = 0;
        }

        /*
         * post-install
         */
        else if (all && !assgn && (strcmp(parm, "post-install") == 0)) {
            decode_exec(arg, EXEC_POST_INSTALL);
            one_err = 0;
        }

        /*
         * pre-remove
         */
        else if (all && !assgn && (strcmp(parm, "pre-remove") == 0)) {
            decode_exec(arg, EXEC_PRE_REMOVE);
            one_err = 0;
        }

        /*
         * remove
         */
        else if (all && !assgn && (strcmp(parm, "remove") == 0)) {
            decode_exec(arg, EXEC_REMOVE);
            one_err = 0;
        }

        /*
         * post-remove
         */
        else if (all && !assgn && (strcmp(parm, "post-remove") == 0)) {
            decode_exec(arg, EXEC_POST_REMOVE);
            one_err = 0;
        }

        /*
         * insmod_opt=
         */
        else if (assgn && (strcmp(parm, "insmod_opt") == 0)) {
            insmod_opt = xstrdup(arg);
            one_err = 0;
        }

        /*
         * keep
         */
        else if (!assgn && (strcmp(parm, "keep") == 0)) {
            drop_default_paths = 0;
            one_err = 0;
        }

        /*
         * path...=
         */
        else if (assgn && strncmp(parm, "path", 4) == 0) {
            /*
             * Specification: config file / path parameter
             * The path parameter specifies a directory to
             * search for modules.
             * This parameter may be repeated multiple times.
             *
             * Note that the actual path may be defined using
             * wildcards and other shell meta-chars, such as "*?`".
             * For example:
             *      path[misc]=/lib/modules/1.1.5?/misc
             *
             * Optionally the path keyword carries a tag.
             * This tells us a little more about the purpose of
             * this directory and allows some automated operations.
             * A path is marked with a tag by adding the tag,
             * enclosed in square brackets, to the path keyword:
             * #
             * path[boot]=/lib/modules/boot
             * #
             * This case identifies the path a of directory
             * holding modules loadable a boot time.
             */

            if (drop_default_paths) {
                int n;

                /*
                 * Specification: config file / path / default
                 *
                 * Whenever there is a path[] specification
                 * in the config file, all the default
                 * path are reset.
                 *
                 * If one instead wants to _add_ to the default
                 * set of paths, one has to have the option
                 *    keep
                 * before the first path[]-specification line
                 * in the configuration file.
                 */
                drop_default_paths = 0;
                for (n = 0; n < nmodpath; n++) {
                    free(modpath[n].path);
                    free(modpath[n].type);
                }
                nmodpath = 0;
            }

            /*
             * Get (the optional) tag
             * If the tag is missing, the word "misc"
             * is assumed.
             */
            type = "misc";

            if (parm[4] == '[') {
                char *pt_type = parm + 5;

                while (*pt_type != '\0' && *pt_type != ']')
                    pt_type++;

                if (*pt_type == ']' && pt_type[1] == '\0') {
                    *pt_type = '\0';
                    type = parm + 5;
                } /* else CHECKME */
            }

            /*
             * Handle the actual path description
             */
            if (meta_expand(arg, &g, base_dir, version, ME_ALL)) {
                ret = -1;
                goto out;
            }
            for (glb = g.pathv; glb && *glb; ++glb) {
                modpath[nmodpath].type = xstrdup(type);
                modpath[nmodpath].path = *glb;
                if (++nmodpath >= maxpath) {
                    maxpath += 100;
                    modpath = (struct PATH_TYPE *)xrealloc(modpath,
                                                           maxpath * sizeof(struct PATH_TYPE));
                }
            }
            one_err = 0;
        }

        /*
         * persistdir
         */
        else if (assgn && strcmp(parm, "persistdir") == 0) {
            meta_expand(arg, &g, NULL, version, ME_ALL);
            persistdir = xstrdup(g.pathc ? g.pathv[0] : arg);
            one_err = 0;
        }

        /* Names for generated files in config file */
        for (i = 0; one_err && i < gen_file_count; ++i)
            one_err = gen_file_conf(gen_file+i, assgn, parm, arg);

        /*
         * any errors so far?
         */
        if (all == 0)
            one_err = 0;
        else if (one_err) {
            error("Invalid line %d in %s\n\t%s",
                  lineno, conf_file, buf);
            ret = -1;
        }
    }
    if (fin)
        fclose(fin);

    if (level) {
        error("missing endif at %s EOF", conf_file);
        ret = -1;
    }

    if (ret)
        goto out;
    /* else */

    if (depth == 0) {
        /* Check we have names for generated files */
        for (i = 0; !ret && i < gen_file_count; ++i)
            ret = gen_file_check(gen_file+i, &g, base_dir, version);
    }

out:
    return ret;
}