summaryrefslogtreecommitdiff
path: root/appl/lib/string.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/lib/string.b')
-rw-r--r--appl/lib/string.b358
1 files changed, 358 insertions, 0 deletions
diff --git a/appl/lib/string.b b/appl/lib/string.b
new file mode 100644
index 00000000..16bc1940
--- /dev/null
+++ b/appl/lib/string.b
@@ -0,0 +1,358 @@
+implement String;
+include "string.m";
+
+splitl(s: string, cl: string): (string, string)
+{
+ n := len s;
+ for(j := 0; j < n; j++) {
+ if(in(s[j], cl))
+ return (s[0:j], s[j:n]);
+ }
+ return (s,"");
+}
+
+splitr(s: string, cl: string): (string, string)
+{
+ n := len s;
+ for(j := n-1; j >= 0; j--) {
+ if(in(s[j], cl))
+ return (s[0:j+1], s[j+1:n]);
+ }
+ return ("",s);
+}
+
+drop(s: string, cl: string): string
+{
+ n := len s;
+ for(j := 0; j < n; j++) {
+ if(!in(s[j], cl))
+ return (s[j:n]);
+ }
+ return "";
+}
+
+take(s: string, cl: string): string
+{
+ n := len s;
+ for(j := 0; j < n; j++) {
+ if(!in(s[j], cl))
+ return (s[0:j]);
+ }
+ return s;
+}
+
+in(c: int, s: string): int
+{
+ n := len s;
+ if(n == 0)
+ return 0;
+ ans := 0;
+ negate := 0;
+ if(s[0] == '^') {
+ negate = 1;
+ s = s[1:];
+ n--;
+ }
+ for(i := 0; i < n; i++) {
+ if(s[i] == '-' && i > 0 && i < n-1) {
+ if(c >= s[i-1] && c <= s[i+1]) {
+ ans = 1;
+ break;
+ }
+ i++;
+ }
+ else
+ if(c == s[i]) {
+ ans = 1;
+ break;
+ }
+ }
+ if(negate)
+ ans = !ans;
+ return ans;
+}
+
+splitstrl(s: string, t: string): (string, string)
+{
+ n := len s;
+ nt := len t;
+ if(nt == 0)
+ return ("", s);
+ c0 := t[0];
+ mainloop:
+ for(j := 0; j <= n-nt; j++) {
+ if(s[j] == c0) {
+ for(k := 1; k < nt; k++)
+ if(s[j+k] != t[k])
+ continue mainloop;
+ return(s[0:j], s[j:n]);
+ }
+ }
+ return (s,"");
+}
+
+splitstrr(s: string, t: string): (string, string)
+{
+ n := len s;
+ nt := len t;
+ if(nt == 0)
+ return (s, "");
+ c0 := t[0];
+ mainloop:
+ for(j := n-nt; j >= 0; j--) {
+ if(s[j] == c0) {
+ for(k := 1; k < nt; k++)
+ if(s[j+k] != t[k])
+ continue mainloop;
+ return(s[0:j+nt], s[j+nt:n]);
+ }
+ }
+ return ("",s);
+}
+
+prefix(pre: string, s: string): int
+{
+ ns := len s;
+ n := len pre;
+ if(ns < n)
+ return 0;
+ for(k := 0; k < n; k++) {
+ if(pre[k] != s[k])
+ return 0;
+ }
+ return 1;
+}
+
+tolower(s: string): string
+{
+ r := s;
+ for(i := 0; i < len r; i++) {
+ c := r[i];
+ if(c >= int 'A' && c <= int 'Z')
+ r[i] = r[i] + (int 'a' - int 'A');
+ }
+ return r;
+}
+
+toupper(s: string): string
+{
+ r := s;
+ for(i := 0; i < len r; i++) {
+ c := r[i];
+ if(c >= int 'a' && c <= int 'z')
+ r[i] = r[i] - (int 'a' - int 'A');
+ }
+ return r;
+}
+
+tobig(s: string, base: int): (big, string)
+{
+ if (s == nil || base < 0 || base > 36 || base == 1)
+ return (big 0, s);
+
+ # skip possible leading white space
+ c: int;
+ for (i := 0; i < len s; i++) {
+ c = s[i];
+ if(c != ' ' && c != '\t' && c != '\n')
+ break;
+ }
+
+ # skip possible sign character
+ neg := 0;
+ if (c == '-' || c == '+') {
+ if(c == '-')
+ neg = 1;
+ i++;
+ }
+
+ if (base == 0) {
+ # parse possible leading base designator
+ start := i;
+ base = -1;
+ for (; i < start+3 && i < len s; i++) {
+ c = s[i];
+ if (c == 'r' && i > start) {
+ base = int s[start:i];
+ i++;
+ break;
+ } else if (c < '0' || c > '9')
+ break;
+ }
+ if (base == -1) {
+ i = start;
+ base = 10;
+ } else if (base == 0 || base > 36)
+ return (big 0, s);
+ }
+
+ # parse number itself.
+ # perhaps this should check for overflow, and max out, as limbo op does?
+ start := i;
+ dig := '9';
+ if (base < 10)
+ dig = '0' + base - 1;
+ n := big 0;
+ for (; i < len s; i++) {
+ c = s[i];
+ if ('0' <= c && c <= dig)
+ n = (n * big base) + big(c - '0');
+ else if ('a' <= c && c < 'a' + base - 10)
+ n = (n * big base) + big(c - 'a' + 10);
+ else if ('A' <= c && c < 'A' + base - 10)
+ n = (n * big base) + big(c - 'A' + 10);
+ else
+ break;
+ }
+ if (i == start)
+ return (big 0, s);
+ if (neg)
+ return (-n, s[i:]);
+ return (n, s[i:]);
+}
+
+toint(s: string, base: int): (int, string)
+{
+ if (s == nil || base < 0 || base > 36 || base == 1)
+ return (0, s);
+
+ # skip possible leading white space
+ c: int;
+ for (i := 0; i < len s; i++) {
+ c = s[i];
+ if(c != ' ' && c != '\t' && c != '\n')
+ break;
+ }
+
+ # skip possible sign character
+ neg := 0;
+ if (c == '-' || c == '+') {
+ if(c == '-')
+ neg = 1;
+ i++;
+ }
+
+ if (base == 0) {
+ # parse possible leading base designator
+ start := i;
+ base = -1;
+ for (; i < start+3 && i < len s; i++) {
+ c = s[i];
+ if (c == 'r' && i > start) {
+ base = int s[start:i];
+ i++;
+ break;
+ } else if (c < '0' || c > '9')
+ break;
+ }
+ if (base == -1) {
+ i = start;
+ base = 10;
+ } else if (base == 0 || base > 36)
+ return (0, s);
+ }
+
+ # parse number itself.
+ # perhaps this should check for overflow, and max out, as limbo op does?
+ start := i;
+ dig := '9';
+ if (base < 10)
+ dig = '0' + base - 1;
+ n := 0;
+ for (; i < len s; i++) {
+ c = s[i];
+ if ('0' <= c && c <= dig)
+ n = (n * base) + (c - '0');
+ else if ('a' <= c && c < 'a' + base - 10)
+ n = (n * base) + (c - 'a' + 10);
+ else if ('A' <= c && c < 'A' + base - 10)
+ n = (n * base) + (c - 'A' + 10);
+ else
+ break;
+ }
+ if (i == start)
+ return (0, s);
+ if (neg)
+ return (-n, s[i:]);
+ return (n, s[i:]);
+}
+
+append(s: string, l: list of string): list of string
+{
+ t: list of string;
+
+ # Reverse l, prepend s, and reverse result.
+ while (l != nil) {
+ t = hd l :: t;
+ l = tl l;
+ }
+ t = s :: t;
+ do {
+ l = hd t :: l;
+ t = tl t;
+ } while (t != nil);
+ return l;
+}
+
+quoted(argv: list of string): string
+{
+ return quotedc(argv, nil);
+}
+
+quotedc(argv: list of string, cl: string): string
+{
+ s := "";
+ while(argv != nil){
+ arg := hd argv;
+ for(i := 0; i < len arg; i++){
+ c := arg[i];
+ if(c == ' ' || c == '\t' || c == '\n' || c == '\'' || in(c, cl))
+ break;
+ }
+ if(i < len arg || arg == nil){
+ s += "'" + arg[0:i];
+ for(; i < len arg; i++){
+ if (arg[i] == '\'')
+ s[len s] = '\'';
+ s[len s] = arg[i];
+ }
+ s[len s] = '\'';
+ }else
+ s += arg;
+ if(tl argv != nil)
+ s[len s] = ' ';
+ argv = tl argv;
+ }
+ return s;
+}
+
+unquoted(s: string): list of string
+{
+ args: list of string;
+ word: string;
+ inquote := 0;
+ for(j := len s; j > 0;){
+ c := s[j-1];
+ if(c == ' ' || c == '\t' || c == '\n'){
+ j--;
+ continue;
+ }
+ for(i := j-1; i >= 0 && ((c = s[i]) != ' ' && c != '\t' && c != '\n' || inquote); i--){ # collect word
+ if(c == '\''){
+ word = s[i+1:j] + word;
+ j = i;
+ if(!inquote || i == 0 || s[i-1] != '\'')
+ inquote = !inquote;
+ else
+ i--;
+ }
+ }
+ args = (s[i+1:j]+word) :: args;
+ word = nil;
+ j = i;
+ }
+ # if quotes were unbalanced, balance them and try again.
+ if(inquote)
+ return unquoted(s + "'");
+ return args;
+}