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