Back to home page

Enduro/X

 
 

    


0001 /* see copyright notice in pscript.h */
0002 #include <pscript.h>
0003 #include <psstdstring.h>
0004 #include <string.h>
0005 #include <stdlib.h>
0006 #include <stdio.h>
0007 #include <ctype.h>
0008 #include <assert.h>
0009 #include <nstdutil.h>
0010 #include <ndebug.h>
0011 
0012 #define MAX_FORMAT_LEN  20
0013 #define MAX_WFORMAT_LEN 3
0014 #define ADDITIONAL_FORMAT_SPACE (100*sizeof(PSChar))
0015 
0016 static PSBool isfmtchr(PSChar ch)
0017 {
0018     switch(ch) {
0019     case '-': case '+': case ' ': case '#': case '0': return PSTrue;
0020     }
0021     return PSFalse;
0022 }
0023 
0024 static PSInteger validate_format(HPSCRIPTVM v, PSChar *fmt, const PSChar *src, PSInteger n,PSInteger &width)
0025 {
0026     PSChar *dummy;
0027     PSChar swidth[MAX_WFORMAT_LEN];
0028     PSInteger wc = 0;
0029     PSInteger start = n;
0030     fmt[0] = '%';
0031     while (isfmtchr(src[n])) n++;
0032     while (scisdigit(src[n])) {
0033         swidth[wc] = src[n];
0034         n++;
0035         wc++;
0036         if(wc>=MAX_WFORMAT_LEN)
0037             return ps_throwerror(v,_SC("width format too long"));
0038     }
0039     swidth[wc] = '\0';
0040     if(wc > 0) {
0041         width = scstrtol(swidth,&dummy,10);
0042     }
0043     else
0044         width = 0;
0045     if (src[n] == '.') {
0046         n++;
0047 
0048         wc = 0;
0049         while (scisdigit(src[n])) {
0050             swidth[wc] = src[n];
0051             n++;
0052             wc++;
0053             if(wc>=MAX_WFORMAT_LEN)
0054                 return ps_throwerror(v,_SC("precision format too long"));
0055         }
0056         swidth[wc] = '\0';
0057         if(wc > 0) {
0058             width += scstrtol(swidth,&dummy,10);
0059 
0060         }
0061     }
0062     if (n-start > MAX_FORMAT_LEN )
0063         return ps_throwerror(v,_SC("format too long"));
0064     memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(PSChar));
0065     fmt[(n-start)+2] = '\0';
0066     return n;
0067 }
0068 
0069 PSRESULT psstd_format(HPSCRIPTVM v,PSInteger nformatstringidx,PSInteger *outlen,PSChar **output)
0070 {
0071     const PSChar *format;
0072     PSChar *dest;
0073     PSChar fmt[MAX_FORMAT_LEN];
0074     ps_getstring(v,nformatstringidx,&format);
0075     PSInteger format_size = ps_getsize(v,nformatstringidx);
0076     PSInteger allocated = (format_size+2)*sizeof(PSChar);
0077     dest = ps_getscratchpad(v,allocated);
0078     PSInteger n = 0,i = 0, nparam = nformatstringidx+1, w = 0;
0079     //while(format[n] != '\0')
0080     while(n < format_size)
0081     {
0082         if(format[n] != '%') {
0083             assert(i < allocated);
0084             dest[i++] = format[n];
0085             n++;
0086         }
0087         else if(format[n+1] == '%') { //handles %%
0088                 dest[i++] = '%';
0089                 n += 2;
0090         }
0091         else {
0092             n++;
0093             if( nparam > ps_gettop(v) )
0094                 return ps_throwerror(v,_SC("not enough paramters for the given format string"));
0095             n = validate_format(v,fmt,format,n,w);
0096             if(n < 0) return -1;
0097             PSInteger addlen = 0;
0098             PSInteger valtype = 0;
0099             const PSChar *ts = NULL;
0100             PSInteger ti = 0;
0101             PSFloat tf = 0;
0102             switch(format[n]) {
0103             case 's':
0104                 if(PS_FAILED(ps_getstring(v,nparam,&ts)))
0105                     return ps_throwerror(v,_SC("string expected for the specified format"));
0106                 addlen = (ps_getsize(v,nparam)*sizeof(PSChar))+((w+1)*sizeof(PSChar));
0107                 valtype = 's';
0108                 break;
0109             case 'i': case 'd': case 'o': case 'u':  case 'x':  case 'X':
0110 #ifdef _PS64
0111                 {
0112                 size_t flen = scstrlen(fmt);
0113                 PSInteger fpos = flen - 1;
0114                 PSChar f = fmt[fpos];
0115                 const PSChar *prec = (const PSChar *)_PRINT_INT_PREC;
0116                 while(*prec != _SC('\0')) {
0117                     fmt[fpos++] = *prec++;
0118                 }
0119                 fmt[fpos++] = f;
0120                 fmt[fpos++] = _SC('\0');
0121                 }
0122 #endif
0123             case 'c':
0124                 if(PS_FAILED(ps_getinteger(v,nparam,&ti)))
0125                     return ps_throwerror(v,_SC("integer expected for the specified format"));
0126                 addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(PSChar));
0127                 valtype = 'i';
0128                 break;
0129             case 'f': case 'g': case 'G': case 'e':  case 'E':
0130                 if(PS_FAILED(ps_getfloat(v,nparam,&tf)))
0131                     return ps_throwerror(v,_SC("float expected for the specified format"));
0132                 addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(PSChar));
0133                 valtype = 'f';
0134                 break;
0135             default:
0136                 return ps_throwerror(v,_SC("invalid format"));
0137             }
0138             n++;
0139             allocated += addlen + sizeof(PSChar);
0140             dest = ps_getscratchpad(v,allocated);
0141             switch(valtype) {
0142             case 's': i += scsprintf(&dest[i],allocated,fmt,ts); break;
0143             case 'i': i += scsprintf(&dest[i],allocated,fmt,ti); break;
0144             case 'f': i += scsprintf(&dest[i],allocated,fmt,tf); break;
0145             };
0146             nparam ++;
0147         }
0148     }
0149     *outlen = i;
0150     dest[i] = '\0';
0151     *output = dest;
0152     return PS_OK;
0153 }
0154 
0155 static PSInteger _string_format(HPSCRIPTVM v)
0156 {
0157     PSChar *dest = NULL;
0158     PSInteger length = 0;
0159     if(PS_FAILED(psstd_format(v,2,&length,&dest)))
0160         return -1;
0161     ps_pushstring(v,dest,length);
0162     return 1;
0163 }
0164 
0165 static void __strip_l(const PSChar *str,const PSChar **start)
0166 {
0167     const PSChar *t = str;
0168     while(((*t) != '\0') && scisspace(*t)){ t++; }
0169     *start = t;
0170 }
0171 
0172 static void __strip_r(const PSChar *str,PSInteger len,const PSChar **end)
0173 {
0174     if(len == 0) {
0175         *end = str;
0176         return;
0177     }
0178     const PSChar *t = &str[len-1];
0179     while(t >= str && scisspace(*t)) { t--; }
0180     *end = t + 1;
0181 }
0182 
0183 static PSInteger _string_strip(HPSCRIPTVM v)
0184 {
0185     const PSChar *str,*start,*end;
0186     ps_getstring(v,2,&str);
0187     PSInteger len = ps_getsize(v,2);
0188     __strip_l(str,&start);
0189     __strip_r(str,len,&end);
0190     ps_pushstring(v,start,end - start);
0191     return 1;
0192 }
0193 
0194 static PSInteger _string_lstrip(HPSCRIPTVM v)
0195 {
0196     const PSChar *str,*start;
0197     ps_getstring(v,2,&str);
0198     __strip_l(str,&start);
0199     ps_pushstring(v,start,-1);
0200     return 1;
0201 }
0202 
0203 static PSInteger _string_rstrip(HPSCRIPTVM v)
0204 {
0205     const PSChar *str,*end;
0206     ps_getstring(v,2,&str);
0207     PSInteger len = ps_getsize(v,2);
0208     __strip_r(str,len,&end);
0209     ps_pushstring(v,str,end - str);
0210     return 1;
0211 }
0212 
0213 static PSInteger _string_split(HPSCRIPTVM v)
0214 {
0215     const PSChar *str,*seps;
0216     PSChar *stemp;
0217     ps_getstring(v,2,&str);
0218     ps_getstring(v,3,&seps);
0219     PSInteger sepsize = ps_getsize(v,3);
0220     if(sepsize == 0) return ps_throwerror(v,_SC("empty separators string"));
0221     PSInteger memsize = (ps_getsize(v,2)+1)*sizeof(PSChar);
0222     stemp = ps_getscratchpad(v,memsize);
0223     memcpy(stemp,str,memsize);
0224     PSChar *start = stemp;
0225     PSChar *end = stemp;
0226     ps_newarray(v,0);
0227     while(*end != '\0')
0228     {
0229         PSChar cur = *end;
0230         for(PSInteger i = 0; i < sepsize; i++)
0231         {
0232             if(cur == seps[i])
0233             {
0234                 *end = 0;
0235                 ps_pushstring(v,start,-1);
0236                 ps_arrayappend(v,-2);
0237                 start = end + 1;
0238                 break;
0239             }
0240         }
0241         end++;
0242     }
0243     if(end != start)
0244     {
0245         ps_pushstring(v,start,-1);
0246         ps_arrayappend(v,-2);
0247     }
0248     return 1;
0249 }
0250 
0251 /**
0252  * Return common part of the string.
0253  * @param v
0254  * @return 
0255  */
0256 static PSInteger _string_strcommon(HPSCRIPTVM v)
0257 {
0258     const PSChar *str,*str2;
0259     PSChar *stemp;
0260     int i, len;
0261     ps_getstring(v,2,&str);
0262     ps_getstring(v,3,&str2);
0263     PSInteger memsize = (ps_getsize(v,2)+1)*sizeof(PSChar);
0264     stemp = ps_getscratchpad(v,memsize);
0265     memcpy(stemp,str,memsize);
0266     len = strlen(stemp);
0267     
0268     for (i=0; i<len; i++)
0269     {
0270         if (stemp[i]!=str2[i])
0271         {
0272             stemp[i] = EXEOS;
0273             break;
0274         }
0275     }
0276     
0277     ps_pushstring(v,stemp,-1);
0278     
0279     return 1;
0280 }
0281 
0282 /**
0283  * Return differential part from first string
0284  * @param v
0285  * @return 
0286  */
0287 static PSInteger _string_strdiff(HPSCRIPTVM v)
0288 {
0289     const PSChar *str,*str2;
0290     PSChar *stemp;
0291     int i, len;
0292     static char empty[]="";
0293     char *ret=empty;
0294     ps_getstring(v,2,&str);
0295     ps_getstring(v,3,&str2);
0296     PSInteger memsize = (ps_getsize(v,2)+1)*sizeof(PSChar);
0297     stemp = ps_getscratchpad(v,memsize);
0298     memcpy(stemp,str,memsize);
0299     len = strlen(stemp);
0300     
0301     for (i=0; i<len; i++)
0302     {
0303         if (stemp[i]!=str2[i])
0304         {
0305             ret = &stemp[i];
0306             break;
0307         }
0308     }
0309     
0310     ps_pushstring(v,ret,-1);
0311     
0312     return 1;
0313 }
0314 
0315 /**
0316  * Right strip symbols
0317  * @param v
0318  * @return 
0319  */
0320 static PSInteger _string_rstrips(HPSCRIPTVM v)
0321 {
0322     const PSChar *str,*str2;
0323     PSChar *stemp;
0324     char *ret;
0325     ps_getstring(v,2,&str);
0326     ps_getstring(v,3,&str2);
0327     PSInteger memsize = (ps_getsize(v,2)+1)*sizeof(PSChar);
0328     stemp = ps_getscratchpad(v,memsize);
0329     memcpy(stemp,str,memsize);   
0330     ndrx_str_rstrip(stemp, (char *)str2);
0331     ret = stemp;
0332     ps_pushstring(v,ret,-1);
0333     return 1;
0334 }
0335 
0336 /**
0337  * Right strip symbols
0338  * @param v
0339  * @return 
0340  */
0341 static PSInteger _string_lstrips(HPSCRIPTVM v)
0342 {
0343     const PSChar *str,*str2;
0344     PSChar *stemp;
0345     char *ret;
0346     ps_getstring(v,2,&str);
0347     ps_getstring(v,3,&str2);
0348     ret = ndrx_str_lstrip_ptr((char *)str, (char *)str2);
0349     ps_pushstring(v,ret,-1);
0350     return 1;
0351 }
0352 
0353 /**
0354  * Substring, perl like
0355  * @param [script] string
0356  * @param [script] postion from, 0 based, if -1, then position is form str end.
0357  * @param [script] number of chars, if negative, then number of chars to strip from the end.
0358  * @param v
0359  * @return [script] string
0360  */
0361 static PSInteger _string_substr(HPSCRIPTVM v)
0362 {
0363     PSInteger offset, length;
0364     const PSChar *str;
0365     PSChar *stemp;
0366     char *ret;
0367     PSInteger memsize;
0368     int i, len, len_tmp;
0369     
0370     ps_getstring(v,2,&str);
0371     ps_getinteger(v,3,&offset);
0372     
0373     len_tmp = len = strlen(str);
0374     
0375     if (offset<0)
0376     {
0377         /* substract from total len.. */
0378         offset+=len_tmp;
0379     }
0380     
0381     if(ps_gettop(v) > 3)
0382     {
0383         ps_getinteger(v,4,&length);
0384         
0385         if (length < 0)
0386         {
0387             /* actually would be -... */
0388             len+=length;
0389             length = len_tmp;
0390         }
0391     }
0392     else
0393     {
0394         length = len_tmp;
0395     }
0396     
0397     memsize = (ps_getsize(v,2)+1)*sizeof(PSChar);
0398     stemp = ps_getscratchpad(v,memsize);
0399     
0400     if (offset>=len)
0401     {
0402         NDRX_STRCPY_SAFE(stemp, "");
0403     }
0404     else
0405     {
0406         for (i=offset; i < len && ( (i-offset) < length); i++)
0407         {
0408             stemp[i-offset]=str[i];
0409         }
0410         stemp[i-offset]=EXEOS;
0411     }
0412     
0413     ret = stemp;
0414     ps_pushstring(v,ret,-1);
0415     return 1;
0416 }
0417 
0418 /**
0419  * Strip symbols off
0420  * @param v
0421  * @return 
0422  */
0423 static PSInteger _string_strips(HPSCRIPTVM v)
0424 {
0425     const PSChar *str,*str2;
0426     PSChar *stemp;
0427     char *ret;
0428     ps_getstring(v,2,&str);
0429     ps_getstring(v,3,&str2);
0430     PSInteger memsize = (ps_getsize(v,2)+1)*sizeof(PSChar);
0431     stemp = ps_getscratchpad(v,memsize);
0432     memcpy(stemp,str,memsize);   
0433     ret = ndrx_str_strip((char *)stemp, (char *)str2);
0434     ps_pushstring(v,ret,-1);
0435     return 1;
0436 }
0437 
0438 
0439 /**
0440  * Block split the strings, i.e. keep the block together with block escaping option
0441  * Currently only ASCII version.
0442  * @param v
0443  * @return 
0444  */
0445 static PSInteger _string_strtokblk(HPSCRIPTVM v)
0446 {
0447     const PSChar *str,*seps, *quote;
0448     PSChar *stemp, *p;
0449     ps_getstring(v,2,&str);
0450     ps_getstring(v,3,&seps);
0451     ps_getstring(v,4,&quote);
0452     PSInteger sepsize = ps_getsize(v,3);
0453     if(sepsize == 0) return ps_throwerror(v,_SC("empty separators string"));
0454     
0455     PSInteger quotesize = ps_getsize(v,4);
0456     if(quotesize == 0) return ps_throwerror(v,_SC("empty quotes string"));
0457     
0458     PSInteger memsize = (ps_getsize(v,2)+1)*sizeof(PSChar);
0459     stemp = ps_getscratchpad(v,memsize);
0460     memcpy(stemp,str,memsize);
0461     
0462     ps_newarray(v,0);
0463     
0464     for (p = ndrx_strtokblk ( (char *)stemp, (char *)seps, (char *)quote); 
0465         NULL!=p;
0466         p = ndrx_strtokblk (NULL, (char *)seps, (char *)quote))
0467     {
0468         ps_pushstring(v,p,-1);
0469         ps_arrayappend(v,-2);
0470     }
0471 
0472     return 1;
0473 }
0474 
0475 static PSInteger _string_escape(HPSCRIPTVM v)
0476 {
0477     const PSChar *str;
0478     PSChar *dest,*resstr;
0479     PSInteger size;
0480     ps_getstring(v,2,&str);
0481     size = ps_getsize(v,2);
0482     if(size == 0) {
0483         ps_push(v,2);
0484         return 1;
0485     }
0486 #ifdef PSUNICODE
0487 #if WCHAR_SIZE == 2
0488     const PSChar *escpat = _SC("\\x%04x");
0489     const PSInteger maxescsize = 6;
0490 #else //WCHAR_SIZE == 4
0491     const PSChar *escpat = _SC("\\x%08x");
0492     const PSInteger maxescsize = 10;
0493 #endif
0494 #else
0495     const PSChar *escpat = _SC("\\x%02x");
0496     const PSInteger maxescsize = 4;
0497 #endif
0498     PSInteger destcharsize = (size * maxescsize); //assumes every char could be escaped
0499     resstr = dest = (PSChar *)ps_getscratchpad(v,destcharsize * sizeof(PSChar));
0500     PSChar c;
0501     PSChar escch;
0502     PSInteger escaped = 0;
0503     for(int n = 0; n < size; n++){
0504         c = *str++;
0505         escch = 0;
0506         if(scisprint(c) || c == 0) {
0507             switch(c) {
0508             case '\a': escch = 'a'; break;
0509             case '\b': escch = 'b'; break;
0510             case '\t': escch = 't'; break;
0511             case '\n': escch = 'n'; break;
0512             case '\v': escch = 'v'; break;
0513             case '\f': escch = 'f'; break;
0514             case '\r': escch = 'r'; break;
0515             case '\\': escch = '\\'; break;
0516             case '\"': escch = '\"'; break;
0517             case '\'': escch = '\''; break;
0518             case 0: escch = '0'; break;
0519             }
0520             if(escch) {
0521                 *dest++ = '\\';
0522                 *dest++ = escch;
0523                 escaped++;
0524             }
0525             else {
0526                 *dest++ = c;
0527             }
0528         }
0529         else {
0530 
0531             dest += scsprintf(dest, destcharsize, escpat, c);
0532             escaped++;
0533         }
0534     }
0535 
0536     if(escaped) {
0537         ps_pushstring(v,resstr,dest - resstr);
0538     }
0539     else {
0540         ps_push(v,2); //nothing escaped
0541     }
0542     return 1;
0543 }
0544 
0545 static PSInteger _string_startswith(HPSCRIPTVM v)
0546 {
0547     const PSChar *str,*cmp;
0548     ps_getstring(v,2,&str);
0549     ps_getstring(v,3,&cmp);
0550     PSInteger len = ps_getsize(v,2);
0551     PSInteger cmplen = ps_getsize(v,3);
0552     PSBool ret = PSFalse;
0553     if(cmplen <= len) {
0554         ret = memcmp(str,cmp,ps_rsl(cmplen)) == 0 ? PSTrue : PSFalse;
0555     }
0556     ps_pushbool(v,ret);
0557     return 1;
0558 }
0559 
0560 static PSInteger _string_endswith(HPSCRIPTVM v)
0561 {
0562     const PSChar *str,*cmp;
0563     ps_getstring(v,2,&str);
0564     ps_getstring(v,3,&cmp);
0565     PSInteger len = ps_getsize(v,2);
0566     PSInteger cmplen = ps_getsize(v,3);
0567     PSBool ret = PSFalse;
0568     if(cmplen <= len) {
0569         ret = memcmp(&str[len - cmplen],cmp,ps_rsl(cmplen)) == 0 ? PSTrue : PSFalse;
0570     }
0571     ps_pushbool(v,ret);
0572     return 1;
0573 }
0574 
0575 #define SETUP_REX(v) \
0576     PSRex *self = NULL; \
0577     ps_getinstanceup(v,1,(PSUserPointer *)&self,0);
0578 
0579 static PSInteger _rexobj_releasehook(PSUserPointer p, PSInteger PS_UNUSED_ARG(size))
0580 {
0581     PSRex *self = ((PSRex *)p);
0582     psstd_rex_free(self);
0583     return 1;
0584 }
0585 
0586 static PSInteger _regexp_match(HPSCRIPTVM v)
0587 {
0588     SETUP_REX(v);
0589     const PSChar *str;
0590     ps_getstring(v,2,&str);
0591     if(psstd_rex_match(self,str) == PSTrue)
0592     {
0593         ps_pushbool(v,PSTrue);
0594         return 1;
0595     }
0596     ps_pushbool(v,PSFalse);
0597     return 1;
0598 }
0599 
0600 static void _addrexmatch(HPSCRIPTVM v,const PSChar *str,const PSChar *begin,const PSChar *end)
0601 {
0602     ps_newtable(v);
0603     ps_pushstring(v,_SC("begin"),-1);
0604     ps_pushinteger(v,begin - str);
0605     ps_rawset(v,-3);
0606     ps_pushstring(v,_SC("end"),-1);
0607     ps_pushinteger(v,end - str);
0608     ps_rawset(v,-3);
0609 }
0610 
0611 static PSInteger _regexp_search(HPSCRIPTVM v)
0612 {
0613     SETUP_REX(v);
0614     const PSChar *str,*begin,*end;
0615     PSInteger start = 0;
0616     ps_getstring(v,2,&str);
0617     if(ps_gettop(v) > 2) ps_getinteger(v,3,&start);
0618     if(psstd_rex_search(self,str+start,&begin,&end) == PSTrue) {
0619         _addrexmatch(v,str,begin,end);
0620         return 1;
0621     }
0622     return 0;
0623 }
0624 
0625 static PSInteger _regexp_capture(HPSCRIPTVM v)
0626 {
0627     SETUP_REX(v);
0628     const PSChar *str,*begin,*end;
0629     PSInteger start = 0;
0630     ps_getstring(v,2,&str);
0631     if(ps_gettop(v) > 2) ps_getinteger(v,3,&start);
0632     if(psstd_rex_search(self,str+start,&begin,&end) == PSTrue) {
0633         PSInteger n = psstd_rex_getsubexpcount(self);
0634         PSRexMatch match;
0635         ps_newarray(v,0);
0636         for(PSInteger i = 0;i < n; i++) {
0637             psstd_rex_getsubexp(self,i,&match);
0638             if(match.len > 0)
0639                 _addrexmatch(v,str,match.begin,match.begin+match.len);
0640             else
0641                 _addrexmatch(v,str,str,str); //empty match
0642             ps_arrayappend(v,-2);
0643         }
0644         return 1;
0645     }
0646     return 0;
0647 }
0648 
0649 static PSInteger _regexp_subexpcount(HPSCRIPTVM v)
0650 {
0651     SETUP_REX(v);
0652     ps_pushinteger(v,psstd_rex_getsubexpcount(self));
0653     return 1;
0654 }
0655 
0656 static PSInteger _regexp_constructor(HPSCRIPTVM v)
0657 {
0658     const PSChar *error,*pattern;
0659     ps_getstring(v,2,&pattern);
0660     PSRex *rex = psstd_rex_compile(pattern,&error);
0661     if(!rex) return ps_throwerror(v,error);
0662     ps_setinstanceup(v,1,rex);
0663     ps_setreleasehook(v,1,_rexobj_releasehook);
0664     return 0;
0665 }
0666 
0667 static PSInteger _regexp__typeof(HPSCRIPTVM v)
0668 {
0669     ps_pushstring(v,_SC("regexp"),-1);
0670     return 1;
0671 }
0672 
0673 #define _DECL_REX_FUNC(name,nparams,pmask) {_SC(#name),_regexp_##name,nparams,pmask}
0674 static const PSRegFunction rexobj_funcs[]={
0675     _DECL_REX_FUNC(constructor,2,_SC(".s")),
0676     _DECL_REX_FUNC(search,-2,_SC("xsn")),
0677     _DECL_REX_FUNC(match,2,_SC("xs")),
0678     _DECL_REX_FUNC(capture,-2,_SC("xsn")),
0679     _DECL_REX_FUNC(subexpcount,1,_SC("x")),
0680     _DECL_REX_FUNC(_typeof,1,_SC("x")),
0681     {NULL,(PSFUNCTION)0,0,NULL}
0682 };
0683 #undef _DECL_REX_FUNC
0684 
0685 #define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask}
0686 static const PSRegFunction stringlib_funcs[]={
0687     _DECL_FUNC(format,-2,_SC(".s")),
0688     _DECL_FUNC(strip,2,_SC(".s")),
0689     _DECL_FUNC(lstrip,2,_SC(".s")),
0690     _DECL_FUNC(rstrip,2,_SC(".s")),
0691     _DECL_FUNC(split,3,_SC(".ss")),
0692     _DECL_FUNC(strcommon,3,_SC(".ss")),
0693     _DECL_FUNC(strdiff,3,_SC(".ss")),
0694     _DECL_FUNC(rstrips,3,_SC(".ss")),
0695     _DECL_FUNC(lstrips,3,_SC(".ss")),
0696     _DECL_FUNC(strips,3,_SC(".ss")),
0697     _DECL_FUNC(strtokblk,4,_SC(".sss")),
0698     _DECL_FUNC(substr,-3,_SC(".snn")),
0699     _DECL_FUNC(escape,2,_SC(".s")),
0700     _DECL_FUNC(startswith,3,_SC(".ss")),
0701     _DECL_FUNC(endswith,3,_SC(".ss")),
0702     {NULL,(PSFUNCTION)0,0,NULL}
0703 };
0704 #undef _DECL_FUNC
0705 
0706 
0707 PSInteger psstd_register_stringlib(HPSCRIPTVM v)
0708 {
0709     ps_pushstring(v,_SC("regexp"),-1);
0710     ps_newclass(v,PSFalse);
0711     PSInteger i = 0;
0712     while(rexobj_funcs[i].name != 0) {
0713         const PSRegFunction &f = rexobj_funcs[i];
0714         ps_pushstring(v,f.name,-1);
0715         ps_newclosure(v,f.f,0);
0716         ps_setparamscheck(v,f.nparamscheck,f.typemask);
0717         ps_setnativeclosurename(v,-1,f.name);
0718         ps_newslot(v,-3,PSFalse);
0719         i++;
0720     }
0721     ps_newslot(v,-3,PSFalse);
0722 
0723     i = 0;
0724     while(stringlib_funcs[i].name!=0)
0725     {
0726         ps_pushstring(v,stringlib_funcs[i].name,-1);
0727         ps_newclosure(v,stringlib_funcs[i].f,0);
0728         ps_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask);
0729         ps_setnativeclosurename(v,-1,stringlib_funcs[i].name);
0730         ps_newslot(v,-3,PSFalse);
0731         i++;
0732     }
0733     return 1;
0734 }