mirror of https://github.com/lua/lua
615 lines
11 KiB
C
615 lines
11 KiB
C
/*
|
|
** iolib.c
|
|
** Input/output library to LUA
|
|
*/
|
|
|
|
char *rcs_iolib="$Id: iolib.c,v 1.15 1994/11/13 14:54:18 roberto Exp roberto $";
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <sys/stat.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "mem.h"
|
|
#include "lua.h"
|
|
#include "lualib.h"
|
|
|
|
static FILE *in=stdin, *out=stdout;
|
|
|
|
/*
|
|
** Open a file to read.
|
|
** LUA interface:
|
|
** status = readfrom (filename)
|
|
** where:
|
|
** status = 1 -> success
|
|
** status = 0 -> error
|
|
*/
|
|
static void io_readfrom (void)
|
|
{
|
|
lua_Object o = lua_getparam (1);
|
|
if (o == NULL) /* restore standart input */
|
|
{
|
|
if (in != stdin)
|
|
{
|
|
fclose (in);
|
|
in = stdin;
|
|
}
|
|
lua_pushnumber (1);
|
|
}
|
|
else
|
|
{
|
|
if (!lua_isstring (o))
|
|
{
|
|
lua_error ("incorrect argument to function 'readfrom`");
|
|
lua_pushnumber (0);
|
|
}
|
|
else
|
|
{
|
|
FILE *fp = fopen (lua_getstring(o),"r");
|
|
if (fp == NULL)
|
|
{
|
|
lua_pushnumber (0);
|
|
}
|
|
else
|
|
{
|
|
if (in != stdin) fclose (in);
|
|
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)
|
|
{
|
|
lua_Object o = lua_getparam (1);
|
|
if (o == NULL) /* restore standart output */
|
|
{
|
|
if (out != stdout)
|
|
{
|
|
fclose (out);
|
|
out = stdout;
|
|
}
|
|
lua_pushnumber (1);
|
|
}
|
|
else
|
|
{
|
|
if (!lua_isstring (o))
|
|
{
|
|
lua_error ("incorrect argument to function 'writeto`");
|
|
lua_pushnumber (0);
|
|
}
|
|
else
|
|
{
|
|
FILE *fp = fopen (lua_getstring(o),"w");
|
|
if (fp == NULL)
|
|
{
|
|
lua_pushnumber (0);
|
|
}
|
|
else
|
|
{
|
|
if (out != stdout) fclose (out);
|
|
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)
|
|
{
|
|
lua_Object o = lua_getparam (1);
|
|
if (o == NULL) /* restore standart output */
|
|
{
|
|
if (out != stdout)
|
|
{
|
|
fclose (out);
|
|
out = stdout;
|
|
}
|
|
lua_pushnumber (1);
|
|
}
|
|
else
|
|
{
|
|
if (!lua_isstring (o))
|
|
{
|
|
lua_error ("incorrect argument to function 'appendto`");
|
|
lua_pushnumber (0);
|
|
}
|
|
else
|
|
{
|
|
int r;
|
|
FILE *fp;
|
|
struct stat st;
|
|
if (stat(lua_getstring(o), &st) == -1) r = 1;
|
|
else r = 2;
|
|
fp = fopen (lua_getstring(o),"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 == NULL || !lua_isstring(o)) /* free format */
|
|
{
|
|
int c;
|
|
char s[256];
|
|
while (isspace(c=fgetc(in)))
|
|
;
|
|
if (c == '\"')
|
|
{
|
|
int n=0;
|
|
while((c = fgetc(in)) != '\"')
|
|
{
|
|
if (c == EOF)
|
|
{
|
|
lua_pushnil ();
|
|
return;
|
|
}
|
|
s[n++] = c;
|
|
}
|
|
s[n] = 0;
|
|
}
|
|
else if (c == '\'')
|
|
{
|
|
int n=0;
|
|
while((c = fgetc(in)) != '\'')
|
|
{
|
|
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 = lua_getstring(o);
|
|
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, 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 = newvector(n+1, char);
|
|
while((c = fgetc(in)) != EOF && c != d)
|
|
{
|
|
if (m==n)
|
|
{
|
|
n *= 2;
|
|
s = growvector(s, n+1, char);
|
|
}
|
|
s[m++] = c;
|
|
}
|
|
if (c != EOF) ungetc(c,in);
|
|
s[m] = 0;
|
|
lua_pushstring(s);
|
|
luaI_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))
|
|
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; i<m; i++)
|
|
string[i] = '*';
|
|
string[i] = 0;
|
|
}
|
|
else if (m!=0 && j=='|')
|
|
{
|
|
int k;
|
|
int i=l-1;
|
|
while (isspace(string[i]) || string[i]==0) i--;
|
|
string -= (m-i)/2;
|
|
for(k=0; k<(m-i)/2; k++)
|
|
string[k] = ' ';
|
|
}
|
|
/* add space characteres */
|
|
while (fspace != fstart)
|
|
{
|
|
string--;
|
|
fspace--;
|
|
*string = *fspace;
|
|
}
|
|
while (isspace(*e)) *send++ = *e++;
|
|
*send = 0;
|
|
return string;
|
|
}
|
|
static void io_write (void)
|
|
{
|
|
lua_Object o1 = lua_getparam (1);
|
|
lua_Object o2 = lua_getparam (2);
|
|
if (o1 == NULL) /* new line */
|
|
{
|
|
fprintf (out, "\n");
|
|
lua_pushnumber(1);
|
|
}
|
|
else if (o2 == NULL) /* free format */
|
|
{
|
|
int status=0;
|
|
if (lua_isnumber(o1))
|
|
status = fprintf (out, "%g", lua_getnumber(o1));
|
|
else if (lua_isstring(o1))
|
|
status = fprintf (out, "%s", lua_getstring(o1));
|
|
lua_pushnumber(status);
|
|
}
|
|
else /* formated */
|
|
{
|
|
if (!lua_isstring(o2))
|
|
{
|
|
lua_error ("incorrect format to function `write'");
|
|
lua_pushnumber(0);
|
|
return;
|
|
}
|
|
lua_pushnumber(fprintf (out, "%s", buildformat(lua_getstring(o2),o1)));
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Execute a executable program using "system".
|
|
** Return the result of execution.
|
|
*/
|
|
static void io_execute (void)
|
|
{
|
|
lua_Object o = lua_getparam (1);
|
|
if (o == NULL || !lua_isstring (o))
|
|
{
|
|
lua_error ("incorrect argument to function 'execute`");
|
|
lua_pushnumber (0);
|
|
}
|
|
else
|
|
{
|
|
int res = system(lua_getstring(o));
|
|
lua_pushnumber (res);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
** Remove a file.
|
|
** On error put 0 on stack, otherwise put 1.
|
|
*/
|
|
static void io_remove (void)
|
|
{
|
|
lua_Object o = lua_getparam (1);
|
|
if (o == NULL || !lua_isstring (o))
|
|
{
|
|
lua_error ("incorrect argument to function 'execute`");
|
|
lua_pushnumber (0);
|
|
}
|
|
else
|
|
{
|
|
if (remove(lua_getstring(o)) == 0)
|
|
lua_pushnumber (1);
|
|
else
|
|
lua_pushnumber (0);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
** To get a environment variables
|
|
*/
|
|
static void io_getenv (void)
|
|
{
|
|
lua_Object s = lua_getparam(1);
|
|
if (!lua_isstring(s))
|
|
lua_pushnil();
|
|
else
|
|
{
|
|
char *env = getenv(lua_getstring(s));
|
|
if (env == NULL) lua_pushnil();
|
|
else lua_pushstring(env);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Return time: hour, min, sec
|
|
*/
|
|
static void io_time (void)
|
|
{
|
|
time_t t;
|
|
struct tm *s;
|
|
|
|
time(&t);
|
|
s = localtime(&t);
|
|
lua_pushnumber(s->tm_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))
|
|
printf("%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];
|
|
printf("lua_debug> ");
|
|
if (gets(buffer) == 0) return;
|
|
if (strcmp(buffer, "cont") == 0) return;
|
|
lua_dostring(buffer);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** 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);
|
|
}
|