/* Copyright (c) 1998,1999 Stanley J. Brooks * All rights reserved. * * You may redistribute under the terms of either the GNU General Public * License or the Perl Artistic License. */ #include #include #include #include #include #include #include /* this was just to verify that cp0 will be an slstring static int is_same(char *cp0) { char *cp1; if (!SLang_pop_slstring(&cp1)) { SLang_free_slstring(cp1); return (cp0 == cp1); } return 0; } */ static int is_uppers(unsigned char *cp) { unsigned char ch; while ((ch=*cp++)) if (!isalpha(ch) || ch != UPPER_CASE(ch)) return 0; return 1; } static int is_lowers(unsigned char *cp) { unsigned char ch; while ((ch=*cp++)) if (!isalpha(ch) || ch != LOWER_CASE(ch)) return 0; return 1; } /* this one depends on C locale: */ static int is_alnums(unsigned char *cp) { unsigned char ch; while ((ch=*cp++)) if (!isalnum(ch)) return 0; return 1; } static int is_digits(unsigned char *cp) { unsigned char ch; while ((ch=*cp++)) if (!isdigit(ch)) return 0; return 1; } /* [sjb] new builtin _time(), so remove this... */ static int unix_time(void) { return (int) time(NULL); } /* string = cut_list_element(string,string-to-cut,delim) */ static void cut_list_element(char* cp0, char* cut, int *delim) { char *cp,*out; char ch0,ch; int len,dl = (char) *delim; if (!(cp0 = SLmake_string(cp0))) { SLang_verror(SL_MALLOC_ERROR,"Problem making string"); return; } len=strlen(cut); ch0=*cut; for (cp=out=cp0; (ch=*cp); ) { if ((!ch0 || (ch==ch0 && !memcmp(cp,cut,len))) && (!cp[len]||cp[len]==dl)) { cp+=len; if (!*cp++) { if (out>cp0) out--; break; } }else{ while((ch=*cp++) && ch!=dl) *out++=ch; if (!ch) break; *out++=ch; } } *out='\0'; SLang_push_malloced_string(cp0); /* ^^ this frees it, do don't bother with realloc */ return; } static int SLirc_index(char *cp, int *c) { register char *p=cp; register char ch; register char ch0=*c; while ((ch=*p++)) if (ch==ch0) return p-cp; return 0; } static int SLirc_rindex(char *cp, int *c) { register char *p=cp; char *q=NULL; register char ch; register char ch0=*c; while ((ch=*p++)) if (ch==ch0) q=p; if (q) return(q-cp); return 0; } static void chop_1st(char* cp0) { char *cp; cp = cp0; if (*cp) cp++; SLang_push_string(cp); return; } static void chop_last(char *cp0) { char *cp1; int i; i = strlen(cp0); if (!i) i++; cp1 = (char*) SLmalloc(i); if (cp1) { if (--i) (void)memcpy(cp1,cp0,i); *(cp1+i) = '\0'; i = SLang_push_malloced_string(cp1); if (i != -1) return; } SLang_verror(SL_MALLOC_ERROR,"Problem making string"); } /* if input string ends with "\n" or "\r\n", * push string less that. * eg: s = chomp(s); */ static void chomp(char *cp0) { char *p; int r,i; p = rindex(cp0,'\n'); if (!p || p[1]) i = strlen(p); else { if (*--p != '\r') p++; i = p - cp0; } p = (char*) SLmalloc(i+1); if (p) { if (i) (void)memcpy(p,cp0,i); p[i] = '\0'; r = SLang_push_malloced_string(p); if (!r) return; } SLang_verror(SL_MALLOC_ERROR,"Problem making string"); return; } /* url_encode replaces various special chars by their %xx equivs * and ' ' by '+' * this is for urlencoded HTTP queries */ static void url_encode(char* p) { unsigned char ch; char *s0,*s; s0 = (char*) SLmalloc(3*strlen(p)+1); /* enough for maximum expansion */ if (!s0) return; s = s0; while((ch = *p++)) { if (ch == ' ') { *s++ = '+'; continue; } if ( (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= 0xa0) /* iso-latin-1 chars */ || (ch == '_') || (ch == '.') || (ch == '-') || (ch == '$') /* safe */ /* || (ch == '!') || (ch == '*') || (ch == '\'') */ /* || (ch == '(') || (ch == ')') || (ch == ',') */ ) { *s++ = ch; continue;} sprintf(s,"%%%.2X",ch); s+=3; } *s++ = 0; (void) SLang_push_malloced_string(s0); } static int hexlate(unsigned char ch) { int r; if (ch >= '0' && ch <= '9') r = ch - '0'; else { ch &= ~0x20; if (ch >= 'A' && ch <= 'F') r = ch + 10 - 'A'; else r = -1; } return r; } static void url_decode(char* p) { unsigned char ch; char *s0,*s; s0 = (char*) SLmalloc(strlen(p)+1); /* enough, can't expand. */ if (!s0) return; s = s0; while((ch = *p++)) { if (ch == '+') ch = ' '; if (ch == '%') { int r1,r2; if ( ((r1 = hexlate(p[0])) >= 0) && ((r2 = hexlate(p[1])) >= 0) && (r2 += r1<<4) ) { p+=2; ch = r2; } } *s++ = ch; } *s++ = 0; (void) SLang_push_malloced_string(s0); } /* s_split(string,delimiter) splits string with respect to delim-char, * pushing token strings onto stack, followed by the integer count * of the tokens. The first token in the string is pushed LAST, so * that it will be the 1st to be popped. * * My IMPRESSION is that any string on the stack *should* be a * private copy in RAM, so it shouldn't be necessary to save & restore * the delim's, but who knows? I might be wrong. * * LATER THOUGHTS: above is true when you pop via SLpop_string, * but NOT if SLang_pop_slstring. * Also, if the parameter is specified via SLANG_STRING_TYPE in * the intrinsic declaration, then the pointer you get is an slstring, * which MUST NOT be modified. * * Something I'm still not clear on: when param is indicated as * SLANG_STRING_TYPE in intrinsic declaration, do you still need * to do SLang_free_slstring() on it within the subroutine? * I assume that answer is "no" because of ... intrin_strcmp() in * slang's own slstd.c source-file */ static int s_split(char *cp0, int *delim) { char *cp,*cph,dl; int pmct=0; cp0 = SLmake_string(cp0); if (!cp0) { SLang_verror(SL_MALLOC_ERROR,"Problem making string"); return 0; } dl = (char)(*delim); for (cph=cp0+strlen(cp0); cph>cp0; cph=--cp) { *cph='\0'; for (cp=cph; cp>cp0 && *--cp!=dl; ); /* back up to delim */ if (cp>cp0) cp++; SLang_push_string(cp); pmct++; } SLfree(cp0); return(pmct); } static void v_split(char *cp0,char *delims) { char *cp,*cph,dl; cp0 = SLmake_string(cp0); if (!cp0) { SLang_verror(SL_MALLOC_ERROR,"Problem making string"); return; } for(cp=cp0; (dl=*delims++); cp=cph) { cph=index(cp,dl); if (!cph) break; *cph='\0'; SLang_push_string(cp); *cph++=dl; /* restore it! */ } SLang_push_string(cp); /* the last piece */ SLfree(cp0); if (dl) /* fell short */ do { SLang_push_string(""); } while (*delims++); } static int is_prefix(char *cpa, char *cpb) { u_char cha,chb; while((chb=*cpb++)) { cha=*cpa++; if (cha!=chb) return 0; } return 1; } static int is_prefix_i(char *cpa, char *cpb) { u_char cha,chb; while((chb=*cpb++)) { cha=*cpa++; if (LOWER_CASE(cha)!=LOWER_CASE(chb)) return 0; } return 1; } static int streq(char *cpa, char *cpb) { u_char cha,chb; while((chb=*cpb++)) { cha=*cpa++; if (cha!=chb) return 0; } return (*cpa)?0:1; } static int streq_i(char *cpa, char *cpb) { u_char cha,chb; while((chb=*cpb++)) { cha=*cpa++; if (LOWER_CASE(cha)!=LOWER_CASE(chb)) return 0; } return (*cpa)?0:1; } static int u_strspn(char *cpa, char *cpb) { char *pa,*pb; char cha,chb; pa=cpa; while((cha=*pa++)) { for (pb = cpb; ((chb=*pb++)) && chb != cha;); if (!chb) break; } return (--pa-cpa); } static int u_strcspn(char *cpa, char *cpb) { char *pa,*pb; char cha,chb; pa=cpa; while((cha=*pa++)) { for (pb = cpb; ((chb=*pb++)) && chb != cha;); if (chb) break; } return (--pa-cpa); } /* The Intrinsics Table for LinkList stuff, and some misc */ static SLang_Intrin_Fun_Type Utils_Fun_Intrinsics[] = { MAKE_INTRINSIC_0("unix_time", unix_time, SLANG_INT_TYPE), MAKE_INTRINSIC_S("is_uppers", is_uppers, SLANG_INT_TYPE), MAKE_INTRINSIC_S("is_lowers", is_lowers, SLANG_INT_TYPE), MAKE_INTRINSIC_S("is_alnums", is_alnums, SLANG_INT_TYPE), MAKE_INTRINSIC_S("is_digits", is_digits, SLANG_INT_TYPE), MAKE_INTRINSIC_SS("is_prefix", is_prefix, SLANG_INT_TYPE), MAKE_INTRINSIC_SS("is_prefix_i", is_prefix_i, SLANG_INT_TYPE), MAKE_INTRINSIC_SS("streq", streq, SLANG_INT_TYPE), MAKE_INTRINSIC_SS("streq_i", streq_i, SLANG_INT_TYPE), MAKE_INTRINSIC_SS("strspn", u_strspn, SLANG_INT_TYPE), MAKE_INTRINSIC_SS("strcspn", u_strcspn, SLANG_INT_TYPE), MAKE_INTRINSIC_SI("index", SLirc_index, SLANG_INT_TYPE), MAKE_INTRINSIC_SI("rindex", SLirc_rindex, SLANG_INT_TYPE), MAKE_INTRINSIC_S("chop_1st", chop_1st, SLANG_VOID_TYPE), MAKE_INTRINSIC_S("chop_last", chop_last, SLANG_VOID_TYPE), MAKE_INTRINSIC_S("chomp", chomp, SLANG_VOID_TYPE), MAKE_INTRINSIC_S("url_encode", url_encode, SLANG_VOID_TYPE), MAKE_INTRINSIC_S("url_decode", url_decode, SLANG_VOID_TYPE), MAKE_INTRINSIC_SSI("cut_list_element", cut_list_element, SLANG_VOID_TYPE), MAKE_INTRINSIC_SI("s_split", s_split, SLANG_INT_TYPE), MAKE_INTRINSIC_SS("v_split", v_split, SLANG_VOID_TYPE), SLANG_END_TABLE }; int init_utils_module(void) __attribute__((unused)); int init_utils_module(void) { if (SLdefine_for_ifdef("UTILS")) { fprintf(stderr,"utils-module: fail define_for_isdef(UTILS)\n"); return -1; } if (SLadd_intrin_fun_table(Utils_Fun_Intrinsics, "Utils")) return -1; return 1; }