1 /*
2     linevent.c:
3 
4     Copyright (C) 1991 Barry Vercoe, John ffitch, matt ingalls
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"     /*                              LINEVENT.C      */
25 #include <ctype.h>
26 
27 #ifdef MSVC
28 #include <fcntl.h>
29 #endif
30 
31 #include "linevent.h"
32 
33 #ifdef PIPES
34 # if defined(SGI) || defined(LINUX) || defined(NeXT) || defined(__MACH__)
35 #  define _popen popen
36 #  define _pclose pclose
37 # elif defined(__BEOS__) ||  defined(__HAIKU__) || defined(__MACH__)
38 #  include <stdio.h>
39 #  define _popen popen
40 #  define _pclose pclose
41 # else
42    FILE *_popen(const char *, const char *);
43 # endif
44 #endif
45 
46 #define LBUFSIZ1 32768
47 #define LF        '\n'
48 
49 /* typedef struct { */
50 /*     char    *Linep, *Linebufend; */
51 /*     FILE    *Linecons; */
52 /*     int     stdmode; */
53 /*     EVTBLK  prve; */
54 /*     char    Linebuf[LBUFSIZ]; */
55 /* } LINEVENT_GLOBALS; */
56 
57 static void sensLine(CSOUND *csound, void *userData);
58 
59 #define STA(x)   (csound->lineventStatics.x)
60 #define MAXSTR 1048576 /* 1MB */
61 
RTLineset(CSOUND * csound)62 void RTLineset(CSOUND *csound)      /* set up Linebuf & ready the input files */
63 {                                   /*     callable once from musmon.c        */
64     OPARMS  *O = csound->oparms;
65     /* csound->lineventGlobals = (LINEVENT_GLOBALS*) */
66     /*                            csound->Calloc(csound, */
67     /*                            sizeof(LINEVENT_GLOBALS)); */
68 
69     STA(linebufsiz) = LBUFSIZ1;
70     STA(Linebuf) = (char *) csound->Calloc(csound, STA(linebufsiz));
71     STA(orchestrab) = (char *) csound->Calloc(csound, MAXSTR);
72     STA(orchestra) = STA(orchestrab);
73     STA(prve).opcod = ' ';
74     STA(Linebufend) = STA(Linebuf) + STA(linebufsiz);
75     STA(Linep) = STA(Linebuf);
76     if (strcmp(O->Linename, "stdin") == 0) {
77 #if defined(DOSGCC) || defined(WIN32)
78       setvbuf(stdin, NULL, _IONBF, 0);
79       /* WARNING("-L stdin:  system has no fcntl function to get stdin"); */
80 #else
81       STA(stdmode) = fcntl(csound->Linefd, F_GETFL, 0);
82       if (UNLIKELY(fcntl(csound->Linefd, F_SETFL, STA(stdmode) | O_NDELAY) < 0))
83         csoundDie(csound, Str("-L stdin fcntl failed"));
84 #endif
85     }
86 #ifdef PIPES
87     else if (UNLIKELY(O->Linename[0] == '|')) {
88       csound->Linepipe = _popen(&(O->Linename[1]), "r");
89       if (LIKELY(csound->Linepipe != NULL)) {
90         csound->Linefd = fileno(csound->Linepipe);
91         setvbuf(csound->Linepipe, NULL, _IONBF, 0);
92       }
93       else csoundDie(csound, Str("Cannot open %s"), O->Linename);
94     }
95 #endif
96 #define MODE ,0
97     else
98       if (UNLIKELY((csound->Linefd=open(O->Linename, O_RDONLY|O_NDELAY MODE)) < 0))
99         csoundDie(csound, Str("Cannot open %s"), O->Linename);
100     if(csound->oparms->odebug)
101     csound->Message(csound, Str("stdmode = %.8x Linefd = %d\n"),
102                     STA(stdmode), csound->Linefd);
103     csound->RegisterSenseEventCallback(csound, sensLine, NULL);
104 }
105 
106 #ifdef PIPES
107 int _pclose(FILE*);
108 #endif
109 
RTclose(CSOUND * csound)110 void RTclose(CSOUND *csound)
111 {
112     if (csound->oparms->Linein == 0)
113       return;
114     csound->oparms->Linein = 0;
115     if(csound->oparms->odebug)
116     csound->Message(csound, Str("stdmode = %.8x Linefd = %d\n"),
117                     STA(stdmode), csound->Linefd);
118 #ifdef PIPES
119     if (csound->oparms->Linename[0] == '|')
120       _pclose(csound->Linepipe);
121     else
122 #endif
123       {
124         if (strcmp(csound->oparms->Linename, "stdin") != 0)
125           close(csound->Linefd);
126 #if !defined(DOSGCC) && !defined(WIN32)
127         else
128           if (UNLIKELY(fcntl(csound->Linefd, F_SETFL, STA(stdmode))))
129             csoundDie(csound, Str("Failed to set file status\n"));
130 #endif
131       }
132 
133 //csound->Free(csound, csound->lineventGlobals);
134 //csound->lineventGlobals = NULL;
135 }
136 
137 /* does string segment contain LF? */
138 
containsLF(char * cp,char * endp)139 static inline int containsLF(char *cp, char *endp)
140 {
141     while (cp < endp) {
142       if (UNLIKELY(*cp++ == LF))
143         return 1;
144     }
145     return 0;
146 }
147 
linevent_alloc(CSOUND * csound,int reallocsize)148 static CS_NOINLINE int linevent_alloc(CSOUND *csound, int reallocsize)
149 {
150     volatile jmp_buf tmpExitJmp;
151     int         err;
152     unsigned int tmp;
153 
154     if (reallocsize > 0) {
155       /* VL 20-11-17 need to record the STA(Linep) offset
156          in relation to STA(Linebuf) */
157       tmp = (STA(Linep) - STA(Linebuf));
158       STA(Linebuf) = (char *) csound->ReAlloc(csound,
159                                               (void *) STA(Linebuf), reallocsize);
160 
161       STA(linebufsiz) = reallocsize;
162       STA(Linebufend) = STA(Linebuf) + STA(linebufsiz);
163       /* VL 20-11-17 so we can place it in the correct position
164          after reallocation */
165       STA(Linep) =  STA(Linebuf) + tmp;
166     } else if (STA(Linebuf)==NULL) {
167        STA(linebufsiz) = LBUFSIZ1;
168        STA(Linebuf) = (char *) csound->Calloc(csound, STA(linebufsiz));
169     }
170     if (STA(Linebuf) == NULL) {
171        return 1;
172     }
173     //csound->Message(csound, "1. realloc: %d\n", reallocsize);
174     if (STA(Linep)) return 0;
175     csound->Linefd = -1;
176     memcpy((void*) &tmpExitJmp, (void*) &csound->exitjmp, sizeof(jmp_buf));
177     if ((err = setjmp(csound->exitjmp)) != 0) {
178       memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf));
179       //csound->lineventGlobals = NULL;
180       return -1;
181     }
182 
183 
184     memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf));
185     STA(prve).opcod = ' ';
186     STA(Linebufend) = STA(Linebuf) + STA(linebufsiz);
187     STA(Linep) = STA(Linebuf);
188     csound->RegisterSenseEventCallback(csound, sensLine, NULL);
189 
190     return 0;
191 }
192 
193 /* insert text from an external source,
194    to be interpreted as if coming in from stdin/Linefd for -L */
195 
csoundInputMessageInternal(CSOUND * csound,const char * message)196 void csoundInputMessageInternal(CSOUND *csound, const char *message)
197 {
198     int32  size = (int32) strlen(message);
199     int n;
200 
201     if ((n=linevent_alloc(csound, 0)) != 0) return;
202 
203     if (!size) return;
204     if (UNLIKELY((STA(Linep) + size) >= STA(Linebufend))) {
205       int extralloc = STA(Linep) + size - STA(Linebufend);
206       csound->Message(csound, "realloc %d\n", extralloc);
207       // csound->Message(csound, "extralloc: %d %d %d\n",
208       //                 extralloc, size, (int)(STA(Linebufend) - STA(Linep)));
209       // FIXME -- Coverity points out that this test is always false
210       // and n is never used
211 #if 0
212       if ((n=linevent_alloc(csound, (STA(linebufsiz) + extralloc))) != 0) {
213         csoundErrorMsg(csound, Str("LineBuffer Overflow - "
214                                    "Input Data has been Lost"));
215         return;
216       }
217 #else
218       n = linevent_alloc(csound, (STA(linebufsiz) + extralloc));
219 
220 #endif
221     }
222     //csound->Message(csound, "%u = %u\n", (STA(Linep) + size),  STA(Linebufend) );
223     memcpy(STA(Linep), message, size);
224     if (STA(Linep)[size - 1] != (char) '\n')
225       STA(Linep)[size++] = (char) '\n';
226     STA(Linep) += size;
227 }
228 
229 /* accumlate RT Linein buffer, & place completed events in EVTBLK */
230 /* does more syntax checking than rdscor, since not preprocessed  */
231 
sensLine(CSOUND * csound,void * userData)232 static void sensLine(CSOUND *csound, void *userData)
233 {
234     char    *cp, *Linestart, *Linend;
235     int     c, cm1, cpp1, n, pcnt, oflag = STA(oflag);
236     IGN(userData);
237 
238     while (1) {
239       if(STA(oflag) > oflag) break;
240       Linend = STA(Linep);
241       if (csound->Linefd >= 0) {
242         n = read(csound->Linefd, Linend, STA(Linebufend) - Linend);
243         Linend += (n > 0 ? n : 0);
244       }
245       if (Linend <= STA(Linebuf))
246         break;
247       Linestart = STA(Linebuf);
248       cp = Linestart;
249 
250       while (containsLF(Linestart, Linend)) {
251         EVTBLK  e;
252         char    *sstrp = NULL;
253         int     scnt = 0;
254         int     strsiz = 0;
255         memset(&e, 0, sizeof(EVTBLK));
256         e.strarg = NULL; e.scnt = 0;
257         c = *cp;
258         while (isblank(c))              /* skip initial white space */
259           c = *(++cp);
260         if (c == LF) {                  /* if null line, bugout     */
261           Linestart = (++cp);
262           continue;
263         }
264         cm1 = *(cp-1);
265         cpp1 = *(cp+1);
266 
267         /* new orchestra input
268          */
269         if(STA(oflag)) {
270           if(c == '}' && cm1 != '}' && cpp1 != '}') {
271             STA(oflag) = 0;
272             STA(orchestra) = STA(orchestrab);
273             csoundCompileOrc(csound, STA(orchestrab));
274             csound->Message(csound, "::compiling orchestra::\n");
275             Linestart = (++cp);
276             continue;
277           }
278           else {
279             char *pc;
280             memcpy(STA(orchestra), Linestart, Linend - Linestart);
281             STA(orchestra) += (Linend - Linestart);
282             *STA(orchestra) = '\0';
283             STA(oflag)++;
284             if((pc = strrchr(STA(orchestrab), '}')) != NULL) {
285 
286               if(*(pc-1) != '}') {
287               *pc = '\0';
288                cp = strrchr(Linestart, '}');
289               } else {
290                Linestart = Linend;
291               }
292               } else {
293               Linestart = Linend;
294             }
295             continue;
296           }
297         } else if(c == '{') {
298           STA(oflag) = 1;
299           csound->Message(csound,
300                           "::reading orchestra, use '}' to terminate::\n");
301           cp++;
302           continue;
303         }
304 
305         switch (c) {                    /* look for legal opcode    */
306         case 'e':                       /* Quit realtime            */
307         case 'i':
308         case 'q':
309         case 'f':
310         case 'a':
311         case 'd':
312           e.opcod = c;
313           break;
314         default:
315           csound->ErrorMsg(csound, Str("unknown opcode %c"), c);
316           goto Lerr;
317         }                                       /* for params that follow:  */
318         pcnt = 0;
319         do {
320           char  *newcp;
321           do {                                  /* skip white space */
322             c = *(++cp);
323           } while (isblank(c));
324           if (c == LF)
325             break;
326           pcnt++;
327           if (c == '"') {                       /* if find character string */
328             if (e.strarg == NULL)
329               e.strarg = csound->Malloc(csound, strsiz=SSTRSIZ);
330             sstrp = e.strarg;
331             n = scnt;
332             while (n-->0) sstrp += strlen(sstrp)+1;
333             n = 0;
334 
335             while ((c = *(++cp)) != '"') {
336               /* VL: allow strings to be multi-line */
337               // if (UNLIKELY(c == LF)) {
338               //  csound->ErrorMsg(csound, Str("unmatched quotes"));
339               //  goto Lerr;
340               //}
341 
342               if(c == '\\') {
343                 cp++;
344                 if(*cp == '"') c = *cp; /* if it is a double quote */
345                 /* otherwise we ignore it */
346                 else cp--;
347               }
348               sstrp[n++] = c;                   /*   save in private strbuf */
349 
350               if (UNLIKELY((sstrp-e.strarg)+n >= strsiz-10)) {
351                 e.strarg = csound->ReAlloc(csound, e.strarg, strsiz+=SSTRSIZ);
352                 sstrp = e.strarg+n;
353               }
354             }
355             sstrp[n] = '\0';
356             {
357               union {
358                 MYFLT d;
359                 int32 i;
360               } ch;
361               ch.d = SSTRCOD; ch.i += scnt++;
362               e.p[pcnt] = ch.d;           /* set as string with count */
363             }
364             e.scnt = scnt;
365             //printf("string: %s\n", sstrp);
366             continue;
367           }
368           if (UNLIKELY(!(isdigit(c) || c == '+' || c == '-' || c == '.')))
369             goto Lerr;
370           if (c == '.' &&                       /*  if lone dot,       */
371               (isblank(n = cp[1]) || n == LF)) {
372             if (UNLIKELY(e.opcod != 'i' ||
373                          STA(prve).opcod != 'i' || pcnt > STA(prve).pcnt)) {
374               csound->ErrorMsg(csound, Str("dot carry has no reference"));
375               goto Lerr;
376             }                                   /*        pfld carry   */
377             e.p[pcnt] = STA(prve).p[pcnt];
378             if (UNLIKELY(csound->ISSTRCOD(e.p[pcnt]))) {
379               csound->ErrorMsg(csound, Str("cannot carry string p-field"));
380               goto Lerr;
381             }
382             continue;
383           }
384           e.p[pcnt] = (MYFLT) cs_strtod(cp, &newcp);
385           cp = newcp - 1;
386         } while (pcnt < PMAX);
387         if (e.opcod =='f' && e.p[1]<FL(0.0)); /* an OK case */
388         else  /* Check for sufficient pfields (0-based, opcode counted already). */
389           if (UNLIKELY(pcnt < 2 && e.opcod != 'e')) {
390             csound->ErrorMsg(csound, Str("too few pfields (%d)"), pcnt + 1);
391             goto Lerr;
392           }
393         if (UNLIKELY(pcnt > 1 && e.p[2] < FL(0.0))) {
394           csound->ErrorMsg(csound, Str("-L with negative p2 illegal"));
395           goto Lerr;
396         }
397         e.pcnt = pcnt;                          /*   &  record pfld count    */
398         if (e.opcod == 'i') {                   /* do carries for instr data */
399           memcpy((void*) &STA(prve), (void*) &e,
400                  (size_t) ((char*) &(e.p[pcnt + 1]) - (char*) &e));
401           /* FIXME: how to carry string args ? */
402           STA(prve).strarg = NULL;
403         }
404         if (UNLIKELY(pcnt >= PMAX && c != LF)) {
405           csound->ErrorMsg(csound, Str("too many pfields"));
406           while (*(++cp) != LF)                 /* flush any excess data     */
407             ;
408         }
409         Linestart = (++cp);
410         insert_score_event_at_sample(csound, &e, csound->icurTime);
411         continue;
412       Lerr:
413         n = cp - Linestart;                     /* error position */
414         while (*cp != LF)
415           cp++;                                 /* go on to LF    */
416         *cp = '\0';                             /*  & insert NULL */
417         csound->ErrorMsg(csound, Str("illegal RT scoreline:\n%s\n%*s"),
418                                  Linestart, n + 1, "^");  /* mark the error */
419         Linestart = (++cp);
420       }
421       if (Linestart != &(STA(Linebuf)[0])) {
422         int len = (int) (Linend - Linestart);
423         /* move any remaining characters to the beginning of the buffer */
424         for (n = 0; n < len; n++)
425           STA(Linebuf)[n] = Linestart[n];
426         n = (int) (Linestart - &(STA(Linebuf)[0]));
427         STA(Linep) -= n;
428         Linend -= n;
429       }
430       if (Linend == STA(Linep))      /* return if no more data is available  */
431         break;
432       STA(Linep) = Linend;                       /* accum the chars          */
433     }
434 
435 }
436 
437 /* send a lineevent from the orchestra -matt 2001/12/07 */
438 
439 static const char *errmsg_1 =
440   Str_noop("event: param 1 must be \"a\", \"i\", \"q\", \"f\", \"d\", or \"e\"");
441 static const char *errmsg_2 =
442   Str_noop("event: string name is allowed only for \"i\", \"d\", and \"q\" events");
443 
eventOpcode_(CSOUND * csound,LINEVENT * p,int insname,char p1)444 int eventOpcode_(CSOUND *csound, LINEVENT *p, int insname, char p1)
445 {
446     EVTBLK  evt;
447     int     i;
448     char    opcod;
449     memset(&evt, 0, sizeof(EVTBLK));
450 
451     if (p1==0)
452          opcod = *((STRINGDAT*) p->args[0])->data;
453     else  opcod = p1;
454 
455     if (UNLIKELY((opcod != 'a' && opcod != 'i' && opcod != 'q' && opcod != 'f' &&
456                   opcod != 'e' && opcod != 'd')
457                  /*|| ((STRINGDAT*) p->args[0])->data[1] != '\0'*/))
458       return csound->PerfError(csound, &(p->h), "%s", Str(errmsg_1));
459     evt.strarg = NULL; evt.scnt = 0;
460     evt.opcod = opcod;
461     if (p->flag==1) evt.pcnt = p->argno-2;
462     else
463       evt.pcnt = p->INOCOUNT - 1;
464 
465     /* IV - Oct 31 2002: allow string argument */
466     if (evt.pcnt > 0) {
467       if (insname) {
468         int res;
469         if (UNLIKELY(evt.opcod != 'i' && evt.opcod != 'q' && opcod != 'd'))
470           return csound->PerfError(csound, &(p->h), "%s", Str(errmsg_2));
471         res = csound->strarg2insno(csound, ((STRINGDAT*) p->args[1])->data, 1);
472         if (UNLIKELY(res == NOT_AN_INSTRUMENT)) return NOTOK;
473         evt.p[1] = (MYFLT) res;
474         evt.strarg = NULL; evt.scnt = 0;
475       }
476       else {
477         int res;
478         if (csound->ISSTRCOD(*p->args[1])) {
479           res = csound->strarg2insno(csound,
480                                      get_arg_string(csound, *p->args[1]), 1);
481           if (UNLIKELY(res == NOT_AN_INSTRUMENT)) return NOTOK;
482           evt.p[1] = (MYFLT)res;
483         } else {                  /* Should check for valid instr num here */
484           MYFLT insno = FABS(*p->args[1]);
485           evt.p[1] = *p->args[1];
486           if (UNLIKELY((opcod == 'i' || opcod == 'd') && (insno ==0 ||
487                        insno > csound->engineState.maxinsno ||
488                        !csound->engineState.instrtxtp[(int)insno]))) {
489             csound->Message(csound, Str("WARNING: Cannot Find Instrument %d\n"),
490                            (int) insno);
491             return NOTOK;
492           }
493         }
494         evt.strarg = NULL; evt.scnt = 0;
495       }
496       for (i = 2; i <= evt.pcnt; i++)
497         evt.p[i] = *p->args[i];
498     }
499 
500     if(opcod == 'd') {
501       evt.opcod = 'i';
502       evt.p[1] *= -1;
503     }
504 
505     if (UNLIKELY(insert_score_event_at_sample(csound, &evt, csound->icurTime) != 0))
506       return csound->PerfError(csound, &(p->h),
507                                Str("event: error creating '%c' event"),
508                                opcod);
509     return OK;
510 }
511 
eventOpcode(CSOUND * csound,LINEVENT * p)512 int eventOpcode(CSOUND *csound, LINEVENT *p)
513 {
514     return eventOpcode_(csound, p, 0, 0);
515 }
516 
eventOpcode_S(CSOUND * csound,LINEVENT * p)517 int eventOpcode_S(CSOUND *csound, LINEVENT *p)
518 {
519     return eventOpcode_(csound, p, 1, 0);
520 }
521 
522 
523 
524 /* i-time version of event opcode */
525 
eventOpcodeI_(CSOUND * csound,LINEVENT * p,int insname,char p1)526 int eventOpcodeI_(CSOUND *csound, LINEVENT *p, int insname, char p1)
527 {
528     EVTBLK  evt;
529     int     i, err = 0;
530     char    opcod;
531     memset(&evt, 0, sizeof(EVTBLK));
532 
533     if (p1==0)
534          opcod = *((STRINGDAT*) p->args[0])->data;
535     else opcod = p1;
536     if (UNLIKELY((opcod != 'a' && opcod != 'i' && opcod != 'q' && opcod != 'f' &&
537                   opcod != 'e' && opcod != 'd')
538                  /*|| ((STRINGDAT*) p->args[0])->data[1] != '\0'*/))
539       return csound->InitError(csound, "%s", Str(errmsg_1));
540     evt.strarg = NULL; evt.scnt = 0;
541     evt.opcod = opcod;
542     if (p->flag==1) evt.pcnt = p->argno-1;
543     else
544       evt.pcnt = p->INOCOUNT - 1;
545     /* IV - Oct 31 2002: allow string argument */
546     if (evt.pcnt > 0) {
547       if (insname) {
548         int res;
549         if (UNLIKELY(evt.opcod != 'i' && evt.opcod != 'q' && opcod != 'd'))
550           return csound->InitError(csound, "%s", Str(errmsg_2));
551         res = csound->strarg2insno(csound,((STRINGDAT *)p->args[1])->data, 1);
552         if (UNLIKELY(res == NOT_AN_INSTRUMENT)) return NOTOK;
553         evt.p[1] = (MYFLT)res;
554         evt.strarg = NULL; evt.scnt = 0;
555         for (i = 2; i <= evt.pcnt; i++)
556            evt.p[i] = *p->args[i];
557       }
558       else {
559         evt.strarg = NULL; evt.scnt = 0;
560         if (csound->ISSTRCOD(*p->args[1])) {
561           int res = csound->strarg2insno(csound,
562                                          get_arg_string(csound, *p->args[1]), 1);
563           if (UNLIKELY(evt.p[1] == NOT_AN_INSTRUMENT)) return NOTOK;
564           evt.p[1] = (MYFLT)res;
565         }
566         else {                  /* Should check for valid instr num here */
567           MYFLT insno = FABS(*p->args[1]);
568           evt.p[1] = *p->args[1];
569           if (UNLIKELY((opcod == 'i' || opcod == 'd') && (insno ==0 ||
570                        insno > csound->engineState.maxinsno ||
571                        !csound->engineState.instrtxtp[(int)insno]))) {
572             csound->Message(csound, Str("WARNING: Cannot Find Instrument %d\n"),
573                            (int) insno);
574             return NOTOK;
575           }
576           evt.strarg = NULL; evt.scnt = 0;
577         }
578         for (i = 2; i <= evt.pcnt; i++)
579           evt.p[i] = *p->args[i];
580       }
581 
582     }
583     if(opcod == 'd') {
584       evt.opcod = 'i';
585       evt.p[1] *= -1;
586     }
587 
588 
589     if (opcod == 'f' && (int) evt.pcnt >= 2 && evt.p[2] <= FL(0.0)) {
590       FUNC  *dummyftp;
591       err = csound->hfgens(csound, &dummyftp, &evt, 0);
592     }
593     else
594       err = insert_score_event_at_sample(csound, &evt, csound->icurTime);
595     if (UNLIKELY(err))
596       csound->InitError(csound, Str("event_i: error creating '%c' event"),
597                                 opcod);
598     return (err == 0 ? OK : NOTOK);
599 }
600 
eventOpcodeI(CSOUND * csound,LINEVENT * p)601 int eventOpcodeI(CSOUND *csound, LINEVENT *p)
602 {
603     return eventOpcodeI_(csound, p, 0, 0);
604 }
605 
eventOpcodeI_S(CSOUND * csound,LINEVENT * p)606 int eventOpcodeI_S(CSOUND *csound, LINEVENT *p)
607 {
608     return eventOpcodeI_(csound, p, 1, 0);
609 }
610 
instanceOpcode_(CSOUND * csound,LINEVENT2 * p,int insname)611 int instanceOpcode_(CSOUND *csound, LINEVENT2 *p, int insname)
612 {
613     EVTBLK  evt;
614     int     i;
615 
616     evt.strarg = NULL; evt.scnt = 0;
617     evt.opcod = 'i';
618     evt.pcnt = p->INOCOUNT;
619 
620        /* pass in the memory to hold the instance after insertion */
621     evt.pinstance = (void *) p->inst;
622 
623     /* IV - Oct 31 2002: allow string argument */
624     if (evt.pcnt > 0) {
625       int res;
626       if (insname) {
627         res = csound->strarg2insno(csound,
628                                    ((STRINGDAT*) p->args[0])->data, 1);
629         if (UNLIKELY(evt.p[1] == NOT_AN_INSTRUMENT)) return NOTOK;
630         evt.p[1] = (MYFLT)res;
631         evt.strarg = NULL; evt.scnt = 0;
632       }
633       else {
634         if (csound->ISSTRCOD(*p->args[0])) {
635           res = csound->strarg2insno(csound,
636                                      get_arg_string(csound, *p->args[0]), 1);
637           if (UNLIKELY(evt.p[1] == NOT_AN_INSTRUMENT)) return NOTOK;
638           evt.p[1] = (MYFLT)res;
639         } else evt.p[1] = *p->args[0];
640         evt.strarg = NULL; evt.scnt = 0;
641       }
642       for (i = 2; i <= evt.pcnt; i++)
643         evt.p[i] = *p->args[i-1];
644     }
645     if (insert_score_event_at_sample(csound, &evt, csound->icurTime) != 0)
646       return csound->PerfError(csound, &(p->h),
647                                Str("instance: error creating event"));
648 
649     return OK;
650 }
651 
instanceOpcode(CSOUND * csound,LINEVENT2 * p)652 int instanceOpcode(CSOUND *csound, LINEVENT2 *p)
653 {
654     return instanceOpcode_(csound, p, 0);
655 }
656 
instanceOpcode_S(CSOUND * csound,LINEVENT2 * p)657 int instanceOpcode_S(CSOUND *csound, LINEVENT2 *p)
658 {
659     return instanceOpcode_(csound, p, 1);
660 }
661