1 /*
2 rdscor.c:
3
4 Copyright (C) 2011 John ffitch (after Barry Vercoe)
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" /* RDSCORSTR.C */
25 #include "corfile.h"
26 #include "insert.h"
27
get_arg_string(CSOUND * csound,MYFLT p)28 char* get_arg_string(CSOUND *csound, MYFLT p)
29 {
30 int32 n;
31 char *ss;
32 INSDS* ip = csound->ids->insdshead;
33 while (ip->opcod_iobufs != NULL) {
34 ip = ((OPCOD_IOBUFS*)ip->opcod_iobufs)->parent_ip;
35 }
36 ss = ip->strarg; /* look at this instr's strarg */
37
38 {
39 union {
40 MYFLT d;
41 int32 i;
42 } ch;
43 ch.d = p; n = ch.i&0xffff;
44 while (n-- > 0) {
45 ss += strlen(ss)+1;
46 }
47 }
48 return ss;
49 }
50
51 static void dumpline(CSOUND *);
52
flushline(CSOUND * csound)53 static void flushline(CSOUND *csound) /* flush scorefile to next newline */
54 {
55 int c;
56 while ((c = corfile_getc(csound->scstr)) != '\0' && c != '\n')
57 ;
58 }
59
scanflt(CSOUND * csound,MYFLT * pfld)60 static int scanflt(CSOUND *csound, MYFLT *pfld)
61 { /* read a MYFLT from scorefile; return 1 if OK, else 0 */
62 int c;
63
64 while ((c = corfile_getc(csound->scstr)) == ' ' ||
65 c == '\t') /* skip leading white space */
66 ;
67 if (UNLIKELY(c == ';')) { /* Comments terminate line */
68 flushline(csound);
69 return 0;
70 }
71 if (c == '"') { /* if find a quoted string */
72 char *sstrp;
73 int n = csound->scnt;
74 if ((sstrp = csound->sstrbuf) == NULL)
75 sstrp = csound->sstrbuf = csound->Malloc(csound, csound->strsiz=SSTRSIZ);
76 while (n--!=0) sstrp += strlen(sstrp)+1;
77 n = sstrp-csound->sstrbuf;
78 while ((c = corfile_getc(csound->scstr)) != '"') {
79 if (c=='\\') { c = corfile_getc(csound->scstr);
80 switch (c) {
81 case '"': c = '"'; break;
82 case '\'': c = '\''; break;
83 case '\\': c = '\\'; break;
84 case 'a': c = '\a'; break;
85 case 'b': c = '\b'; break;
86 case 'f': c = '\f'; break;
87 case 'n': c = '\n'; break;
88 case 'r': c = '\r'; break;
89 case 't': c = '\t'; break;
90 case 'v': c = '\v'; break;
91 }
92 }
93 *sstrp++ = c;
94 n++;
95 if (n > csound->strsiz-10) {
96 csound->sstrbuf = csound->ReAlloc(csound, csound->sstrbuf,
97 csound->strsiz+=SSTRSIZ);
98 sstrp = csound->sstrbuf+n;
99 }
100 }
101 *sstrp++ = '\0';
102 {
103 union {
104 MYFLT d;
105 int32 i;
106 } ch;
107 ch.d = SSTRCOD; ch.i += csound->scnt++;
108 *pfld = ch.d; /* set as string with count */
109 }
110 csound->sstrlen = sstrp - csound->sstrbuf; /* & overall length */
111 //printf("csound->sstrlen = %d\n", csound->sstrlen);
112 return(1);
113 }
114 if (UNLIKELY(!((c>='0' && c<='9') || c=='+' || c=='-' || c=='.'))) {
115 corfile_ungetc(csound->scstr);
116 csound->Message(csound,
117 Str("ERROR: illegal character %c(%.2x) in scoreline: "),
118 c, c);
119 dumpline(csound);
120 return(0);
121 }
122 corfile_ungetc(csound->scstr);
123 {
124 MYFLT ans = corfile_get_flt(csound->scstr);
125 *pfld = ans;
126 //printf("%s(%d):%lf %lf\n", __FILE__, __LINE__, ans, *pfld);
127 }
128 return(1);
129 }
130
dumpline(CSOUND * csound)131 static void dumpline(CSOUND *csound) /* print the line while flushing it */
132 {
133 int c;
134 while ((c = corfile_getc(csound->scstr)) != '\0' && c != '\n') {
135 csound->Message(csound, "%c", c);
136 }
137 csound->Message(csound, Str("\n\tremainder of line flushed\n"));
138 }
139
rdscor(CSOUND * csound,EVTBLK * e)140 int rdscor(CSOUND *csound, EVTBLK *e) /* read next score-line from scorefile */
141 /* & maintain section warped status */
142 { /* presumes good format if warped */
143 MYFLT *pp, *plim;
144 int c;
145
146 e->pinstance = NULL;
147 if (csound->scstr == NULL ||
148 csound->scstr->body[0] == '\0') { /* if no concurrent scorefile */
149 e->opcod = 'f'; /* return an 'f 0 3600' */
150 e->p[1] = FL(0.0);
151 e->p[2] = FL(INF);
152 e->p2orig = FL(INF);
153 e->pcnt = 2;
154
155 return(1);
156 }
157
158 /* else read the real score */
159 while ((c = corfile_getc(csound->scstr)) != '\0') {
160 csound->scnt = 0;
161 switch (c) {
162 case ' ':
163 case '\t':
164 case '\n':
165 continue; /* skip leading white space */
166 case ';':
167 flushline(csound);
168 continue;
169 case 's':
170 case 't':
171 case 'y':
172 csound->warped = 0;
173 goto unwarped;
174 case 'w':
175 csound->warped = 1; /* w statement is itself unwarped */
176 unwarped: e->opcod = c; /* UNWARPED scorefile: */
177 pp = &e->p[0];
178 plim = &e->p[PMAX]; /* caution, irregular format */
179 while (1) {
180 while ((c = corfile_getc(csound->scstr))==' ' ||
181 c=='\t'); /* eat whitespace */
182 if (c == ';') { flushline(csound); break; } /* comments? skip */
183 if (c == '\n' || c == '\0') break; /* newline? done */
184 corfile_ungetc(csound->scstr); /* pfld: back up */
185 if (!scanflt(csound, ++pp)) break; /* & read value */
186 if (UNLIKELY(pp >= plim)) {
187 csound->Message(csound, Str("ERROR: too many pfields: "));
188 dumpline(csound);
189 break;
190 }
191 }
192 e->p2orig = e->p[2]; /* now go count the pfields */
193 e->p3orig = e->p[3];
194 e->c.extra = NULL;
195 goto setp;
196 case 'e':
197 e->opcod = c;
198 e->pcnt = 0;
199 return(1);
200 case EOF: /* necessary for cscoreGetEvent */
201 return(0);
202 default: /* WARPED scorefile: */
203 if (!csound->warped) goto unwarped;
204 e->opcod = c; /* opcod */
205 csound->Free(csound, e->c.extra);
206 e->c.extra = NULL;
207 pp = &e->p[0];
208 plim = &e->p[PMAX];
209 if (corfile_getc(csound->scstr) != '\n' &&
210 scanflt(csound, ++pp)) /* p1 */
211 if (corfile_getc(csound->scstr) != '\n' &&
212 scanflt(csound, &e->p2orig)) /* p2 orig */
213 if (corfile_getc(csound->scstr) != '\n' &&
214 scanflt(csound, ++pp)) /* p2 warp */
215 if (corfile_getc(csound->scstr) != '\n' &&
216 scanflt(csound, &e->p3orig)) /* p3 */
217 if (corfile_getc(csound->scstr) != '\n' &&
218 scanflt(csound, ++pp)) /* p3 warp */
219 while (corfile_getc(csound->scstr) != '\n' &&
220 scanflt(csound, ++pp))
221 /* p4.... */
222 if (pp >= plim) {
223 MYFLT *new;
224 MYFLT *q;
225 int c=1;
226 csound->DebugMsg(csound, "Extra p-fields (%d %d %d %d)\n",
227 (int)e->p[1],(int)e->p[2],
228 (int)e->p[3],(int)e->p[4]);
229 new = (MYFLT*) csound->Malloc(csound, sizeof(MYFLT)*PMAX);
230 if (UNLIKELY(new==NULL)) {
231 fprintf(stderr, Str("Out of Memory\n"));
232 exit(7);
233 }
234 e->c.extra = new;
235 e->c.extra[0] = PMAX-2;
236 e->c.extra[1] = *pp;
237 q = &e->c.extra[1];
238 while ((corfile_getc(csound->scstr) != '\n') &&
239 (scanflt(csound, &q[c++]))) {
240 if (c+1 >= (int) e->c.extra[0]) {
241 int size = (int)e->c.extra[0]+PMAX;
242 /* printf("last values(%p): %f %f %f\n", */
243 /* q, q[c-3], q[c-2], q[c-1]); */
244 csound->DebugMsg(csound,
245 "and more extra p-fields [%d](%d)%d\n",
246 c, (int) e->c.extra[0],
247 (int)sizeof(MYFLT)*
248 ((int)e->c.extra[0]+PMAX));
249 new =
250 (MYFLT *) csound->ReAlloc(csound,
251 e->c.extra,
252 sizeof(MYFLT)*size);
253 if (new==NULL) {
254 fprintf(stderr, "Out of Memory\n");
255 exit(7);
256 }
257 new[0] = size;
258 e->c.extra = new; q = &new[1];
259 /* printf("%p(%d) values: %f %f %f\n", (int)new[0], */
260 /* q, q[c-3], q[c-2], q[c-1]); */
261 }
262 }
263 e->c.extra[0] = c;
264 /* flushline(csound); */
265 goto setp;
266 }
267 setp:
268 if (!csound->csoundIsScorePending_ && e->opcod == 'i') {
269 /* FIXME: should pause and not mute */
270 csound->sstrlen = 0;
271 e->opcod = 'f'; e->p[1] = FL(0.0); e->pcnt = 2; e->scnt = 0;
272 return 1;
273 }
274 e->pcnt = pp - &e->p[0]; /* count the pfields */
275 if (UNLIKELY(e->pcnt>=PMAX))
276 e->pcnt += e->c.extra[0]; /* and overflow fields */
277 if (csound->sstrlen) { /* if string arg present, save it */
278 e->strarg = csound->sstrbuf; csound->sstrbuf = NULL;
279 e->scnt = csound->scnt;
280 csound->sstrlen = 0;
281 }
282 else { e->strarg = NULL; e->scnt = 0; } /* is this necessary?? */
283 return 1;
284 }
285 }
286 corfile_rm(csound, &(csound->scstr));
287 return 0;
288 }
289