OSDN Git Service

first commit
[soopy/alpha1.git] / src / String.cpp
1 /*
2  * Programming Language SOOPY
3  *   (Simple Object Oriented Programming sYstem)
4  *
5  * Copyright (C) 2002 SUZUKI Jun
6  *
7  * URL: http://sourceforge.jp/projects/soopy/
8  * License: GPL(GNU General Public License)
9  *
10  *
11  * $Id: String.cpp,v 1.65 2004/05/18 12:47:17 randy Exp $
12  */
13
14 //
15 // Soopy String Class
16 //
17
18 #include <limits.h>
19 #include "soopy.h"
20
21 /*
22 void SpString::append(const char* s)
23 {
24 //cout << "spstr.app('" << s << "')" << endl;
25     istringstream ist(s);
26     StreamReader reader(&ist);
27     while(true){
28         SpChar ch = reader.ReadChar();
29         if(ch == (SpChar)NULL){ break; }
30         str.push_back(ch);
31     }
32 }
33  */
34
35 //void SpString::appendWithEncoder(const char* s, ReadEncoder& encoder)
36 void SpString::append(const char* s, ReadEncoder& encoder)
37 {
38   //cout << "spstr.app('" << s << "')" << endl;
39   istringstream ist(s);
40   StreamReader sr(&ist);
41   Reader* old = encoder.getReader();
42   encoder.setReader(&sr);
43   while(!encoder.eof()){
44     SpChar ch = encoder.ReadChar();
45     if(ch == (SpChar)NULL){ break; }
46     str.push_back(ch);
47   }
48   encoder.setReader(old);
49 }
50
51 SpString::~SpString()
52 {
53 #ifdef TEST
54   *spout << ":destroy SpString '" << toCStringWithEncoder() << "'" << "\n";
55 #endif
56 }
57
58 const int Buf_Size = 1024 * 4;
59
60 /*
61 const char* SpString::toCString()
62 {
63     ostringstream ost;
64     StreamWriter writer(&ost);
65     SpCharVector::iterator it;
66     for(it = str.begin(); it < str.end(); it++){
67         writer.WriteChar(*it);
68     }
69
70     static string str;
71     str = ost.str();
72     return str.c_str();
73 }
74  */
75
76 const char* SpString::toCStringWithEncoder(WriteEncoder& encoder)
77 {
78   ostringstream ost;
79   StreamWriter sw(&ost);
80   Writer* old = encoder.getWriter();
81   encoder.setWriter(&sw);
82   SpCharVector::iterator it;
83   for(it = str.begin(); it < str.end(); it++){
84     encoder.WriteChar(*it);
85   }
86   encoder.setWriter(old);
87
88   static string str;
89   str = ost.str();
90   return str.c_str();
91 }
92
93 SpValue& SpString::toString()
94 {
95   SpString* str = new SpString("\"");
96   *str += toCStringWithEncoder();
97   *str += "\"";
98   //    static SpValue val;
99   //    val.setNewObject(str);
100   //    return val;
101   return SpObjectResult(str);
102 }
103
104 bool SpString::operator==(SpObject& obj)
105 {
106   //cout << "str==  " << *this << " <-> " << obj << endl;
107   if(SpString* s = dynamic_cast<SpString*>(&obj)){
108     return str == s->str;
109   }
110   return false;
111 }
112
113 bool SpString::operator<(SpObject& obj)
114 {
115   //cout << "str==  " << *this << " <-> " << obj << endl;
116   if(typeid(*this) == typeid(obj)){
117     if(SpString* s = dynamic_cast<SpString*>(&obj)){
118       return str < s->str;
119     }
120   }
121   return SpObject::operator<(obj);
122 }
123
124 SpString& SpString::operator+=(SpString& s)
125 {
126   SpCharVector::iterator it;
127   for(it = s.str.begin(); it != s.str.end(); it++){
128     str.push_back(*it);
129   }
130   return *this;
131 }
132
133 SpValue& SpString::plus(SpValue& e1, SpValue& e2)
134 {
135   SpString* s1;
136   SpString* s2;
137   SpString* s3;
138
139   if(!e2.isString()){
140     throw SpException("type mismatch in +(String, ...)");
141   }
142   s1 = dynamic_cast<SpString*>(e1.getObject());
143   s2 = dynamic_cast<SpString*>(e2.getObject());
144   s3 = new SpString(*s1);
145   *s3 += *s2;
146   //    static SpValue v;
147   //    v.setNewObject(s3);
148   //    return v;
149   return SpObjectResult(s3);
150 }
151
152 bool SpString::match(SpValue&, SpValue& val, SpNameSpace*)
153 {
154   if(val.isObject()){
155     return operator==(*(val.getObject()));
156   }
157   return false;
158 }
159
160 SpValue& SpString::eq(SpValue&, SpValue& e2)
161 {
162   if(!e2.isString()){
163     //throw SpException("type mismatch in ==(String, ...)");
164     return FalseObject;
165   }
166   SpString* s = e2.asString();
167   if(str == s->str){
168     return TrueObject;
169   }
170   return FalseObject;
171 }
172
173 SpValue& SpString::gt(SpValue&, SpValue& e2)
174 {
175   if(!e2.isString()){
176     throw SpException("type mismatch in >(String, ...)");
177   }
178   SpString* s = e2.asString();
179   if(str > s->str){
180     return TrueObject;
181   }
182   return FalseObject;
183 }
184
185 SpValue& SpString::lt(SpValue&, SpValue& e2)
186 {
187   if(!e2.isString()){
188     throw SpException("type mismatch in <(String, ...)");
189   }
190   SpString* s = e2.asString();
191   if(str < s->str){
192     return TrueObject;
193   }
194   return FalseObject;
195 }
196
197 // \83p\83X\82ð\83f\83B\83\8c\83N\83g\83\8a\82Æ\83t\83@\83C\83\8b\96¼\82É\95ª\82¯\82é\81B
198 SpTuple* SpString::split_path_file()
199 {
200   SpCharVector::iterator it   = begin();
201   SpCharVector::iterator last = end();
202
203   for(; it < end(); it++){
204 #ifdef __WIN32__
205     if((*it == JIS('\\')) ||
206        (*it == JIS('/'))){
207       last = it;
208     }
209 #else
210     if(*it == JIS('/')){
211       last = it;
212     }
213 #endif
214   }
215   SpTuple* tuple;
216   if(last == end()){
217     SpValue temp;
218     tuple = new SpTuple(NullString);
219     temp.setNewObject(this);
220     tuple->append(temp);
221   }else{
222     SpString* pstr = new SpString; // path
223     SpString* fstr = new SpString; // filename
224     for(it = begin(); it < last; it++){
225       pstr->addSpChar(*it);
226     }
227     for(it++; it < end(); it++){
228       fstr->addSpChar(*it);
229     }
230
231     SpValue temp;
232     temp.setNewObject(pstr);
233     tuple = new SpTuple(temp);
234     temp.setNewObject(fstr);
235     tuple->append(temp);
236   }
237   return tuple;
238 }
239
240 // match_glob
241 static bool string_match_glob(SpCharVector::iterator sbegin,
242                               SpCharVector::iterator send,
243                               SpCharVector::iterator gbegin,
244                               SpCharVector::iterator gend)
245 {
246   SpCharVector::iterator it  = sbegin;
247   SpCharVector::iterator git = gbegin;
248
249   for(git; git < gend; git++){
250     if(it >= send){
251       return false;
252     }
253     switch(*git){
254     case JIS('*'):
255       git++;
256       if(git >= gend){
257         return true;
258       }
259       if(*git == JIS('*')){
260         throw SpException("illegal glob '**'");
261       }
262
263     research:
264       while(*it != *git){
265         if(it >= send){
266           return false;
267         }
268         if(*git == JIS('?')){
269           break;
270         }
271         it++;
272       }
273       if(string_match_glob(it, send, git, gend)){
274         return true;
275       }else{
276         it++;
277         goto research;
278       }
279
280       break;
281     case JIS('?'):
282       it++;
283       break;
284     case JIS('\\'):
285       git++;
286       if(git == gend){
287         throw SpException("illegal end (glob)");
288       }
289       if(*git != *it){
290         return false;
291       }
292       it++;
293       break;
294     default:
295       if(*git != *it){
296         return false;
297       }
298       it++;
299     }
300   }
301
302   if(it == send){
303     return true;
304   }
305   return false;
306 }
307
308 bool SpString::match_glob(SpString* glob)
309 {
310   return string_match_glob(begin(), end(), glob->begin(), glob->end());
311 }
312
313 // split
314 SpValue& SpString::split(SpChar c)
315 {
316   if(length() == 0){
317     return NilObject;
318   }
319
320   SpCons* cons = NULL;
321   SpString s;
322   SpCharVector::iterator it = begin();;
323   while(it < end()){
324     s.clear();
325     for(; it < end(); it++){
326       if(*it == c){
327         it++;
328         break;
329       }
330       s.addSpChar(*it);
331     }
332     SpString* s2;
333     s2 = new SpString(s);
334     SpValue temp;
335     temp.setNewObject(s2);
336     if(cons == NULL){
337       cons = new SpCons(temp);
338     }else{
339       cons->append(temp);
340     }
341   }
342
343   //    static SpValue result;
344   //    result.setNewObject(cons);
345   //    return result;
346   return SpObjectResult(cons);
347 }
348
349 /*
350  * Message Handler
351  */
352
353 SpValue& SpString::onMessage(SpValue& rec, SpValue& msg)
354 {
355   return StringMsgHandler(rec, msg);
356 }
357
358 // string Primitives
359
360 SpValue& str_length(SpValue& s)
361 {
362   SpString* ptr = dynamic_cast<SpString*>(s.getObject());
363   if(ptr == NULL){
364     throw SpException("not string (length)");
365   }
366   //    static SpValue v;
367   //    v.setInt(ptr->length());
368   //    return v;
369   return SpIntResult(ptr->length());
370 }
371
372 SpValue& SpString::prim_nth(SpValue& self, SpValue& index)
373 {
374   if(!index.isInt()){
375     throw SpException("not int. (tuple.nth)");
376   }
377   SpInt i = index.getInt();
378   SpString* str = self.asString();
379   if(str->length() < i + 1){
380     throw SpException("size over (string.nth)");
381   }
382   //    static SpValue result;
383   //    result.setSpChar((*str)[i]);
384   //    return result;
385   return SpCharResult((*str)[i]);
386 }
387
388 SpValue& SpString::prim_sub(SpValue& self, SpValue& from, SpValue& len)
389 {
390   if(!from.isInt()){
391     throw SpException("not int. (string.sub)");
392   }
393   if(!len.isInt()){
394     throw SpException("not int. (string.sub)");
395   }
396   SpInt i = from.getInt();
397   SpInt j = len.getInt();
398   if(j == 0){
399     return NullString;
400   }
401   SpString* str = self.asString();
402   if(str->length() < i+1){
403     throw SpException("string is too short (string.sub)");
404   }
405   if(str->length() < i+j){
406     throw SpException("string is too short. (string.sub)");
407   }
408
409   SpCharVector vec;
410   for(int k=0; k < j; k++){
411     vec.push_back(str->str[i+k]);
412   }
413   SpString* s = new SpString(vec);
414   //    static SpValue result;
415   //    result.setNewObject(s);
416   //    return result;
417   return SpObjectResult(s);
418 }
419
420 SpValue& SpString::prim_split(SpValue& self, SpValue& ch)
421 {
422   if(!ch.isChar()){
423     throw SpException("not char(string.split)");
424   }
425   SpChar c = ch.getChar();
426   SpString* str = self.asString();
427
428   //    static SpValue result;
429   //    result = str->split(c);
430   //    return result;
431   return SpValueResult(str->split(c));
432 }
433
434 SpValue& SpString::prim_split1(SpValue& self, SpValue& ch)
435 {
436   if(!ch.isChar()){
437     throw SpException("not char(string.split1)");
438   }
439   SpChar c = ch.getChar();
440   SpString* str = self.asString();
441
442   if(str->length() == 0){
443     return NilObject;
444   }
445
446   SpCons* cons;
447   SpString s;
448   SpCharVector::iterator it = str->begin();;
449
450   for(; it < str->end(); it++){
451     if(*it == c){
452       it++;
453       break;
454     }
455     s.addSpChar(*it);
456   }
457   SpString* s2;
458   s2 = new SpString(s);
459   SpValue temp;
460   temp.setNewObject(s2);
461   cons = new SpCons(temp);
462   if(it < str->end()){
463     s.clear();
464     for(; it < str->end(); it++){
465       s.addSpChar(*it);
466     }
467     s2 = new SpString(s);
468     temp.setNewObject(s2);
469     cons->append(temp);
470   }else{
471     cons->append(NullString);
472   }
473
474   //    static SpValue result;
475   //    result.setNewObject(cons);
476   //    return result;
477   return SpObjectResult(cons);
478 }
479
480 SpValue& SpString::prim_tr(SpValue& self, SpValue& from, SpValue& to)
481 {
482   if(!from.isChar()){
483     throw SpException("not char(string.tr)");
484   }
485   if(!to.isChar()){
486     throw SpException("not char(string.tr)");
487   }
488   SpChar c1 = from.getChar();
489   SpChar c2 = to.getChar();
490   SpString* str = self.asString();
491
492   SpString* s = new SpString;
493   SpCharVector::iterator it;
494   for(it = str->begin(); it < str->end(); it++){
495     if(*it == c1){
496       s->addSpChar(c2);
497     }else{
498       s->addSpChar(*it);
499     }
500   }
501
502   //    static SpValue result;
503   //    result.setNewObject(s);
504   //    return result;
505   return SpObjectResult(s);
506 }
507
508 SpValue& SpString::prim_reader(SpValue& self)
509 {
510   SpString* str = self.asString();
511   StringReader* reader = new StringReader(str);
512
513   //    static SpValue result;
514   //    result.setNewObject(reader);
515   //    return result;
516   return SpObjectResult(reader);
517 }
518
519 SpValue& SpString::prim_upper(SpValue& self)
520 {
521   SpString* str = self.asString();
522
523   SpString* s = new SpString;
524   SpCharVector::iterator it;
525   for(it = str->begin(); it < str->end(); it++){
526     s->addSpChar(SpChar2Upper(*it));
527   }
528
529   //    static SpValue result;
530   //    result.setNewObject(s);
531   //    return result;
532   return SpObjectResult(s);
533 }
534
535 SpValue& SpString::prim_lower(SpValue& self)
536 {
537   SpString* str = self.asString();
538
539   SpString* s = new SpString;
540   SpCharVector::iterator it;
541   for(it = str->begin(); it < str->end(); it++){
542     s->addSpChar(SpChar2Lower(*it));
543   }
544
545   //    static SpValue result;
546   //    result.setNewObject(s);
547   //    return result;
548   return SpObjectResult(s);
549 }
550
551 SpValue& str2symbol(SpValue& s)
552 {
553   SpString* ptr = dynamic_cast<SpString*>(s.getObject());
554   if(ptr == NULL){
555     throw SpException("not string (string.symbol)");
556   }
557   //    static SpValue v;
558   //    v.setNewObject(new SpSymbol(*ptr));
559   //    return v;
560   return SpObjectResult(new SpSymbol(*ptr));
561 }
562
563 SpValue& SpString::prim_toInt(SpValue& self)
564 {
565   SpString* str = self.asString();
566   SpInt n = 0;
567
568   SpCharVector::iterator it = str->str.begin();
569   for(; it < str->str.end(); it++){
570     SpChar c = *it;
571     if(!isDIGIT(c)){
572       throw SpException("not digit (string.toInt)");
573     }
574     n = n * 10 + (c - JIS('0'));
575   }
576
577   //    static SpValue result;
578   //    result.setInt(n);
579   //    return result;
580   return SpIntResult(n);
581 }
582
583 SpValue& SpString::prim_replace(SpValue& self, SpValue& from, SpValue& to)
584 {
585   if(!from.isString()){
586     throw SpException("not string(string.replace)");
587   }
588   if(!to.isString()){
589     throw SpException("not string(string.replace)");
590   }
591   SpString* src = self.asString();
592   SpString* s1 = from.asString();
593   SpString* s2 = to.asString();
594
595   SpString* res = new SpString;
596   SpCharVector::iterator sit; // source iterator
597   SpCharVector::iterator fit; // from iterator
598
599   sit = src->begin();
600   fit = s1->begin();
601   while(sit < src->end()){
602     if(*sit == *fit){
603       bool all_match = true;
604       SpCharVector::iterator it1;
605       SpCharVector::iterator it2;
606       it1 = sit;
607       it2 = fit;
608       it1++;
609       it2++;
610       while(it2 < s1->end()){
611         if(*it1 != *it2){
612           all_match = false;
613           break;
614         }
615         it1++;
616         it2++;
617       }
618       if(all_match){
619         SpCharVector::iterator it3 = s2->begin();
620         for(; it3 < s2->end(); it3++){
621           res->addSpChar(*it3);
622         }
623
624         sit += s1->length();
625       }else{
626         res->addSpChar(*sit);
627         sit++;
628       }
629     }else{
630       res->addSpChar(*sit);
631       sit++;
632     }
633   }
634
635   //    static SpValue result;
636   //    result.setNewObject(res);
637   //    return result;
638   return SpObjectResult(res);
639 }
640
641 SpValue& SpString::prim_replace1(SpValue& self, SpValue& from, SpValue& to)
642 {
643   if(!from.isString()){
644     throw SpException("not string(string.replace1)");
645   }
646   if(!to.isString()){
647     throw SpException("not string(string.replace1)");
648   }
649   SpString* src = self.asString();
650   SpString* s1 = from.asString();
651   SpString* s2 = to.asString();
652
653   SpString* res = new SpString;
654   SpCharVector::iterator sit; // source iterator
655   SpCharVector::iterator fit; // from iterator
656
657   sit = src->begin();
658   fit = s1->begin();
659   while(sit < src->end()){
660     if(*sit == *fit){
661       bool all_match = true;
662       SpCharVector::iterator it1;
663       SpCharVector::iterator it2;
664       it1 = sit;
665       it2 = fit;
666       it1++;
667       it2++;
668       while(it2 < s1->end()){
669         if(*it1 != *it2){
670           all_match = false;
671           break;
672         }
673         it1++;
674         it2++;
675       }
676       if(all_match){
677         SpCharVector::iterator it3 = s2->begin();
678         for(; it3 < s2->end(); it3++){
679           res->addSpChar(*it3);
680         }
681         sit += s1->length();
682         for(; sit < src->end(); sit++){
683           res->addSpChar(*sit);
684         }
685         break;
686       }else{
687         res->addSpChar(*sit);
688         sit++;
689       }
690     }else{
691       res->addSpChar(*sit);
692       sit++;
693     }
694   }
695
696   //    static SpValue result;
697   //    result.setNewObject(res);
698   //    return result;
699   return SpObjectResult(res);
700 }
701
702 SpValue& SpString::prim_find(SpValue& self, SpValue& s, SpValue& from)
703 {
704   //    static SpValue result;
705   SpValue result;
706
707   if(!s.isString()){
708     throw SpException("not string(string.find)");
709   }
710   if(!from.isInt()){
711     throw SpException("not int(string.find)");
712   }
713   SpString* src = self.asString();
714   SpString* s1 = s.asString();
715   SpInt start = from.getInt();
716
717   SpCharVector::iterator it = src->begin();;
718   //int i = 0;
719   int i = start;
720   it += start;
721   int j;
722 cont:
723   for(; *it != s1->str[0]; it++, i++){
724     if(i >= src->length()){
725       result.setInt(-1);
726       //            return result;
727       return SpValueResult(result);
728     }
729   }
730   // found first char
731   SpCharVector::iterator it2 = it;
732   it2++;
733   for(j=1; j < s1->length(); j++, it2++)
734     {
735       if(i+j >= src->length()){
736         i = -1;
737         break;
738       }
739       if(*it2 != s1->str[j]){
740         it++;
741         i++;
742         goto cont;
743       }
744     }
745   result.setInt(i);
746   //    return result;
747   return SpValueResult(result);
748 }
749
750 //
751 // format
752 //    ex. "format string %s %d %f\n" format aString aInt aReal;
753 //
754 static SpValue PrimAdd;
755 static SpValue& _prim_add(SpValue& a, SpValue& b)
756 {
757   SpValue result, temp1, temp2;
758   temp1 = a.eval();
759   temp2 = b.eval();
760   result = temp1.plus(temp2);
761   return SpValueResult(result);
762 }
763
764 // '%s'
765 class _format_make_string : public SpFunc {
766 protected:
767   bool   flag;     // '-' flag(\8d\8bl)
768   int    width;
769   SpChar preChar;
770
771 public:
772   _format_make_string(SpChar ch, int len, bool f)
773        : preChar(ch), width(len), flag(f)
774   {
775     argLen = 1;
776   }
777   virtual SpValue& operator()(SpValue& arg);
778   SpValue& toString();
779   const char* typeString(){ return "_format_make_string"; }
780 };
781
782 SpValue& _format_make_string::toString()
783 {
784   SpString* str = new SpString("<make format string>");
785   return SpObjectResult(str);
786 }
787
788 SpValue& _format_make_string::operator()(SpValue& arg)
789 {
790   SpValue temp;
791   SpValue result;
792
793   SpString* str;
794   if(!arg.isString()){
795     temp = arg.toString();
796     str  = temp.asString();
797   }else{
798     str = arg.asString();
799   }
800   int len = str->length();
801   if((width == 0) || (width <= len)){
802     result.setObject(str);
803   }else{  // width > len
804     if(flag){ // \8d\8bl
805       SpString* str2 = new SpString();
806       *str2 += *str;
807       for(int i=0; i < width - len; i++){
808         //str2->addSpChar(preChar);
809         str2->addSpChar(MakeSpChar(CodeJIS, ' '));
810       }
811       result.setObject(str2);
812     }else{
813       SpString* str2 = new SpString();
814       for(int i=0; i < width - len; i++){
815         str2->addSpChar(preChar);
816       }
817       *str2 += *str;
818       result.setObject(str2);
819     }
820   }
821
822   return SpValueResult(result);
823 }
824
825 class _format_make_string_object : public _format_make_string {
826 public:
827   _format_make_string_object(SpChar ch, int len, bool f) : _format_make_string(ch, len, f) {}
828   SpValue& operator()(SpValue& arg){
829     SpValue temp = arg.toString();
830     return _format_make_string::operator()(temp);
831   }
832 };
833
834 // '%u'
835 class _format_make_unsigned_string : public _format_make_string {
836 public:
837   _format_make_unsigned_string(SpChar ch, int len, bool f) : _format_make_string(ch, len, f) {}
838   SpValue& operator()(SpValue& arg);
839 };
840
841 SpValue& _format_make_unsigned_string::operator()(SpValue& arg)
842 {
843   if(!arg.isInt()){
844     throw SpException("not int in string.format '%u'");
845   }
846   SpInt n = arg.getInt();
847   char buf[64];
848   sprintf(buf, "%u", n);
849   SpValue temp;
850   temp.setNewObject(new SpString(buf));
851   return _format_make_string::operator()(temp);
852 }
853
854 // '%c'
855 class _format_make_char_string : public _format_make_string {
856 public:
857   _format_make_char_string(SpChar ch, int w, bool f)
858        : _format_make_string(ch, w, f) {}
859   SpValue& operator()(SpValue& arg);
860   SpValue& toString()
861   {
862     SpString* str = new SpString("<make format string:char>");
863     return SpObjectResult(str);
864   }
865   const char* typeString(){ return "_format_make_char_string"; }
866 };
867
868 SpValue& _format_make_char_string::operator()(SpValue& arg)
869 {
870   SpValue temp;
871   SpInt n;
872   SpString* str;
873
874   str = new SpString();
875   temp.setNewObject(str);
876   n = arg.getInt();
877   str->addSpChar((SpChar)n);
878
879   return _format_make_string::operator()(temp);
880 }
881
882 // '%f'
883 class _format_make_real_string : public SpFunc {
884   char format[64];
885
886 public:
887   _format_make_real_string(char* str)
888   {
889     argLen = 1;
890     strncpy(format, str, 63);
891   }
892   SpValue& operator()(SpValue& arg);
893   SpValue& toString()
894   {
895     SpString* str = new SpString("<make format string:real>");
896     return SpObjectResult(str);
897   }
898   const char* typeString(){ return "_format_make_real_string"; }
899 };
900
901 SpValue& _format_make_real_string::operator()(SpValue& arg)
902 {
903   SpValue result;
904   SpReal real;
905   char buf[128];
906
907   if(arg.isInt()){
908     arg.setReal((SpReal)arg.getInt());
909   }
910   if(!arg.isReal()){
911     throw SpException("arg is not real in format string");
912   }
913   real = arg.getReal();
914   sprintf(buf, format, real);
915   result.setNewObject(new SpString(buf));
916
917   return SpValueResult(result);
918 }
919
920 // '%b'
921 class _format_make_b_string : public SpFunc {
922 private:
923   int width;
924   bool fSharp;
925   bool fMinus;
926   bool fZero;
927
928 public:
929   _format_make_b_string(int w, bool s, bool m, bool z)
930        : width(w), fSharp(s), fMinus(m), fZero(z)
931   {
932     argLen = 1;
933   }
934   SpValue& operator()(SpValue& arg);
935   SpValue& toString()
936   {
937     SpString* str = new SpString("<make format string:b>");
938     return SpObjectResult(str);
939   }
940   const char* typeString(){ return "_format_make_b_string"; }
941 };
942
943 #ifndef INT_BIT
944 #define INT_BIT (CHAR_BIT * (sizeof(int) / sizeof(char)))
945 #endif
946
947 SpValue& _format_make_b_string::operator()(SpValue& arg)
948 {
949   SpValue result;
950   SpValue temp;
951   SpInt n;
952   SpString* str = NULL;
953
954   if(!arg.isInt()){
955     throw SpException("not int '%b'");
956   }
957   n = arg.getInt();
958
959   for(int i = INT_BIT-1; i >= 0; i--){
960     if(((n >> i) & 1) == 1){
961       if(str == NULL){
962         str = new SpString("1");
963         result.setObject(str);
964       }else{
965         str->addSpChar(MakeSpChar(CodeJIS, '1'));
966       }
967     }else{
968       if(str != NULL){
969         str->addSpChar(MakeSpChar(CodeJIS, '0'));
970       }
971     }
972   }
973   if(str == NULL){
974     str = new SpString();
975     result.setObject(str);
976   }
977
978   int len = str->length();
979   if(fSharp){ // '#' flag
980     if((width - 2) > len){
981       SpString* str2;
982       if(fMinus){ // \8d\8bl
983         str2 = new SpString("0b");
984         *str2 += *str;
985         for(int i=0; i < (width - 2) - len; i++){
986           str2->addSpChar(MakeSpChar(CodeJIS, ' '));
987         }
988       }else{
989         if(fZero){
990           str2 = new SpString("0b");
991           for(int i=0; i < (width - 2) - len; i++){
992             str2->addSpChar(MakeSpChar(CodeJIS, '0'));
993           }
994         }else{
995           str2 = new SpString();
996           for(int i=0; i < (width - 2) - len; i++){
997             str2->addSpChar(MakeSpChar(CodeJIS, ' '));
998           }
999           str2->addSpChar(MakeSpChar(CodeJIS, '0'));
1000           str2->addSpChar(MakeSpChar(CodeJIS, 'b'));
1001         }
1002         *str2 += *str;
1003       }
1004       result.setObject(str2);
1005     }else{
1006       SpString* str2 = new SpString("0b");
1007       SpValue temp;
1008       temp.setObject(str2);
1009       *str2 += *str;
1010       result.setObject(str2);
1011     }
1012   }else{
1013     if(width > len){
1014       SpString* str2 = new SpString();
1015       if(fMinus){ // \8d\8bl
1016         *str2 += *str;
1017         for(int i=0; i < width - len; i++){
1018           str2->addSpChar(MakeSpChar(CodeJIS, ' '));
1019         }
1020       }else{
1021         SpChar preChar;
1022         if(fZero){
1023           preChar = MakeSpChar(CodeJIS, '0');
1024         }else{
1025           preChar = MakeSpChar(CodeJIS, ' ');
1026         }
1027         for(int i=0; i < width - len; i++){
1028           str2->addSpChar(preChar);
1029         }
1030         *str2 += *str;
1031       }
1032       result.setObject(str2);
1033     }
1034   }
1035
1036   return SpValueResult(result);
1037 }
1038
1039 // '%o'
1040 class _format_make_o_string : public SpFunc {
1041 private:
1042   int width;
1043   bool fSharp;
1044   bool fMinus;
1045   bool fZero;
1046
1047 public:
1048   _format_make_o_string(int w, bool s, bool m, bool z)
1049        : width(w), fSharp(s), fMinus(m), fZero(z)
1050   {
1051     argLen = 1;
1052   }
1053   SpValue& operator()(SpValue& arg);
1054   SpValue& toString()
1055   {
1056     SpString* str = new SpString("<make format string:o>");
1057     return SpObjectResult(str);
1058   }
1059   const char* typeString(){ return "_format_make_o_string"; }
1060 };
1061
1062 SpValue& _format_make_o_string::operator()(SpValue& arg)
1063 {
1064   SpValue result;
1065   SpValue temp;
1066   SpUInt n;
1067   SpString* str;
1068
1069   if(!arg.isInt()){
1070     throw SpException("not int '%o'");
1071   }
1072   n = (SpUInt)arg.getInt();
1073
1074   str = new SpString();
1075   result.setNewObject(str);
1076   for(SpUInt i = n; i > 0; i >>= 3){
1077     int j = i & 0x7;
1078     str->insertSpChar(MakeSpChar(CodeJIS, j + '0'));
1079   }
1080   if(str->length() == 0){
1081     str->addSpChar(MakeSpChar(CodeJIS, '0'));
1082   }
1083
1084   int len = str->length();
1085   if(fSharp){ // '#' flag
1086     if((width - 2) > len){
1087       SpString* str2;
1088       if(fMinus){ // \8d\8bl
1089         str2 = new SpString("00");
1090         *str2 += *str;
1091         for(int i=0; i < (width - 2) - len; i++){
1092           str2->addSpChar(MakeSpChar(CodeJIS, ' '));
1093         }
1094       }else{
1095         if(fZero){
1096           str2 = new SpString("00");
1097           for(int i=0; i < (width - 2) - len; i++){
1098             str2->addSpChar(MakeSpChar(CodeJIS, '0'));
1099           }
1100         }else{
1101           str2 = new SpString();
1102           for(int i=0; i < (width - 2) - len; i++){
1103             str2->addSpChar(MakeSpChar(CodeJIS, ' '));
1104           }
1105           str2->addSpChar(MakeSpChar(CodeJIS, '0'));
1106           str2->addSpChar(MakeSpChar(CodeJIS, '0'));
1107         }
1108         *str2 += *str;
1109       }
1110       result.setObject(str2);
1111     }else{
1112       SpString* str2 = new SpString("00");
1113       SpValue temp;
1114       temp.setObject(str2);
1115       *str2 += *str;
1116       result.setObject(str2);
1117     }
1118   }else{
1119     if(width > len){
1120       SpString* str2 = new SpString();
1121       if(fMinus){ // \8d\8bl
1122         *str2 += *str;
1123         for(int i=0; i < width - len; i++){
1124           str2->addSpChar(MakeSpChar(CodeJIS, ' '));
1125         }
1126       }else{
1127         SpChar preChar;
1128         if(fZero){
1129           preChar = MakeSpChar(CodeJIS, '0');
1130         }else{
1131           preChar = MakeSpChar(CodeJIS, ' ');
1132         }
1133         for(int i=0; i < width - len; i++){
1134           str2->addSpChar(preChar);
1135         }
1136         *str2 += *str;
1137       }
1138       result.setObject(str2);
1139     }
1140   }
1141
1142   return SpValueResult(result);
1143 }
1144
1145 // '%x' '%X'
1146 class _format_make_hex_string : public SpFunc {
1147 private:
1148   int width;
1149   bool upper;
1150   bool fSharp;
1151   bool fMinus;
1152   bool fZero;
1153
1154 public:
1155   _format_make_hex_string(int w, bool up, bool s, bool m, bool z)
1156        : width(w), upper(up), fSharp(s), fMinus(m), fZero(z)
1157   {
1158     argLen = 1;
1159   }
1160   SpValue& operator()(SpValue& arg);
1161   SpValue& toString()
1162   {
1163     SpString* str = new SpString("<make format string:x(X)>");
1164     return SpObjectResult(str);
1165   }
1166   const char* typeString(){ return "_format_make_hex_string"; }
1167 };
1168
1169 SpValue& _format_make_hex_string::operator()(SpValue& arg)
1170 {
1171   SpValue result;
1172   SpValue temp;
1173   SpUInt n;
1174   SpString* str;
1175
1176   if(!arg.isInt()){
1177     throw SpException("not int '%x' or '%X'");
1178   }
1179   n = (SpUInt)arg.getInt();
1180
1181   str = new SpString();
1182   result.setNewObject(str);
1183   for(SpUInt i = n; i > 0; i >>= 4){
1184     int j = i & 0xF;
1185     if(j <= 9){
1186       str->insertSpChar(MakeSpChar(CodeJIS, j + '0'));
1187     }else{
1188       if(upper){
1189         str->insertSpChar(MakeSpChar(CodeJIS, j - 10 + 'A'));
1190       }else{
1191         str->insertSpChar(MakeSpChar(CodeJIS, j - 10 + 'a'));
1192       }
1193     }
1194   }
1195   if(str->length() == 0){
1196     str->addSpChar(MakeSpChar(CodeJIS, '0'));
1197   }
1198
1199   int len = str->length();
1200   if(fSharp){ // '#' flag
1201     if((width - 2) > len){
1202       SpString* str2;
1203       if(fMinus){ // \8d\8bl
1204         if(upper){
1205           str2 = new SpString("0X");
1206         }else{
1207           str2 = new SpString("0x");
1208         }
1209         *str2 += *str;
1210         for(int i=0; i < (width - 2) - len; i++){
1211           str2->addSpChar(MakeSpChar(CodeJIS, ' '));
1212         }
1213       }else{
1214         if(fZero){
1215           if(upper){
1216             str2 = new SpString("0X");
1217           }else{
1218             str2 = new SpString("0x");
1219           }
1220           for(int i=0; i < (width - 2) - len; i++){
1221             str2->addSpChar(MakeSpChar(CodeJIS, '0'));
1222           }
1223         }else{
1224           str2 = new SpString();
1225           for(int i=0; i < (width - 2) - len; i++){
1226             str2->addSpChar(MakeSpChar(CodeJIS, ' '));
1227           }
1228           str2->addSpChar(MakeSpChar(CodeJIS, '0'));
1229           if(upper){
1230             str2->addSpChar(MakeSpChar(CodeJIS, 'X'));
1231           }else{
1232             str2->addSpChar(MakeSpChar(CodeJIS, 'x'));
1233           }
1234         }
1235         *str2 += *str;
1236       }
1237       result.setObject(str2);
1238     }else{
1239       SpString* str2;
1240       if(upper){
1241         str2 = new SpString("0X");
1242       }else{
1243         str2 = new SpString("0x");
1244       }
1245       SpValue temp;
1246       temp.setObject(str2);
1247       *str2 += *str;
1248       result.setObject(str2);
1249     }
1250   }else{
1251     if(width > len){
1252       SpString* str2 = new SpString();
1253       if(fMinus){ // \8d\8bl
1254         *str2 += *str;
1255         for(int i=0; i < width - len; i++){
1256           str2->addSpChar(MakeSpChar(CodeJIS, ' '));
1257         }
1258       }else{
1259         SpChar preChar;
1260         if(fZero){
1261           preChar = MakeSpChar(CodeJIS, '0');
1262         }else{
1263           preChar = MakeSpChar(CodeJIS, ' ');
1264         }
1265         for(int i=0; i < width - len; i++){
1266           str2->addSpChar(preChar);
1267         }
1268         *str2 += *str;
1269       }
1270       result.setObject(str2);
1271     }
1272   }
1273
1274   return SpValueResult(result);
1275 }
1276
1277 // prim_format
1278 SpValue& SpString::prim_format(SpValue& self)
1279 {
1280   SpCharVector vec;
1281   SpChar preChar;
1282   bool flagSharp = false;
1283   bool flagPlus  = false;
1284   bool flagSpace = false;
1285   bool flagMinus = false;
1286   bool flagZero  = false;
1287   bool upper_hex = true;
1288   int  width  = -1;  // -1 \82Ì\82Æ\82«\82É\82Í\95\9d\82Ì\8ew\92è\82Í\96³\82µ
1289   int  width2 = -1;  // -1 \82Ì\82Æ\82«\82É\82Í\95\9d\82Ì\8ew\92è\82Í\96³\82µ\81A\82½\82¾\82µ\90¸\93x\82Ì\8fÈ\97ª\92l\82Í\82U
1290   SpValueVector args;
1291   SpCons* body = NULL;
1292   SpCons* exps = NULL;
1293   SpFunc* func = NULL;
1294   SpValue vArgs;
1295   SpValue vBody;
1296   SpValue temp;
1297   SpValue temp2;
1298   SpValue temp3;
1299   SpSymbol* sym;
1300   int count = 0;
1301   char buf[64];
1302   char format[64];
1303
1304   SpString* ptr = dynamic_cast<SpString*>(self.getObject());
1305   if(ptr == NULL){
1306     throw SpException("not string (format)");
1307   }
1308   // parse format string
1309   SpCharVector::iterator it;
1310   it = ptr->str.begin();
1311   for(; it != ptr->str.end(); it++){
1312     flagSharp = false;
1313     flagPlus  = false;
1314     flagSpace = false;
1315     flagMinus = false;
1316     flagZero  = false;
1317     upper_hex = true;
1318     width  = -1;
1319     width2 = -1;
1320
1321     if(*it == MakeSpChar(CodeJIS, '%')){    // parse '%'
1322       it++;
1323       if(it == ptr->str.end()){
1324         throw SpException("illegal format string");
1325       }
1326       if(*it == MakeSpChar(CodeJIS, '%')){    // parse "%%"
1327         vec.push_back(*it);
1328         continue;
1329       }
1330
1331       // init preChar & width
1332       preChar = MakeSpChar(CodeJIS, ' ');
1333       width = 0;
1334       temp.setNewObject(new SpString(vec));
1335       vec.clear();
1336       if(exps == NULL){
1337         exps = new SpCons(temp);
1338       }else{
1339         exps->append(temp);
1340       }
1341
1342       // parse flag ('#', '+', ' ', '-', '0')
1343 parse_flags:
1344       switch(*it){
1345       case MakeSpChar(CodeJIS, '#'):
1346         flagSharp = true;
1347         it++;
1348         if(it == ptr->str.end()){
1349           throw SpException("illegal format string");
1350         }
1351         goto parse_flags;
1352         break;
1353       case MakeSpChar(CodeJIS, '+'):
1354         flagPlus = true;
1355         it++;
1356         if(it == ptr->str.end()){
1357           throw SpException("illegal format string");
1358         }
1359         goto parse_flags;
1360         break;
1361       case MakeSpChar(CodeJIS, ' '):
1362         flagSpace = true;
1363         it++;
1364         if(it == ptr->str.end()){
1365           throw SpException("illegal format string");
1366         }
1367         goto parse_flags;
1368         break;
1369       case MakeSpChar(CodeJIS, '-'):
1370         flagMinus = true;
1371         it++;
1372         if(it == ptr->str.end()){
1373           throw SpException("illegal format string");
1374         }
1375         goto parse_flags;
1376         break;
1377       case MakeSpChar(CodeJIS, '0'):
1378         flagZero = true;
1379         preChar  = *it;
1380         it++;
1381         if(it == ptr->str.end()){
1382           throw SpException("illegal format string");
1383         }
1384         break;
1385       }
1386
1387       // parse width
1388       if(isDIGIT(*it)){
1389         width = toINT(*it);
1390         for(it++; it != ptr->str.end() && isDIGIT(*it); it++){
1391           width = width * 10 + toINT(*it);
1392         }
1393       }
1394
1395       // parser width2 '.num'
1396       if(*it == MakeSpChar(CodeJIS, '.')){
1397         it++;
1398         width2 = 0;
1399         for(; it != ptr->str.end() && isDIGIT(*it); it++){
1400           width2 = width2 * 10 + toINT(*it);
1401         }
1402       }
1403
1404       switch(*it){
1405       case MakeSpChar(CodeJIS, 'c'): // char
1406 #ifdef _MICROSOFTC_
1407         _snprintf(buf, 60, "a%d", count++);
1408 #else
1409         snprintf(buf, 60, "a%d", count++);
1410 #endif
1411         sym = new SpSymbol(buf);
1412         temp2.setNewObject(sym);
1413         temp.setNewObject(new _format_make_char_string(preChar, width, flagMinus));
1414         temp.setNewObject(new SpSendMsg(temp, temp2));
1415         exps->append(temp);
1416         temp3.setNewObject(new SpArg(temp2, NilObject));
1417         args.push_back(temp3);
1418         break;
1419       case MakeSpChar(CodeJIS, 's'): // string
1420       case MakeSpChar(CodeJIS, 'p'):
1421 #ifdef _MICROSOFTC_
1422         _snprintf(buf, 60, "a%d", count++);
1423 #else
1424         snprintf(buf, 60, "a%d", count++);
1425 #endif
1426         sym = new SpSymbol(buf);
1427         temp2.setNewObject(sym);
1428         temp.setNewObject(new _format_make_string(preChar, width, flagMinus));
1429         temp.setNewObject(new SpSendMsg(temp, temp2));
1430         exps->append(temp);
1431         temp3.setNewObject(new SpArg(temp2, NilObject));
1432         args.push_back(temp3);
1433         break;
1434       case MakeSpChar(CodeJIS, 'd'): // digit
1435       case MakeSpChar(CodeJIS, 'i'):
1436 #ifdef _MICROSOFTC_
1437         _snprintf(buf, 60, "a%d", count++);
1438 #else
1439         snprintf(buf, 60, "a%d", count++);
1440 #endif
1441         sym = new SpSymbol(buf);
1442         temp2.setNewObject(sym);
1443         temp.setNewObject(new _format_make_string_object(preChar, width, flagMinus));
1444         temp.setNewObject(new SpSendMsg(temp, temp2));
1445         exps->append(temp);
1446         temp3.setNewObject(new SpArg(temp2, NilObject));
1447         args.push_back(temp3);
1448         break;
1449       case MakeSpChar(CodeJIS, 'u'): // unsigned int
1450 #ifdef _MICROSOFTC_
1451         _snprintf(buf, 60, "a%d", count++);
1452 #else
1453         snprintf(buf, 60, "a%d", count++);
1454 #endif
1455         sym = new SpSymbol(buf);
1456         temp2.setNewObject(sym);
1457         temp.setNewObject(new _format_make_unsigned_string(preChar, width, flagMinus));
1458         temp.setNewObject(new SpSendMsg(temp, temp2));
1459         exps->append(temp);
1460         temp3.setNewObject(new SpArg(temp2, NilObject));
1461         args.push_back(temp3);
1462         break;
1463       case MakeSpChar(CodeJIS, 'b'): // bin
1464 #ifdef _MICROSOFTC_
1465         _snprintf(buf, 60, "a%d", count++);
1466 #else
1467         snprintf(buf, 60, "a%d", count++);
1468 #endif
1469         sym = new SpSymbol(buf);
1470         temp2.setNewObject(sym);
1471         temp.setNewObject(new _format_make_b_string(width, flagSharp, flagMinus, flagZero));
1472         temp.setNewObject(new SpSendMsg(temp, temp2));
1473         exps->append(temp);
1474         temp3.setNewObject(new SpArg(temp2, NilObject));
1475         args.push_back(temp3);
1476         break;
1477       case MakeSpChar(CodeJIS, 'o'): // oct
1478 #ifdef _MICROSOFTC_
1479         _snprintf(buf, 60, "a%d", count++);
1480 #else
1481         snprintf(buf, 60, "a%d", count++);
1482 #endif
1483         sym = new SpSymbol(buf);
1484         temp2.setNewObject(sym);
1485         temp.setNewObject(new _format_make_o_string(width, flagSharp, flagMinus, flagZero));
1486         temp.setNewObject(new SpSendMsg(temp, temp2));
1487         exps->append(temp);
1488         temp3.setNewObject(new SpArg(temp2, NilObject));
1489         args.push_back(temp3);
1490         break;
1491       case MakeSpChar(CodeJIS, 'x'): // hex
1492         upper_hex = false;
1493       case MakeSpChar(CodeJIS, 'X'): // HEX
1494 #ifdef _MICROSOFTC_
1495         _snprintf(buf, 60, "a%d", count++);
1496 #else
1497         snprintf(buf, 60, "a%d", count++);
1498 #endif
1499         sym = new SpSymbol(buf);
1500         temp2.setNewObject(sym);
1501         temp.setNewObject(new _format_make_hex_string(width, upper_hex, flagSharp, flagMinus, flagZero));
1502         temp.setNewObject(new SpSendMsg(temp, temp2));
1503         exps->append(temp);
1504         temp3.setNewObject(new SpArg(temp2, NilObject));
1505         args.push_back(temp3);
1506         break;
1507       case MakeSpChar(CodeJIS, 'f'):
1508       case MakeSpChar(CodeJIS, 'e'):
1509       case MakeSpChar(CodeJIS, 'E'):
1510       case MakeSpChar(CodeJIS, 'g'):
1511       case MakeSpChar(CodeJIS, 'G'):
1512 #ifdef _MICROSOFTC_
1513         _snprintf(buf, 60, "a%d", count++);
1514 #else
1515         snprintf(buf, 60, "a%d", count++);
1516 #endif
1517         sym = new SpSymbol(buf);
1518         temp2.setNewObject(sym);
1519         if(width2 == -1){
1520           width2 = 6;
1521         }
1522         if(width < 0){
1523           if(flagSharp){
1524             sprintf(format, "%%#.%d%c", width2, SpCharGetChar(*it));
1525           }else if(flagPlus){
1526             sprintf(format, "%%+.%d%c", width2, SpCharGetChar(*it));
1527           }else if(flagSpace){
1528             sprintf(format, "%% .%d%c", width2, SpCharGetChar(*it));
1529           }else if(flagMinus){
1530             sprintf(format, "%%-.%d%c", width2, SpCharGetChar(*it));
1531           }else if(flagZero){
1532             sprintf(format, "%%0.%d%c", width2, SpCharGetChar(*it));
1533           }else{
1534             sprintf(format, "%%.%d%c", width2, SpCharGetChar(*it));
1535           }
1536         }else{
1537           if(flagSharp){
1538             sprintf(format, "%%#%d.%d%c", width, width2, SpCharGetChar(*it));
1539           }else if(flagPlus){
1540             sprintf(format, "%%+%d.%d%c", width, width2, SpCharGetChar(*it));
1541           }else if(flagSpace){
1542             sprintf(format, "%% %d.%d%c", width, width2, SpCharGetChar(*it));
1543           }else if(flagMinus){
1544             sprintf(format, "%%-%d.%d%c", width, width2, SpCharGetChar(*it));
1545           }else if(flagZero){
1546             sprintf(format, "%%0%d.%d%c", width, width2, SpCharGetChar(*it));
1547           }else{
1548             sprintf(format, "%%%d.%d%c", width, width2, SpCharGetChar(*it));
1549           }
1550         }
1551         temp.setNewObject(new _format_make_real_string(format));
1552         temp.setNewObject(new SpSendMsg(temp, temp2));
1553         exps->append(temp);
1554         temp3.setNewObject(new SpArg(temp2, NilObject));
1555         args.push_back(temp3);
1556         break;
1557       default:
1558         throw SpException("illegal format string");
1559       }
1560
1561     }else{
1562       vec.push_back(*it);
1563     }
1564   }
1565   if(vec.size() > 0){
1566     if(exps == NULL){
1567       temp.setNewObject(new SpString(vec));
1568       body = new SpCons(temp);
1569     }else{
1570       SpValue recv, msg;
1571       SpSendMsg* sm;
1572       temp.setNewObject(new SpString(vec));
1573       exps->append(temp);
1574       recv.setObject(exps);
1575       sm = new SpSendMsg(recv, SymFoldl);
1576       recv.setObject(sm);
1577       sm = new SpSendMsg(recv, PrimAdd);
1578       temp.setNewObject(sm);
1579       body = new SpCons(temp);
1580     }
1581   }else{
1582     if(exps != NULL){
1583       SpValue recv, msg;
1584       SpSendMsg* sm;
1585       recv.setObject(exps);
1586       sm = new SpSendMsg(recv, SymFoldl);
1587       recv.setObject(sm);
1588       sm = new SpSendMsg(recv, PrimAdd);
1589       temp.setNewObject(sm);
1590       body = new SpCons(temp);
1591     }
1592   }
1593
1594   // make function
1595   if(args.size() != 0){
1596     vArgs.setNewObject(new SpTuple(args));
1597   }
1598   if(body != NULL){
1599     vBody.setObject(body);
1600   }
1601
1602   func = new SpUsrFunc(NilObject, vArgs, NilObject, NilObject, vBody, NilObject, NilObject);
1603
1604   return SpObjectResult(func);
1605 }
1606
1607 // init Message Handler
1608 void SpString::init()
1609 {
1610   StringMsgHandler.append(SymIsString, PrimTrue);
1611
1612   PrimAdd.setNewObject(new SpPrim2(_prim_add));
1613
1614   SpValue PrimLength(new SpPrim1(str_length));
1615   StringMsgHandler.append(SymLength, PrimLength);
1616
1617   SpValue PrimNth(new SpPrim2(prim_nth));
1618   StringMsgHandler.append(SymNth, PrimNth);
1619
1620   SpValue SymSub(new SpSymbol("sub"));
1621   SpValue PrimSub(new SpPrim3(prim_sub));
1622   StringMsgHandler.append(SymSub, PrimSub);
1623
1624   SpValue SymSymbol(new SpSymbol("symbol"));
1625   SpValue PrimSymbol(new SpPrim1(str2symbol));
1626   StringMsgHandler.append(SymSymbol, PrimSymbol);
1627
1628   SpValue PrimSplit(new SpPrim2(prim_split));
1629   StringMsgHandler.append(SymSplit, PrimSplit);
1630
1631   SpValue SymTr(new SpSymbol("tr"));
1632   SpValue PrimTr(new SpPrim3(prim_tr));
1633   StringMsgHandler.append(SymTr, PrimTr);
1634
1635   SpValue PrimReader(new SpPrim1(prim_reader));
1636   StringMsgHandler.append(SymReader, PrimReader);
1637
1638   SpValue PrimUpper(new SpPrim1(prim_upper));
1639   StringMsgHandler.append(SymUpper, PrimUpper);
1640
1641   SpValue PrimLower(new SpPrim1(prim_lower));
1642   StringMsgHandler.append(SymLower, PrimLower);
1643
1644   SpValue PrimReplace(new SpPrim3(prim_replace));
1645   StringMsgHandler.append(SymReplace, PrimReplace);
1646
1647   SpValue PrimToInt(new SpPrim1(prim_toInt));
1648   StringMsgHandler.append(SymToInt, PrimToInt);
1649
1650   SpValue PrimFind(new SpPrim3(prim_find));
1651   StringMsgHandler.append(SymFind, PrimFind);
1652
1653   SpValue PrimSplit1(new SpPrim2(prim_split1));
1654   StringMsgHandler.append(SymSplit1, PrimSplit1);
1655
1656   SpValue PrimReplace1(new SpPrim3(prim_replace1));
1657   StringMsgHandler.append(SymReplace1, PrimReplace1);
1658
1659   SpValue SymFormat(new SpSymbol("format"));
1660   SpValue PrimFormat(new SpPrim1(prim_format));
1661   StringMsgHandler.append(SymFormat, PrimFormat);
1662 }
1663