diff options
Diffstat (limited to 'strlib.c')
| -rw-r--r-- | strlib.c | 167 |
1 files changed, 100 insertions, 67 deletions
| @@ -3,7 +3,7 @@ | |||
| 3 | ** String library to LUA | 3 | ** String library to LUA |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | char *rcs_strlib="$Id: strlib.c,v 1.26 1996/08/05 20:55:24 roberto Exp roberto $"; | 6 | char *rcs_strlib="$Id: strlib.c,v 1.27 1996/08/09 13:14:11 roberto Exp roberto $"; |
| 7 | 7 | ||
| 8 | #include <string.h> | 8 | #include <string.h> |
| 9 | #include <stdio.h> | 9 | #include <stdio.h> |
| @@ -14,25 +14,32 @@ char *rcs_strlib="$Id: strlib.c,v 1.26 1996/08/05 20:55:24 roberto Exp roberto $ | |||
| 14 | #include "lualib.h" | 14 | #include "lualib.h" |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | static char *buffer = NULL; | 17 | struct lbuff { |
| 18 | static size_t maxbuff = 0; | 18 | char *b; |
| 19 | static size_t buff_size = 0; | 19 | size_t max; |
| 20 | size_t size; | ||
| 21 | }; | ||
| 22 | |||
| 23 | static struct lbuff lbuffer = {NULL, 0, 0}; | ||
| 20 | 24 | ||
| 21 | 25 | ||
| 22 | static char *lua_strbuffer (unsigned long size) | 26 | static char *lua_strbuffer (unsigned long size) |
| 23 | { | 27 | { |
| 24 | if (size > maxbuff) { | 28 | if (size > lbuffer.max) { |
| 25 | buffer = (buffer) ? realloc(buffer, maxbuff=size) : malloc(maxbuff=size); | 29 | /* ANSI "realloc" doesn't need this test, but some machines (Sun!) |
| 26 | if (buffer == NULL) | 30 | don't follow ANSI */ |
| 31 | lbuffer.b = (lbuffer.b) ? realloc(lbuffer.b, lbuffer.max=size) : | ||
| 32 | malloc(lbuffer.max=size); | ||
| 33 | if (lbuffer.b == NULL) | ||
| 27 | lua_error("memory overflow"); | 34 | lua_error("memory overflow"); |
| 28 | } | 35 | } |
| 29 | return buffer; | 36 | return lbuffer.b; |
| 30 | } | 37 | } |
| 31 | 38 | ||
| 32 | static char *openspace (unsigned long size) | 39 | static char *openspace (unsigned long size) |
| 33 | { | 40 | { |
| 34 | char *buff = lua_strbuffer(buff_size+size); | 41 | char *buff = lua_strbuffer(lbuffer.size+size); |
| 35 | return buff+buff_size; | 42 | return buff+lbuffer.size; |
| 36 | } | 43 | } |
| 37 | 44 | ||
| 38 | void lua_arg_check(int cond, char *funcname) | 45 | void lua_arg_check(int cond, char *funcname) |
| @@ -72,21 +79,25 @@ long lua_opt_number (int numArg, long def, char *funcname) | |||
| 72 | 79 | ||
| 73 | char *luaI_addchar (int c) | 80 | char *luaI_addchar (int c) |
| 74 | { | 81 | { |
| 75 | if (buff_size >= maxbuff) | 82 | if (lbuffer.size >= lbuffer.max) |
| 76 | lua_strbuffer(maxbuff == 0 ? 100 : maxbuff*2); | 83 | lua_strbuffer(lbuffer.max == 0 ? 100 : lbuffer.max*2); |
| 77 | buffer[buff_size++] = c; | 84 | lbuffer.b[lbuffer.size++] = c; |
| 78 | if (c == 0) | 85 | if (c == 0) |
| 79 | buff_size = 0; /* prepare for next string */ | 86 | lbuffer.size = 0; /* prepare for next string */ |
| 80 | return buffer; | 87 | return lbuffer.b; |
| 81 | } | 88 | } |
| 82 | 89 | ||
| 83 | static void addnchar (char *s, int n) | 90 | static void addnchar (char *s, int n) |
| 84 | { | 91 | { |
| 85 | char *b = openspace(n); | 92 | char *b = openspace(n); |
| 86 | strncpy(b, s, n); | 93 | strncpy(b, s, n); |
| 87 | buff_size += n; | 94 | lbuffer.size += n; |
| 88 | } | 95 | } |
| 89 | 96 | ||
| 97 | static void addstr (char *s) | ||
| 98 | { | ||
| 99 | addnchar(s, strlen(s)); | ||
| 100 | } | ||
| 90 | 101 | ||
| 91 | /* | 102 | /* |
| 92 | ** Interface to strtok | 103 | ** Interface to strtok |
| @@ -113,8 +124,6 @@ static void str_tok (void) | |||
| 113 | 124 | ||
| 114 | /* | 125 | /* |
| 115 | ** Return the string length | 126 | ** Return the string length |
| 116 | ** LUA interface: | ||
| 117 | ** n = strlen (string) | ||
| 118 | */ | 127 | */ |
| 119 | static void str_len (void) | 128 | static void str_len (void) |
| 120 | { | 129 | { |
| @@ -122,9 +131,7 @@ static void str_len (void) | |||
| 122 | } | 131 | } |
| 123 | 132 | ||
| 124 | /* | 133 | /* |
| 125 | ** Return the substring of a string, from start to end | 134 | ** Return the substring of a string |
| 126 | ** LUA interface: | ||
| 127 | ** substring = strsub (string, start, end) | ||
| 128 | */ | 135 | */ |
| 129 | static void str_sub (void) | 136 | static void str_sub (void) |
| 130 | { | 137 | { |
| @@ -140,24 +147,26 @@ static void str_sub (void) | |||
| 140 | } | 147 | } |
| 141 | 148 | ||
| 142 | /* | 149 | /* |
| 143 | ** Transliterate a string | 150 | ** Convert a string to lower case. |
| 144 | */ | 151 | */ |
| 145 | static void str_map (void) | 152 | static void str_lower (void) |
| 146 | { | 153 | { |
| 147 | char *s = lua_check_string(1, "strmap"); | 154 | char *s = lua_check_string(1, "strlower"); |
| 148 | char *from = lua_check_string(2, "strmap"); | 155 | luaI_addchar(0); |
| 149 | char *to = lua_opt_string(3, "", "strmap"); | 156 | while (*s) |
| 150 | long len = strlen(to); | 157 | luaI_addchar(tolower(*s++)); |
| 151 | for (luaI_addchar(0); *s; s++) { | 158 | lua_pushstring(luaI_addchar(0)); |
| 152 | char *f = strrchr(from, *s); | 159 | } |
| 153 | if (f == NULL) | 160 | |
| 154 | luaI_addchar(*s); | 161 | /* |
| 155 | else { | 162 | ** Convert a string to upper case. |
| 156 | long pos = f-from; | 163 | */ |
| 157 | if (pos < len) | 164 | static void str_upper (void) |
| 158 | luaI_addchar(to[pos]); | 165 | { |
| 159 | } | 166 | char *s = lua_check_string(1, "strupper"); |
| 160 | } | 167 | luaI_addchar(0); |
| 168 | while (*s) | ||
| 169 | luaI_addchar(toupper(*s++)); | ||
| 161 | lua_pushstring(luaI_addchar(0)); | 170 | lua_pushstring(luaI_addchar(0)); |
| 162 | } | 171 | } |
| 163 | 172 | ||
| @@ -255,11 +264,13 @@ static int num_captures; /* only valid after a sucessful call to match */ | |||
| 255 | static void push_captures (void) | 264 | static void push_captures (void) |
| 256 | { | 265 | { |
| 257 | int i; | 266 | int i; |
| 258 | luaI_addchar(0); | ||
| 259 | for (i=0; i<num_captures; i++) { | 267 | for (i=0; i<num_captures; i++) { |
| 260 | if (capture[i].len == -1) lua_error("unfinished capture"); | 268 | int l = capture[i].len; |
| 261 | addnchar(capture[i].init, capture[i].len); | 269 | char *buff = openspace(l+1); |
| 262 | lua_pushstring(luaI_addchar(0)); | 270 | if (l == -1) lua_error("unfinished capture"); |
| 271 | strncpy(buff, capture[i].init, l); | ||
| 272 | buff[l] = 0; | ||
| 273 | lua_pushstring(buff); | ||
| 263 | } | 274 | } |
| 264 | } | 275 | } |
| 265 | 276 | ||
| @@ -271,18 +282,6 @@ static int check_cap (int l, int level) | |||
| 271 | return l; | 282 | return l; |
| 272 | } | 283 | } |
| 273 | 284 | ||
| 274 | static void add_s (char *newp) | ||
| 275 | { | ||
| 276 | while (*newp) { | ||
| 277 | if (*newp != ESC || !isdigit(*++newp)) | ||
| 278 | luaI_addchar(*newp++); | ||
| 279 | else { | ||
| 280 | int l = check_cap(*newp++, num_captures); | ||
| 281 | addnchar(capture[l].init, capture[l].len); | ||
| 282 | } | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | static int capture_to_close (int level) | 285 | static int capture_to_close (int level) |
| 287 | { | 286 | { |
| 288 | for (level--; level>=0; level--) | 287 | for (level--; level>=0; level--) |
| @@ -376,12 +375,44 @@ static void str_find (void) | |||
| 376 | } | 375 | } |
| 377 | } | 376 | } |
| 378 | 377 | ||
| 379 | static void str_s (void) | 378 | static void add_s (lua_Object newp) |
| 379 | { | ||
| 380 | if (lua_isstring(newp)) { | ||
| 381 | char *news = lua_getstring(newp); | ||
| 382 | while (*news) { | ||
| 383 | if (*news != ESC || !isdigit(*++news)) | ||
| 384 | luaI_addchar(*news++); | ||
| 385 | else { | ||
| 386 | int l = check_cap(*news++, num_captures); | ||
| 387 | addnchar(capture[l].init, capture[l].len); | ||
| 388 | } | ||
| 389 | } | ||
| 390 | } | ||
| 391 | else if (lua_isfunction(newp)) { | ||
| 392 | lua_Object res; | ||
| 393 | struct lbuff oldbuff; | ||
| 394 | lua_beginblock(); | ||
| 395 | push_captures(); | ||
| 396 | /* function may use lbuffer, so save it and create a new one */ | ||
| 397 | oldbuff = lbuffer; | ||
| 398 | lbuffer.b = NULL; lbuffer.max = lbuffer.size = 0; | ||
| 399 | lua_callfunction(newp); | ||
| 400 | /* restore old buffer */ | ||
| 401 | free(lbuffer.b); | ||
| 402 | lbuffer = oldbuff; | ||
| 403 | res = lua_getresult(1); | ||
| 404 | addstr(lua_isstring(res) ? lua_getstring(res) : ""); | ||
| 405 | lua_endblock(); | ||
| 406 | } | ||
| 407 | else lua_error("incorrect argument to `gsub'"); | ||
| 408 | } | ||
| 409 | |||
| 410 | static void str_gsub (void) | ||
| 380 | { | 411 | { |
| 381 | char *src = lua_check_string(1, "s"); | 412 | char *src = lua_check_string(1, "gsub"); |
| 382 | char *p = lua_check_string(2, "s"); | 413 | char *p = lua_check_string(2, "gsub"); |
| 383 | char *newp = lua_check_string(3, "s"); | 414 | lua_Object newp = lua_getparam(3); |
| 384 | int max_s = lua_opt_number(4, strlen(src), "s"); | 415 | int max_s = lua_opt_number(4, strlen(src), "gsub"); |
| 385 | int anchor = (*p == '^') ? (p++, 1) : 0; | 416 | int anchor = (*p == '^') ? (p++, 1) : 0; |
| 386 | int n = 0; | 417 | int n = 0; |
| 387 | luaI_addchar(0); | 418 | luaI_addchar(0); |
| @@ -390,14 +421,14 @@ static void str_s (void) | |||
| 390 | if ((e=match(src, p, 0)) == NULL) | 421 | if ((e=match(src, p, 0)) == NULL) |
| 391 | luaI_addchar(*src++); | 422 | luaI_addchar(*src++); |
| 392 | else { | 423 | else { |
| 393 | if (e == src) lua_error("empty pattern in substitution"); /* ??? */ | 424 | if (e == src) lua_error("empty pattern in substitution"); |
| 394 | add_s(newp); | 425 | add_s(newp); |
| 395 | src = e; | 426 | src = e; |
| 396 | n++; | 427 | n++; |
| 397 | } | 428 | } |
| 398 | if (anchor) break; | 429 | if (anchor) break; |
| 399 | } | 430 | } |
| 400 | addnchar(src, strlen(src)); | 431 | addstr(src); |
| 401 | lua_pushstring(luaI_addchar(0)); | 432 | lua_pushstring(luaI_addchar(0)); |
| 402 | lua_pushnumber(n); /* number of substitutions */ | 433 | lua_pushnumber(n); /* number of substitutions */ |
| 403 | } | 434 | } |
| @@ -455,16 +486,17 @@ static void str_format (void) | |||
| 455 | case 's': { | 486 | case 's': { |
| 456 | char *s = lua_check_string(arg++, "format"); | 487 | char *s = lua_check_string(arg++, "format"); |
| 457 | buff = openspace(strlen(s)); | 488 | buff = openspace(strlen(s)); |
| 458 | buff_size += sprintf(buff, form, s); | 489 | lbuffer.size += sprintf(buff, form, s); |
| 459 | break; | 490 | break; |
| 460 | } | 491 | } |
| 461 | case 'c': case 'd': case 'i': case 'o': | 492 | case 'c': case 'd': case 'i': case 'o': |
| 462 | case 'u': case 'x': case 'X': | 493 | case 'u': case 'x': case 'X': |
| 463 | buff_size += sprintf(buff, form, | 494 | lbuffer.size += sprintf(buff, form, |
| 464 | (int)lua_check_number(arg++, "format")); | 495 | (int)lua_check_number(arg++, "format")); |
| 465 | break; | 496 | break; |
| 466 | case 'e': case 'E': case 'f': case 'g': | 497 | case 'e': case 'E': case 'f': case 'g': |
| 467 | buff_size += sprintf(buff, form, lua_check_number(arg++, "format")); | 498 | lbuffer.size += sprintf(buff, form, |
| 499 | lua_check_number(arg++, "format")); | ||
| 468 | break; | 500 | break; |
| 469 | default: /* also treat cases 'pnLlh' */ | 501 | default: /* also treat cases 'pnLlh' */ |
| 470 | lua_error("invalid format option in function `format'"); | 502 | lua_error("invalid format option in function `format'"); |
| @@ -488,11 +520,12 @@ static struct lua_reg strlib[] = { | |||
| 488 | {"strlen", str_len}, | 520 | {"strlen", str_len}, |
| 489 | {"strsub", str_sub}, | 521 | {"strsub", str_sub}, |
| 490 | {"strset", str_set}, | 522 | {"strset", str_set}, |
| 491 | {"strmap", str_map}, | 523 | {"strlower", str_lower}, |
| 524 | {"strupper", str_upper}, | ||
| 492 | {"ascii", str_ascii}, | 525 | {"ascii", str_ascii}, |
| 493 | {"format", str_format}, | 526 | {"format", str_format}, |
| 494 | {"strfind", str_find}, | 527 | {"strfind", str_find}, |
| 495 | {"gsub", str_s} | 528 | {"gsub", str_gsub} |
| 496 | }; | 529 | }; |
| 497 | 530 | ||
| 498 | 531 | ||
