1 /*
2     sread.c:
3 
4     Copyright (C) 1991, 1997 Barry Vercoe, John ffitch
5 
6     This file is part of Csound.
7 
8     The Csound Library is free software; you can redistribute it
9     and/or modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation; either
11     version 2.1 of the License, or (at your option) any later version.
12 
13     Csound is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU Lesser General Public License for more details.
17 
18     You should have received a copy of the GNU Lesser General Public
19     License along with Csound; if not, write to the Free Software
20     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21     02110-1301 USA
22 */
23 
24 #include "csoundCore.h"                             /*   SREAD.C     */
25 #include <math.h>      /* for fabs() */
26 #include <ctype.h>
27 #include <inttypes.h>
28 #include "namedins.h"           /* IV - Oct 31 2002 */
29 #include "corfile.h"
30 #include "Engine/score_param.h"
31 
32 #define MEMSIZ  16384           /* size of memory requests from system  */
33 #define MARGIN  4096            /* minimum remaining before new request */
34 #define NAMELEN 40              /* array size of repeat macro names */
35 #define RPTDEPTH 40             /* size of repeat_n arrays (39 loop levels) */
36 
37 //#define MACDEBUG (1)
38 
39 static void print_input_backtrace(CSOUND *csound, int needLFs,
40                                   void (*msgfunc)(CSOUND*, const char*, ...));
41 static  void    copylin(CSOUND *), copypflds(CSOUND *);
42 static  void    ifa(CSOUND *), setprv(CSOUND *);
43 static  void    carryerror(CSOUND *), pcopy(CSOUND *, int, int, SRTBLK*);
44 static  void    salcinit(CSOUND *);
45 static  void    salcblk(CSOUND *), flushlin(CSOUND *);
46 static  int     getop(CSOUND *), getpfld(CSOUND *, int);
47         MYFLT   stof(CSOUND *, char *);
48 extern  void    *fopen_path(CSOUND *, FILE **, char *, char *, char *, int);
49 extern int csound_prslex_init(void *);
50 extern void csound_prsset_extra(void *, void *);
51 
52 extern int csound_prslex(CSOUND*, void*);
53 extern int csound_prslex_destroy(void *);
54 extern void cs_init_smacros(CSOUND*, PRS_PARM*, NAMES*);
55 
56 #define STA(x)  (csound->sread.x)
57 
expand_nxp(CSOUND * csound)58 static intptr_t expand_nxp(CSOUND *csound)
59 {
60     char      *oldp;
61     SRTBLK    *p;
62     intptr_t  offs;
63     size_t    nbytes;
64 
65     if (UNLIKELY((csound->sread.nxp) >=
66                  ((csound->sread.memend) + MARGIN))) {
67       csound->Die(csound, Str("sread:  text space overrun, increase MARGIN"));
68       return 0;     /* not reached */
69     }
70     /* calculate the number of bytes to allocate */
71     nbytes = (size_t) ((csound->sread.memend) -
72                        (csound->sread.curmem));
73     nbytes = nbytes + (nbytes >> 3) + (size_t) (MEMSIZ - 1);
74     nbytes &= ~((size_t) (MEMSIZ - 1));
75     /* extend allocated memory */
76     oldp = (csound->sread.curmem);
77     (csound->sread.curmem) =
78       (char*) csound->ReAlloc(csound, (csound->sread.curmem),
79                               nbytes + (size_t) MARGIN);
80     (csound->sread.memend) =
81       (char*) (csound->sread.curmem) + (int32) nbytes;
82     /* did the pointer change ? */
83     if ((csound->sread.curmem) == oldp)
84       return (intptr_t) 0;      /* no, nothing to do */
85     /* correct all pointers for the change */
86     offs = (intptr_t) ((uintptr_t)(csound->sread.curmem) - (uintptr_t) oldp);
87     if ((csound->sread.bp) != NULL)
88       (csound->sread.bp) =
89         (SRTBLK*) ((uintptr_t) (csound->sread.bp) + (intptr_t) offs);
90     if ((csound->sread.prvibp) != NULL)
91       (csound->sread.prvibp) =
92         (SRTBLK*) ((uintptr_t) (csound->sread.prvibp) + (intptr_t) offs);
93     if ((csound->sread.sp) != NULL)
94       (csound->sread.sp) =
95         (char*) ((uintptr_t) (csound->sread.sp) + (intptr_t) offs);
96     if ((csound->sread.nxp) != NULL)
97       (csound->sread.nxp) =
98         (char*) ((uintptr_t) (csound->sread.nxp) + (intptr_t) offs);
99     if (csound->frstbp == NULL)
100       return offs;
101     p = csound->frstbp;
102     csound->frstbp = p = (SRTBLK*) ((uintptr_t) p + (intptr_t) offs);
103     do {
104       if (p->prvblk != NULL)
105         p->prvblk = (SRTBLK*) ((uintptr_t) p->prvblk + (intptr_t) offs);
106       if (p->nxtblk != NULL)
107         p->nxtblk = (SRTBLK*) ((uintptr_t) p->nxtblk + (intptr_t) offs);
108       p = p->nxtblk;
109     } while (p != NULL);
110     /* return pointer change in bytes */
111     return offs;
112 }
113 
114 /* sreaderr() - for non-fatal "warnings" */
sreaderr(CSOUND * csound,const char * s,...)115 static void sreaderr(CSOUND *csound, const char *s, ...)
116 {
117     va_list   args;
118 
119     csoundMessage(csound, Str("sread: "));
120     va_start(args, s);
121     csoundMessageV(csound, 0, s, args);
122     va_end(args);
123     csoundMessage(csound, "\n");
124     print_input_backtrace(csound, 1, csoundMessage);
125     return;
126 }
127 
128 /* scorerr() - for fatal errors in score parsing */
scorerr(CSOUND * csound,const char * s,...)129 static void scorerr(CSOUND *csound, const char *s, ...)
130 {
131     va_list   args;
132 
133     va_start(args, s);
134     csound->ErrMsgV(csound, Str("score error:  "), s, args);
135     va_end(args);
136     print_input_backtrace(csound, 0, csoundErrorMsg);
137     csound->LongJmp(csound, 1);
138 }
139 
print_input_backtrace(CSOUND * csound,int needLFs,void (* msgfunc)(CSOUND *,const char *,...))140 static void print_input_backtrace(CSOUND *csound, int needLFs,
141                                   void (*msgfunc)(CSOUND*, const char*, ...))
142 {
143     IN_STACK  *curr = (csound->sread.str);
144     char      *m, *lf = (needLFs ? "\n" : "");
145     int       lastinput = 0;
146     int       lastsource = 2; /* 2=current file, 1=macro, 0=#include */
147 
148     msgfunc(csound, Str("  section %d:  at position %d%s"), csound->sectcnt,
149                     (csound->sread.linepos), lf);
150 
151     do {
152       if (curr == (csound->sread.inputs)) lastinput = 1;
153       if (UNLIKELY(!curr->mac || !curr->mac->name)){
154         csound->Warning(csound, Str("Internal error in print_input_backtrace()"));
155         return;
156       }
157       switch(lastsource) {
158       case 0: m = Str("  included from line %d of macro %s%s"); break;
159       case 1: m = Str("  called from line %d of macro %s%s"); break;
160         //default:
161       case 2: m = Str("  in line %d of macro %s%s"); break;
162       }
163       msgfunc(csound, m, (lastsource == 0 ? curr->line - 1 : curr->line),
164               curr->mac->name, lf);  /* #include is one line before */
165       if (lastinput && csound->oparms->useCsdLineCounts && csound->csdname) {
166         /* print name & line # of CSD instead of temp sco */
167         msgfunc(csound, m,
168                 (lastsource == 0 ? csound->scoLineOffset + curr->line - 1 :
169                  csound->scoLineOffset + curr->line), csound->csdname, lf);
170       }
171       /* else { */
172       /*   msgfunc(csound, m, (lastsource == 0 ? curr->line - 1 : curr->line), */
173       /*     corfile_tell(curr->cf), lf);  /\* #include is one line before *\/ */
174       /* } */
175     } while (!lastsource);
176     curr--;
177     return;
178 }
179 
operate(CSOUND * csound,MYFLT a,MYFLT b,char c)180 static MYFLT operate(CSOUND *csound, MYFLT a, MYFLT b, char c)
181 {
182     MYFLT ans;
183     extern MYFLT MOD(MYFLT,MYFLT);
184 
185     switch (c) {
186     case '+': ans = a + b; break;
187     case '-': ans = a - b; break;
188     case '*': ans = a * b; break;
189     case '/': ans = a / b; break;
190     case '%': ans = MOD(a, b); break;
191     case '^': ans = POWER(a, b); break;
192     case '&': ans = (MYFLT) (MYFLT2LRND(a) & MYFLT2LRND(b)); break;
193     case '|': ans = (MYFLT) (MYFLT2LRND(a) | MYFLT2LRND(b)); break;
194     case '#': ans = (MYFLT) (MYFLT2LRND(a) ^ MYFLT2LRND(b)); break;
195     default:
196       csoundDie(csound, Str("Internal error op=%c"), c);
197       ans = FL(0.0);    /* compiler only */
198     }
199     return ans;
200 }
201 
isNameChar(int c,int pos)202 static inline int isNameChar(int c, int pos)
203 {
204     //c = (int) ((unsigned char) c);
205     if (UNLIKELY(c<0)) return 0;
206     return (isalpha(c) || (pos && (c == '_' || isdigit(c))));
207 }
208 
209 /* Functions to read/unread chracters from
210  * a stack of file and macro inputs */
211 
ungetscochar(CSOUND * csound,int c)212 static inline void ungetscochar(CSOUND *csound, int c)
213 {
214     corfile_ungetc(csound->expanded_sco);
215     csound->expanded_sco->body[csound->expanded_sco->p] = (char)c;
216 }
217 
getscochar(CSOUND * csound,int expand)218 static int getscochar(CSOUND *csound, int expand)
219 {
220 /* Read a score character, expanding macros if flag set */
221     int     c;
222     IGN(expand);
223 /* Read a score character, expanding macros expanded */
224     c = corfile_getc(csound->expanded_sco);
225     if (c == EOF) {
226       if ((csound->sread.str) == &(csound->sread.inputs)[0]) {
227         return EOF;
228       }
229     }
230 #ifdef MACDEBUG
231     csound->DebugMsg(csound,"%s(%d): character = %c(%.2d)\n",
232                      __FILE__, __LINE__, c, c);
233 #endif
234     if (c == '\n') {
235       (csound->sread.str)->line++; (csound->sread.linepos) = -1;
236     }
237     else (csound->sread.linepos)++;
238     return c;
239 }
240 
sread_initstr(CSOUND * csound,CORFIL * sco)241 void sread_initstr(CSOUND *csound, CORFIL *sco)
242 {
243     /* sread_alloc_globals(csound); */
244     IGN(sco);
245     (csound->sread.inputs) =
246       (IN_STACK*) csound->Malloc(csound, 20 * sizeof(IN_STACK));
247     (csound->sread.input_size) = 20;
248     (csound->sread.input_cnt) = 0;
249     (csound->sread.str) = (csound->sread.inputs);
250     (csound->sread.str)->is_marked_repeat = 0;
251     (csound->sread.str)->line = 1; (csound->sread.str)->mac = NULL;
252     //init_smacros(csound, csound->smacros);
253     {
254       PRS_PARM  qq;
255       memset(&qq, '\0', sizeof(PRS_PARM));
256       csound_prslex_init(&qq.yyscanner);
257       cs_init_smacros(csound, &qq, csound->smacros);
258       csound_prsset_extra(&qq, qq.yyscanner);
259       csound->expanded_sco = corfile_create_w(csound);
260       /* printf("Input:\n%s<<<\n", */
261       /*        corfile_body(csound->sread.str->cf)); */
262       csound_prslex(csound, qq.yyscanner);
263       csound->DebugMsg(csound, "yielding >>%s<<\n",
264                        corfile_body(csound->expanded_sco));
265       csound_prslex_destroy(qq.yyscanner);
266       corfile_rm(csound, &csound->scorestr);
267       corfile_rewind(csound->expanded_sco);
268     }
269 }
270 
sread(CSOUND * csound)271 int sread(CSOUND *csound)       /*  called from main,  reads from SCOREIN   */
272 {                               /*  each score statement gets a sortblock   */
273     int  rtncod;                /* return code to calling program:      */
274                                 /*   1 = section read                   */
275                                 /*   0 = end of file                    */
276     /* sread_alloc_globals(csound); */
277     (csound->sread.bp) =
278       (csound->sread.prvibp) = csound->frstbp = NULL;
279     (csound->sread.nxp) = NULL;
280     (csound->sread.warpin) = 0;
281     (csound->sread.lincnt) = 1;
282     csound->sectcnt++;
283     rtncod = 0;
284     salcinit(csound);           /* init the mem space for this section  */
285 #ifdef never
286     if (csound->score_parser) {
287       extern int scope(CSOUND*);
288       printf("**********************************************************\n");
289       printf("*******************EXPERIMENTAL CODE**********************\n");
290       printf("**********************************************************\n");
291       scope(csound);
292       exit(0);
293     }
294 #endif
295     //printf("sread starts with >>%s<<\n", csound->expanded_sco->body);
296     while (((csound->sread.op) = getop(csound)) != EOF) {
297       /* read next op from scorefile */
298       rtncod = 1;
299       salcblk(csound);          /* build a line structure; init bp,nxp  */
300     again:
301       //printf("*** reading: %c (%.2x)\n",
302       //       (csound->sread.op), (csound->sread.op));
303       switch ((csound->sread.op)) { /*  and dispatch on opcodes  */
304       case 'y':
305         {
306           char  *p = &((csound->sread.bp)->text[1]);
307           char q;
308           //char *old_nxp = (csound->sread.nxp)-2;
309           //printf("text=%s<<\n", (csound->sread.bp)->text);
310           /* Measurement shows isdigit and 3 cases is about 30% */
311           /* faster than use of strchr (measured on Suse9.3)    */
312           /*         if (strchr("+-.0123456789", *p) != NULL) { */
313           while ((q=getscochar(csound,1))!='\n') *p++ = q;
314           *p = '\0';
315           //printf("text=%s<<\n", (csound->sread.bp)->text);
316           p = &((csound->sread.bp)->text[1]);
317           while (isblank(q=*p)) p++;
318           if (isdigit(q) || q=='+' || q=='-' || q=='.') {
319             double  tt;
320             char    *tmp = p;
321             tt = cs_strtod(p, &tmp);
322             //printf("tt=%lf q=%c\n", tt, q);
323             csound->randSeed1 = (int)tt;
324             printf("seed from score %d\n", csound->randSeed1);
325           }
326           else {
327             uint32_t tmp = (uint32_t) csound->GetRandomSeedFromTime();
328             while (tmp >= (uint32_t) 0x7FFFFFFE)
329               tmp -= (uint32_t) 0x7FFFFFFE;
330             csound->randSeed1 = tmp+1;
331             printf("seed from clock %d\n", csound->randSeed1);
332           }
333           //printf("cleaning up\n");
334           break;
335           //q = (csound->sread.op) = getop(csound);
336           //printf("next op = %c(%.2x)\n", q, q);
337           //goto again;
338         }
339       case 'i':
340       case 'd':
341       case 'f':
342       case 'a':
343       case 'q':
344         ifa(csound);
345         break;
346       case 'w':
347         (csound->sread.warpin)++;
348         copypflds(csound);
349         break;
350       case 't':
351         copypflds(csound);
352         break;
353       case 'B':
354       case 'b': /* Set a clock base */
355         {
356           char *old_nxp = (csound->sread.nxp)-2;
357           getpfld(csound,0);
358           if (csound->sread.op == 'b')
359             (csound->sread.clock_base) =
360               stof(csound, (csound->sread.sp));
361           else
362             (csound->sread.clock_base) +=
363               stof(csound, (csound->sread.sp));
364 
365           if (csound->oparms->msglevel & TIMEMSG)
366             csound->Message(csound,Str("Clockbase = %f\n"),
367                             csound->sread.clock_base);
368           flushlin(csound);
369           (csound->sread.op) = getop(csound);
370           (csound->sread.nxp) = old_nxp;
371           *(csound->sread.nxp)++ =
372             (csound->sread.op); /* Undo this line */
373           (csound->sread.nxp)++;
374           goto again;
375         }
376       case 'C':                 /* toggle carry */
377         {
378           char *old_nxp = (csound->sread.nxp)-2;
379           getpfld(csound,0);
380           (csound->sread.nocarry) =
381             stof(csound, (csound->sread.sp))==0.0?1:0;
382           //printf("nocarry = %d\n", (csound->sread.nocarry));
383           flushlin(csound);
384           (csound->sread.op) = getop(csound);
385           (csound->sread.nxp) = old_nxp;
386           *(csound->sread.nxp)++ =
387             (csound->sread.op); /* Undo this line */
388           (csound->sread.nxp)++;
389           goto again;
390         }
391       case 's':
392       case 'e':
393         /* check for optional p1 before doing repeats */
394         copylin(csound);
395         {
396           char  *p = &((csound->sread.bp)->text[1]);
397           char q;
398           while (isblank(*p))
399             p++;
400           /* Measurement shows isdigit and 3 cases is about 30% */
401           /* faster than use of strchr (measured on Suse9.3)    */
402           /*         if (strchr("+-.0123456789", *p) != NULL) { */
403           q = *p;
404           if (isdigit(q) || q=='+' || q=='-' || q=='.') {
405             double  tt;
406             char    *tmp = p;
407             tt = cs_strtod(p, &tmp);
408             if (tmp != p && (*tmp == '\0' || isspace(*tmp))) {
409               (csound->sread.bp)->pcnt = 1;
410               (csound->sread.bp)->p1val =
411                 (csound->sread.bp)->p2val =
412                 (csound->sread.bp)->newp2 = (MYFLT) tt;
413             }
414           }
415           else (csound->sread.bp)->p1val =
416                  (csound->sread.bp)->p2val =
417                  (csound->sread.bp)->newp2 = FL(0.0);
418         }
419         /* If we are in a repeat of a marked section ('n' statement),
420            we must pop those inputs before doing an 'r' repeat. */
421         if ((csound->sread.str)->is_marked_repeat) {
422           //printf("end of n; return to %d\n", (csound->sread.str)->oposit);
423           corfile_set(csound->expanded_sco, (csound->sread.str)->oposit);
424           (csound->sread.str)--;
425           return rtncod;
426         }
427         /* while ((csound->sread.str)->is_marked_repeat && */
428         /*        (csound->sread.input_cnt) > 0) { */
429         /*   /\* close all marked repeat inputs *\/ */
430         /*   //corfile_rm(&((csound->sread.str)->cf)); */
431         /*   (csound->sread.str)--; (csound->sread.input_cnt)--; */
432         /* } */
433         /* if ((csound->sread.repeat_cnt) != 0) { */
434         /*   if (do_repeat(csound)) */
435         /*     return rtncod; */
436         /* } */
437         if ((csound->sread.op) != 'e') {
438           (csound->sread.clock_base) = FL(0.0);
439           (csound->sread.warp_factor) = FL(1.0);
440           (csound->sread.prvp2) = -FL(1.0);
441         }
442         return rtncod;
443       case 'm': /* Remember this place */
444         {
445           char  *old_nxp = (csound->sread.nxp)-2;
446           char  buff[200];
447           int   c;
448           int   i = 0, j;
449           while (isblank(c = getscochar(csound, 1)));
450           while (isNameChar(c, i)) {
451             buff[i++] = c;
452             c = getscochar(csound, 1);
453           }
454           buff[i] = '\0';
455           if (c != EOF && c != '\n') flushlin(csound);
456           if (csound->oparms->msglevel & TIMEMSG)
457             csound->Message(csound,Str("m Named section >>>%s<<<\n"), buff);
458             //printf("*** last_name = %d\n", (csound->sread.last_name));
459           for (j=0; j<(csound->sread.last_name); j++) {
460             //printf("m: %s %s(%d)\n",
461             //       buff, (csound->sread.names)[j].name, j);
462             if (strcmp(buff, (csound->sread.names)[j].name)==0) break;
463           }
464           if (j>=(csound->sread.last_name)) {
465             j = ++(csound->sread.last_name);
466             (csound->sread.names)[j].name =cs_strdup(csound, buff);
467           }
468           (csound->sread.names)[j].posit =
469             corfile_tell(csound->expanded_sco);
470           //printf("posit=%d\n", (csound->sread.names)[j].posit);
471           (csound->sread.names)[j].line = (csound->sread.str)->line;
472           //printf("line-%d\n",(csound->sread.names)[j].line);
473           if (csound->oparms->msglevel & TIMEMSG)
474             csound->Message(csound,Str("%d: %s position %"PRIi32"\n"),
475                             j, (csound->sread.names)[j].name,
476                             (csound->sread.names)[j].posit);
477           (csound->sread.op) = getop(csound);
478           (csound->sread.nxp) = old_nxp;
479           *(csound->sread.nxp)++ =
480             (csound->sread.op); /* Undo this line */
481           (csound->sread.nxp)++;
482           goto again;           /* suggested this loses a line?? */
483         }
484       case 'n':
485         {
486           char *old_nxp = (csound->sread.nxp)-2;
487           char buff[200];
488           int c;
489           int i = 0;
490           while (isblank(c = getscochar(csound, 1)));
491           while (isNameChar(c, i)) {
492             buff[i++] = c;
493             c = getscochar(csound, 1);
494           }
495           buff[i] = '\0';
496           printf("n Named section %s\n", buff);
497           if (c != '\n' && c != EOF) flushlin(csound);
498           //printf("last_name %d\n", (csound->sread.last_name));
499           for (i = 0; i<=(csound->sread.last_name); i++) {
500             //printf("n: %s %s(%d)\n",
501             //       buff, (csound->sread.names)[i].name, i);
502             if (strcmp(buff, (csound->sread.names)[i].name)==0) break;
503           }
504           //printf("i=%d\n", i);
505           if (UNLIKELY(i > (csound->sread.last_name)))
506             sreaderr(csound, Str("Name %s not found"), buff);
507           else {
508             //csound->Message(csound, Str("%d: %s (%ld)\n"),
509             //                i, buff, (csound->sread.names)[i].posit);
510             (csound->sread.input_cnt)++;
511             if (csound->sread.input_cnt>=csound->sread.input_size) {
512               int old = (csound->sread.str)-(csound->sread.inputs);
513               (csound->sread.input_size) += 20;
514               (csound->sread.inputs) =
515                 csound->ReAlloc(csound, (csound->sread.inputs),
516                                 csound->sread.input_size * sizeof(IN_STACK));
517               (csound->sread.str) =
518                 &(csound->sread.inputs)[old];     /* In case it moves */
519             }
520             (csound->sread.str)++;
521             (csound->sread.str)->is_marked_repeat = 1;
522             (csound->sread.str)->line = (csound->sread.names)[i].line;
523             (csound->sread.str)->oposit = corfile_tell(csound->expanded_sco);
524             corfile_set(csound->expanded_sco,
525                         (csound->sread.names)[i].posit);
526             //printf("posit was %d moved to %d\n",
527             //       (csound->sread.str)->oposit,
528             //       (csound->sread.names)[i].posit);
529           }
530               (csound->sread.op) = getop(csound);
531           (csound->sread.nxp) = old_nxp;
532           *(csound->sread.nxp)++ =
533             (csound->sread.op); /* Undo this line */
534           (csound->sread.nxp)++;
535           goto again;
536         }
537       case 'v': /* Suggestion of Bryan Bales */
538         {       /* Set local variability of time */
539           char *old_nxp = (csound->sread.nxp)-2;
540           getpfld(csound,0);
541           (csound->sread.warp_factor) =
542             stof(csound, (csound->sread.sp));
543           if (csound->oparms->msglevel & TIMEMSG)
544             csound->Message(csound, Str("Warp_factor = %f\n"),
545                             (csound->sread.warp_factor));
546           flushlin(csound);
547           (csound->sread.op) = getop(csound);
548           (csound->sread.nxp) = old_nxp;
549           *(csound->sread.nxp)++ =
550             (csound->sread.op);          /* Undo this line */
551           (csound->sread.nxp)++;
552           goto again;
553         }
554       case 'x':                         /* Skip section */
555         //printf("***skipping section\n");
556         flushlin(csound);
557         while (1) {
558           switch ((csound->sread.op) = getop(csound)) {
559           case 's':
560           case 'r':
561           case 'm':
562           case 'e':
563             //printf("***skip ending with %c\n", (csound->sread.op));
564             salcblk(csound);            /* place op, blank into text    */
565             goto again;
566           case EOF:
567             goto ending;
568           default:
569             //printf("***ignoring %c\n", (csound->sread.op));
570             flushlin(csound);
571           }
572         }
573         break;
574       case -1:
575         break;
576       default:
577         csound->Message(csound,
578                         Str("sread is confused on legal opcodes %c(%.2x)\n"),
579                         (csound->sread.op), (csound->sread.op));
580         break;
581       }
582     }
583  ending:
584     /* if ((csound->sread.repeat_cnt) > 0) { */
585     /*   (csound->sread.op) = 'e'; */
586     /*   salcblk(csound); */
587     /*   /\* if (do_repeat(csound)) *\/ */
588     /*   /\*   return rtncod; *\/ */
589     /*   *(csound->sread.nxp)++ = LF; */
590     /* } */
591     /* if (!rtncod) {                      /\* Ending so clear macros *\/ */
592     /*   while ((csound->sread.macros) != NULL) { */
593     /*     undefine_score_macro(csound, (csound->sread.macros)->name); */
594     /*   } */
595     /* } */
596     return rtncod;
597 }
598 
copylin(CSOUND * csound)599 static void copylin(CSOUND *csound)     /* copy source line to srtblk   */
600 {
601     int c;
602     (csound->sread.nxp)--;
603     if (csound->sread.nxp >= csound->sread.memend)
604       /* if this memblk exhausted */
605       expand_nxp(csound);
606     do {
607       c = getscochar(csound, 1);
608       *(csound->sread.nxp)++ = c;
609     } while (c != LF && c != EOF);
610     if (c == EOF) *((csound->sread.nxp)-1) = '\n'; /* Avoid EOF characters */
611     (csound->sread.lincnt)++;
612     (csound->sread.linpos) = 0;
613 }
614 
copypflds(CSOUND * csound)615 static void copypflds(CSOUND *csound)
616 {
617     (csound->sread.bp)->pcnt = 0;
618     while (getpfld(csound,1))                    /* copy each pfield,    */
619       (csound->sread.bp)->pcnt++;         /* count them,          */
620     *(csound->sread.nxp-1) = LF;          /* terminate with newline */
621 }
622 
ifa(CSOUND * csound)623 static void ifa(CSOUND *csound)
624 {
625     SRTBLK *prvbp;
626     int n, nocarry = 0;
627 
628     (csound->sread.bp)->pcnt = 0;
629     while (getpfld(csound,0)) {   /* while there's another pfield,  */
630       nocarry = 0;
631       ++(csound->sread.bp)->pcnt;
632       /* if (UNLIKELY(++(csound->sread.bp)->pcnt == PMAX)) { */
633       /*   sreaderr(csound, Str("instr pcount exceeds PMAX")); */
634       /*   csound->Message(csound, Str("      remainder of line flushed\n")); */
635       /*   flushlin(csound); */
636       /*   continue; */
637       /* } */
638       if (*(csound->sread.sp) == '^' &&
639           (csound->sread.op) == 'i' &&
640           (csound->sread.bp)->pcnt == 2) {
641         int foundplus = 0;
642         if (*((csound->sread.sp)+1)=='+') {
643           (csound->sread.sp)++; foundplus = 1;
644         }
645         if (UNLIKELY((csound->sread.prvp2)<0)) {
646           sreaderr(csound,Str("No previous event for ^"));
647           (csound->sread.prvp2) =
648             (csound->sread.bp)->p2val =
649               (csound->sread.warp_factor) *
650                stof(csound, (csound->sread.sp)+1);
651         }
652         else if (UNLIKELY(isspace(*((csound->sread.sp)+1)))) {
653           /* stof() assumes no leading whitespace -- 070204, akozar */
654           sreaderr(csound, Str("illegal space following %s, zero substituted"),
655                            (foundplus ? "^+" : "^"));
656           (csound->sread.prvp2) =
657             (csound->sread.bp)->p2val =
658                (csound->sread.prvp2);
659         }
660         else (csound->sread.prvp2) =
661                (csound->sread.bp)->p2val =
662                  (csound->sread.prvp2) + csound->sread.warp_factor *
663                stof(csound, (csound->sread.sp) + 1);
664       }
665       else if ((csound->sread.nxp)-(csound->sread.sp) == 2 &&
666                (*(csound->sread.sp) == '.' ||
667                 *(csound->sread.sp) == '+')) {
668         if ((csound->sread.op) == 'i'
669             && (*(csound->sread.sp) == '.' ||
670                 (csound->sread.bp)->pcnt == 2)
671             && (((csound->sread.bp)->pcnt >= 2
672                  && (prvbp = (csound->sread.prvibp)) != NULL
673                  && (csound->sread.bp)->pcnt <= prvbp->pcnt)
674                 || ((csound->sread.bp)->pcnt == 1 &&
675                     (prvbp = (csound->sread.bp)->prvblk) != NULL
676                     && prvbp->text[0] == 'i'))) {
677           if (*(csound->sread.sp) == '.') {
678             (csound->sread.nxp) = (csound->sread.sp);
679             pcopy(csound, (int) (csound->sread.bp)->pcnt, 1, prvbp);
680             if ((csound->sread.bp)->pcnt >= 2)
681               (csound->sread.prvp2) = (csound->sread.bp)->p2val;
682           }
683           else /* need the fabs() in case of neg p3 */
684             (csound->sread.prvp2) = (csound->sread.bp)->p2val =
685                         prvbp->p2val + FABS(prvbp->p3val);
686         }
687         else carryerror(csound);
688       }
689       else if (*(csound->sread.sp) == '!') {
690         int getmore = 0;
691         if (UNLIKELY((csound->sread.op) != 'i')) {
692           *((csound->sread.nxp)-1) = '\0';
693           getmore = 1;
694           sreaderr(csound, Str("ignoring '%s' in '%c' event"),
695                    (csound->sread.sp), (csound->sread.op));
696         }
697         else if (UNLIKELY((csound->sread.bp)->pcnt < 4)) {
698           sreaderr(csound, Str("! invalid in p1, p2, or p3"));
699           csound->Message(csound, Str("      remainder of line flushed\n"));
700           flushlin(csound);
701         }
702         else if (UNLIKELY(csound->sread.nxp-csound->sread.sp != 2)) {
703           sreaderr(csound, Str("illegal character after !: '%c'"),
704                    *((csound->sread.sp)+1));
705           csound->Message(csound, Str("      remainder of line flushed\n"));
706           flushlin(csound);
707         }
708         else {
709           nocarry = 1;         /* only set when no syntax errors */
710           flushlin(csound);
711         }
712         /* but always delete the pfield beginning with '!' */
713         (csound->sread.nxp) = (csound->sread.sp);
714         (csound->sread.bp)->pcnt--;
715         if (getmore) continue; /* not the best, but not easy to delete event */
716                                /* since ifa() doesn't return anything */
717         else break;
718       }
719       else switch ((csound->sread.bp)->pcnt) { /*  watch for p1,p2,p3, */
720         case 1:                           /*   & MYFLT, setinsno..*/
721           if (((csound->sread.op) == 'i' ||
722                (csound->sread.op) == 'd' ||
723                (csound->sread.op) == 'q') &&
724               *(csound->sread.sp) == '"') {
725             /* csound->DebugMsg(csound,"***Entering second dubious code scnt=%d\n",
726                csound->scnt0); */
727             (csound->sread.bp)->p1val = SSTRCOD;      /* allow string name */
728           }
729           else {
730             (csound->sread.bp)->p1val =
731               stof(csound, (csound->sread.sp));
732           }
733           if ((csound->sread.op) == 'i' || (csound->sread.op) == 'd')
734             setprv(csound);
735           else (csound->sread.prvibp) = NULL;
736           break;
737         case 2: (csound->sread.prvp2) = (csound->sread.bp)->p2val =
738             (csound->sread.warp_factor)*
739             stof(csound, csound->sread.sp) + csound->sread.clock_base;
740           break;
741         case 3: if ((csound->sread.op) == 'i')
742             (csound->sread.bp)->p3val =
743               (csound->sread.warp_factor) *
744               stof(csound, (csound->sread.sp));
745           else (csound->sread.bp)->p3val =
746                  stof(csound, (csound->sread.sp));
747           break;
748         default:break;
749       }
750       switch ((csound->sread.bp)->pcnt) {           /* newp2, newp3:   */
751       case 2: if ((csound->sread.warpin)) {         /* for warpin,     */
752           getpfld(csound,0);                   /*   newp2 follows */
753           (csound->sread.bp)->newp2 =
754             (csound->sread.warp_factor) *
755             stof(csound, (csound->sread.sp)) +
756             (csound->sread.clock_base);
757           (csound->sread.nxp) = (csound->sread.sp); /* (skip text)  */
758         }
759         else (csound->sread.bp)->newp2 =
760                (csound->sread.bp)->p2val;   /* else use p2val  */
761         break;
762       case 3: if ((csound->sread.warpin) &&
763                   ((csound->sread.op) == 'i' ||
764                    (csound->sread.op) == 'f')) {
765           getpfld(csound,0);                    /* same for newp3  */
766           (csound->sread.bp)->newp3 =
767             (csound->sread.warp_factor) *
768             stof(csound, (csound->sread.sp));
769           (csound->sread.nxp) = (csound->sread.sp);
770         }
771         else (csound->sread.bp)->newp3 = (csound->sread.bp)->p3val;
772         break;
773       }
774     }
775     if ((csound->sread.nocarry) &&
776         ((csound->sread.bp)->pcnt<3) &&
777         (csound->sread.op) == 'i' &&
778         ((prvbp = (csound->sread.prvibp)) != NULL ||
779          (!(csound->sread.bp)->pcnt &&
780           (prvbp = (csound->sread.bp)->prvblk) != NULL &&
781           prvbp->text[0] == 'i'))){ /* carry p1-p3 */
782       int pcnt = (csound->sread.bp)->pcnt;
783       n = 3-pcnt;
784       pcopy(csound, pcnt + 1, n, prvbp);
785       (csound->sread.bp)->pcnt = 3;
786     }
787     if ((csound->sread.op) == 'i' && !nocarry && /* then carry any rem pflds */
788         !(csound->sread.nocarry) &&
789         ((prvbp = (csound->sread.prvibp)) != NULL ||
790          (!(csound->sread.bp)->pcnt &&
791           (prvbp = (csound->sread.bp)->prvblk) != NULL &&
792           prvbp->text[0] == 'i')) &&
793         (n = prvbp->pcnt - (csound->sread.bp)->pcnt) > 0) {
794       //printf("carrying p-fields\n");
795       pcopy(csound, (int) (csound->sread.bp)->pcnt + 1, n, prvbp);
796       (csound->sread.bp)->pcnt += n;
797     }
798     *((csound->sread.nxp)-1) = LF;   /* terminate this stmnt with newline */
799 }
800 
setprv(CSOUND * csound)801 static void setprv(CSOUND *csound)      /*  set insno = (int) p1val         */
802 {                                       /*  prvibp = prv note, same insno   */
803     SRTBLK *p = (csound->sread.bp);
804     int16 n;
805 
806     if (csound->ISSTRCOD((csound->sread.bp)->p1val) &&
807         *(csound->sread.sp) == '"') {
808       /* IV - Oct 31 2002 */
809       int sign = 0;
810       char name[MAXNAME], *c, *s = (csound->sread.sp);
811       /* unquote instrument name */
812       c = name; while (*++s != '"') *c++ = *s; *c = '\0';
813       if (*name=='-') {
814         sign = 1;
815         printf("negative name %s\n", name); }
816       /* find corresponding insno */
817       if (UNLIKELY(!(n = (int16) named_instr_find(csound, name+sign)))) {
818         csound->Message(csound, Str("WARNING: instr %s not found, "
819                                     "assuming insno = -1\n"), name);
820         n = -1;
821       }
822       if (sign) n = -n;
823     }
824     else n = (int16) (csound->sread.bp)->p1val;         /* set current insno */
825     (csound->sread.bp)->insno = n;
826 
827     while ((p = p->prvblk) != NULL)
828       if (p->insno == n) {
829         (csound->sread.prvibp) = p;                     /* find prev same */
830         return;
831       }
832     (csound->sread.prvibp) = NULL;                      /*  if there is one */
833 }
834 
carryerror(CSOUND * csound)835 static void carryerror(CSOUND *csound)      /* print offending text line  */
836 {                                           /*      (partial)             */
837     char *p;
838 
839     csound->Message(csound, Str("sread: illegal use of carry, "
840                                 "  0 substituted\n"));
841     *((csound->sread.nxp) - 3) = SP;
842     p = (csound->sread.bp)->text;
843     while (p <= (csound->sread.nxp) - 2)
844       csound->Message(csound, "%c", *p++);
845     csound->Message(csound, "<=\n");
846     print_input_backtrace(csound, 1, csoundMessage);
847     *((csound->sread.nxp) - 2) = '0';
848 }
849 
pcopy(CSOUND * csound,int pfno,int ncopy,SRTBLK * prvbp)850 static void pcopy(CSOUND *csound, int pfno, int ncopy, SRTBLK *prvbp)
851                                 /* cpy pfields from prev note of this instr */
852                                 /*     begin at pfno, copy 'ncopy' fields   */
853                                 /*     uses *nxp++;    sp untouched         */
854 {
855     char *p, *pp, c;
856     int  n;
857 
858     pp = prvbp->text;                       /* in text of prev note,    */
859     n = pfno;
860     while (n--)
861       while (*pp++ != SP)                   /*    locate starting pfld  */
862         ;
863     n = ncopy;
864     p = (csound->sread.nxp);
865     while (n--) {                           /*      and copy n pflds    */
866       if (*pp != '"')
867         while ((*p++ = c = *pp++) != SP && c != LF)
868           ;
869       else {
870         *p++ = *pp++;
871         while ((*p++ = *pp++) != '"')
872           ;
873         *p++ = *pp++;
874       }
875       switch (pfno) {
876       case 1: (csound->sread.bp)->p1val = prvbp->p1val;       /*  with p1-p3 vals */
877         setprv(csound);
878         break;
879       case 2:
880         if (*(p-2) == '+')              /* (interpr . of +) */
881           (csound->sread.prvp2) =
882             (csound->sread.bp)->p2val = prvbp->p2val + FABS(prvbp->p3val);
883         else (csound->sread.prvp2) = (csound->sread.bp)->p2val = prvbp->p2val;
884         (csound->sread.bp)->newp2 = (csound->sread.bp)->p2val;
885         break;
886       case 3: (csound->sread.bp)->newp3 = (csound->sread.bp)->p3val = prvbp->p3val;
887         break;
888       default:
889         break;
890       }
891       (csound->sread.bp)->lineno = prvbp->lineno;
892       pfno++;
893     }
894     (csound->sread.nxp) = p;            /*          adjust globl nxp pntr */
895 }
896 
salcinit(CSOUND * csound)897 static void salcinit(CSOUND *csound)
898 {                             /* init the sorter mem space for a new section */
899     if (csound->sread.curmem == NULL) { /*  alloc 1st memblk if nec;
900                                             init *nxp to this */
901       (csound->sread.curmem) =
902         (char*) csound->Calloc(csound, (size_t) (MEMSIZ + MARGIN));
903       (csound->sread.memend) = (char*) (csound->sread.curmem) + MEMSIZ;
904     }
905     (csound->sread.nxp) = (char*) (csound->sread.curmem);
906 }
907 
salcblk(CSOUND * csound)908 static void salcblk(CSOUND *csound)
909 {                               /* alloc a srtblk from current mem space:   */
910     SRTBLK  *prvbp;             /*   align following *nxp, set new bp, nxp  */
911                                 /*   set srtblk lnks, put op+blank in text  */
912     if (csound->sread.nxp >= csound->sread.memend) /* if this memblk exhausted */
913       expand_nxp(csound);
914     /* now allocate a srtblk from this space: */
915     prvbp = (csound->sread.bp);
916     (csound->sread.bp) =
917       (SRTBLK*) (((uintptr_t) csound->sread.nxp + (uintptr_t)7) & ~((uintptr_t)7));
918     if (csound->frstbp == NULL)
919       csound->frstbp = (csound->sread.bp);
920     if (prvbp != NULL)
921       prvbp->nxtblk = (csound->sread.bp); /* link with prev srtblk        */
922     (csound->sread.bp)->nxtblk = NULL;
923     (csound->sread.bp)->prvblk = prvbp;
924     (csound->sread.bp)->insno = 0;
925     (csound->sread.bp)->pcnt = 0;
926     (csound->sread.bp)->lineno = (csound->sread.lincnt);
927     (csound->sread.nxp) = &((csound->sread.bp)->text[0]);
928     *(csound->sread.nxp)++ = (csound->sread.op); /* place op, blank into text    */
929     *(csound->sread.nxp)++ = SP;
930     *(csound->sread.nxp) = '\0';
931 }
932 
sfree(CSOUND * csound)933 void sfree(CSOUND *csound)       /* free all sorter allocated space */
934 {                                /*    called at completion of sort */
935     /* sread_alloc_globals(csound); */
936     if ((csound->sread.curmem) != NULL) {
937       csound->Free(csound, (csound->sread.curmem));
938       (csound->sread.curmem) = NULL;
939     }
940     while ((csound->sread.str) != &(csound->sread.inputs)[0]) {
941       //corfile_rm(&((csound->sread.str)->cf));
942       (csound->sread.str)--;
943     }
944     corfile_rm(csound, &(csound->scorestr));
945 }
946 
flushlin(CSOUND * csound)947 static void flushlin(CSOUND *csound)
948 {                                   /* flush input to end-of-line; inc lincnt */
949     int c;
950     while ((c = getscochar(csound, 0)) != LF && c != EOF)
951       ;
952     (csound->sread.linpos) = 0;
953     (csound->sread.lincnt)++;
954 }
955 
956 /* unused at the moment
957 static inline int check_preproc_name(CSOUND *csound, const char *name)
958 {
959     int   i;
960     char  c;
961     for (i = 1; name[i] != '\0'; i++) {
962       c = (char) getscochar(csound, 1);
963       if (c != name[i])
964         return 0;
965     }
966     return 1;
967 }
968 */
969 
sget1(CSOUND * csound)970 static int sget1(CSOUND *csound)    /* get first non-white, non-comment char */
971 {
972     int c;
973 
974     //srch:
975     while (isblank(c = getscochar(csound, 1)) || c == LF)
976       if (c == LF) {
977         (csound->sread.lincnt)++;
978         (csound->sread.linpos) = 0;
979       }
980     /* Can never be ; from lexer, could do c in lexer *\/ */
981     /* if (c == ';' || c == 'c') { */
982     /*   flushlin(csound); */
983     /*   goto srch; */
984     /* } */
985     //printf("***Next non white: %c(%.2x)\n", c, c);
986     return c;
987 }
988 
getop(CSOUND * csound)989 static int getop(CSOUND *csound)        /* get next legal opcode */
990 {
991     int c;
992 
993  nextc:
994     c = sget1(csound);  /* get first active char */
995 
996     switch (c) {        /*   and check legality  */
997     case 'a':           /* Advance time */
998     case 'b':           /* Reset base clock */
999     case 'B':           /* Reset base clock accumulative*/
1000     case 'd':           /* De-note */
1001     case 'C':           /* toggle carry flag */
1002     case 'e':           /* End of all */
1003     case 'f':           /* f-table */
1004     case 'i':           /* Instrument */
1005     case 'm':           /* Mark this point */
1006     case 'n':           /* Duplicate from named position */
1007     case 'q':           /* quiet instrument ie mute */
1008     case 'r':           /* Repeated section */
1009     case 's':           /* Section */
1010     case 't':           /* time warp */
1011     case 'v':           /* Local warping */
1012     case 'w':
1013     case 'x':
1014     case 'y':           /* Set random seed */
1015     case '{':           /* Section brackets */
1016     case '}':
1017     case EOF:
1018       break;            /* if ok, go with it    */
1019     default:            /*   else complain      */
1020       sreaderr(csound, Str("illegal opcode %c"), c);
1021       csound->Message(csound,Str("      remainder of line flushed\n"));
1022       flushlin(csound);
1023       goto nextc;
1024     }
1025     (csound->sread.linpos)++;
1026     return(c);
1027 }
1028 
read_expression(CSOUND * csound)1029 static MYFLT read_expression(CSOUND *csound)
1030 {
1031       char  stack[30];
1032       MYFLT vv[30];
1033       char  *op = stack - 1;
1034       MYFLT *pv = vv - 1;
1035       char  buffer[100];
1036       int   i, c;
1037       int   type = 0;  /* 1 -> expecting binary operator,')', or ']'; else 0 */
1038       *++op = '[';
1039       c = getscochar(csound, 1);
1040       do {
1041         //printf("read_expression: c=%c\n", c);
1042         switch (c) {
1043         case '0': case '1': case '2': case '3': case '4':
1044         case '5': case '6': case '7': case '8': case '9':
1045         case '.':
1046           if (UNLIKELY(type)) {
1047             scorerr(csound, Str("illegal placement of number in [] "
1048                                 "expression"));
1049           }
1050  parseNumber:
1051           i = 0;
1052           do {
1053             buffer[i++] = c;
1054             c = getscochar(csound, 1);
1055           } while (isdigit(c) || c == '.');
1056           if (c == 'e' || c == 'E') {
1057             buffer[i++] = c;
1058             c = getscochar(csound, 1);
1059             if (c == '+' || c == '-') {
1060               buffer[i++] = c;
1061               c = getscochar(csound, 1);
1062             }
1063             while (isdigit(c)) {
1064               buffer[i++] = c;
1065               c = getscochar(csound, 1);
1066             }
1067           }
1068           buffer[i] = '\0';
1069           //printf("****>>%s<<\n", buffer);
1070           *++pv = stof(csound, buffer);
1071           type = 1;
1072           break;
1073         case '~':
1074           if (UNLIKELY(type)) {
1075             scorerr(csound, Str("illegal placement of operator ~ in [] "
1076                                 "expression"));
1077           }
1078           *++pv = (MYFLT) (csound->Rand31(&(csound->randSeed1)) - 1)
1079                   / FL(2147483645);
1080           type = 1;
1081           c = getscochar(csound, 1);
1082           break;
1083         case '@':
1084           if (UNLIKELY(type)) {
1085             scorerr(csound, Str("illegal placement of operator @ or @@ in"
1086                                 " [] expression"));
1087           }
1088           {
1089             int n = 0;
1090             int k = 0;          /* 0 or 1 depending on guard bit */
1091             c = getscochar(csound, 1);
1092             if (c=='@') { k = 1; c = getscochar(csound, 1);}
1093             while (isdigit(c)) {
1094               n = 10*n + c - '0';
1095               c = getscochar(csound, 1);
1096             }
1097             i = 1;
1098             while (i<=n-k && i< 0x4000000) i <<= 1;
1099             *++pv = (MYFLT)(i+k);
1100             type = 1;
1101           }
1102           break;
1103         case '+': case '-':
1104           if (!type)
1105             goto parseNumber;
1106           if (*op != '[' && *op != '(') {
1107             MYFLT v = operate(csound, *(pv-1), *pv, *op);
1108             op--; pv--;
1109             *pv = v;
1110           }
1111           type = 0;
1112           *++op = c; c = getscochar(csound, 1); break;
1113         case '*':
1114         case '/':
1115         case '%':
1116           if (UNLIKELY(!type)) {
1117             scorerr(csound, Str("illegal placement of operator %c in [] "
1118                                 "expression"), c);
1119           }
1120           if (*op == '*' || *op == '/' || *op == '%') {
1121             MYFLT v = operate(csound, *(pv-1), *pv, *op);
1122             op--; pv--;
1123             *pv = v;
1124           }
1125           type = 0;
1126           *++op = c; c = getscochar(csound, 1); break;
1127         case '&':
1128         case '|':
1129         case '#':
1130           if (UNLIKELY(!type)) {
1131             scorerr(csound, Str("illegal placement of operator %c in [] "
1132                                 "expression"), c);
1133           }
1134           if (*op == '|' || *op == '&' || *op == '#') {
1135             MYFLT v = operate(csound, *(pv-1), *pv, *op);
1136             op--; pv--;
1137             *pv = v;
1138           }
1139           type = 0;
1140           *++op = c; c = getscochar(csound, 1); break;
1141         case '(':
1142           if (UNLIKELY(type)) {
1143             scorerr(csound, Str("illegal placement of '(' in [] expression"));
1144           }
1145           type = 0;
1146           *++op = c; c = getscochar(csound, 1); break;
1147         case ')':
1148           if (UNLIKELY(!type)) {
1149             scorerr(csound, Str("missing operand before ')' in [] expression"));
1150           }
1151           while (*op != '(') {
1152             MYFLT v = operate(csound, *(pv-1), *pv, *op);
1153             op--; pv--;
1154             *pv = v;
1155           }
1156           type = 1;
1157           op--; c = getscochar(csound, 1); break;
1158         case '^':
1159           type = 0;
1160           *++op = c; c = getscochar(csound, 1); break;
1161         case '[':
1162           if (UNLIKELY(type)) {
1163             scorerr(csound, Str("illegal placement of '[' in [] expression"));
1164           }
1165           type = 1;
1166           {
1167             //int i;
1168             MYFLT x;
1169             //for (i=0;i<=pv-vv;i++) printf(" %lf ", vv[i]);
1170             //printf("| %d\n", pv-vv);
1171             x = read_expression(csound);
1172             *++pv = x;
1173             //printf("recursion gives %lf (%lf)\n", x,*(pv-1));
1174             //for (i=0;i<pv-vv;i++) printf(" %lf ", vv[i]); printf("| %d\n", pv-vv);
1175             c = getscochar(csound, 1); break;
1176           }
1177         case ']':
1178           if (UNLIKELY(!type)) {
1179             scorerr(csound, Str("missing operand before closing bracket in []"));
1180           }
1181           while (*op != '[') {
1182             MYFLT v = operate(csound, *(pv-1), *pv, *op);
1183             op--; pv--;
1184             *pv = v;
1185           }
1186           //printf("done ]*** *op=%c v=%lg (%c)\n", *op, *pv, c);
1187           //getscochar(csound, 1);
1188           c = '$'; return *pv;
1189         case '$':
1190           break;
1191         case ' ':               /* Ignore spaces */
1192           c = getscochar(csound, 1);
1193           continue;
1194         default:
1195           scorerr(csound, Str("illegal character %c(%.2x) in [] expression"),
1196                   c, c);
1197         }
1198       } while (c != '$');
1199       return *pv;
1200 }
1201 
1202 
getpfld(CSOUND * csound,int type)1203 static int getpfld(CSOUND *csound, int type) /* get pfield val from SCOREIN file */
1204 {                                            /*      set sp, nxp                 */
1205     int  c;
1206     char *p;
1207 
1208     if ((c = sget1(csound)) == EOF)     /* get 1st non-white,non-comment c  */
1209       return(0);
1210     if (c=='[') {
1211       MYFLT xx = read_expression(csound);
1212       //printf("****xx=%a\n", xx);
1213       //printf("nxp = %p\n", (csound->sread.nxp));
1214       snprintf((csound->sread.sp) = (csound->sread.nxp), 28, "%a$", xx);
1215       p = strchr((csound->sread.sp),'$');
1216       goto blank;
1217     }
1218 
1219                     /* if non-numeric, and non-carry, and non-special-char: */
1220     /*    if (strchr("0123456789.+-^np<>()\"~!", c) == NULL) { */
1221     if (!isdigit(c) && (type || (c!='.' && c!='+' && c!='-' && c!='^' && c!='n'
1222                                  && c!='p' && c!='<' && c!='>' && c!='(' && c!=')'
1223                                  && c!='"' && c!='~' && c!='!' && c!='z'))) {
1224       ungetscochar(csound, c);                /* then no more pfields    */
1225       if (UNLIKELY((csound->sread.linpos))) {
1226         sreaderr(csound, Str("unexpected char %c"), c);
1227         csound->Message(csound, Str("      remainder of line flushed\n"));
1228         flushlin(csound);
1229       }
1230       return(0);                              /*    so return            */
1231     }
1232     p = (csound->sread.sp) = (csound->sread.nxp); /* else start copying to text */
1233     *p++ = c;
1234     (csound->sread.linpos)++;
1235     if (c == '"') {                           /* if have quoted string,  */
1236       /* IV - Oct 31 2002: allow string instr name for i and q events */
1237       if (UNLIKELY((csound->sread.bp)->pcnt < 3 &&
1238           !(((csound->sread.op) == 'i' ||
1239              (csound->sread.op) == 'd' || (csound->sread.op) == 'q') &&
1240             !(csound->sread.bp)->pcnt))) {
1241         sreaderr(csound, Str("illegally placed string"));
1242         csound->Message(csound, Str("      remainder of line flushed\n"));
1243         flushlin(csound);
1244         return(0);
1245       }
1246       while ((c = getscochar(csound, 1)) != '"') {
1247         if (UNLIKELY(c == LF || c == EOF)) {
1248           sreaderr(csound, Str("unmatched quote"));
1249           return(0);
1250         }
1251         *p++ = c;                       /*   copy to matched quote */
1252         if (c=='\\') {
1253           *p++ = getscochar(csound, 1);
1254           //          printf("escaped %c\n", *(p-1));
1255         }
1256         /* **** CHECK **** */
1257         if (p >= (csound->sread.memend))
1258           p = (char*) ((uintptr_t) p + expand_nxp(csound));
1259         /* **** END CHECK **** */
1260       }
1261       *p++ = c;
1262       goto blank;
1263     }
1264     while (1) {
1265       c = getscochar(csound, 1);
1266       /* else while legal chars, continue to bld string */
1267       /*      if (strchr("0123456789.+-eEnp<>()~", c) != NULL) { */
1268       if (isdigit(c) || c=='.' || c=='+' || c=='-' || c=='e' ||
1269           c=='E' || c=='n' || c=='p' || c=='<' || c=='>' || c=='(' ||
1270           c==')' || c=='~' || c=='z') {
1271         *p++ = c;
1272         /* **** CHECK **** */
1273         if (p >= (csound->sread.memend))
1274           p = (char*) ((uintptr_t) p + expand_nxp(csound));
1275         /* **** END CHECK **** */
1276       }
1277       else {                                /* any illegal is delimiter */
1278         ungetscochar(csound, c);
1279         break;
1280       }
1281     }
1282  blank:
1283     *p++ = SP;
1284     (csound->sread.nxp) = p;                            /*  add blank      */
1285     return(1);                              /*  and report ok  */
1286 }
1287 
stof(CSOUND * csound,char s[])1288 MYFLT stof(CSOUND *csound, char s[])            /* convert string to MYFLT  */
1289                                     /* (assumes no white space at beginning */
1290 {                                   /*      but a blank or nl at end)       */
1291     char    *p;
1292     MYFLT   x = (MYFLT) cs_strtod(s, &p);
1293     if (*p=='z') return FL(800000000000.0); /* 25367 years */
1294     if (UNLIKELY(s == p || !(*p == '\0' || isspace(*p)))) {
1295       csound->Message(csound, Str("sread: illegal number format:  "));
1296       p = s;
1297       while (!(*p == '\0' || isspace(*p))) {
1298         csound->Message(csound, "%c", *p);
1299         *p++ = '0';
1300       }
1301       csound->Message(csound,Str("   zero substituted.\n"));
1302       print_input_backtrace(csound, 1, csoundMessage);
1303       return FL(0.0);
1304     }
1305     return x;
1306 }
1307