1 
2 /*
3 #    Sfront, a SAOL to C translator
4 #    This file: Reads, processes, and generates code for SASL data.
5 #
6 # Copyright (c) 1999-2006, Regents of the University of California
7 # All rights reserved.
8 #
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions are
11 # met:
12 #
13 #  Redistributions of source code must retain the above copyright
14 #  notice, this list of conditions and the following disclaimer.
15 #
16 #  Redistributions in binary form must reproduce the above copyright
17 #  notice, this list of conditions and the following disclaimer in the
18 #  documentation and/or other materials provided with the distribution.
19 #
20 #  Neither the name of the University of California, Berkeley nor the
21 #  names of its contributors may be used to endorse or promote products
22 #  derived from this software without specific prior written permission.
23 #
24 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #
36 #    Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu
37 */
38 
39 
40 
41 #include "tree.h"
42 
43 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
44 /*                  void readscore(int)                         */
45 /*                                                              */
46 /* This top-level function for reading score data is called in  */
47 /* postparse.c, for both ASCII and binary score data. Note that */
48 /* some of the second-level score-reading functions located     */
49 /* later in this file are also used by readmidi.c.              */
50 /*                                                              */
51 /*______________________________________________________________*/
52 
53 extern tnode * scorelex(int);
54 extern int parseend(sasdata *, tnode *);
55 extern int parsetempo(sasdata *, tnode *, int);
56 extern int parsetable(sasdata *, tnode *, int, int);
57 extern int parsecontrol(sasdata *, tnode *, int);
58 extern int parselcontrol(sasdata *, tnode *, int);
59 extern int parselinstr(sasdata *, tnode *, int, int);
60 extern int parseinstr(sasdata *, tnode *, int, int);
61 extern void showbadline(tnode *);
62 extern void badline(tnode *);
63 
64 /*********************************************************/
65 /*     read .mp4/ASCII SASL: called in postparse.c       */
66 /*********************************************************/
67 
readscore(int scotype)68 void readscore(int scotype)
69 
70 {
71   sasdata * sdata = NULL;
72   tnode * nsl;
73   tnode * tptr;
74   tnode * tokenptr;
75   int found = 1;
76   int tcount;
77   int hpe;
78 
79   switch (scotype) {
80   case BCONFSCORE:
81     found = readprepare(BINSCORE); /* falls through */
82   case FCONFSCORE:
83     sdata = confsasl;
84     break;
85   case BSSTRSCORE:
86     found = readprepare(BINSSTR); /* falls through */
87     bitlinecount = -1;
88   case FSSTRSCORE:
89     sdata = sstrsasl;
90     break;
91   default:
92     internalerror("readscore.c", "readscore() switch");
93   }
94 
95   if (!found)
96     return;
97 
98   while ((tptr = scorelex(scotype))->ttype != S_EOF)
99     if (tptr->ttype != S_NEWLINE)
100       {
101 	tokenptr = nsl = tptr;
102 	tcount = 1;
103 
104 	if ((tptr->ttype == S_BADCHAR) || (tptr->ttype == S_BADNUMBER))
105 	  {
106 	    printf("Error: Misformed %s on SASL line.\n",
107 		   (tptr->ttype == S_BADCHAR) ? "token or string" : "number");
108 	    showbadline(nsl);
109 	  }
110 
111 	while (( (tptr = scorelex(scotype))->ttype != S_NEWLINE ) &&
112 	       (tptr->ttype != S_EOF))
113 	  {
114 
115 	    if ((tptr->ttype == S_BADCHAR) || (tptr->ttype == S_BADNUMBER))
116 	      {
117 		printf("Error: Misformed %s on SASL line.\n",
118 		       (tptr->ttype == S_BADCHAR) ?
119 		       "token or string" : "number");
120 		showbadline(nsl);
121 	      }
122 
123 	    if (tptr->ttype == S_STAR)
124 	      {
125 		printf("Error: '*' must be first symbol on SASL line.\n");
126 		showbadline(nsl);
127 	      }
128 	    tokenptr->next = tptr;
129 	    tokenptr = tptr;
130 	    tcount++;
131 	  }
132 	if (scotype == BSSTRSCORE)
133 	  sdata = bitscohastime ? sstrsasl : abssasl;
134 	if (nsl->ttype == S_STAR)
135 	  {
136 	    nsl = nsl->next;
137 	    hpe = 1;
138 	    tcount--;
139 	  }
140 	else
141 	  hpe = 0;
142 	found = 0;
143 	if (tcount <= 1)
144 	  badline(nsl);
145 	if (tcount == 2)
146 	  {
147 	    if (sdata->endtimeval != NULL)
148 	      sdata->scorefsize--;
149 	    found = parseend(sdata, nsl);
150 	  }
151 	if (tcount == 3)
152 	  {
153 	    found = parsetempo(sdata, nsl, hpe);
154 	    if (!found)
155 	      found = parseinstr(sdata, nsl, tcount, hpe);
156 	  }
157 	if ((!found) &&(tcount > 3) && (nsl->next->ttype == S_TABLE) )
158 	  found = parsetable(sdata, nsl, tcount, hpe);
159 	if ((!found) &&(tcount == 4) && (nsl->next->ttype == S_CONTROL))
160 	  found = parsecontrol(sdata, nsl, hpe);
161 	if ((!found) && (tcount == 5) && (nsl->next->next->ttype == S_CONTROL))
162 	  found = parselcontrol(sdata, nsl, hpe);
163 	if ((!found) && (tcount > 4))
164 	  found = parselinstr(sdata, nsl, tcount, hpe);
165 	if ((!found) &&(tcount > 3))
166 	  found = parseinstr(sdata, nsl, tcount, hpe);
167 	if (!found)
168 	  badline(nsl);
169 	sdata->scorefsize++;
170 	if (tptr->ttype == S_EOF)
171 	  {
172 	    if (cppsaol == 0)
173 	      printf("Warning: -sco file does not end in newline.\n");
174 	    break;
175 	  }
176       }
177 
178 }
179 
180 
181 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
182 /*                                                              */
183 /* Top-level functions for intermediate score processing        */
184 /*                 Called in sfmain.c                           */
185 /*                                                              */
186 /*______________________________________________________________*/
187 
188 extern tnode * maketempomap(void);
189 extern int midipointers(tnode **, tnode **);
190 extern void timestampconvert(tnode *, int);
191 
192 /*********************************************************/
193 /*    renumber abssasl and sstrmidi to absolute time     */
194 /*********************************************************/
195 
renumberabs(void)196 void renumberabs(void)
197 
198 {
199   tnode * tempo, * control, * mstart, * mend;
200   tnode * tmapptr, * tptr, * endptr;
201   float tval, ktime, fval,  midiscale;
202   float scorebase, scoremult, scorebeats;
203   int kcycleidx, kbase,  hasmidi;
204 
205 
206   /* logic: mstrfile always needs tempomap, but   */
207   /*        sstrfile needs it only if writing.    */
208   /* will need to change for has_time=0 support   */
209 
210   if ((boutfile && sstrfile) || mstrfile)
211     tempomap = maketempomap();
212 
213   if (!mstrfile)
214     return;
215 
216   /* add instr, table, and endval for has_time=0 support */
217 
218   tempo = abssasl->temporoot;
219   control = abssasl->controlroot;
220 
221   /* do renumbering to absolute time */
222 
223   hasmidi = midipointers(&mstart, &mend);
224   tmapptr = tempomap;
225   ktime = 1.0F/krate;
226   kcycleidx = kbase = 1;
227   tval = 120.0F;           /* midi file default tempo */
228   scorebase = 0.0F;
229   ktime = scoremult = 1.0F/krate;
230   midiscale = 1.0F/sstrmidi->miditicks;
231   while (tempo || control || hasmidi)
232     {
233       scorebeats = scoremult*(kcycleidx - kbase) + scorebase;
234 
235       hasmidi = 0;
236 
237       /* convert starttimes for midinotes */
238 
239       tptr = mstart;
240       while (tptr)
241 	{
242 	  while (tptr->down &&
243 		 (tptr->down->rate*midiscale <= scorebeats))
244 	    {
245 	      timestampconvert(tptr->down, kcycleidx);
246 	      tptr->down = tptr->down->next;
247 	    }
248 	  if (tptr->down)
249 	    {
250 	      hasmidi = 1;
251 	    }
252 	  tptr = tptr->next;
253 	}
254 
255       /* convert endtimes for midinotes */
256 
257       tptr = mend;
258       while (tptr)
259 	{
260 	  endptr = tptr->down;
261 	  while (endptr && endptr->opwidth)
262 	    {
263 	      if (endptr->width*midiscale <= scorebeats)
264 		{
265 		  if (!endptr->inwidth)
266 		    {
267 		      endptr->inwidth = kcycleidx;
268 		      endptr->time = (kcycleidx-1.5F)/(float)krate;
269 		    }
270 		  if (endptr == tptr->down)
271 		    tptr->down = tptr->down->next;
272 		}
273 	      endptr = endptr->next;
274 	    }
275 	  if (tptr->down)
276 	    hasmidi = 1;
277 	  tptr = tptr->next;
278 	}
279 
280       while (tempo && (tempo->time <= scorebeats))
281 	{
282 	  timestampconvert(tempo, kcycleidx);
283 	  tempo = tempo->next;
284 	}
285       while (control && (control->time <= scorebeats))
286 	{
287 	  timestampconvert(control, kcycleidx);
288 	  control = control->next;
289 	}
290 
291       while (tmapptr && (tmapptr->time <= scorebeats))
292 	{
293 	  kbase = kcycleidx;
294 	  scorebase = scorebeats;
295 	  if ((fval = (float)atof(tmapptr->val)) < 0.0F)
296 	    printf("Warning: Encode ignoring negative tempo command.\n\n");
297 	  else
298 	    tval = fval;
299 	  scoremult = 1.666667e-02F*ktime*tval;
300 	  tmapptr = tmapptr->next;
301 	}
302       kcycleidx++;
303     }
304 
305   abssasl->compendtime = ((float)kcycleidx/krate);
306 
307   if (has.o_settempo)
308     printf("Warning: Settempo() call ignored by streaming encoding\n\n");
309 
310 }
311 
312 
313 extern void mergerootlist(tnode **, tnode **, tnode **, tnode **,
314 			  tnode **, tnode **);
315 extern void mergelabeltable(sigsym *);
316 
317 /*********************************************************/
318 /*       merge confsasl and sstrsasl into allsasl        */
319 /*********************************************************/
320 
mergescores(void)321 void mergescores(void)
322 
323 {
324   int i;
325   sigsym * sptr;
326 
327   vmcheck(allsasl = calloc(1, sizeof(sasdata)));
328 
329   /* after these calls, confsasl and sstrsasl root/tails are NULL */
330 
331   mergerootlist(&(confsasl->temporoot), &(confsasl->tempotail),
332 		&(sstrsasl->temporoot), &(sstrsasl->tempotail),
333 		&(allsasl->temporoot), &(allsasl->tempotail));
334   mergerootlist(&(confsasl->tableroot), &(confsasl->tabletail),
335 		&(sstrsasl->tableroot), &(sstrsasl->tabletail),
336 		&(allsasl->tableroot), &(allsasl->tabletail));
337   mergerootlist(&(confsasl->controlroot), &(confsasl->controltail),
338 		&(sstrsasl->controlroot), &(sstrsasl->controltail),
339 		&(allsasl->controlroot), &(allsasl->controltail));
340   mergerootlist(&(confsasl->instrroot), &(confsasl->instrtail),
341 		&(sstrsasl->instrroot), &(sstrsasl->instrtail),
342 		&(allsasl->instrroot), &(allsasl->instrtail));
343 
344   /* confsasl/strsasl num's, scoresize, endtime still valid */
345 
346   allsasl->numtempo =  confsasl->numtempo + sstrsasl->numtempo;
347   allsasl->numtable =  confsasl->numtable + sstrsasl->numtable;
348 
349   allsasl->scorefsize = confsasl->scorefsize + sstrsasl->scorefsize;
350 
351   allsasl->endtimeval = confsasl->endtimeval ? confsasl->endtimeval :
352     sstrsasl->endtimeval;
353 
354   if (confsasl->endtimeval && sstrsasl->endtimeval)
355     {
356       if (atof(confsasl->endtimeval) > atof(sstrsasl->endtimeval))
357 	allsasl->endtimeval = confsasl->endtimeval;
358       else
359 	allsasl->endtimeval = sstrsasl->endtimeval;
360     }
361 
362   /* after this section, conf/sstr labeltables are null */
363 
364   allsasl->labeltable = confsasl->labeltable ? confsasl->labeltable :
365     sstrsasl->labeltable;
366 
367   if (confsasl->labeltable && sstrsasl->labeltable)
368     mergelabeltable(sstrsasl->labeltable);
369 
370   if (abssasl->labeltable)
371     {
372       i = 0;
373       sptr = abssasl->labeltable;
374       while (sptr)
375 	{
376 	  i++;
377 	  sptr = sptr->next;
378 	}
379       abssasl->numlabels = i;
380       mergelabeltable(abssasl->labeltable);
381     }
382 
383   abssasl->labeltable = confsasl->labeltable = sstrsasl->labeltable =  NULL;
384 
385   i = 0;
386   sptr = allsasl->labeltable;
387   while (sptr)
388     {
389       sptr->special = i++;
390       sptr = sptr->next;
391     }
392   allsasl->numlabels = i - abssasl->numlabels;
393 
394 
395 }
396 
397 
398 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
399 /*                                                              */
400 /* Top-level functions for printing out score data and score    */
401 /* functions. Called in writepre.c and sfmain.c.                */
402 /*                                                              */
403 /*______________________________________________________________*/
404 
405 /*********************************************************/
406 /*     computes end-time of last SASL note for endtime   */
407 /*********************************************************/
408 
initendsasl(void)409 void initendsasl(void)
410 
411 {
412   float tval;
413   float newtval;
414 
415   if (allsasl->instrtail != NULL)
416     {
417       vmcheck(allsasl->endtimeval = (char *) calloc(1024, sizeof(char)));
418       if (allsasl->instrtail->ttype == S_INSTR)
419 	{
420 	  if (atof(allsasl->instrtail->down->next->next->val)>0)
421 	    sprintf(allsasl->endtimeval,"%1.6e", 2.0F +
422 		    atof(allsasl->instrtail->val) +
423 		    atof(allsasl->instrtail->down->next->next->val));
424 	  else
425 	    sprintf(allsasl->endtimeval,"%1.6e",
426 		    atof(allsasl->instrtail->val)+10.0F);
427 	}
428       else
429 	{
430 	  if (atof(allsasl->instrtail->down->next->
431 		   next->next->next->val) > 0 )
432 	    sprintf(allsasl->endtimeval,"%1.6e", 2.0F +
433 		    atof(allsasl->instrtail->down->next->next->val) +
434 		    atof(allsasl->instrtail->
435 			 down->next->next->next->next->val));
436 	  else
437 	    sprintf(allsasl->endtimeval,"%1.6e", 10.0F +
438 		    atof(allsasl->instrtail->down->next->next->val));
439 	}
440     }
441 
442 
443   if (abssasl->instrtail != NULL)
444     {
445       /* determine worst-case tempo */
446 
447       tval = confmidi->miditicks ? 120.0F : 60.0F;
448       vmcheck(abssasl->endtimeval = (char *) calloc(1024, sizeof(char)));
449       if ((abssasl->tempotail != NULL)||(allsasl->tempotail != NULL))
450 	{
451 	  if (abssasl->tempotail)
452 	    {
453 	      newtval = (float)atof(abssasl->tempotail->down->next->next->val);
454 	      if ((newtval > 0.0F) && (newtval < tval))
455 		tval = newtval;
456 	    }
457 	  if (allsasl->tempotail)
458 	    {
459 	      newtval = (float)atof(allsasl->tempotail->down->next->next->val);
460 	      if ((newtval > 0.0F) && (newtval < tval))
461 		tval = newtval;
462 	    }
463 	}
464 
465       /* apply tempo to duration */
466 
467       if (abssasl->instrtail->ttype == S_INSTR)
468 	{
469 	  if (atof(abssasl->instrtail->down->next->next->val)>0)
470 	    sprintf(abssasl->endtimeval,"%1.6e", 2.0F +
471 		    atof(abssasl->instrtail->val) + (60.0F/tval)*
472 		    atof(abssasl->instrtail->down->next->next->val));
473 	  else
474 	    sprintf(abssasl->endtimeval,"%1.6e",
475 		    atof(abssasl->instrtail->val)+10.0F);
476 	}
477       else
478 	{
479 	  if (atof(abssasl->instrtail->down->next->
480 		   next->next->next->val) > 0 )
481 	    sprintf(abssasl->endtimeval,"%1.6e", 2.0F +
482 		    atof(abssasl->instrtail->down->next->next->val) +
483 		    (60.0F/tval)*atof(abssasl->instrtail->
484 			 down->next->next->next->next->val));
485 	  else
486 	    sprintf(abssasl->endtimeval,"%1.6e", 10.0F +
487 		    atof(abssasl->instrtail->down->next->next->val));
488 	}
489     }
490 
491 }
492 
493 /*********************************************************/
494 /*     declares initialized endtime variable             */
495 /*********************************************************/
496 
initendtime(void)497 void initendtime(void)
498 
499 {
500 
501   sigsym * sptr;
502 
503   /* if absolute or relative endtimeval set, use it */
504   /* if not, come up with an allsasl value */
505 
506   if ((allsasl->endtimeval == NULL) && (abssasl->endtimeval == NULL))
507     {
508       if (cin || session)
509 	fprintf(outfile,"#define CSYS_GIVENENDTIME 0\n\n");
510 
511       /* first, let MIDI streams set it */
512 
513       if (confmidi->miditicks > 0)
514 	{
515 	  vmcheck(allsasl->endtimeval = (char *) calloc(1024, sizeof(char)));
516  	  sprintf(allsasl->endtimeval,"%1.6e",
517 		  ((float)confmidi->midimaxtime/confmidi->miditicks)+2.0F);
518 	}
519       else
520 	{
521 
522 	  /* or else let SASL do it */
523 
524 	  if ((allsasl->instrtail != NULL)||(abssasl->instrtail != NULL))
525 	    initendsasl();
526 	  else
527 	    {
528 	      /* or else use absolute time or a constant */
529 
530 	      if (abssasl->compendtime)
531 		{
532 		  vmcheck(abssasl->endtimeval = (char *) calloc(1024, 1));
533 		  sprintf(abssasl->endtimeval,"%f",abssasl->compendtime
534 			  + 2.0F);
535 		}
536 	      else
537 		{
538 		  vmcheck(allsasl->endtimeval = (char *) calloc(1024, 1));
539 		  sptr = getvsym(&busnametable,"input_bus");
540 		  if ((sptr == NULL) && (!cin) && (!session))
541 		    sprintf(allsasl->endtimeval,"-1.0");
542 		  else
543 		    sprintf(allsasl->endtimeval,"60.0");
544 		}
545 	    }
546 	}
547     }
548   else
549     if (cin || session)
550       fprintf(outfile,"#define CSYS_GIVENENDTIME 1\n\n");
551 
552 
553   fprintf(outfile,"#define MAXENDTIME 1E+37\n\n");
554 
555   if (abssasl->endtimeval)
556     fprintf(outfile,"int endkinit;\n");
557 
558   if (allsasl->endtimeval || abssasl->endtimeval)
559     fprintf(outfile,"float endtime;\n");
560   else
561     internalerror("readscore.c", "initendtime tail");
562 }
563 
564 /*************************************************************/
565 /* initialize endkinit and endtime. prints in engine_init() */
566 /*************************************************************/
567 
initendtimeassign(void)568 void initendtimeassign(void)
569 
570 {
571   if (abssasl->endtimeval)
572     fprintf(outfile,"  EV(endkinit) = %i;\n", 2 + (int)
573 	    (krate*atof(abssasl->endtimeval)));
574 
575   if (allsasl->endtimeval)
576     fprintf(outfile,"  EV(endtime) = %sF;\n",allsasl->endtimeval);
577   else
578     {
579       if (abssasl->endtimeval)
580 	fprintf(outfile,"  EV(endtime) = %fF;\n",
581 		(1.0F/krate)*((2 + (int)(krate*atof(abssasl->endtimeval)))));
582       else
583 	internalerror("readscore.c", "initendtime tail");
584     }
585   fprintf(outfile,"\n");
586 }
587 
588 
589 /*********************************************************/
590 /*       declarations for the score instr variables      */
591 /*********************************************************/
592 
initscoreinstr(int type,sigsym * sptr)593 void initscoreinstr(int type, sigsym * sptr)
594 
595 {
596   int score;
597   char * prefix;
598   char * val;
599 
600   if (type == RELTSTAMP)
601     {
602       if (!( allsasl->instrroot))
603 	return;
604       prefix = "s";
605       score = sptr->score;
606     }
607   else
608     {
609       if (!(abssasl->instrroot))
610 	return;
611       prefix = "sa";
612       score = sptr->ascore;
613     }
614 
615   fprintf(outfile,"instr_line %s_%s[%i];\n",prefix,sptr->val, score);
616 
617   if ((score > 1) || csasl)
618     {
619       val = dupunderscore(sptr->val);
620       fprintf(outfile,"instr_line * %s_%sfirst;\n", prefix, val);
621       fprintf(outfile,"instr_line * %s_%slast;\n", prefix, val);
622       fprintf(outfile,"instr_line * %s_%send;\n\n", prefix,val);
623       free(val);
624     }
625 
626 }
627 
628 /*********************************************************/
629 /*   engine_init() assignments for instr variables      */
630 /*********************************************************/
631 
initscoreinstrassign(int type,sigsym * sptr)632 void initscoreinstrassign(int type, sigsym * sptr)
633 
634 {
635   int i, score;
636   tnode * tptr;
637   char * prefix;
638   char * val;
639 
640   if (type == RELTSTAMP)
641     {
642       if (!(tptr = allsasl->instrroot))
643 	return;
644       prefix = "s";
645       score = sptr->score;
646     }
647   else
648     {
649       if (!(tptr = abssasl->instrroot))
650 	return;
651       prefix = "sa";
652       score = sptr->ascore;
653     }
654 
655   fprintf(outfile,"  memcpy(EV(%s_%s), %s_%s_init, sizeof EV(%s_%s));\n",
656 	  prefix, sptr->val, prefix, sptr->val, prefix, sptr->val);
657 
658   i = -1;
659   while (tptr != NULL)
660     {
661       if (tptr->sptr == sptr)
662 	{
663 	  i++;
664 	}
665       tptr= tptr->next;
666     }
667 
668   if ((score > 1) || csasl)
669     {
670       val = dupunderscore(sptr->val);
671       fprintf(outfile,"  EV(%s_%sfirst) = &EV(%s_%s)[0];\n",
672 	      prefix,val,prefix,sptr->val);
673       fprintf(outfile,"  EV(%s_%slast) = &EV(%s_%s)[0];\n",
674 	      prefix,val,prefix,sptr->val);
675       fprintf(outfile,"  EV(%s_%send) = &EV(%s_%s)[%i];\n\n",
676 	      prefix,val,prefix,sptr->val,i);
677       free(val);
678     }
679 }
680 
681 
682 /*********************************************************/
683 /* declare and init true constant vars for score instrs  */
684 /*********************************************************/
685 
initscoreinstrconstant(int type,sigsym * sptr)686 void initscoreinstrconstant(int type, sigsym * sptr)
687 
688 {
689 
690   int i, j, score;
691   tnode * tptr;
692   tnode * pvalptr;
693   char * prefix;
694   sigsym * label;
695 
696   if (type == RELTSTAMP)
697     {
698       if (!(tptr = allsasl->instrroot))
699 	return;
700       prefix = "s";
701       score = sptr->score;
702     }
703   else
704     {
705       if (!(tptr = abssasl->instrroot))
706 	return;
707       prefix = "sa";
708       score = sptr->ascore;
709     }
710 
711   fprintf(outfile,"instr_line %s_%s_init[%i] = {\n",prefix,sptr->val,
712 	  score);
713 
714   i = -1;
715   while (tptr != NULL)
716     {
717       if (tptr->sptr == sptr)
718 	{
719 	  i++;
720 	  if (i != 0)
721 	    fprintf(outfile,",\n");
722 	  fprintf(outfile,"{");
723 	  tptr->arrayidx = i;
724 
725 	  /* float starttime, float endtime, float startabs, float endabs */
726 
727 	  if (type == RELTSTAMP)
728 	    fprintf(outfile," %sF, MAXENDTIME, MAXENDTIME, MAXENDTIME, ",
729 		    tptr->val);
730 	  else
731 	    fprintf(outfile," MAXENDTIME, MAXENDTIME, %sF, MAXENDTIME, ",
732 		    tptr->val);
733 
734 	  /* float abstime, float time, float itime */
735 
736 	  fprintf(outfile," 0.0F, 0.0F, 0.0F, ");
737 
738 	  /* float sdur */
739 
740 	  if (tptr->down->next->ttype == S_COL)
741 	    {
742 	      fprintf(outfile, "%sF, ",tptr->down->next->next->next->next->val);
743 	      pvalptr = tptr->down->next->next->next->next->next;
744 	      label = getsym(&(allsasl->labeltable), tptr->down);
745 	    }
746 	  else
747 	    {
748 	      fprintf(outfile, " %sF, ",tptr->down->next->next->val);
749 	      pvalptr = tptr->down->next->next->next;
750 	      label = NULL;
751 	    }
752 
753 	  /* int kbirth, int released, int turnoff, int noteon,  */
754 	  /* int notestate, int launch, int numchan, int preset, */
755 	  /* int notenum */
756 
757 	  fprintf(outfile,"0, 0, 0, 1, 0, 0, 0, 0, 0,");
758 
759 	  /* int label */
760 
761 	  if (label)
762 	    fprintf(outfile, " %i,", label->special + 1);
763 	  else
764 	    fprintf(outfile, " 0,");
765 
766 	  /* float p[] */
767 
768 	  fprintf(outfile," {");
769 	  j = numpfields;
770 	  while (j > 0)
771 	    {
772 	      if (pvalptr != NULL)
773 		{
774 		  fprintf(outfile," %sF ",pvalptr->val);
775 		  pvalptr = pvalptr->next;
776 		}
777 	      else
778 		fprintf(outfile," 0.0F ");
779 	      if (!(--j))
780 		fprintf(outfile,"},");
781 	      else
782 		fprintf(outfile,",");
783 	    }
784 
785 
786 	  /* struct ninstr_types * nstate */
787 
788 	  fprintf(outfile," NULL "); /* last 3:*pass*/
789 	  fprintf(outfile,"}");
790 	}
791       tptr= tptr->next;
792     }
793   fprintf(outfile,"};\n\n");
794 
795 }
796 
797 
798 /*********************************************************/
799 /*       declarations for the score control variables    */
800 /*********************************************************/
801 
initscorecontrol(int type)802 void initscorecontrol(int type)
803 
804 {
805   char * prefix;
806   sasdata * sdata;
807   tnode * tptr;
808   tnode * lptr;
809   sigsym * psptr;
810   sigsym * label;
811 
812   if (type == RELTSTAMP)
813     {
814       sdata = allsasl;
815       prefix = "s";
816     }
817   else
818     {
819       sdata = abssasl;
820       prefix = "sa";
821     }
822 
823   sdata->numcontrol = 0;
824   tptr = sdata->controlroot;
825   while (tptr != NULL)
826     {
827       if (tptr->ttype == S_LCONTROL)
828 	{
829 
830 	  label = getsym(&(allsasl->labeltable), tptr->down->next);
831 	  if (label == NULL)
832 	    {
833 	      printf("Error: Unknown score label %s.\n",tptr->down->next->val);
834 	      showbadline(tptr->down);
835 	    }
836 	  lptr = label->defnode;
837 	  while (lptr != NULL)
838 	    {
839 	      psptr = getsym(&(lptr->down->sptr->defnode->sptr),
840 			     tptr->down->next->next->next);
841 	      if ((psptr != NULL) && (psptr->kind == K_IMPORT))
842 		sdata->numcontrol++;
843 	      lptr = lptr->next;
844 	    }
845 	}
846       else
847 	{
848 	  psptr = getsym(&globalsymtable,tptr->down->next->next);
849 	  if ((psptr != NULL) ||
850 	      (!strcmp("MIDIctrl",tptr->down->next->next->val)) ||
851 	      (!strcmp("MIDIbend",tptr->down->next->next->val)) ||
852 	      (!strcmp("MIDItouch",tptr->down->next->next->val)) )
853 	    sdata->numcontrol++;
854 	}
855       tptr = tptr->next;
856     }
857 
858   if (sdata->numcontrol == 0)
859     return;
860 
861   fprintf(outfile, "scontrol_lines %scontrol[%i];\n", prefix, sdata->numcontrol);
862   fprintf(outfile, "scontrol_lines * %scontrolidx;\n", prefix);
863   fprintf(outfile, "scontrol_lines * end%scontrol;\n\n", prefix);
864 }
865 
866 /*********************************************************/
867 /*   content_init() assignments for control variables    */
868 /*********************************************************/
869 
initscorecontrolassign(int type)870 void initscorecontrolassign(int type)
871 
872 {
873   char * prefix;
874   sasdata * sdata;
875   sigsym * sptr;
876   tnode * tptr;
877   tnode * lptr;
878   sigsym * psptr;
879   sigsym * label;
880   int i;
881 
882   if (type == RELTSTAMP)
883     {
884       sdata = allsasl;
885       prefix = "s";
886     }
887   else
888     {
889       sdata = abssasl;
890       prefix = "sa";
891     }
892 
893   if (sdata->numcontrol == 0)
894     return;
895 
896   fprintf(outfile,"  memcpy(EV(%scontrol), %scontrol_init, sizeof EV(%scontrol));\n",
897 	  prefix, prefix, prefix);
898 
899   i = 0;
900   tptr = sdata->controlroot;
901   while (tptr != NULL)
902     {
903       if (tptr->ttype == S_LCONTROL)
904 	{
905 
906 	  label = getsym(&(allsasl->labeltable), tptr->down->next);
907 	  if (label == NULL)
908 	    {
909 	      printf("Error: Unknown score label %s.\n",tptr->down->next->val);
910 	      showbadline(tptr->down);
911 	    }
912 	  lptr = label->defnode;
913 	  while (lptr != NULL)
914 	    {
915 	      sptr = lptr->down->sptr;
916 	      psptr = getsym(&(lptr->down->sptr->defnode->sptr),
917 			     tptr->down->next->next->next);
918 	      if ((psptr != NULL) && (psptr->kind == K_IMPORT))
919 		{
920 		  fprintf(outfile, "  EV(%scontrol)[%i].iline = &EV(%s_%s)[%i];\n",
921 			  prefix, i, prefix, sptr->val,
922 			  lptr->down->arrayidx);
923 		  i++;
924 		}
925 	      lptr = lptr->next;
926 	    }
927 	}
928       else
929 	{
930 	  psptr = getsym(&globalsymtable,tptr->down->next->next);
931 	  if ((psptr != NULL) ||
932 	      (!strcmp("MIDIctrl",tptr->down->next->next->val)) ||
933 	      (!strcmp("MIDIbend",tptr->down->next->next->val)) ||
934 	      (!strcmp("MIDItouch",tptr->down->next->next->val)) )
935 	    i++;
936 	}
937       tptr = tptr->next;
938     }
939 
940   fprintf(outfile, "  EV(%scontrolidx) = &EV(%scontrol)[0];\n", prefix, prefix);
941   fprintf(outfile, "  EV(end%scontrol) = &EV(%scontrol)[%i];\n\n",
942 	  prefix, prefix, sdata->numcontrol-1);
943 }
944 
945 /*********************************************************/
946 /* declare and init true constant vars for score control */
947 /*********************************************************/
948 
initscorecontrolconstant(int type)949 void initscorecontrolconstant(int type)
950 
951 {
952   char * prefix;
953   sasdata * sdata;
954   int i;
955   tnode * tptr;
956   tnode * lptr;
957   sigsym * psptr;
958   sigsym * label;
959 
960   if (type == RELTSTAMP)
961     {
962       sdata = allsasl;
963       prefix = "s";
964     }
965   else
966     {
967       sdata = abssasl;
968       prefix = "sa";
969     }
970 
971   sdata->numcontrol = 0;
972   tptr = sdata->controlroot;
973   while (tptr != NULL)
974     {
975       if (tptr->ttype == S_LCONTROL)
976 	{
977 
978 	  label = getsym(&(allsasl->labeltable), tptr->down->next);
979 	  if (label == NULL)
980 	    {
981 	      printf("Error: Unknown score label %s.\n",tptr->down->next->val);
982 	      showbadline(tptr->down);
983 	    }
984 	  lptr = label->defnode;
985 	  while (lptr != NULL)
986 	    {
987 	      psptr = getsym(&(lptr->down->sptr->defnode->sptr),
988 			     tptr->down->next->next->next);
989 	      if ((psptr != NULL) && (psptr->kind == K_IMPORT))
990 		sdata->numcontrol++;
991 	      lptr = lptr->next;
992 	    }
993 	}
994       else
995 	{
996 	  psptr = getsym(&globalsymtable,tptr->down->next->next);
997 	  if ((psptr != NULL) ||
998 	      (!strcmp("MIDIctrl",tptr->down->next->next->val)) ||
999 	      (!strcmp("MIDIbend",tptr->down->next->next->val)) ||
1000 	      (!strcmp("MIDItouch",tptr->down->next->next->val)) )
1001 	    sdata->numcontrol++;
1002 	}
1003       tptr = tptr->next;
1004     }
1005 
1006   if (sdata->numcontrol == 0)
1007     return;
1008 
1009   fprintf(outfile, "scontrol_lines %scontrol_init[%i] = {\n",
1010 	  prefix, sdata->numcontrol);
1011   i = -1;
1012   tptr = sdata->controlroot;
1013   while (tptr != NULL)
1014     {
1015       if (tptr->ttype == S_LCONTROL)
1016 	{
1017 
1018 	  label = getsym(&(allsasl->labeltable),tptr->down->next);
1019 	  lptr = label->defnode;
1020 	  while (lptr != NULL)
1021 	    {
1022 	      psptr = getsym(&(lptr->down->sptr->defnode->sptr),
1023 			     tptr->down->next->next->next);
1024 	      if ((psptr != NULL) && (psptr->kind == K_IMPORT))
1025 		{
1026 		  i++;
1027 		  if (i != 0)
1028 		    fprintf(outfile,",\n");
1029 		  fprintf(outfile,"{");
1030 		  fprintf(outfile," %sF,", tptr->val);           /* t */
1031 		  fprintf(outfile," %i,", label->special + 1);   /* label */
1032 		  fprintf(outfile," %i, ",lptr->down->arrayidx); /* siptr */
1033 		  fprintf(outfile," NULL, ");                    /* iline */
1034 		  fprintf(outfile,"%s_%s, ",                    /* imptr */
1035 			  lptr->down->sptr->val,psptr->val);
1036 		  fprintf(outfile,"%sF ",                       /* imval */
1037 			  tptr->down->next->next->next->next->val);
1038 		  fprintf(outfile,"}");
1039 		}
1040 	      lptr = lptr->next;
1041 	    }
1042 	}
1043       else
1044 	{
1045 	  psptr = getsym(&globalsymtable,tptr->down->next->next);
1046 	  if ((psptr != NULL) ||
1047 	      (!strcmp("MIDIctrl",tptr->down->next->next->val)) ||
1048 	      (!strcmp("MIDIbend",tptr->down->next->next->val)) ||
1049 	      (!strcmp("MIDItouch",tptr->down->next->next->val)) )
1050 	    {
1051 	      i++;
1052 	      if (i != 0)
1053 		fprintf(outfile,",\n");
1054 	      fprintf(outfile,"{");
1055 	      fprintf(outfile," %sF, 0, -1, NULL,",tptr->val);
1056                                                /* t, label,siptr, iline */
1057 	      if (psptr != NULL)
1058 		fprintf(outfile," GBL_%s, ", psptr->val);        /* imptr */
1059 	      else
1060 		{
1061 		  if (!strcmp("MIDIctrl",tptr->down->next->next->val))
1062 		    fprintf(outfile," %i, ", MIDIFRAMELEN*
1063 			    tptr->down->next->next->down->width +
1064 			    MIDICTRLPOS + tptr->down->next->next->arrayidx);
1065 		  if (!strcmp("MIDIbend",tptr->down->next->next->val))
1066 		    fprintf(outfile," %i, ", MIDIFRAMELEN*
1067 			    tptr->down->next->next->down->width +
1068 			    MIDIBENDPOS);
1069 		  if (!strcmp("MIDItouch",tptr->down->next->next->val))
1070 		    {
1071 		      if (tptr->down->next->next->arrayidx >= 0)
1072 			fprintf(outfile," %i, ", MIDIFRAMELEN*
1073 				tptr->down->next->next->down->width +
1074 			MIDITOUCHPOS + tptr->down->next->next->arrayidx);
1075 		      else
1076 			fprintf(outfile," %i, ", MIDIFRAMELEN*
1077 				tptr->down->next->next->down->width +
1078 				MIDICHTOUCHPOS);
1079 		    }
1080 		}
1081 	      fprintf(outfile," %sF ",                            /* imval */
1082 		      tptr->down->next->next->next->val);
1083 	      fprintf(outfile,"}");
1084 	    }
1085 	}
1086       tptr = tptr->next;
1087     }
1088 
1089   fprintf(outfile,"\n};\n\n");
1090 }
1091 
1092 
1093 /*********************************************************/
1094 /*       declarations for the score tempo variables      */
1095 /*********************************************************/
1096 
initscoretempo(int type)1097 void initscoretempo(int type)
1098 
1099 {
1100   char * prefix;
1101 
1102   if (type == RELTSTAMP)
1103     {
1104       if (!(allsasl->temporoot))
1105 	return;
1106       prefix = "s";
1107     }
1108   else
1109     {
1110       if (!(abssasl->temporoot))
1111 	return;
1112       prefix = "sa";
1113     }
1114 
1115   fprintf(outfile,"int end%stempo;\n", prefix);
1116   fprintf(outfile,"int %stempoidx;\n\n", prefix);
1117 }
1118 
1119 /*********************************************************/
1120 /*   content_init() assignments for the tempo variables  */
1121 /*********************************************************/
1122 
initscoretempoassign(int type)1123 void initscoretempoassign(int type)
1124 
1125 {
1126   char * prefix;
1127   tnode * tptr;
1128   int i;
1129 
1130   if (type == RELTSTAMP)
1131     {
1132       if (!(tptr = allsasl->temporoot))
1133 	return;
1134       prefix = "s";
1135     }
1136   else
1137     {
1138       if (!(tptr = abssasl->temporoot))
1139 	return;
1140       prefix = "sa";
1141     }
1142 
1143   i = 0;
1144   while (tptr != NULL)
1145     {
1146       i++;
1147       tptr = tptr->next;
1148     }
1149 
1150   fprintf(outfile,"  EV(end%stempo) = %i;\n",prefix,i-1);
1151 }
1152 
1153 
1154 /*********************************************************/
1155 /* declare and init "true constant" vars for score tempo */
1156 /*********************************************************/
1157 
initscoretempoconstant(int type)1158 void initscoretempoconstant(int type)
1159 
1160 {
1161   char * prefix;
1162   int i,  numtempo;
1163   tnode * tptr;
1164 
1165 
1166   if (type == RELTSTAMP)
1167     {
1168       if (!(tptr = allsasl->temporoot))
1169 	return;
1170       numtempo = allsasl->numtempo;
1171       prefix = "s";
1172     }
1173   else
1174     {
1175       if (!(tptr = abssasl->temporoot))
1176 	return;
1177       numtempo = abssasl->numtempo;
1178       prefix = "sa";
1179     }
1180 
1181   fprintf(outfile, "stempo_lines %stempo[%i] = {\n", prefix, numtempo + 1);
1182 
1183   i = 0;
1184   while (tptr != NULL)
1185     {
1186       if (i++ != 0)
1187 	fprintf(outfile,",\n");
1188       fprintf(outfile,"{");
1189       fprintf(outfile,"%sF, %sF",tptr->val,tptr->down->next->next->val);
1190       fprintf(outfile,"}");
1191       tptr = tptr->next;
1192     }
1193   fprintf(outfile,"};\n\n");
1194 }
1195 
1196 /*********************************************************/
1197 /*       declarations for the score table variables      */
1198 /*********************************************************/
1199 
initscoretablevars(int type)1200 void initscoretablevars(int type)
1201 
1202 {
1203   char * prefix;
1204 
1205   if (type == RELTSTAMP)
1206     {
1207       if (!(allsasl->tableroot))
1208 	return;
1209       prefix = "s";
1210     }
1211   else
1212     {
1213       if (!(abssasl->tableroot))
1214 	return;
1215       prefix = "sa";
1216     }
1217 
1218   fprintf(outfile,"int end%stable;\n\n", prefix);
1219   fprintf(outfile,"int %stableidx;\n\n", prefix);
1220 }
1221 
1222 /*********************************************************/
1223 /*   content_init() assignments for the table variables  */
1224 /*********************************************************/
1225 
initscoretableassign(int type)1226 void initscoretableassign(int type)
1227 
1228 {
1229   int i;
1230   tnode * tptr;
1231   char * prefix;
1232 
1233   if (type == RELTSTAMP)
1234     {
1235       if (!(tptr = allsasl->tableroot))
1236 	return;
1237       prefix = "s";
1238     }
1239   else
1240     {
1241       if (!(tptr = abssasl->tableroot))
1242 	return;
1243       prefix = "sa";
1244     }
1245 
1246   i = 0;
1247   while (tptr != NULL)
1248     {
1249       i++;
1250       tptr = tptr->next;
1251     }
1252 
1253   fprintf(outfile,"  EV(end%stable) = %i;\n\n",prefix,i-1);
1254 }
1255 
1256 
1257 /*********************************************************/
1258 /* declare and init true constant vars for score tables  */
1259 /*********************************************************/
1260 
initscoretableconstant(int type)1261 void initscoretableconstant(int type)
1262 
1263 {
1264   int i, numtable;
1265   tnode * tptr;
1266   tnode * defnode;
1267   char * prefix;
1268 
1269   if (type == RELTSTAMP)
1270     {
1271       if (!(tptr = allsasl->tableroot))
1272 	return;
1273       numtable = allsasl->numtable;
1274       prefix = "s";
1275     }
1276   else
1277     {
1278       if (!(tptr = abssasl->tableroot))
1279 	return;
1280       numtable = abssasl->numtable;
1281       prefix = "sa";
1282     }
1283 
1284   fprintf(outfile,"stable_lines %stable[%i] = {\n",
1285 	  prefix, numtable+1);
1286 
1287   i = 0;
1288   while (tptr != NULL)
1289     {
1290       if (i != 0)
1291 	fprintf(outfile,",");
1292 
1293       fprintf(outfile,"\n{");
1294 
1295       defnode = tptr->sptr->defnode;
1296 
1297       fprintf(outfile," %sF, TBL_GBL_%s, %i, ",
1298 	      tptr->val, defnode->down->next->val,
1299 	      defnode->usesinput ? defnode->arrayidx : -1);
1300 
1301       if (defnode->usesinput)
1302 	fprintf(outfile,"NULL, &(score_%stdata%i[0])", prefix, i);
1303       else
1304 	fprintf(outfile," score_%stable%i, NULL", prefix, i);
1305 
1306       fprintf(outfile,"}");
1307       i++;
1308       tptr = tptr->next;
1309     }
1310   fprintf(outfile,"};\n\n");
1311 }
1312 
1313 
1314 /*********************************************************/
1315 /*       initializes score table externs             */
1316 /*********************************************************/
1317 
initscoretableexterns(int type)1318 void initscoretableexterns(int type)
1319 
1320 {
1321   int i, numtable;
1322   tnode * tptr;
1323   char * prefix;
1324 
1325   if (type == RELTSTAMP)
1326     {
1327       if (!(tptr = allsasl->tableroot))
1328 	return;
1329       numtable = allsasl->numtable;
1330       prefix = "s";
1331     }
1332   else
1333     {
1334       if (!(tptr = abssasl->tableroot))
1335 	return;
1336       numtable = abssasl->numtable;
1337       prefix = "sa";
1338     }
1339 
1340   i = 0;
1341   while (i < numtable)
1342     {
1343       fprintf(outfile, "extern void score_%stable%i(ENGINE_PTR_TYPE);\n", prefix,i);
1344       fprintf(outfile, "extern %s score_%stdata%i[];\n",
1345 	      hexstrings ? "char" : "float", prefix, i);
1346       fprintf(outfile, "\n");
1347       i++;
1348     }
1349   fprintf(outfile, "\n");
1350 }
1351 
1352 
1353 /*********************************************************/
1354 /* prints functions to initialize SASL tables: sfmain.c  */
1355 /*********************************************************/
1356 
printtablefunctions(void)1357 void printtablefunctions(void)
1358 
1359 {
1360   int i;
1361   tnode * tptr;
1362   char name[STRSIZE];
1363 
1364   currinputwidth = 1;
1365   currinstrwidth = 1;
1366   currinstancename = "GBL";
1367   curropcodeprefix  = "GBL";
1368   currinstrument = NULL;
1369   currinstance = NULL;
1370   curropcodestack = NULL;
1371   redefglobal();
1372 
1373   tptr = allsasl->tableroot;
1374   i = -1;
1375   while (tptr != NULL)
1376     {
1377       i++;
1378       if (tptr->sptr->defnode->usesinput)
1379 	{
1380 	  sprintf(name, "score_stdata%i",i);
1381 	  printtablestring(tptr->sptr, name);
1382 	}
1383       else
1384 	{
1385 	  fprintf(outfile,"\n\nvoid score_stable%i(ENGINE_PTR_DECLARE)\n{\n\n",i);
1386 	  if (wavegeneratorname(tptr->down->next->next->next))
1387 	    {
1388 	      wavegeneratorvar(tptr->sptr);
1389 	      fprintf(outfile,"   int i,j;\n\n");
1390 	      createtable(tptr->sptr, "TBL_GBL", S_SASLFILE);
1391 	    }
1392 	  fprintf(outfile,"}\n\n");
1393 	}
1394       tptr = tptr->next;
1395     }
1396 
1397 
1398   tptr = abssasl->tableroot;
1399   i = -1;
1400   while (tptr != NULL)
1401     {
1402       i++;
1403       if (tptr->sptr->defnode->usesinput)
1404 	{
1405 	  sprintf(name, "score_satdata%i",i);
1406 	  printtablestring(tptr->sptr, name);
1407 	}
1408       else
1409 	{
1410 	  fprintf(outfile,"\n\nvoid score_satable%i(ENGINE_PTR_DECLARE)\n{\n\n",i);
1411 	  if (wavegeneratorname(tptr->down->next->next->next))
1412 	    {
1413 	      wavegeneratorvar(tptr->sptr);
1414 	      fprintf(outfile,"   int i,j;\n\n");
1415 	      createtable(tptr->sptr, "TBL_GBL", S_SASLFILE);
1416 	    }
1417 	  fprintf(outfile,"}\n\n");
1418 	}
1419       tptr = tptr->next;
1420     }
1421 
1422   redefnormal();
1423 }
1424 
1425 
1426 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1427 /*                                                              */
1428 /* Second-level functions for reading score data. Note that     */
1429 /* parsetempo() and parsecontrol() also called by readmidi.c    */
1430 /*                                                              */
1431 /*______________________________________________________________*/
1432 
1433 
1434 /*********************************************************/
1435 /*          lexical analyzer for score files             */
1436 /*********************************************************/
1437 
scorelex(int scotype)1438 tnode * scorelex (int scotype)
1439 
1440 {
1441   FILE * sfile = NULL;
1442   int c,i,foundit, hashmark;
1443   char buf[LEXBUFSIZE] = {'\0'};
1444   tnode * scorelval;
1445 
1446   switch (scotype) {
1447   case BCONFSCORE:
1448     return binconflex();
1449     break;
1450   case FCONFSCORE:
1451     sfile = saslfile;
1452     break;
1453   case BSSTRSCORE:
1454     return binsstrlex();
1455     break;
1456   case FSSTRSCORE:
1457     sfile = sstrfile;
1458     break;
1459   default:
1460     internalerror("readscore.c", "scorelex() switch");
1461   }
1462 
1463   scorelval = make_tnode("", S_BADCHAR);
1464 
1465   /* delete whitespace, hash-defines, and comments */
1466 
1467   foundit = 0;
1468   while (!foundit)
1469     {
1470       while ((isspace(c = getc(sfile)))&&(c != '\n'));
1471       if ((c != '#') && (c != '/'))
1472 	foundit = 1;
1473       else
1474 	{
1475 	  hashmark = (c == '#');
1476 	  c = getc(sfile);
1477 	  if ((hashmark == 0) && (c != '/'))
1478 	    {
1479 	      ungetc(c,sfile);
1480 	      buf[0]='/'; buf[1]='\0';
1481 	      scorelval->val =  dupval(buf);
1482 	      scorelval->ttype = S_BADCHAR;
1483 	      return scorelval;
1484 	    }
1485 	  else
1486 	    {
1487 	      while ((c != '\n') && (c != EOF))
1488 		c = getc(sfile);
1489 	      if (c == EOF)
1490 		foundit = 1;
1491 	    }
1492 	}
1493     }
1494 
1495   /* string constant */
1496 
1497   if (c == '"')
1498     {
1499       i=0; c = getc(sfile);
1500       while (c != EOF)
1501 	if (c != '"')
1502 	  {
1503 	    if (i < LEXBUFSIZE)
1504 	      buf[i++]=(char)c;
1505 	    c = getc(sfile);
1506 	  }
1507 	else
1508 	  {
1509 	    if ((i!=0)&&buf[i-1]=='\\')
1510 	      {
1511 		buf[i-1]= '"';
1512 		c = getc(sfile);
1513 	      }
1514 	    else
1515 	      {
1516 		if (i < LEXBUFSIZE)
1517 		  {
1518 		    buf[i]='\0';
1519 		    scorelval->ttype = S_STRCONST;
1520 		  }
1521 		else
1522 		  {
1523 		    /* string overflows buffer -- keep S_BADCHAR */
1524 
1525 		    buf[LEXBUFSIZE - 1]= '\0';
1526 		  }
1527 
1528 		scorelval->val =  dupval(buf);
1529 		return scorelval;
1530 	      }
1531 	  }
1532 
1533       /* unterminated string constant fills file  -- keep S_BADCHAR */
1534 
1535       if (i < LEXBUFSIZE)
1536 	buf[i]= '\0';
1537       else
1538 	buf[LEXBUFSIZE - 1]= '\0';
1539 
1540       scorelval->val =  dupval(buf);
1541       return scorelval;
1542     }
1543 
1544   /* parse integers and numbers */
1545 
1546   i = 0;
1547   if (c == '-')
1548     {
1549       buf[i]= '-'; i++;                           /* can't overflow */
1550       c = getc(sfile);
1551       if (!(isdigit(c)||(c == '.')))
1552 	{
1553 	  ungetc(c,sfile);
1554 	  buf[i]='\0';                            /* can't overflow */
1555 	  scorelval->val =  dupval(buf);
1556 	  scorelval->ttype = S_BADNUMBER;
1557 	  return scorelval;
1558 	}
1559     }
1560   if (isdigit(c)||(c == '.'))
1561     {
1562       if (c == '.')
1563 	{
1564 	  buf[i]= '0'; i++;                       /* can't overflow */
1565 	  c = getc(sfile);
1566 	  if (!isdigit(c))
1567 	    {
1568 	      ungetc(c,sfile);
1569 	      buf[i]='\0';
1570 	      scorelval->val =  dupval(buf);
1571 	      scorelval->ttype = S_BADNUMBER;
1572 	      return scorelval;
1573 	    }
1574 	  else
1575 	    {
1576 	      ungetc(c,sfile);
1577 	      c = '.';
1578 	    }
1579 	}
1580       else
1581 	{
1582 	  while (isdigit(c))
1583 	    {
1584 	      if (i < LEXBUFSIZE)
1585 		buf[i++]=(char)c;
1586 	      c = getc(sfile);
1587 	    }
1588 	  if ((c != 'e') && (c != '.'))      /* an integer, convert to number */
1589 	    {
1590 	      ungetc(c,sfile);
1591 	      if (i + 2 < LEXBUFSIZE)
1592 		{
1593 		  buf[i]='.'; i++;
1594 		  buf[i]='0'; i++;
1595 		  buf[i]='\0';
1596 		  scorelval->ttype = S_NUMBER;
1597 		}
1598 	      else
1599 		{
1600 		  buf[(i < LEXBUFSIZE) ? i : LEXBUFSIZE - 1] = '\0';
1601 		  scorelval->ttype = S_BADNUMBER;
1602 		}
1603 	      scorelval->val =  dupval(buf);
1604 	      return scorelval;
1605 	    }
1606 	}
1607       if (c == '.')
1608 	{
1609 	  if (i < LEXBUFSIZE)
1610 	    buf[i++]=(char)c;
1611 	  c = getc(sfile);
1612 	  if (!isdigit(c))
1613 	    {
1614 	      if (i < LEXBUFSIZE)
1615 		buf[i++]= '0';
1616 	    }
1617 	  else
1618 	    {
1619 	      while (isdigit(c))
1620 		{
1621 		  if (i < LEXBUFSIZE)
1622 		    buf[i++]=(char)c;
1623 		  c = getc(sfile);
1624 		}
1625 	    }
1626 	}
1627       if (c != 'e')
1628 	{
1629 	  ungetc(c,sfile);
1630 	  if (i < LEXBUFSIZE)
1631 	    {
1632 	      buf[i]='\0';
1633 	      scorelval->ttype = S_NUMBER;
1634 	    }
1635 	  else
1636 	    {
1637 	      buf[LEXBUFSIZE - 1]= '\0';
1638 	      scorelval->ttype = S_BADNUMBER;
1639 	    }
1640 	  scorelval->val =  dupval(buf);
1641 	  return scorelval;
1642 	}
1643       else
1644 	{
1645 	  if (i < LEXBUFSIZE)
1646 	    buf[i++]=(char)c;
1647 	  c = getc(sfile);
1648 	  if ((c=='+')||(c=='-'))
1649 	    {
1650 	      if (i < LEXBUFSIZE)
1651 		buf[i++]=(char)c;
1652 	      c = getc(sfile);
1653 	    }
1654 	  if (isdigit(c))
1655 	    {
1656 	      while (isdigit(c))
1657 		{
1658 		  if (i < LEXBUFSIZE)
1659 		    buf[i++]=(char)c;
1660 		  c = getc(sfile);
1661 		}
1662 	      ungetc(c,sfile);
1663 
1664 	      if (i < LEXBUFSIZE)
1665 		{
1666 		  buf[i]='\0';
1667 		  scorelval->ttype = S_NUMBER;
1668 		}
1669 	      else
1670 		{
1671 		  buf[LEXBUFSIZE - 1]= '\0';
1672 		  scorelval->ttype = S_BADNUMBER;
1673 		}
1674 
1675 	      scorelval->val =  dupval(buf);
1676 	      return scorelval;
1677 	    }
1678 	  else
1679 	    {
1680 	      ungetc(c,sfile);
1681 	      buf[i < LEXBUFSIZE ? i : LEXBUFSIZE - 1]='\0';
1682 	      scorelval->val =  dupval(buf);
1683 	      scorelval->ttype = S_BADNUMBER;
1684 	      return scorelval;
1685 	    }
1686 	}
1687     }
1688 
1689   if ((isalpha(c))||(c == '_'))    /* keywords and identifiers */
1690     {
1691 
1692       i = 0;
1693       while (((isalnum(c)) || (c == '_')))
1694 	{
1695 	  if (i < LEXBUFSIZE - 1)   /* only first 16 chars matter in spec */
1696 	    buf[i++] = (char)c;
1697 	  c = getc(sfile);
1698 	}
1699       buf[i] = '\0';
1700       ungetc(c,sfile);
1701       scorelval->val = dupval(buf);
1702 
1703       if (!strcmp(buf,"control"))
1704 	{
1705 	  scorelval->ttype = S_CONTROL;
1706 	  return scorelval;
1707 	}
1708 
1709       if (!strcmp(buf,"tempo"))
1710 	{
1711 	  scorelval->ttype = S_TEMPO;
1712 	  return scorelval;
1713 	}
1714 
1715       if (!strcmp(buf,"table"))
1716 	{
1717 	  scorelval->ttype = S_TABLE;
1718 	  return scorelval;
1719 	}
1720 
1721       if (!strcmp(buf,"end"))
1722 	{
1723 	  scorelval->ttype = S_END;
1724 	  return scorelval;
1725 	}
1726 
1727       scorelval->ttype = S_IDENT;
1728       return scorelval;
1729     }
1730 
1731 
1732   buf[0]=(char)c;
1733   buf[1]='\0';
1734   scorelval->val = dupval(buf);
1735   scorelval->ttype = c;
1736 
1737   switch (c) {
1738 
1739   case '\n':
1740     scorelval->ttype = S_NEWLINE;
1741     return scorelval;
1742   case EOF:
1743     scorelval->ttype = S_EOF;
1744     return scorelval;
1745   case ':':
1746     scorelval->ttype = S_COL;
1747     return scorelval;
1748   case '*':
1749     scorelval->ttype = S_STAR;
1750     return scorelval;
1751   }
1752 
1753   scorelval->ttype = S_BADCHAR;
1754   return scorelval;
1755 
1756 }
1757 
1758 /*********************************************************/
1759 /*          parse function for SASL end statement        */
1760 /*********************************************************/
1761 
parseend(sasdata * sdata,tnode * nsl)1762 int parseend(sasdata * sdata, tnode * nsl)
1763 
1764 {
1765 
1766   if ( ((nsl->ttype == S_NUMBER) ||
1767 	(nsl->ttype == S_INTGR))     &&
1768        (nsl->next->ttype == S_END) )
1769     {
1770       if (sdata->endtimeval == NULL)
1771 	sdata->endtimeval =  dupval(nsl->val);
1772       else
1773 	{
1774 	  if (atof(nsl->val) <  atof(sdata->endtimeval))
1775 	    sdata->endtimeval = dupval(nsl->val);
1776 	}
1777     }
1778   else
1779     badline(nsl);
1780   return 1;
1781 }
1782 
1783 
1784 extern void mergenodes(tnode **, tnode *);
1785 
1786 /*********************************************************/
1787 /*          parse function for SASL tempo statement      */
1788 /*********************************************************/
1789 
parsetempo(sasdata * sdata,tnode * nsl,int hpe)1790 int parsetempo(sasdata * sdata, tnode * nsl, int hpe)
1791 
1792 {
1793 
1794   tnode * newtempo;
1795   int ret = 0;
1796 
1797   if ( ((nsl->ttype == S_NUMBER) ||
1798 	(nsl->ttype == S_INTGR))     &&
1799        (nsl->next->ttype == S_TEMPO) &&
1800        ((nsl->next->next->ttype == S_NUMBER) ||
1801 	(nsl->next->next->ttype == S_INTGR)) )
1802     {
1803       sdata->numtempo++;
1804       newtempo = make_tnode(nsl->val, S_TEMPO);
1805       newtempo->down = nsl;
1806       newtempo->special = hpe;
1807       newtempo->time = (float) atof(nsl->val);
1808       if (sdata->temporoot == NULL)
1809 	{
1810 	  sdata->temporoot = sdata->tempotail = newtempo;
1811 	}
1812       else
1813 	{
1814 	  if (newtempo->time >= sdata->tempotail->time)
1815 	    {
1816 	      sdata->tempotail->next = newtempo;
1817 	      sdata->tempotail = newtempo;
1818 	    }
1819 	  else
1820 	    {
1821 	      mergenodes(&(sdata->temporoot),newtempo);
1822 	    }
1823 	}
1824       ret = 1;
1825     }
1826   return ret;
1827 }
1828 
1829 
1830 extern void tablepfieldcheck(tnode *);
1831 extern void scoreaddsymtable(tnode *);
1832 
1833 /*********************************************************/
1834 /*          parse function for SASL table statement      */
1835 /*********************************************************/
1836 
parsetable(sasdata * sdata,tnode * nsl,int tcount,int hpe)1837 int parsetable(sasdata * sdata, tnode * nsl, int tcount, int hpe)
1838 
1839 {
1840   tnode * newtable;
1841   tnode * tptr;
1842   tnode * pptr;
1843   tnode * wgen;
1844   tnode * sizeptr;
1845   int flag = 1;
1846 
1847   if (((nsl->ttype == S_NUMBER) || (nsl->ttype == S_INTGR)) &&
1848       (nsl->next->ttype == S_TABLE) &&
1849       (nsl->next->next->ttype == S_IDENT) &&
1850       (nsl->next->next->next->ttype == S_IDENT) &&
1851       ((flag = (getvsym(&globalsymtable, nsl->next->next->val) != NULL))))
1852     {
1853       sdata->numtable++;
1854       newtable = make_tnode(nsl->val, S_TABLE);
1855       addvsym(&newtable->sptr,nsl->next->next->val, K_NORMAL);
1856       newtable->sptr->defnode = make_tnode("<table>", S_TABLE);
1857       newtable->sptr->defnode->vol = CONSTANT;
1858       tptr = newtable->sptr->defnode->down = make_tnode("TABLE", S_TABLE);
1859       tptr->next = make_tnode(nsl->next->next->val, S_IDENT);
1860       tptr = tptr->next;
1861       tptr->next = make_tnode("(", S_LP);
1862       tptr = tptr->next;
1863       tptr->next = make_tnode(nsl->next->next->next->val, S_IDENT);
1864       wgen = tptr = tptr->next;
1865 
1866       if (!wavegeneratorname(wgen))
1867 	{
1868 	  printf("Error: Invalid generator name %s.\n\n",tptr->val);
1869 	  showbadline(nsl);
1870 	}
1871       tablepfieldcheck(nsl);
1872 
1873       tptr->next = make_tnode(",", S_COM);
1874       tptr = tptr->next;
1875       tptr->next = make_tnode("<exprstrlist>", S_EXPRSTRLIST);
1876       tptr->next->next = make_tnode(")", S_RP);
1877       pptr = nsl->next->next->next->next;
1878       sizeptr = tptr->next->down = make_tnode("<expr>", S_EXPR);
1879       tptr = tptr->next->down;
1880 
1881       while (pptr != NULL)
1882 	{
1883 	  tptr->down = make_tnode(dupval(pptr->val), pptr->ttype);
1884 	  tptr->rate = tptr->down->rate = IRATETYPE;
1885 	  tptr->vol = tptr->down->vol = CONSTANT;
1886 	  tptr->width = tptr->down->width = 1;
1887 	  if (pptr->ttype == S_IDENT)
1888 	    {
1889 	      tptr->vartype = tptr->down->vartype = TABLETYPE;
1890 	      tptr->down->sptr = pptr->sptr;
1891 	    }
1892 	  else
1893 	    tptr->vartype = tptr->down->vartype = SCALARTYPE;
1894 	  tptr->res = tptr->down->res;
1895 	  if (pptr->next)
1896 	    {
1897 	      tptr->next = make_tnode(",", S_COM);
1898 	      tptr = tptr->next;
1899 	      if (pptr->next->ttype == S_STRCONST)
1900 		{
1901 		  tptr->next = make_tnode(dupval(pptr->next->val), S_STRCONST);
1902 		  pptr = pptr->next;
1903 		  tptr = tptr->next;
1904 		  if (pptr->next)
1905 		    {
1906 		      tptr->next = make_tnode(",", S_COM);
1907 		      tptr = tptr->next;
1908 		      tptr->next = make_tnode("<expr>", S_EXPR);
1909 		    }
1910 		}
1911 	      else
1912 		tptr->next = make_tnode("<expr>", S_EXPR);
1913 	      tptr = tptr->next;
1914 	    }
1915 	  pptr = pptr->next;
1916 	}
1917 
1918       newtable->sptr->consval = (char *)
1919 	wavereduceconstants(newtable->sptr->defnode, nsl);
1920 
1921       if (newtable->sptr->defnode->usesinput == 0)
1922 	haswavegenerator(wgen);
1923 
1924       newtable->down = nsl;
1925       newtable->special = hpe;
1926       newtable->width = tcount - 4;
1927       newtable->time = (float) atof(nsl->val);
1928       if (sdata->tableroot == NULL)
1929 	{
1930 	  sdata->tableroot = sdata->tabletail = newtable;
1931 	}
1932       else
1933 	{
1934 	  if (newtable->time >= sdata->tabletail->time)
1935 	    {
1936 	      sdata->tabletail->next = newtable;
1937 	      sdata->tabletail = newtable;
1938 	    }
1939 	  else
1940 	    {
1941 	      mergenodes(&(sdata->tableroot),newtable);
1942 	    }
1943 	}
1944       if (boutfile)
1945 	{
1946 	  scoreaddsymtable(nsl->next->next);
1947 	  scoreaddsymtable(nsl->next->next->next);
1948 	}
1949     }
1950   else
1951     {
1952       if (flag)
1953 	badline(nsl);
1954     }
1955   return 1;
1956 }
1957 
1958 /*********************************************************/
1959 /*          parse function for SASL control statement    */
1960 /*********************************************************/
1961 
parsecontrol(sasdata * sdata,tnode * nsl,int hpe)1962 int parsecontrol(sasdata * sdata, tnode * nsl, int hpe)
1963 
1964 {
1965   tnode * newcontrol;
1966 
1967   if ( ((nsl->ttype == S_NUMBER) ||
1968 	(nsl->ttype == S_INTGR))     &&
1969        (nsl->next->next->ttype == S_IDENT) &&
1970        ((nsl->next->next->next->ttype == S_NUMBER) ||
1971 	(nsl->next->next->next->ttype == S_INTGR)) )
1972     {
1973       newcontrol = make_tnode(nsl->val, S_CONTROL);
1974       newcontrol->down = nsl;
1975       newcontrol->special = hpe;
1976       newcontrol->time = (float) atof(nsl->val);
1977       if (sdata->controlroot == NULL)
1978 	{
1979 	  sdata->controlroot = sdata->controltail = newcontrol;
1980 	}
1981       else
1982 	{
1983 	  if (newcontrol->time >= sdata->controltail->time)
1984 	    {
1985 	      sdata->controltail->next = newcontrol;
1986 	      sdata->controltail = newcontrol;
1987 	    }
1988 	  else
1989 	    {
1990 	      mergenodes(&(sdata->controlroot),newcontrol);
1991 	    }
1992 	}
1993       if (boutfile)
1994 	scoreaddsymtable(nsl->next->next);
1995     }
1996   else
1997     badline(nsl);
1998   return 1;
1999 
2000 }
2001 
2002 /*********************************************************/
2003 /*          parse function for SASL control statement    */
2004 /*********************************************************/
2005 
parselcontrol(sasdata * sdata,tnode * nsl,int hpe)2006 int parselcontrol(sasdata * sdata, tnode * nsl, int hpe)
2007 
2008 {
2009   tnode * newcontrol;
2010 
2011   if ( ((nsl->ttype == S_NUMBER) ||
2012 	(nsl->ttype == S_INTGR))     &&
2013        (nsl->next->ttype == S_IDENT) &&
2014        (nsl->next->next->next->ttype == S_IDENT) &&
2015        ((nsl->next->next->next->next->ttype == S_NUMBER) ||
2016 	(nsl->next->next->next->next->ttype == S_INTGR)) )
2017     {
2018       newcontrol = make_tnode(nsl->val, S_LCONTROL);
2019       newcontrol->down = nsl;
2020       newcontrol->special = hpe;
2021       newcontrol->time = (float) atof(nsl->val);
2022       if (sdata->controlroot == NULL)
2023 	{
2024 	  sdata->controlroot = sdata->controltail = newcontrol;
2025 	}
2026       else
2027 	{
2028 	  if (newcontrol->time >= sdata->controltail->time)
2029 	    {
2030 	      sdata->controltail->next = newcontrol;
2031 	      sdata->controltail = newcontrol;
2032 	    }
2033 	  else
2034 	    {
2035 	      mergenodes(&(sdata->controlroot),newcontrol);
2036 	    }
2037 	}
2038       if (boutfile)
2039 	{
2040 	  scoreaddsymtable(nsl->next);
2041 	  scoreaddsymtable(nsl->next->next->next);
2042 	}
2043     }
2044   else
2045     badline(nsl);
2046   return 1;
2047 }
2048 
2049 
2050 extern void instrpfieldcheck(tnode *, tnode *);
2051 
2052 /*********************************************************/
2053 /*          parse function for SASL instr statement      */
2054 /*********************************************************/
2055 
parselinstr(sasdata * sdata,tnode * nsl,int tcount,int hpe)2056 int parselinstr(sasdata * sdata, tnode * nsl, int tcount, int hpe)
2057 
2058 {
2059 
2060   tnode * newinstr;
2061   sigsym * label;
2062   tnode * lptr;
2063 
2064   if ( (nsl->ttype == S_IDENT) &&
2065        (nsl->next->ttype == S_COL) &&
2066        ((nsl->next->next->ttype == S_NUMBER) ||
2067 	(nsl->next->next->ttype == S_INTGR))  &&
2068        (nsl->next->next->next->ttype == S_IDENT) &&
2069        ((nsl->next->next->next->next->ttype == S_NUMBER) ||
2070 	(nsl->next->next->next->next->ttype == S_INTGR)))
2071     {
2072 
2073       newinstr = make_tnode(nsl->next->next->val, S_LINSTR);
2074       newinstr->width = tcount - 5; /* num pfields */
2075       newinstr->special = hpe;
2076       newinstr->down = nsl;
2077       newinstr->time = (float) atof(newinstr->val);
2078       addvsym(&(sdata->labeltable), nsl->val, S_LINSTR);
2079       label = getsym(&(sdata->labeltable), nsl);
2080       lptr = make_tnode(nsl->next->next->next->val, S_INSTR);
2081       lptr->down = newinstr;
2082       if (label->defnode == NULL)
2083 	label->defnode = lptr;
2084       else
2085 	{
2086 	  lptr->next = label->defnode;
2087 	  label->defnode = lptr;
2088 	}
2089       newinstr->sptr = getsym(&instrnametable,nsl->next->next->next);
2090       if (newinstr->sptr == NULL)
2091 	{
2092 	  printf("Error: Instr %s, used in -sco, not in -orc.\n",
2093 		 nsl->next->next->next->val);
2094 	  showbadline(nsl);
2095 	}
2096       instrpfieldcheck(nsl, nsl->next->next->next->next->next);
2097       if (nsl->next->next->opwidth)
2098 	newinstr->sptr->ascore++;
2099       else
2100 	newinstr->sptr->score++;
2101       if (sdata->instrroot == NULL)
2102 	{
2103 	  sdata->instrroot = sdata->instrtail = newinstr;
2104 	}
2105       else
2106 	{
2107 	  if (newinstr->time >= sdata->instrtail->time)
2108 	    {
2109 	      sdata->instrtail->next = newinstr;
2110 	      sdata->instrtail = newinstr;
2111 	    }
2112 	  else
2113 	    {
2114 	      mergenodes(&(sdata->instrroot), newinstr);
2115 	    }
2116 	}
2117       if (boutfile)
2118 	{
2119 	  scoreaddsymtable(nsl);
2120 	  scoreaddsymtable(nsl->next->next->next);
2121 	}
2122       return 1;
2123     }
2124   return 0;
2125 }
2126 
2127 /*********************************************************/
2128 /*          parse function for SASL instr statement      */
2129 /*********************************************************/
2130 
parseinstr(sasdata * sdata,tnode * nsl,int tcount,int hpe)2131 int parseinstr(sasdata * sdata, tnode * nsl, int tcount, int hpe)
2132 
2133 {
2134 
2135   tnode * newinstr;
2136 
2137   if ( ((nsl->ttype == S_NUMBER) ||
2138 	(nsl->ttype == S_INTGR))  &&
2139        (nsl->next->ttype == S_IDENT) &&
2140        ((nsl->next->next->ttype == S_NUMBER) ||
2141 	(nsl->next->next->ttype == S_INTGR)))
2142     {
2143       newinstr = make_tnode(nsl->val, S_INSTR);
2144       newinstr->width = tcount - 3; /* num pfields */
2145       newinstr->special = hpe;
2146       newinstr->down = nsl;
2147       newinstr->time = (float) atof(nsl->val);
2148       newinstr->sptr = getsym(&instrnametable,nsl->next);
2149       if (newinstr->sptr == NULL)
2150 	{
2151 	  printf("Error: Instr %s, used in -sco, not in -orc.\n",
2152 		 nsl->next->val);
2153 	  showbadline(nsl);
2154 	}
2155       instrpfieldcheck(nsl, nsl->next->next->next);
2156       if (nsl->opwidth)
2157 	newinstr->sptr->ascore++;
2158       else
2159 	newinstr->sptr->score++;
2160       if (sdata->instrroot == NULL)
2161 	{
2162 	  sdata->instrroot = sdata->instrtail = newinstr;
2163 	}
2164       else
2165 	{
2166 	  if (newinstr->time >= sdata->instrtail->time)
2167 	    {
2168 	      sdata->instrtail->next = newinstr;
2169 	      sdata->instrtail = newinstr;
2170 	    }
2171 	  else
2172 	    {
2173 	      mergenodes(&(sdata->instrroot), newinstr);
2174 	    }
2175 	}
2176       if (boutfile)
2177 	scoreaddsymtable(nsl->next);
2178       return 1;
2179     }
2180   return 0;
2181 }
2182 
2183 /*********************************************************/
2184 /*          shows bad SASL line, closes sfront           */
2185 /*********************************************************/
2186 
showbadline(tnode * line)2187 void showbadline(tnode * line)
2188 
2189 
2190 {
2191 
2192   printf("Offending line from -sco file:\n\n");
2193   while (line != NULL)
2194     {
2195       printf(" %s ",line->val);
2196       line = line->next;
2197     }
2198   printf("\n");
2199   if (bitfile)
2200     {
2201       printf("Error originates in score_file SA block of -bit file.\n");
2202       printf("Use -scoout and -orcout to generate ASCII files and\n");
2203       printf("run sfront on these files to pinpoint error.\n");
2204     }
2205   else
2206     {
2207       if (cppsaol)
2208 	{
2209 	  printf("If this line not in your main -sco file, look at\n");
2210 	  printf("files you may have included via pre-processing.\n");
2211 	}
2212     }
2213   noerrorplace();
2214 
2215 }
2216 
2217 /*********************************************************/
2218 /*          generic error function for SASL              */
2219 /*********************************************************/
2220 
badline(tnode * line)2221 void badline(tnode * line)
2222 
2223 
2224 {
2225    printf("Error: SASL Syntax error: \n\n");
2226    showbadline(line);
2227 }
2228 
2229 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2230 /*                                                              */
2231 /*   Second-level functions for intermediate score processing   */
2232 /*                                                              */
2233 /*______________________________________________________________*/
2234 
2235 extern void addtempomap(tnode **, tnode *);
2236 
2237 /*********************************************************/
2238 /*    makes a global tempo map for renumbering           */
2239 /*********************************************************/
2240 
maketempomap(void)2241 tnode * maketempomap(void)
2242 
2243 {
2244   tnode * ret, * tptr;
2245   tnode * ctempo, * stempo, * atempo;
2246   int state;
2247 
2248   /* tempos from SASL and MIDI in the configuration block */
2249 
2250   ctempo = confsasl->temporoot;
2251 
2252   /* tempos from has_time = 1 in SASL */
2253 
2254   stempo = sstrsasl->temporoot;
2255 
2256   /* tempos generated from mstrfile read, in relative form */
2257 
2258   atempo = abssasl->temporoot;
2259 
2260   /* default tempo */
2261 
2262   if (mstrfile)
2263     tptr = ret = make_tnode("120.0", S_TEMPO);
2264   else
2265     tptr = ret = make_tnode("60.0", S_TEMPO);
2266 
2267   ret->time = 0.0;
2268 
2269   while (ctempo || stempo || atempo)
2270     {
2271       state = (ctempo != NULL) + 2*(stempo != NULL) + 4*(atempo != NULL);
2272       switch(state) {
2273       case 1:  /* ctempo only */
2274 	addtempomap(&ctempo, tptr);
2275 	break;
2276       case 2:  /* stempo only */
2277 	addtempomap(&stempo, tptr);
2278 	break;
2279       case 3:  /* stempo and ctempo */
2280 	if (stempo->time < ctempo->time)
2281 	  addtempomap(&stempo, tptr);
2282 	else
2283 	  addtempomap(&ctempo, tptr);
2284 	break;
2285       case 4:  /* atempo only */
2286 	addtempomap(&atempo, tptr);
2287 	break;
2288       case 5:  /* atempo and ctempo */
2289 	if (atempo->time < ctempo->time)
2290 	  addtempomap(&atempo, tptr);
2291 	else
2292 	  addtempomap(&ctempo, tptr);
2293 	break;
2294       case 6:  /* atempo and stempo */
2295 	if (stempo->time < atempo->time)
2296 	  addtempomap(&stempo, tptr);
2297 	else
2298 	  addtempomap(&atempo, tptr);
2299 	break;
2300       case 7:  /* atempo and stempo and ctempo */
2301 	if ((stempo->time <= atempo->time) &&
2302 	    (stempo->time <= ctempo->time))
2303 	  addtempomap(&stempo, tptr);
2304 	else
2305 	  {
2306 	    if (atempo->time < ctempo->time)
2307 	      addtempomap(&atempo, tptr);
2308 	    else
2309 	      addtempomap(&ctempo, tptr);
2310 	  }
2311 	break;
2312       }
2313       tptr = tptr->next;
2314     }
2315 
2316   /* delete dummy 60.0/120.0 */
2317 
2318   ret = ret->next;
2319   return ret;
2320 
2321 }
2322 
2323 /*********************************************************/
2324 /*    set up mstart and mend pointers for renumbering    */
2325 /*                                                       */
2326 /* fields in each midi note:                             */
2327 /*                                                       */
2328 /* rate: starttime, in miditicks                         */
2329 /* width: endtime, in miditicks                          */
2330 /* opwidth: starttime, in kcycleidx (>= 1)               */
2331 /* inwidth: endtime, in kcycleidx (>= 1)                 */
2332 /* res: notenumber                                       */
2333 /* vartype: velocity                                     */
2334 /* usesinput: flag for noteoffwrite                      */
2335 /*********************************************************/
2336 
midipointers(tnode ** mstart,tnode ** mend)2337 int midipointers(tnode ** mstart, tnode ** mend)
2338 
2339 {
2340   int hasmidi;
2341   tnode * tptr, *startptr, *endptr;
2342 
2343   /* set up lists of current MIDI channel list pointers */
2344 
2345   hasmidi = 0;
2346   tptr = sstrmidi->imidiroot;
2347   (*mstart) = (*mend) = startptr = endptr = NULL;
2348   while (tptr)
2349     {
2350       if (!(*mstart))
2351 	{
2352 	  (*mstart) = startptr = make_tnode("tag", S_MIDITAG);
2353 	  (*mend) = endptr = make_tnode("tag", S_MIDITAG);
2354 	}
2355       else
2356 	{
2357 	  startptr->next = make_tnode("tag", S_MIDITAG);
2358 	  startptr = startptr->next;
2359 	  endptr->next = make_tnode("tag", S_MIDITAG);
2360 	  endptr = endptr->next;
2361 	}
2362       startptr->down = endptr->down = tptr->down; /* list of notes */
2363       if (tptr->down)
2364 	hasmidi = 1;
2365       tptr = tptr->next;
2366     }
2367   return hasmidi;
2368 
2369 }
2370 
2371 /*********************************************************/
2372 /*    converts timestamps from relative to absolute      */
2373 /*********************************************************/
2374 
timestampconvert(tnode * tptr,int kcycleidx)2375 void timestampconvert(tnode * tptr, int kcycleidx)
2376 
2377 {
2378   float ktime;
2379 
2380   ktime = 1.0F/krate;
2381   vmcheck(tptr->val = (char *) calloc(64, sizeof(char)));
2382   sprintf(tptr->val, "%f", (kcycleidx-1.5F)*ktime);
2383   tptr->opwidth = kcycleidx;
2384 
2385 }
2386 
2387 /*********************************************************/
2388 /*              merges a sasl rootlist                   */
2389 /*********************************************************/
2390 
mergerootlist(tnode ** oneroot,tnode ** onetail,tnode ** tworoot,tnode ** twotail,tnode ** outroot,tnode ** outtail)2391 void mergerootlist(tnode ** oneroot, tnode ** onetail,
2392 		   tnode ** tworoot, tnode ** twotail,
2393 		   tnode ** outroot, tnode ** outtail)
2394 
2395 {
2396   tnode * tptr = NULL;
2397 
2398   /* first handle simple cases */
2399 
2400   if (*tworoot == NULL)
2401     {
2402       *outroot = *oneroot;
2403       *outtail = *onetail;
2404       *onetail = NULL;
2405       return;
2406     }
2407   if (*oneroot == NULL)
2408     {
2409       *outroot = *tworoot;
2410       *outtail = *twotail;
2411       *twotail = NULL;
2412       return;
2413     }
2414 
2415   /* set up the merge */
2416 
2417   if ((*oneroot)->time < (*tworoot)->time)
2418     {
2419       *outroot = tptr = *oneroot;
2420       *oneroot = (*oneroot)->next;
2421     }
2422   else
2423     {
2424       *outroot = tptr = *tworoot;
2425       *tworoot = (*tworoot)->next;
2426     }
2427 
2428   /* do the merge */
2429 
2430   while ((*oneroot != NULL) || (*tworoot != NULL))
2431     {
2432       if (*oneroot == NULL)
2433 	{
2434 	  tptr->next = *tworoot;
2435 	  *outtail = *twotail;
2436 	  *tworoot = NULL;
2437 	  break;
2438 	}
2439       if (*tworoot == NULL)
2440 	{
2441 	  tptr->next = *oneroot;
2442 	  *outtail = *onetail;
2443 	  *oneroot = NULL;
2444 	  break;
2445 	}
2446       if ((*oneroot)->time < (*tworoot)->time)
2447 	{
2448 	  tptr->next = *oneroot;
2449 	  *oneroot = (*oneroot)->next;
2450 	}
2451       else
2452 	{
2453 	  tptr->next = *tworoot;
2454 	  *tworoot = (*tworoot)->next;
2455 	}
2456       tptr = tptr->next;
2457     }
2458 
2459   *onetail = *twotail = NULL;
2460   return;
2461 }
2462 
2463 /*********************************************************/
2464 /*       merges a labeltable list into allsasl           */
2465 /*********************************************************/
2466 
mergelabeltable(sigsym * sptr)2467 void mergelabeltable(sigsym * sptr)
2468 
2469 {
2470   sigsym * label;
2471   tnode * lptr;
2472 
2473   while (sptr)
2474     {
2475       if ((label = getvsym(&(allsasl->labeltable),sptr->val)))
2476 	{
2477 	  lptr = sptr->defnode;
2478 	  while (lptr->next != NULL)
2479 	    lptr = lptr->next;
2480 	  lptr->next = label->defnode;
2481 	  label->defnode = sptr->defnode;
2482 	}
2483       else
2484 	{
2485 	  addvsym(&(allsasl->labeltable), sptr->val, S_LINSTR);
2486 	  label = getvsym(&(allsasl->labeltable),sptr->val);
2487 	  label->defnode = sptr->defnode;
2488 	}
2489       sptr = sptr->next;
2490     }
2491 }
2492 
2493 
2494 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2495 /*                                                              */
2496 /*       Utility functions for reading score data.              */
2497 /*                                                              */
2498 /*______________________________________________________________*/
2499 
2500 /*********************************************************/
2501 /*          adds score IDENT to symbol table             */
2502 /*********************************************************/
2503 
scoreaddsymtable(tnode * tptr)2504 void scoreaddsymtable(tnode * tptr)
2505 
2506 {
2507   if (!identtoken(tptr))
2508     if ((addvsym(&bitsymtable, tptr->val, K_INTERNAL) == INSTALLED)
2509 	&& (bitsymtable->next != NULL))
2510       bitsymtable->special = bitsymtable->next->special + 1;
2511 }
2512 
2513 /*********************************************************/
2514 /*          merge sort for SASL note-ons                 */
2515 /*********************************************************/
2516 
mergenodes(tnode ** rootnode,tnode * newnode)2517 void mergenodes(tnode ** rootnode, tnode * newnode)
2518 
2519 {
2520 
2521   tnode * tptr;
2522 
2523   if ((*rootnode)->time >= newnode->time)
2524     {
2525       newnode->next = *rootnode;
2526       *rootnode = newnode;
2527       return;
2528     }
2529   else
2530     {
2531       tptr = *rootnode;
2532       while (tptr->next != NULL)
2533 	{
2534 	  if (tptr->next->time >= newnode->time)
2535 	    {
2536 	      newnode->next = tptr->next;
2537 	      tptr->next = newnode;
2538 	      return;
2539 	    }
2540 	  tptr = tptr->next;
2541 	}
2542       internalerror("readscore.c", "mergenodes()");
2543     }
2544 
2545 }
2546 
2547 
2548 /*********************************************************/
2549 /*          checks instr pfields for bad elements        */
2550 /*********************************************************/
2551 
instrpfieldcheck(tnode * nsl,tnode * ptest)2552 void instrpfieldcheck(tnode * nsl, tnode * ptest)
2553 
2554 {
2555 
2556   while (ptest != NULL)
2557     {
2558       if ((ptest->ttype != S_NUMBER) && (ptest->ttype != S_INTGR))
2559 	{
2560 	  printf("Error: Element %s not allowed in SASL instr pfields\n",
2561 		 ptest->val);
2562 	  showbadline(nsl);
2563 	}
2564       ptest = ptest->next;
2565     }
2566 
2567 }
2568 
2569 /*********************************************************/
2570 /*          checks table pfields for bad elements        */
2571 /*********************************************************/
2572 
tablepfieldcheck(tnode * nsl)2573 void tablepfieldcheck(tnode * nsl)
2574 
2575 {
2576 
2577   tnode * ptest;
2578   int sample, concat;
2579 
2580   sample = !(strcmp(nsl->next->next->next->val,"sample"));
2581   concat = !(strcmp(nsl->next->next->next->val,"concat"));
2582 
2583   ptest = nsl->next->next->next->next;
2584 
2585   /* check type of size parameter */
2586 
2587   if ((ptest->ttype != S_NUMBER) && (ptest->ttype != S_INTGR))
2588     {
2589       printf("Error: Bad size parameter %s in SASL table pfields\n",
2590 	     ptest->val);
2591       showbadline(nsl);
2592     }
2593   ptest = ptest->next;
2594 
2595   /* special cases for concat and sample parameters */
2596 
2597   if (sample)
2598     {
2599       if (!ptest || (ptest->ttype != S_STRCONST))
2600 	{
2601 	  if (ptest)
2602 	    printf("Error: Bad filename parameter %s in SASL table pfields\n",
2603 		   ptest->val);
2604 	  else
2605 	    printf("Error: No filename parameter in SASL table pfields\n");
2606 	  showbadline(nsl);
2607 	}
2608       ptest = ptest->next;
2609     }
2610 
2611   if (concat)
2612     {
2613       while (ptest != NULL)
2614 	{
2615 	  if ((ptest->ttype != S_IDENT) ||
2616 	      (!(ptest->sptr = getvsym(&globalsymtable,ptest->val))) ||
2617 	      (ptest->sptr->vartype != TABLETYPE))
2618 	    {
2619 	      printf("Error: Bad table parameter %s in SASL table pfields\n",
2620 		     ptest->val);
2621 	      showbadline(nsl);
2622 	    }
2623 	  ptest = ptest->next;
2624 	}
2625     }
2626 
2627   /* checks all numeric parameters */
2628 
2629   while (ptest != NULL)
2630     {
2631       if ((ptest->ttype != S_NUMBER) && (ptest->ttype != S_INTGR))
2632 	{
2633 	  printf("Error: Element %s not allowed in SASL table pfields\n",
2634 		 ptest->val);
2635 	  showbadline(nsl);
2636 	}
2637       ptest = ptest->next;
2638     }
2639 
2640 }
2641 
2642 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2643 /*                                                              */
2644 /*       Utility functions for intermediate score processing.   */
2645 /*                                                              */
2646 /*______________________________________________________________*/
2647 
2648 /*********************************************************/
2649 /*      creates a new element for the tempo map          */
2650 /*********************************************************/
2651 
addtempomap(tnode ** mptr,tnode * tptr)2652 void addtempomap(tnode ** mptr, tnode * tptr)
2653 
2654 {
2655   tptr->next = make_tnode((*mptr)->down->next->next->val, S_TEMPO);
2656   tptr->next->time = (*mptr)->time;
2657   *mptr = (*mptr)->next;
2658 }
2659 
2660