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