1 %{
2 
3  /*
4     csound_pre.l:
5 
6     Copyright (C) 2011
7     John ffitch
8 
9     This file is part of Csound.
10 
11     The Csound Library is free software; you can redistribute it
12     and/or modify it under the terms of the 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, MAc
23     02110-1301 USA
24 */
25 
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include "csoundCore.h"
31 #include "corfile.h"
32 #include <inttypes.h>
33 #define YY_DECL int yylex (CSOUND *csound, yyscan_t yyscanner)
34 static void comment(yyscan_t);
35 static void do_comment(yyscan_t);
36 static void do_include(CSOUND *, int, yyscan_t);
37 static void do_new_include(CSOUND *, yyscan_t);
38 static void do_macro_arg(CSOUND *, char *, yyscan_t);
39 static void do_macro(CSOUND *, char *, yyscan_t);
40 static void do_umacro(CSOUND *, char *, yyscan_t);
41 static void do_umacroq(CSOUND *, char *, yyscan_t);
42 static void do_ifdef(CSOUND *, char *, yyscan_t);
43 static void do_ifdef_skip_code(CSOUND *, yyscan_t);
44 static void do_function(CSOUND*, char *, CORFIL*);
45 //static void print_csound_predata(CSOUND *,char *,yyscan_t);
46 static void csound_pre_line(CSOUND *, CORFIL*, yyscan_t);
47 //static void delete_macros(CSOUND*, yyscan_t);
48 #include "parse_param.h"
49 
50 #define YY_EXTRA_TYPE  PRE_PARM *
51 #define PARM    yyget_extra(yyscanner)
52 
53 #define YY_USER_INIT {csound_pre_scan_string(csound->orchstr->body, yyscanner); \
54     csound_preset_lineno(csound->orcLineOffset, yyscanner);             \
55     yyg->yy_flex_debug_r=1; PARM->macro_stack_size = 0;                 \
56     PARM->alt_stack = NULL; PARM->macro_stack_ptr = 0;                  \
57     PARM->path = ".";                                                   \
58   }
59 static MACRO *find_definition(MACRO *, char *);
60 
61 #define S_INC (10)
62 
63 %}
64 %option reentrant
65 %option noyywrap
66 %option prefix="csound_pre"
67 %option outfile="Engine/csound_prelex.c"
68 %option stdout
69 
70 NEWLINE         (\n|\r\n?)
71 STSTR           \"
72 ESCAPE          \\.
73 XSTR            \{\{([^}]|\}[^}])*\}\}
74 IDENT           [a-zA-Z_][a-zA-Z0-9_]*
75 MACRONAME       "$"`?[a-zA-Z_][a-zA-Z0-9_`]*
76 MACRONAMED      "$"`?[a-zA-Z_][a-zA-Z0-9_`]*\.
77 MACRONAMEA      "$"`?[a-zA-Z_][a-zA-Z0-9_`]*\(
78 MACRONAMEDA     "$"`?[a-zA-Z_][a-zA-Z0-9_`]*\.\(
79 MACROB          [a-zA-Z_][a-zA-Z0-9_]*\(
80 MACRO           [a-zA-Z_][a-zA-Z0-9_]*
81 
82 STCOM           \/\*
83 INCLUDE         "#include"
84 INCLUDESTR      "#includestr"
85 DEFINE          #[ \t]*define
86 UNDEF           "#undef"
87 IFDEF           #ifn?def
88 ELSE            #else[ \t]*(;.*)?$
89 END             #end(if)?[ \t]*(;.*)?
90 CONT            \\[ \t]*(;.*)?(\n|\r\n?)
91 RESET           "###\n"
92 
93 INT             "int"[ \t]*\(
94 FRAC            "frac"[ \t]*\(
95 ROUND           "round"[ \t]*\(
96 FLOOR           "floor"[ \t]*\(
97 CEIL            "ceil"[ \t]*\(
98 RND             "rnd"[ \t]*\(
99 BIRND           "birnd"[ \t]*\(
100 ABS             "abs"[ \t]*\(
101 EXP             "exp"[ \t]*\(
102 LOG             "log"[ \t]*\(
103 SQRT            "sqrt"[ \t]*\(
104 SIN             "sin"[ \t]*\(
105 COS             "cos"[ \t]*\(
106 TAN             "tan"[ \t]*\(
107 SININV          "sininv"[ \t]*\(
108 COSINV          "cosinv"[ \t]*\(
109 TANINV          "taninv"[ \t]*\(
110 LOG10           "log10"[ \t]*\(
111 LOG2            "log2"[ \t]*\(
112 SINH            "sinh"[ \t]*\(
113 COSH            "cosh"[ \t]*\(
114 TANH            "tanh"[ \t]*\(
115 AMPDB           "ampdb"[ \t]*\(
116 AMPDBFS         "ampdbfs"[ \t]*\(
117 DBAMP           "dbamp"[ \t]*\(
118 DBFSAMP         "dbfsamp"[ \t]*\(
119 FTCPS           "ftcps"[ \t]*\(
120 FTLEN           "ftlen"[ \t]*\(
121 FTSR            "ftsr"[ \t]*\(
122 FTLPTIM         "ftlptim"[ \t]*\(
123 FTCHNLS         "ftchnls"[ \t]*\(
124 I               "i"[ \t]*\(
125 K               "k"[ \t]*\(
126 CPSOCT          "cpsoct"[ \t]*\(
127 OCTPCH          "octpch"[ \t]*\(
128 CPSPCH          "cpspch"[ \t]*\(
129 PCHOCT          "pchoct"[ \t]*\(
130 OCTCPS          "octcps"[ \t]*\(
131 NSAMP           "nsamp"[ \t]*\(
132 POWOFTWO        "powoftwo"[ \t]*\(
133 LOGBTWO         "logbtwo"[ \t]*\(
134 A               "a"[ \t]*\(
135 TB0             "tb0"[ \t]*\(
136 TB1             "tb1"[ \t]*\(
137 TB2             "tb2"[ \t]*\(
138 TB3             "tb3"[ \t]*\(
139 TB4             "tb4"[ \t]*\(
140 TB5             "tb5"[ \t]*\(
141 TB6             "tb6"[ \t]*\(
142 TB7             "tb7"[ \t]*\(
143 TB8             "tb8"[ \t]*\(
144 TB9             "tb9"[ \t]*\(
145 TB10            "tb10"[ \t]*\(
146 TB11            "tb11"[ \t]*\(
147 TB12            "tb12"[ \t]*\(
148 TB13            "tb13"[ \t]*\(
149 TB14            "tb14"[ \t]*\(
150 TB15            "tb15"[ \t]*\(
151 URD             "urd"[ \t]*\(
152 NOT             "not"[ \t]*\(
153 CENT            "cent"[ \t]*\(
154 OCTAVE          "octave"[ \t]*\(
155 SEMITONE        "semitone"[ \t]*\(
156 CPSMIDIN        "cpsmidinn"[ \t]*\(
157 OCTMIDIN        "octmidinn"[ \t]*\(
158 PCHMIDIN        "pchmidinn"[ \t]*\(
159 DB              "db"[ \t]*\(
160 P               "p"[ \t]*\(
161 QINF            "qinf"[ \t]*\(
162 QNAN            "qnan"[ \t]*\(
163 
164 %X incl
165 %x macro
166 %x umacro
167 %x ifdef
168 
169 %%
170 
171 {RESET}         { csound_preset_lineno(csound->orcLineOffset, yyscanner);
172                   csound->Free(csound, PARM->alt_stack);
173                 }
174 {CONT}          {
175                   char bb[80];
176                   csound_preset_lineno(1+csound_preget_lineno(yyscanner),
177                                        yyscanner);
178                   if (PARM->isString==0) {
179                     sprintf(bb, "#sline %d ", csound_preget_lineno(yyscanner));
180                     corfile_puts(csound, bb, csound->expanded_orc);
181                   }
182                 }
183 {NEWLINE}       {
184                   corfile_putc(csound, '\n', csound->expanded_orc);
185                   csound_preset_lineno(1+csound_preget_lineno(yyscanner),
186                                        yyscanner);
187                   csound_pre_line(csound, csound->expanded_orc, yyscanner);
188                 }
189 "//"            {
190                   if (PARM->isString != 1) {
191                     comment(yyscanner);
192                     corfile_putc(csound, '\n', csound->expanded_orc);
193                     csound_pre_line(csound, csound->expanded_orc, yyscanner);
194                   }
195                   else {
196                     corfile_puts(csound, yytext, csound->expanded_orc);
197                   }
198                 }
199 ";"             {
200                   if (PARM->isString != 1) {
201                     comment(yyscanner);
202                     corfile_putc(csound, '\n', csound->expanded_orc);
203                     csound_pre_line(csound, csound->expanded_orc, yyscanner);
204                   }
205                   else {
206                     corfile_puts(csound, yytext, csound->expanded_orc);
207                   }
208                   //corfile_putline(csound_preget_lineno(yyscanner),
209                   //                csound->expanded_orc);
210                 }
211 {STCOM}         {
212                   if (PARM->isString != 1)
213                     do_comment(yyscanner);
214                   else
215                     corfile_puts(csound, yytext, csound->expanded_orc);
216                 }
217 {ESCAPE}        { corfile_puts(csound, yytext, csound->expanded_orc); }
218 {STSTR}         {
219                   corfile_putc(csound, '"', csound->expanded_orc);
220                   PARM->isString = !PARM->isString;
221                   if (PARM->isinclude && PARM->isString==0) {
222                     do_new_include(csound, yyscanner);
223                     PARM->isinclude = 0;
224                   }
225                 }
226 {XSTR}          {
227                   char c, *str = yytext;
228                   if (PARM->isString == 1)
229                     yyless(2);
230                   while ((c = *str++) != '\0') {
231                     switch(c) {
232                     case '\r': if (*str == '\n') continue;
233                     case '\n':
234                       csound_preset_lineno(1+csound_preget_lineno(yyscanner),
235                                            yyscanner);
236                       break;
237                     default: break;
238                     }
239                   }
240                   corfile_puts(csound, yytext, csound->expanded_orc);
241                 }
242 {MACRONAME}|{MACRONAMED}     {
243                    MACRO     *mm = csound->orc_macros;
244                    //printf("macro name >>%s<<\n", yytext);
245                    mm = find_definition(mm, yytext+1);
246                    if (UNLIKELY(mm == NULL)) {
247                      csound->Message(csound,Str("Undefined macro: '%s'"), yytext);
248                      //csound->LongJmp(csound, 1);
249                      corfile_puts(csound, "$error", csound->expanded_orc);
250                    }
251                    else {
252                      /* Need to read from macro definition */
253                      if (UNLIKELY(PARM->macro_stack_ptr +1 >=
254                                   PARM->macro_stack_size )) {
255                        PARM->alt_stack =
256                          (MACRON*)
257                          csound->ReAlloc(csound, PARM->alt_stack,
258                                          sizeof(MACRON)*
259                                                (PARM->macro_stack_size+=S_INC));
260                        if (UNLIKELY(PARM->alt_stack == NULL)) {
261                          csound->Message(csound, Str("Memory exhausted"));
262                          csound->LongJmp(csound, 1);
263                        }
264                      }
265                      PARM->alt_stack[PARM->macro_stack_ptr].n = 0;
266                      PARM->alt_stack[PARM->macro_stack_ptr].line =
267                        csound_preget_lineno(yyscanner);
268                      PARM->alt_stack[PARM->macro_stack_ptr].path = NULL;
269                      PARM->alt_stack[PARM->macro_stack_ptr++].s = NULL;
270                      yypush_buffer_state(YY_CURRENT_BUFFER, yyscanner);
271                      csound_preset_lineno(1, yyscanner);
272                      if (UNLIKELY(PARM->depth>1022)) {
273                        csound->Message(csound,
274                                        Str("macros/include nested too deep: "));
275                        csound->LongJmp(csound, 1);
276                      }
277                      PARM->lstack[++PARM->depth] =
278                        (strchr(mm->body,'\n') ?file_to_int(csound, yytext) : 63);
279                      yy_scan_string(mm->body, yyscanner);
280                      /* csound->DebugMsg(csound,"%p\n", YY_CURRENT_BUFFER); */
281                    }
282                 }
283 {MACRONAMEA}|{MACRONAMEDA}    {
284                    MACRO     *mm = csound->orc_macros;
285                    int err = 0;
286                    char      *mname;
287                    int c, i, j, cnt=0;
288                    //csound->DebugMsg(csound,"Macro with arguments call %s\n",
289                    //                 yytext);
290                    yytext[yyleng-1] = '\0';
291                    mm = find_definition(csound->orc_macros, yytext+1);
292                    if (UNLIKELY(mm == NULL)) {
293                      csound->Message(csound,Str("Undefined macro: '%s'"), yytext);
294                      corfile_puts(csound, "$error", csound->expanded_orc);
295                    }
296                    else {
297                      mname = yytext;
298                      /* Need to read from macro definition */
299                      csound->DebugMsg(csound,"Looking for %d args\n", mm->acnt);
300                      for (j = 0; j < mm->acnt; j++) {
301                        char  term = (j == mm->acnt - 1 ? ')' : '\'');
302                        /* Compatability */
303                        char  trm1 = (j == mm->acnt - 1 ? ')' : '#');
304                        MACRO *nn = (MACRO*) csound->Malloc(csound, sizeof(MACRO));
305                        int   size = 100;
306                        if (UNLIKELY(nn == NULL)) {
307                          csound->Message(csound, Str("Memory exhausted"));
308                          csound->LongJmp(csound, 1);
309                        }
310                        nn->name = csound->Malloc(csound, strlen(mm->arg[j]) + 1);
311                        if (UNLIKELY(nn->name == NULL)) {
312                          csound->Message(csound, Str("Memory exhausted"));
313                          csound->LongJmp(csound, 1);
314                        }
315                        csound->DebugMsg(csound,"Arg %d: %s\n", j+1, mm->arg[j]);
316                        strcpy(nn->name, mm->arg[j]);
317                        csound->Message(csound, "defining argument %s ",
318                                        nn->name);
319                        i = 0;
320                        nn->body = (char*) csound->Malloc(csound, 100);
321                        if (UNLIKELY(nn->body == NULL)) {
322                          csound->Message(csound, Str("Memory exhausted"));
323                          csound->LongJmp(csound, 1);
324                        }
325                        while (1) {
326                          c = input(yyscanner);
327                          if (cnt==0 && ( c==term || c==trm1)) break;
328                          if (UNLIKELY(cnt==0 && c == ')')) {
329                            csound->Message(csound,
330                                            Str("Too few arguments to macro\n"));
331                            corfile_puts(csound, "$error", csound->expanded_orc);
332                            err = 1; break;
333                          }
334                          if (c=='(') cnt++;
335                          if (c==')') cnt--;
336                          if (c == '\\') {
337                            int newc = input(yyscanner);
338                            if (newc == ')')
339                              nn->body[i++] = c;
340                            c = newc;
341                          }
342                          if (UNLIKELY(i > 98)) {
343                            csound->Message(csound,
344                                            Str("Missing argument "
345                                                "terminator\n%.98s"),
346                                            nn->body);
347                            corfile_puts(csound, "$error", csound->expanded_orc);
348                            err = 1; break;
349                          }
350                          nn->body[i++] = c;
351                          if (UNLIKELY(i >= size)) {
352                            nn->body = csound->ReAlloc(csound, nn->body,
353                                                       size += 100);
354                            if (UNLIKELY(nn->body == NULL)) {
355                              csound->Message(csound, Str("Memory exhausted"));
356                              csound->LongJmp(csound, 1);
357                            }
358                          }
359                        }
360                        nn->body[i] = '\0';
361                        csound->Message(csound, "as...#%s#\n", nn->body);
362                        nn->acnt = 0;       /* No arguments for arguments */
363                        nn->next = csound->orc_macros;
364                        csound->orc_macros = nn;
365                      }
366                      if (!err) {
367                        //csound->DebugMsg(csound,"New body: ...#%s#\n", mm->body);
368                        if (UNLIKELY(PARM->macro_stack_ptr +1 >=
369                                     PARM->macro_stack_size )) {
370                          PARM->alt_stack =
371                            (MACRON*)
372                            csound->ReAlloc(csound, PARM->alt_stack,
373                                            sizeof(MACRON)*
374                                                  (PARM->macro_stack_size+=S_INC));
375                          if (UNLIKELY(PARM->alt_stack == NULL)) {
376                            csound->Message(csound, Str("Memory exhausted"));
377                            csound->LongJmp(csound, 1);
378                          }
379                          /* csound->DebugMsg(csound, */
380                          /*        "macro_stack extends alt_stack to %d long\n", */
381                          /*                  PARM->macro_stack_size); */
382                        }
383                        PARM->alt_stack[PARM->macro_stack_ptr].n =
384                          csound->orc_macros->acnt;
385                        PARM->alt_stack[PARM->macro_stack_ptr].line =
386                          csound_preget_lineno(yyscanner);
387                        PARM->alt_stack[PARM->macro_stack_ptr].path = NULL;
388                        PARM->alt_stack[PARM->macro_stack_ptr++].s = csound->orc_macros;
389                        PARM->alt_stack[PARM->macro_stack_ptr].n = 0;
390                        PARM->alt_stack[PARM->macro_stack_ptr].line =
391                          csound_preget_lineno(yyscanner);
392                        PARM->alt_stack[PARM->macro_stack_ptr].path = NULL;
393                        /* printf("stacked line = %llu at %d\n", */
394                        /*  csound_preget_lineno(yyscanner), */
395                        /* PARM->macro_stack_ptr-1); */
396                        PARM->alt_stack[PARM->macro_stack_ptr].s = NULL;
397                        //csound->DebugMsg(csound,"Push %p macro stack\n",
398                        //                 csound->orc_macros);
399                        yypush_buffer_state(YY_CURRENT_BUFFER, yyscanner);
400                        csound_preset_lineno(1, yyscanner);
401                        if (UNLIKELY(PARM->depth>1022)) {
402                          csound->Message(csound,
403                                          Str("macros/include nested too deep: "));
404                          corfile_puts(csound, "$error", csound->expanded_orc);
405                          err = 1;
406                        }
407                      }
408                      if (!err) {
409                        PARM->lstack[++PARM->depth] =
410                          (strchr(mm->body,'\n') ?file_to_int(csound, mname) : 63);
411                        yy_scan_string(mm->body, yyscanner);
412                        csound_preset_lineno(0, yyscanner); /* for Valgrind */
413                      }
414                    }
415                  }
416 {INCLUDESTR}    {
417                   if (PARM->isString != 1)
418                     PARM->isinclude = 1;
419                   else
420                     corfile_puts(csound, yytext, csound->expanded_orc);
421                 }
422 {INCLUDE}       {
423                   if (PARM->isString != 1)
424                     BEGIN(incl);
425                   else
426                     corfile_puts(csound, yytext, csound->expanded_orc);
427                 }
428 <incl>[ \t]*     /* eat the whitespace */
429 <incl>.         { /* got the include file name */
430                   do_include(csound, yytext[0], yyscanner);
431                   BEGIN(INITIAL);
432                 }
433 #exit           { corfile_putc(csound, '\0', csound->expanded_orc);
434                   corfile_putc(csound, '\0', csound->expanded_orc);
435                   //delete_macros(csound, yyscanner);
436                   return 0;}
437 <<EOF>>         {
438                   MACRO *x, *y=NULL;
439                   int n;
440                   /* csound->DebugMsg(csound,"*********Leaving buffer %p\n", */
441                   /*                  YY_CURRENT_BUFFER); */
442                   yypop_buffer_state(yyscanner);
443                   PARM->depth--;
444                   if (UNLIKELY(PARM->depth > 1024))
445                     csound->Die(csound, Str("unexpected EOF!"));
446                   PARM->llocn = PARM->locn; PARM->locn = make_location(PARM);
447                   /* csound->DebugMsg(csound,"%s(%d): loc=%Ld; lastloc=%Ld\n", */
448                   /*                  __FILE__, __LINE__, */
449                   /*        PARM->llocn, PARM->locn); */
450                   if ( !YY_CURRENT_BUFFER ) yyterminate();
451                   csound->DebugMsg(csound,"End of input; popping to %p\n",
452                           YY_CURRENT_BUFFER);
453                   csound_pre_line(csound, csound->expanded_orc, yyscanner);
454                   n = PARM->alt_stack[--PARM->macro_stack_ptr].n;
455                   if (PARM->alt_stack[PARM->macro_stack_ptr].path) {
456                     //printf("restoring path from %s to %s\n",
457                     //    PARM->path, PARM->alt_stack[PARM->macro_stack_ptr].path);
458                     free(PARM->path);
459                     PARM->path = PARM->alt_stack[PARM->macro_stack_ptr].path;
460                   }
461                   /* printf("lineno on stack is %llu\n", */
462                   /*        PARM->alt_stack[PARM->macro_stack_ptr].line); */
463                   csound->DebugMsg(csound,"n=%d\n", n);
464                   if (n!=0) {
465                     /* We need to delete n macros starting with y */
466                     y = PARM->alt_stack[PARM->macro_stack_ptr].s;
467                     x = csound->orc_macros;
468                     if (x==y) {
469                       while (n>0) {
470                         mfree(csound, y->name); x=y->next;
471                         mfree(csound, y); y=x; n--;
472                       }
473                       csound->orc_macros = x;
474                     }
475                     else {
476                       MACRO *nxt = y->next;
477                       while (x->next != y) x = x->next;
478                       while (n>0) {
479                         nxt = y->next;
480                         mfree(csound, y->name); mfree(csound, y); y=nxt; n--;
481                       }
482                       x->next = nxt;
483                     }
484                     y->next = x;
485                   }
486                   csound_preset_lineno(PARM->alt_stack[PARM->macro_stack_ptr].line,
487                                        yyscanner);
488                   csound->DebugMsg(csound, "csound_pre(%d): line now %d at %d\n",
489                                    __LINE__,
490                                    csound_preget_lineno(yyscanner),
491                                    PARM->macro_stack_ptr);
492                   csound->DebugMsg(csound,
493                                    "End of input segment: macro pop %p -> %p\n",
494                                    y, csound->orc_macros);
495                   //csound_preset_lineno(PARM->alt_stack[PARM->macro_stack_ptr].line,
496                   //                     yyscanner);
497                   //print_csound_predata(csound,"Before pre_line", yyscanner);
498                   csound_pre_line(csound, csound->orchstr, yyscanner);
499                   //print_csound_predata(csound,"After pre_line", yyscanner);
500                 }
501 {DEFINE}        {
502                   if (PARM->isString != 1)
503                     BEGIN(macro);
504                   else
505                     corfile_puts(csound, yytext, csound->expanded_orc);
506                 }
507 <macro>[ \t]*    /* eat the whitespace */
508 <macro>{MACROB} {
509                   yytext[yyleng-1] = '\0';
510                   csound->DebugMsg(csound,"Define macro with args %s\n",
511                                       yytext);
512                   /* print_csound_predata(csound, "Before do_macro_arg",
513                                           yyscanner); */
514                   do_umacroq(csound, yytext, yyscanner);
515                   do_macro_arg(csound, yytext, yyscanner);
516                   //print_csound_predata(csound,"After do_macro_arg", yyscanner);
517                   BEGIN(INITIAL);
518                 }
519 <macro>{MACRO} {
520                   csound->DebugMsg(csound,"Define macro %s\n", yytext);
521                   /* print_csound_predata(csound,"Before do_macro", yyscanner); */
522                   do_umacroq(csound, yytext, yyscanner);
523                   do_macro(csound, yytext, yyscanner);
524                   //print_csound_predata(csound,"After do_macro", yyscanner);
525                   BEGIN(INITIAL);
526                 }
527 <macro>.        { csound->Message(csound,
528                                   Str("Unexpected character %c(%.2x) line %d\n"),
529                                   yytext[0], yytext[0],
530                                   csound_preget_lineno(yyscanner));
531                   csound->LongJmp(csound, 1);
532                 }
533 {UNDEF}         {
534                   if (PARM->isString != 1)
535                     BEGIN(umacro);
536                   else
537                     corfile_puts(csound, yytext, csound->expanded_orc);
538                 }
539 <umacro>[ \t]*    /* eat the whitespace */
540 <umacro>{MACRO}  {
541                   csound->DebugMsg(csound,"Undefine macro %s\n", yytext);
542                   do_umacro(csound, yytext, yyscanner);
543                   BEGIN(INITIAL);
544                 }
545 
546 {IFDEF}         {
547                   if (PARM->isString != 1) {
548                     PARM->isIfndef = (yytext[3] == 'n');  /* #ifdef or #ifndef */
549                     csound_preset_lineno(1+csound_preget_lineno(yyscanner),
550                                          yyscanner);
551                     corfile_putc(csound, '\n', csound->expanded_orc);
552                     csound_pre_line(csound, csound->expanded_orc, yyscanner);
553                     BEGIN(ifdef);
554                   }
555                   else {
556                     corfile_puts(csound, yytext, csound->expanded_orc);
557                   }
558                 }
559 <ifdef>[ \t]*     /* eat the whitespace */
560 <ifdef>{IDENT}  {
561                   do_ifdef(csound, yytext, yyscanner);
562                   BEGIN(INITIAL);
563                 }
564 {ELSE}          {
565                   if (PARM->isString != 1) {
566                     if (PARM->ifdefStack == NULL) {
567                       csound->Message(csound, Str("#else without #if\n"));
568                       csound->LongJmp(csound, 1);
569                     }
570                     else if (PARM->ifdefStack->isElse) {
571                       csound->Message(csound, Str("#else after #else\n"));
572                       csound->LongJmp(csound, 1);
573                     }
574                     PARM->ifdefStack->isElse = 1;
575                     csound_preset_lineno(1+csound_preget_lineno(yyscanner),
576                                          yyscanner);
577                     corfile_putc(csound, '\n', csound->expanded_orc);
578                     csound_pre_line(csound, csound->expanded_orc, yyscanner);
579                     do_ifdef_skip_code(csound, yyscanner);
580                   }
581                   else {
582                     corfile_puts(csound, yytext, csound->expanded_orc);
583                   }
584                 }
585 {END}           {
586                   if (PARM->isString != 1) {
587                     IFDEFSTACK *pp = PARM->ifdefStack;
588                     if (UNLIKELY(pp == NULL)) {
589                       csound->Message(csound, Str("Unmatched #end\n"));
590                       csound->LongJmp(csound, 1);
591                     }
592                     PARM->ifdefStack = pp->prv;
593                     csound_preset_lineno(1+csound_preget_lineno(yyscanner),
594                                          yyscanner);
595                     corfile_putc(csound, '\n', csound->expanded_orc);
596                     csound_pre_line(csound, csound->expanded_orc, yyscanner);
597                     mfree(csound, pp);
598                   }
599                   else {
600                     corfile_puts(csound, yytext, csound->expanded_orc);
601                   }
602 }
603 {IDENT}         { corfile_puts(csound, yytext,csound->expanded_orc); }
604 {INT}           { do_function(csound, yytext,csound->expanded_orc); }
605 {FRAC}          { do_function(csound, yytext,csound->expanded_orc); }
606 {ROUND}         { do_function(csound, yytext,csound->expanded_orc); }
607 {FLOOR}         { do_function(csound, yytext,csound->expanded_orc); }
608 {CEIL}          { do_function(csound, yytext,csound->expanded_orc); }
609 {RND}           { do_function(csound, yytext,csound->expanded_orc); }
610 {BIRND}         { do_function(csound, yytext,csound->expanded_orc); }
611 {ABS}           { do_function(csound, yytext,csound->expanded_orc); }
612 {EXP}           { do_function(csound, yytext,csound->expanded_orc); }
613 {LOG}           { do_function(csound, yytext,csound->expanded_orc); }
614 {SQRT}          { do_function(csound, yytext,csound->expanded_orc); }
615 {SIN}           { do_function(csound, yytext,csound->expanded_orc); }
616 {COS}           { do_function(csound, yytext,csound->expanded_orc); }
617 {TAN}           { do_function(csound, yytext,csound->expanded_orc); }
618 {SININV}        { do_function(csound, yytext,csound->expanded_orc); }
619 {COSINV}        { do_function(csound, yytext,csound->expanded_orc); }
620 {TANINV}        { do_function(csound, yytext,csound->expanded_orc); }
621 {LOG10}         { do_function(csound, yytext,csound->expanded_orc); }
622 {LOG2}          { do_function(csound, yytext,csound->expanded_orc); }
623 {SINH}          { do_function(csound, yytext,csound->expanded_orc); }
624 {COSH}          { do_function(csound, yytext,csound->expanded_orc); }
625 {TANH}          { do_function(csound, yytext,csound->expanded_orc); }
626 {AMPDB}         { do_function(csound, yytext,csound->expanded_orc); }
627 {AMPDBFS}       { do_function(csound, yytext,csound->expanded_orc); }
628 {DBAMP}         { do_function(csound, yytext,csound->expanded_orc); }
629 {DBFSAMP}       { do_function(csound, yytext,csound->expanded_orc); }
630 {FTCPS}         { do_function(csound, yytext,csound->expanded_orc); }
631 {FTLEN}         { do_function(csound, yytext,csound->expanded_orc); }
632 {FTSR}          { do_function(csound, yytext,csound->expanded_orc); }
633 {FTLPTIM}       { do_function(csound, yytext,csound->expanded_orc); }
634 {FTCHNLS}       { do_function(csound, yytext,csound->expanded_orc); }
635 {I}             { do_function(csound, yytext,csound->expanded_orc); }
636 {K}             { do_function(csound, yytext,csound->expanded_orc); }
637 {CPSOCT}        { do_function(csound, yytext,csound->expanded_orc); }
638 {OCTPCH}        { do_function(csound, yytext,csound->expanded_orc); }
639 {CPSPCH}        { do_function(csound, yytext,csound->expanded_orc); }
640 {PCHOCT}        { do_function(csound, yytext,csound->expanded_orc); }
641 {OCTCPS}        { do_function(csound, yytext,csound->expanded_orc); }
642 {NSAMP}         { do_function(csound, yytext,csound->expanded_orc); }
643 {POWOFTWO}      { do_function(csound, yytext,csound->expanded_orc); }
644 {LOGBTWO}       { do_function(csound, yytext,csound->expanded_orc); }
645 {A}             { do_function(csound, yytext,csound->expanded_orc); }
646 {TB0}           { do_function(csound, yytext,csound->expanded_orc); }
647 {TB1}           { do_function(csound, yytext,csound->expanded_orc); }
648 {TB2}           { do_function(csound, yytext,csound->expanded_orc); }
649 {TB3}           { do_function(csound, yytext,csound->expanded_orc); }
650 {TB4}           { do_function(csound, yytext,csound->expanded_orc); }
651 {TB5}           { do_function(csound, yytext,csound->expanded_orc); }
652 {TB6}           { do_function(csound, yytext,csound->expanded_orc); }
653 {TB7}           { do_function(csound, yytext,csound->expanded_orc); }
654 {TB8}           { do_function(csound, yytext,csound->expanded_orc); }
655 {TB9}           { do_function(csound, yytext,csound->expanded_orc); }
656 {TB10}          { do_function(csound, yytext,csound->expanded_orc); }
657 {TB11}          { do_function(csound, yytext,csound->expanded_orc); }
658 {TB12}          { do_function(csound, yytext,csound->expanded_orc); }
659 {TB13}          { do_function(csound, yytext,csound->expanded_orc); }
660 {TB14}          { do_function(csound, yytext,csound->expanded_orc); }
661 {TB15}          { do_function(csound, yytext,csound->expanded_orc); }
662 {URD}           { do_function(csound, yytext,csound->expanded_orc); }
663 {NOT}           { do_function(csound, yytext,csound->expanded_orc); }
664 {CENT}          { do_function(csound, yytext,csound->expanded_orc); }
665 {OCTAVE}        { do_function(csound, yytext,csound->expanded_orc); }
666 {SEMITONE}      { do_function(csound, yytext,csound->expanded_orc); }
667 {CPSMIDIN}      { do_function(csound, yytext,csound->expanded_orc); }
668 {OCTMIDIN}      { do_function(csound, yytext,csound->expanded_orc); }
669 {PCHMIDIN}      { do_function(csound, yytext,csound->expanded_orc); }
670 {DB}            { do_function(csound, yytext,csound->expanded_orc); }
671 {P}             { do_function(csound, yytext,csound->expanded_orc); }
672 {QINF}          { do_function(csound, yytext,csound->expanded_orc); }
673 {QNAN}          { do_function(csound, yytext,csound->expanded_orc); }
674 
675 .               { corfile_putc(csound, yytext[0], csound->expanded_orc); }
676 
677 %%
678 void comment(yyscan_t yyscanner)              /* Skip until nextline */
679 {
680     char c;
681     struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
682     while ((c = input(yyscanner)) != '\n' && c != '\r') { /* skip */
683       if (UNLIKELY((int)c == EOF || c == '\0')) {
684         YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
685           YY_BUFFER_EOF_PENDING;
686         return;
687       }
688     }
689     if (c == '\r' && (c = input(yyscanner)) != '\n') {
690       if (LIKELY((int)c != EOF && c != '\0'))
691         unput(c);
692       else
693         YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
694           YY_BUFFER_EOF_PENDING;
695     }
696     csound_preset_lineno(1+csound_preget_lineno(yyscanner),yyscanner);
697 }
698 
699 void do_comment(yyscan_t yyscanner)              /* Skip until * and / chars */
700 {
701     int c;
702     struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
703  TOP:
704     c = input(yyscanner);
705     switch (c) {
706     NL:
707     case '\n':
708       csound_preset_lineno(1+csound_preget_lineno(yyscanner),yyscanner);
709       goto TOP;
710     case '*':
711     AST:
712       c = input(yyscanner);
713       switch (c) {
714       case '*':
715         goto AST;
716       case '\n':
717         goto NL;
718       case '/':
719         return;
720       case EOF:
721       case '\0':
722         goto ERR;
723       default:
724         goto TOP;
725       }
726     case EOF:
727     ERR:
728       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
729         YY_BUFFER_EOF_PENDING;
730       return;
731     default:
732       goto TOP;
733     }
734 }
735 #ifndef WIN32
736 int isDir(char *path) {
737    struct stat statbuf;
738    if (stat(path, &statbuf) != 0)
739        return 0;
740    return S_ISDIR(statbuf.st_mode);
741 }
742 #else
743 int isDir(char *path) { return 0;}
744 #endif
745 
746 void do_include(CSOUND *csound, int term, yyscan_t yyscanner)
747 {
748     char buffer[100];
749     int p=0;
750     int c;
751     CORFIL *cf;
752     struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
753     while ((c=input(yyscanner))!=term) {
754       if (c=='\n' || c==EOF || c=='\0') {
755         csound->Warning(csound, Str("Ill formed #include ignored"));
756         return;
757       }
758       buffer[p] = c;
759       p++;
760     }
761     buffer[p] = '\0';
762     //printf("****buffer >>%s<<\n", buffer);
763     while ((c=input(yyscanner))!='\n');
764     if (UNLIKELY(PARM->depth++>=1024)) {
765       csound->Die(csound, Str("Includes nested too deeply"));
766     }
767     csound_preset_lineno(1+csound_preget_lineno(yyscanner), yyscanner);
768     csound->DebugMsg(csound,"line %d at end of #include line\n",
769                      csound_preget_lineno(yyscanner));
770     {
771       uint8_t n = file_to_int(csound, buffer);
772       char bb[128];
773       PARM->lstack[PARM->depth] = n;
774       sprintf(bb, "#source %"PRIu64"\n", PARM->locn = make_location(PARM));
775       PARM->llocn = PARM->locn;
776       corfile_puts(csound, bb, csound->expanded_orc);
777     }
778     csound->DebugMsg(csound,"reading included file \"%s\"\n", buffer);
779     if (UNLIKELY(isDir(buffer)))
780       csound->Warning(csound, Str("%s is a directory; not including"), buffer);
781     if (PARM->path && buffer[0]!= DIRSEP) { // if nested included directories
782       char tmp[1024];
783       printf("using path %s\n", PARM->path);
784       strncpy(tmp, PARM->path, 1023);
785       strcat(tmp, "/");
786       strncat(tmp, buffer, 1022-strlen(tmp));
787       if ((cf = copy_to_corefile(csound, tmp, "INCDIR", 0))==NULL)
788           cf = copy_to_corefile(csound, buffer, "INCDIR", 0);
789     }
790     else cf = copy_to_corefile(csound, buffer, "INCDIR", 0);
791     if (UNLIKELY(cf == NULL))
792       csound->Die(csound,
793                   Str("Cannot open #include'd file %s\n"), buffer);
794     if (UNLIKELY(PARM->macro_stack_ptr +1 >= PARM->macro_stack_size )) {
795       PARM->alt_stack =
796         (MACRON*) csound->ReAlloc(csound, PARM->alt_stack,
797                                   sizeof(MACRON)*(PARM->macro_stack_size+=S_INC));
798       if (UNLIKELY(PARM->alt_stack == NULL)) {
799         csound->Message(csound, Str("Memory exhausted"));
800         csound->LongJmp(csound, 1);
801       }
802       /* csound->DebugMsg(csound, "alt_stack now %d long,\n", */
803       /*                  PARM->macro_stack_size); */
804     }
805     csound->DebugMsg(csound,"cso_pre(%d): stacking line %d at %d\n", __LINE__,
806            csound_preget_lineno(yyscanner),PARM->macro_stack_ptr);
807     PARM->alt_stack[PARM->macro_stack_ptr].n = 0;
808     PARM->alt_stack[PARM->macro_stack_ptr].line = csound_preget_lineno(yyscanner);
809     if (strrchr(buffer,DIRSEP)) {
810       PARM->alt_stack[PARM->macro_stack_ptr].path = PARM->path;
811       printf("setting path from %s to ", PARM->path);
812       PARM->path = strdup(buffer); /* wasteful! */
813       *(strrchr(PARM->path,DIRSEP)) = '\0';
814       printf("%s\n",PARM->path);
815     }
816     else PARM->alt_stack[PARM->macro_stack_ptr].path = NULL;
817     PARM->alt_stack[PARM->macro_stack_ptr++].s = NULL;
818     csound_prepush_buffer_state(YY_CURRENT_BUFFER, yyscanner);
819     csound_pre_scan_string(cf->body, yyscanner);
820     corfile_rm(csound, &cf);
821     csound->DebugMsg(csound,"Set line number to 1\n");
822     csound_preset_lineno(1, yyscanner);
823 }
824 
825 void  do_new_include(CSOUND *csound, yyscan_t yyscanner)
826 {
827     char buffer[128];
828     CORFIL *cf = csound->expanded_orc;
829     int p = cf->p-2;
830     struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
831 
832     //printf("*** in do_new_include\n");
833     cf->body[p+1] = '\0';
834     while (cf->body[p]!='"') p--;
835     //printf("*** name is >>%s<<\n", &cf->body[p]);
836     cf->body[p] = '\0';
837     strncpy(buffer, &cf->body[p+1],127); buffer[127]='\0';
838     cf->p = p;
839     //printf("****buffer >>%s<<\n", buffer);
840     while ((input(yyscanner))!='\n');
841     if (UNLIKELY(PARM->depth++>=1024)) {
842       csound->Die(csound, Str("Includes nested too deeply"));
843     }
844     csound_preset_lineno(1+csound_preget_lineno(yyscanner), yyscanner);
845     csound->DebugMsg(csound,"line %d at end of #include line\n",
846                      csound_preget_lineno(yyscanner));
847     {
848       uint8_t n = file_to_int(csound, buffer);
849       char bb[128];
850       PARM->lstack[PARM->depth] = n;
851       sprintf(bb, "#source %"PRIu64"\n", PARM->locn = make_location(PARM));
852       PARM->llocn = PARM->locn;
853       corfile_puts(csound, bb, csound->expanded_orc);
854     }
855     csound->DebugMsg(csound,"reading included file \"%s\"\n", buffer);
856     if (UNLIKELY(isDir(buffer)))
857       csound->Warning(csound, Str("%s is a directory; not including"), buffer);
858     if (PARM->path && buffer[0]!=DIRSEP) {
859       char tmp[1024];
860       strncpy(tmp, PARM->path, 1023);
861       strcat(tmp, "/");
862       strncat(tmp, buffer, 1022-strlen(tmp));
863       cf = copy_to_corefile(csound, tmp, "INCDIR", 0);
864     }
865     else cf = copy_to_corefile(csound, buffer, "INCDIR", 0);
866     if (UNLIKELY(cf == NULL))
867       csound->Die(csound,
868                   Str("Cannot open #include'd file %s\n"), buffer);
869     if (UNLIKELY(PARM->macro_stack_ptr +1 >= PARM->macro_stack_size )) {
870       PARM->alt_stack =
871         (MACRON*) csound->ReAlloc(csound, PARM->alt_stack,
872                                   sizeof(MACRON)*(PARM->macro_stack_size+=S_INC));
873       if (UNLIKELY(PARM->alt_stack == NULL)) {
874         csound->Message(csound, Str("Memory exhausted"));
875         csound->LongJmp(csound, 1);
876       }
877       /* csound->DebugMsg(csound, "alt_stack now %d long,\n", */
878       /*                  PARM->macro_stack_size); */
879     }
880     csound->DebugMsg(csound,"cso_pre(%d): stacking line %d at %d\n", __LINE__,
881            csound_preget_lineno(yyscanner),PARM->macro_stack_ptr);
882     PARM->alt_stack[PARM->macro_stack_ptr].n = 0;
883     PARM->alt_stack[PARM->macro_stack_ptr].line = csound_preget_lineno(yyscanner);
884     if (strrchr(buffer,DIRSEP)) {
885       PARM->alt_stack[PARM->macro_stack_ptr].path = PARM->path;
886       PARM->path = strdup(buffer); /* wasteful! */
887       *(strrchr(PARM->path,DIRSEP)) = '\0';
888     }
889     else PARM->alt_stack[PARM->macro_stack_ptr].path = NULL;
890     PARM->alt_stack[PARM->macro_stack_ptr++].s = NULL;
891     csound_prepush_buffer_state(YY_CURRENT_BUFFER, yyscanner);
892     csound_pre_scan_string(cf->body, yyscanner);
893     corfile_rm(csound, &cf);
894     csound->DebugMsg(csound,"Set line number to 1\n");
895     csound_preset_lineno(1, yyscanner);
896 }
897 
898 static inline int isNameChar(int c, int pos)
899 {
900     c = (int) ((unsigned char) c);
901     return (isalpha(c) || (pos && (c == '_' || isdigit(c))));
902 }
903 
904 static void do_macro_arg(CSOUND *csound, char *name0, yyscan_t yyscanner)
905 {
906     MACRO *mm = (MACRO*) csound->Malloc(csound, sizeof(MACRO));
907     int   arg = 0, i, c;
908     int   size = 100;
909     int mlen = 40;
910     char *q = name0;
911     char *mname = malloc(mlen);
912 
913     if (UNLIKELY(mm == NULL)) {
914       csound->Message(csound, Str("Memory exhausted"));
915       csound->LongJmp(csound, 1);
916     }
917     mm->margs = MARGS;    /* Initial size */
918     mm->name = (char*)csound->Malloc(csound, strlen(name0) + 1);
919     if (UNLIKELY(mm->name == NULL)) {
920       csound->Message(csound, Str("Memory exhausted"));
921       csound->LongJmp(csound, 1);
922     }
923     strcpy(mm->name, name0);
924     do {
925       i = 0;
926       q = name0;
927       mname[i++] = '`';
928       while ((c = *q++)) {
929         mname[i++] = c;
930         if (UNLIKELY(i==mlen))
931           mname = (char *)realloc(mname, mlen+=40);
932         if (UNLIKELY(mname == NULL)) {
933           csound->Message(csound, Str("Memory exhausted"));
934           csound->LongJmp(csound, 1);
935         }
936       }
937       mname[i++] = '`';
938       if (UNLIKELY(i==mlen)) {
939         mname = (char *)realloc(mname, mlen+=40);
940         if (UNLIKELY(mname == NULL)) {
941           csound->Message(csound, Str("Memory exhausted"));
942           csound->LongJmp(csound, 1);
943         }
944       }
945       mname[i++] = '`';
946       if (UNLIKELY(i==mlen)) {
947         mname = (char *)realloc(mname, mlen+=40);
948         if (UNLIKELY(mname == NULL)) {
949           csound->Message(csound, Str("Memory exhausted"));
950           csound->LongJmp(csound, 1);
951         }
952       }
953       while (isspace((c = input(yyscanner))));
954 
955       while (isNameChar(c, i)) {
956         mname[i++] = c;
957         if (UNLIKELY(i==mlen)) {
958           mname = (char *)realloc(mname, mlen+=40);
959           if (UNLIKELY(mname == NULL)) {
960             csound->Message(csound, Str("Memory exhausted"));
961             csound->LongJmp(csound, 1);
962           }
963         }
964         c = input(yyscanner);
965       }
966       mname[i] = '\0';
967       mm->arg[arg] = csound->Malloc(csound, i + 1);
968       if (UNLIKELY(mm->arg[arg] == NULL)) {
969         csound->Message(csound, Str("Memory exhausted"));
970         csound->LongJmp(csound, 1);
971       }
972       strcpy(mm->arg[arg++], mname);
973       if (UNLIKELY(arg >= mm->margs)) {
974         mm = (MACRO*) csound->ReAlloc(csound, mm, sizeof(MACRO)
975                                + mm->margs * sizeof(char*));
976         if (UNLIKELY(mm == NULL)) {
977           csound->Message(csound, Str("Memory exhausted"));
978           csound->LongJmp(csound, 1);
979         }
980         mm->margs += MARGS;
981       }
982       while (isspace(c))
983         c = input(yyscanner);
984     } while (c == '\'' || c == '#');
985     if (UNLIKELY(c != ')')) {
986       csound->Message(csound, Str("macro error\n"));
987     }
988     free(mname);
989     c = input(yyscanner);
990     while (c!='#') {
991       if (UNLIKELY(c==EOF || c=='\0'))
992         csound->Die(csound, Str("define macro runaway\n"));
993       else if (c==';') {
994         while ((c=input(yyscanner))!= '\n')
995           if (UNLIKELY(c==EOF || c=='\0')) {
996             csound->Die(csound, Str("define macro runaway\n"));
997           }
998       }
999       else if (c=='/') {
1000         if ((c=input(yyscanner))=='/') {
1001           while ((c=input(yyscanner))!= '\n')
1002             if (UNLIKELY(c==EOF || c=='\0'))
1003               csound->Die(csound, Str("define macro runaway\n"));
1004         }
1005         else if (c=='*') {
1006           while ((c=input(yyscanner))!='*') {
1007           again:
1008             if (UNLIKELY(c==EOF || c=='\0'))
1009               csound->Die(csound, Str("define macro runaway\n"));
1010           }
1011           if ((c=input(yyscanner))!='/') goto again;
1012         }
1013       }
1014       else if (UNLIKELY(!isspace(c)))
1015         csound->Die(csound,
1016                Str("define macro unexpected character %c(0x%.2x) awaiting #\n"),
1017                     c, c);
1018       c = input(yyscanner); /* skip to start of body */
1019     }
1020     mm->acnt = arg;
1021     i = 0;
1022     mm->body = (char*) csound->Malloc(csound, 100);
1023     if (UNLIKELY(mm->body == NULL)) {
1024       csound->Message(csound, Str("Memory exhausted"));
1025       csound->LongJmp(csound, 1);
1026     }
1027 
1028     while ((c = input(yyscanner)) != '#') { /* read body */
1029       if (UNLIKELY(c == EOF || c == '\0'))
1030         csound->Die(csound, Str("define macro with args: unexpected EOF"));
1031       if (c=='$') {             /* munge macro name? */
1032         int n = strlen(name0)+4;
1033         if (UNLIKELY(i+n >= size)) {
1034           mm->body = csound->ReAlloc(csound, mm->body, size += 100);
1035           if (UNLIKELY(mm->body == NULL)) {
1036             csound->Message(csound, Str("Memory exhausted"));
1037             csound->LongJmp(csound, 1);
1038           }
1039         }
1040         mm->body[i] = '$'; mm->body[i+1] = '`';
1041         strcpy(&mm->body[i+2], name0);
1042         mm->body[i + n - 2] = '`'; mm->body[i + n - 1] = '`';
1043         i+=n;
1044         continue;
1045       }
1046       mm->body[i++] = c=='\r'?'\n':c;
1047       if (UNLIKELY(i >= size)) {
1048         mm->body = csound->ReAlloc(csound, mm->body, size += 100);
1049         if (UNLIKELY(mm->body == NULL)) {
1050           csound->Message(csound, Str("Memory exhausted"));
1051           csound->LongJmp(csound, 1);
1052         }
1053       }
1054       if (c == '\\') {                    /* allow escaped # */
1055         mm->body[i++] = c = input(yyscanner);
1056         if (UNLIKELY(i >= size)) {
1057           mm->body = csound->ReAlloc(csound, mm->body, size += 100);
1058           if (UNLIKELY(mm->body == NULL)) {
1059             csound->Message(csound, Str("Memory exhausted"));
1060             csound->LongJmp(csound, 1);
1061           }
1062         }
1063       }
1064       if (UNLIKELY(c == '\n' || c == '\r')) {
1065         csound_preset_lineno(1+csound_preget_lineno(yyscanner),yyscanner);
1066         corfile_putc(csound, '\n', csound->expanded_orc);
1067         csound_pre_line(csound, csound->expanded_orc, yyscanner);
1068       }
1069     }
1070     mm->body[i] = '\0';
1071     mm->next = csound->orc_macros;
1072     csound->orc_macros = mm;
1073 }
1074 
1075 static void do_macro(CSOUND *csound, char *name0, yyscan_t yyscanner)
1076 {
1077     MACRO *mm = (MACRO*) csound->Malloc(csound, sizeof(MACRO));
1078     int   i, c;
1079     int   size = 100;
1080     if (UNLIKELY(mm == NULL)) {
1081       csound->Message(csound, Str("Memory exhausted"));
1082       csound->LongJmp(csound, 1);
1083     }
1084 
1085     mm->margs = MARGS;    /* Initial size */
1086     csound->DebugMsg(csound,"Macro definition for %s\n", name0);
1087     mm->name = (char*)csound->Malloc(csound, strlen(name0) + 1);
1088     if (UNLIKELY(mm->name == NULL)) {
1089       csound->Message(csound, Str("Memory exhausted"));
1090       csound->LongJmp(csound, 1);
1091     }
1092     strcpy(mm->name, name0);
1093     mm->acnt = 0;
1094     i = 0;
1095     while ((c = input(yyscanner)) != '#') {
1096       if (UNLIKELY(c==EOF || c=='\0'))
1097         csound->Die(csound, Str("define macro runaway\n"));
1098       else if (c==';') {
1099         while ((c=input(yyscanner))!= '\n')
1100           if (UNLIKELY(c==EOF || c=='\0')) {
1101             csound->Die(csound, Str("define macro runaway\n"));
1102           }
1103       }
1104       else if (c=='/') {
1105         if ((c=input(yyscanner))=='/') {
1106           while ((c=input(yyscanner))!= '\n')
1107             if (UNLIKELY(c==EOF || c=='\0'))
1108               csound->Die(csound, Str("define macro runaway\n"));
1109         }
1110         else if (c=='*') {
1111           while ((c=input(yyscanner))!='*') {
1112           again:
1113             if (UNLIKELY(c==EOF || c=='\0'))
1114               csound->Die(csound, Str("define macro runaway\n"));
1115           }
1116           if ((c=input(yyscanner))!='/') goto again;
1117         }
1118       }
1119       else if (UNLIKELY(!isspace(c)))
1120         csound->Die(csound,
1121                     Str("define macro unexpected character %c(0x%.2x)"
1122                         " awaiting #\n"),
1123                     c, c);
1124     }
1125     mm->body = (char*) csound->Malloc(csound, 100);
1126     if (UNLIKELY(mm->body == NULL)) {
1127       csound->Message(csound, Str("Memory exhausted"));
1128       csound->LongJmp(csound, 1);
1129     }
1130     while ((c = input(yyscanner)) != '#') {
1131       if (UNLIKELY(c == EOF || c=='\0'))
1132         csound->Die(csound, Str("define macro: unexpected EOF"));
1133       mm->body[i++] = c=='\r'?'\n':c;
1134       if (UNLIKELY(i >= size)) {
1135         mm->body = csound->ReAlloc(csound, mm->body, size += 100);
1136         if (UNLIKELY(mm->body == NULL)) {
1137           csound->Message(csound, Str("Memory exhausted"));
1138           csound->LongJmp(csound, 1);
1139         }
1140       }
1141       if (c == '\\') {                    /* allow escaped # */
1142         mm->body[i++] = c = input(yyscanner);
1143         if (UNLIKELY(i >= size)) {
1144           mm->body = csound->ReAlloc(csound, mm->body, size += 100);
1145           if (UNLIKELY(mm->body == NULL)) {
1146             csound->Message(csound, Str("Memory exhausted"));
1147             csound->LongJmp(csound, 1);
1148           }
1149         }
1150       }
1151       if (UNLIKELY(c == '\n' || c == '\r')) {
1152         csound_preset_lineno(1+csound_preget_lineno(yyscanner),yyscanner);
1153         corfile_putc(csound, '\n', csound->expanded_orc);
1154         csound_pre_line(csound, csound->expanded_orc, yyscanner);
1155       }
1156     }
1157     mm->body[i] = '\0';
1158     csound->DebugMsg(csound,"Body #%s#\n", mm->body);
1159     mm->next = csound->orc_macros;
1160     csound->orc_macros = mm;
1161 }
1162 
1163 static void do_umacro(CSOUND *csound, char *name0, yyscan_t yyscanner)
1164 {
1165     int i,c;
1166     if (UNLIKELY(csound->oparms->msglevel))
1167       csound->Message(csound,Str("macro %s undefined\n"), name0);
1168     csound->DebugMsg(csound, "macro %s undefined\n", name0);
1169     if (strcmp(name0, csound->orc_macros->name)==0) {
1170       MACRO *mm=csound->orc_macros->next;
1171       mfree(csound, csound->orc_macros->name); mfree(csound, csound->orc_macros->body);
1172       for (i=0; i<csound->orc_macros->acnt; i++)
1173         mfree(csound, csound->orc_macros->arg[i]);
1174       mfree(csound, csound->orc_macros); csound->orc_macros = mm;
1175     }
1176     else {
1177       MACRO *mm = csound->orc_macros;
1178       MACRO *nn = mm->next;
1179       while (strcmp(name0, nn->name) != 0) {
1180         mm = nn; nn = nn->next;
1181         if (UNLIKELY(nn == NULL)) {
1182           csound->Message(csound, Str("Undefining undefined macro"));
1183           csound->LongJmp(csound, 1);
1184         }
1185       }
1186       mfree(csound, nn->name); mfree(csound, nn->body);
1187       for (i=0; i<nn->acnt; i++)
1188         mfree(csound, nn->arg[i]);
1189       mm->next = nn->next; mfree(csound, nn);
1190     }
1191     while ((c=input(yyscanner)) != '\n' &&
1192            c != EOF && c != '\r'); /* ignore rest of line */
1193     csound_preset_lineno(1+csound_preget_lineno(yyscanner),yyscanner);
1194 }
1195 
1196 static void do_umacroq(CSOUND *csound, char *name0, yyscan_t yyscanner)
1197 {
1198     int i;
1199     MACRO *mm = csound->orc_macros, *last = NULL;
1200     while (mm) {
1201       if (strcmp(name0, mm->name)==0) {
1202         MACRO *nn=mm->next;
1203         mfree(csound, mm->name); mfree(csound, mm->body);
1204         for (i=0; i<mm->acnt; i++)
1205           mfree(csound, mm->arg[i]);
1206         mfree(csound, mm);
1207         if (last) last->next = nn;
1208         else csound->orc_macros = nn;
1209         return;
1210       }
1211       last = mm; mm = last->next;
1212     }
1213     return;
1214 }
1215 
1216 static void do_ifdef(CSOUND *csound, char *name0, yyscan_t yyscanner)
1217 {
1218     int c;
1219     MACRO *mm;
1220     IFDEFSTACK *pp;
1221     pp = (IFDEFSTACK*) csound->Calloc(csound, sizeof(IFDEFSTACK));
1222     if (UNLIKELY(pp == NULL)) {
1223       csound->Message(csound, Str("Memory exhausted"));
1224       csound->LongJmp(csound, 1);
1225     }
1226     pp->prv = PARM->ifdefStack;
1227     pp->isDef = PARM->isIfndef;
1228     for (mm = csound->orc_macros; mm != NULL; mm = mm->next) {
1229       if (strcmp(name0, mm->name) == 0) {
1230         pp->isDef ^= (unsigned char) 1;
1231         break;
1232       }
1233     }
1234     PARM->ifdefStack = pp;
1235     pp->isSkip = pp->isDef ^ (unsigned char) 1;
1236     if (pp->isSkip)
1237       do_ifdef_skip_code(csound, yyscanner);
1238     else
1239       while ((c = input(yyscanner)) != '\n' && c != '\r' && c != EOF);
1240 }
1241 
1242 static void do_ifdef_skip_code(CSOUND *csound, yyscan_t yyscanner)
1243 {
1244     int i, c, nested_ifdef = 0;
1245     char buf[8];
1246     IFDEFSTACK *pp;
1247     /* buf = (char*)malloc(8*sizeof(char)); */
1248     /* if (UNLIKELY(buf == NULL)) { */
1249     /*   csound->Message(csound, Str("Memory exhausted")); */
1250     /*   csound->LongJmp(csound, 1); */
1251     /* } */
1252     pp = PARM->ifdefStack;
1253     c = input(yyscanner);
1254     for (;;) {
1255       while (c!='\n' && c!= '\r') {
1256         if (UNLIKELY(c == EOF || c=='\0')) {
1257           csound->Message(csound, Str("Unmatched #if%sdef\n"),
1258                           PARM->isIfndef ? "n" : "");
1259           csound->LongJmp(csound, 1);
1260         }
1261         c = input(yyscanner);
1262       }
1263       csound_preset_lineno(1+csound_preget_lineno(yyscanner),
1264                            yyscanner);
1265       corfile_putc(csound, '\n', csound->expanded_orc);
1266       csound_pre_line(csound, csound->expanded_orc, yyscanner);
1267       while (isblank(c = input(yyscanner)));  /* eat the whitespace */
1268       if (c == '#') {
1269         for (i=0; islower(c = input(yyscanner)) && i < 7; i++)
1270           buf[i] = c;
1271         buf[i] = '\0';
1272         if (strcmp("end", buf) == 0 || strcmp("endif", buf) == 0) {
1273           if (nested_ifdef-- == 0) {
1274             PARM->ifdefStack = pp->prv;
1275             mfree(csound, pp);
1276             break;
1277           }
1278         }
1279         else if (strcmp("ifdef", buf) == 0 || strcmp("ifndef", buf) == 0) {
1280           nested_ifdef++;
1281         }
1282         else if (strcmp("else", buf) == 0 && nested_ifdef == 0) {
1283           if (UNLIKELY(pp->isElse)) {
1284             csound->Message(csound, Str("#else after #else\n"));
1285             csound->LongJmp(csound, 1);
1286           }
1287           pp->isElse = 1;
1288           break;
1289         }
1290       }
1291     }
1292     while (c != '\n' && c != EOF && c != '\r') c = input(yyscanner);
1293 }
1294 
1295 #if 0
1296 static void delete_macros(CSOUND *csound, yyscan_t yyscanner)
1297 {
1298     MACRO * qq = csound->orc_macros;
1299     if (qq) {
1300       MACRO *mm = qq;
1301       while (mm) {
1302         csound->Free(csound, mm->body);
1303         csound->Free(csound, mm->name);
1304         qq = mm->next;
1305         csound->Free(csound, mm);
1306         mm = qq;
1307        }
1308     }
1309 }
1310 #endif
1311 
1312 static void add_math_const_macro(CSOUND *csound, char * name, char *body)
1313 {
1314     MACRO *mm;
1315 
1316     mm = (MACRO*) csound->Calloc(csound, sizeof(MACRO));
1317     mm->name = (char*) csound->Calloc(csound, strlen(name) + 3);
1318     sprintf(mm->name, "M_%s", name);
1319     mm->next = csound->orc_macros;
1320     csound->orc_macros = mm;
1321     mm->margs = MARGS;    /* Initial size */
1322     mm->acnt = 0;
1323     mm->body = (char*) csound->Calloc(csound, strlen(body) + 1);
1324     mm->body = strcpy(mm->body, body);
1325 }
1326 
1327 /**
1328  * Add math constants from math.h as orc csound->orc_macros
1329  */
1330 void cs_init_math_constants_macros(CSOUND *csound)
1331 {
1332     if (csound->orc_macros == NULL) {
1333       add_math_const_macro(csound, "E",     "2.71828182845904523536");
1334       add_math_const_macro(csound, "LOG2E", "1.44269504088896340736");
1335       add_math_const_macro(csound, "LOG10E","0.43429448190325182765");
1336       add_math_const_macro(csound, "LN2",   "0.69314718055994530942");
1337       add_math_const_macro(csound, "LN10",  "2.30258509299404568402");
1338       add_math_const_macro(csound, "PI",    "3.14159265358979323846");
1339       add_math_const_macro(csound, "PI_2",  "1.57079632679489661923");
1340       add_math_const_macro(csound, "PI_4",  "0.78539816339744830962");
1341       add_math_const_macro(csound, "1_PI",  "0.31830988618379067154");
1342       add_math_const_macro(csound, "2_PI",  "0.63661977236758134308");
1343       add_math_const_macro(csound, "2_SQRTPI", "1.12837916709551257390");
1344       add_math_const_macro(csound, "SQRT2", "1.41421356237309504880");
1345       add_math_const_macro(csound, "SQRT1_2","0.70710678118654752440");
1346       add_math_const_macro(csound, "INF",   "800000000000.0");/* ~25367 years */
1347     }
1348 }
1349 
1350 void cs_init_omacros(CSOUND *csound, NAMES *nn)
1351 {
1352     while (nn) {
1353       char  *s = nn->mac;
1354       char  *p = strchr(s, '=');
1355       char  *mname;
1356       MACRO *mm;
1357 
1358       if (p == NULL)
1359         p = s + strlen(s);
1360       if (csound->oparms->msglevel & 7)
1361         csound->Message(csound, Str("Macro definition for %*s\n"), (int)(p - s), s);
1362       s = strchr(s, ':') + 1;                   /* skip arg bit */
1363       if (UNLIKELY(s == NULL || s >= p)) {
1364         csound->Die(csound, Str("Invalid macro name for --omacro"));
1365       }
1366       mname = (char*) csound->Malloc(csound, (p - s) + 1);
1367       if (UNLIKELY(mname == NULL)) {
1368         csound->Message(csound, Str("Memory exhausted"));
1369         csound->LongJmp(csound, 1);
1370       }
1371       strncpy(mname, s, p - s);
1372       mname[p - s] = '\0';
1373       /* check if macro is already defined */
1374       for (mm = csound->orc_macros; mm != NULL; mm = mm->next) {
1375         if (strcmp(mm->name, mname) == 0)
1376           break;
1377       }
1378       if (mm == NULL) {
1379         mm = (MACRO*) csound->Calloc(csound, sizeof(MACRO));
1380         if (UNLIKELY(mm  == NULL)) {
1381           csound->Message(csound, Str("Memory exhausted"));
1382           csound->LongJmp(csound, 1);
1383         }
1384         mm->name = mname;
1385         mm->next = csound->orc_macros;
1386         csound->orc_macros = mm;
1387       }
1388       else
1389         mfree(csound, mname);
1390       mm->margs = MARGS;    /* Initial size */
1391       mm->acnt = 0;
1392       if (*p != '\0')
1393         p++;
1394       mm->body = (char*) csound->Malloc(csound, strlen(p) + 1);
1395       if (UNLIKELY(mm->body == NULL)) {
1396         csound->Message(csound, Str("Memory exhausted"));
1397         csound->LongJmp(csound, 1);
1398       }
1399       strcpy(mm->body, p);
1400       nn = nn->next;
1401     }
1402 }
1403 
1404 /* int csound_prewrap(void *yyscanner)  */
1405 /* {  */
1406 /*     return 1; */
1407 /* } */
1408 
1409 void csound_pre_line(CSOUND *csound, CORFIL* cf, void *yyscanner)
1410 {
1411     int n = csound_preget_lineno(yyscanner);
1412     //printf("line number %d\n", n);
1413     /* This assumes that the initial line was not written with this system  */
1414     if (cf->p>0 && cf->body[cf->p-1]=='\n') {
1415       uint64_t locn = PARM->locn;
1416       uint64_t llocn = PARM->llocn;
1417       if (UNLIKELY(locn != llocn)) {
1418         char bb[80];
1419         sprintf(bb, "#source %"PRIu64"\n", locn);
1420         corfile_puts(csound, bb, cf);
1421       }
1422       PARM->llocn = locn;
1423       if (UNLIKELY(n!=PARM->line+1)) {
1424         char bb[80];
1425         sprintf(bb, "#line   %d\n", n);
1426         corfile_puts(csound, bb, cf);
1427       }
1428     }
1429     PARM->line = n;
1430 }
1431 
1432 void do_function(CSOUND *csound, char *text, CORFIL *cf)
1433 {
1434     char *p = text;
1435     //printf("do_function on >>%s<<\n", text);
1436     while (*p != '\0') {
1437       if (!isspace(*p)) corfile_putc(csound, *p, cf);
1438       p++;
1439     }
1440     return;
1441 }
1442 
1443 static MACRO *find_definition(MACRO *mmo, char *s)
1444 {
1445     MACRO *mm = mmo;
1446     if (s[strlen(s)-1]=='.') s[strlen(s)-1]='\0';
1447     else if (s[strlen(s)-2]=='.' && s[strlen(s)-1]=='(') {
1448       s[strlen(s)-2] = '('; s[strlen(s)-1] = '\0'; }
1449     // printf("****Looking for %s strlen=%d\n", s, strlen(s), s[strlen(s)-1]);
1450     while (mm != NULL) {  /* Find the definition */
1451       //printf("looking at %p(%s) body #%s#\n", mm, mm->name, mm->body);
1452       if (!(strcmp(s, mm->name))) break;
1453       mm = mm->next;
1454     }
1455     if (mm == NULL) {
1456       mm = mmo;
1457       s++;                      /* skip _ */
1458     looking:
1459       while (*s++!='`') { if (*s=='\0') return NULL; }
1460       if (*s++!='`') { s--; goto looking; }
1461       //printf("now try looking for %s\n", s);
1462       while (mm != NULL) {  /* Find the definition */
1463         //printf("looking at %p(%s) body #%s#\n", mm, mm->name, mm->body);
1464         if (!(strcmp(s, mm->name))) break;
1465         mm = mm->next;
1466       }
1467     }
1468     //if (mm) printf("found body #%s#\n****\n", mm->body);
1469     return mm;
1470 }
1471 
1472 
1473 #if 0
1474 static void print_csound_predata(CSOUND *csound, char *mesg, void *yyscanner)
1475 {
1476     struct yyguts_t *yyg =(struct yyguts_t*)yyscanner;
1477     csound->DebugMsg(csound,"********* %s extra data ************", mesg);
1478     csound->DebugMsg(csound,"yyscanner = %p", yyscanner);
1479     csound->DebugMsg(csound,"yyextra_r = %p, yyin_r = %p, yyout_r = %p,"
1480                      " yy_buffer_stack_top = %d",
1481            yyg->yyextra_r, yyg->yyin_r,yyg->yyout_r, yyg->yy_buffer_stack_top);
1482     csound->DebugMsg(csound,"yy_buffer_stack_max = %d1, yy_buffer_stack = %p, "
1483                      "yy_hold_char = %d '%c'",
1484            yyg->yy_buffer_stack_max, yyg->yy_buffer_stack, yyg->yy_hold_char,
1485            yyg->yy_hold_char);
1486     csound->DebugMsg(csound,"yy_n_chars = %d, yyleng_r = %d, yy_c_buf_p = %p %c",
1487            yyg->yy_n_chars, yyg->yyleng_r, yyg->yy_c_buf_p, *yyg->yy_c_buf_p);
1488     csound->DebugMsg(csound,"yy_init = %d, yy_start = %d, "
1489                      "yy_did_buffer_switch_on_eof = %d",
1490            yyg->yy_init, yyg->yy_start, yyg->yy_did_buffer_switch_on_eof);
1491     csound->DebugMsg(csound,"yy_start_stack_ptr = %d,"
1492                      " yy_start_stack_depth = %d, yy_start_stack = %p",
1493            yyg->yy_start_stack_ptr, yyg->yy_start_stack_depth, yyg->yy_start_stack);
1494 
1495     csound->DebugMsg(csound,"yy_last_accepting_state = %d, "
1496                      "yy_last_accepting_cpos = %p %c",
1497            yyg->yy_last_accepting_state, yyg->yy_last_accepting_cpos,
1498                      *yyg->yy_last_accepting_cpos);
1499     csound->DebugMsg(csound,"yylineno_r = %d, yy_flex_debug_r = %d, "
1500                      "yytext_r = %p \"%s\", yy_more_flag = %d, yy_more_len = %d",
1501            yyg->yylineno_r, yyg->yy_flex_debug_r, yyg->yytext_r, yyg->yytext_r,
1502                      yyg->yy_more_flag, yyg->yy_more_len);
1503     {
1504       PRE_PARM* pp = yyg->yyextra_r;
1505       printf("macros = %p, isIfndef = %d, isString = %d, line - %d loc = %d\n",
1506              pp->macros, pp->isIfndef, pp->isString, pp->line, pp->locn);
1507       printf
1508         ("llocn = %d dept=%d\n", pp->llocn, pp->depth);
1509     }
1510     csound->DebugMsg(csound,"*********\n");
1511 }
1512 #endif
1513