diff options
author | Lua Team <team@lua.org> | 1996-11-19 12:00:00 +0000 |
---|---|---|
committer | repogen <> | 1996-11-19 12:00:00 +0000 |
commit | 47a298a24ad3a8202440051de5938618502302a0 (patch) | |
tree | 9be43568f1e90c9219d5e3860b58c8ac1db5f062 /clients/lib | |
parent | 721542976ebc89f2f8d17d19be7e4426570b69be (diff) | |
download | lua-github-2.5.tar.gz |
Lua 2.52.5
Diffstat (limited to 'clients/lib')
-rw-r--r-- | clients/lib/Makefile | 8 | ||||
-rw-r--r-- | clients/lib/iolib.c | 583 | ||||
-rw-r--r-- | clients/lib/mathlib.c | 8 | ||||
-rw-r--r-- | clients/lib/mathlib.h | 13 | ||||
-rw-r--r-- | clients/lib/old/Makefile | 35 | ||||
-rw-r--r-- | clients/lib/old/iolib.c | 618 | ||||
-rw-r--r-- | clients/lib/old/lualib.h | 33 | ||||
-rw-r--r-- | clients/lib/old/mathlib.c | 230 | ||||
-rw-r--r-- | clients/lib/old/strlib.c | 276 | ||||
-rw-r--r-- | clients/lib/strlib.c | 539 | ||||
-rw-r--r-- | clients/lib/strlib.h | 13 |
11 files changed, 1748 insertions, 608 deletions
diff --git a/clients/lib/Makefile b/clients/lib/Makefile index ffe2a63f..03888051 100644 --- a/clients/lib/Makefile +++ b/clients/lib/Makefile @@ -4,10 +4,10 @@ LUA= ../.. include $(LUA)/config -EXTRA_DEFS= $(POPEN) +EXTRA_DEFS= $(POPEN) $(NOSTRERROR) OBJS= iolib.o mathlib.o strlib.o -SRCS= iolib.c mathlib.c mathlib.h strlib.c strlib.h +SRCS= iolib.c mathlib.c strlib.c SLIB= $(LIB)/liblualib.a @@ -19,8 +19,8 @@ all: $(SLIB) dynamic: $(DLIB) $(SLIB): $(OBJS) - ar rcuv $@ $(OBJS) - ranlib $(SLIB) + ar rcu $@ $(OBJS) + $(RANLIB) $(SLIB) $(DLIB): $(OBJS) ld -o $@ $(OBJS) diff --git a/clients/lib/iolib.c b/clients/lib/iolib.c index 9ed7e479..c2faf1c5 100644 --- a/clients/lib/iolib.c +++ b/clients/lib/iolib.c @@ -1,10 +1,3 @@ -/* -** iolib.c -** Input/output library to LUA -*/ - -char *rcs_iolib="$Id: iolib.c,v 1.44 1996/05/03 20:10:59 roberto Exp $"; - #include <stdio.h> #include <ctype.h> #include <string.h> @@ -16,7 +9,8 @@ char *rcs_iolib="$Id: iolib.c,v 1.44 1996/05/03 20:10:59 roberto Exp $"; #include "luadebug.h" #include "lualib.h" -static FILE *in=stdin, *out=stdout; + +FILE *lua_infile, *lua_outfile; #ifdef POPEN @@ -31,515 +25,203 @@ int pclose(); static void pushresult (int i) { if (i) - lua_pushnumber (1); - else - lua_pushnil(); -} - -static void closeread (void) -{ - if (in != stdin) - { - if (pclose(in) == -1) - fclose(in); - in = stdin; + lua_pushuserdata(NULL); + else { + lua_pushnil(); +#ifndef NOSTRERROR + lua_pushstring(strerror(errno)); +#else + lua_pushstring("system unable to define the error"); +#endif } } -static void closewrite (void) + +static void closefile (FILE *f) { - if (out != stdout) - { - if (pclose(out) == -1) - fclose(out); - out = stdout; - } + if (f == stdin || f == stdout) + return; + if (f == lua_infile) + lua_infile = stdin; + if (f == lua_outfile) + lua_outfile = stdout; + if (pclose(f) == -1) + fclose(f); } -/* -** Open a file to read. -** LUA interface: -** status = readfrom (filename) -** where: -** status = 1 -> success -** status = nil -> error -*/ + + static void io_readfrom (void) { - if (lua_getparam (1) == LUA_NOOBJECT) - { /* restore standart input */ - closeread(); - lua_pushnumber (1); - } - else - { - char *s = lua_check_string(1, "readfrom"); - FILE *fp = (*s == '|') ? popen(s+1, "r") : fopen(s, "r"); - if (fp == NULL) - lua_pushnil(); - else - { - closeread(); - in = fp; - lua_pushnumber (1); - } - } + lua_Object f = lua_getparam(1); + if (f == LUA_NOOBJECT) + closefile(lua_infile); /* restore standart input */ + else if (lua_isuserdata(f)) + lua_infile = lua_getuserdata(f); + else { + char *s = lua_check_string(1, "readfrom"); + FILE *fp = (*s == '|') ? popen(s+1, "r") : fopen(s, "r"); + if (fp) + lua_infile = fp; + else { + pushresult(0); + return; + } + } + lua_pushuserdata(lua_infile); } -/* -** Open a file to write. -** LUA interface: -** status = writeto (filename) -** where: -** status = 1 -> success -** status = nil -> error -*/ static void io_writeto (void) { - if (lua_getparam (1) == LUA_NOOBJECT) /* restore standart output */ - { - closewrite(); - lua_pushnumber (1); - } - else - { - char *s = lua_check_string(1, "writeto"); - FILE *fp = (*s == '|') ? popen(s+1,"w") : fopen(s,"w"); - if (fp == NULL) - lua_pushnil(); - else - { - closewrite(); - out = fp; - lua_pushnumber (1); - } - } + lua_Object f = lua_getparam(1); + if (f == LUA_NOOBJECT) + closefile(lua_outfile); /* restore standart output */ + else if (lua_isuserdata(f)) + lua_outfile = lua_getuserdata(f); + else { + char *s = lua_check_string(1, "writeto"); + FILE *fp = (*s == '|') ? popen(s+1,"w") : fopen(s,"w"); + if (fp) + lua_outfile = fp; + else { + pushresult(0); + return; + } + } + lua_pushuserdata(lua_outfile); } -/* -** Open a file to write appended. -** LUA interface: -** status = appendto (filename) -** where: -** status = 1 -> success -** status = nil -> error -*/ static void io_appendto (void) { - char *s = lua_check_string(1, "appendto"); - FILE *fp = fopen (s, "a"); - if (fp == NULL) - lua_pushnil(); - else - { - if (out != stdout) fclose (out); - out = fp; - lua_pushnumber(1); - } -} - - -static char getformat (char *f, int *just, int *m, int *n) -{ - int t; - switch (*f++) - { - case 'q': case 'Q': - case 's': case 'S': - case 'i': case 'I': - t = tolower(*(f-1)); - break; - case 'f': case 'F': case 'g': case 'G': case 'e': case 'E': - t = 'f'; - break; - default: - t = 0; /* to avoid compiler warnings */ - lua_arg_error("read/write (format)"); - } - *just = (*f == '<' || *f == '>' || *f == '|') ? *f++ : '>'; - if (isdigit(*f)) - { - *m = 0; - while (isdigit(*f)) - *m = *m*10 + (*f++ - '0'); + char *s = lua_check_string(1, "appendto"); + FILE *fp = fopen (s, "a"); + if (fp != NULL) { + lua_outfile = fp; + lua_pushuserdata(lua_outfile); } else - *m = -1; - if (*f == '.') - { - f++; /* skip point */ - *n = 0; - while (isdigit(*f)) - *n = *n*10 + (*f++ - '0'); - } - else - *n = -1; - return t; + pushresult(0); } -/* -** Read a variable. On error put nil on stack. -** LUA interface: -** variable = read ([format]) -** -** O formato pode ter um dos seguintes especificadores: -** -** s ou S -> para string -** f ou F, g ou G, e ou E -> para reais -** i ou I -> para inteiros -** -** Estes especificadores podem vir seguidos de numero que representa -** o numero de campos a serem lidos. -*/ - -static int read_until_char (int del) -{ - int c; - while((c = fgetc(in)) != EOF && c != del) - luaI_addchar(c); - return c; -} - -static void read_until_blank (void) -{ - int c; - while((c = fgetc(in)) != EOF && !isspace(c)) - luaI_addchar(c); - if (c != EOF) ungetc(c,in); -} - -static void read_m (int m) -{ - int c; - while (m-- && (c = fgetc(in)) != EOF) - luaI_addchar(c); -} - - -static void read_free (void) -{ - int c; - while (isspace(c=fgetc(in))) - ; - if (c == EOF) - { - lua_pushnil(); - return; - } - if (c == '\"' || c == '\'') - { /* string */ - c = read_until_char(c); - if (c == EOF) - lua_pushnil(); - else - lua_pushstring(luaI_addchar(0)); - } - else - { - double d; - char dummy; - char *s; - luaI_addchar(c); - read_until_blank(); - s = luaI_addchar(0); - if (sscanf(s, "%lf %c", &d, &dummy) == 1) - lua_pushnumber(d); - else - lua_pushstring(s); - } -} +#define NEED_OTHER (EOF-1) /* just some flag different from EOF */ static void io_read (void) { - lua_Object o = lua_getparam (1); - luaI_addchar(0); /* initialize buffer */ - if (o == LUA_NOOBJECT) /* free format */ - read_free(); - else /* formatted */ - { - int m, dummy1, dummy2; - switch (getformat(lua_check_string(1, "read"), &dummy1, &m, &dummy2)) - { - case 's': - { - char *s; - if (m < 0) - read_until_blank(); - else - read_m(m); - s = luaI_addchar(0); - if ((m >= 0 && strlen(s) == m) || (m < 0 && strlen(s) > 0)) - lua_pushstring(s); - else - lua_pushnil(); - break; + char *buff; + char *p = lua_opt_string(1, "[^\n]*{\n}", "read"); + int inskip = 0; /* to control {skips} */ + int c = NEED_OTHER; + luaI_addchar(0); + while (*p) { + if (*p == '{' || *p == '}') { + inskip = (*p == '{'); + p++; + } + else { + char *ep = item_end(p); /* get what is next */ + int m; /* match result */ + if (c == NEED_OTHER) c = getc(lua_infile); + m = (c == EOF) ? 0 : singlematch((char)c, p); + if (m) { + if (!inskip) luaI_addchar(c); + c = NEED_OTHER; } - - case 'i': /* can read as float, since it makes no difference to Lua */ - case 'f': - { - double d; - int result; - if (m < 0) - result = fscanf(in, "%lf", &d); - else - { - read_m(m); - result = sscanf(luaI_addchar(0), "%lf", &d); - } - if (result == 1) - lua_pushnumber(d); - else - lua_pushnil(); - break; + switch (*ep) { + case '*': /* repetition */ + if (!m) p = ep+1; /* else stay in (repeat) the same item */ + break; + case '?': /* optional */ + p = ep+1; /* continues reading the pattern */ + break; + default: + if (m) p = ep; /* continues reading the pattern */ + else + goto break_while; /* pattern fails */ } - default: - lua_arg_error("read (format)"); } - } -} - - -/* -** Read characters until a given one. The delimiter is not read. -*/ -static void io_readuntil (void) -{ - int del, c; - lua_Object p = lua_getparam(1); - luaI_addchar(0); /* initialize buffer */ - if (p == LUA_NOOBJECT || lua_isnil(p)) - del = EOF; - else - del = *lua_check_string(1, "readuntil"); - c = read_until_char(del); - if (c != EOF) ungetc(c,in); - lua_pushstring(luaI_addchar(0)); -} - - -/* -** Write a variable. On error put 0 on stack, otherwise put 1. -** LUA interface: -** status = write (variable [,format]) -** -** O formato pode ter um dos seguintes especificadores: -** -** s ou S -> para string -** f ou F, g ou G, e ou E -> para reais -** i ou I -> para inteiros -** -** Estes especificadores podem vir seguidos de: -** -** [?][m][.n] -** -** onde: -** ? -> indica justificacao -** < = esquerda -** | = centro -** > = direita (default) -** m -> numero maximo de campos (se exceder estoura) -** n -> indica precisao para -** reais -> numero de casas decimais -** inteiros -> numero minimo de digitos -** string -> nao se aplica -*/ - -static int write_fill (int n, int c) -{ - while (n--) - if (fputc(c, out) == EOF) - return 0; - return 1; -} - -static int write_string (char *s, int just, int m) -{ - int status; - int l = strlen(s); - int pre; /* number of blanks before string */ - if (m < 0) m = l; - else if (l > m) - { - write_fill(m, '*'); - return 0; - } - pre = (just == '<') ? 0 : (just == '>') ? m-l : (m-l)/2; - status = write_fill(pre, ' '); - status = status && fprintf(out, "%s", s) >= 0; - status = status && write_fill(m-(l+pre), ' '); - return status; -} - -static int write_quoted (int just, int m) -{ - luaI_addchar(0); - luaI_addquoted(lua_check_string(1, "write")); - return write_string(luaI_addchar(0), just, m); -} - -static int write_float (int just, int m, int n) -{ - char buffer[100]; - lua_Object p = lua_getparam(1); - float number; - if (!lua_isnumber(p)) return 0; - number = lua_getnumber(p); - if (n >= 0) - sprintf(buffer, "%.*f", n, number); - else - sprintf(buffer, "%g", number); - return write_string(buffer, just, m); -} - - -static int write_int (int just, int m, int n) -{ - char buffer[100]; - lua_Object p = lua_getparam(1); - int number; - if (!lua_isnumber(p)) return 0; - number = (int)lua_getnumber(p); - if (n >= 0) - sprintf(buffer, "%.*d", n, number); - else - sprintf(buffer, "%d", number); - return write_string(buffer, just, m); + } break_while: + if (c >= 0) /* not EOF nor NEED_OTHER? */ + ungetc(c, lua_infile); + buff = luaI_addchar(0); + if (*buff != 0 || *p == 0) /* read something or did not fail? */ + lua_pushstring(buff); } static void io_write (void) { - int status = 0; - if (lua_getparam (2) == LUA_NOOBJECT) /* free format */ - { - lua_Object o1 = lua_getparam(1); - int t = lua_type(o1); - if (t == LUA_T_NUMBER) - status = fprintf (out, "%g", lua_getnumber(o1)) >= 0; - else if (t == LUA_T_STRING) - status = fprintf (out, "%s", lua_getstring(o1)) >= 0; - } - else /* formated */ - { - int just, m, n; - switch (getformat(lua_check_string(2, "write"), &just, &m, &n)) - { - case 's': - { - lua_Object p = lua_getparam(1); - if (lua_isstring(p)) - status = write_string(lua_getstring(p), just, m); - else - status = 0; - break; - } - case 'q': - status = write_quoted(just, m); - break; - case 'f': - status = write_float(just, m, n); - break; - case 'i': - status = write_int(just, m, n); - break; - } - } - if (status) - lua_pushnumber(status); - else - lua_pushnil(); + int arg = 1; + int status = 1; + char *s; + while ((s = lua_opt_string(arg++, NULL, "write")) != NULL) + status = status && (fputs(s, lua_outfile) != EOF); + pushresult(status); } -/* -** Execute a executable program using "system". -** Return the result of execution. -*/ + static void io_execute (void) { lua_pushnumber(system(lua_check_string(1, "execute"))); } -/* -** Remove a file. On error return nil. -*/ + static void io_remove (void) { pushresult(remove(lua_check_string(1, "remove")) == 0); } + static void io_rename (void) { - char *f1 = lua_check_string(1, "rename"); - char *f2 = lua_check_string(2, "rename"); - pushresult(rename(f1, f2) == 0); + pushresult(rename(lua_check_string(1, "rename"), + lua_check_string(2, "rename")) == 0); } + static void io_tmpname (void) { lua_pushstring(tmpnam(NULL)); } -static void io_errorno (void) -{ -/* lua_pushstring(strerror(errno));*/ -} -/* -** To get a environment variable -*/ static void io_getenv (void) { - char *env = getenv(lua_check_string(1, "getenv")); - lua_pushstring(env); /* if NULL push nil */ + lua_pushstring(getenv(lua_check_string(1, "getenv"))); /* if NULL push nil */ } -/* -** Return user formatted time stamp -*/ + static void io_date (void) { - time_t t; - struct tm *tm; - char *s; - char b[BUFSIZ]; - if (lua_getparam(1) == LUA_NOOBJECT) - s = "%c"; - else - s = lua_check_string(1, "date"); - time(&t); tm = localtime(&t); - if (strftime(b,sizeof(b),s,tm)) - lua_pushstring(b); - else - lua_error("invalid `date' format"); + time_t t; + struct tm *tm; + char *s = lua_opt_string(1, "%c", "date"); + char b[BUFSIZ]; + time(&t); tm = localtime(&t); + if (strftime(b,sizeof(b),s,tm)) + lua_pushstring(b); + else + lua_error("invalid `date' format"); } -/* -** To exit -*/ + static void io_exit (void) { - lua_Object o = lua_getparam(1); - int code = lua_isnumber(o) ? (int)lua_getnumber(o) : 1; - exit(code); + lua_Object o = lua_getparam(1); + exit(lua_isnumber(o) ? (int)lua_getnumber(o) : 1); } -/* -** To debug a lua program. Start a dialog with the user, interpreting - lua commands until an 'cont'. -*/ + static void io_debug (void) { - while (1) - { + while (1) { char buffer[250]; fprintf(stderr, "lua_debug> "); if (fgets(buffer, sizeof(buffer), stdin) == 0) return; - if (strcmp(buffer, "cont") == 0) return; + if (strcmp(buffer, "cont\n") == 0) return; lua_dostring(buffer); } } @@ -550,21 +232,18 @@ static void lua_printstack (FILE *f) int level = 0; lua_Object func; fprintf(f, "Active Stack:\n"); - while ((func = lua_stackedfunction(level++)) != LUA_NOOBJECT) - { + while ((func = lua_stackedfunction(level++)) != LUA_NOOBJECT) { char *name; int currentline; fprintf(f, "\t"); - switch (*lua_getobjname(func, &name)) - { + switch (*lua_getobjname(func, &name)) { case 'g': fprintf(f, "function %s", name); break; case 'f': fprintf(f, "`%s' fallback", name); break; - default: - { + default: { char *filename; int linedefined; lua_funcinfo(func, &filename, &linedefined); @@ -585,8 +264,7 @@ static void lua_printstack (FILE *f) static void errorfb (void) { - lua_Object o = lua_getparam(1); - char *s = lua_isstring(o) ? lua_getstring(o) : "(no messsage)"; + char *s = lua_opt_string(1, "(no messsage)", NULL); fprintf(stderr, "lua: %s\n", s); lua_printstack(stderr); } @@ -597,13 +275,11 @@ static struct lua_reg iolib[] = { {"writeto", io_writeto}, {"appendto", io_appendto}, {"read", io_read}, -{"readuntil",io_readuntil}, {"write", io_write}, {"execute", io_execute}, {"remove", io_remove}, {"rename", io_rename}, {"tmpname", io_tmpname}, -{"ioerror", io_errorno}, {"getenv", io_getenv}, {"date", io_date}, {"exit", io_exit}, @@ -613,6 +289,7 @@ static struct lua_reg iolib[] = { void iolib_open (void) { + lua_infile=stdin; lua_outfile=stdout; luaI_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0]))); lua_setfallback("error", errorfb); } diff --git a/clients/lib/mathlib.c b/clients/lib/mathlib.c index 07081e48..d8f8dc13 100644 --- a/clients/lib/mathlib.c +++ b/clients/lib/mathlib.c @@ -3,7 +3,7 @@ ** Mathematics library to LUA */ -char *rcs_mathlib="$Id: mathlib.c,v 1.17 1996/04/30 21:13:55 roberto Exp $"; +char *rcs_mathlib="$Id: mathlib.c,v 1.18 1996/08/01 14:55:33 roberto Exp $"; #include <stdlib.h> #include <math.h> @@ -92,9 +92,9 @@ static void math_floor (void) static void math_mod (void) { - int d1 = (int)lua_check_number(1, "mod"); - int d2 = (int)lua_check_number(2, "mod"); - lua_pushnumber (d1%d2); + float x = lua_check_number(1, "mod"); + float y = lua_check_number(2, "mod"); + lua_pushnumber(fmod(x, y)); } diff --git a/clients/lib/mathlib.h b/clients/lib/mathlib.h deleted file mode 100644 index 7630144a..00000000 --- a/clients/lib/mathlib.h +++ /dev/null @@ -1,13 +0,0 @@ -/* -** Math library to LUA -** TeCGraf - PUC-Rio -** $Id: mathlib.h,v 1.1 1993/12/17 18:41:19 celes Stab $ -*/ - - -#ifndef strlib_h - -void mathlib_open (void); - -#endif - diff --git a/clients/lib/old/Makefile b/clients/lib/old/Makefile new file mode 100644 index 00000000..b9668617 --- /dev/null +++ b/clients/lib/old/Makefile @@ -0,0 +1,35 @@ +# makefile for lualib + +LUA= ../../.. + +include $(LUA)/config + +EXTRA_DEFS= $(POPEN) $(NOSTRERROR) + +OBJS= iolib.o mathlib.o strlib.o +SRCS= iolib.c mathlib.c strlib.c + +SLIB= $(LIB)/liboldlualib.a + +# dynamic libraries only work for SunOs +DLIB= $(LIB)/liboldlualib.so.$(VERSION) + +all: $(SLIB) + +dynamic: $(DLIB) + +$(SLIB): $(OBJS) + ar rcu $@ $(OBJS) + $(RANLIB) $(SLIB) + +$(DLIB): $(OBJS) + ld -o $@ $(OBJS) + +clean: + rm -f $(OBJS) $(SLIB) $(DLIB) + +co: + co -f -M -rv2_4 $(SRCS) + +klean: clean + rm -f $(SRCS) diff --git a/clients/lib/old/iolib.c b/clients/lib/old/iolib.c new file mode 100644 index 00000000..9ed7e479 --- /dev/null +++ b/clients/lib/old/iolib.c @@ -0,0 +1,618 @@ +/* +** iolib.c +** Input/output library to LUA +*/ + +char *rcs_iolib="$Id: iolib.c,v 1.44 1996/05/03 20:10:59 roberto Exp $"; + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#include <stdlib.h> +#include <errno.h> + +#include "lua.h" +#include "luadebug.h" +#include "lualib.h" + +static FILE *in=stdin, *out=stdout; + + +#ifdef POPEN +FILE *popen(); +int pclose(); +#else +#define popen(x,y) NULL /* that is, popen always fails */ +#define pclose(x) (-1) +#endif + + +static void pushresult (int i) +{ + if (i) + lua_pushnumber (1); + else + lua_pushnil(); +} + +static void closeread (void) +{ + if (in != stdin) + { + if (pclose(in) == -1) + fclose(in); + in = stdin; + } +} + +static void closewrite (void) +{ + if (out != stdout) + { + if (pclose(out) == -1) + fclose(out); + out = stdout; + } +} + +/* +** Open a file to read. +** LUA interface: +** status = readfrom (filename) +** where: +** status = 1 -> success +** status = nil -> error +*/ +static void io_readfrom (void) +{ + if (lua_getparam (1) == LUA_NOOBJECT) + { /* restore standart input */ + closeread(); + lua_pushnumber (1); + } + else + { + char *s = lua_check_string(1, "readfrom"); + FILE *fp = (*s == '|') ? popen(s+1, "r") : fopen(s, "r"); + if (fp == NULL) + lua_pushnil(); + else + { + closeread(); + in = fp; + lua_pushnumber (1); + } + } +} + + +/* +** Open a file to write. +** LUA interface: +** status = writeto (filename) +** where: +** status = 1 -> success +** status = nil -> error +*/ +static void io_writeto (void) +{ + if (lua_getparam (1) == LUA_NOOBJECT) /* restore standart output */ + { + closewrite(); + lua_pushnumber (1); + } + else + { + char *s = lua_check_string(1, "writeto"); + FILE *fp = (*s == '|') ? popen(s+1,"w") : fopen(s,"w"); + if (fp == NULL) + lua_pushnil(); + else + { + closewrite(); + out = fp; + lua_pushnumber (1); + } + } +} + + +/* +** Open a file to write appended. +** LUA interface: +** status = appendto (filename) +** where: +** status = 1 -> success +** status = nil -> error +*/ +static void io_appendto (void) +{ + char *s = lua_check_string(1, "appendto"); + FILE *fp = fopen (s, "a"); + if (fp == NULL) + lua_pushnil(); + else + { + if (out != stdout) fclose (out); + out = fp; + lua_pushnumber(1); + } +} + + +static char getformat (char *f, int *just, int *m, int *n) +{ + int t; + switch (*f++) + { + case 'q': case 'Q': + case 's': case 'S': + case 'i': case 'I': + t = tolower(*(f-1)); + break; + case 'f': case 'F': case 'g': case 'G': case 'e': case 'E': + t = 'f'; + break; + default: + t = 0; /* to avoid compiler warnings */ + lua_arg_error("read/write (format)"); + } + *just = (*f == '<' || *f == '>' || *f == '|') ? *f++ : '>'; + if (isdigit(*f)) + { + *m = 0; + while (isdigit(*f)) + *m = *m*10 + (*f++ - '0'); + } + else + *m = -1; + if (*f == '.') + { + f++; /* skip point */ + *n = 0; + while (isdigit(*f)) + *n = *n*10 + (*f++ - '0'); + } + else + *n = -1; + return t; +} + + +/* +** Read a variable. On error put nil on stack. +** LUA interface: +** variable = read ([format]) +** +** O formato pode ter um dos seguintes especificadores: +** +** s ou S -> para string +** f ou F, g ou G, e ou E -> para reais +** i ou I -> para inteiros +** +** Estes especificadores podem vir seguidos de numero que representa +** o numero de campos a serem lidos. +*/ + +static int read_until_char (int del) +{ + int c; + while((c = fgetc(in)) != EOF && c != del) + luaI_addchar(c); + return c; +} + +static void read_until_blank (void) +{ + int c; + while((c = fgetc(in)) != EOF && !isspace(c)) + luaI_addchar(c); + if (c != EOF) ungetc(c,in); +} + +static void read_m (int m) +{ + int c; + while (m-- && (c = fgetc(in)) != EOF) + luaI_addchar(c); +} + + +static void read_free (void) +{ + int c; + while (isspace(c=fgetc(in))) + ; + if (c == EOF) + { + lua_pushnil(); + return; + } + if (c == '\"' || c == '\'') + { /* string */ + c = read_until_char(c); + if (c == EOF) + lua_pushnil(); + else + lua_pushstring(luaI_addchar(0)); + } + else + { + double d; + char dummy; + char *s; + luaI_addchar(c); + read_until_blank(); + s = luaI_addchar(0); + if (sscanf(s, "%lf %c", &d, &dummy) == 1) + lua_pushnumber(d); + else + lua_pushstring(s); + } +} + +static void io_read (void) +{ + lua_Object o = lua_getparam (1); + luaI_addchar(0); /* initialize buffer */ + if (o == LUA_NOOBJECT) /* free format */ + read_free(); + else /* formatted */ + { + int m, dummy1, dummy2; + switch (getformat(lua_check_string(1, "read"), &dummy1, &m, &dummy2)) + { + case 's': + { + char *s; + if (m < 0) + read_until_blank(); + else + read_m(m); + s = luaI_addchar(0); + if ((m >= 0 && strlen(s) == m) || (m < 0 && strlen(s) > 0)) + lua_pushstring(s); + else + lua_pushnil(); + break; + } + + case 'i': /* can read as float, since it makes no difference to Lua */ + case 'f': + { + double d; + int result; + if (m < 0) + result = fscanf(in, "%lf", &d); + else + { + read_m(m); + result = sscanf(luaI_addchar(0), "%lf", &d); + } + if (result == 1) + lua_pushnumber(d); + else + lua_pushnil(); + break; + } + default: + lua_arg_error("read (format)"); + } + } +} + + +/* +** Read characters until a given one. The delimiter is not read. +*/ +static void io_readuntil (void) +{ + int del, c; + lua_Object p = lua_getparam(1); + luaI_addchar(0); /* initialize buffer */ + if (p == LUA_NOOBJECT || lua_isnil(p)) + del = EOF; + else + del = *lua_check_string(1, "readuntil"); + c = read_until_char(del); + if (c != EOF) ungetc(c,in); + lua_pushstring(luaI_addchar(0)); +} + + +/* +** Write a variable. On error put 0 on stack, otherwise put 1. +** LUA interface: +** status = write (variable [,format]) +** +** O formato pode ter um dos seguintes especificadores: +** +** s ou S -> para string +** f ou F, g ou G, e ou E -> para reais +** i ou I -> para inteiros +** +** Estes especificadores podem vir seguidos de: +** +** [?][m][.n] +** +** onde: +** ? -> indica justificacao +** < = esquerda +** | = centro +** > = direita (default) +** m -> numero maximo de campos (se exceder estoura) +** n -> indica precisao para +** reais -> numero de casas decimais +** inteiros -> numero minimo de digitos +** string -> nao se aplica +*/ + +static int write_fill (int n, int c) +{ + while (n--) + if (fputc(c, out) == EOF) + return 0; + return 1; +} + +static int write_string (char *s, int just, int m) +{ + int status; + int l = strlen(s); + int pre; /* number of blanks before string */ + if (m < 0) m = l; + else if (l > m) + { + write_fill(m, '*'); + return 0; + } + pre = (just == '<') ? 0 : (just == '>') ? m-l : (m-l)/2; + status = write_fill(pre, ' '); + status = status && fprintf(out, "%s", s) >= 0; + status = status && write_fill(m-(l+pre), ' '); + return status; +} + +static int write_quoted (int just, int m) +{ + luaI_addchar(0); + luaI_addquoted(lua_check_string(1, "write")); + return write_string(luaI_addchar(0), just, m); +} + +static int write_float (int just, int m, int n) +{ + char buffer[100]; + lua_Object p = lua_getparam(1); + float number; + if (!lua_isnumber(p)) return 0; + number = lua_getnumber(p); + if (n >= 0) + sprintf(buffer, "%.*f", n, number); + else + sprintf(buffer, "%g", number); + return write_string(buffer, just, m); +} + + +static int write_int (int just, int m, int n) +{ + char buffer[100]; + lua_Object p = lua_getparam(1); + int number; + if (!lua_isnumber(p)) return 0; + number = (int)lua_getnumber(p); + if (n >= 0) + sprintf(buffer, "%.*d", n, number); + else + sprintf(buffer, "%d", number); + return write_string(buffer, just, m); +} + + +static void io_write (void) +{ + int status = 0; + if (lua_getparam (2) == LUA_NOOBJECT) /* free format */ + { + lua_Object o1 = lua_getparam(1); + int t = lua_type(o1); + if (t == LUA_T_NUMBER) + status = fprintf (out, "%g", lua_getnumber(o1)) >= 0; + else if (t == LUA_T_STRING) + status = fprintf (out, "%s", lua_getstring(o1)) >= 0; + } + else /* formated */ + { + int just, m, n; + switch (getformat(lua_check_string(2, "write"), &just, &m, &n)) + { + case 's': + { + lua_Object p = lua_getparam(1); + if (lua_isstring(p)) + status = write_string(lua_getstring(p), just, m); + else + status = 0; + break; + } + case 'q': + status = write_quoted(just, m); + break; + case 'f': + status = write_float(just, m, n); + break; + case 'i': + status = write_int(just, m, n); + break; + } + } + if (status) + lua_pushnumber(status); + else + lua_pushnil(); +} + +/* +** Execute a executable program using "system". +** Return the result of execution. +*/ +static void io_execute (void) +{ + lua_pushnumber(system(lua_check_string(1, "execute"))); +} + +/* +** Remove a file. On error return nil. +*/ +static void io_remove (void) +{ + pushresult(remove(lua_check_string(1, "remove")) == 0); +} + +static void io_rename (void) +{ + char *f1 = lua_check_string(1, "rename"); + char *f2 = lua_check_string(2, "rename"); + pushresult(rename(f1, f2) == 0); +} + +static void io_tmpname (void) +{ + lua_pushstring(tmpnam(NULL)); +} + +static void io_errorno (void) +{ +/* lua_pushstring(strerror(errno));*/ +} + + +/* +** To get a environment variable +*/ +static void io_getenv (void) +{ + char *env = getenv(lua_check_string(1, "getenv")); + lua_pushstring(env); /* if NULL push nil */ +} + +/* +** Return user formatted time stamp +*/ +static void io_date (void) +{ + time_t t; + struct tm *tm; + char *s; + char b[BUFSIZ]; + if (lua_getparam(1) == LUA_NOOBJECT) + s = "%c"; + else + s = lua_check_string(1, "date"); + time(&t); tm = localtime(&t); + if (strftime(b,sizeof(b),s,tm)) + lua_pushstring(b); + else + lua_error("invalid `date' format"); +} + +/* +** To exit +*/ +static void io_exit (void) +{ + lua_Object o = lua_getparam(1); + int code = lua_isnumber(o) ? (int)lua_getnumber(o) : 1; + exit(code); +} + +/* +** To debug a lua program. Start a dialog with the user, interpreting + lua commands until an 'cont'. +*/ +static void io_debug (void) +{ + while (1) + { + char buffer[250]; + fprintf(stderr, "lua_debug> "); + if (fgets(buffer, sizeof(buffer), stdin) == 0) return; + if (strcmp(buffer, "cont") == 0) return; + lua_dostring(buffer); + } +} + + +static void lua_printstack (FILE *f) +{ + int level = 0; + lua_Object func; + fprintf(f, "Active Stack:\n"); + while ((func = lua_stackedfunction(level++)) != LUA_NOOBJECT) + { + char *name; + int currentline; + fprintf(f, "\t"); + switch (*lua_getobjname(func, &name)) + { + case 'g': + fprintf(f, "function %s", name); + break; + case 'f': + fprintf(f, "`%s' fallback", name); + break; + default: + { + char *filename; + int linedefined; + lua_funcinfo(func, &filename, &linedefined); + if (linedefined == 0) + fprintf(f, "main of %s", filename); + else if (linedefined < 0) + fprintf(f, "%s", filename); + else + fprintf(f, "function (%s:%d)", filename, linedefined); + } + } + if ((currentline = lua_currentline(func)) > 0) + fprintf(f, " at line %d", currentline); + fprintf(f, "\n"); + } +} + + +static void errorfb (void) +{ + lua_Object o = lua_getparam(1); + char *s = lua_isstring(o) ? lua_getstring(o) : "(no messsage)"; + fprintf(stderr, "lua: %s\n", s); + lua_printstack(stderr); +} + + +static struct lua_reg iolib[] = { +{"readfrom", io_readfrom}, +{"writeto", io_writeto}, +{"appendto", io_appendto}, +{"read", io_read}, +{"readuntil",io_readuntil}, +{"write", io_write}, +{"execute", io_execute}, +{"remove", io_remove}, +{"rename", io_rename}, +{"tmpname", io_tmpname}, +{"ioerror", io_errorno}, +{"getenv", io_getenv}, +{"date", io_date}, +{"exit", io_exit}, +{"debug", io_debug}, +{"print_stack", errorfb} +}; + +void iolib_open (void) +{ + luaI_openlib(iolib, (sizeof(iolib)/sizeof(iolib[0]))); + lua_setfallback("error", errorfb); +} diff --git a/clients/lib/old/lualib.h b/clients/lib/old/lualib.h new file mode 100644 index 00000000..6005d7c2 --- /dev/null +++ b/clients/lib/old/lualib.h @@ -0,0 +1,33 @@ +/* +** Libraries to be used in LUA programs +** Grupo de Tecnologia em Computacao Grafica +** TeCGraf - PUC-Rio +** $Id: lualib.h,v 1.8 1996/04/30 21:13:55 roberto Exp $ +*/ + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + +void iolib_open (void); +void strlib_open (void); +void mathlib_open (void); + + +/* auxiliar functions (private) */ + +struct lua_reg { + char *name; + lua_CFunction func; +}; + +void luaI_openlib (struct lua_reg *l, int n); +void lua_arg_error(char *funcname); +char *lua_check_string (int numArg, char *funcname); +double lua_check_number (int numArg, char *funcname); +char *luaI_addchar (int c); +void luaI_addquoted (char *s); + +#endif + diff --git a/clients/lib/old/mathlib.c b/clients/lib/old/mathlib.c new file mode 100644 index 00000000..07081e48 --- /dev/null +++ b/clients/lib/old/mathlib.c @@ -0,0 +1,230 @@ +/* +** mathlib.c +** Mathematics library to LUA +*/ + +char *rcs_mathlib="$Id: mathlib.c,v 1.17 1996/04/30 21:13:55 roberto Exp $"; + +#include <stdlib.h> +#include <math.h> + +#include "lualib.h" +#include "lua.h" + +#ifndef PI +#define PI 3.14159265358979323846 +#endif +#define TODEGREE(a) ((a)*180.0/PI) +#define TORAD(a) ((a)*PI/180.0) + +static void math_abs (void) +{ + double d = lua_check_number(1, "abs"); + if (d < 0) d = -d; + lua_pushnumber (d); +} + + +static void math_sin (void) +{ + double d = lua_check_number(1, "sin"); + lua_pushnumber (sin(TORAD(d))); +} + + + +static void math_cos (void) +{ + double d = lua_check_number(1, "cos"); + lua_pushnumber (cos(TORAD(d))); +} + + + +static void math_tan (void) +{ + double d = lua_check_number(1, "tan"); + lua_pushnumber (tan(TORAD(d))); +} + + +static void math_asin (void) +{ + double d = lua_check_number(1, "asin"); + lua_pushnumber (TODEGREE(asin(d))); +} + + +static void math_acos (void) +{ + double d = lua_check_number(1, "acos"); + lua_pushnumber (TODEGREE(acos(d))); +} + + +static void math_atan (void) +{ + double d = lua_check_number(1, "atan"); + lua_pushnumber (TODEGREE(atan(d))); +} + + +static void math_atan2 (void) +{ + double d1 = lua_check_number(1, "atan2"); + double d2 = lua_check_number(2, "atan2"); + lua_pushnumber (TODEGREE(atan2(d1, d2))); +} + + +static void math_ceil (void) +{ + double d = lua_check_number(1, "ceil"); + lua_pushnumber (ceil(d)); +} + + +static void math_floor (void) +{ + double d = lua_check_number(1, "floor"); + lua_pushnumber (floor(d)); +} + +static void math_mod (void) +{ + int d1 = (int)lua_check_number(1, "mod"); + int d2 = (int)lua_check_number(2, "mod"); + lua_pushnumber (d1%d2); +} + + +static void math_sqrt (void) +{ + double d = lua_check_number(1, "sqrt"); + lua_pushnumber (sqrt(d)); +} + +static int old_pow; + +static void math_pow (void) +{ + lua_Object o1 = lua_getparam (1); + lua_Object o2 = lua_getparam (2); + lua_Object op = lua_getparam(3); + if (!lua_isnumber(o1) || !lua_isnumber(o2) || *(lua_getstring(op)) != 'p') + { + lua_Object old = lua_getref(old_pow); + lua_pushobject(o1); + lua_pushobject(o2); + lua_pushobject(op); + if (lua_callfunction(old) != 0) + lua_error(NULL); + } + else + { + double d1 = lua_getnumber(o1); + double d2 = lua_getnumber(o2); + lua_pushnumber (pow(d1,d2)); + } +} + +static void math_min (void) +{ + int i=1; + double dmin = lua_check_number(i, "min"); + while (lua_getparam(++i) != LUA_NOOBJECT) + { + double d = lua_check_number(i, "min"); + if (d < dmin) dmin = d; + } + lua_pushnumber (dmin); +} + +static void math_max (void) +{ + int i=1; + double dmax = lua_check_number(i, "max"); + while (lua_getparam(++i) != LUA_NOOBJECT) + { + double d = lua_check_number(i, "max"); + if (d > dmax) dmax = d; + } + lua_pushnumber (dmax); +} + +static void math_log (void) +{ + double d = lua_check_number(1, "log"); + lua_pushnumber (log(d)); +} + + +static void math_log10 (void) +{ + double d = lua_check_number(1, "log10"); + lua_pushnumber (log10(d)); +} + + +static void math_exp (void) +{ + double d = lua_check_number(1, "exp"); + lua_pushnumber (exp(d)); +} + +static void math_deg (void) +{ + float d = lua_check_number(1, "deg"); + lua_pushnumber (d*180./PI); +} + +static void math_rad (void) +{ + float d = lua_check_number(1, "rad"); + lua_pushnumber (d/180.*PI); +} + +static void math_random (void) +{ + lua_pushnumber((double)(rand()%RAND_MAX) / (double)RAND_MAX); +} + +static void math_randomseed (void) +{ + srand(lua_check_number(1, "randomseed")); +} + + +static struct lua_reg mathlib[] = { +{"abs", math_abs}, +{"sin", math_sin}, +{"cos", math_cos}, +{"tan", math_tan}, +{"asin", math_asin}, +{"acos", math_acos}, +{"atan", math_atan}, +{"atan2", math_atan2}, +{"ceil", math_ceil}, +{"floor", math_floor}, +{"mod", math_mod}, +{"sqrt", math_sqrt}, +{"min", math_min}, +{"max", math_max}, +{"log", math_log}, +{"log10", math_log10}, +{"exp", math_exp}, +{"deg", math_deg}, +{"rad", math_rad}, +{"random", math_random}, +{"randomseed", math_randomseed} +}; + +/* +** Open math library +*/ +void mathlib_open (void) +{ + luaI_openlib(mathlib, (sizeof(mathlib)/sizeof(mathlib[0]))); + old_pow = lua_refobject(lua_setfallback("arith", math_pow), 1); +} + diff --git a/clients/lib/old/strlib.c b/clients/lib/old/strlib.c new file mode 100644 index 00000000..6a99871c --- /dev/null +++ b/clients/lib/old/strlib.c @@ -0,0 +1,276 @@ +/* +** strlib.c +** String library to LUA +*/ + +char *rcs_strlib="$Id: strlib.c,v 1.23 1996/04/30 21:13:55 roberto Exp $"; + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <limits.h> + +#include "lua.h" +#include "lualib.h" + + +void lua_arg_error(char *funcname) +{ + char buff[100]; + sprintf(buff, "incorrect arguments to function `%s'", funcname); + lua_error(buff); +} + +char *lua_check_string (int numArg, char *funcname) +{ + lua_Object o = lua_getparam(numArg); + if (!lua_isstring(o)) + lua_arg_error(funcname); + return lua_getstring(o); +} + +double lua_check_number (int numArg, char *funcname) +{ + lua_Object o = lua_getparam(numArg); + if (!lua_isnumber(o)) + lua_arg_error(funcname); + return lua_getnumber(o); +} + +static int lua_opt_number (int numArg, int def, char *funcname) +{ + return (lua_getparam(numArg) == LUA_NOOBJECT) ? def : + (int)lua_check_number(numArg, funcname); +} + +char *luaI_addchar (int c) +{ + static char *buff = NULL; + static int max = 0; + static int n = 0; + if (n >= max) + { + if (max == 0) + { + max = 100; + buff = (char *)malloc(max); + } + else + { + max *= 2; + buff = (char *)realloc(buff, max); + } + if (buff == NULL) + lua_error("memory overflow"); + } + buff[n++] = c; + if (c == 0) + n = 0; /* prepare for next string */ + return buff; +} + + +/* +** Return the position of the first caracter of a substring into a string +** LUA interface: +** n = strfind (string, substring, init, end) +*/ +static void str_find (void) +{ + char *s1 = lua_check_string(1, "strfind"); + char *s2 = lua_check_string(2, "strfind"); + int init = lua_opt_number(3, 1, "strfind") - 1; + char *f = (init>=0 && init<=strlen(s1)) ? strstr(s1+init,s2) : NULL; + if (f != NULL) + { + int pos = f-s1+1; + if (lua_opt_number(4, INT_MAX, "strfind") >= pos+strlen(s2)-1) + lua_pushnumber (pos); + else + lua_pushnil(); + } + else + lua_pushnil(); +} + +/* +** Return the string length +** LUA interface: +** n = strlen (string) +*/ +static void str_len (void) +{ + char *s = lua_check_string(1, "strlen"); + lua_pushnumber(strlen(s)); +} + + +/* +** Return the substring of a string, from start to end +** LUA interface: +** substring = strsub (string, start, end) +*/ +static void str_sub (void) +{ + char *s = lua_check_string(1, "strsub"); + int start = (int)lua_check_number(2, "strsub"); + int end = lua_opt_number(3, strlen(s), "strsub"); + if (end < start || start < 1 || end > strlen(s)) + lua_pushliteral(""); + else + { + luaI_addchar(0); + while (start <= end) + luaI_addchar(s[start++ - 1]); + lua_pushstring (luaI_addchar(0)); + } +} + +/* +** Convert a string to lower case. +** LUA interface: +** lowercase = strlower (string) +*/ +static void str_lower (void) +{ + char *s = lua_check_string(1, "strlower"); + luaI_addchar(0); + while (*s) + luaI_addchar(tolower(*s++)); + lua_pushstring(luaI_addchar(0)); +} + + +/* +** Convert a string to upper case. +** LUA interface: +** uppercase = strupper (string) +*/ +static void str_upper (void) +{ + char *s = lua_check_string(1, "strupper"); + luaI_addchar(0); + while (*s) + luaI_addchar(toupper(*s++)); + lua_pushstring(luaI_addchar(0)); +} + +/* +** get ascii value of a character in a string +*/ +static void str_ascii (void) +{ + char *s = lua_check_string(1, "ascii"); + int pos = lua_opt_number(2, 1, "ascii") - 1; + if (pos<0 || pos>=strlen(s)) + lua_arg_error("ascii"); + lua_pushnumber(s[pos]); +} + +void luaI_addquoted (char *s) +{ + luaI_addchar('"'); + for (; *s; s++) + { + if (*s == '"' || *s == '\\' || *s == '\n') + luaI_addchar('\\'); + luaI_addchar(*s); + } + luaI_addchar('"'); +} + +#define MAX_CONVERTION 2000 +#define MAX_FORMAT 50 + +static void str_format (void) +{ + int arg = 1; + char *strfrmt = lua_check_string(arg++, "format"); + luaI_addchar(0); /* initialize */ + while (*strfrmt) + { + if (*strfrmt != '%') + luaI_addchar(*strfrmt++); + else if (*++strfrmt == '%') + luaI_addchar(*strfrmt++); /* %% */ + else + { /* format item */ + char form[MAX_FORMAT]; /* store the format ('%...') */ + char buff[MAX_CONVERTION]; /* store the formated value */ + int size = 0; + int i = 0; + form[i++] = '%'; + form[i] = *strfrmt++; + while (!isalpha(form[i])) + { + if (isdigit(form[i])) + { + size = size*10 + form[i]-'0'; + if (size >= MAX_CONVERTION) + lua_error("format size/precision too long in function `format'"); + } + else if (form[i] == '.') + size = 0; /* re-start */ + if (++i >= MAX_FORMAT) + lua_error("bad format in function `format'"); + form[i] = *strfrmt++; + } + form[i+1] = 0; /* ends string */ + switch (form[i]) + { + case 'q': + luaI_addquoted(lua_check_string(arg++, "format")); + buff[0] = '\0'; /* addchar already done */ + break; + case 's': + { + char *s = lua_check_string(arg++, "format"); + if (strlen(s) >= MAX_CONVERTION) + lua_error("string argument too long in function `format'"); + sprintf(buff, form, s); + break; + } + case 'c': case 'd': case 'i': case 'o': + case 'u': case 'x': case 'X': + sprintf(buff, form, (int)lua_check_number(arg++, "format")); + break; + case 'e': case 'E': case 'f': case 'g': + sprintf(buff, form, lua_check_number(arg++, "format")); + break; + default: /* also treat cases 'pnLlh' */ + lua_error("invalid format option in function `format'"); + } + for (i=0; buff[i]; i++) /* move formated value to result */ + luaI_addchar(buff[i]); + } + } + lua_pushstring(luaI_addchar(0)); /* push the result */ +} + + +void luaI_openlib (struct lua_reg *l, int n) +{ + int i; + for (i=0; i<n; i++) + lua_register(l[i].name, l[i].func); +} + +static struct lua_reg strlib[] = { +{"strfind", str_find}, +{"strlen", str_len}, +{"strsub", str_sub}, +{"strlower", str_lower}, +{"strupper", str_upper}, +{"ascii", str_ascii}, +{"format", str_format} +}; + + +/* +** Open string library +*/ +void strlib_open (void) +{ + luaI_openlib(strlib, (sizeof(strlib)/sizeof(strlib[0]))); +} diff --git a/clients/lib/strlib.c b/clients/lib/strlib.c index 6a99871c..47e91f4f 100644 --- a/clients/lib/strlib.c +++ b/clients/lib/strlib.c @@ -3,134 +3,151 @@ ** String library to LUA */ -char *rcs_strlib="$Id: strlib.c,v 1.23 1996/04/30 21:13:55 roberto Exp $"; +char *rcs_strlib="$Id: strlib.c,v 1.33 1996/11/20 13:47:59 roberto Exp $"; #include <string.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> -#include <limits.h> #include "lua.h" #include "lualib.h" -void lua_arg_error(char *funcname) +struct lbuff { + char *b; + size_t max; + size_t size; +}; + +static struct lbuff lbuffer = {NULL, 0, 0}; + + +static char *lua_strbuffer (unsigned long size) +{ + if (size > lbuffer.max) { + /* ANSI "realloc" doesn't need this test, but some machines (Sun!) + don't follow ANSI */ + lbuffer.b = (lbuffer.b) ? realloc(lbuffer.b, lbuffer.max=size) : + malloc(lbuffer.max=size); + if (lbuffer.b == NULL) + lua_error("memory overflow"); + } + return lbuffer.b; +} + +static char *openspace (unsigned long size) { - char buff[100]; - sprintf(buff, "incorrect arguments to function `%s'", funcname); - lua_error(buff); + char *buff = lua_strbuffer(lbuffer.size+size); + return buff+lbuffer.size; +} + +void lua_arg_check(int cond, char *funcname) +{ + if (!cond) { + char buff[100]; + sprintf(buff, "incorrect argument to function `%s'", funcname); + lua_error(buff); + } } char *lua_check_string (int numArg, char *funcname) { lua_Object o = lua_getparam(numArg); - if (!lua_isstring(o)) - lua_arg_error(funcname); + lua_arg_check(lua_isstring(o), funcname); return lua_getstring(o); } +char *lua_opt_string (int numArg, char *def, char *funcname) +{ + return (lua_getparam(numArg) == LUA_NOOBJECT) ? def : + lua_check_string(numArg, funcname); +} + double lua_check_number (int numArg, char *funcname) { lua_Object o = lua_getparam(numArg); - if (!lua_isnumber(o)) - lua_arg_error(funcname); + lua_arg_check(lua_isnumber(o), funcname); return lua_getnumber(o); } -static int lua_opt_number (int numArg, int def, char *funcname) +long lua_opt_number (int numArg, long def, char *funcname) { return (lua_getparam(numArg) == LUA_NOOBJECT) ? def : - (int)lua_check_number(numArg, funcname); + (long)lua_check_number(numArg, funcname); } char *luaI_addchar (int c) { - static char *buff = NULL; - static int max = 0; - static int n = 0; - if (n >= max) - { - if (max == 0) - { - max = 100; - buff = (char *)malloc(max); - } - else - { - max *= 2; - buff = (char *)realloc(buff, max); - } - if (buff == NULL) - lua_error("memory overflow"); - } - buff[n++] = c; + if (lbuffer.size >= lbuffer.max) + lua_strbuffer(lbuffer.max == 0 ? 100 : lbuffer.max*2); + lbuffer.b[lbuffer.size++] = c; if (c == 0) - n = 0; /* prepare for next string */ - return buff; + lbuffer.size = 0; /* prepare for next string */ + return lbuffer.b; } +static void addnchar (char *s, int n) +{ + char *b = openspace(n); + strncpy(b, s, n); + lbuffer.size += n; +} + +static void addstr (char *s) +{ + addnchar(s, strlen(s)); +} /* -** Return the position of the first caracter of a substring into a string -** LUA interface: -** n = strfind (string, substring, init, end) +** Interface to strtok */ -static void str_find (void) +static void str_tok (void) { - char *s1 = lua_check_string(1, "strfind"); - char *s2 = lua_check_string(2, "strfind"); - int init = lua_opt_number(3, 1, "strfind") - 1; - char *f = (init>=0 && init<=strlen(s1)) ? strstr(s1+init,s2) : NULL; - if (f != NULL) - { - int pos = f-s1+1; - if (lua_opt_number(4, INT_MAX, "strfind") >= pos+strlen(s2)-1) - lua_pushnumber (pos); - else - lua_pushnil(); - } - else - lua_pushnil(); + char *s1 = lua_check_string(1, "strtok"); + char *del = lua_check_string(2, "strtok"); + lua_Object t = lua_createtable(); + int i = 1; + /* As strtok changes s1, and s1 is "constant", make a copy of it */ + s1 = strcpy(lua_strbuffer(strlen(s1+1)), s1); + while ((s1 = strtok(s1, del)) != NULL) { + lua_pushobject(t); + lua_pushnumber(i++); + lua_pushstring(s1); + lua_storesubscript(); + s1 = NULL; /* prepare for next strtok */ + } + lua_pushobject(t); + lua_pushnumber(i-1); /* total number of tokens */ } + /* ** Return the string length -** LUA interface: -** n = strlen (string) */ static void str_len (void) { - char *s = lua_check_string(1, "strlen"); - lua_pushnumber(strlen(s)); + lua_pushnumber(strlen(lua_check_string(1, "strlen"))); } - /* -** Return the substring of a string, from start to end -** LUA interface: -** substring = strsub (string, start, end) +** Return the substring of a string */ static void str_sub (void) { - char *s = lua_check_string(1, "strsub"); - int start = (int)lua_check_number(2, "strsub"); - int end = lua_opt_number(3, strlen(s), "strsub"); - if (end < start || start < 1 || end > strlen(s)) - lua_pushliteral(""); - else - { - luaI_addchar(0); - while (start <= end) - luaI_addchar(s[start++ - 1]); - lua_pushstring (luaI_addchar(0)); - } + char *s = lua_check_string(1, "strsub"); + long start = (long)lua_check_number(2, "strsub"); + long end = lua_opt_number(3, strlen(s), "strsub"); + if (1 <= start && start <= end && end <= strlen(s)) { + luaI_addchar(0); + addnchar(s+start-1, end-start+1); + lua_pushstring(luaI_addchar(0)); + } + else lua_pushliteral(""); } /* ** Convert a string to lower case. -** LUA interface: -** lowercase = strlower (string) */ static void str_lower (void) { @@ -141,11 +158,8 @@ static void str_lower (void) lua_pushstring(luaI_addchar(0)); } - /* ** Convert a string to upper case. -** LUA interface: -** uppercase = strupper (string) */ static void str_upper (void) { @@ -156,78 +170,357 @@ static void str_upper (void) lua_pushstring(luaI_addchar(0)); } +static void str_rep (void) +{ + char *s = lua_check_string(1, "strrep"); + int n = (int)lua_check_number(2, "strrep"); + luaI_addchar(0); + while (n-- > 0) + addstr(s); + lua_pushstring(luaI_addchar(0)); +} + /* ** get ascii value of a character in a string */ static void str_ascii (void) { char *s = lua_check_string(1, "ascii"); - int pos = lua_opt_number(2, 1, "ascii") - 1; - if (pos<0 || pos>=strlen(s)) - lua_arg_error("ascii"); - lua_pushnumber(s[pos]); + long pos = lua_opt_number(2, 1, "ascii") - 1; + lua_arg_check(0<=pos && pos<strlen(s), "ascii"); + lua_pushnumber((unsigned char)s[pos]); +} + + +/* pattern matching */ + +#define ESC '%' +#define SPECIALS "^$*?.([%" + +static char *bracket_end (char *p) +{ + return (*p == 0) ? NULL : strchr((*p=='^') ? p+2 : p+1, ']'); +} + +char *item_end (char *p) +{ + switch (*p++) { + case '\0': return p-1; + case ESC: + if (*p == 0) lua_error("incorrect pattern"); + return p+1; + case '[': { + char *end = bracket_end(p); + if (end == NULL) lua_error("incorrect pattern"); + return end+1; + } + default: + return p; + } +} + +static int matchclass (int c, int cl) +{ + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + +int singlematch (int c, char *p) +{ + if (c == 0) return 0; + switch (*p) { + case '.': return 1; + case ESC: return matchclass(c, *(p+1)); + case '[': { + char *end = bracket_end(p+1); + int sig = *(p+1) == '^' ? (p++, 0) : 1; + while (++p < end) { + if (*p == ESC) { + if (((p+1) < end) && matchclass(c, *++p)) return sig; + } + else if ((*(p+1) == '-') && (p+2 < end)) { + p+=2; + if (*(p-2) <= c && c <= *p) return sig; + } + else if (*p == c) return sig; + } + return !sig; + } + default: return (*p == c); + } +} + +#define MAX_CAPT 9 + +static struct { + char *init; + int len; /* -1 signals unfinished capture */ +} capture[MAX_CAPT]; + +static int num_captures; /* only valid after a sucessful call to match */ + + +static void push_captures (void) +{ + int i; + for (i=0; i<num_captures; i++) { + int l = capture[i].len; + char *buff = openspace(l+1); + if (l == -1) lua_error("unfinished capture"); + strncpy(buff, capture[i].init, l); + buff[l] = 0; + lua_pushstring(buff); + } } +static int check_cap (int l, int level) +{ + l -= '1'; + if (!(0 <= l && l < level && capture[l].len != -1)) + lua_error("invalid capture index"); + return l; +} + +static int capture_to_close (int level) +{ + for (level--; level>=0; level--) + if (capture[level].len == -1) return level; + lua_error("invalid pattern capture"); + return 0; /* to avoid warnings */ +} + +static char *matchbalance (char *s, int b, int e) +{ + if (*s != b) return NULL; + else { + int cont = 1; + while (*(++s)) { + if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + +static char *match (char *s, char *p, int level) +{ + init: /* using goto's to optimize tail recursion */ + switch (*p) { + case '(': /* start capture */ + if (level >= MAX_CAPT) lua_error("too many captures"); + capture[level].init = s; + capture[level].len = -1; + level++; p++; goto init; /* return match(s, p+1, level); */ + case ')': { /* end capture */ + int l = capture_to_close(level); + char *res; + capture[l].len = s - capture[l].init; /* close capture */ + if ((res = match(s, p+1, level)) == NULL) /* match failed? */ + capture[l].len = -1; /* undo capture */ + return res; + } + case ESC: + if (isdigit(*(p+1))) { /* capture */ + int l = check_cap(*(p+1), level); + if (strncmp(capture[l].init, s, capture[l].len) == 0) { + /* return match(p+2, s+capture[l].len, level); */ + p+=2; s+=capture[l].len; goto init; + } + else return NULL; + } + else if (*(p+1) == 'b') { /* balanced string */ + if (*(p+2) == 0 || *(p+3) == 0) + lua_error("bad balanced pattern specification"); + s = matchbalance(s, *(p+2), *(p+3)); + if (s == NULL) return NULL; + else { /* return match(p+4, s, level); */ + p+=4; goto init; + } + } + else goto dflt; + case '\0': case '$': /* (possibly) end of pattern */ + if (*p == 0 || (*(p+1) == 0 && *s == 0)) { + num_captures = level; + return s; + } + else goto dflt; + default: dflt: { /* it is a pattern item */ + int m = singlematch(*s, p); + char *ep = item_end(p); /* get what is next */ + switch (*ep) { + case '*': { /* repetition */ + char *res; + if (m && (res = match(s+1, p, level))) + return res; + p=ep+1; goto init; /* else return match(s, ep+1, level); */ + } + case '?': { /* optional */ + char *res; + if (m && (res = match(s+1, ep+1, level))) + return res; + p=ep+1; goto init; /* else return match(s, ep+1, level); */ + } + default: + if (m) { s++; p=ep; goto init; } /* return match(s+1, ep, level); */ + else return NULL; + } + } + } +} + +static void str_find (void) +{ + char *s = lua_check_string(1, "strfind"); + char *p = lua_check_string(2, "strfind"); + long init = lua_opt_number(3, 1, "strfind") - 1; + lua_arg_check(0 <= init && init <= strlen(s), "strfind"); + if (lua_getparam(4) != LUA_NOOBJECT || + strpbrk(p, SPECIALS) == NULL) { /* no special caracters? */ + char *s2 = strstr(s+init, p); + if (s2) { + lua_pushnumber(s2-s+1); + lua_pushnumber(s2-s+strlen(p)); + } + } + else { + int anchor = (*p == '^') ? (p++, 1) : 0; + char *s1=s+init; + do { + char *res; + if ((res=match(s1, p, 0)) != NULL) { + lua_pushnumber(s1-s+1); /* start */ + lua_pushnumber(res-s); /* end */ + push_captures(); + return; + } + } while (*s1++ && !anchor); + } +} + +static void add_s (lua_Object newp) +{ + if (lua_isstring(newp)) { + char *news = lua_getstring(newp); + while (*news) { + if (*news != ESC || !isdigit(*++news)) + luaI_addchar(*news++); + else { + int l = check_cap(*news++, num_captures); + addnchar(capture[l].init, capture[l].len); + } + } + } + else if (lua_isfunction(newp)) { + lua_Object res; + struct lbuff oldbuff; + lua_beginblock(); + push_captures(); + /* function may use lbuffer, so save it and create a new one */ + oldbuff = lbuffer; + lbuffer.b = NULL; lbuffer.max = lbuffer.size = 0; + lua_callfunction(newp); + /* restore old buffer */ + free(lbuffer.b); + lbuffer = oldbuff; + res = lua_getresult(1); + addstr(lua_isstring(res) ? lua_getstring(res) : ""); + lua_endblock(); + } + else lua_arg_check(0, "gsub"); +} + +static void str_gsub (void) +{ + char *src = lua_check_string(1, "gsub"); + char *p = lua_check_string(2, "gsub"); + lua_Object newp = lua_getparam(3); + int max_s = lua_opt_number(4, strlen(src), "gsub"); + int anchor = (*p == '^') ? (p++, 1) : 0; + int n = 0; + luaI_addchar(0); + while (*src && n < max_s) { + char *e; + if ((e=match(src, p, 0)) == NULL) + luaI_addchar(*src++); + else { + if (e == src) lua_error("empty pattern in substitution"); + add_s(newp); + src = e; + n++; + } + if (anchor) break; + } + addstr(src); + lua_pushstring(luaI_addchar(0)); + lua_pushnumber(n); /* number of substitutions */ +} + +static void str_set (void) +{ + char *item = lua_check_string(1, "strset"); + int i; + lua_arg_check(*item_end(item) == 0, "strset"); + luaI_addchar(0); + for (i=1; i<256; i++) /* 0 cannot be part of a set */ + if (singlematch(i, item)) + luaI_addchar(i); + lua_pushstring(luaI_addchar(0)); +} + + void luaI_addquoted (char *s) { luaI_addchar('"'); - for (; *s; s++) - { - if (*s == '"' || *s == '\\' || *s == '\n') + for (; *s; s++) { + if (strchr("\"\\\n", *s)) luaI_addchar('\\'); luaI_addchar(*s); } luaI_addchar('"'); } -#define MAX_CONVERTION 2000 -#define MAX_FORMAT 50 +#define MAX_FORMAT 200 static void str_format (void) { int arg = 1; char *strfrmt = lua_check_string(arg++, "format"); luaI_addchar(0); /* initialize */ - while (*strfrmt) - { + while (*strfrmt) { if (*strfrmt != '%') luaI_addchar(*strfrmt++); else if (*++strfrmt == '%') luaI_addchar(*strfrmt++); /* %% */ - else - { /* format item */ + else { /* format item */ char form[MAX_FORMAT]; /* store the format ('%...') */ - char buff[MAX_CONVERTION]; /* store the formated value */ - int size = 0; - int i = 0; - form[i++] = '%'; - form[i] = *strfrmt++; - while (!isalpha(form[i])) - { - if (isdigit(form[i])) - { - size = size*10 + form[i]-'0'; - if (size >= MAX_CONVERTION) - lua_error("format size/precision too long in function `format'"); - } - else if (form[i] == '.') - size = 0; /* re-start */ - if (++i >= MAX_FORMAT) - lua_error("bad format in function `format'"); - form[i] = *strfrmt++; - } - form[i+1] = 0; /* ends string */ - switch (form[i]) - { + char *buff; + char *initf = strfrmt-1; /* -1 to include % */ + strfrmt = match(strfrmt, "[-+ #]*(%d*)%.?(%d*)", 0); + if (capture[0].len > 3 || capture[1].len > 3) /* < 1000? */ + lua_error("invalid format (width/precision too long)"); + strncpy(form, initf, strfrmt-initf+1); /* +1 to include convertion */ + form[strfrmt-initf+1] = 0; + buff = openspace(1000); /* to store the formated value */ + switch (*strfrmt++) { case 'q': luaI_addquoted(lua_check_string(arg++, "format")); - buff[0] = '\0'; /* addchar already done */ - break; - case 's': - { + continue; + case 's': { char *s = lua_check_string(arg++, "format"); - if (strlen(s) >= MAX_CONVERTION) - lua_error("string argument too long in function `format'"); + buff = openspace(strlen(s)); sprintf(buff, form, s); break; } @@ -241,8 +534,7 @@ static void str_format (void) default: /* also treat cases 'pnLlh' */ lua_error("invalid format option in function `format'"); } - for (i=0; buff[i]; i++) /* move formated value to result */ - luaI_addchar(buff[i]); + lbuffer.size += strlen(buff); } } lua_pushstring(luaI_addchar(0)); /* push the result */ @@ -256,14 +548,19 @@ void luaI_openlib (struct lua_reg *l, int n) lua_register(l[i].name, l[i].func); } + static struct lua_reg strlib[] = { -{"strfind", str_find}, +{"strtok", str_tok}, {"strlen", str_len}, {"strsub", str_sub}, +{"strset", str_set}, {"strlower", str_lower}, {"strupper", str_upper}, +{"strrep", str_rep}, {"ascii", str_ascii}, -{"format", str_format} +{"format", str_format}, +{"strfind", str_find}, +{"gsub", str_gsub} }; diff --git a/clients/lib/strlib.h b/clients/lib/strlib.h deleted file mode 100644 index db3d38c5..00000000 --- a/clients/lib/strlib.h +++ /dev/null @@ -1,13 +0,0 @@ -/* -** String library to LUA -** TeCGraf - PUC-Rio -** $Id: strlib.h,v 1.1 1993/12/17 18:41:19 celes Stab $ -*/ - - -#ifndef strlib_h - -void strlib_open (void); - -#endif - |