diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1996-09-16 15:02:40 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1996-09-16 15:02:40 -0300 |
commit | c96ad1c9455b59ea3ff25660549b0e2ad222791e (patch) | |
tree | 8d15f6055e16302bba23e066b89f2fbf5cc22709 | |
parent | 5b9fbfa0066e86a8397c7f07a9596cb94d14e51b (diff) | |
download | lua-c96ad1c9455b59ea3ff25660549b0e2ad222791e.tar.gz lua-c96ad1c9455b59ea3ff25660549b0e2ad222791e.tar.bz2 lua-c96ad1c9455b59ea3ff25660549b0e2ad222791e.zip |
"strmap" replaced by "strupper" and "strlower" (that's what people will
use, anyway).
"gsub" aceppts a function to give the replacement string.
-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 | ||