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
22 Primitives for String.
26 #include "PyrPrimitive.h"
27 #include "PyrKernel.h"
34 #include "SC_DirUtils.h"
37 # include "SC_Win32Utils.h"
39 # include <sys/param.h>
42 #include <boost/filesystem/path.hpp>
43 #include <boost/filesystem/operations.hpp>
44 #include <boost/regex.hpp>
45 #include <boost/intrusive/list.hpp>
46 #include <boost/intrusive/unordered_set.hpp>
53 int prStringAsSymbol(struct VMGlobals
*g
, int numArgsPushed
);
54 int prStringAsSymbol(struct VMGlobals
*g
, int numArgsPushed
)
57 char str
[1024], *strp
=0;
61 len
= slotRawObject(a
)->size
;
62 strp
= len
> 1023 ? (char*)malloc(len
+1) : str
;
64 memcpy(strp
, slotRawString(a
)->s
, len
);
67 SetSymbol(a
, getsym(strp
));
69 if (len
> 1023) free(strp
);
74 int prString_AsInteger(struct VMGlobals
*g
, int numArgsPushed
);
75 int prString_AsInteger(struct VMGlobals
*g
, int numArgsPushed
)
80 int err
= slotStrVal(a
, str
, 255);
88 int prString_AsFloat(struct VMGlobals
*g
, int numArgsPushed
);
89 int prString_AsFloat(struct VMGlobals
*g
, int numArgsPushed
)
94 int err
= slotStrVal(a
, str
, 255);
97 SetFloat(a
, atof(str
));
102 int prString_AsCompileString(struct VMGlobals
*g
, int numArgsPushed
)
105 PyrString
* scstr
= slotRawString(a
);
106 char *chars1
= scstr
->s
;
107 int newSize
= scstr
->size
+ 2;
108 for (int i
=0; i
<scstr
->size
; ++i
) {
109 if (chars1
[i
] == '"' || chars1
[i
] == '\\') newSize
++;
111 PyrString
*newString
= newPyrStringN(g
->gc
, newSize
, 0, true);
112 char *chars2
= newString
->s
;
114 chars2
[newSize
- 1] = '"';
116 for (int i
=0; i
<scstr
->size
; ++i
) {
118 if (c
== '"' || c
== '\\') chars2
[k
++] = '\\';
121 SetObject(a
, newString
);
125 int prString_Format(struct VMGlobals
*g
, int numArgsPushed
)
127 PyrSlot
*a
= g
->sp
- 1;
130 if (!isKindOfSlot(b
, class_array
)) return errWrongType
;
132 char *fmt
= slotRawString(a
)->s
;
134 int asize
= slotRawObject(a
)->size
;
135 int bsize
= slotRawObject(b
)->size
;
138 PyrSlot
*slots
= slotRawObject(b
)->slots
;
139 for (int i
=0; i
<bsize
; ++i
) {
140 PyrSlot
*slot
= slots
+ i
;
141 if (!isKindOfSlot(slot
, class_string
)) return errWrongType
;
142 csize
+= slotRawString(slot
)->size
;
144 PyrString
*newString
= newPyrStringN(g
->gc
, csize
, 0, true);
145 char* buf
= newString
->s
;
149 for (int i
=0; i
<asize
;) {
153 PyrString
* bstring
= slotRawString(&slots
[index
]);
154 memcpy(buf
+k
, bstring
->s
, bstring
->size
);
158 } else if (ch
== '\\') {
159 if (i
>= asize
) break;
171 SetObject(a
, newString
);
177 namespace bin
= boost::intrusive
;
179 class regex_lru_cache
184 bin::list_base_hook
<>,
185 bin::unordered_set_base_hook
<>
188 regex_node(const char * str
, size_t size
, int regex_flags
):
189 pattern(str
, size
, regex_flags
)
192 boost::regex
const & get (void) const
198 boost::regex pattern
;
203 bool operator()(regex_node
const & lhs
, regex_node
const & rhs
) const
205 return lhs
.get() == rhs
.get();
208 bool operator()(const char * lhs
, regex_node
const & rhs
) const
210 return strcmp(lhs
, rhs
.get().str().c_str()) == 0;
214 static inline std::size_t string_hash(const char * str
)
221 ret
= c
+ (ret
<< 6) + (ret
<< 16) - ret
;
228 size_t operator()(regex_node
const & arg
) const
230 return string_hash(arg
.get().str().c_str());
233 size_t operator()(const char * arg
) const
235 return string_hash(arg
);
239 typedef bin::unordered_set
<regex_node
, bin::equal
<regex_equal
>, bin::hash
<regex_hash
>,
240 bin::power_2_buckets
<true>, bin::constant_time_size
<false> >
242 typedef re_set_t::bucket_type bucket_type
;
243 typedef re_set_t::bucket_traits bucket_traits
;
244 bucket_type buckets
[128];
247 bin::list
<regex_node
> re_list
;
251 regex_node
& rlu
= re_list
.back();
258 regex_lru_cache(int regex_flags
= boost::regex_constants::ECMAScript
):
259 re_set(bucket_traits(buckets
, 128))
264 while (!re_list
.empty()) {
269 boost::regex
const & get_regex(const char * str
, size_t size
)
271 re_set_t::iterator re_in_cache
= re_set
.find(str
, regex_hash(), regex_equal());
272 if (re_in_cache
!= re_set
.end()) {
273 regex_node
& node
= *re_in_cache
;
274 bin::list
<regex_node
>::iterator re_in_list
= bin::list
<regex_node
>::s_iterator_to(node
);
276 re_list
.splice(re_list
.begin(), re_list
, re_in_list
); // move to the begin of the list
277 assert(&re_list
.front() == &node
);
281 if (re_list
.size() >= 64)
284 regex_node
* new_node
= new regex_node(str
, size
, regex_flags
);
285 re_set
.insert(*new_node
);
286 re_list
.push_front(*new_node
);
287 return new_node
->get();
293 int prString_Regexp(struct VMGlobals
*g
, int numArgsPushed
)
296 static detail::regex_lru_cache
regex_lru_cache(boost::regex_constants::ECMAScript
| boost::regex_constants::nosubs
);
298 using namespace boost
;
300 int err
, start
, end
, ret
, len
;
302 PyrSlot
*a
= g
->sp
- 3;
303 PyrSlot
*b
= g
->sp
- 2;
304 PyrSlot
*c
= g
->sp
- 1;
307 if (!isKindOfSlot(b
, class_string
)) return errWrongType
;
308 if (NotInt(c
) || (NotInt(d
) && NotNil(d
))) return errWrongType
;
309 start
= slotRawInt(c
);
311 len
= slotRawObject(b
)->size
; // last char index instead of size
322 if(end
- start
<= 0) {
327 int stringlen
= end
- start
;
330 regex
const & pattern
= regex_lru_cache
.get_regex(slotRawString(a
)->s
, slotRawObject(a
)->size
);
331 match_flag_type flags
= match_nosubs
| match_any
;
333 const char * stringStart
= slotRawString(b
)->s
+ start
;
334 const char * stringEnd
= stringStart
+ stringlen
;
335 bool res
= regex_search(stringStart
, stringEnd
, pattern
, flags
);
343 } catch (std::exception
const & e
) {
344 postfl("Warning: Exception in _String_Regexp - %s\n", e
.what());
349 struct sc_regexp_match
{
355 static int prString_FindRegexp(struct VMGlobals
*g
, int numArgsPushed
)
358 static detail::regex_lru_cache
regex_lru_cache(boost::regex_constants::ECMAScript
);
360 using namespace boost
;
362 PyrSlot
*a
= g
->sp
- 2; // source string
363 PyrSlot
*b
= g
->sp
- 1; // pattern
364 PyrSlot
*c
= g
->sp
; // offset
366 if (!isKindOfSlot(b
, class_string
) || (NotInt(c
))) return errWrongType
;
368 int offset
= slotRawInt(c
);
369 int stringlen
= std::max(slotRawObject(a
)->size
- offset
, 0);
370 int patternsize
= slotRawObject(b
)->size
+ 1;
372 std::vector
<sc_regexp_match
> matches
;
373 const char* const stringBegin
= slotRawString(a
)->s
+ offset
;
375 regex
const & pattern
= regex_lru_cache
.get_regex(slotRawString(b
)->s
, slotRawObject(b
)->size
);
376 match_flag_type flags
= match_default
;
378 match_results
<const char*> what
;
379 const char* start
= stringBegin
;
380 const char* end
= start
+ stringlen
;
381 while (start
<= end
&& regex_search(start
, end
, what
, pattern
, flags
))
383 for (int i
= 0; i
< what
.size(); ++i
)
385 sc_regexp_match match
;
386 if (what
[i
].matched
) {
387 match
.pos
= what
[i
].first
- stringBegin
;
388 match
.len
= what
[i
].second
- what
[i
].first
;
393 matches
.push_back(match
);
395 start
= what
[0].second
;
396 if(what
[0].first
== what
[0].second
) ++start
;
398 } catch (std::exception
const & e
) {
399 postfl("Warning: Exception in _String_FindRegexp - %s\n", e
.what());
403 int match_count
= matches
.size();
405 PyrObject
*result_array
= newPyrArray(g
->gc
, match_count
, 0, true);
406 result_array
->size
= 0;
407 SetObject(a
, result_array
);
409 if( !match_count
) return errNone
;
411 for (int i
= 0; i
< match_count
; ++i
)
413 int pos
= matches
[i
].pos
;
414 int len
= matches
[i
].len
;
416 PyrObject
*array
= newPyrArray(g
->gc
, 2, 0, true);
417 SetObject(result_array
->slots
+ i
, array
);
418 result_array
->size
++;
419 g
->gc
->GCWrite(result_array
, array
);
421 PyrString
*matched_string
= newPyrStringN(g
->gc
, len
, 0, true);
422 memcpy(matched_string
->s
, stringBegin
+ pos
, len
);
425 SetInt(array
->slots
, pos
+ offset
);
426 SetObject(array
->slots
+1, matched_string
);
427 g
->gc
->GCWrite(array
, matched_string
);
433 int memcmpi(char *a
, char *b
, int len
)
435 for (int i
=0; i
<len
; ++i
) {
436 char aa
= toupper(a
[i
]);
437 char bb
= toupper(b
[i
]);
438 if (aa
< bb
) return -1;
439 if (aa
> bb
) return 1;
444 int prStringCompare(struct VMGlobals
*g
, int numArgsPushed
);
445 int prStringCompare(struct VMGlobals
*g
, int numArgsPushed
)
454 if (NotObj(b
) || !isKindOf(slotRawObject(b
), class_string
)) {
458 length
= sc_min(slotRawObject(a
)->size
, slotRawObject(b
)->size
);
459 if (IsTrue(c
)) cmp
= memcmpi(slotRawString(a
)->s
, slotRawString(b
)->s
, length
);
460 else cmp
= memcmp(slotRawString(a
)->s
, slotRawString(b
)->s
, length
);
462 if (slotRawObject(a
)->size
< slotRawObject(b
)->size
) cmp
= -1;
463 else if (slotRawObject(a
)->size
> slotRawObject(b
)->size
) cmp
= 1;
469 int prStringHash(struct VMGlobals
*g
, int numArgsPushed
);
470 int prStringHash(struct VMGlobals
*g
, int numArgsPushed
)
473 int hash
= Hash(slotRawString(a
)->s
, slotRawString(a
)->size
);
481 int prStringPathMatch(struct VMGlobals
*g
, int numArgsPushed
);
482 int prStringPathMatch(struct VMGlobals
*g
, int numArgsPushed
)
487 int err
= slotStrVal(a
, pattern
, 1023);
492 int gflags
= GLOB_MARK
| GLOB_TILDE
;
494 gflags
|= GLOB_QUOTE
;
497 int gerr
= glob(pattern
, gflags
, NULL
, &pglob
);
501 PyrObject
* array
= newPyrArray(g
->gc
, pglob
.gl_pathc
, 0, true);
503 if (gerr
) return errNone
;
505 for (unsigned int i
=0; i
<pglob
.gl_pathc
; ++i
) {
506 PyrObject
*string
= (PyrObject
*)newPyrString(g
->gc
, pglob
.gl_pathv
[i
], 0, true);
507 SetObject(array
->slots
+i
, string
);
508 g
->gc
->GCWrite(array
, string
);
516 #else //#ifndef SC_WIN32
517 int prStringPathMatch(struct VMGlobals
*g
, int numArgsPushed
);
519 int prStringPathMatch(struct VMGlobals
*g
, int numArgsPushed
)
524 int err
= slotStrVal(a
, pattern
, 1023);
527 win32_ReplaceCharInString(pattern
,1024,'/','\\');
528 // Remove trailing slash if found, to allow folders to be matched
529 if(pattern
[strlen(pattern
)-1]=='\\'){
530 pattern
[strlen(pattern
)-1] = 0;
532 // extract the containing folder, including backslash
534 win32_ExtractContainingFolder(folder
,pattern
,1024);
538 WIN32_FIND_DATA findData
;
542 hFind
= ::FindFirstFile(pattern
, &findData
);
543 if (hFind
== INVALID_HANDLE_VALUE
) {
547 if (hFind
== INVALID_HANDLE_VALUE
) {
548 // This is what happens when no matches. So we create an empty array to return.
549 PyrObject
* array
= newPyrArray(g
->gc
, 0, 0, true);
555 if(strcmp(findData
.cFileName
, "..")!=0 && strcmp(findData
.cFileName
, "..")!=0){
558 } while( ::FindNextFile(hFind
, &findData
));
563 hFind
= ::FindFirstFile(pattern
, &findData
);
564 if (hFind
== INVALID_HANDLE_VALUE
) {
568 PyrObject
* array
= newPyrArray(g
->gc
, nbPaths
, 0, true);
570 if (hFind
== INVALID_HANDLE_VALUE
) {
576 if(strcmp(findData
.cFileName
, "..")!=0 && strcmp(findData
.cFileName
, ".")!=0){
577 std::string
strPath(folder
);
578 strPath
+= std::string(findData
.cFileName
);
579 if(findData
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
){
580 strPath
+= std::string("\\"); // Append trailing slash, to match behaviour on unix (used by sclang to detect folderness)
582 const char* fullPath
= strPath
.c_str();
583 PyrObject
*string
= (PyrObject
*)newPyrString(g
->gc
, fullPath
, 0, true);
584 SetObject(array
->slots
+i
, string
);
585 g
->gc
->GCWrite(array
, string
);
589 } while( ::FindNextFile(hFind
, &findData
));
593 #endif //#ifndef SC_WIN32
595 int prString_Getenv(struct VMGlobals
* g
, int numArgsPushed
);
596 int prString_Getenv(struct VMGlobals
* g
, int /* numArgsPushed */)
598 PyrSlot
* arg
= g
->sp
;
603 err
= slotStrVal(arg
, key
, 256);
609 PyrString
* pyrString
= newPyrString(g
->gc
, value
, 0, true);
610 if (!pyrString
) return errFailed
;
611 SetObject(arg
, pyrString
);
619 int prString_Setenv(struct VMGlobals
* g
, int numArgsPushed
);
620 int prString_Setenv(struct VMGlobals
* g
, int /* numArgsPushed */)
622 PyrSlot
* args
= g
->sp
- 1;
626 err
= slotStrVal(args
+0, key
, 256);
631 SetEnvironmentVariable(key
,NULL
);
637 err
= slotStrVal(args
+1, value
, 1024);
640 SetEnvironmentVariable(key
, value
);
642 setenv(key
, value
, 1);
649 int prStripRtf(struct VMGlobals
*g
, int numArgsPushed
);
650 int prStripRtf(struct VMGlobals
*g
, int numArgsPushed
)
653 int len
= slotRawObject(a
)->size
;
654 char * chars
= (char*)malloc(len
+ 1);
655 memcpy(chars
, slotRawString(a
)->s
, len
);
659 PyrString
* string
= newPyrString(g
->gc
, chars
, 0, false);
660 SetObject(a
, string
);
666 int prStripHtml(struct VMGlobals
*g
, int numArgsPushed
);
667 int prStripHtml(struct VMGlobals
*g
, int numArgsPushed
)
670 int len
= slotRawObject(a
)->size
;
671 char * chars
= (char*)malloc(len
+ 1);
672 memcpy(chars
, slotRawString(a
)->s
, len
);
676 PyrString
* string
= newPyrString(g
->gc
, chars
, 0, false);
677 SetObject(a
, string
);
684 int prString_GetResourceDirPath(struct VMGlobals
*g
, int numArgsPushed
);
685 int prString_GetResourceDirPath(struct VMGlobals
*g
, int numArgsPushed
)
689 char * chars
= (char*)malloc(MAXPATHLEN
- 32);
690 sc_GetResourceDirectory(chars
, MAXPATHLEN
- 32);
692 PyrString
* string
= newPyrString(g
->gc
, chars
, 0, false);
693 SetObject(a
, string
);
700 int prString_Find(struct VMGlobals
*g
, int numArgsPushed
);
701 int prString_Find(struct VMGlobals
*g
, int numArgsPushed
)
703 PyrSlot
*a
= g
->sp
- 3; // source string
704 PyrSlot
*b
= g
->sp
- 2; // search string
705 PyrSlot
*c
= g
->sp
- 1; // ignoreCase
706 PyrSlot
*d
= g
->sp
; // offset
709 int err
= slotIntVal(d
, &offset
);
712 if (!isKindOfSlot(b
, class_string
)) {
717 int alength
= slotRawObject(a
)->size
- offset
;
718 int blength
= slotRawObject(b
)->size
;
722 // should also return nil if search string is longer than source
723 || (blength
> alength
))
729 int cmp
= 1; // assume contains will be false
730 char *achar
= slotRawString(a
)->s
+ offset
;
731 char *bchar
= slotRawString(b
)->s
;
732 char bchar0
= bchar
[0];
733 int scanlength
= alength
- blength
;
735 bchar0
= toupper(bchar0
);
736 for (int i
=0; i
<= scanlength
; ++i
, ++achar
) {
737 if (toupper(*achar
) == bchar0
) {
738 cmp
= memcmpi(achar
+1, bchar
+1, blength
-1);
743 for (int i
=0; i
<= scanlength
; ++i
, ++achar
) {
744 if (*achar
== bchar0
) {
745 cmp
= memcmp(achar
+1, bchar
+1, blength
-1);
751 SetInt(a
, achar
- slotRawString(a
)->s
);
758 int prString_FindBackwards(struct VMGlobals
*g
, int numArgsPushed
);
759 int prString_FindBackwards(struct VMGlobals
*g
, int numArgsPushed
)
761 PyrSlot
*a
= g
->sp
- 3; // source string
762 PyrSlot
*b
= g
->sp
- 2; // search string
763 PyrSlot
*c
= g
->sp
- 1; // ignoreCase
764 PyrSlot
*d
= g
->sp
; // offset
767 int err
= slotIntVal(d
, &offset
);
770 if (!isKindOfSlot(b
, class_string
)) {
775 int alength
= sc_min(offset
+ 1, slotRawObject(a
)->size
);
776 int blength
= slotRawObject(b
)->size
;
780 // should also return nil if search string is longer than source
781 || (blength
> alength
))
787 int cmp
= 1; // assume contains will be false
788 char *achar
= slotRawString(a
)->s
+ (alength
- blength
);
789 char *bchar
= slotRawString(b
)->s
;
790 char bchar0
= bchar
[0];
791 int scanlength
= alength
- blength
;
793 bchar0
= toupper(bchar0
);
794 for (int i
=scanlength
; i
>= 0; --i
, --achar
) {
795 if (toupper(*achar
) == bchar0
) {
796 cmp
= memcmpi(achar
+1, bchar
+1, blength
-1);
801 for (int i
=scanlength
; i
>= 0; --i
, --achar
) {
802 if (*achar
== bchar0
) {
803 cmp
= memcmp(achar
+1, bchar
+1, blength
-1);
809 SetInt(a
, achar
- slotRawString(a
)->s
);
817 # include <CoreFoundation/CoreFoundation.h>
820 int prString_StandardizePath(struct VMGlobals
* g
, int numArgsPushed
);
821 int prString_StandardizePath(struct VMGlobals
* g
, int /* numArgsPushed */)
823 PyrSlot
* arg
= g
->sp
;
824 char ipath
[PATH_MAX
];
825 char opathbuf
[PATH_MAX
];
826 char* opath
= opathbuf
;
829 err
= slotStrVal(arg
, ipath
, PATH_MAX
);
832 if (!sc_StandardizePath(ipath
, opath
)) {
837 CFStringRef cfstring
=
838 CFStringCreateWithCString(NULL
,
840 kCFStringEncodingUTF8
);
841 err
= !CFStringGetFileSystemRepresentation(cfstring
, opath
, PATH_MAX
);
843 if (err
) return errFailed
;
846 PyrString
* pyrString
= newPyrString(g
->gc
, opath
, 0, true);
847 SetObject(arg
, pyrString
);
852 int prString_RealPath(struct VMGlobals
* g
, int numArgsPushed
)
854 PyrSlot
* arg
= g
->sp
;
855 char ipath
[PATH_MAX
];
856 char opath
[PATH_MAX
];
859 err
= slotStrVal(arg
, ipath
, PATH_MAX
);
862 bool isAlias
= false;
863 if(sc_ResolveIfAlias(ipath
, opath
, isAlias
, PATH_MAX
)!=0) {
867 boost::system::error_code error_code
;
868 boost::filesystem::path p
= boost::filesystem::canonical(opath
,error_code
);
873 strcpy(opath
,p
.string().c_str());
876 CFStringRef cfstring
=
877 CFStringCreateWithCString(NULL
,
879 kCFStringEncodingUTF8
);
880 err
= !CFStringGetFileSystemRepresentation(cfstring
, opath
, PATH_MAX
);
882 if (err
) return errFailed
;
885 PyrString
* pyrString
= newPyrString(g
->gc
, opath
, 0, true);
886 SetObject(arg
, pyrString
);
891 int prString_EscapeChar(struct VMGlobals
* g
, int numArgsPushed
)
893 PyrSlot
* arg
= g
->sp
- 1;
894 PyrSlot
* charToEscapeSlot
= g
->sp
;
896 assert (isKindOfSlot(arg
, class_string
));
898 if (!IsChar(charToEscapeSlot
))
901 char charToEscape
= slotRawChar(charToEscapeSlot
);
903 PyrString
* argString
= slotRawString(arg
);
904 int length
= argString
->size
;
905 PyrString
* resultString
= newPyrStringN(g
->gc
, length
*2 + 1, 0, 1); // pressimize
907 char * original
= argString
->s
;
908 char * result
= resultString
->s
;
910 int resultLength
= length
;
911 for (int i
= 0; i
!= length
; ++i
) {
912 char current
= *original
++;
913 if (current
== charToEscape
) {
921 resultString
->size
= resultLength
;
923 SetRaw(arg
, (PyrObject
*)resultString
);
928 int prString_mkdir(struct VMGlobals
* g
, int numArgsPushed
)
930 PyrSlot
* arg
= g
->sp
;
932 char argString
[MAXPATHLEN
];
933 int error
= slotStrVal(arg
, argString
, MAXPATHLEN
);
934 if (error
!= errNone
)
937 boost::system::error_code error_code
;
938 boost::filesystem::create_directories(argString
, error_code
);
940 postfl("Warning: %s (\"%s\")\n", error_code
.message().c_str(), argString
);
946 void initStringPrimitives();
947 void initStringPrimitives()
951 base
= nextPrimitiveIndex();
953 definePrimitive(base
, index
++, "_StringCompare", prStringCompare
, 3, 0);
954 definePrimitive(base
, index
++, "_StringHash", prStringHash
, 1, 0);
955 definePrimitive(base
, index
++, "_StringPathMatch", prStringPathMatch
, 1, 0);
956 definePrimitive(base
, index
++, "_StringAsSymbol", prStringAsSymbol
, 1, 0);
957 definePrimitive(base
, index
++, "_String_AsInteger", prString_AsInteger
, 1, 0);
958 definePrimitive(base
, index
++, "_String_AsFloat", prString_AsFloat
, 1, 0);
959 definePrimitive(base
, index
++, "_String_AsCompileString", prString_AsCompileString
, 1, 0);
960 definePrimitive(base
, index
++, "_String_Getenv", prString_Getenv
, 1, 0);
961 definePrimitive(base
, index
++, "_String_Setenv", prString_Setenv
, 2, 0);
962 definePrimitive(base
, index
++, "_String_Find", prString_Find
, 4, 0);
963 definePrimitive(base
, index
++, "_String_FindBackwards", prString_FindBackwards
, 4, 0);
964 definePrimitive(base
, index
++, "_String_Format", prString_Format
, 2, 0);
965 definePrimitive(base
, index
++, "_String_Regexp", prString_Regexp
, 4, 0);
966 definePrimitive(base
, index
++, "_String_FindRegexp", prString_FindRegexp
, 3, 0);
967 definePrimitive(base
, index
++, "_StripRtf", prStripRtf
, 1, 0);
968 definePrimitive(base
, index
++, "_StripHtml", prStripHtml
, 1, 0);
969 definePrimitive(base
, index
++, "_String_GetResourceDirPath", prString_GetResourceDirPath
, 1, 0);
970 definePrimitive(base
, index
++, "_String_StandardizePath", prString_StandardizePath
, 1, 0);
971 definePrimitive(base
, index
++, "_String_RealPath", prString_RealPath
, 1, 0);
972 definePrimitive(base
, index
++, "_String_EscapeChar", prString_EscapeChar
, 2, 0);
973 definePrimitive(base
, index
++, "_String_Mkdir", prString_mkdir
, 1, 0);
979 #include "SCPlugin.h"
981 // export the function that SC will call to load the plug in.
983 extern "C" { SCPlugIn
* loadPlugIn(void); }
987 // define plug in object
988 class APlugIn
: public SCPlugIn
994 virtual void AboutToCompile();
999 // constructor for plug in
1004 // destructor for plug in
1007 void APlugIn::AboutToCompile()
1009 // this is called each time the class library is compiled.
1010 initStringPrimitives();
1013 // This function is called when the plug in is loaded into SC.
1014 // It returns an instance of APlugIn.
1015 SCPlugIn
* loadPlugIn()
1017 return new APlugIn();