2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
35 # include <sys/param.h>
38 #include <boost/filesystem/path.hpp>
41 #include "PyrParseNode.h"
42 #include "Bison/lang11d_tab.h"
44 #include "PyrObject.h"
45 #include "PyrObjectProto.h"
48 #include "SC_InlineUnaryOp.h"
49 #include "SC_InlineBinaryOp.h"
51 #include "SimpleStack.h"
53 #include "PyrSymbolTable.h"
54 #include "PyrInterpreter.h"
55 #include "PyrPrimitive.h"
56 #include "PyrObjectProto.h"
57 #include "PyrPrimitiveProto.h"
58 #include "PyrKernelProto.h"
59 #include "InitAlloc.h"
60 #include "PredefinedSymbols.h"
67 #include "SC_LibraryConfig.h"
69 #include "SC_DirUtils.h"
70 #include "SC_TextUtils.hpp"
73 int processaccidental1(char *s
);
74 int processaccidental2(char *s
);
77 extern bool gFullyFunctional
;
78 double compileStartTime
;
79 int gNumCompiledFiles
;
81 thisProcess.interpreter.executeFile("Macintosh HD:score").size.postln;
84 PyrSymbol
*gCompilingFileSym
= 0;
85 VMGlobals
*gCompilingVMGlobals
= 0;
86 static char gCompileDir
[MAXPATHLEN
];
89 bool gDebugLexer
= false;
91 bool gShowWarnings
= false;
93 LongStack closedFuncCharNo
;
94 LongStack generatorStack
;
95 int lastClosedFuncCharNo
= 0;
97 const char *binopchars
= "!@%&*-+=|<>?/";
98 char yytext
[MAXYYLEN
];
99 char curfilename
[PATH_MAX
];
103 bool compilingCmdLine
= false;
104 bool compilingCmdLineErrorWindow
= false;
107 int lineno
, charno
, linepos
;
114 int errLineOffset
, errCharPosOffset
;
116 bool compiledOK
= false;
117 std::set
<std::string
> compiledDirectories
;
119 /* so the text editor's dumb paren matching will work */
120 #define OPENPAREN '('
121 #define OPENCURLY '{'
122 #define OPENSQUAR '['
123 #define CLOSSQUAR ']'
124 #define CLOSCURLY '}'
125 #define CLOSPAREN ')'
127 int sc_strtoi(const char *str
, int n
, int base
)
130 for (int i
=0; i
<n
; ++i
)
134 if (c
>= '0' && c
<= '0' + sc_min(10,base
) - 1) z
= z
* base
+ c
- '0';
135 else if (c
>= 'a' && c
<= 'a' + sc_min(36,base
) - 11) z
= z
* base
+ c
- 'a' + 10;
136 else if (c
>= 'A' && c
<= 'A' + sc_min(36,base
) - 11) z
= z
* base
+ c
- 'A' + 10;
141 double sc_strtof(const char *str
, int n
, int base
)
145 for (int i
=0; i
<n
; ++i
)
149 if (c
>= '0' && c
<= '0' + sc_min(10,base
) - 1) z
= z
* base
+ c
- '0';
150 else if (c
>= 'a' && c
<= 'a' + sc_min(36,base
) - 11) z
= z
* base
+ c
- 'a' + 10;
151 else if (c
>= 'A' && c
<= 'A' + sc_min(36,base
) - 11) z
= z
* base
+ c
- 'A' + 10;
152 else if (c
== '.') decptpos
= i
;
154 //calculation previously included decimal point in count of columns (was n-decptpos); there are 1 less than n characters which are columns in the number contribution
155 z
= z
/ pow((double)base
, n
-1- decptpos
);
159 static void sc_InitCompileDirectory(void)
161 // main class library folder: only used for relative path resolution
162 sc_GetResourceDirectory(gCompileDir
, MAXPATHLEN
-32);
163 sc_AppendToPath(gCompileDir
, MAXPATHLEN
, "SCClassLibrary");
166 extern void asRelativePath(char *inPath
, char *outPath
)
168 uint32 len
= strlen(gCompileDir
);
169 if (strlen(inPath
) < len
|| memcmp(inPath
, gCompileDir
, len
) != 0) {
170 // gCompileDir is not the prefix.
171 strcpy(outPath
, inPath
);
174 strcpy(outPath
, inPath
+ len
);
178 static bool getFileText(char* filename
, char **text
, int *length
)
185 file
= fopen(filename
, "rb");
187 file
= fopen(filename
, "r");
189 if (!file
) return false;
191 fseek(file
, 0L, SEEK_END
);
192 llength
= ftell(file
);
193 fseek(file
, 0L, SEEK_SET
);
194 ltext
= (char*)pyr_pool_compile
->Alloc((llength
+1) * sizeof(char));
196 // win32 isprint( ) doesn't like the 0xcd after the end of file when
197 // there is a mismatch in lengths due to line endings....
198 memset(ltext
,0,(llength
+1) * sizeof(char));
202 size_t size
= fread(ltext
, 1, llength
, file
);
203 if (size
!= llength
) {
204 error("error when reading file");
209 //ltext[llength] = 0;
220 bool startLexer(PyrSymbol
*fileSym
, int startPos
, int endPos
, int lineOffset
)
222 char *filename
= fileSym
->name
;
226 if(!fileSym
->u
.source
) {
227 if (!getFileText(filename
, &text
, &textlen
)) return false;
228 fileSym
->u
.source
= text
;
232 text
= fileSym
->u
.source
;
234 if((startPos
>= 0) && (endPos
> 0)) {
235 textlen
= endPos
- startPos
;
238 else if(textlen
== -1)
239 textlen
= strlen(text
);
241 if(lineOffset
> 0) errLineOffset
= lineOffset
;
242 else errLineOffset
= 0;
244 if(startPos
> 0) errCharPosOffset
= startPos
;
245 else errCharPosOffset
= 0;
247 initLongStack(&brackets
);
248 initLongStack(&closedFuncCharNo
);
249 initLongStack(&generatorStack
);
250 lastClosedFuncCharNo
= 0;
260 strcpy(curfilename
, filename
);
261 maxlinestarts
= 1000;
262 linestarts
= (int*)pyr_pool_compile
->Alloc(maxlinestarts
* sizeof(int*));
269 void startLexerCmdLine(char *textbuf
, int textbuflen
)
272 // lifetime: kill after compile. (this one gets killed anyway)
273 text
= (char*)pyr_pool_compile
->Alloc((textbuflen
+2) * sizeof(char));
275 memcpy(text
, textbuf
, textbuflen
);
276 text
[textbuflen
] = ' ';
277 text
[textbuflen
+1] = 0;
278 textlen
= textbuflen
+ 1;
282 initLongStack(&brackets
);
283 initLongStack(&closedFuncCharNo
);
284 initLongStack(&generatorStack
);
285 lastClosedFuncCharNo
= 0;
295 strcpy(curfilename
, "selected text");
296 maxlinestarts
= 1000;
297 linestarts
= (int*)pyr_pool_compile
->Alloc(maxlinestarts
* sizeof(int*));
302 errCharPosOffset
= 0;
307 pyr_pool_compile
->Free(linestarts
);
308 freeLongStack(&brackets
);
309 freeLongStack(&closedFuncCharNo
);
310 freeLongStack(&generatorStack
);
315 //strcpy(binopchars, "!@%&*-+=|:<>?/");
321 if (textpos
>= textlen
) {
327 if (c
== '\n' || c
== '\r') {
331 if (lineno
>= maxlinestarts
) {
332 maxlinestarts
+= maxlinestarts
;
333 linestarts
= (int*)pyr_pool_compile
->Realloc(
334 linestarts
, maxlinestarts
* sizeof(int*));
336 linestarts
[lineno
] = linepos
;
340 if (c
!= 0 && yylen
< MAXYYLEN
-2) yytext
[yylen
++] = c
;
341 //if (gDebugLexer) postfl("input '%c' %d\n",c,c);
348 if (textpos
>= textlen
) {
350 textpos
++; // so unput will work properly
355 if (c
== '\n' || c
== '\r') {
359 if (lineno
>= maxlinestarts
) {
360 maxlinestarts
+= maxlinestarts
;
361 linestarts
= (int*)pyr_pool_compile
->Realloc(
362 linestarts
, maxlinestarts
* sizeof(int*));
364 linestarts
[lineno
] = linepos
;
368 //if (gDebugLexer) postfl("input0 '%c' %d\n",c,c);
374 if (textpos
>0) textpos
--;
377 if (charno
) --charno
;
378 if (c
== '\n' || c
== '\r') {
386 if (textpos
>0) textpos
--;
387 if (charno
) --charno
;
388 if (c
== '\n' || c
== '\r') {
397 char extPath
[MAXPATHLEN
]; // for error reporting
400 // finite state machine to parse input stream into tokens
402 if (lexCmdLine
== 1) {
410 if (c
== 0) { r
= 0; goto leave
; }
411 else if (c
==' ' || c
=='\t' || c
=='\n' || c
=='\r' || c
=='\v' || c
=='\f') {
415 else if ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z') || c
== '_') goto ident
;
418 if (c
== '/') goto comment1
;
419 else if (c
== '*') goto comment2
;
420 else { unput(c
); goto binop
; }
422 else if (c
>= '0' && c
<= '9') goto digits_1
;
423 else if (c
== OPENPAREN
|| c
== OPENSQUAR
|| c
== OPENCURLY
) {
424 pushls(&brackets
, (int)c
);
425 if (c
== OPENCURLY
) {
426 pushls(&closedFuncCharNo
, linestarts
[lineno
] + charno
- 1);
431 else if (c
== CLOSSQUAR
) {
432 if (!emptyls(&brackets
)) {
433 if ((d
= popls(&brackets
)) != OPENSQUAR
) {
435 post("opening bracket was a '%c', but found a '%c'\n",d
,c
);
440 post("unmatched '%c'\n",c
);
446 else if (c
== CLOSPAREN
) {
447 if (!emptyls(&brackets
)) {
448 if ((d
= popls(&brackets
)) != OPENPAREN
) {
450 post("opening bracket was a '%c', but found a '%c'\n",d
,c
);
455 post("unmatched '%c'\n",c
);
461 else if (c
== CLOSCURLY
) {
462 if (!emptyls(&brackets
)) {
463 if ((d
= popls(&brackets
)) != OPENCURLY
) {
465 post("opening bracket was a '%c', but found a '%c'\n",d
,c
);
468 lastClosedFuncCharNo
= popls(&closedFuncCharNo
);
471 post("unmatched '%c'\n",c
);
477 else if (c
== '^') { r
= c
; goto leave
; }
478 else if (c
== '~') { r
= c
; goto leave
; }
479 else if (c
== ';') { r
= c
; goto leave
; }
480 else if (c
== ':') { r
= c
; goto leave
; }
481 else if (c
== '`') { r
= c
; goto leave
; }
482 else if (c
== '\\') goto symbol1
;
483 else if (c
== '\'') goto symbol3
;
484 else if (c
== '"') goto string1
;
486 if ((c
= input()) == '.') {
487 if ((c
= input()) == '.') {
503 if ((c
= input()) == OPENCURLY
) {
504 pushls(&brackets
, OPENCURLY
);
505 pushls(&closedFuncCharNo
, linestarts
[lineno
] + charno
- 2);
518 case 'n' : c
= '\n'; break;
519 case 'r' : c
= '\r'; break;
520 case 't' : c
= '\t'; break;
521 case 'f' : c
= '\f'; break;
522 case 'v' : c
= '\v'; break;
528 else if (c
== ',') { r
= c
; goto leave
; }
531 if (strchr(binopchars
, c
)) goto binop
;
538 else if (strchr(binopchars
, c
)) goto binop
;
539 else if(!(isprint(c
) || isspace(c
) || c
== 0)) {
548 if ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z')
549 || c
== '_' || (c
>= '0' && c
<= '9')) goto ident
;
552 r
= processkeywordbinop(yytext
) ;
557 r
= processident(yytext
) ;
564 if ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z') || c
== '_') goto symbol2
;
565 else if (c
>= '0' && c
<= '9') goto symbol4
;
569 r
= processsymbol(yytext
) ;
576 if ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z')
577 || c
== '_' || (c
>= '0' && c
<= '9')) goto symbol2
;
581 r
= processsymbol(yytext
) ;
587 if (c
>= '0' && c
<= '9') goto symbol4
;
591 r
= processsymbol(yytext
) ;
601 if (c
== 0) goto binop2
;
602 if (strchr(binopchars
, c
)) goto binop
;
607 r
= processbinop(yytext
) ;
614 if (c
>= '0' && c
<= '0' + sc_min(10,radix
) - 1) goto radix_digits_1
;
615 if (c
>= 'a' && c
<= 'a' + sc_min(36,radix
) - 11) goto radix_digits_1
;
616 if (c
>= 'A' && c
<= 'A' + sc_min(36,radix
) - 11) goto radix_digits_1
;
622 r
= processintradix(yytext
, yylen
, radix
);
628 if (c
>= '0' && c
<= '0' + sc_min(10,radix
) - 1) goto radix_digits_2
;
629 if (c
>= 'A' && c
<= 'A' + sc_min(36,radix
) - 11) goto radix_digits_2
;
630 // do not allow lower case after decimal point.
633 r
= processfloatradix(yytext
, yylen
, radix
);
639 if (c
>= '0' && c
<= '9') goto hexdigits
;
640 if (c
>= 'a' && c
<= 'f') goto hexdigits
;
641 if (c
>= 'A' && c
<= 'F') goto hexdigits
;
644 r
= processhex(yytext
);
647 digits_1
: /* number started with digits */
651 if (c
>= '0' && c
<= '9') goto digits_1
;
653 radix
= sc_strtoi(yytext
, yylen
-1, 10);
657 else if (c
== 'e' || c
== 'E') goto expon_1
;
660 if (c2
>= '0' && c2
<= '9') goto digits_2
;
665 r
= processint(yytext
);
669 else if (c
== 'b' || c
== 's') {
671 if (d
>= '0' && d
<= '9') goto accidental1
;
672 if (d
== c
) goto accidental2
;
676 if (d
>= '0' && d
<= '9') goto accidental1
;
679 r
= processaccidental1(yytext
);
683 if (d
== c
) goto accidental2
;
687 r
= processaccidental2(yytext
);
696 r
= processint(yytext
);
704 if (c
>= '0' && c
<= '9') goto digits_2
;
705 else if (c
== 'e' || c
== 'E') goto expon_1
;
706 // else if (c == 'π' || c == '∏') {
708 // yytext[yylen] = 0;
709 // r = processfloat(yytext, 1);
715 r
= processfloat(yytext
, 0);
719 expon_1
: /* e has been seen, need digits */
722 if (c
>= '0' && c
<= '9') goto expon_3
;
723 else if (c
== '+' || c
== '-') goto expon_2
;
726 expon_2
: /* + or - seen but still need digits */
729 if (c
>= '0' && c
<= '9') goto expon_3
;
735 if (c
>= '0' && c
<= '9') goto expon_3
;
736 // else if (c == 'π' || c == '∏') {
738 // yytext[yylen] = 0;
739 // r = processfloat(yytext, 1);
745 r
= processfloat(yytext
, 0);
750 int startline
, endchar
;
756 } while (c != endchar && c != 0);*/
757 for (;yylen
<MAXYYLEN
;) {
759 if (c
== '\n' || c
== '\r') {
760 asRelativePath(curfilename
,extPath
);
761 post("Symbol open at end of line on line %d in file '%s'\n",
762 startline
+errLineOffset
, extPath
);
770 } else if (c
== endchar
) break;
774 asRelativePath(curfilename
,extPath
);
775 post("Open ended symbol ... started on line %d in file '%s'\n",
776 startline
+errLineOffset
, extPath
);
783 r
= processsymbol(yytext
);
788 int startline
, endchar
;
792 for (;yylen
<MAXYYLEN
;) {
798 case 'n' : yytext
[yylen
-1] = '\n'; break;
799 case 'r' : yytext
[yylen
-1] = '\r'; break;
800 case 't' : yytext
[yylen
-1] = '\t'; break;
801 case 'f' : yytext
[yylen
-1] = '\f'; break;
802 case 'v' : yytext
[yylen
-1] = '\v'; break;
804 } else if (c
== '\r') c
= '\n';
805 else if (c
== endchar
) break;
809 asRelativePath(curfilename
,extPath
);
810 post("Open ended string ... started on line %d in file '%s'\n",
811 startline
+errLineOffset
, extPath
);
820 } while (c
&& isspace(c
));
822 if (c
== '"') goto string1
;
823 else if (c
) unput0(c
);
826 r
= processstring(yytext
);
830 comment1
: /* comment -- to end of line */
833 } while (c
!= '\n' && c
!= '\r' && c
!= 0);
835 if (c
== 0) { r
= 0; goto leave
; }
839 int startline
, clevel
, prevc
;
845 if (c
== '/' && prevc
== '*') {
846 if (--clevel
<= 0) break;
847 } else if (c
== '*' && prevc
== '/') clevel
++;
852 asRelativePath(curfilename
,extPath
);
853 post("Open ended comment ... started on line %d in file '%s'\n",
854 startline
+errLineOffset
, extPath
);
866 asRelativePath(curfilename
, extPath
);
867 post("illegal input string '%s' \n at '%s' line %d char %d\n",
868 yytext
, extPath
, lineno
+errLineOffset
, charno
);
869 post("code %d\n", c
);
870 //postfl(" '%c' '%s'\n", c, binopchars);
871 //postfl("%d\n", strchr(binopchars, c));
874 asRelativePath(curfilename
, extPath
);
875 post(" in file '%s' line %d char %d\n", extPath
, lineno
+errLineOffset
, charno
);
883 if (gDebugLexer
) postfl("yylex: %d '%s'\n",r
,yytext
);
885 //if (lexCmdLine>0) postfl("yylex: %d '%s'\n",r,yytext);
889 int processbinop(char *token
)
896 if (gDebugLexer
) postfl("processbinop: '%s'\n",token
);
899 SetSymbol(&slot
, sym
);
900 node
= newPyrSlotNode(&slot
);
902 if (strcmp(token
, "<-")==0) return LEFTARROW
;
903 if (strcmp(token
, "<>")==0) return READWRITEVAR
;
904 if (strcmp(token
, "|")==0) return '|';
905 if (strcmp(token
, "<")==0) return '<';
906 if (strcmp(token
, ">")==0) return '>';
907 if (strcmp(token
, "-")==0) return '-';
908 if (strcmp(token
, "*")==0) return '*';
909 if (strcmp(token
, "+")==0) return '+';
913 int processkeywordbinop(char *token
)
919 //post("'%s' file '%s'\n", token, curfilename);
922 if (gDebugLexer
) postfl("processkeywordbinop: '%s'\n",token
);
924 token
[strlen(token
)-1] = 0; // strip off colon
926 SetSymbol(&slot
, sym
);
927 node
= newPyrSlotNode(&slot
);
932 int processident(char *token
)
944 if (gDebugLexer
) postfl("word: '%s'\n",token
);
947 strcpy(uptoken, token);
948 for (str = uptoken; *str; ++str) {
949 if (*str >= 'a' && *str <= 'z') *str += 'A' - 'a';
952 if (token
[0] == '_') {
954 node
= newPyrCurryArgNode();
959 SetSymbol(&slot
, sym
);
960 node
= newPyrSlotNode(&slot
);
962 return PRIMITIVENAME
;
965 if (token
[0] >= 'A' && token
[0] <= 'Z') {
967 SetSymbol(&slot
, sym
);
968 node
= newPyrSlotNode(&slot
);
971 if (gDebugLexer
) postfl("CLASSNAME: '%s'\n",token
);
975 if (strcmp("var",token
) ==0) return VAR
;
976 if (strcmp("arg",token
) ==0) return ARG
;
977 if (strcmp("classvar",token
) ==0) return CLASSVAR
;
978 if (strcmp("const",token
) ==0) return SC_CONST
;
980 if (strcmp("while",token
) ==0) {
983 SetSymbol(&slot
, sym
);
984 node
= newPyrSlotNode(&slot
);
988 if (strcmp("pi",token
) ==0) {
990 node
= newPyrSlotNode(&slot
);
994 if (strcmp("true",token
) ==0) {
996 node
= newPyrSlotNode(&slot
);
1000 if (strcmp("false",token
) ==0) {
1002 node
= newPyrSlotNode(&slot
);
1006 if (strcmp("nil",token
) ==0) {
1008 node
= newPyrSlotNode(&slot
);
1012 if (strcmp("inf",token
) ==0) {
1013 SetFloat(&slot
, std::numeric_limits
<double>::infinity());
1014 node
= newPyrSlotNode(&slot
);
1019 sym
= getsym(token
);
1021 SetSymbol(&slot
, sym
);
1022 node
= newPyrSlotNode(&slot
);
1027 int processhex(char *s
)
1034 if (gDebugLexer
) postfl("processhex: '%s'\n",s
);
1040 if (*c
>= '0' && *c
<= '9') val
= val
*16 + *c
- '0';
1041 else if (*c
>= 'a' && *c
<= 'z') val
= val
*16 + *c
- 'a' + 10;
1042 else if (*c
>= 'A' && *c
<= 'Z') val
= val
*16 + *c
- 'A' + 10;
1047 node
= newPyrSlotNode(&slot
);
1053 int processintradix(char *s
, int n
, int radix
)
1058 if (gDebugLexer
) postfl("processintradix: '%s'\n",s
);
1061 SetInt(&slot
, sc_strtoi(s
, n
, radix
));
1062 node
= newPyrSlotNode(&slot
);
1067 int processfloatradix(char *s
, int n
, int radix
)
1072 if (gDebugLexer
) postfl("processfloatradix: '%s'\n",s
);
1075 SetFloat(&slot
, sc_strtof(s
, n
, radix
));
1076 node
= newPyrSlotNode(&slot
);
1081 int processint(char *s
)
1086 if (gDebugLexer
) postfl("processint: '%s'\n",s
);
1089 SetInt(&slot
, atoi(s
));
1090 node
= newPyrSlotNode(&slot
);
1095 int processchar(int c
)
1100 if (gDebugLexer
) postfl("processhex: '%c'\n",c
);
1104 node
= newPyrSlotNode(&slot
);
1109 int processfloat(char *s
, int sawpi
)
1115 if (gDebugLexer
) postfl("processfloat: '%s'\n",s
);
1118 if (sawpi
) { z
= atof(s
)*pi
; SetFloat(&slot
, z
); }
1119 else { SetFloat(&slot
, atof(s
)); }
1120 node
= newPyrSlotNode(&slot
);
1126 int processaccidental1(char *s
)
1133 double centsdiv
=1000.;
1135 printf("processaccidental1: '%s'\n",s
);
1140 if (*c
>= '0' && *c
<= '9') degree
= degree
*10. + *c
- '0';
1145 if (*c
== 'b') centsdiv
= -1000.;
1146 else if (*c
== 's') centsdiv
= 1000.;
1150 if (*c
>= '0' && *c
<= '9') {
1151 cents
= cents
*10. + *c
- '0';
1157 if (cents
> 499.) cents
= 499.;
1159 SetFloat(&slot
, degree
+ cents
/centsdiv
);
1160 node
= newPyrSlotNode(&slot
);
1165 int processaccidental2(char *s
)
1171 double semitones
=0.;
1173 printf("processaccidental2: '%s'\n",s
);
1178 if (*c
>= '0' && *c
<= '9') degree
= degree
*10. + *c
- '0';
1184 if (*c
== 'b') semitones
-= 1.;
1185 else if (*c
== 's') semitones
+= 1.;
1189 if (semitones
> 4.) semitones
= 4.;
1191 SetFloat(&slot
, degree
+ semitones
/10.);
1192 node
= newPyrSlotNode(&slot
);
1197 int processsymbol(char *s
)
1203 if (gDebugLexer
) postfl("processsymbol: '%s'\n",s
);
1207 SetSymbol(&slot
, sym
);
1208 node
= newPyrSlotNode(&slot
);
1213 int processstring(char *s
)
1219 if (gDebugLexer
) postfl("processstring: '%s'\n",s
);
1221 int flags
= compilingCmdLine
? obj_immutable
: obj_permanent
| obj_immutable
;
1222 string
= newPyrString(gMainVMGlobals
->gc
, s
+1, flags
, false);
1223 SetObject(&slot
, string
);
1224 node
= newPyrSlotNode(&slot
);
1229 void yyerror(const char *s
)
1234 postErrorLine(lineno
, linepos
, charno
);
1242 error("Parse error\n");
1243 postErrorLine(lineno
, linepos
, charno
);
1248 void postErrorLine()
1250 int i
, j
, start
, end
;
1254 for (i
=textpos
-1; i
>=0; --i
) {
1255 if (text
[i
] == '\r' || text
[i
] == '\n') break;
1258 for (i
=textpos
; i
< textlen
; ++i
) {
1259 if (text
[i
] == '\r' || text
[i
] == '\n') break;
1262 for (i
=start
, j
=0; i
<end
; ++i
) {
1263 if (i
== textpos
) str
[j
++] = '¶';
1266 if (textpos
== end
) str
[j
++] = '¶';
1269 postfl("%s\n", str
);
1273 void postErrorLine(int linenum
, int start
, int charpos
)
1278 //post("start %d\n", start);
1279 //parseFailed = true;
1280 char extPath
[MAXPATHLEN
];
1281 asRelativePath(curfilename
, extPath
);
1282 post(" in file '%s'\n", extPath
);
1283 post(" line %d char %d:\n\n", linenum
+errLineOffset
, charpos
);
1284 // nice: postfl previous line for context
1286 //postfl("text '%s' %d\n", text, text);
1288 // postfl error line for context
1289 pos
= start
+ charpos
;
1290 for (i
=pos
; i
< textlen
; ++i
) {
1291 if (text
[i
] == 0 || text
[i
] == '\r' || text
[i
] == '\n') break;
1294 for (i
=start
, j
=0; i
<end
&& j
<255; ++i
) {
1298 post(" %s\n ", str
);
1299 for (i
=0; i
<charpos
-yylen
; i
++) post(" ");
1300 for (i
=0; i
<yylen
; i
++) post("^");
1305 // postfl following line for context
1306 for (j
=0; j
<255 && i
<textlen
; ++i
) {
1307 if (text
[i
] == 0 ||text
[i
] == '\r' || text
[i
] == '\n') break;
1313 post("-----------------------------------\n", str
);
1317 void c2pstrcpy(unsigned char* dst, const char *src);
1318 void c2pstrcpy(unsigned char* dst, const char *src)
1321 unsigned char *dstp = &dst[1];
1322 while ((c = *src++) != 0) *dstp++ = c;
1323 dst[0] = dstp - dst - 1;
1326 void p2cstrcpy(char *dst, const unsigned char* src);
1327 void p2cstrcpy(char *dst, const unsigned char* src)
1330 for (int i=0; i<n; ++i) *dst++ = *src++;
1335 void pstrncpy(unsigned char *s1
, unsigned char *s2
, int n
);
1336 void pstrncpy(unsigned char *s1
, unsigned char *s2
, int n
)
1340 n
= (n
< m
) ? n
: m
;
1342 for (i
=0; i
<n
; ++i
) { *s1
= *s2
; s1
++; s2
++; }
1345 int pstrcmp(unsigned char *s1
, unsigned char *s2
);
1346 int pstrcmp(unsigned char *s1
, unsigned char *s2
)
1348 int i
, len1
, len2
, len
;
1351 len
= sc_min(len1
, len2
);
1352 for (i
=0; i
<len
; ++i
) {
1353 if (s1
[i
] < s2
[i
]) return -1;
1354 if (s1
[i
] > s2
[i
]) return 1;
1356 if (len1
< len2
) return -1;
1357 if (len1
> len2
) return 1;
1361 bool scanForClosingBracket()
1363 int r
, c
, d
, startLevel
;
1365 // finite state machine to parse input stream into tokens
1368 if (gDebugLexer
) postfl("->scanForClosingBracket\n");
1370 startLevel
= brackets
.num
;
1374 if (c
== 0) goto leave
;
1375 else if (c
==' ' || c
=='\t' || c
=='\n' || c
=='\r' || c
=='\v' || c
=='\f') {
1378 else if (c
== '\'') goto symbol3
;
1379 else if (c
== '"') goto string1
;
1380 else if (c
== '/') {
1382 if (c
== '/') goto comment1
;
1383 else if (c
== '*') goto comment2
;
1384 else { unput(c
); goto start
; }
1386 else if (c
== '$') {
1391 case 'n' : c
= '\n'; break;
1392 case 'r' : c
= '\r'; break;
1393 case 't' : c
= '\t'; break;
1394 case 'f' : c
= '\f'; break;
1395 case 'v' : c
= '\v'; break;
1400 else if (c
== OPENPAREN
|| c
== OPENSQUAR
|| c
== OPENCURLY
) {
1401 pushls(&brackets
, (int)c
);
1405 else if (c
== CLOSSQUAR
) {
1406 if (!emptyls(&brackets
)) {
1407 if ((d
= popls(&brackets
)) != OPENSQUAR
) {
1409 post("opening bracket was a '%c', but found a '%c'\n",d
,c
);
1414 post("unmatched '%c'\n",c
);
1418 if (brackets
.num
< startLevel
) goto leave
;
1421 else if (c
== CLOSPAREN
) {
1422 if (!emptyls(&brackets
)) {
1423 if ((d
= popls(&brackets
)) != OPENPAREN
) {
1425 post("opening bracket was a '%c', but found a '%c'\n",d
,c
);
1430 post("unmatched '%c'\n",c
);
1433 if (brackets
.num
< startLevel
) goto leave
;
1436 else if (c
== CLOSCURLY
) {
1437 if (!emptyls(&brackets
)) {
1438 if ((d
= popls(&brackets
)) != OPENCURLY
) {
1440 post("opening bracket was a '%c', but found a '%c'\n",d
,c
);
1445 post("unmatched '%c'\n",c
);
1448 if (brackets
.num
< startLevel
) goto leave
;
1454 int startline
, endchar
;
1463 } while (c
!= endchar
&& c
!= 0);
1465 char extPath
[MAXPATHLEN
];
1466 asRelativePath(curfilename
, extPath
);
1467 post("Open ended symbol ... started on line %d in file '%s'\n",
1468 startline
, extPath
);
1475 int startline
, endchar
;
1484 } while (c
!= endchar
&& c
!= 0);
1486 char extPath
[MAXPATHLEN
];
1487 asRelativePath(curfilename
, extPath
);
1488 post("Open ended string ... started on line %d in file '%s'\n",
1489 startline
, extPath
);
1494 comment1
: /* comment -- to end of line */
1497 } while (c
!= '\n' && c
!= '\r' && c
!= 0);
1498 if (c
== 0) { goto leave
; }
1502 int startline
, clevel
, prevc
;
1508 if (c
== '/' && prevc
== '*') {
1509 if (--clevel
<= 0) break;
1510 } else if (c
== '*' && prevc
== '/') clevel
++;
1514 char extPath
[MAXPATHLEN
];
1515 asRelativePath(curfilename
, extPath
);
1516 post("Open ended comment ... started on line %d in file '%s'\n",
1517 startline
, extPath
);
1524 char extPath
[MAXPATHLEN
];
1525 asRelativePath(curfilename
, extPath
);
1526 post(" in file '%s' line %d char %d\n", extPath
, lineno
, charno
);
1536 if (gDebugLexer
) postfl("<-scanForClosingBracket\n");
1543 static ClassExtFile
* sClassExtFiles
;
1544 static ClassExtFile
* eClassExtFiles
;
1546 ClassExtFile
* newClassExtFile(PyrSymbol
*fileSym
, int startPos
, int endPos
);
1547 ClassExtFile
* newClassExtFile(PyrSymbol
*fileSym
, int startPos
, int endPos
)
1549 ClassExtFile
* classext
;
1550 classext
= (ClassExtFile
*)pyr_pool_compile
->Alloc(sizeof(ClassExtFile
));
1551 classext
->fileSym
= fileSym
;
1553 classext
->startPos
= startPos
;
1554 classext
->endPos
= endPos
;
1555 if (!sClassExtFiles
) sClassExtFiles
= classext
;
1556 else eClassExtFiles
->next
= classext
;
1557 eClassExtFiles
= classext
;
1562 ClassDependancy
* newClassDependancy(PyrSymbol
*className
, PyrSymbol
*superClassName
,
1563 PyrSymbol
*fileSym
, int startPos
, int endPos
, int lineOffset
)
1565 ClassDependancy
* classdep
;
1567 //post("classdep '%s' '%s' '%s' %d %d\n", className->name, superClassName->name,
1568 // fileSym->name, className, superClassName);
1570 // lifetime: kill after compile.
1572 if (className
->classdep
) {
1573 error("duplicate Class found: '%s' \n", className
->name
);
1574 post("%s\n",className
->classdep
->fileSym
->name
);
1575 postfl("%s\n\n",fileSym
->name
);
1576 return className
->classdep
;
1578 classdep
= (ClassDependancy
*)pyr_pool_compile
->Alloc(sizeof(ClassDependancy
));
1580 classdep
->className
= className
;
1581 classdep
->superClassName
= superClassName
;
1582 classdep
->fileSym
= fileSym
;
1583 classdep
->superClassDep
= NULL
;
1584 classdep
->next
= NULL
;
1585 classdep
->subclasses
= NULL
;
1587 classdep
->startPos
= startPos
;
1588 classdep
->endPos
= endPos
;
1589 classdep
->lineOffset
= lineOffset
;
1591 className
->classdep
= classdep
;
1597 ClassDependancy
*next
;
1598 SymbolTable
* symbolTable
= gMainVMGlobals
->symbolTable
;
1600 //postfl("->buildDepTree\n"); fflush(stdout);
1601 for (int i
=0; i
<symbolTable
->TableSize(); ++i
) {
1602 PyrSymbol
*sym
= symbolTable
->Get(i
);
1603 if (sym
&& (sym
->flags
& sym_Class
)) {
1604 if (sym
->classdep
) {
1605 if (sym
->classdep
->superClassName
->classdep
) {
1606 next
= sym
->classdep
->superClassName
->classdep
->subclasses
;
1607 sym
->classdep
->superClassName
->classdep
->subclasses
= sym
->classdep
;
1608 sym
->classdep
->next
= next
;
1609 } else if (sym
->classdep
->superClassName
!= s_none
) {
1610 error("Superclass '%s' of class '%s' is not defined in any file.\n%s\n",
1611 sym
->classdep
->superClassName
->name
, sym
->classdep
->className
->name
,sym
->classdep
->fileSym
->name
);
1616 //postfl("<-buildDepTree\n"); fflush(stdout);
1619 extern PyrClass
*gClassList
;
1621 ClassDependancy
**gClassCompileOrder
;
1622 int gClassCompileOrderNum
= 0;
1623 int gClassCompileOrderSize
= 1000;
1625 void compileDepTree();
1627 void traverseFullDepTree()
1629 //postfl("->traverseFullDepTree\n"); fflush(stdout);
1630 gClassCompileOrderNum
= 0;
1631 gClassCompileOrder
= (ClassDependancy
**)pyr_pool_compile
->Alloc(
1632 gClassCompileOrderSize
* sizeof(ClassDependancy
));
1633 MEMFAIL(gClassCompileOrder
);
1635 // parse and compile all files
1636 initParser(); // sets compiler errors to 0
1639 traverseDepTree(s_object
->classdep
, 0);
1640 compileDepTree(); // compiles backwards using the order defined in gClassCompileOrder
1641 compileClassExtensions();
1643 pyr_pool_compile
->Free(gClassCompileOrder
);
1646 //postfl("<-traverseFullDepTree\n"); fflush(stdout);
1650 void traverseDepTree(ClassDependancy
*classdep
, int level
)
1652 ClassDependancy
*subclassdep
;
1654 if (!classdep
) return;
1656 subclassdep
= classdep
->subclasses
;
1657 for (; subclassdep
; subclassdep
= subclassdep
->next
) {
1658 traverseDepTree(subclassdep
, level
+1);
1660 if (gClassCompileOrderNum
> gClassCompileOrderSize
) {
1661 gClassCompileOrderSize
*= 2;
1662 gClassCompileOrder
= (ClassDependancy
**)pyr_pool_compile
->Realloc(gClassCompileOrder
,
1663 gClassCompileOrderSize
* sizeof(ClassDependancy
));
1664 MEMFAIL(gClassCompileOrder
);
1667 /* postfl("traverse level:%d, gClassCompileOrderNum:%d, '%s' '%s' '%s'\n", level, gClassCompileOrderNum, classdep->className->name, classdep->superClassName->name,
1668 classdep->fileSym->name); fflush(stdout);
1671 gClassCompileOrder
[gClassCompileOrderNum
++] = classdep
;
1675 void compileClass(PyrSymbol
*fileSym
, int startPos
, int endPos
, int lineOffset
)
1677 //fprintf(stderr, "compileClass: %d\n", fileSym->u.index);
1679 gCompilingFileSym
= fileSym
;
1680 gCompilingVMGlobals
= 0;
1681 gRootParseNode
= NULL
;
1683 if (startLexer(fileSym
, startPos
, endPos
, lineOffset
)) {
1684 //postfl("->Parsing %s\n", fileSym->name); fflush(stdout);
1685 parseFailed
= yyparse();
1686 //postfl("<-Parsing %s %d\n", fileSym->name, parseFailed); fflush(stdout);
1687 //post("parseFailed %d\n", parseFailed); fflush(stdout);
1688 if (!parseFailed
&& gRootParseNode
) {
1689 //postfl("Compiling nodes %p\n", gRootParseNode);fflush(stdout);
1690 compilingCmdLine
= false;
1691 compileNodeList(gRootParseNode
, true);
1692 //postfl("done compiling\n");fflush(stdout);
1695 char extPath
[MAXPATHLEN
];
1696 asRelativePath(fileSym
->name
, extPath
);
1697 error("file '%s' parse failed\n", extPath
);
1698 postfl("error parsing\n");
1702 error("file '%s' open failed\n", fileSym
->name
);
1707 void compileDepTree()
1709 ClassDependancy
*classdep
;
1712 for (i
=gClassCompileOrderNum
-1; i
>=0; --i
) {
1713 classdep
= gClassCompileOrder
[i
];
1714 /*postfl("compile %d '%s' '%s' '%s'...%d/%d/%d\n", i, classdep->className->name, classdep->superClassName->name,
1715 classdep->fileSym->name, classdep->startLine, classdep->endLine, classDep->lineOffset);*/
1716 compileClass(classdep
->fileSym
, classdep
->startPos
, classdep
->endPos
, classdep
->lineOffset
);
1718 //postfl("<compile\n");
1721 void compileClassExtensions()
1723 if (sClassExtFiles
) {
1724 ClassExtFile
*classext
= sClassExtFiles
;
1726 //postfl("compile class ext: %d/%d\n", classext->startPos, classext->endPos);
1727 compileClass(classext
->fileSym
, classext
->startPos
, classext
->endPos
, -1);
1728 classext
= classext
->next
;
1733 void findDiscrepancy();
1735 void traverseFullDepTree2()
1738 // assign a class index to all classes
1739 if (!parseFailed
&& !compileErrors
) {
1743 // now I index them during pass one
1744 indexClassTree(class_object
, 0);
1746 if (2*numClassDeps
!= gNumClasses
) {
1747 error("There is a discrepancy.\n");
1748 /* not always correct
1749 if(2*numClassDeps < gNumClasses) {
1750 post("Duplicate files may exist in the directory structure.\n");
1752 post("Some class files may be missing.\n");
1755 post("numClassDeps %d gNumClasses %d\n", numClassDeps
, gNumClasses
);
1760 buildBigMethodMatrix();
1761 SymbolTable
* symbolTable
= gMainVMGlobals
->symbolTable
;
1762 post("\tNumber of Symbols %d\n", symbolTable
->NumItems());
1763 post("\tByte Code Size %d\n", totalByteCodes
);
1764 //elapsed = TickCount() - compileStartTime;
1766 elapsed
= elapsedTime() - compileStartTime
;
1767 post("\tcompiled %d files in %.2f seconds\n",
1768 gNumCompiledFiles
, elapsed
);
1769 if(numOverwrites
== 1){
1770 post("\nInfo: One method is currently overwritten by an extension. To see which, execute:\nMethodOverride.printAll\n\n");
1772 else if(numOverwrites
> 1){
1773 post("\nInfo: %i methods are currently overwritten by extensions. To see which, execute:\nMethodOverride.printAll\n\n", numOverwrites
);
1775 post("compile done\n");
1780 bool parseOneClass(PyrSymbol
*fileSym
)
1783 PyrSymbol
*className
, *superClassName
;
1784 ClassDependancy
*classdep
;
1787 int startPos
, startLineOffset
;
1792 startLineOffset
= lineno
- 1;
1795 if (token
== CLASSNAME
) {
1796 className
= slotRawSymbol(&((PyrSlotNode
*)zzval
)->mSlot
);
1797 // I think this is wrong: zzval is space pool alloced
1798 //pyrfree((PyrSlot*)zzval);
1801 if (token
== 0) return false;
1802 if (token
== OPENSQUAR
) {
1803 scanForClosingBracket(); // eat indexing spec
1805 if (token
== 0) return false;
1808 token
= yylex(); // get super class
1809 if (token
== 0) return false;
1810 if (token
== CLASSNAME
) {
1811 superClassName
= slotRawSymbol(&((PyrSlotNode
*)zzval
)->mSlot
);
1812 // I think this is wrong: zzval is space pool alloced
1813 //pyrfree((PyrSlot*)zzval);
1815 if (token
== 0) return false;
1816 if (token
== OPENCURLY
) {
1817 scanForClosingBracket(); // eat class body
1818 classdep
= newClassDependancy(className
, superClassName
, fileSym
, startPos
, textpos
, startLineOffset
);
1821 postfl("Expected %c. got token: '%s' %d\n", OPENCURLY
, yytext
, token
);
1822 postErrorLine(lineno
, linepos
, charno
);
1827 post("Expected superclass name. got token: '%s' %d\n", yytext
, token
);
1828 postErrorLine(lineno
, linepos
, charno
);
1831 } else if (token
== OPENCURLY
) {
1832 if (className
== s_object
) superClassName
= s_none
;
1833 else superClassName
= s_object
;
1834 scanForClosingBracket(); // eat class body
1835 classdep
= newClassDependancy(className
, superClassName
, fileSym
, startPos
, textpos
, startLineOffset
);
1838 post("Expected ':' or %c. got token: '%s' %d\n", OPENCURLY
, yytext
, token
);
1839 postErrorLine(lineno
, linepos
, charno
);
1842 } else if (token
== '+') {
1844 if (token
== 0) return false;
1845 scanForClosingBracket();
1847 newClassExtFile(fileSym
, startPos
, textpos
);
1852 post("Expected class name. got token: '%s' %d\n", yytext
, token
);
1853 postErrorLine(lineno
, linepos
, charno
);
1862 //void ClearLibMenu();
1864 void aboutToFreeRuntime();
1865 void aboutToFreeRuntime()
1870 //void init_graph_compile();
1871 //void tellPlugInsAboutToCompile();
1872 void pyrmath_init_globs();
1876 aboutToFreeRuntime();
1878 //dump_pool_histo(pyr_pool_runtime);
1879 pyr_pool_runtime
->FreeAllInternal();
1880 //dump_pool_histo(pyr_pool_runtime);
1881 //gPermanentObjPool.Init(pyr_pool_runtime, PERMOBJCHUNK);
1884 void *ptr
= pyr_pool_runtime
->Alloc(sizeof(SymbolTable
));
1885 gMainVMGlobals
->symbolTable
= new (ptr
) SymbolTable(pyr_pool_runtime
, 8192);
1887 //gFileSymbolTable = newSymbolTable(512);
1889 pyrmath_init_globs();
1891 initSymbols(); // initialize symbol globals
1892 //init_graph_compile();
1893 initSpecialSelectors();
1894 initSpecialClasses();
1899 //tellPlugInsAboutToCompile();
1904 compiledDirectories
.clear();
1905 sc_InitCompileDirectory();
1910 //postfl("->finiPassOne\n");
1912 //postfl("<-finiPassOne\n");
1915 static bool passOne_ProcessDir(const char *dirname
, int level
)
1917 if (!sc_DirectoryExists(dirname
))
1920 if (compiledDirectories
.find(std::string(dirname
)) != compiledDirectories
.end())
1924 bool success
= true;
1926 if (gLibraryConfig
&& gLibraryConfig
->pathIsExcluded(dirname
)) {
1927 post("\texcluding dir: '%s'\n", dirname
);
1931 if (level
== 0) post("\tcompiling dir: '%s'\n", dirname
);
1933 SC_DirHandle
*dir
= sc_OpenDir(dirname
);
1935 error("open directory failed '%s'\n", dirname
); fflush(stdout
);
1940 char diritem
[MAXPATHLEN
];
1941 bool skipItem
= true;
1942 bool validItem
= sc_ReadDir(dir
, dirname
, diritem
, skipItem
);
1943 if (!validItem
) break;
1944 if (skipItem
) continue;
1946 if (sc_DirectoryExists(diritem
)) {
1947 success
= passOne_ProcessDir(diritem
, level
+ 1);
1949 success
= passOne_ProcessOneFile(diritem
, level
+ 1);
1952 if (!success
) break;
1955 compiledDirectories
.insert(std::string(dirname
));
1964 if (sc_IsStandAlone()) {
1965 /// FIXME: this should be moved to the LibraryConfig file
1966 if (!passOne_ProcessDir(gCompileDir
, 0))
1969 if (!gLibraryConfig
->forEachIncludedDirectory(passOne_ProcessDir
))
1976 // true if filename ends in ".sc"
1977 bool isValidSourceFileName(char *filename
)
1979 int len
= strlen(filename
);
1980 bool validExtension
= (len
>3 && strncmp(filename
+len
-3, ".sc", 3) == 0)
1981 || (len
>7 && strncmp(filename
+len
-7, ".sc.rtf", 7) == 0);
1982 if (!validExtension
)
1985 boost::filesystem::path
pathname(filename
);
1987 if (pathname
.filename().c_str()[0] == '.') // hidden filename
1993 // sekhar's replacement
1994 bool passOne_ProcessOneFile(const char * filenamearg
, int level
)
1996 bool success
= true;
1998 bool isAlias
= false;
2000 char filename
[MAXPATHLEN
];
2001 int status
= sc_ResolveIfAlias(filenamearg
, filename
, isAlias
, MAXPATHLEN
);
2004 printf("WARNING: skipping invalid symbolic link: %s\n", filenamearg
);
2008 if (gLibraryConfig
&& gLibraryConfig
->pathIsExcluded(filename
)) {
2009 post("\texcluding file: '%s'\n", filename
);
2013 if (isValidSourceFileName(filename
)) {
2014 gNumCompiledFiles
++;
2015 PyrSymbol
* fileSym
= getsym(filename
);
2016 fileSym
->u
.source
= NULL
;
2017 if (startLexer(fileSym
, -1, -1, -1)) {
2018 while (parseOneClass(fileSym
)) { };
2021 error("file '%s' open failed\n", filename
);
2025 if (sc_DirectoryExists(filename
))
2026 success
= passOne_ProcessDir(filename
, level
);
2033 void compileSucceeded();
2034 void compileSucceeded()
2036 compiledOK
= !(parseFailed
|| compileErrors
);
2040 compiledOK
= initRuntime(gMainVMGlobals
, 128*1024, pyr_pool_runtime
);
2043 VMGlobals
*g
= gMainVMGlobals
;
2045 g
->canCallOS
= true;
2046 //++g->sp; SetObject(g->sp, g->process);
2047 //runInterpreter(g, s_hardwaresetup, 1);
2049 ++g
->sp
; SetObject(g
->sp
, g
->process
);
2050 runInterpreter(g
, s_startup
, 1);
2051 g
->canCallOS
= false;
2059 void aboutToCompileLibrary();
2060 void aboutToCompileLibrary()
2062 //printf("->aboutToCompileLibrary\n");
2063 pthread_mutex_lock (&gLangMutex
);
2065 VMGlobals
*g
= gMainVMGlobals
;
2067 g
->canCallOS
= true;
2070 SetObject(g
->sp
, g
->process
);
2071 runInterpreter(g
, s_shutdown
, 1);
2073 g
->canCallOS
= false;
2075 pthread_mutex_unlock (&gLangMutex
);
2076 //printf("<-aboutToCompileLibrary\n");
2079 void closeAllGUIScreens();
2080 void TempoClock_stopAll(void);
2081 void closeAllCustomPorts();
2083 void shutdownLibrary()
2085 closeAllGUIScreens();
2089 aboutToCompileLibrary();
2091 TempoClock_stopAll();
2093 pthread_mutex_lock (&gLangMutex
);
2095 closeAllCustomPorts();
2098 VMGlobals
*g
= gMainVMGlobals
;
2099 g
->canCallOS
= true;
2100 g
->gc
->RunAllFinalizers();
2101 g
->canCallOS
= false;
2104 pyr_pool_runtime
->FreeAll();
2108 pthread_mutex_unlock (&gLangMutex
);
2111 SC_DLLEXPORT_C
bool compileLibrary()
2113 //printf("->compileLibrary\n");
2116 pthread_mutex_lock (&gLangMutex
);
2117 gNumCompiledFiles
= 0;
2120 // FIXME: the library config should have been initialized earlier!
2121 if (!gLibraryConfig
)
2122 SC_LanguageConfig::readDefaultLibraryConfig();
2124 compileStartTime
= elapsedTime();
2129 postfl("compiling class library...\n");
2131 postfl("compiling class library (debug build)...\n");
2134 bool res
= passOne();
2137 postfl("\tpass 1 done\n");
2139 if (!compileErrors
) {
2141 traverseFullDepTree();
2142 traverseFullDepTree2();
2145 if (!compileErrors
&& gShowWarnings
) {
2146 SymbolTable
* symbolTable
= gMainVMGlobals
->symbolTable
;
2147 symbolTable
->CheckSymbols();
2150 pyr_pool_compile
->FreeAll();
2157 pthread_mutex_unlock (&gLangMutex
);
2158 //printf("<-compileLibrary\n");
2162 void signal_init_globs();
2164 void dumpByteCodes(PyrBlock
*theBlock
);
2166 SC_DLLEXPORT_C
void runLibrary(PyrSymbol
* selector
)
2168 VMGlobals
*g
= gMainVMGlobals
;
2169 g
->canCallOS
= true;
2172 ++g
->sp
; SetObject(g
->sp
, g
->process
);
2173 runInterpreter(g
, selector
, 1);
2175 postfl("Library has not been compiled successfully.\n");
2177 } catch (std::exception
&ex
) {
2178 PyrMethod
*meth
= g
->method
;
2180 int ip
= slotRawInt8Array(&meth
->code
) ? g
->ip
- slotRawInt8Array(&meth
->code
)->b
: -1;
2181 post("caught exception in runLibrary %s:%s %3d\n",
2182 slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
, ip
2184 dumpByteCodes(meth
);
2186 post("caught exception in runLibrary\n");
2190 postfl("DANGER: OUT of MEMORY. Operation failed.\n");
2192 g
->canCallOS
= false;
2195 void interpretCmdLine(const char *textbuf
, int textlen
, char *methodname
)
2202 string
= newPyrStringN(gMainVMGlobals
->gc
, textlen
, 0, false);
2203 memcpy(string
->s
, textbuf
, textlen
);
2204 SetObject(&slotRawInterpreter(&gMainVMGlobals
->process
->interpreter
)->cmdLine
, string
);
2205 gMainVMGlobals
->gc
->GCWrite(slotRawObject(&gMainVMGlobals
->process
->interpreter
), string
);
2206 SetObject(&slot
, gMainVMGlobals
->process
);
2208 // ProfilerInit(collectSummary, microsecondsTimeBase, 500, 100);
2210 slotCopy((++gMainVMGlobals
->sp
), &slot
);
2211 runInterpreter(gMainVMGlobals
, getsym(methodname
), 1);
2213 // ProfilerDump("\pErase2.prof");
2217 postfl("Library has not been compiled successfully.\n");
2221 void init_SuperCollider()