1 /*
2     goto_ops.c:
3 
4     Copyright (C) 1991, 1997, 1999, 2002, 2005
5     Barry Vercoe, Istvan Varga, John ffitch,
6     Gabriel Maldonado, matt ingalls
7 
8     This file is part of Csound.
9 
10     The Csound Library is free software; you can redistribute it
11     and/or modify it under the terms of the GNU Lesser General Public
12     License as published by the Free Software Foundation; either
13     version 2.1 of the License, or (at your option) any later version.
14 
15     Csound is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU Lesser General Public License for more details.
19 
20     You should have received a copy of the GNU Lesser General Public
21     License along with Csound; if not, write to the Free Software
22     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23     02110-1301 USA
24 */
25 
26 #include "csoundCore.h" /*                            GOTO_OPS.C        */
27 #include "insert.h"     /* for goto's */
28 #include "aops.h"       /* for cond's */
29 extern int32_t strarg2insno(CSOUND *, void *p, int32_t is_string);
30 
igoto(CSOUND * csound,GOTO * p)31 int32_t igoto(CSOUND *csound, GOTO *p)
32 {
33     csound->ids = p->lblblk->prvi;
34     return OK;
35 }
36 
kgoto(CSOUND * csound,GOTO * p)37 int32_t kgoto(CSOUND *csound, GOTO *p)
38 {
39     IGN(csound);
40     CS_PDS = p->lblblk->prvp;
41     return OK;
42 }
43 
icgoto(CSOUND * csound,CGOTO * p)44 int32_t icgoto(CSOUND *csound, CGOTO *p)
45 {
46     if (*p->cond)
47       csound->ids = p->lblblk->prvi;
48     return OK;
49 }
50 
kcgoto(CSOUND * csound,CGOTO * p)51 int32_t kcgoto(CSOUND *csound, CGOTO *p)
52 {
53     IGN(csound);
54     if (*p->cond)
55       CS_PDS = p->lblblk->prvp;
56 
57     return OK;
58 }
59 
60 /* an 'if-then' variant of 'if-goto' */
ingoto(CSOUND * csound,CGOTO * p)61 int32_t ingoto(CSOUND *csound, CGOTO *p)
62 {
63     /* Make sure we have an i-time conditional */
64     if (p->h.optext->t.intype == 'b' && !*p->cond)
65       csound->ids = p->lblblk->prvi;
66     return OK;
67 }
68 
kngoto(CSOUND * csound,CGOTO * p)69 int32_t kngoto(CSOUND *csound, CGOTO *p)
70 {
71     IGN(csound);
72     if (!*p->cond)
73       CS_PDS = p->lblblk->prvp;
74     return OK;
75 }
76 
timset(CSOUND * csound,TIMOUT * p)77 int32_t timset(CSOUND *csound, TIMOUT *p)
78 {
79     if (UNLIKELY((p->cnt1 = (int32_t)(*p->idel * CS_EKR + FL(0.5))) < 0L ||
80                  (p->cnt2 = (int32_t)(*p->idur * CS_EKR + FL(0.5))) < 0L))
81       return csoundInitError(csound, Str("negative time period"));
82     return OK;
83 }
84 
timout(CSOUND * csound,TIMOUT * p)85 int32_t timout(CSOUND *csound, TIMOUT *p)
86 {
87     IGN(csound);
88     if (p->cnt1)                            /* once delay has expired, */
89       p->cnt1--;
90     else if (--p->cnt2 >= 0L)               /*  br during idur countdown */
91       CS_PDS = p->lblblk->prvp;
92     return OK;
93 }
94 
rireturn(CSOUND * csound,LINK * p)95 int32_t rireturn(CSOUND *csound, LINK *p)
96 {
97     IGN(p);
98     IGN(csound);
99     return OK;
100 }
101 
reinit(CSOUND * csound,GOTO * p)102 int32_t reinit(CSOUND *csound, GOTO *p)
103 {
104     csound->reinitflag = p->h.insdshead->reinitflag = 1;
105     if (csound->oparms->realtime == 0) {
106       csound->curip = p->h.insdshead;
107       csound->ids = p->lblblk->prvi;        /* now, despite ANSI C warning:  */
108       while ((csound->ids = csound->ids->nxti) != NULL &&
109              (csound->ids->iopadr != (SUBR) rireturn))
110         (*csound->ids->iopadr)(csound, csound->ids);
111       csound->reinitflag = p->h.insdshead->reinitflag = 0;
112     }
113     else {
114       uint64_t wp = csound->alloc_queue_wp;
115       ATOMIC_SET(p->h.insdshead->init_done, 0);
116       ATOMIC_SET8(p->h.insdshead->actflg, 0);
117       csound->alloc_queue[wp].ip = p->h.insdshead;
118       csound->alloc_queue[wp].ids = p->lblblk->prvi;
119       csound->alloc_queue[wp].type = 3;
120       csound->alloc_queue_wp = wp + 1 < MAX_ALLOC_QUEUE ? wp + 1 : 0;
121       ATOMIC_INCR(csound->alloc_queue_items);
122       return NOTOK;
123     }
124     return OK;
125 }
126 
rigoto(CSOUND * csound,GOTO * p)127 int32_t rigoto(CSOUND *csound, GOTO *p)
128 {
129     if (p->h.insdshead->reinitflag)
130       csound->ids = p->lblblk->prvi;
131     return OK;
132 }
133 
tigoto(CSOUND * csound,GOTO * p)134 int32_t tigoto(CSOUND *csound, GOTO *p)     /* I-time only, NOP at reinit */
135 {
136     if (p->h.insdshead->tieflag && !p->h.insdshead->reinitflag)
137       csound->ids = p->lblblk->prvi;
138     return OK;
139 }
140 
tival(CSOUND * csound,EVAL * p)141 int32_t tival(CSOUND *csound, EVAL *p)      /* I-time only, NOP at reinit */
142 {
143     IGN(csound);
144     if (!p->h.insdshead->reinitflag)
145       *p->r = p->h.insdshead->tieflag;
146     /* *p->r = (csound->tieflag ? FL(1.0) : FL(0.0)); */
147     return OK;
148 }
149 
ihold(CSOUND * csound,LINK * p)150 int32_t ihold(CSOUND *csound, LINK *p)  /* make this note indefinit duration */
151 {                                       /* called by ihold statmnt at Itime  */
152     IGN(csound);
153     if (!p->h.insdshead->reinitflag) {  /* no-op at reinit                   */
154       csound->curip->offbet = -1.0;
155       csound->curip->offtim = -1.0;
156     }
157     return OK;
158 }
159 
turnoff(CSOUND * csound,LINK * p)160 int32_t turnoff(CSOUND *csound, LINK *p)/* terminate the current instrument  */
161 {                                       /* called by turnoff statmt at Ptime */
162     IGN(csound);
163     INSDS *current = p->h.insdshead;
164     INSDS *lcurip = p->h.insdshead;
165     if (lcurip->actflg) {
166     /* IV - Oct 16 2002: check for subinstr and user opcode */
167     /* find top level instrument instance */
168       while (lcurip->opcod_iobufs)
169         lcurip = ((OPCOD_IOBUFS*) lcurip->opcod_iobufs)->parent_ip;
170       xturnoff(csound, lcurip);
171       if (current->xtratim <= 0) {
172         OPDS* curOp = current->pds;
173         while (curOp->nxtp != NULL)
174           curOp = curOp->nxtp;                /* loop to last opds */
175         current->pds = curOp;
176       }
177     }
178     return OK;
179 }
180 
181 /* turnoff2 opcode */
turnoff2(CSOUND * csound,TURNOFF2 * p,int32_t isStringArg)182 int32_t turnoff2(CSOUND *csound, TURNOFF2 *p, int32_t isStringArg)
183 {
184     MYFLT p1;
185     INSDS *ip, *ip2, *nip;
186     int32_t   mode, insno, allow_release;
187 
188     if (isStringArg) {
189       p1 = (MYFLT) strarg2insno(csound, ((STRINGDAT *)p->kInsNo)->data, 1);
190     }
191     else if (csound->ISSTRCOD(*p->kInsNo)) {
192       p1 = (MYFLT) strarg2insno(csound, get_arg_string(csound, *p->kInsNo), 1);
193     }
194     else p1 = *(p->kInsNo);
195 
196     if (p1 <= FL(0.0))
197       return OK;    /* not triggered */
198 
199     insno = (int32_t) p1;
200     if (UNLIKELY(insno < 1 || insno > (int32_t) csound->engineState.maxinsno ||
201                  csound->engineState.instrtxtp[insno] == NULL)) {
202       return csoundPerfError(csound, &(p->h),
203                              Str("turnoff2: invalid instrument number"));
204     }
205     mode = (int32_t) (*(p->kFlags) + FL(0.5));
206     allow_release = (*(p->kRelease) == FL(0.0) ? 0 : 1);
207     if (UNLIKELY(mode < 0 || mode > 15 || (mode & 3) == 3)) {
208       return csoundPerfError(csound, &(p->h),
209                              Str("turnoff2: invalid mode parameter"));
210     }
211     ip = &(csound->actanchor);
212     ip2 = NULL;
213 /*     if ((mode & 4) && !ip->p1){ */
214 /*       return csoundPerfError(csound, &(p->h), */
215 /*                              Str("turnoff2: invalid instrument number")); */
216 /*     }   */
217     while ((ip = ip->nxtact) != NULL && (int32_t) ip->insno != insno);
218     if (ip == NULL)
219       return OK;
220     do {                        /* This loop does not terminate in mode=0 */
221       nip = ip->nxtact;
222       if (((mode & 8) && ip->offtim >= 0.0) ||
223           ((mode & 4) && ip->p1.value != p1) ||
224           (allow_release && ip->relesing)) {
225         ip = nip;
226         continue;
227       }
228       if (!(mode & 3)) {
229         if (allow_release) {
230           xturnoff(csound, ip);
231         }
232         else {
233           nip = ip->nxtact;
234           xturnoff_now(csound, ip);
235         }
236       }
237       else {
238         ip2 = ip;
239         if ((mode & 3) == 1)
240           break;
241       }
242       ip = nip;
243     } while (ip != NULL && (int32_t) ip->insno == insno);
244     if (ip2 != NULL) {
245       if (allow_release) {
246         xturnoff(csound, ip2);
247       }
248       else {
249         xturnoff_now(csound, ip2);
250       }
251     }
252     if (!p->h.insdshead->actflg) {  /* if current note was deactivated: */
253       while (CS_PDS->nxtp != NULL)
254         CS_PDS = CS_PDS->nxtp;            /* loop to last opds */
255     }
256     return OK;
257 }
258 
turnoff2S(CSOUND * csound,TURNOFF2 * p)259 int32_t turnoff2S(CSOUND *csound, TURNOFF2 *p){
260     return turnoff2(csound, p, 1);
261 }
262 
turnoff2k(CSOUND * csound,TURNOFF2 * p)263 int32_t turnoff2k(CSOUND *csound, TURNOFF2 *p){
264     return turnoff2(csound, p, 0);
265 }
266 
loop_l_i(CSOUND * csound,LOOP_OPS * p)267 int32_t loop_l_i(CSOUND *csound, LOOP_OPS *p)
268 {
269     /* if ((indxvar += iincr) < ilimit) igoto l */
270     *(p->ndxvar) += *(p->incr);
271     if (*(p->ndxvar) < *(p->limit))
272       csound->ids = p->l->prvi;
273     return OK;
274 }
275 
loop_le_i(CSOUND * csound,LOOP_OPS * p)276 int32_t loop_le_i(CSOUND *csound, LOOP_OPS *p)
277 {
278     /* if ((indxvar += iincr) <= ilimit) igoto l */
279     *(p->ndxvar) += *(p->incr);
280     if (*(p->ndxvar) <= *(p->limit))
281       csound->ids = p->l->prvi;
282     return OK;
283 }
284 
loop_g_i(CSOUND * csound,LOOP_OPS * p)285 int32_t loop_g_i(CSOUND *csound, LOOP_OPS *p)
286 {
287     /* if ((indxvar -= idecr) > ilimit) igoto l */
288     *(p->ndxvar) -= *(p->incr);
289     if (*(p->ndxvar) > *(p->limit))
290       csound->ids = p->l->prvi;
291     return OK;
292 }
293 
loop_ge_i(CSOUND * csound,LOOP_OPS * p)294 int32_t loop_ge_i(CSOUND *csound, LOOP_OPS *p)
295 {
296     /* if ((indxvar -= idecr) >= ilimit) igoto l */
297     *(p->ndxvar) -= *(p->incr);
298     if (*(p->ndxvar) >= *(p->limit))
299       csound->ids = p->l->prvi;
300     return OK;
301 }
302 
loop_l_p(CSOUND * csound,LOOP_OPS * p)303 int32_t loop_l_p(CSOUND *csound, LOOP_OPS *p)
304 {
305     /* if ((kndxvar += kincr) < klimit) kgoto l */
306     IGN(csound);
307     *(p->ndxvar) += *(p->incr);
308     if (*(p->ndxvar) < *(p->limit))
309       CS_PDS = p->l->prvp;
310     return OK;
311 }
312 
loop_le_p(CSOUND * csound,LOOP_OPS * p)313 int32_t loop_le_p(CSOUND *csound, LOOP_OPS *p)
314 {
315     /* if ((kndxvar += kincr) <= klimit) kgoto l */
316     IGN(csound);
317     *(p->ndxvar) += *(p->incr);
318     if (*(p->ndxvar) <= *(p->limit))
319       CS_PDS = p->l->prvp;
320     return OK;
321 }
322 
loop_g_p(CSOUND * csound,LOOP_OPS * p)323 int32_t loop_g_p(CSOUND *csound, LOOP_OPS *p)
324 {
325     /* if ((kndxvar -= kdecr) > klimit) kgoto l */
326     IGN(csound);
327     *(p->ndxvar) -= *(p->incr);
328     if (*(p->ndxvar) > *(p->limit))
329       CS_PDS = p->l->prvp;
330     return OK;
331 }
332 
loop_ge_p(CSOUND * csound,LOOP_OPS * p)333 int32_t loop_ge_p(CSOUND *csound, LOOP_OPS *p)
334 {
335     /* if ((kndxvar -= kdecr) >= klimit) kgoto l */
336     IGN(csound);
337     *(p->ndxvar) -= *(p->incr);
338     if (*(p->ndxvar) >= *(p->limit))
339       CS_PDS = p->l->prvp;
340     return OK;
341 }
342