1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2008 Masanao Izumo <iz@onicos.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdint.h>
24 
25 #include "timidity.h"
26 #include "common.h"
27 #include "instrum.h"
28 #include "quantity.h"
29 
30 
31 namespace TimidityPlus
32 {
33 
34 #define MAXWORDS 130
35 #define CHECKERRLIMIT \
36   if(++errcnt >= 10) { \
37     printMessage(CMSG_ERROR, VERB_NORMAL, \
38       "Too many errors... Give up read %s", name); \
39     reuse_mblock(&varbuf); \
40     tf_close(tf); return 1; }
41 
42 
43 typedef struct {
44 	const char *name;
45 	int mapid, isdrum;
46 } MapNameEntry;
47 
mapnamecompare(const void * name,const void * entry)48 static int mapnamecompare(const void *name, const void *entry)
49 {
50 	return strcmp((const char *)name, ((const MapNameEntry *)entry)->name);
51 }
52 
mapname2id(char * name,int * isdrum)53 static int mapname2id(char *name, int *isdrum)
54 {
55 	static const MapNameEntry data[] = {
56 		/* sorted in alphabetical order */
57 		{ "gm2",         GM2_TONE_MAP, 0 },
58 	{ "gm2drum",     GM2_DRUM_MAP, 1 },
59 	{ "sc55",        SC_55_TONE_MAP, 0 },
60 	{ "sc55drum",    SC_55_DRUM_MAP, 1 },
61 	{ "sc88",        SC_88_TONE_MAP, 0 },
62 	{ "sc8850",      SC_8850_TONE_MAP, 0 },
63 	{ "sc8850drum",  SC_8850_DRUM_MAP, 1 },
64 	{ "sc88drum",    SC_88_DRUM_MAP, 1 },
65 	{ "sc88pro",     SC_88PRO_TONE_MAP, 0 },
66 	{ "sc88prodrum", SC_88PRO_DRUM_MAP, 1 },
67 	{ "xg",          XG_NORMAL_MAP, 0 },
68 	{ "xgdrum",      XG_DRUM_MAP, 1 },
69 	{ "xgsfx126",    XG_SFX126_MAP, 1 },
70 	{ "xgsfx64",     XG_SFX64_MAP, 0 }
71 	};
72 	const MapNameEntry *found;
73 
74 	found = (MapNameEntry *)bsearch(name, data, sizeof data / sizeof data[0], sizeof data[0], mapnamecompare);
75 	if (found != NULL)
76 	{
77 		*isdrum = found->isdrum;
78 		return found->mapid;
79 	}
80 	return -1;
81 }
82 
config_parse_tune(const char * cp,int * num)83 static float *config_parse_tune(const char *cp, int *num)
84 {
85 	const char *p;
86 	float *tune_list;
87 	int i;
88 
89 	/* count num */
90 	*num = 1, p = cp;
91 	while ((p = strchr(p, ',')) != NULL)
92 		(*num)++, p++;
93 	/* alloc */
94 	tune_list = (float *)safe_malloc((*num) * sizeof(float));
95 	/* regist */
96 	for (i = 0, p = cp; i < *num; i++, p++) {
97 		tune_list[i] = atof(p);
98 		if (!(p = strchr(p, ',')))
99 			break;
100 	}
101 	return tune_list;
102 }
103 
config_parse_int16(const char * cp,int * num)104 static int16_t *config_parse_int16(const char *cp, int *num)
105 {
106 	const char *p;
107 	int16_t *list;
108 	int i;
109 
110 	/* count num */
111 	*num = 1, p = cp;
112 	while ((p = strchr(p, ',')) != NULL)
113 		(*num)++, p++;
114 	/* alloc */
115 	list = (int16_t *)safe_malloc((*num) * sizeof(int16_t));
116 	/* regist */
117 	for (i = 0, p = cp; i < *num; i++, p++) {
118 		list[i] = atoi(p);
119 		if (!(p = strchr(p, ',')))
120 			break;
121 	}
122 	return list;
123 }
124 
config_parse_envelope(const char * cp,int * num)125 static int **config_parse_envelope(const char *cp, int *num)
126 {
127 	const char *p, *px;
128 	int **env_list;
129 	int i, j;
130 
131 	/* count num */
132 	*num = 1, p = cp;
133 	while ((p = strchr(p, ',')) != NULL)
134 		(*num)++, p++;
135 	/* alloc */
136 	env_list = (int **)safe_malloc((*num) * sizeof(int *));
137 	for (i = 0; i < *num; i++)
138 		env_list[i] = (int *)safe_malloc(6 * sizeof(int));
139 	/* init */
140 	for (i = 0; i < *num; i++)
141 		for (j = 0; j < 6; j++)
142 			env_list[i][j] = -1;
143 	/* regist */
144 	for (i = 0, p = cp; i < *num; i++, p++) {
145 		px = strchr(p, ',');
146 		for (j = 0; j < 6; j++, p++) {
147 			if (*p == ':')
148 				continue;
149 			env_list[i][j] = atoi(p);
150 			if (!(p = strchr(p, ':')))
151 				break;
152 			if (px && p > px)
153 				break;
154 		}
155 		if (!(p = px))
156 			break;
157 	}
158 	return env_list;
159 }
160 
config_parse_modulation(const char * name,int line,const char * cp,int * num,int mod_type)161 static Quantity **config_parse_modulation(const char *name, int line, const char *cp, int *num, int mod_type)
162 {
163 	const char *p, *px, *err;
164 	char buf[128], *delim;
165 	Quantity **mod_list;
166 	int i, j;
167 	static const char * qtypestr[] = { "tremolo", "vibrato" };
168 	static const uint16_t qtypes[] = {
169 		QUANTITY_UNIT_TYPE(TREMOLO_SWEEP), QUANTITY_UNIT_TYPE(TREMOLO_RATE), QUANTITY_UNIT_TYPE(DIRECT_INT),
170 		QUANTITY_UNIT_TYPE(VIBRATO_SWEEP), QUANTITY_UNIT_TYPE(VIBRATO_RATE), QUANTITY_UNIT_TYPE(DIRECT_INT)
171 	};
172 
173 	/* count num */
174 	*num = 1, p = cp;
175 	while ((p = strchr(p, ',')) != NULL)
176 		(*num)++, p++;
177 	/* alloc */
178 	mod_list = (Quantity **)safe_malloc((*num) * sizeof(Quantity *));
179 	for (i = 0; i < *num; i++)
180 		mod_list[i] = (Quantity *)safe_malloc(3 * sizeof(Quantity));
181 	/* init */
182 	for (i = 0; i < *num; i++)
183 		for (j = 0; j < 3; j++)
184 			INIT_QUANTITY(mod_list[i][j]);
185 	buf[sizeof buf - 1] = '\0';
186 	/* regist */
187 	for (i = 0, p = cp; i < *num; i++, p++) {
188 		px = strchr(p, ',');
189 		for (j = 0; j < 3; j++, p++) {
190 			if (*p == ':')
191 				continue;
192 			if ((delim = strpbrk(strncpy(buf, p, sizeof buf - 1), ":,")) != NULL)
193 				*delim = '\0';
194 			if (*buf != '\0' && (err = string_to_quantity(buf, &mod_list[i][j], qtypes[mod_type * 3 + j])) != NULL) {
195 				printMessage(CMSG_ERROR, VERB_NORMAL, "%s: line %d: %s: parameter %d of item %d: %s (%s)",
196 					name, line, qtypestr[mod_type], j + 1, i + 1, err, buf);
197 				free_ptr_list(mod_list, *num);
198 				mod_list = NULL;
199 				*num = 0;
200 				return NULL;
201 			}
202 			if (!(p = strchr(p, ':')))
203 				break;
204 			if (px && p > px)
205 				break;
206 		}
207 		if (!(p = px))
208 			break;
209 	}
210 	return mod_list;
211 }
212 
213 
214 /*! copy bank and, if necessary, map appropriately */
copybank(ToneBank * to,ToneBank * from,int mapid,int bankmapfrom,int bankno)215 void Instruments::copybank(ToneBank *to, ToneBank *from, int mapid, int bankmapfrom, int bankno)
216 {
217 	ToneBankElement *toelm, *fromelm;
218 	int i;
219 
220 	if (from == NULL)
221 		return;
222 	for (i = 0; i < 128; i++)
223 	{
224 		toelm = &to->tone[i];
225 		fromelm = &from->tone[i];
226 		if (fromelm->name == NULL)
227 			continue;
228 		copy_tone_bank_element(toelm, fromelm);
229 		toelm->instrument = NULL;
230 		if (mapid != INST_NO_MAP)
231 			set_instrument_map(mapid, bankmapfrom, i, bankno, i);
232 	}
233 }
234 
235 /*! copy the whole mapped bank. returns 0 if no error. */
copymap(int mapto,int mapfrom,int isdrum)236 int Instruments::copymap(int mapto, int mapfrom, int isdrum)
237 {
238 	ToneBank **tb = isdrum ? drumset : tonebank;
239 	int i, bankfrom, bankto;
240 
241 	for (i = 0; i < 128; i++)
242 	{
243 		bankfrom = find_instrument_map_bank(isdrum, mapfrom, i);
244 		if (bankfrom <= 0) /* not mapped */
245 			continue;
246 		bankto = alloc_instrument_map_bank(isdrum, mapto, i);
247 		if (bankto == -1) /* failed */
248 			return 1;
249 		copybank(tb[bankto], tb[bankfrom], mapto, i, bankto);
250 	}
251 	return 0;
252 }
253 
set_gus_patchconf_opts(const char * name,int line,char * opts,ToneBankElement * tone)254 int Instruments::set_gus_patchconf_opts(const char *name, int line, char *opts, ToneBankElement *tone)
255 {
256 	char *cp;
257 	int k;
258 
259 	if (!(cp = strchr(opts, '='))) {
260 		printMessage(CMSG_ERROR, VERB_NORMAL,
261 			"%s: line %d: bad patch option %s", name, line, opts);
262 		return 1;
263 	}
264 	*cp++ = 0;
265 	if (!strcmp(opts, "amp")) {
266 		k = atoi(cp);
267 		if ((k < 0 || k > MAX_AMPLIFICATION) || (*cp < '0' || *cp > '9')) {
268 			printMessage(CMSG_ERROR, VERB_NORMAL,
269 				"%s: line %d: amplification must be between 0 and %d",
270 				name, line, MAX_AMPLIFICATION);
271 			return 1;
272 		}
273 		tone->amp = k;
274 	}
275 	else if (!strcmp(opts, "note")) {
276 		k = atoi(cp);
277 		if ((k < 0 || k > 127) || (*cp < '0' || *cp > '9')) {
278 			printMessage(CMSG_ERROR, VERB_NORMAL,
279 				"%s: line %d: note must be between 0 and 127",
280 				name, line);
281 			return 1;
282 		}
283 		tone->note = k;
284 		tone->scltune = config_parse_int16("100", &tone->scltunenum);
285 	}
286 	else if (!strcmp(opts, "pan")) {
287 		if (!strcmp(cp, "center"))
288 			k = 64;
289 		else if (!strcmp(cp, "left"))
290 			k = 0;
291 		else if (!strcmp(cp, "right"))
292 			k = 127;
293 		else {
294 			k = ((atoi(cp) + 100) * 100) / 157;
295 			if ((k < 0 || k > 127)
296 				|| (k == 0 && *cp != '-' && (*cp < '0' || *cp > '9'))) {
297 				printMessage(CMSG_ERROR, VERB_NORMAL,
298 					"%s: line %d: panning must be left, right, "
299 					"center, or between -100 and 100",
300 					name, line);
301 				return 1;
302 			}
303 		}
304 		tone->pan = k;
305 	}
306 	else if (!strcmp(opts, "tune"))
307 		tone->tune = config_parse_tune(cp, &tone->tunenum);
308 	else if (!strcmp(opts, "rate"))
309 		tone->envrate = config_parse_envelope(cp, &tone->envratenum);
310 	else if (!strcmp(opts, "offset"))
311 		tone->envofs = config_parse_envelope(cp, &tone->envofsnum);
312 	else if (!strcmp(opts, "keep")) {
313 		if (!strcmp(cp, "env"))
314 			tone->strip_envelope = 0;
315 		else if (!strcmp(cp, "loop"))
316 			tone->strip_loop = 0;
317 		else {
318 			printMessage(CMSG_ERROR, VERB_NORMAL,
319 				"%s: line %d: keep must be env or loop", name, line);
320 			return 1;
321 		}
322 	}
323 	else if (!strcmp(opts, "strip")) {
324 		if (!strcmp(cp, "env"))
325 			tone->strip_envelope = 1;
326 		else if (!strcmp(cp, "loop"))
327 			tone->strip_loop = 1;
328 		else if (!strcmp(cp, "tail"))
329 			tone->strip_tail = 1;
330 		else {
331 			printMessage(CMSG_ERROR, VERB_NORMAL,
332 				"%s: line %d: strip must be env, loop, or tail",
333 				name, line);
334 			return 1;
335 		}
336 	}
337 	else if (!strcmp(opts, "tremolo")) {
338 		if ((tone->trem = config_parse_modulation(name,
339 			line, cp, &tone->tremnum, 0)) == NULL)
340 			return 1;
341 	}
342 	else if (!strcmp(opts, "vibrato")) {
343 		if ((tone->vib = config_parse_modulation(name,
344 			line, cp, &tone->vibnum, 1)) == NULL)
345 			return 1;
346 	}
347 	else if (!strcmp(opts, "sclnote"))
348 		tone->sclnote = config_parse_int16(cp, &tone->sclnotenum);
349 	else if (!strcmp(opts, "scltune"))
350 		tone->scltune = config_parse_int16(cp, &tone->scltunenum);
351 	else if (!strcmp(opts, "comm")) {
352 		char *p;
353 
354 		if (tone->comment)
355 			free(tone->comment);
356 		p = tone->comment = safe_strdup(cp);
357 		while (*p) {
358 			if (*p == ',')
359 				*p = ' ';
360 			p++;
361 		}
362 	}
363 	else if (!strcmp(opts, "modrate"))
364 		tone->modenvrate = config_parse_envelope(cp, &tone->modenvratenum);
365 	else if (!strcmp(opts, "modoffset"))
366 		tone->modenvofs = config_parse_envelope(cp, &tone->modenvofsnum);
367 	else if (!strcmp(opts, "envkeyf"))
368 		tone->envkeyf = config_parse_envelope(cp, &tone->envkeyfnum);
369 	else if (!strcmp(opts, "envvelf"))
370 		tone->envvelf = config_parse_envelope(cp, &tone->envvelfnum);
371 	else if (!strcmp(opts, "modkeyf"))
372 		tone->modenvkeyf = config_parse_envelope(cp, &tone->modenvkeyfnum);
373 	else if (!strcmp(opts, "modvelf"))
374 		tone->modenvvelf = config_parse_envelope(cp, &tone->modenvvelfnum);
375 	else if (!strcmp(opts, "trempitch"))
376 		tone->trempitch = config_parse_int16(cp, &tone->trempitchnum);
377 	else if (!strcmp(opts, "tremfc"))
378 		tone->tremfc = config_parse_int16(cp, &tone->tremfcnum);
379 	else if (!strcmp(opts, "modpitch"))
380 		tone->modpitch = config_parse_int16(cp, &tone->modpitchnum);
381 	else if (!strcmp(opts, "modfc"))
382 		tone->modfc = config_parse_int16(cp, &tone->modfcnum);
383 	else if (!strcmp(opts, "fc"))
384 		tone->fc = config_parse_int16(cp, &tone->fcnum);
385 	else if (!strcmp(opts, "q"))
386 		tone->reso = config_parse_int16(cp, &tone->resonum);
387 	else if (!strcmp(opts, "fckeyf"))		/* filter key-follow */
388 		tone->key_to_fc = atoi(cp);
389 	else if (!strcmp(opts, "fcvelf"))		/* filter velocity-follow */
390 		tone->vel_to_fc = atoi(cp);
391 	else if (!strcmp(opts, "qvelf"))		/* resonance velocity-follow */
392 		tone->vel_to_resonance = atoi(cp);
393 	else {
394 		printMessage(CMSG_ERROR, VERB_NORMAL,
395 			"%s: line %d: bad patch option %s",
396 			name, line, opts);
397 		return 1;
398 	}
399 	return 0;
400 }
401 
402 
reinit_tone_bank_element(ToneBankElement * tone)403 void Instruments::reinit_tone_bank_element(ToneBankElement *tone)
404 {
405 	free_tone_bank_element(tone);
406 	tone->note = tone->pan = -1;
407 	tone->strip_loop = tone->strip_envelope = tone->strip_tail = -1;
408 	tone->amp = -1;
409 	tone->rnddelay = 0;
410 	tone->loop_timeout = 0;
411 	tone->legato = tone->damper_mode = tone->key_to_fc = tone->vel_to_fc = 0;
412 	tone->reverb_send = tone->chorus_send = tone->delay_send = -1;
413 	tone->tva_level = -1;
414 	tone->play_note = -1;
415 }
416 
417 
set_gus_patchconf(const char * name,int line,ToneBankElement * tone,char * pat,char ** opts)418 int Instruments::set_gus_patchconf(const char *name, int line, ToneBankElement *tone, char *pat, char **opts)
419 {
420 	int j;
421 	reinit_tone_bank_element(tone);
422 
423 	if (strcmp(pat, "%font") == 0) /* Font extention */
424 	{
425 		/* %font filename bank prog [note-to-use]
426 		* %font filename 128 bank key
427 		*/
428 
429 		if (opts[0] == NULL || opts[1] == NULL || opts[2] == NULL ||
430 			(atoi(opts[1]) == 128 && opts[3] == NULL))
431 		{
432 			printMessage(CMSG_ERROR, VERB_NORMAL,
433 				"%s: line %d: Syntax error", name, line);
434 			return 1;
435 		}
436 		tone->name = safe_strdup(opts[0]);
437 		tone->instype = 1;
438 		if (atoi(opts[1]) == 128) /* drum */
439 		{
440 			tone->font_bank = 128;
441 			tone->font_preset = atoi(opts[2]);
442 			tone->font_keynote = atoi(opts[3]);
443 			opts += 4;
444 		}
445 		else
446 		{
447 			tone->font_bank = atoi(opts[1]);
448 			tone->font_preset = atoi(opts[2]);
449 
450 			if (opts[3] && isdigit(opts[3][0]))
451 			{
452 				tone->font_keynote = atoi(opts[3]);
453 				opts += 4;
454 			}
455 			else
456 			{
457 				tone->font_keynote = -1;
458 				opts += 3;
459 			}
460 		}
461 	}
462 	else if (strcmp(pat, "%sample") == 0) /* Sample extention */
463 	{
464 		/* %sample filename */
465 
466 		if (opts[0] == NULL)
467 		{
468 			printMessage(CMSG_ERROR, VERB_NORMAL,
469 				"%s: line %d: Syntax error", name, line);
470 			return 1;
471 		}
472 		tone->name = safe_strdup(opts[0]);
473 		tone->instype = 2;
474 		opts++;
475 	}
476 	else
477 	{
478 		tone->instype = 0;
479 		tone->name = safe_strdup(pat);
480 	}
481 
482 	for (j = 0; opts[j] != NULL; j++)
483 	{
484 		int err;
485 		if ((err = set_gus_patchconf_opts(name, line, opts[j], tone)) != 0)
486 			return err;
487 	}
488 	if (tone->comment == NULL)
489 		tone->comment = safe_strdup(tone->name);
490 	return 0;
491 }
492 
493 
494 
set_patchconf(const char * name,int line,ToneBank * bank,char * w[],int dr,int mapid,int bankmapfrom,int bankno)495 int Instruments::set_patchconf(const char *name, int line, ToneBank *bank, char *w[], int dr, int mapid, int bankmapfrom, int bankno)
496 {
497 	int i;
498 
499 	i = atoi(w[0]);
500 	if (!dr)
501 		i -= progbase;
502 	if (i < 0 || i > 127)
503 	{
504 		if (dr)
505 			printMessage(CMSG_ERROR, VERB_NORMAL,
506 				"%s: line %d: Drum number must be between "
507 				"0 and 127",
508 				name, line);
509 		else
510 			printMessage(CMSG_ERROR, VERB_NORMAL,
511 				"%s: line %d: Program must be between "
512 				"%d and %d",
513 				name, line, progbase, 127 + progbase);
514 		return 1;
515 	}
516 	if (!bank)
517 	{
518 		printMessage(CMSG_ERROR, VERB_NORMAL,
519 			"%s: line %d: Must specify tone bank or drum set "
520 			"before assignment", name, line);
521 		return 1;
522 	}
523 
524 	if (set_gus_patchconf(name, line, &bank->tone[i], w[1], w + 2))
525 		return 1;
526 	if (mapid != INST_NO_MAP)
527 		set_instrument_map(mapid, bankmapfrom, i, bankno, i);
528 	return 0;
529 }
530 
531 
532 
533 /* string[0] should not be '#' */
strip_trailing_comment(char * string,int next_token_index)534 int Instruments::strip_trailing_comment(char *string, int next_token_index)
535 {
536 	if (string[next_token_index - 1] == '#'	/* strip \1 in /^\S+(#*[ \t].*)/ */
537 		&& (string[next_token_index] == ' ' || string[next_token_index] == '\t'))
538 	{
539 		string[next_token_index] = '\0';	/* new c-string terminator */
540 		while (string[--next_token_index - 1] == '#')
541 			;
542 	}
543 	return next_token_index;
544 }
545 
expand_variables(char * string,MBlockList * varbuf,const char * basedir)546 char *Instruments::expand_variables(char *string, MBlockList *varbuf, const char *basedir)
547 {
548 	char *p, *expstr;
549 	const char *copystr;
550 	int limlen, copylen, explen, varlen, braced;
551 
552 	if ((p = strchr(string, '$')) == NULL)
553 		return string;
554 	varlen = (int)strlen(basedir);
555 	explen = limlen = 0;
556 	expstr = NULL;
557 	copystr = string;
558 	copylen = p - string;
559 	string = p;
560 	for (;;)
561 	{
562 		if (explen + copylen + 1 > limlen)
563 		{
564 			limlen += copylen + 128;
565 			expstr = (char*)memcpy(new_segment(varbuf, limlen), expstr, explen);
566 		}
567 		memcpy(&expstr[explen], copystr, copylen);
568 		explen += copylen;
569 		if (*string == '\0')
570 			break;
571 		else if (*string == '$')
572 		{
573 			braced = *++string == '{';
574 			if (braced)
575 			{
576 				if ((p = strchr(string + 1, '}')) == NULL)
577 					p = string;	/* no closing brace */
578 				else
579 					string++;
580 			}
581 			else
582 				for (p = string; isalnum(*p) || *p == '_'; p++);
583 			if (p == string)	/* empty */
584 			{
585 				copystr = "${";
586 				copylen = 1 + braced;
587 			}
588 			else
589 			{
590 				if (p - string == 7 && memcmp(string, "basedir", 7) == 0)
591 				{
592 					copystr = basedir;
593 					copylen = varlen;
594 				}
595 				else	/* undefined variable */
596 					copylen = 0;
597 				string = p + braced;
598 			}
599 		}
600 		else	/* search next */
601 		{
602 			p = strchr(string, '$');
603 			if (p == NULL)
604 				copylen = (int)strlen(string);
605 			else
606 				copylen = int(p - string);
607 			copystr = string;
608 			string += copylen;
609 		}
610 	}
611 	expstr[explen] = '\0';
612 	return expstr;
613 }
614 
615 
read_config_file(const char * name,int self,int allow_missing_file)616 int Instruments::read_config_file(const char *name, int self, int allow_missing_file)
617 {
618 	timidity_file *tf;
619 	char buf[1024], *tmp, *w[MAXWORDS + 1], *cp;
620 	ToneBank *bank = NULL;
621 	int i, j, k, line = 0, words, errcnt = 0;
622 	static int rcf_count = 0;
623 	int dr = 0, bankno = 0, mapid = INST_NO_MAP, origbankno = 0x7FFFFFFF;
624 	int extension_flag, param_parse_err;
625 	MBlockList varbuf;
626 	const char *basedir;
627 	char *sep;
628 
629 	if (rcf_count > 50)
630 	{
631 		printMessage(CMSG_ERROR, VERB_NORMAL,
632 			"Probable source loop in configuration files");
633 		return READ_CONFIG_RECURSION;
634 	}
635 
636 	tf = open_file(name, sfreader);
637 	if (tf == NULL)
638 		return allow_missing_file ? READ_CONFIG_FILE_NOT_FOUND :
639 		READ_CONFIG_ERROR;
640 
641 	init_mblock(&varbuf);
642 	if (!self)
643 	{
644 		char *c = strdup_mblock(&varbuf, tf->filename.c_str());
645 		basedir = c;
646 		for (; *c; c++) if (*c == '\\') *c = '/';
647 		sep = (char*)strrchr(basedir, '/');
648 	}
649 	else
650 		sep = NULL;
651 	if (sep == NULL)
652 	{
653 		basedir = ".";
654 	}
655 	else
656 	{
657 		if ((cp = (char*)strchr(sep, '#')) != NULL)
658 			sep = cp + 1;	/* inclusive of '#' */
659 		*sep = '\0';
660 	}
661 
662 	while (tf_gets(buf, sizeof(buf), tf))
663 	{
664 		line++;
665 		if (strncmp(buf, "#extension", 10) == 0) {
666 			extension_flag = 1;
667 			i = 10;
668 		}
669 		else
670 		{
671 			extension_flag = 0;
672 			i = 0;
673 		}
674 
675 		while (isspace(buf[i]))			/* skip /^\s*(?#)/ */
676 			i++;
677 		if (buf[i] == '#' || buf[i] == '\0')	/* /^#|^$/ */
678 			continue;
679 		tmp = expand_variables(buf, &varbuf, basedir);
680 		j = (int)strcspn(tmp + i, " \t\r\n\240");
681 		if (j == 0)
682 			j = (int)strlen(tmp + i);
683 		j = strip_trailing_comment(tmp + i, j);
684 		tmp[i + j] = '\0';			/* terminate the first token */
685 		w[0] = tmp + i;
686 		i += j + 1;
687 		words = param_parse_err = 0;
688 		while (words < MAXWORDS - 1)		/* -1 : next arg */
689 		{
690 			char *terminator;
691 
692 			while (isspace(tmp[i]))		/* skip /^\s*(?#)/ */
693 				i++;
694 			if (tmp[i] == '\0'
695 				|| tmp[i] == '#')		/* /\s#/ */
696 				break;
697 			if ((tmp[i] == '"' || tmp[i] == '\'')
698 				&& (terminator = strchr(tmp + i + 1, tmp[i])) != NULL)
699 			{
700 				if (!isspace(terminator[1]) && terminator[1] != '\0')
701 				{
702 					printMessage(CMSG_ERROR, VERB_NORMAL,
703 						"%s: line %d: there must be at least one whitespace between "
704 						"string terminator (%c) and the next parameter", name, line, tmp[i]);
705 					CHECKERRLIMIT;
706 					param_parse_err = 1;
707 					break;
708 				}
709 				w[++words] = tmp + i + 1;
710 				i = terminator - tmp + 1;
711 				*terminator = '\0';
712 			}
713 			else	/* not terminated */
714 			{
715 				j = (int)strcspn(tmp + i, " \t\r\n\240");
716 				if (j > 0)
717 					j = strip_trailing_comment(tmp + i, j);
718 				w[++words] = tmp + i;
719 				i += j;
720 				if (tmp[i] != '\0')		/* unless at the end-of-string (i.e. EOF) */
721 					tmp[i++] = '\0';		/* terminate the token */
722 			}
723 		}
724 		if (param_parse_err)
725 			continue;
726 		w[++words] = NULL;
727 
728 		/*
729 		* #extension [something...]
730 		*/
731 
732 		/* #extension timeout program sec */
733 		if (strcmp(w[0], "timeout") == 0)
734 		{
735 			if (words != 3)
736 			{
737 				printMessage(CMSG_ERROR, VERB_NORMAL,
738 					"%s: line %d: syntax error", name, line);
739 				CHECKERRLIMIT;
740 				continue;
741 			}
742 			if (!bank)
743 			{
744 				printMessage(CMSG_ERROR, VERB_NORMAL,
745 					"%s: line %d: Must specify tone bank or drum set "
746 					"before assignment", name, line);
747 				CHECKERRLIMIT;
748 				continue;
749 			}
750 			i = atoi(w[1]);
751 			if (i < 0 || i > 127)
752 			{
753 				printMessage(CMSG_ERROR, VERB_NORMAL,
754 					"%s: line %d: extension timeout "
755 					"must be between 0 and 127", name, line);
756 				CHECKERRLIMIT;
757 				continue;
758 			}
759 			bank->tone[i].loop_timeout = atoi(w[2]);
760 		}
761 		/* #extension copydrumset drumset */
762 		else if (strcmp(w[0], "copydrumset") == 0)
763 		{
764 			if (words < 2)
765 			{
766 				printMessage(CMSG_ERROR, VERB_NORMAL,
767 					"%s: line %d: No copydrumset number given",
768 					name, line);
769 				CHECKERRLIMIT;
770 				continue;
771 			}
772 			i = atoi(w[1]);
773 			if (i < 0 || i > 127)
774 			{
775 				printMessage(CMSG_ERROR, VERB_NORMAL,
776 					"%s: line %d: extension copydrumset "
777 					"must be between 0 and 127", name, line);
778 				CHECKERRLIMIT;
779 				continue;
780 			}
781 			if (!bank)
782 			{
783 				printMessage(CMSG_ERROR, VERB_NORMAL,
784 					"%s: line %d: Must specify tone bank or "
785 					"drum set before assignment", name, line);
786 				CHECKERRLIMIT;
787 				continue;
788 			}
789 			copybank(bank, drumset[i], mapid, origbankno, bankno);
790 		}
791 		/* #extension copybank bank */
792 		else if (strcmp(w[0], "copybank") == 0)
793 		{
794 			if (words < 2)
795 			{
796 				printMessage(CMSG_ERROR, VERB_NORMAL,
797 					"%s: line %d: No copybank number given",
798 					name, line);
799 				CHECKERRLIMIT;
800 				continue;
801 			}
802 			i = atoi(w[1]);
803 			if (i < 0 || i > 127)
804 			{
805 				printMessage(CMSG_ERROR, VERB_NORMAL,
806 					"%s: line %d: extension copybank "
807 					"must be between 0 and 127", name, line);
808 				CHECKERRLIMIT;
809 				continue;
810 			}
811 			if (!bank)
812 			{
813 				printMessage(CMSG_ERROR, VERB_NORMAL,
814 					"%s: line %d: Must specify tone bank or "
815 					"drum set before assignment", name, line);
816 				CHECKERRLIMIT;
817 				continue;
818 			}
819 			copybank(bank, tonebank[i], mapid, origbankno, bankno);
820 		}
821 		/* #extension copymap tomapid frommapid */
822 		else if (strcmp(w[0], "copymap") == 0)
823 		{
824 			int mapto, mapfrom;
825 			int toisdrum, fromisdrum;
826 
827 			if (words != 3)
828 			{
829 				printMessage(CMSG_ERROR, VERB_NORMAL,
830 					"%s: line %d: syntax error", name, line);
831 				CHECKERRLIMIT;
832 				continue;
833 			}
834 			if ((mapto = mapname2id(w[1], &toisdrum)) == -1)
835 			{
836 				printMessage(CMSG_ERROR, VERB_NORMAL,
837 					"%s: line %d: Invalid map name: %s", name, line, w[1]);
838 				CHECKERRLIMIT;
839 				continue;
840 			}
841 			if ((mapfrom = mapname2id(w[2], &fromisdrum)) == -1)
842 			{
843 				printMessage(CMSG_ERROR, VERB_NORMAL,
844 					"%s: line %d: Invalid map name: %s", name, line, w[2]);
845 				CHECKERRLIMIT;
846 				continue;
847 			}
848 			if (toisdrum != fromisdrum)
849 			{
850 				printMessage(CMSG_ERROR, VERB_NORMAL,
851 					"%s: line %d: Map type should be matched", name, line);
852 				CHECKERRLIMIT;
853 				continue;
854 			}
855 			if (copymap(mapto, mapfrom, toisdrum))
856 			{
857 				printMessage(CMSG_ERROR, VERB_NORMAL,
858 					"%s: line %d: No free %s available to map",
859 					name, line, toisdrum ? "drum set" : "tone bank");
860 				CHECKERRLIMIT;
861 				continue;
862 			}
863 		}
864 		/* #extension undef program */
865 		else if (strcmp(w[0], "undef") == 0)
866 		{
867 			if (words < 2)
868 			{
869 				printMessage(CMSG_ERROR, VERB_NORMAL,
870 					"%s: line %d: No undef number given",
871 					name, line);
872 				CHECKERRLIMIT;
873 				continue;
874 			}
875 			i = atoi(w[1]);
876 			if (i < 0 || i > 127)
877 			{
878 				printMessage(CMSG_ERROR, VERB_NORMAL,
879 					"%s: line %d: extension undef "
880 					"must be between 0 and 127", name, line);
881 				CHECKERRLIMIT;
882 				continue;
883 			}
884 			if (!bank)
885 			{
886 				printMessage(CMSG_ERROR, VERB_NORMAL,
887 					"%s: line %d: Must specify tone bank or "
888 					"drum set before assignment", name, line);
889 				CHECKERRLIMIT;
890 				continue;
891 			}
892 			free_tone_bank_element(&bank->tone[i]);
893 		}
894 		/* #extension altassign numbers... */
895 		else if (strcmp(w[0], "altassign") == 0)
896 		{
897 			ToneBank *bk;
898 
899 			if (!bank)
900 			{
901 				printMessage(CMSG_ERROR, VERB_NORMAL,
902 					"%s: line %d: Must specify tone bank or drum set "
903 					"before altassign", name, line);
904 				CHECKERRLIMIT;
905 				continue;
906 			}
907 			if (words < 2)
908 			{
909 				printMessage(CMSG_ERROR, VERB_NORMAL,
910 					"%s: line %d: No alternate assignment", name, line);
911 				CHECKERRLIMIT;
912 				continue;
913 			}
914 
915 			if (!dr) {
916 				printMessage(CMSG_WARNING, VERB_NORMAL,
917 					"%s: line %d: Warning: Not a drumset altassign"
918 					" (ignored)",
919 					name, line);
920 				continue;
921 			}
922 
923 			bk = drumset[bankno];
924 			bk->alt = add_altassign_string(bk->alt, w + 1, words - 1);
925 		}	/* #extension legato [program] [0 or 1] */
926 		else if (strcmp(w[0], "legato") == 0)
927 		{
928 			if (words != 3)
929 			{
930 				printMessage(CMSG_ERROR, VERB_NORMAL,
931 					"%s: line %d: syntax error", name, line);
932 				CHECKERRLIMIT;
933 				continue;
934 			}
935 			if (!bank)
936 			{
937 				printMessage(CMSG_ERROR, VERB_NORMAL,
938 					"%s: line %d: Must specify tone bank or drum set "
939 					"before assignment", name, line);
940 				CHECKERRLIMIT;
941 				continue;
942 			}
943 			i = atoi(w[1]);
944 			if (i < 0 || i > 127)
945 			{
946 				printMessage(CMSG_ERROR, VERB_NORMAL,
947 					"%s: line %d: extension legato "
948 					"must be between 0 and 127", name, line);
949 				CHECKERRLIMIT;
950 				continue;
951 			}
952 			bank->tone[i].legato = atoi(w[2]);
953 		}	/* #extension damper [program] [0 or 1] */
954 		else if (strcmp(w[0], "damper") == 0)
955 		{
956 			if (words != 3)
957 			{
958 				printMessage(CMSG_ERROR, VERB_NORMAL,
959 					"%s: line %d: syntax error", name, line);
960 				CHECKERRLIMIT;
961 				continue;
962 			}
963 			if (!bank)
964 			{
965 				printMessage(CMSG_ERROR, VERB_NORMAL,
966 					"%s: line %d: Must specify tone bank or drum set "
967 					"before assignment", name, line);
968 				CHECKERRLIMIT;
969 				continue;
970 			}
971 			i = atoi(w[1]);
972 			if (i < 0 || i > 127)
973 			{
974 				printMessage(CMSG_ERROR, VERB_NORMAL,
975 					"%s: line %d: extension damper "
976 					"must be between 0 and 127", name, line);
977 				CHECKERRLIMIT;
978 				continue;
979 			}
980 			bank->tone[i].damper_mode = atoi(w[2]);
981 		}	/* #extension rnddelay [program] [0 or 1] */
982 		else if (strcmp(w[0], "rnddelay") == 0)
983 		{
984 			if (words != 3)
985 			{
986 				printMessage(CMSG_ERROR, VERB_NORMAL,
987 					"%s: line %d: syntax error", name, line);
988 				CHECKERRLIMIT;
989 				continue;
990 			}
991 			if (!bank)
992 			{
993 				printMessage(CMSG_ERROR, VERB_NORMAL,
994 					"%s: line %d: Must specify tone bank or drum set "
995 					"before assignment", name, line);
996 				CHECKERRLIMIT;
997 				continue;
998 			}
999 			i = atoi(w[1]);
1000 			if (i < 0 || i > 127)
1001 			{
1002 				printMessage(CMSG_ERROR, VERB_NORMAL,
1003 					"%s: line %d: extension rnddelay "
1004 					"must be between 0 and 127", name, line);
1005 				CHECKERRLIMIT;
1006 				continue;
1007 			}
1008 			bank->tone[i].rnddelay = atoi(w[2]);
1009 		}	/* #extension level program tva_level */
1010 		else if (strcmp(w[0], "level") == 0)
1011 		{
1012 			if (words != 3)
1013 			{
1014 				printMessage(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1015 				CHECKERRLIMIT;
1016 				continue;
1017 			}
1018 			if (!bank)
1019 			{
1020 				printMessage(CMSG_ERROR, VERB_NORMAL,
1021 					"%s: line %d: Must specify tone bank or drum set "
1022 					"before assignment", name, line);
1023 				CHECKERRLIMIT;
1024 				continue;
1025 			}
1026 			i = atoi(w[2]);
1027 			if (i < 0 || i > 127)
1028 			{
1029 				printMessage(CMSG_ERROR, VERB_NORMAL,
1030 					"%s: line %d: extension level "
1031 					"must be between 0 and 127", name, line);
1032 				CHECKERRLIMIT;
1033 				continue;
1034 			}
1035 			cp = w[1];
1036 			do {
1037 				if (string_to_7bit_range(cp, &j, &k))
1038 				{
1039 					while (j <= k)
1040 						bank->tone[j++].tva_level = i;
1041 				}
1042 				cp = strchr(cp, ',');
1043 			} while (cp++ != NULL);
1044 		}	/* #extension reverbsend */
1045 		else if (strcmp(w[0], "reverbsend") == 0)
1046 		{
1047 			if (words != 3)
1048 			{
1049 				printMessage(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1050 				CHECKERRLIMIT;
1051 				continue;
1052 			}
1053 			if (!bank)
1054 			{
1055 				printMessage(CMSG_ERROR, VERB_NORMAL,
1056 					"%s: line %d: Must specify tone bank or drum set "
1057 					"before assignment", name, line);
1058 				CHECKERRLIMIT;
1059 				continue;
1060 			}
1061 			i = atoi(w[2]);
1062 			if (i < 0 || i > 127)
1063 			{
1064 				printMessage(CMSG_ERROR, VERB_NORMAL,
1065 					"%s: line %d: extension reverbsend "
1066 					"must be between 0 and 127", name, line);
1067 				CHECKERRLIMIT;
1068 				continue;
1069 			}
1070 			cp = w[1];
1071 			do {
1072 				if (string_to_7bit_range(cp, &j, &k))
1073 				{
1074 					while (j <= k)
1075 						bank->tone[j++].reverb_send = i;
1076 				}
1077 				cp = strchr(cp, ',');
1078 			} while (cp++ != NULL);
1079 		}	/* #extension chorussend */
1080 		else if (strcmp(w[0], "chorussend") == 0)
1081 		{
1082 			if (words != 3)
1083 			{
1084 				printMessage(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1085 				CHECKERRLIMIT;
1086 				continue;
1087 			}
1088 			if (!bank)
1089 			{
1090 				printMessage(CMSG_ERROR, VERB_NORMAL,
1091 					"%s: line %d: Must specify tone bank or drum set "
1092 					"before assignment", name, line);
1093 				CHECKERRLIMIT;
1094 				continue;
1095 			}
1096 			i = atoi(w[2]);
1097 			if (i < 0 || i > 127)
1098 			{
1099 				printMessage(CMSG_ERROR, VERB_NORMAL,
1100 					"%s: line %d: extension chorussend "
1101 					"must be between 0 and 127", name, line);
1102 				CHECKERRLIMIT;
1103 				continue;
1104 			}
1105 			cp = w[1];
1106 			do {
1107 				if (string_to_7bit_range(cp, &j, &k))
1108 				{
1109 					while (j <= k)
1110 						bank->tone[j++].chorus_send = i;
1111 				}
1112 				cp = strchr(cp, ',');
1113 			} while (cp++ != NULL);
1114 		}	/* #extension delaysend */
1115 		else if (strcmp(w[0], "delaysend") == 0)
1116 		{
1117 			if (words != 3)
1118 			{
1119 				printMessage(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1120 				CHECKERRLIMIT;
1121 				continue;
1122 			}
1123 			if (!bank)
1124 			{
1125 				printMessage(CMSG_ERROR, VERB_NORMAL,
1126 					"%s: line %d: Must specify tone bank or drum set "
1127 					"before assignment", name, line);
1128 				CHECKERRLIMIT;
1129 				continue;
1130 			}
1131 			i = atoi(w[2]);
1132 			if (i < 0 || i > 127)
1133 			{
1134 				printMessage(CMSG_ERROR, VERB_NORMAL,
1135 					"%s: line %d: extension delaysend "
1136 					"must be between 0 and 127", name, line);
1137 				CHECKERRLIMIT;
1138 				continue;
1139 			}
1140 			cp = w[1];
1141 			do {
1142 				if (string_to_7bit_range(cp, &j, &k))
1143 				{
1144 					while (j <= k)
1145 						bank->tone[j++].delay_send = i;
1146 				}
1147 				cp = strchr(cp, ',');
1148 			} while (cp++ != NULL);
1149 		}	/* #extension playnote */
1150 		else if (strcmp(w[0], "playnote") == 0)
1151 		{
1152 			if (words != 3)
1153 			{
1154 				printMessage(CMSG_ERROR, VERB_NORMAL, "%s: line %d: syntax error", name, line);
1155 				CHECKERRLIMIT;
1156 				continue;
1157 			}
1158 			if (!bank)
1159 			{
1160 				printMessage(CMSG_ERROR, VERB_NORMAL,
1161 					"%s: line %d: Must specify tone bank or drum set "
1162 					"before assignment", name, line);
1163 				CHECKERRLIMIT;
1164 				continue;
1165 			}
1166 			i = atoi(w[2]);
1167 			if (i < 0 || i > 127)
1168 			{
1169 				printMessage(CMSG_ERROR, VERB_NORMAL,
1170 					"%s: line %d: extension playnote"
1171 					"must be between 0 and 127", name, line);
1172 				CHECKERRLIMIT;
1173 				continue;
1174 			}
1175 			cp = w[1];
1176 			do {
1177 				if (string_to_7bit_range(cp, &j, &k))
1178 				{
1179 					while (j <= k)
1180 						bank->tone[j++].play_note = i;
1181 				}
1182 				cp = strchr(cp, ',');
1183 			} while (cp++ != NULL);
1184 		}
1185 		else if (!strcmp(w[0], "soundfont"))
1186 		{
1187 			int order, cutoff, isremove, reso, amp;
1188 			char *sf_file;
1189 
1190 			if (words < 2)
1191 			{
1192 				printMessage(CMSG_ERROR, VERB_NORMAL,
1193 					"%s: line %d: No soundfont file given",
1194 					name, line);
1195 				CHECKERRLIMIT;
1196 				continue;
1197 			}
1198 
1199 			sf_file = w[1];
1200 			order = cutoff = reso = amp = -1;
1201 			isremove = 0;
1202 			for (j = 2; j < words; j++)
1203 			{
1204 				if (strcmp(w[j], "remove") == 0)
1205 				{
1206 					isremove = 1;
1207 					break;
1208 				}
1209 				if (!(cp = strchr(w[j], '=')))
1210 				{
1211 					printMessage(CMSG_ERROR, VERB_NORMAL,
1212 						"%s: line %d: bad patch option %s",
1213 						name, line, w[j]);
1214 					CHECKERRLIMIT;
1215 					break;
1216 				}
1217 				*cp++ = 0;
1218 				k = atoi(cp);
1219 				if (!strcmp(w[j], "order"))
1220 				{
1221 					if (k < 0 || (*cp < '0' || *cp > '9'))
1222 					{
1223 						printMessage(CMSG_ERROR, VERB_NORMAL,
1224 							"%s: line %d: order must be a digit",
1225 							name, line);
1226 						CHECKERRLIMIT;
1227 						break;
1228 					}
1229 					order = k;
1230 				}
1231 				else if (!strcmp(w[j], "cutoff"))
1232 				{
1233 					if (k < 0 || (*cp < '0' || *cp > '9'))
1234 					{
1235 						printMessage(CMSG_ERROR, VERB_NORMAL,
1236 							"%s: line %d: cutoff must be a digit",
1237 							name, line);
1238 						CHECKERRLIMIT;
1239 						break;
1240 					}
1241 					cutoff = k;
1242 				}
1243 				else if (!strcmp(w[j], "reso"))
1244 				{
1245 					if (k < 0 || (*cp < '0' || *cp > '9'))
1246 					{
1247 						printMessage(CMSG_ERROR, VERB_NORMAL,
1248 							"%s: line %d: reso must be a digit",
1249 							name, line);
1250 						CHECKERRLIMIT;
1251 						break;
1252 					}
1253 					reso = k;
1254 				}
1255 				else if (!strcmp(w[j], "amp"))
1256 				{
1257 					amp = k;
1258 				}
1259 			}
1260 			if (isremove)
1261 				remove_soundfont(sf_file);
1262 			else
1263 				add_soundfont(sf_file, order, cutoff, reso, amp);
1264 		}
1265 		else if (!strcmp(w[0], "font"))
1266 		{
1267 			int bank, preset, keynote;
1268 			if (words < 2)
1269 			{
1270 				printMessage(CMSG_ERROR, VERB_NORMAL,
1271 					"%s: line %d: no font command", name, line);
1272 				CHECKERRLIMIT;
1273 				continue;
1274 			}
1275 			if (!strcmp(w[1], "exclude"))
1276 			{
1277 				if (words < 3)
1278 				{
1279 					printMessage(CMSG_ERROR, VERB_NORMAL,
1280 						"%s: line %d: No bank/preset/key is given",
1281 						name, line);
1282 					CHECKERRLIMIT;
1283 					continue;
1284 				}
1285 				bank = atoi(w[2]);
1286 				if (words >= 4)
1287 					preset = atoi(w[3]) - progbase;
1288 				else
1289 					preset = -1;
1290 				if (words >= 5)
1291 					keynote = atoi(w[4]);
1292 				else
1293 					keynote = -1;
1294 				if (exclude_soundfont(bank, preset, keynote))
1295 				{
1296 					printMessage(CMSG_ERROR, VERB_NORMAL,
1297 						"%s: line %d: No soundfont is given",
1298 						name, line);
1299 					CHECKERRLIMIT;
1300 				}
1301 			}
1302 			else if (!strcmp(w[1], "order"))
1303 			{
1304 				int order;
1305 				if (words < 4)
1306 				{
1307 					printMessage(CMSG_ERROR, VERB_NORMAL,
1308 						"%s: line %d: No order/bank is given",
1309 						name, line);
1310 					CHECKERRLIMIT;
1311 					continue;
1312 				}
1313 				order = atoi(w[2]);
1314 				bank = atoi(w[3]);
1315 				if (words >= 5)
1316 					preset = atoi(w[4]) - progbase;
1317 				else
1318 					preset = -1;
1319 				if (words >= 6)
1320 					keynote = atoi(w[5]);
1321 				else
1322 					keynote = -1;
1323 				if (order_soundfont(bank, preset, keynote, order))
1324 				{
1325 					printMessage(CMSG_ERROR, VERB_NORMAL,
1326 						"%s: line %d: No soundfont is given",
1327 						name, line);
1328 					CHECKERRLIMIT;
1329 				}
1330 			}
1331 		}
1332 		else if (!strcmp(w[0], "progbase"))
1333 		{
1334 			if (words < 2 || *w[1] < '0' || *w[1] > '9')
1335 			{
1336 				printMessage(CMSG_ERROR, VERB_NORMAL,
1337 					"%s: line %d: syntax error", name, line);
1338 				CHECKERRLIMIT;
1339 				continue;
1340 			}
1341 			progbase = atoi(w[1]);
1342 		}
1343 		else if (!strcmp(w[0], "map")) /* map <name> set1 elem1 set2 elem2 */
1344 		{
1345 			int arg[5], isdrum;
1346 
1347 			if (words != 6)
1348 			{
1349 				printMessage(CMSG_ERROR, VERB_NORMAL,
1350 					"%s: line %d: syntax error", name, line);
1351 				CHECKERRLIMIT;
1352 				continue;
1353 			}
1354 			if ((arg[0] = mapname2id(w[1], &isdrum)) == -1)
1355 			{
1356 				printMessage(CMSG_ERROR, VERB_NORMAL,
1357 					"%s: line %d: Invalid map name: %s", name, line, w[1]);
1358 				CHECKERRLIMIT;
1359 				continue;
1360 			}
1361 			for (i = 2; i < 6; i++)
1362 				arg[i - 1] = atoi(w[i]);
1363 			if (isdrum)
1364 			{
1365 				arg[1] -= progbase;
1366 				arg[3] -= progbase;
1367 			}
1368 			else
1369 			{
1370 				arg[2] -= progbase;
1371 				arg[4] -= progbase;
1372 			}
1373 
1374 			for (i = 1; i < 5; i++)
1375 				if (arg[i] < 0 || arg[i] > 127)
1376 					break;
1377 			if (i != 5)
1378 			{
1379 				printMessage(CMSG_ERROR, VERB_NORMAL,
1380 					"%s: line %d: Invalid parameter", name, line);
1381 				CHECKERRLIMIT;
1382 				continue;
1383 			}
1384 			set_instrument_map(arg[0], arg[1], arg[2], arg[3], arg[4]);
1385 		}
1386 
1387 		/*
1388 		* Standard configurations
1389 		*/
1390 		else if (!strcmp(w[0], "dir"))
1391 		{
1392 			if (words < 2)
1393 			{
1394 				printMessage(CMSG_ERROR, VERB_NORMAL,
1395 					"%s: line %d: No directory given", name, line);
1396 				CHECKERRLIMIT;
1397 				continue;
1398 			}
1399 			for (i = 1; i < words; i++)
1400                 sfreader->add_search_path(w[i]);
1401 		}
1402 		else if (!strcmp(w[0], "source") || !strcmp(w[0], "trysource"))
1403 		{
1404 			if (words < 2)
1405 			{
1406 				printMessage(CMSG_ERROR, VERB_NORMAL,
1407 					"%s: line %d: No file name given", name, line);
1408 				CHECKERRLIMIT;
1409 				continue;
1410 			}
1411 			for (i = 1; i < words; i++)
1412 			{
1413 				int status;
1414 				rcf_count++;
1415 				status = read_config_file(w[i], 0, !strcmp(w[0], "trysource"));
1416 				rcf_count--;
1417 				switch (status) {
1418 				case READ_CONFIG_SUCCESS:
1419 					break;
1420 				case READ_CONFIG_ERROR:
1421 					CHECKERRLIMIT;
1422 					continue;
1423 				case READ_CONFIG_RECURSION:
1424 					reuse_mblock(&varbuf);
1425 					tf_close(tf);
1426 					return READ_CONFIG_RECURSION;
1427 				case READ_CONFIG_FILE_NOT_FOUND:
1428 					break;
1429 				}
1430 			}
1431 		}
1432 		else if (!strcmp(w[0], "default"))
1433 		{
1434 			if (words != 2)
1435 			{
1436 				printMessage(CMSG_ERROR, VERB_NORMAL,
1437 					"%s: line %d: Must specify exactly one patch name",
1438 					name, line);
1439 				CHECKERRLIMIT;
1440 				continue;
1441 			}
1442 			strncpy(def_instr_name, w[1], 255);
1443 			def_instr_name[255] = '\0';
1444 			default_instrument_name = def_instr_name;
1445 		}
1446 		/* drumset [mapid] num */
1447 		else if (!strcmp(w[0], "drumset"))
1448 		{
1449 			int newmapid, isdrum, newbankno;
1450 
1451 			if (words < 2)
1452 			{
1453 				printMessage(CMSG_ERROR, VERB_NORMAL,
1454 					"%s: line %d: No drum set number given", name, line);
1455 				CHECKERRLIMIT;
1456 				continue;
1457 			}
1458 			if (words != 2 && !isdigit(*w[1]))
1459 			{
1460 				if ((newmapid = mapname2id(w[1], &isdrum)) == -1 || !isdrum)
1461 				{
1462 					printMessage(CMSG_ERROR, VERB_NORMAL,
1463 						"%s: line %d: Invalid drum set map name: %s", name, line, w[1]);
1464 					CHECKERRLIMIT;
1465 					continue;
1466 				}
1467 				words--;
1468 				memmove(&w[1], &w[2], sizeof w[0] * words);
1469 			}
1470 			else
1471 				newmapid = INST_NO_MAP;
1472 			i = atoi(w[1]) - progbase;
1473 			if (i < 0 || i > 127)
1474 			{
1475 				printMessage(CMSG_ERROR, VERB_NORMAL,
1476 					"%s: line %d: Drum set must be between %d and %d",
1477 					name, line,
1478 					progbase, progbase + 127);
1479 				CHECKERRLIMIT;
1480 				continue;
1481 			}
1482 
1483 			newbankno = i;
1484 			i = alloc_instrument_map_bank(1, newmapid, i);
1485 			if (i == -1)
1486 			{
1487 				printMessage(CMSG_ERROR, VERB_NORMAL,
1488 					"%s: line %d: No free drum set available to map",
1489 					name, line);
1490 				CHECKERRLIMIT;
1491 				continue;
1492 			}
1493 
1494 			if (words == 2)
1495 			{
1496 				bank = drumset[i];
1497 				bankno = i;
1498 				mapid = newmapid;
1499 				origbankno = newbankno;
1500 				dr = 1;
1501 			}
1502 			else
1503 			{
1504 				if (words < 4 || *w[2] < '0' || *w[2] > '9')
1505 				{
1506 					printMessage(CMSG_ERROR, VERB_NORMAL,
1507 						"%s: line %d: syntax error", name, line);
1508 					CHECKERRLIMIT;
1509 					continue;
1510 				}
1511 				if (set_patchconf(name, line, drumset[i], &w[2], 1, newmapid, newbankno, i))
1512 				{
1513 					CHECKERRLIMIT;
1514 					continue;
1515 				}
1516 			}
1517 		}
1518 		/* bank [mapid] num */
1519 		else if (!strcmp(w[0], "bank"))
1520 		{
1521 			int newmapid, isdrum, newbankno;
1522 
1523 			if (words < 2)
1524 			{
1525 				printMessage(CMSG_ERROR, VERB_NORMAL,
1526 					"%s: line %d: No bank number given", name, line);
1527 				CHECKERRLIMIT;
1528 				continue;
1529 			}
1530 			if (words != 2 && !isdigit(*w[1]))
1531 			{
1532 				if ((newmapid = mapname2id(w[1], &isdrum)) == -1 || isdrum)
1533 				{
1534 					printMessage(CMSG_ERROR, VERB_NORMAL,
1535 						"%s: line %d: Invalid bank map name: %s", name, line, w[1]);
1536 					CHECKERRLIMIT;
1537 					continue;
1538 				}
1539 				words--;
1540 				memmove(&w[1], &w[2], sizeof w[0] * words);
1541 			}
1542 			else
1543 				newmapid = INST_NO_MAP;
1544 			i = atoi(w[1]);
1545 			if (i < 0 || i > 127)
1546 			{
1547 				printMessage(CMSG_ERROR, VERB_NORMAL,
1548 					"%s: line %d: Tone bank must be between 0 and 127",
1549 					name, line);
1550 				CHECKERRLIMIT;
1551 				continue;
1552 			}
1553 
1554 			newbankno = i;
1555 			i = alloc_instrument_map_bank(0, newmapid, i);
1556 			if (i == -1)
1557 			{
1558 				printMessage(CMSG_ERROR, VERB_NORMAL,
1559 					"%s: line %d: No free tone bank available to map",
1560 					name, line);
1561 				CHECKERRLIMIT;
1562 				continue;
1563 			}
1564 
1565 			if (words == 2)
1566 			{
1567 				bank = tonebank[i];
1568 				bankno = i;
1569 				mapid = newmapid;
1570 				origbankno = newbankno;
1571 				dr = 0;
1572 			}
1573 			else
1574 			{
1575 				if (words < 4 || *w[2] < '0' || *w[2] > '9')
1576 				{
1577 					printMessage(CMSG_ERROR, VERB_NORMAL,
1578 						"%s: line %d: syntax error", name, line);
1579 					CHECKERRLIMIT;
1580 					continue;
1581 				}
1582 				if (set_patchconf(name, line, tonebank[i], &w[2], 0, newmapid, newbankno, i))
1583 				{
1584 					CHECKERRLIMIT;
1585 					continue;
1586 				}
1587 			}
1588 		}
1589 		else
1590 		{
1591 			if (words < 2 || *w[0] < '0' || *w[0] > '9')
1592 			{
1593 				if (extension_flag)
1594 					continue;
1595 				printMessage(CMSG_ERROR, VERB_NORMAL,
1596 					"%s: line %d: syntax error", name, line);
1597 				CHECKERRLIMIT;
1598 				continue;
1599 			}
1600 			if (set_patchconf(name, line, bank, w, dr, mapid, origbankno, bankno))
1601 			{
1602 				CHECKERRLIMIT;
1603 				continue;
1604 			}
1605 		}
1606 	}
1607 	reuse_mblock(&varbuf);
1608 	tf_close(tf);
1609 	return (errcnt == 0) ? READ_CONFIG_SUCCESS : READ_CONFIG_ERROR;
1610 }
1611 
1612 }
1613