iup-stack/iup/srclua5/iuplua_scanf.c

198 lines
4.3 KiB
C
Raw Normal View History

2023-02-20 16:44:45 +00:00
/** \file
* \brief IUP binding for Lua 5.
* IupScanf special implementation.
*
* See Copyright Notice in "iup.h"
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lua.h>
#include <lauxlib.h>
#include "iup.h"
#include "iuplua.h"
#include "il.h"
#include "iup_str.h"
#include "iup_predialogs.h"
#define ALLOC(n,t) ((t *)calloc((n),sizeof(t)))
#define REQUIRE(b) {if (!(b)) goto cleanup;}
int iupluaScanf(lua_State *L)
{
char *format;
int i;
int fields;
int *width = NULL;
int *scroll = NULL;
char **prompt = NULL;
char **text = NULL;
char *title = NULL;
char *s = NULL;
char *s1 = NULL;
char *outf = NULL;
int indParam; /* va_list va; */
int total = 0;
format = (char*)luaL_checkstring(L, 1);
fields = iupStrCountChar(format, '\n') - 1;
REQUIRE(fields > 0);
width = ALLOC(fields, int);
REQUIRE(width != NULL);
scroll = ALLOC(fields, int);
REQUIRE(scroll != NULL);
prompt = ALLOC(fields, char *);
REQUIRE(prompt != NULL);
text = ALLOC(fields, char *);
REQUIRE(text != NULL);
indParam = 2; /* va_start(va,format); */
REQUIRE((s1 = s = (char *) iupStrDup(format)) != NULL);
title = iupStrDupUntil((const char**)&s, '\n');
REQUIRE(title != NULL);
for (i = 0; i < fields; ++i) {
int n;
prompt[i] = iupStrDupUntil((const char**)&s, '%');
REQUIRE(prompt[i] != NULL);
n = sscanf(s, "%d.%d", width + i, scroll + i);
REQUIRE(n == 2);
s = strchr(s, '%');
REQUIRE(s != NULL);
if (outf) free(outf);
outf = iupStrDupUntil((const char**)&s, '\n');
text[i] = ALLOC(width[i] + 1, char);
REQUIRE(text[i] != NULL);
switch (s[-2]) {
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X':
if (s[-3] == 'l')
sprintf(text[i], outf, (long)luaL_checkinteger(L, indParam++));
else if (s[-3] == 'h')
sprintf(text[i], outf, (short)luaL_checkinteger(L, indParam++));
else
sprintf(text[i], outf, (int)luaL_checkinteger(L, indParam++));
break;
case 'e':
case 'f':
case 'g':
case 'E':
case 'G':
if (s[-3] == 'l')
sprintf(text[i], outf, (double)luaL_checknumber(L, indParam++));
else
sprintf(text[i], outf, (float)luaL_checknumber(L, indParam++));
break;
case 's':
sprintf(text[i], outf, (char *)luaL_checkstring(L, indParam++));
break;
default:
goto cleanup;
}
}
/* va_end(va); */
REQUIRE(iupDataEntry(fields, width, scroll, title, prompt, text)>0);
/* va_start(va,format); */
s = strchr(format, '\n') + 1;
for (i = 0; i < fields; ++i) {
s = strchr(s, '\n') + 1;
switch (s[-2]) {
case 'd':
case 'u':
if (s[-3] == 'l') {
long l = 0;
sscanf(text[i], "%ld", &l);
lua_pushinteger(L, l);
total++;
} else if (s[-3] == 'h') {
short l = 0;
sscanf(text[i], "%hd", &l);
lua_pushinteger(L, l);
total++;
} else {
int l = 0;
sscanf(text[i], "%d", &l);
lua_pushinteger(L, l);
total++;
}
break;
case 'i':
case 'o':
case 'x':
case 'X':
if (s[-3] == 'l') {
long l = 0;
sscanf(text[i], "%li", &l);
lua_pushinteger(L, l);
total++;
} else if (s[-3] == 'h') {
short l = 0;
sscanf(text[i], "%hi", &l);
lua_pushinteger(L, l);
total++;
} else {
int l = 0;
sscanf(text[i], "%i", &l);
lua_pushinteger(L, l);
total++;
}
break;
case 'e':
case 'f':
case 'g':
case 'E':
case 'G':
if (s[-3] == 'l') {
double l = 0;
sscanf(text[i], "%lf", &l);
lua_pushnumber(L, l);
total++;
} else {
float l = 0;
sscanf(text[i], "%f", &l);
lua_pushnumber(L, l);
total++;
}
break;
case 's':
lua_pushstring(L, text[i]);
total++;
break;
}
}
/* va_end(va); */
cleanup:
if (s1) free(s1);
if (title) free(title);
if (width) free(width);
if (scroll) free(scroll);
if (outf) free(outf);
if (prompt)
{
for (i = 0; i < fields; ++i)
if (prompt[i]) free(prompt[i]);
free(prompt);
}
if (text)
{
for (i = 0; i < fields; ++i)
if (text[i]) free(text[i]);
free(text);
}
return total;
}