/* ** iolib.c ** Input/output library to LUA */ char *rcs_iolib="$Id: iolib.c,v 1.26 1995/10/26 14:21:56 roberto Exp roberto $"; #include #include #include #include #include #include #include #include "lua.h" #include "luadebug.h" #include "lualib.h" static FILE *in=stdin, *out=stdout; #ifndef POPEN #define popen(x,y) NULL /* that is, popen always fails */ #define pclose(x) (-1) #endif static void str_error(char *funcname) { char buff[250]; sprintf(buff, "incorrect arguments to function `%s'", funcname); lua_error(buff); } static char *check_and_get_string (int numArg, char *funcname) { lua_Object o = lua_getparam(numArg); if (!(lua_isstring(o) || lua_isnumber(o))) str_error(funcname); return lua_getstring(o); } 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 = 0 -> error */ static void io_readfrom (void) { if (lua_getparam (1) == LUA_NOOBJECT) { /* restore standart input */ closeread(); lua_pushnumber (1); } else { char *s = check_and_get_string(1, "readfrom"); FILE *fp = (*s == '|') ? popen(s+1, "r") : fopen(s, "r"); if (fp == NULL) lua_pushnumber (0); else { closeread(); in = fp; lua_pushnumber (1); } } } /* ** Open a file to write. ** LUA interface: ** status = writeto (filename) ** where: ** status = 1 -> success ** status = 0 -> error */ static void io_writeto (void) { if (lua_getparam (1) == LUA_NOOBJECT) /* restore standart output */ { closewrite(); lua_pushnumber (1); } else { char *s = check_and_get_string(1, "writeto"); FILE *fp = (*s == '|') ? popen(s+1,"w") : fopen(s,"w"); if (fp == NULL) lua_pushnumber (0); else { closewrite(); out = fp; lua_pushnumber (1); } } } /* ** Open a file to write appended. ** LUA interface: ** status = appendto (filename) ** where: ** status = 2 -> success (already exist) ** status = 1 -> success (new file) ** status = 0 -> error */ static void io_appendto (void) { char *s = check_and_get_string(1, "appendto"); struct stat st; int r = (stat(s, &st) == -1) ? 1 : 2; FILE *fp = fopen (s, "a"); if (fp == NULL) lua_pushnumber (0); else { if (out != stdout) fclose (out); out = fp; lua_pushnumber (r); } } /* ** 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 void io_read (void) { lua_Object o = lua_getparam (1); if (o == LUA_NOOBJECT) /* free format */ { int c; char s[256]; while (isspace(c=fgetc(in))) ; if (c == '\"' || c == '\'') { int del = c; int n=0; while((c = fgetc(in)) != del) { if (c == EOF) { lua_pushnil (); return; } s[n++] = c; } s[n] = 0; } else { double d; ungetc (c, in); if (fscanf (in, "%s", s) != 1) { lua_pushnil (); return; } if (sscanf(s, "%lf %*c", &d) == 1) { lua_pushnumber (d); return; } } lua_pushstring (s); return; } else /* formatted */ { char *e = check_and_get_string(1, "read"); char t; int m=0; while (isspace(*e)) e++; t = *e++; while (isdigit(*e)) m = m*10 + (*e++ - '0'); if (m > 0) { char f[80]; char s[256]; sprintf (f, "%%%ds", m); if (fgets (s, m+1, in) == NULL) { lua_pushnil(); return; } else { if (s[strlen(s)-1] == '\n') s[strlen(s)-1] = 0; } switch (tolower(t)) { case 'i': { long int l; sscanf (s, "%ld", &l); lua_pushnumber(l); } break; case 'f': case 'g': case 'e': { float fl; sscanf (s, "%f", &fl); lua_pushnumber(fl); } break; default: lua_pushstring(s); break; } } else { switch (tolower(t)) { case 'i': { long int l; if (fscanf (in, "%ld", &l) == EOF) lua_pushnil(); else lua_pushnumber(l); } break; case 'f': case 'g': case 'e': { float f; if (fscanf (in, "%f", &f) == EOF) lua_pushnil(); else lua_pushnumber(f); } break; default: { char s[256]; if (fscanf (in, "%s", s) == EOF) lua_pushnil(); else lua_pushstring(s); } break; } } } } /* ** Read characters until a given one. The delimiter is not read. */ static void io_readuntil (void) { int n=255,m=0; int c,d; char *s; lua_Object lo = lua_getparam(1); if (!lua_isstring(lo)) d = EOF; else d = *lua_getstring(lo); s = (char *)malloc(n+1); while((c = fgetc(in)) != EOF && c != d) { if (m==n) { n *= 2; s = (char *)realloc(s, n+1); } s[m++] = c; } if (c != EOF) ungetc(c,in); s[m] = 0; lua_pushstring(s); free(s); } /* ** 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 char *buildformat (char *e, lua_Object o) { static char buffer[2048]; static char f[80]; char *string = &buffer[255]; char *fstart=e, *fspace, *send; char t, j='r'; int m=0, n=-1, l; while (isspace(*e)) e++; fspace = e; t = *e++; if (*e == '<' || *e == '|' || *e == '>') j = *e++; while (isdigit(*e)) m = m*10 + (*e++ - '0'); if (*e == '.') e++; /* skip point */ while (isdigit(*e)) if (n < 0) n = (*e++ - '0'); else n = n*10 + (*e++ - '0'); sprintf(f,"%%"); if (j == '<' || j == '|') sprintf(strchr(f,0),"-"); if (m > 0) sprintf(strchr(f,0),"%d", m); if (n >= 0) sprintf(strchr(f,0),".%d", n); switch (t) { case 'i': case 'I': t = 'd'; sprintf(strchr(f,0), "%c", t); sprintf (string, f, (long int)lua_getnumber(o)); break; case 'f': case 'g': case 'e': case 'G': case 'E': sprintf(strchr(f,0), "%c", t); sprintf (string, f, (float)lua_getnumber(o)); break; case 'F': t = 'f'; sprintf(strchr(f,0), "%c", t); sprintf (string, f, (float)lua_getnumber(o)); break; case 's': case 'S': t = 's'; sprintf(strchr(f,0), "%c", t); sprintf (string, f, lua_getstring(o)); break; default: return ""; } l = strlen(string); send = string+l; if (m!=0 && l>m) { int i; for (i=0; itm_hour); lua_pushnumber(s->tm_min); lua_pushnumber(s->tm_sec); } /* ** Return date: dd, mm, yyyy */ static void io_date (void) { time_t t; struct tm *s; time(&t); s = localtime(&t); lua_pushnumber(s->tm_mday); lua_pushnumber(s->tm_mon+1); lua_pushnumber(s->tm_year+1900); } /* ** Beep */ static void io_beep (void) { printf("\a"); } /* ** To exit */ static void io_exit (void) { lua_Object o = lua_getparam(1); if (lua_isstring(o)) fprintf(stderr, "%s\n", lua_getstring(o)); exit(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) { char buffer[250]; fprintf(stderr, "lua_debug> "); if (gets(buffer) == 0) return; if (strcmp(buffer, "cont") == 0) return; lua_dostring(buffer); } } 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 (*getobjname(func, &name)) { case 'g': fprintf(f, "function %s", name); break; case 'f': fprintf(f, "fallback %s", 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); } /* ** Open io library */ void iolib_open (void) { lua_register ("readfrom", io_readfrom); lua_register ("writeto", io_writeto); lua_register ("appendto", io_appendto); lua_register ("read", io_read); lua_register ("readuntil",io_readuntil); lua_register ("write", io_write); lua_register ("execute", io_execute); lua_register ("remove", io_remove); lua_register ("getenv", io_getenv); lua_register ("time", io_time); lua_register ("date", io_date); lua_register ("beep", io_beep); lua_register ("exit", io_exit); lua_register ("debug", io_debug); lua_register ("print_stack", errorfb); lua_setfallback("error", errorfb); }