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"
61 #include "PredefinedSymbols.h"
68 #include "SC_LibraryConfig.h"
70 #include "SC_DirUtils.h"
74 int processaccidental1(char *s
);
75 int processaccidental2(char *s
);
78 extern bool gFullyFunctional
;
79 double compileStartTime
;
80 int gNumCompiledFiles
;
82 thisProcess.interpreter.executeFile("Macintosh HD:score").size.postln;
85 PyrSymbol
*gCompilingFileSym
= 0;
86 VMGlobals
*gCompilingVMGlobals
= 0;
87 static char gCompileDir
[MAXPATHLEN
];
90 bool gDebugLexer
= false;
92 bool gShowWarnings
= false;
94 LongStack closedFuncCharNo
;
95 LongStack generatorStack
;
96 int lastClosedFuncCharNo
= 0;
98 const char *binopchars
= "!@%&*-+=|<>?/";
99 char yytext
[MAXYYLEN
];
100 char curfilename
[PATH_MAX
];
104 bool compilingCmdLine
= false;
105 bool compilingCmdLineErrorWindow
= false;
108 int lineno
, charno
, linepos
;
115 int errLineOffset
, errCharPosOffset
;
117 bool compiledOK
= false;
118 std::set
<std::string
> compiledDirectories
;
120 /* so the text editor's dumb paren matching will work */
121 #define OPENPAREN '('
122 #define OPENCURLY '{'
123 #define OPENSQUAR '['
124 #define CLOSSQUAR ']'
125 #define CLOSCURLY '}'
126 #define CLOSPAREN ')'
128 //int rtf2txt(char* txt);
130 int sc_strtoi(const char *str
, int n
, int base
)
133 for (int i
=0; i
<n
; ++i
)
137 if (c
>= '0' && c
<= '0' + sc_min(10,base
) - 1) z
= z
* base
+ c
- '0';
138 else if (c
>= 'a' && c
<= 'a' + sc_min(36,base
) - 11) z
= z
* base
+ c
- 'a' + 10;
139 else if (c
>= 'A' && c
<= 'A' + sc_min(36,base
) - 11) z
= z
* base
+ c
- 'A' + 10;
144 double sc_strtof(const char *str
, int n
, int base
)
148 for (int i
=0; i
<n
; ++i
)
152 if (c
>= '0' && c
<= '0' + sc_min(10,base
) - 1) z
= z
* base
+ c
- '0';
153 else if (c
>= 'a' && c
<= 'a' + sc_min(36,base
) - 11) z
= z
* base
+ c
- 'a' + 10;
154 else if (c
>= 'A' && c
<= 'A' + sc_min(36,base
) - 11) z
= z
* base
+ c
- 'A' + 10;
155 else if (c
== '.') decptpos
= i
;
157 //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
158 z
= z
/ pow((double)base
, n
-1- decptpos
);
162 static void sc_InitCompileDirectory(void)
164 // main class library folder: only used for relative path resolution
165 sc_GetResourceDirectory(gCompileDir
, MAXPATHLEN
-32);
166 sc_AppendToPath(gCompileDir
, MAXPATHLEN
, "SCClassLibrary");
169 extern void asRelativePath(char *inPath
, char *outPath
)
171 uint32 len
= strlen(gCompileDir
);
172 if (strlen(inPath
) < len
|| memcmp(inPath
, gCompileDir
, len
) != 0) {
173 // gCompileDir is not the prefix.
174 strcpy(outPath
, inPath
);
177 strcpy(outPath
, inPath
+ len
);
181 static bool getFileText(char* filename
, char **text
, int *length
)
188 file
= fopen(filename
, "rb");
190 file
= fopen(filename
, "r");
192 if (!file
) return false;
194 fseek(file
, 0L, SEEK_END
);
195 llength
= ftell(file
);
196 fseek(file
, 0L, SEEK_SET
);
197 ltext
= (char*)pyr_pool_compile
->Alloc((llength
+1) * sizeof(char));
199 // win32 isprint( ) doesn't like the 0xcd after the end of file when
200 // there is a mismatch in lengths due to line endings....
201 memset(ltext
,0,(llength
+1) * sizeof(char));
205 size_t size
= fread(ltext
, 1, llength
, file
);
206 if (size
!= llength
) {
207 error("error when reading file");
212 //ltext[llength] = 0;
222 // strips out all the RichTextFile crap
223 int rtf2txt(char* txt
)
225 int rdpos
=0, wrpos
=0;
227 if (strncmp(txt
,"{\\rtf",5)!=0) return 0; // OK, not an RTF file
229 switch (txt
[wrpos
]=txt
[rdpos
++])
234 sprintf(fname, "rtf2txt_out%d.txt", bugctr++);
235 FILE *fp = fopen(fname, "w");
236 fwrite(txt,wrpos,1,fp);
242 case '\n': goto text
;
244 if (strncmp(txt
+rdpos
,"fonttbl",7)==0
245 || strncmp(txt
+rdpos
,"filetbl",7)==0
246 || strncmp(txt
+rdpos
,"colortbl",8)==0
247 || strncmp(txt
+rdpos
,"stylesheet",10)==0
251 while(level
&& (c
=txt
[rdpos
++]) != 0) {
252 if (c
== OPENCURLY
) level
++;
253 else if (c
== CLOSCURLY
) level
--;
255 } else if (strncmp(txt
+rdpos
,"\'a0",3)==0 || (strncmp(txt
+rdpos
,"\'A0",3)==0))
257 txt
[wrpos
++] = ' '; rdpos
= rdpos
+ 3;
259 if (txt
[rdpos
]==CLOSCURLY
|| txt
[rdpos
]==OPENCURLY
260 || txt
[rdpos
]=='\\' || txt
[rdpos
]=='\t'|| txt
[rdpos
]=='\n')
261 { txt
[wrpos
++] = txt
[rdpos
++]; goto text
; }
262 if (strncmp(txt
+rdpos
,"tab",3)==0) { txt
[wrpos
++] = '\t'; }
263 if (strncmp(txt
+rdpos
,"par",3)==0) { txt
[wrpos
++] = '\n'; }
265 while((c
=txt
[rdpos
++]) && c
!=' ' && c
!='\\');
266 if (c
=='\\') rdpos
--;
275 // strips HTML down to plaintext tags in a fairly simple-minded way
276 int html2txt(char* txt
)
278 int rdpos
=-1, wrpos
=0, bodypos
=-1;
281 // First check if we can find a BODY tag to start at
282 while(bodypos
== -1 && txt
[++rdpos
] != 0){
283 if(strncmp(txt
+rdpos
, "<body", 5) == 0) // FIXME: should be case-insensitive, ideally
291 // Now we start from our start, and add the non-tag text to the result
292 while(txt
[rdpos
] != 0){
294 if(txt
[rdpos
++] == '>')
297 if(txt
[rdpos
] == '<'){
302 if(strncmp(txt+rdpos, "&", 5)==0){
305 }else if(strncmp(txt+rdpos, " ", 6)==0){
308 }else if(strncmp(txt+rdpos, "<", 4)==0){
311 }else if(strncmp(txt+rdpos, ">", 4)==0){
316 txt
[wrpos
++] = txt
[rdpos
++];
326 bool startLexer(PyrSymbol
*fileSym
, int startPos
, int endPos
, int lineOffset
)
328 char *filename
= fileSym
->name
;
332 if(!fileSym
->u
.source
) {
333 if (!getFileText(filename
, &text
, &textlen
)) return false;
334 fileSym
->u
.source
= text
;
338 text
= fileSym
->u
.source
;
340 if((startPos
>= 0) && (endPos
> 0)) {
341 textlen
= endPos
- startPos
;
344 else if(textlen
== -1)
345 textlen
= strlen(text
);
347 if(lineOffset
> 0) errLineOffset
= lineOffset
;
348 else errLineOffset
= 0;
350 if(startPos
> 0) errCharPosOffset
= startPos
;
351 else errCharPosOffset
= 0;
353 initLongStack(&brackets
);
354 initLongStack(&closedFuncCharNo
);
355 initLongStack(&generatorStack
);
356 lastClosedFuncCharNo
= 0;
366 strcpy(curfilename
, filename
);
367 maxlinestarts
= 1000;
368 linestarts
= (int*)pyr_pool_compile
->Alloc(maxlinestarts
* sizeof(int*));
375 void startLexerCmdLine(char *textbuf
, int textbuflen
)
378 // lifetime: kill after compile. (this one gets killed anyway)
379 text
= (char*)pyr_pool_compile
->Alloc((textbuflen
+2) * sizeof(char));
381 memcpy(text
, textbuf
, textbuflen
);
382 text
[textbuflen
] = ' ';
383 text
[textbuflen
+1] = 0;
384 textlen
= textbuflen
+ 1;
388 initLongStack(&brackets
);
389 initLongStack(&closedFuncCharNo
);
390 initLongStack(&generatorStack
);
391 lastClosedFuncCharNo
= 0;
401 strcpy(curfilename
, "selected text");
402 maxlinestarts
= 1000;
403 linestarts
= (int*)pyr_pool_compile
->Alloc(maxlinestarts
* sizeof(int*));
408 errCharPosOffset
= 0;
413 pyr_pool_compile
->Free(linestarts
);
414 freeLongStack(&brackets
);
415 freeLongStack(&closedFuncCharNo
);
416 freeLongStack(&generatorStack
);
421 //strcpy(binopchars, "!@%&*-+=|:<>?/");
427 if (textpos
>= textlen
) {
433 if (c
== '\n' || c
== '\r') {
437 if (lineno
>= maxlinestarts
) {
438 maxlinestarts
+= maxlinestarts
;
439 linestarts
= (int*)pyr_pool_compile
->Realloc(
440 linestarts
, maxlinestarts
* sizeof(int*));
442 linestarts
[lineno
] = linepos
;
446 if (c
!= 0 && yylen
< MAXYYLEN
-2) yytext
[yylen
++] = c
;
447 //if (gDebugLexer) postfl("input '%c' %d\n",c,c);
454 if (textpos
>= textlen
) {
456 textpos
++; // so unput will work properly
461 if (c
== '\n' || c
== '\r') {
465 if (lineno
>= maxlinestarts
) {
466 maxlinestarts
+= maxlinestarts
;
467 linestarts
= (int*)pyr_pool_compile
->Realloc(
468 linestarts
, maxlinestarts
* sizeof(int*));
470 linestarts
[lineno
] = linepos
;
474 //if (gDebugLexer) postfl("input0 '%c' %d\n",c,c);
480 if (textpos
>0) textpos
--;
483 if (charno
) --charno
;
484 if (c
== '\n' || c
== '\r') {
492 if (textpos
>0) textpos
--;
493 if (charno
) --charno
;
494 if (c
== '\n' || c
== '\r') {
503 char extPath
[MAXPATHLEN
]; // for error reporting
506 // finite state machine to parse input stream into tokens
508 if (lexCmdLine
== 1) {
516 if (c
== 0) { r
= 0; goto leave
; }
517 else if (c
==' ' || c
=='\t' || c
=='\n' || c
=='\r' || c
=='\v' || c
=='\f') {
521 else if ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z') || c
== '_') goto ident
;
524 if (c
== '/') goto comment1
;
525 else if (c
== '*') goto comment2
;
526 else { unput(c
); goto binop
; }
528 else if (c
>= '0' && c
<= '9') goto digits_1
;
529 else if (c
== OPENPAREN
|| c
== OPENSQUAR
|| c
== OPENCURLY
) {
530 pushls(&brackets
, (int)c
);
531 if (c
== OPENCURLY
) {
532 pushls(&closedFuncCharNo
, linestarts
[lineno
] + charno
- 1);
537 else if (c
== CLOSSQUAR
) {
538 if (!emptyls(&brackets
)) {
539 if ((d
= popls(&brackets
)) != OPENSQUAR
) {
541 post("opening bracket was a '%c', but found a '%c'\n",d
,c
);
546 post("unmatched '%c'\n",c
);
552 else if (c
== CLOSPAREN
) {
553 if (!emptyls(&brackets
)) {
554 if ((d
= popls(&brackets
)) != OPENPAREN
) {
556 post("opening bracket was a '%c', but found a '%c'\n",d
,c
);
561 post("unmatched '%c'\n",c
);
567 else if (c
== CLOSCURLY
) {
568 if (!emptyls(&brackets
)) {
569 if ((d
= popls(&brackets
)) != OPENCURLY
) {
571 post("opening bracket was a '%c', but found a '%c'\n",d
,c
);
574 lastClosedFuncCharNo
= popls(&closedFuncCharNo
);
577 post("unmatched '%c'\n",c
);
583 else if (c
== '^') { r
= c
; goto leave
; }
584 else if (c
== '~') { r
= c
; goto leave
; }
585 else if (c
== ';') { r
= c
; goto leave
; }
586 else if (c
== ':') { r
= c
; goto leave
; }
587 else if (c
== '`') { r
= c
; goto leave
; }
588 else if (c
== '\\') goto symbol1
;
589 else if (c
== '\'') goto symbol3
;
590 else if (c
== '"') goto string1
;
592 if ((c
= input()) == '.') {
593 if ((c
= input()) == '.') {
609 if ((c
= input()) == OPENCURLY
) {
610 pushls(&brackets
, OPENCURLY
);
611 pushls(&closedFuncCharNo
, linestarts
[lineno
] + charno
- 2);
624 case 'n' : c
= '\n'; break;
625 case 'r' : c
= '\r'; break;
626 case 't' : c
= '\t'; break;
627 case 'f' : c
= '\f'; break;
628 case 'v' : c
= '\v'; break;
634 else if (c
== ',') { r
= c
; goto leave
; }
637 if (strchr(binopchars
, c
)) goto binop
;
644 else if (strchr(binopchars
, c
)) goto binop
;
645 else if(!(isprint(c
) || isspace(c
) || c
== 0)) {
654 if ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z')
655 || c
== '_' || (c
>= '0' && c
<= '9')) goto ident
;
658 r
= processkeywordbinop(yytext
) ;
663 r
= processident(yytext
) ;
670 if ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z') || c
== '_') goto symbol2
;
671 else if (c
>= '0' && c
<= '9') goto symbol4
;
675 r
= processsymbol(yytext
) ;
682 if ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z')
683 || c
== '_' || (c
>= '0' && c
<= '9')) goto symbol2
;
687 r
= processsymbol(yytext
) ;
693 if (c
>= '0' && c
<= '9') goto symbol4
;
697 r
= processsymbol(yytext
) ;
707 if (c
== 0) goto binop2
;
708 if (strchr(binopchars
, c
)) goto binop
;
713 r
= processbinop(yytext
) ;
720 if (c
>= '0' && c
<= '0' + sc_min(10,radix
) - 1) goto radix_digits_1
;
721 if (c
>= 'a' && c
<= 'a' + sc_min(36,radix
) - 11) goto radix_digits_1
;
722 if (c
>= 'A' && c
<= 'A' + sc_min(36,radix
) - 11) goto radix_digits_1
;
728 r
= processintradix(yytext
, yylen
, radix
);
734 if (c
>= '0' && c
<= '0' + sc_min(10,radix
) - 1) goto radix_digits_2
;
735 if (c
>= 'A' && c
<= 'A' + sc_min(36,radix
) - 11) goto radix_digits_2
;
736 // do not allow lower case after decimal point.
739 r
= processfloatradix(yytext
, yylen
, radix
);
745 if (c
>= '0' && c
<= '9') goto hexdigits
;
746 if (c
>= 'a' && c
<= 'f') goto hexdigits
;
747 if (c
>= 'A' && c
<= 'F') goto hexdigits
;
750 r
= processhex(yytext
);
753 digits_1
: /* number started with digits */
757 if (c
>= '0' && c
<= '9') goto digits_1
;
759 radix
= sc_strtoi(yytext
, yylen
-1, 10);
763 else if (c
== 'e' || c
== 'E') goto expon_1
;
766 if (c2
>= '0' && c2
<= '9') goto digits_2
;
771 r
= processint(yytext
);
775 else if (c
== 'b' || c
== 's') {
777 if (d
>= '0' && d
<= '9') goto accidental1
;
778 if (d
== c
) goto accidental2
;
782 if (d
>= '0' && d
<= '9') goto accidental1
;
785 r
= processaccidental1(yytext
);
789 if (d
== c
) goto accidental2
;
793 r
= processaccidental2(yytext
);
802 r
= processint(yytext
);
810 if (c
>= '0' && c
<= '9') goto digits_2
;
811 else if (c
== 'e' || c
== 'E') goto expon_1
;
812 // else if (c == 'π' || c == '∏') {
814 // yytext[yylen] = 0;
815 // r = processfloat(yytext, 1);
821 r
= processfloat(yytext
, 0);
825 expon_1
: /* e has been seen, need digits */
828 if (c
>= '0' && c
<= '9') goto expon_3
;
829 else if (c
== '+' || c
== '-') goto expon_2
;
832 expon_2
: /* + or - seen but still need digits */
835 if (c
>= '0' && c
<= '9') goto expon_3
;
841 if (c
>= '0' && c
<= '9') goto expon_3
;
842 // else if (c == 'π' || c == '∏') {
844 // yytext[yylen] = 0;
845 // r = processfloat(yytext, 1);
851 r
= processfloat(yytext
, 0);
856 int startline
, endchar
;
862 } while (c != endchar && c != 0);*/
863 for (;yylen
<MAXYYLEN
;) {
865 if (c
== '\n' || c
== '\r') {
866 asRelativePath(curfilename
,extPath
);
867 post("Symbol open at end of line on line %d in file '%s'\n",
868 startline
+errLineOffset
, extPath
);
876 } else if (c
== endchar
) break;
880 asRelativePath(curfilename
,extPath
);
881 post("Open ended symbol ... started on line %d in file '%s'\n",
882 startline
+errLineOffset
, extPath
);
889 r
= processsymbol(yytext
);
894 int startline
, endchar
;
898 for (;yylen
<MAXYYLEN
;) {
904 case 'n' : yytext
[yylen
-1] = '\n'; break;
905 case 'r' : yytext
[yylen
-1] = '\r'; break;
906 case 't' : yytext
[yylen
-1] = '\t'; break;
907 case 'f' : yytext
[yylen
-1] = '\f'; break;
908 case 'v' : yytext
[yylen
-1] = '\v'; break;
910 } else if (c
== '\r') c
= '\n';
911 else if (c
== endchar
) break;
915 asRelativePath(curfilename
,extPath
);
916 post("Open ended string ... started on line %d in file '%s'\n",
917 startline
+errLineOffset
, extPath
);
926 } while (c
&& isspace(c
));
928 if (c
== '"') goto string1
;
929 else if (c
) unput0(c
);
932 r
= processstring(yytext
);
936 comment1
: /* comment -- to end of line */
939 } while (c
!= '\n' && c
!= '\r' && c
!= 0);
941 if (c
== 0) { r
= 0; goto leave
; }
945 int startline
, clevel
, prevc
;
951 if (c
== '/' && prevc
== '*') {
952 if (--clevel
<= 0) break;
953 } else if (c
== '*' && prevc
== '/') clevel
++;
958 asRelativePath(curfilename
,extPath
);
959 post("Open ended comment ... started on line %d in file '%s'\n",
960 startline
+errLineOffset
, extPath
);
972 asRelativePath(curfilename
, extPath
);
973 post("illegal input string '%s' \n at '%s' line %d char %d\n",
974 yytext
, extPath
, lineno
+errLineOffset
, charno
);
975 post("code %d\n", c
);
976 //postfl(" '%c' '%s'\n", c, binopchars);
977 //postfl("%d\n", strchr(binopchars, c));
980 asRelativePath(curfilename
, extPath
);
981 post(" in file '%s' line %d char %d\n", extPath
, lineno
+errLineOffset
, charno
);
989 if (gDebugLexer
) postfl("yylex: %d '%s'\n",r
,yytext
);
991 //if (lexCmdLine>0) postfl("yylex: %d '%s'\n",r,yytext);
995 int processbinop(char *token
)
1002 if (gDebugLexer
) postfl("processbinop: '%s'\n",token
);
1004 sym
= getsym(token
);
1005 SetSymbol(&slot
, sym
);
1006 node
= newPyrSlotNode(&slot
);
1008 if (strcmp(token
, "<-")==0) return LEFTARROW
;
1009 if (strcmp(token
, "<>")==0) return READWRITEVAR
;
1010 if (strcmp(token
, "|")==0) return '|';
1011 if (strcmp(token
, "<")==0) return '<';
1012 if (strcmp(token
, ">")==0) return '>';
1013 if (strcmp(token
, "-")==0) return '-';
1014 if (strcmp(token
, "*")==0) return '*';
1015 if (strcmp(token
, "+")==0) return '+';
1019 int processkeywordbinop(char *token
)
1025 //post("'%s' file '%s'\n", token, curfilename);
1028 if (gDebugLexer
) postfl("processkeywordbinop: '%s'\n",token
);
1030 token
[strlen(token
)-1] = 0; // strip off colon
1031 sym
= getsym(token
);
1032 SetSymbol(&slot
, sym
);
1033 node
= newPyrSlotNode(&slot
);
1038 int processident(char *token
)
1050 if (gDebugLexer
) postfl("word: '%s'\n",token
);
1053 strcpy(uptoken, token);
1054 for (str = uptoken; *str; ++str) {
1055 if (*str >= 'a' && *str <= 'z') *str += 'A' - 'a';
1058 if (token
[0] == '_') {
1059 if (token
[1] == 0) {
1060 node
= newPyrCurryArgNode();
1064 sym
= getsym(token
);
1065 SetSymbol(&slot
, sym
);
1066 node
= newPyrSlotNode(&slot
);
1068 return PRIMITIVENAME
;
1071 if (token
[0] >= 'A' && token
[0] <= 'Z') {
1072 sym
= getsym(token
);
1073 SetSymbol(&slot
, sym
);
1074 node
= newPyrSlotNode(&slot
);
1077 if (gDebugLexer
) postfl("CLASSNAME: '%s'\n",token
);
1081 if (strcmp("var",token
) ==0) return VAR
;
1082 if (strcmp("arg",token
) ==0) return ARG
;
1083 if (strcmp("classvar",token
) ==0) return CLASSVAR
;
1084 if (strcmp("const",token
) ==0) return SC_CONST
;
1086 if (strcmp("while",token
) ==0) {
1088 sym
= getsym(token
);
1089 SetSymbol(&slot
, sym
);
1090 node
= newPyrSlotNode(&slot
);
1094 if (strcmp("pi",token
) ==0) {
1095 SetFloat(&slot
, pi
);
1096 node
= newPyrSlotNode(&slot
);
1100 if (strcmp("true",token
) ==0) {
1102 node
= newPyrSlotNode(&slot
);
1106 if (strcmp("false",token
) ==0) {
1108 node
= newPyrSlotNode(&slot
);
1112 if (strcmp("nil",token
) ==0) {
1114 node
= newPyrSlotNode(&slot
);
1118 if (strcmp("inf",token
) ==0) {
1119 SetFloat(&slot
, std::numeric_limits
<double>::infinity());
1120 node
= newPyrSlotNode(&slot
);
1125 sym
= getsym(token
);
1127 SetSymbol(&slot
, sym
);
1128 node
= newPyrSlotNode(&slot
);
1133 int processhex(char *s
)
1140 if (gDebugLexer
) postfl("processhex: '%s'\n",s
);
1146 if (*c
>= '0' && *c
<= '9') val
= val
*16 + *c
- '0';
1147 else if (*c
>= 'a' && *c
<= 'z') val
= val
*16 + *c
- 'a' + 10;
1148 else if (*c
>= 'A' && *c
<= 'Z') val
= val
*16 + *c
- 'A' + 10;
1153 node
= newPyrSlotNode(&slot
);
1159 int processintradix(char *s
, int n
, int radix
)
1164 if (gDebugLexer
) postfl("processintradix: '%s'\n",s
);
1167 SetInt(&slot
, sc_strtoi(s
, n
, radix
));
1168 node
= newPyrSlotNode(&slot
);
1173 int processfloatradix(char *s
, int n
, int radix
)
1178 if (gDebugLexer
) postfl("processfloatradix: '%s'\n",s
);
1181 SetFloat(&slot
, sc_strtof(s
, n
, radix
));
1182 node
= newPyrSlotNode(&slot
);
1187 int processint(char *s
)
1192 if (gDebugLexer
) postfl("processint: '%s'\n",s
);
1195 SetInt(&slot
, atoi(s
));
1196 node
= newPyrSlotNode(&slot
);
1201 int processchar(int c
)
1206 if (gDebugLexer
) postfl("processhex: '%c'\n",c
);
1210 node
= newPyrSlotNode(&slot
);
1215 int processfloat(char *s
, int sawpi
)
1221 if (gDebugLexer
) postfl("processfloat: '%s'\n",s
);
1224 if (sawpi
) { z
= atof(s
)*pi
; SetFloat(&slot
, z
); }
1225 else { SetFloat(&slot
, atof(s
)); }
1226 node
= newPyrSlotNode(&slot
);
1232 int processaccidental1(char *s
)
1239 double centsdiv
=1000.;
1241 printf("processaccidental1: '%s'\n",s
);
1246 if (*c
>= '0' && *c
<= '9') degree
= degree
*10. + *c
- '0';
1251 if (*c
== 'b') centsdiv
= -1000.;
1252 else if (*c
== 's') centsdiv
= 1000.;
1256 if (*c
>= '0' && *c
<= '9') {
1257 cents
= cents
*10. + *c
- '0';
1263 if (cents
> 499.) cents
= 499.;
1265 SetFloat(&slot
, degree
+ cents
/centsdiv
);
1266 node
= newPyrSlotNode(&slot
);
1271 int processaccidental2(char *s
)
1277 double semitones
=0.;
1279 printf("processaccidental2: '%s'\n",s
);
1284 if (*c
>= '0' && *c
<= '9') degree
= degree
*10. + *c
- '0';
1290 if (*c
== 'b') semitones
-= 1.;
1291 else if (*c
== 's') semitones
+= 1.;
1295 if (semitones
> 4.) semitones
= 4.;
1297 SetFloat(&slot
, degree
+ semitones
/10.);
1298 node
= newPyrSlotNode(&slot
);
1303 int processsymbol(char *s
)
1309 if (gDebugLexer
) postfl("processsymbol: '%s'\n",s
);
1313 SetSymbol(&slot
, sym
);
1314 node
= newPyrSlotNode(&slot
);
1319 int processstring(char *s
)
1325 if (gDebugLexer
) postfl("processstring: '%s'\n",s
);
1327 int flags
= compilingCmdLine
? obj_immutable
: obj_permanent
| obj_immutable
;
1328 string
= newPyrString(gMainVMGlobals
->gc
, s
+1, flags
, false);
1329 SetObject(&slot
, string
);
1330 node
= newPyrSlotNode(&slot
);
1335 void yyerror(const char *s
)
1339 error("Parse error\n");
1340 postErrorLine(lineno
, linepos
, charno
);
1348 error("Parse error\n");
1349 postErrorLine(lineno
, linepos
, charno
);
1354 void postErrorLine()
1356 int i
, j
, start
, end
;
1360 for (i
=textpos
-1; i
>=0; --i
) {
1361 if (text
[i
] == '\r' || text
[i
] == '\n') break;
1364 for (i
=textpos
; i
< textlen
; ++i
) {
1365 if (text
[i
] == '\r' || text
[i
] == '\n') break;
1368 for (i
=start
, j
=0; i
<end
; ++i
) {
1369 if (i
== textpos
) str
[j
++] = '¶';
1372 if (textpos
== end
) str
[j
++] = '¶';
1375 postfl("%s\n", str
);
1379 void postErrorLine(int linenum
, int start
, int charpos
)
1384 //post("start %d\n", start);
1385 //parseFailed = true;
1386 char extPath
[MAXPATHLEN
];
1387 asRelativePath(curfilename
, extPath
);
1388 post(" in file '%s'\n", extPath
);
1389 post(" line %d char %d:\n", linenum
+errLineOffset
, charpos
);
1390 // nice: postfl previous line for context
1392 //postfl("text '%s' %d\n", text, text);
1394 // postfl error line for context
1395 pos
= start
+ charpos
;
1396 for (i
=pos
; i
< textlen
; ++i
) {
1397 if (text
[i
] == 0 || text
[i
] == '\r' || text
[i
] == '\n') break;
1400 for (i
=start
, j
=0; i
<end
&& j
<255; ++i
) {
1401 if (i
== pos
) str
[j
++] = BULLET_CHAR
;
1404 if (pos
== end
) str
[j
++] = BULLET_CHAR
;
1410 // postfl following line for context
1411 for (j
=0; j
<255 && i
<textlen
; ++i
) {
1412 if (text
[i
] == 0 ||text
[i
] == '\r' || text
[i
] == '\n') break;
1418 post("-----------------------------------\n", str
);
1422 void c2pstrcpy(unsigned char* dst, const char *src);
1423 void c2pstrcpy(unsigned char* dst, const char *src)
1426 unsigned char *dstp = &dst[1];
1427 while ((c = *src++) != 0) *dstp++ = c;
1428 dst[0] = dstp - dst - 1;
1431 void p2cstrcpy(char *dst, const unsigned char* src);
1432 void p2cstrcpy(char *dst, const unsigned char* src)
1435 for (int i=0; i<n; ++i) *dst++ = *src++;
1440 void pstrncpy(unsigned char *s1
, unsigned char *s2
, int n
);
1441 void pstrncpy(unsigned char *s1
, unsigned char *s2
, int n
)
1445 n
= (n
< m
) ? n
: m
;
1447 for (i
=0; i
<n
; ++i
) { *s1
= *s2
; s1
++; s2
++; }
1450 int pstrcmp(unsigned char *s1
, unsigned char *s2
);
1451 int pstrcmp(unsigned char *s1
, unsigned char *s2
)
1453 int i
, len1
, len2
, len
;
1456 len
= sc_min(len1
, len2
);
1457 for (i
=0; i
<len
; ++i
) {
1458 if (s1
[i
] < s2
[i
]) return -1;
1459 if (s1
[i
] > s2
[i
]) return 1;
1461 if (len1
< len2
) return -1;
1462 if (len1
> len2
) return 1;
1466 bool scanForClosingBracket()
1468 int r
, c
, d
, startLevel
;
1470 // finite state machine to parse input stream into tokens
1473 if (gDebugLexer
) postfl("->scanForClosingBracket\n");
1475 startLevel
= brackets
.num
;
1479 if (c
== 0) goto leave
;
1480 else if (c
==' ' || c
=='\t' || c
=='\n' || c
=='\r' || c
=='\v' || c
=='\f') {
1483 else if (c
== '\'') goto symbol3
;
1484 else if (c
== '"') goto string1
;
1485 else if (c
== '/') {
1487 if (c
== '/') goto comment1
;
1488 else if (c
== '*') goto comment2
;
1489 else { unput(c
); goto start
; }
1491 else if (c
== '$') {
1496 case 'n' : c
= '\n'; break;
1497 case 'r' : c
= '\r'; break;
1498 case 't' : c
= '\t'; break;
1499 case 'f' : c
= '\f'; break;
1500 case 'v' : c
= '\v'; break;
1505 else if (c
== OPENPAREN
|| c
== OPENSQUAR
|| c
== OPENCURLY
) {
1506 pushls(&brackets
, (int)c
);
1510 else if (c
== CLOSSQUAR
) {
1511 if (!emptyls(&brackets
)) {
1512 if ((d
= popls(&brackets
)) != OPENSQUAR
) {
1514 post("opening bracket was a '%c', but found a '%c'\n",d
,c
);
1519 post("unmatched '%c'\n",c
);
1523 if (brackets
.num
< startLevel
) goto leave
;
1526 else if (c
== CLOSPAREN
) {
1527 if (!emptyls(&brackets
)) {
1528 if ((d
= popls(&brackets
)) != OPENPAREN
) {
1530 post("opening bracket was a '%c', but found a '%c'\n",d
,c
);
1535 post("unmatched '%c'\n",c
);
1538 if (brackets
.num
< startLevel
) goto leave
;
1541 else if (c
== CLOSCURLY
) {
1542 if (!emptyls(&brackets
)) {
1543 if ((d
= popls(&brackets
)) != OPENCURLY
) {
1545 post("opening bracket was a '%c', but found a '%c'\n",d
,c
);
1550 post("unmatched '%c'\n",c
);
1553 if (brackets
.num
< startLevel
) goto leave
;
1559 int startline
, endchar
;
1568 } while (c
!= endchar
&& c
!= 0);
1570 char extPath
[MAXPATHLEN
];
1571 asRelativePath(curfilename
, extPath
);
1572 post("Open ended symbol ... started on line %d in file '%s'\n",
1573 startline
, extPath
);
1580 int startline
, endchar
;
1589 } while (c
!= endchar
&& c
!= 0);
1591 char extPath
[MAXPATHLEN
];
1592 asRelativePath(curfilename
, extPath
);
1593 post("Open ended string ... started on line %d in file '%s'\n",
1594 startline
, extPath
);
1599 comment1
: /* comment -- to end of line */
1602 } while (c
!= '\n' && c
!= '\r' && c
!= 0);
1603 if (c
== 0) { goto leave
; }
1607 int startline
, clevel
, prevc
;
1613 if (c
== '/' && prevc
== '*') {
1614 if (--clevel
<= 0) break;
1615 } else if (c
== '*' && prevc
== '/') clevel
++;
1619 char extPath
[MAXPATHLEN
];
1620 asRelativePath(curfilename
, extPath
);
1621 post("Open ended comment ... started on line %d in file '%s'\n",
1622 startline
, extPath
);
1629 char extPath
[MAXPATHLEN
];
1630 asRelativePath(curfilename
, extPath
);
1631 post(" in file '%s' line %d char %d\n", extPath
, lineno
, charno
);
1641 if (gDebugLexer
) postfl("<-scanForClosingBracket\n");
1648 static ClassExtFile
* sClassExtFiles
;
1649 static ClassExtFile
* eClassExtFiles
;
1651 ClassExtFile
* newClassExtFile(PyrSymbol
*fileSym
, int startPos
, int endPos
);
1652 ClassExtFile
* newClassExtFile(PyrSymbol
*fileSym
, int startPos
, int endPos
)
1654 ClassExtFile
* classext
;
1655 classext
= (ClassExtFile
*)pyr_pool_compile
->Alloc(sizeof(ClassExtFile
));
1656 classext
->fileSym
= fileSym
;
1658 classext
->startPos
= startPos
;
1659 classext
->endPos
= endPos
;
1660 if (!sClassExtFiles
) sClassExtFiles
= classext
;
1661 else eClassExtFiles
->next
= classext
;
1662 eClassExtFiles
= classext
;
1667 ClassDependancy
* newClassDependancy(PyrSymbol
*className
, PyrSymbol
*superClassName
,
1668 PyrSymbol
*fileSym
, int startPos
, int endPos
, int lineOffset
)
1670 ClassDependancy
* classdep
;
1672 //post("classdep '%s' '%s' '%s' %d %d\n", className->name, superClassName->name,
1673 // fileSym->name, className, superClassName);
1675 // lifetime: kill after compile.
1677 if (className
->classdep
) {
1678 error("duplicate Class found: '%s' \n", className
->name
);
1679 post("%s\n",className
->classdep
->fileSym
->name
);
1680 postfl("%s\n\n",fileSym
->name
);
1681 return className
->classdep
;
1683 classdep
= (ClassDependancy
*)pyr_pool_compile
->Alloc(sizeof(ClassDependancy
));
1685 classdep
->className
= className
;
1686 classdep
->superClassName
= superClassName
;
1687 classdep
->fileSym
= fileSym
;
1688 classdep
->superClassDep
= NULL
;
1689 classdep
->next
= NULL
;
1690 classdep
->subclasses
= NULL
;
1692 classdep
->startPos
= startPos
;
1693 classdep
->endPos
= endPos
;
1694 classdep
->lineOffset
= lineOffset
;
1696 className
->classdep
= classdep
;
1702 ClassDependancy
*next
;
1703 SymbolTable
* symbolTable
= gMainVMGlobals
->symbolTable
;
1705 //postfl("->buildDepTree\n"); fflush(stdout);
1706 for (int i
=0; i
<symbolTable
->TableSize(); ++i
) {
1707 PyrSymbol
*sym
= symbolTable
->Get(i
);
1708 if (sym
&& (sym
->flags
& sym_Class
)) {
1709 if (sym
->classdep
) {
1710 if (sym
->classdep
->superClassName
->classdep
) {
1711 next
= sym
->classdep
->superClassName
->classdep
->subclasses
;
1712 sym
->classdep
->superClassName
->classdep
->subclasses
= sym
->classdep
;
1713 sym
->classdep
->next
= next
;
1714 } else if (sym
->classdep
->superClassName
!= s_none
) {
1715 error("Superclass '%s' of class '%s' is not defined in any file.\n%s\n",
1716 sym
->classdep
->superClassName
->name
, sym
->classdep
->className
->name
,sym
->classdep
->fileSym
->name
);
1721 //postfl("<-buildDepTree\n"); fflush(stdout);
1724 extern PyrClass
*gClassList
;
1726 ClassDependancy
**gClassCompileOrder
;
1727 int gClassCompileOrderNum
= 0;
1728 int gClassCompileOrderSize
= 1000;
1730 void compileDepTree();
1732 void traverseFullDepTree()
1734 //postfl("->traverseFullDepTree\n"); fflush(stdout);
1735 gClassCompileOrderNum
= 0;
1736 gClassCompileOrder
= (ClassDependancy
**)pyr_pool_compile
->Alloc(
1737 gClassCompileOrderSize
* sizeof(ClassDependancy
));
1738 MEMFAIL(gClassCompileOrder
);
1740 // parse and compile all files
1741 initParser(); // sets compiler errors to 0
1744 traverseDepTree(s_object
->classdep
, 0);
1745 compileDepTree(); // compiles backwards using the order defined in gClassCompileOrder
1746 compileClassExtensions();
1748 pyr_pool_compile
->Free(gClassCompileOrder
);
1751 //postfl("<-traverseFullDepTree\n"); fflush(stdout);
1755 void traverseDepTree(ClassDependancy
*classdep
, int level
)
1757 ClassDependancy
*subclassdep
;
1759 if (!classdep
) return;
1761 subclassdep
= classdep
->subclasses
;
1762 for (; subclassdep
; subclassdep
= subclassdep
->next
) {
1763 traverseDepTree(subclassdep
, level
+1);
1765 if (gClassCompileOrderNum
> gClassCompileOrderSize
) {
1766 gClassCompileOrderSize
*= 2;
1767 gClassCompileOrder
= (ClassDependancy
**)pyr_pool_compile
->Realloc(gClassCompileOrder
,
1768 gClassCompileOrderSize
* sizeof(ClassDependancy
));
1769 MEMFAIL(gClassCompileOrder
);
1772 /* postfl("traverse level:%d, gClassCompileOrderNum:%d, '%s' '%s' '%s'\n", level, gClassCompileOrderNum, classdep->className->name, classdep->superClassName->name,
1773 classdep->fileSym->name); fflush(stdout);
1776 gClassCompileOrder
[gClassCompileOrderNum
++] = classdep
;
1780 void compileClass(PyrSymbol
*fileSym
, int startPos
, int endPos
, int lineOffset
)
1782 //fprintf(stderr, "compileClass: %d\n", fileSym->u.index);
1784 gCompilingFileSym
= fileSym
;
1785 gCompilingVMGlobals
= 0;
1786 gRootParseNode
= NULL
;
1788 if (startLexer(fileSym
, startPos
, endPos
, lineOffset
)) {
1789 //postfl("->Parsing %s\n", fileSym->name); fflush(stdout);
1790 parseFailed
= yyparse();
1791 //postfl("<-Parsing %s %d\n", fileSym->name, parseFailed); fflush(stdout);
1792 //post("parseFailed %d\n", parseFailed); fflush(stdout);
1793 if (!parseFailed
&& gRootParseNode
) {
1794 //postfl("Compiling nodes %p\n", gRootParseNode);fflush(stdout);
1795 compilingCmdLine
= false;
1796 compileNodeList(gRootParseNode
, true);
1797 //postfl("done compiling\n");fflush(stdout);
1800 char extPath
[MAXPATHLEN
];
1801 asRelativePath(fileSym
->name
, extPath
);
1802 error("file '%s' parse failed\n", extPath
);
1803 postfl("error parsing\n");
1807 error("file '%s' open failed\n", fileSym
->name
);
1812 void compileDepTree()
1814 ClassDependancy
*classdep
;
1817 for (i
=gClassCompileOrderNum
-1; i
>=0; --i
) {
1818 classdep
= gClassCompileOrder
[i
];
1819 /*postfl("compile %d '%s' '%s' '%s'...%d/%d/%d\n", i, classdep->className->name, classdep->superClassName->name,
1820 classdep->fileSym->name, classdep->startLine, classdep->endLine, classDep->lineOffset);*/
1821 compileClass(classdep
->fileSym
, classdep
->startPos
, classdep
->endPos
, classdep
->lineOffset
);
1823 //postfl("<compile\n");
1826 void compileClassExtensions()
1828 if (sClassExtFiles
) {
1829 ClassExtFile
*classext
= sClassExtFiles
;
1831 //postfl("compile class ext: %d/%d\n", classext->startPos, classext->endPos);
1832 compileClass(classext
->fileSym
, classext
->startPos
, classext
->endPos
, -1);
1833 classext
= classext
->next
;
1838 void findDiscrepancy();
1840 void traverseFullDepTree2()
1843 // assign a class index to all classes
1844 if (!parseFailed
&& !compileErrors
) {
1848 // now I index them during pass one
1849 indexClassTree(class_object
, 0);
1851 if (2*numClassDeps
!= gNumClasses
) {
1852 error("There is a discrepancy.\n");
1853 /* not always correct
1854 if(2*numClassDeps < gNumClasses) {
1855 post("Duplicate files may exist in the directory structure.\n");
1857 post("Some class files may be missing.\n");
1860 post("numClassDeps %d gNumClasses %d\n", numClassDeps
, gNumClasses
);
1865 buildBigMethodMatrix();
1866 SymbolTable
* symbolTable
= gMainVMGlobals
->symbolTable
;
1867 post("\tNumber of Symbols %d\n", symbolTable
->NumItems());
1868 post("\tByte Code Size %d\n", totalByteCodes
);
1869 //elapsed = TickCount() - compileStartTime;
1871 elapsed
= elapsedTime() - compileStartTime
;
1872 post("\tcompiled %d files in %.2f seconds\n",
1873 gNumCompiledFiles
, elapsed
);
1874 if(numOverwrites
== 1){
1875 post("\nInfo: One method is currently overwritten by an extension. To see which, execute:\nMethodOverride.printAll\n\n");
1877 else if(numOverwrites
> 1){
1878 post("\nInfo: %i methods are currently overwritten by extensions. To see which, execute:\nMethodOverride.printAll\n\n", numOverwrites
);
1880 post("compile done\n");
1885 bool parseOneClass(PyrSymbol
*fileSym
)
1888 PyrSymbol
*className
, *superClassName
;
1889 ClassDependancy
*classdep
;
1892 int startPos
, startLine
, startLineOffset
;
1897 startLineOffset
= lineno
- 1;
1900 if (token
== CLASSNAME
) {
1901 className
= slotRawSymbol(&((PyrSlotNode
*)zzval
)->mSlot
);
1902 // I think this is wrong: zzval is space pool alloced
1903 //pyrfree((PyrSlot*)zzval);
1906 if (token
== 0) return false;
1907 if (token
== OPENSQUAR
) {
1908 scanForClosingBracket(); // eat indexing spec
1910 if (token
== 0) return false;
1913 token
= yylex(); // get super class
1914 if (token
== 0) return false;
1915 if (token
== CLASSNAME
) {
1916 superClassName
= slotRawSymbol(&((PyrSlotNode
*)zzval
)->mSlot
);
1917 // I think this is wrong: zzval is space pool alloced
1918 //pyrfree((PyrSlot*)zzval);
1920 if (token
== 0) return false;
1921 if (token
== OPENCURLY
) {
1922 scanForClosingBracket(); // eat class body
1923 classdep
= newClassDependancy(className
, superClassName
, fileSym
, startPos
, textpos
, startLineOffset
);
1926 postfl("Expected %c. got token: '%s' %d\n", OPENCURLY
, yytext
, token
);
1927 postErrorLine(lineno
, linepos
, charno
);
1932 post("Expected superclass name. got token: '%s' %d\n", yytext
, token
);
1933 postErrorLine(lineno
, linepos
, charno
);
1936 } else if (token
== OPENCURLY
) {
1937 if (className
== s_object
) superClassName
= s_none
;
1938 else superClassName
= s_object
;
1939 scanForClosingBracket(); // eat class body
1940 classdep
= newClassDependancy(className
, superClassName
, fileSym
, startPos
, textpos
, startLineOffset
);
1943 post("Expected ':' or %c. got token: '%s' %d\n", OPENCURLY
, yytext
, token
);
1944 postErrorLine(lineno
, linepos
, charno
);
1947 } else if (token
== '+') {
1949 if (token
== 0) return false;
1950 scanForClosingBracket();
1952 newClassExtFile(fileSym
, startPos
, textpos
);
1957 post("Expected class name. got token: '%s' %d\n", yytext
, token
);
1958 postErrorLine(lineno
, linepos
, charno
);
1967 //void ClearLibMenu();
1969 void aboutToFreeRuntime();
1970 void aboutToFreeRuntime()
1975 //void init_graph_compile();
1976 //void tellPlugInsAboutToCompile();
1977 void pyrmath_init_globs();
1981 aboutToFreeRuntime();
1983 //dump_pool_histo(pyr_pool_runtime);
1984 pyr_pool_runtime
->FreeAllInternal();
1985 //dump_pool_histo(pyr_pool_runtime);
1986 //gPermanentObjPool.Init(pyr_pool_runtime, PERMOBJCHUNK);
1989 void *ptr
= pyr_pool_runtime
->Alloc(sizeof(SymbolTable
));
1990 gMainVMGlobals
->symbolTable
= new (ptr
) SymbolTable(pyr_pool_runtime
, 8192);
1992 //gFileSymbolTable = newSymbolTable(512);
1994 pyrmath_init_globs();
1996 initSymbols(); // initialize symbol globals
1997 //init_graph_compile();
1998 initSpecialSelectors();
1999 initSpecialClasses();
2004 //tellPlugInsAboutToCompile();
2009 compiledDirectories
.clear();
2010 sc_InitCompileDirectory();
2015 //postfl("->finiPassOne\n");
2017 //postfl("<-finiPassOne\n");
2020 static bool passOne_ProcessDir(const char *dirname
, int level
)
2022 if (!sc_DirectoryExists(dirname
))
2025 if (compiledDirectories
.find(std::string(dirname
)) != compiledDirectories
.end())
2029 bool success
= true;
2031 if (gLibraryConfig
&& gLibraryConfig
->pathIsExcluded(dirname
)) {
2032 post("\texcluding dir: '%s'\n", dirname
);
2036 if (level
== 0) post("\tcompiling dir: '%s'\n", dirname
);
2038 SC_DirHandle
*dir
= sc_OpenDir(dirname
);
2040 error("open directory failed '%s'\n", dirname
); fflush(stdout
);
2045 char diritem
[MAXPATHLEN
];
2046 bool skipItem
= true;
2047 bool validItem
= sc_ReadDir(dir
, dirname
, diritem
, skipItem
);
2048 if (!validItem
) break;
2049 if (skipItem
) continue;
2051 if (sc_DirectoryExists(diritem
)) {
2052 success
= passOne_ProcessDir(diritem
, level
+ 1);
2054 success
= passOne_ProcessOneFile(diritem
, level
+ 1);
2057 if (!success
) break;
2060 compiledDirectories
.insert(std::string(dirname
));
2069 if (sc_IsStandAlone()) {
2070 /// FIXME: this should be moved to the LibraryConfig file
2071 if (!passOne_ProcessDir(gCompileDir
, 0))
2074 if (!gLibraryConfig
->forEachIncludedDirectory(passOne_ProcessDir
))
2081 // true if filename ends in ".sc"
2082 bool isValidSourceFileName(char *filename
)
2084 int len
= strlen(filename
);
2085 bool validExtension
= (len
>3 && strncmp(filename
+len
-3, ".sc", 3) == 0)
2086 || (len
>7 && strncmp(filename
+len
-7, ".sc.rtf", 7) == 0);
2087 if (!validExtension
)
2090 boost::filesystem::path
pathname(filename
);
2092 if (pathname
.filename().c_str()[0] == '.') // hidden filename
2098 // sekhar's replacement
2099 bool passOne_ProcessOneFile(const char * filenamearg
, int level
)
2101 bool success
= true;
2103 bool isAlias
= false;
2105 char filename
[MAXPATHLEN
];
2106 int status
= sc_ResolveIfAlias(filenamearg
, filename
, isAlias
, MAXPATHLEN
);
2109 printf("WARNING: skipping invalid symbolic link: %s\n", filenamearg
);
2113 if (gLibraryConfig
&& gLibraryConfig
->pathIsExcluded(filename
)) {
2114 post("\texcluding file: '%s'\n", filename
);
2118 if (isValidSourceFileName(filename
)) {
2119 gNumCompiledFiles
++;
2120 PyrSymbol
* fileSym
= getsym(filename
);
2121 fileSym
->u
.source
= NULL
;
2122 if (startLexer(fileSym
, -1, -1, -1)) {
2123 while (parseOneClass(fileSym
)) { };
2126 error("file '%s' open failed\n", filename
);
2130 if (sc_DirectoryExists(filename
))
2131 success
= passOne_ProcessDir(filename
, level
);
2138 void compileSucceeded();
2139 void compileSucceeded()
2141 compiledOK
= !(parseFailed
|| compileErrors
);
2145 compiledOK
= initRuntime(gMainVMGlobals
, 128*1024, pyr_pool_runtime
);
2148 VMGlobals
*g
= gMainVMGlobals
;
2150 g
->canCallOS
= true;
2151 //++g->sp; SetObject(g->sp, g->process);
2152 //runInterpreter(g, s_hardwaresetup, 1);
2154 ++g
->sp
; SetObject(g
->sp
, g
->process
);
2155 runInterpreter(g
, s_startup
, 1);
2156 g
->canCallOS
= false;
2164 void aboutToCompileLibrary();
2165 void aboutToCompileLibrary()
2167 //printf("->aboutToCompileLibrary\n");
2168 pthread_mutex_lock (&gLangMutex
);
2170 ++gMainVMGlobals
->sp
;
2171 SetObject(gMainVMGlobals
->sp
, gMainVMGlobals
->process
);
2172 runInterpreter(gMainVMGlobals
, s_shutdown
, 1);
2173 gVMGlobals
.gc
->ScanFinalizers(); // run finalizers
2175 pthread_mutex_unlock (&gLangMutex
);
2176 //printf("<-aboutToCompileLibrary\n");
2179 void closeAllGUIScreens();
2180 void TempoClock_stopAll(void);
2181 void closeAllCustomPorts();
2183 void shutdownLibrary()
2185 closeAllGUIScreens();
2187 aboutToCompileLibrary();
2189 TempoClock_stopAll();
2191 pthread_mutex_lock (&gLangMutex
);
2192 closeAllCustomPorts();
2194 pyr_pool_runtime
->FreeAll();
2196 pthread_mutex_unlock (&gLangMutex
);
2199 SC_DLLEXPORT_C
bool compileLibrary()
2201 //printf("->compileLibrary\n");
2204 pthread_mutex_lock (&gLangMutex
);
2205 gNumCompiledFiles
= 0;
2208 // FIXME: the library config should have been initialized earlier!
2209 if (!gLibraryConfig
)
2210 SC_LanguageConfig::readDefaultLibraryConfig();
2212 compileStartTime
= elapsedTime();
2217 postfl("compiling class library...\n");
2219 postfl("compiling class library (debug build)...\n");
2222 bool res
= passOne();
2225 postfl("\tpass 1 done\n");
2227 if (!compileErrors
) {
2229 traverseFullDepTree();
2230 traverseFullDepTree2();
2233 if (!compileErrors
&& gShowWarnings
) {
2234 SymbolTable
* symbolTable
= gMainVMGlobals
->symbolTable
;
2235 symbolTable
->CheckSymbols();
2238 pyr_pool_compile
->FreeAll();
2245 pthread_mutex_unlock (&gLangMutex
);
2246 //printf("<-compileLibrary\n");
2250 void signal_init_globs();
2252 void dumpByteCodes(PyrBlock
*theBlock
);
2254 SC_DLLEXPORT_C
void runLibrary(PyrSymbol
* selector
)
2256 VMGlobals
*g
= gMainVMGlobals
;
2257 g
->canCallOS
= true;
2260 ++g
->sp
; SetObject(g
->sp
, g
->process
);
2261 runInterpreter(g
, selector
, 1);
2263 postfl("Library has not been compiled successfully.\n");
2265 } catch (std::exception
&ex
) {
2266 PyrMethod
*meth
= g
->method
;
2268 int ip
= slotRawInt8Array(&meth
->code
) ? g
->ip
- slotRawInt8Array(&meth
->code
)->b
: -1;
2269 post("caught exception in runLibrary %s:%s %3d\n",
2270 slotRawSymbol(&slotRawClass(&meth
->ownerclass
)->name
)->name
, slotRawSymbol(&meth
->name
)->name
, ip
2272 dumpByteCodes(meth
);
2274 post("caught exception in runLibrary\n");
2278 postfl(BULLET
"DANGER: OUT of MEMORY. Operation failed.\n");
2280 g
->canCallOS
= false;
2283 void interpretCmdLine(const char *textbuf
, int textlen
, char *methodname
)
2290 string
= newPyrStringN(gMainVMGlobals
->gc
, textlen
, 0, false);
2291 memcpy(string
->s
, textbuf
, textlen
);
2292 SetObject(&slotRawInterpreter(&gMainVMGlobals
->process
->interpreter
)->cmdLine
, string
);
2293 gMainVMGlobals
->gc
->GCWrite(slotRawObject(&gMainVMGlobals
->process
->interpreter
), string
);
2294 SetObject(&slot
, gMainVMGlobals
->process
);
2296 // ProfilerInit(collectSummary, microsecondsTimeBase, 500, 100);
2298 slotCopy((++gMainVMGlobals
->sp
), &slot
);
2299 runInterpreter(gMainVMGlobals
, getsym(methodname
), 1);
2301 // ProfilerDump("\pErase2.prof");
2305 postfl("Library has not been compiled successfully.\n");
2309 void init_SuperCollider()