#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/time.h>
#ifndef WIN32
#include <signal.h>
#include <sys/stat.h>
#include <sys/select.h>
#endif

#ifdef USE_MATHLIB
#include <math.h>
#endif

#ifndef WIN32
#ifdef NLL_NETWORK_FUNCTION
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#else
#include <winsock2.h>
#ifdef NLL_NETWORK_FUNCTION
#include <ws2tcpip.h>
#endif
#endif

#ifdef USE_NLLIBC
#include <nllibc.h>
#endif

#include "const.h"
#include "nlltypes.h"
#include "nlllib.h"
#include "value.h"
#include "string.h"
#include "array.h"
#include "area.h"
#include "stack.h"
#include "nll.h"
#include "function.h"
#include "function-ext.h"
#include "libprintf.h"
#include "fileid.h"
#include "queueid.h"
#include "key.h"
#include "mouse.h"
#include "framebuf.h"
#include "graphic.h"
#include "audio.h"

static int function_fargs(value_t *valuep, value_t args);
static int function_copy(value_t *valuep, value_t args);
static int function_true(value_t *valuep, value_t args);
static int function_false(value_t *valuep, value_t args);
static int function_argnum(value_t *valuep, value_t args);
static int function_boolean(value_t *valuep, value_t args);
static int function_cond(value_t *valuep, value_t args);
static int function_at(value_t *valuep, value_t args);
static int function_fpush(value_t *valuep, value_t args);
static int function_fpop(value_t *valuep, value_t args);
static int function_stacknum(value_t *valuep, value_t args);
static int function_fprint(value_t *valuep, value_t args);
static int function_sprintf(value_t *valuep, value_t args);
static int function_printf(value_t *valuep, value_t args);
static int function_printm(value_t *valuep, value_t args);
static int function_input(value_t *valuep, value_t args);
static int function_inputn(value_t *valuep, value_t args);
static int function_fwait(value_t *valuep, value_t args);
static int function_timer(value_t *valuep, value_t args);
static int function_nosystem(value_t *valuep, value_t args);
static int function_nosyscall(value_t *valuep, value_t args);
static int function_nonetwork(value_t *valuep, value_t args);
#ifdef NLL_STDIO_FUNCTION
static int function_fstdin(value_t *valuep, value_t args);
static int function_fstdout(value_t *valuep, value_t args);
#endif
#ifdef NLL_SYSTEM_FUNCTION
static int function_system(value_t *valuep, value_t args);
#endif
#ifdef NLL_SYSCALL_FUNCTION
static int function_syscall(value_t *valuep, value_t args);
#endif
static int function_feval(value_t *valuep, value_t args);
static int function_fevalf(value_t *valuep, value_t args);
static int function_typeof(value_t *valuep, value_t args);
static int function_typename(value_t *valuep, value_t args);
static int function_sizeof(value_t *valuep, value_t args);
static int function_nzero(value_t *valuep, value_t args);
static int function_cmp(value_t *valuep, value_t args);
static int function_rep(value_t *valuep, value_t args);
static int function_insert(value_t *valuep, value_t args);
static int function_delete(value_t *valuep, value_t args);
static int function_itoc(value_t *valuep, value_t args);
static int function_ctoi(value_t *valuep, value_t args);
static int function_itoa(value_t *valuep, value_t args);
static int function_atoi(value_t *valuep, value_t args);
#ifdef NLL_FLOATING_POINT
static int function_itof(value_t *valuep, value_t args);
static int function_ftoi(value_t *valuep, value_t args);
static int function_atof(value_t *valuep, value_t args);
static int function_ftoa(value_t *valuep, value_t args);
#endif
static int function_isalnum(value_t *valuep, value_t args);
static int function_isalpha(value_t *valuep, value_t args);
static int function_isascii(value_t *valuep, value_t args);
static int function_iscntrl(value_t *valuep, value_t args);
static int function_isdigit(value_t *valuep, value_t args);
static int function_isgraph(value_t *valuep, value_t args);
static int function_islower(value_t *valuep, value_t args);
static int function_isprint(value_t *valuep, value_t args);
static int function_ispunct(value_t *valuep, value_t args);
static int function_isspace(value_t *valuep, value_t args);
static int function_isupper(value_t *valuep, value_t args);
static int function_isxdigit(value_t *valuep, value_t args);
static int function_tolower(value_t *valuep, value_t args);
static int function_toupper(value_t *valuep, value_t args);
static int function_left(value_t *valuep, value_t args);
static int function_right(value_t *valuep, value_t args);
static int function_mid(value_t *valuep, value_t args);
static int function_instr(value_t *valuep, value_t args);
static int function_strlen(value_t *valuep, value_t args);
static int function_strcpy(value_t *valuep, value_t args);
static int function_split(value_t *valuep, value_t args);
static int function_splits(value_t *valuep, value_t args);
static int function_chomp(value_t *valuep, value_t args);
static int function_lchomp(value_t *valuep, value_t args);
static int function_rchomp(value_t *valuep, value_t args);
static int function_srand(value_t *valuep, value_t args);
static int function_rand(value_t *valuep, value_t args);
static int function_int(value_t *valuep, value_t args);
static int function_abs(value_t *valuep, value_t args);
static int function_sign(value_t *valuep, value_t args);
static int function_max(value_t *valuep, value_t args);
static int function_min(value_t *valuep, value_t args);
static int function_abs2sum(value_t *valuep, value_t args);
static int function_time(value_t *valuep, value_t args);
static int function_date(value_t *valuep, value_t args);
static int function_fdim(value_t *valuep, value_t args);
static int function_fmemory(value_t *valuep, value_t args);
static int function_peek(value_t *valuep, value_t args);
static int function_poke(value_t *valuep, value_t args);
static int function_mread(value_t *valuep, value_t args);
static int function_mwrite(value_t *valuep, value_t args);
static int function_mcopy(value_t *valuep, value_t args);
#ifdef USE_MATHLIB
static int function_pi(value_t *valuep, value_t args);
static int function_radian(value_t *valuep, value_t args);
static int function_degree(value_t *valuep, value_t args);
static int function_sin(value_t *valuep, value_t args);
static int function_cos(value_t *valuep, value_t args);
static int function_tan(value_t *valuep, value_t args);
static int function_asin(value_t *valuep, value_t args);
static int function_acos(value_t *valuep, value_t args);
static int function_atan(value_t *valuep, value_t args);
static int function_sinh(value_t *valuep, value_t args);
static int function_cosh(value_t *valuep, value_t args);
static int function_tanh(value_t *valuep, value_t args);
static int function_exp(value_t *valuep, value_t args);
static int function_log(value_t *valuep, value_t args);
static int function_log10(value_t *valuep, value_t args);
static int function_sqrt(value_t *valuep, value_t args);
static int function_atan2(value_t *valuep, value_t args);
static int function_pow(value_t *valuep, value_t args);
static int function_fmod(value_t *valuep, value_t args);
static int function_infinity(value_t *valuep, value_t args);
static int function_nan(value_t *valuep, value_t args);
static int function_isfinite(value_t *valuep, value_t args);
static int function_isinf(value_t *valuep, value_t args);
static int function_isnan(value_t *valuep, value_t args);
static int function_isnormal(value_t *valuep, value_t args);
#endif
static int function_rename(value_t *valuep, value_t args);
static int function_unlink(value_t *valuep, value_t args);
static int function_truncate(value_t *valuep, value_t args);
static int function_mkdir(value_t *valuep, value_t args);
static int function_rmdir(value_t *valuep, value_t args);
static int function_chdir(value_t *valuep, value_t args);
static int function_open(value_t *valuep, value_t args);
static int function_close(value_t *valuep, value_t args);
static int function_read(value_t *valuep, value_t args);
static int function_write(value_t *valuep, value_t args);
static int function_lseek(value_t *valuep, value_t args);
static int function_ftruncate(value_t *valuep, value_t args);
static int function_isreadable(value_t *valuep, value_t args);
static int function_iswritable(value_t *valuep, value_t args);
static int function_fopen(value_t *valuep, value_t args);
static int function_fdopen(value_t *valuep, value_t args);
static int function_fclose(value_t *valuep, value_t args);
static int function_fileno(value_t *valuep, value_t args);
static int function_feof(value_t *valuep, value_t args);
static int function_ferror(value_t *valuep, value_t args);
static int function_fgetc(value_t *valuep, value_t args);
static int function_fputc(value_t *valuep, value_t args);
static int function_fgets(value_t *valuep, value_t args);
static int function_fputs(value_t *valuep, value_t args);
static int function_fprintf(value_t *valuep, value_t args);
static int function_fread(value_t *valuep, value_t args);
static int function_fwrite(value_t *valuep, value_t args);
static int function_fseek(value_t *valuep, value_t args);
static int function_qopen(value_t *valuep, value_t args);
static int function_qclose(value_t *valuep, value_t args);
static int function_qlength(value_t *valuep, value_t args);
static int function_qpushf(value_t *valuep, value_t args);
static int function_qpopl(value_t *valuep, value_t args);
static int function_qpushl(value_t *valuep, value_t args);
static int function_qpopf(value_t *valuep, value_t args);
#ifdef NLL_NETWORK_FUNCTION
static int function_sockaddr(value_t *valuep, value_t args);
static int function_socket(value_t *valuep, value_t args);
static int function_bind(value_t *valuep, value_t args);
static int function_listen(value_t *valuep, value_t args);
static int function_accept(value_t *valuep, value_t args);
static int function_connect(value_t *valuep, value_t args);
static int function_shutdown(value_t *valuep, value_t args);
static int function_recv(value_t *valuep, value_t args);
static int function_send(value_t *valuep, value_t args);
static int function_recvfrom(value_t *valuep, value_t args);
static int function_sendto(value_t *valuep, value_t args);
#endif
static int function_keyname(value_t *valuep, value_t args);
static int function_keycode(value_t *valuep, value_t args);
static int function_screen(value_t *valuep, value_t args);
static int function_scrstat(value_t *valuep, value_t args);
static int function_flush(value_t *valuep, value_t args);
static int function_getcolor(value_t *valuep, value_t args);
static int function_getfgcolor(value_t *valuep, value_t args);
static int function_getbgcolor(value_t *valuep, value_t args);
static int function_setcolor(value_t *valuep, value_t args);
static int function_getattr(value_t *valuep, value_t args);
static int function_setattr(value_t *valuep, value_t args);
static int function_getpos(value_t *valuep, value_t args);
static int function_move(value_t *valuep, value_t args);
static int function_getch(value_t *valuep, value_t args);
static int function_clear(value_t *valuep, value_t args);
static int function_scroll(value_t *valuep, value_t args);
static int function_line(value_t *valuep, value_t args);
static int function_box(value_t *valuep, value_t args);
static int function_inkey(value_t *valuep, value_t args);
static int function_gscreen(value_t *valuep, value_t args);
static int function_gscrstat(value_t *valuep, value_t args);
static int function_gcolor(value_t *valuep, value_t args);
static int function_grgb(value_t *valuep, value_t args);
static int function_gsync(value_t *valuep, value_t args);
static int function_gflush(value_t *valuep, value_t args);
static int function_ggetmainimg(value_t *valuep, value_t args);
static int function_gsetmainimg(value_t *valuep, value_t args);
static int function_ggetsize(value_t *valuep, value_t args);
static int function_ggetrange(value_t *valuep, value_t args);
static int function_gsetrange(value_t *valuep, value_t args);
static int function_ggetoffset(value_t *valuep, value_t args);
static int function_gsetoffset(value_t *valuep, value_t args);
static int function_ggetscale(value_t *valuep, value_t args);
static int function_gsetscale(value_t *valuep, value_t args);
static int function_ggetdotoffset(value_t *valuep, value_t args);
static int function_gsetdotoffset(value_t *valuep, value_t args);
static int function_ggetdotsize(value_t *valuep, value_t args);
static int function_gsetdotsize(value_t *valuep, value_t args);
static int function_ggetcolor(value_t *valuep, value_t args);
static int function_gsetcolor(value_t *valuep, value_t args);
static int function_ggetpixel(value_t *valuep, value_t args);
static int function_gclear(value_t *valuep, value_t args);
static int function_gscroll(value_t *valuep, value_t args);
static int function_gdot(value_t *valuep, value_t args);
static int function_gline(value_t *valuep, value_t args);
static int function_gbox(value_t *valuep, value_t args);
static int function_gcircle(value_t *valuep, value_t args);
static int function_gpaint(value_t *valuep, value_t args);
static int function_gcopy(value_t *valuep, value_t args);
static int function_grotate(value_t *valuep, value_t args);
static int function_gchar(value_t *valuep, value_t args);
static int function_gprint(value_t *valuep, value_t args);
static int function_ginkey(value_t *valuep, value_t args);
static int function_gkeystat(value_t *valuep, value_t args);
static int function_gmousepos(value_t *valuep, value_t args);
static int function_ginmouse(value_t *valuep, value_t args);
static int function_gmousestat(value_t *valuep, value_t args);
static int function_gallocimage(value_t *valuep, value_t args);
static int function_gfreeimage(value_t *valuep, value_t args);
static int function_gloadimage(value_t *valuep, value_t args);
static int function_gsaveimage(value_t *valuep, value_t args);
static int function_gcmpimage(value_t *valuep, value_t args);
static int function_gcharset(value_t *valuep, value_t args);
static int function_astop(value_t *valuep, value_t args);
static int function_aclear(value_t *valuep, value_t args);
static int function_asound(value_t *valuep, value_t args);
static int function_asndstat(value_t *valuep, value_t args);
static int function_aplaynum(value_t *valuep, value_t args);
static int function_await(value_t *valuep, value_t args);
static int function_aunitset(value_t *valuep, value_t args);
static int function_aunit(value_t *valuep, value_t args);
static int function_aosc(value_t *valuep, value_t args);
static int function_aaddout(value_t *valuep, value_t args);
static int function_aenvpoint(value_t *valuep, value_t args);
static int function_aenvcopy(value_t *valuep, value_t args);
static int function_afilpoint(value_t *valuep, value_t args);
static int function_afilcopy(value_t *valuep, value_t args);
static int function_aplay(value_t *valuep, value_t args);
static int function_aopen(value_t *valuep, value_t args);
static int function_aclose(value_t *valuep, value_t args);

static const struct function functions_orig[] = {
  { "FARGS"      , "VALUE"  , FUNCTION_TYPE_FARGS      , function_fargs      , FUNCTION_FLAG_FIXED },
  { "COPY"       , NULL     , FUNCTION_TYPE_COPY       , function_copy       , FUNCTION_FLAG_FIXED },
  { "TRUE"       , NULL     , FUNCTION_TYPE_TRUE       , function_true       , FUNCTION_FLAG_FIXED },
  { "FALSE"      , NULL     , FUNCTION_TYPE_FALSE      , function_false      , FUNCTION_FLAG_FIXED },
  { "ARGNUM"     , NULL     , FUNCTION_TYPE_ARGNUM     , function_argnum     , FUNCTION_FLAG_FIXED },
  { "BOOLEAN"    , NULL     , FUNCTION_TYPE_BOOLEAN    , function_boolean    , FUNCTION_FLAG_FIXED },
  { "COND"       , NULL     , FUNCTION_TYPE_COND       , function_cond       , FUNCTION_FLAG_FIXED },
  { "AT"         , NULL     , FUNCTION_TYPE_AT         , function_at         , FUNCTION_FLAG_FIXED },
  { "FPUSH"      , "LOCAL"  , FUNCTION_TYPE_FPUSH      , function_fpush      , 0 },
  { "FPOP"       , "RESTORE", FUNCTION_TYPE_FPOP       , function_fpop       , 0 },
  { "STACKNUM"   , NULL     , FUNCTION_TYPE_STACKNUM   , function_stacknum   , 0 },
  { "FPRINT"     , NULL     , FUNCTION_TYPE_FPRINT     , function_fprint     , 0 },
  { "SPRINTF"    , NULL     , FUNCTION_TYPE_SPRINTF    , function_sprintf    , 0 },
  { "PRINTF"     , NULL     , FUNCTION_TYPE_PRINTF     , function_printf     , 0 },
  { "PRINTM"     , NULL     , FUNCTION_TYPE_PRINTM     , function_printm     , 0 },
  { "INPUT"      , NULL     , FUNCTION_TYPE_INPUT      , function_input      , 0 },
  { "INPUTN"     , NULL     , FUNCTION_TYPE_INPUTN     , function_inputn     , 0 },
  { "FWAIT"      , NULL     , FUNCTION_TYPE_FWAIT      , function_fwait      , 0 },
  { "TIMER"      , NULL     , FUNCTION_TYPE_TIMER      , function_timer      , 0 },
  { "NOSYSTEM"   , NULL     , FUNCTION_TYPE_NOSYSTEM   , function_nosystem   , 0 },
  { "NOSYSCALL"  , NULL     , FUNCTION_TYPE_NOSYSCALL  , function_nosyscall  , 0 },
  { "NONETWORK"  , NULL     , FUNCTION_TYPE_NONETWORK  , function_nonetwork  , 0 },
#ifdef NLL_STDIO_FUNCTION
  { "FSTDIN"     , NULL     , FUNCTION_TYPE_FSTDIN     , function_fstdin     , 0 },
  { "FSTDOUT"    , NULL     , FUNCTION_TYPE_FSTDOUT    , function_fstdout    , 0 },
#endif
#ifdef NLL_SYSTEM_FUNCTION
  { "SYSTEM"     , NULL     , FUNCTION_TYPE_SYSTEM     , function_system     , 0 },
#endif
#ifdef NLL_SYSCALL_FUNCTION
  { "SYSCALL"    , NULL     , FUNCTION_TYPE_SYSCALL    , function_syscall    , 0 },
#endif
  { "FEVAL"      , NULL     , FUNCTION_TYPE_FEVAL      , function_feval      , 0 },
  { "FEVALF"     , NULL     , FUNCTION_TYPE_FEVALF     , function_fevalf     , 0 },
  { "TYPEOF"     , NULL     , FUNCTION_TYPE_TYPEOF     , function_typeof     , FUNCTION_FLAG_FIXED },
  { "TYPENAME"   , NULL     , FUNCTION_TYPE_TYPENAME   , function_typename   , FUNCTION_FLAG_FIXED },
  { "SIZEOF"     , NULL     , FUNCTION_TYPE_SIZEOF     , function_sizeof     , FUNCTION_FLAG_FIXED },
  { "NZERO"      , NULL     , FUNCTION_TYPE_NZERO      , function_nzero      , FUNCTION_FLAG_FIXED },
  { "CMP"        , NULL     , FUNCTION_TYPE_CMP        , function_cmp        , FUNCTION_FLAG_FIXED },
  { "REP"        , NULL     , FUNCTION_TYPE_REP        , function_rep        , FUNCTION_FLAG_FIXED },
  { "INSERT"     , NULL     , FUNCTION_TYPE_INSERT     , function_insert     , FUNCTION_FLAG_FIXED },
  { "DELETE"     , NULL     , FUNCTION_TYPE_DELETE     , function_delete     , FUNCTION_FLAG_FIXED },
  { "ITOC"       , "CHAR"   , FUNCTION_TYPE_ITOC       , function_itoc       , FUNCTION_FLAG_FIXED },
  { "CTOI"       , "ASCII"  , FUNCTION_TYPE_CTOI       , function_ctoi       , FUNCTION_FLAG_FIXED },
  { "ITOA"       , "STR"    , FUNCTION_TYPE_ITOA       , function_itoa       , FUNCTION_FLAG_FIXED },
  { "ATOI"       , "VAL"    , FUNCTION_TYPE_ATOI       , function_atoi       , FUNCTION_FLAG_FIXED },
#ifdef NLL_FLOATING_POINT
  { "ITOF"       , NULL     , FUNCTION_TYPE_ITOF       , function_itof       , FUNCTION_FLAG_FIXED },
  { "FTOI"       , NULL     , FUNCTION_TYPE_FTOI       , function_ftoi       , FUNCTION_FLAG_FIXED },
  { "ATOF"       , NULL     , FUNCTION_TYPE_ATOF       , function_atof       , FUNCTION_FLAG_FIXED },
  { "FTOA"       , NULL     , FUNCTION_TYPE_FTOA       , function_ftoa       , FUNCTION_FLAG_FIXED },
#endif
  { "ISALNUM"    , NULL     , FUNCTION_TYPE_ISALNUM    , function_isalnum    , FUNCTION_FLAG_FIXED },
  { "ISALPHA"    , NULL     , FUNCTION_TYPE_ISALPHA    , function_isalpha    , FUNCTION_FLAG_FIXED },
  { "ISASCII"    , NULL     , FUNCTION_TYPE_ISASCII    , function_isascii    , FUNCTION_FLAG_FIXED },
  { "ISCNTRL"    , NULL     , FUNCTION_TYPE_ISCNTRL    , function_iscntrl    , FUNCTION_FLAG_FIXED },
  { "ISDIGIT"    , NULL     , FUNCTION_TYPE_ISDIGIT    , function_isdigit    , FUNCTION_FLAG_FIXED },
  { "ISGRAPH"    , NULL     , FUNCTION_TYPE_ISGRAPH    , function_isgraph    , FUNCTION_FLAG_FIXED },
  { "ISLOWER"    , NULL     , FUNCTION_TYPE_ISLOWER    , function_islower    , FUNCTION_FLAG_FIXED },
  { "ISPRINT"    , NULL     , FUNCTION_TYPE_ISPRINT    , function_isprint    , FUNCTION_FLAG_FIXED },
  { "ISPUNCT"    , NULL     , FUNCTION_TYPE_ISPUNCT    , function_ispunct    , FUNCTION_FLAG_FIXED },
  { "ISSPACE"    , NULL     , FUNCTION_TYPE_ISSPACE    , function_isspace    , FUNCTION_FLAG_FIXED },
  { "ISUPPER"    , NULL     , FUNCTION_TYPE_ISUPPER    , function_isupper    , FUNCTION_FLAG_FIXED },
  { "ISXDIGIT"   , NULL     , FUNCTION_TYPE_ISXDIGIT   , function_isxdigit   , FUNCTION_FLAG_FIXED },
  { "TOLOWER"    , NULL     , FUNCTION_TYPE_TOLOWER    , function_tolower    , FUNCTION_FLAG_FIXED },
  { "TOUPPER"    , NULL     , FUNCTION_TYPE_TOUPPER    , function_toupper    , FUNCTION_FLAG_FIXED },
  { "LEFT"       , NULL     , FUNCTION_TYPE_LEFT       , function_left       , FUNCTION_FLAG_FIXED },
  { "RIGHT"      , NULL     , FUNCTION_TYPE_RIGHT      , function_right      , FUNCTION_FLAG_FIXED },
  { "MID"        , NULL     , FUNCTION_TYPE_MID        , function_mid        , FUNCTION_FLAG_FIXED },
  { "INSTR"      , NULL     , FUNCTION_TYPE_INSTR      , function_instr      , FUNCTION_FLAG_FIXED },
  { "STRLEN"     , NULL     , FUNCTION_TYPE_STRLEN     , function_strlen     , FUNCTION_FLAG_FIXED },
  { "STRCPY"     , NULL     , FUNCTION_TYPE_STRCPY     , function_strcpy     , FUNCTION_FLAG_FIXED },
  { "SPLIT"      , NULL     , FUNCTION_TYPE_SPLIT      , function_split      , FUNCTION_FLAG_FIXED },
  { "SPLITS"     , NULL     , FUNCTION_TYPE_SPLITS     , function_splits     , FUNCTION_FLAG_FIXED },
  { "CHOMP"      , NULL     , FUNCTION_TYPE_CHOMP      , function_chomp      , FUNCTION_FLAG_FIXED },
  { "LCHOMP"     , NULL     , FUNCTION_TYPE_LCHOMP     , function_lchomp     , FUNCTION_FLAG_FIXED },
  { "RCHOMP"     , NULL     , FUNCTION_TYPE_RCHOMP     , function_rchomp     , FUNCTION_FLAG_FIXED },
  { "SRAND"      , NULL     , FUNCTION_TYPE_SRAND      , function_srand      , 0 },
  { "RAND"       , "RND"    , FUNCTION_TYPE_RAND       , function_rand       , 0 },
  { "INT"        , NULL     , FUNCTION_TYPE_INT        , function_int        , FUNCTION_FLAG_FIXED },
  { "ABS"        , NULL     , FUNCTION_TYPE_ABS        , function_abs        , FUNCTION_FLAG_FIXED },
  { "SIGN"       , "SGN"    , FUNCTION_TYPE_SIGN       , function_sign       , FUNCTION_FLAG_FIXED },
  { "MAX"        , NULL     , FUNCTION_TYPE_MAX        , function_max        , FUNCTION_FLAG_FIXED },
  { "MIN"        , NULL     , FUNCTION_TYPE_MIN        , function_min        , FUNCTION_FLAG_FIXED },
  { "ABS2SUM"    , NULL     , FUNCTION_TYPE_ABS2SUM    , function_abs2sum    , FUNCTION_FLAG_FIXED },
  { "TIME"       , NULL     , FUNCTION_TYPE_TIME       , function_time       , 0 },
  { "DATE"       , NULL     , FUNCTION_TYPE_DATE       , function_date       , 0 },
  { "FDIM"       , NULL     , FUNCTION_TYPE_FDIM       , function_fdim       , 0 },
  { "FMEMORY"    , NULL     , FUNCTION_TYPE_FMEMORY    , function_fmemory    , 0 },
  { "PEEK"       , NULL     , FUNCTION_TYPE_PEEK       , function_peek       , 0 },
  { "POKE"       , NULL     , FUNCTION_TYPE_POKE       , function_poke       , 0 },
  { "MREAD"      , NULL     , FUNCTION_TYPE_MREAD      , function_mread      , 0 },
  { "MWRITE"     , NULL     , FUNCTION_TYPE_MWRITE     , function_mwrite     , 0 },
  { "MCOPY"      , "MEMCPY" , FUNCTION_TYPE_MCOPY      , function_mcopy      , 0 },
#ifdef USE_MATHLIB
  { "PI"         , NULL     , FUNCTION_TYPE_PI         , function_pi         , FUNCTION_FLAG_FIXED },
  { "RADIAN"     , NULL     , FUNCTION_TYPE_RADIAN     , function_radian     , FUNCTION_FLAG_FIXED },
  { "DEGREE"     , NULL     , FUNCTION_TYPE_DEGREE     , function_degree     , FUNCTION_FLAG_FIXED },
  { "SIN"        , NULL     , FUNCTION_TYPE_SIN        , function_sin        , FUNCTION_FLAG_FIXED },
  { "COS"        , NULL     , FUNCTION_TYPE_COS        , function_cos        , FUNCTION_FLAG_FIXED },
  { "TAN"        , NULL     , FUNCTION_TYPE_TAN        , function_tan        , FUNCTION_FLAG_FIXED },
  { "ASIN"       , NULL     , FUNCTION_TYPE_ASIN       , function_asin       , FUNCTION_FLAG_FIXED },
  { "ACOS"       , NULL     , FUNCTION_TYPE_ACOS       , function_acos       , FUNCTION_FLAG_FIXED },
  { "ATAN"       , NULL     , FUNCTION_TYPE_ATAN       , function_atan       , FUNCTION_FLAG_FIXED },
  { "SINH"       , NULL     , FUNCTION_TYPE_SINH       , function_sinh       , FUNCTION_FLAG_FIXED },
  { "COSH"       , NULL     , FUNCTION_TYPE_COSH       , function_cosh       , FUNCTION_FLAG_FIXED },
  { "TANH"       , NULL     , FUNCTION_TYPE_TANH       , function_tanh       , FUNCTION_FLAG_FIXED },
  { "EXP"        , NULL     , FUNCTION_TYPE_EXP        , function_exp        , FUNCTION_FLAG_FIXED },
  { "LOG"        , NULL     , FUNCTION_TYPE_LOG        , function_log        , FUNCTION_FLAG_FIXED },
  { "LOG10"      , NULL     , FUNCTION_TYPE_LOG10      , function_log10      , FUNCTION_FLAG_FIXED },
  { "SQRT"       , "SQR"    , FUNCTION_TYPE_SQRT       , function_sqrt       , FUNCTION_FLAG_FIXED },
  { "ATAN2"      , NULL     , FUNCTION_TYPE_ATAN2      , function_atan2      , FUNCTION_FLAG_FIXED },
  { "POW"        , NULL     , FUNCTION_TYPE_POW        , function_pow        , FUNCTION_FLAG_FIXED },
  { "FMOD"       , NULL     , FUNCTION_TYPE_FMOD       , function_fmod       , FUNCTION_FLAG_FIXED },
  { "INFINITY"   , "INF"    , FUNCTION_TYPE_INFINITY   , function_infinity   , FUNCTION_FLAG_FIXED },
  { "NAN"        , NULL     , FUNCTION_TYPE_NAN        , function_nan        , FUNCTION_FLAG_FIXED },
  { "ISFINITE"   , NULL     , FUNCTION_TYPE_ISFINITE   , function_isfinite   , FUNCTION_FLAG_FIXED },
  { "ISINF"      , NULL     , FUNCTION_TYPE_ISINF      , function_isinf      , FUNCTION_FLAG_FIXED },
  { "ISNAN"      , NULL     , FUNCTION_TYPE_ISNAN      , function_isnan      , FUNCTION_FLAG_FIXED },
  { "ISNORMAL"   , NULL     , FUNCTION_TYPE_ISNORMAL   , function_isnormal   , FUNCTION_FLAG_FIXED },
#endif
  { "RENAME"     , NULL     , FUNCTION_TYPE_RENAME     , function_rename     , 0 },
  { "UNLINK"     , NULL     , FUNCTION_TYPE_UNLINK     , function_unlink     , 0 },
  { "TRUNCATE"   , NULL     , FUNCTION_TYPE_TRUNCATE   , function_truncate   , 0 },
  { "MKDIR"      , NULL     , FUNCTION_TYPE_MKDIR      , function_mkdir      , 0 },
  { "RMDIR"      , NULL     , FUNCTION_TYPE_RMDIR      , function_rmdir      , 0 },
  { "CHDIR"      , NULL     , FUNCTION_TYPE_CHDIR      , function_chdir      , 0 },
  { "OPEN"       , NULL     , FUNCTION_TYPE_OPEN       , function_open       , 0 },
  { "CLOSE"      , NULL     , FUNCTION_TYPE_CLOSE      , function_close      , 0 },
  { "READ"       , NULL     , FUNCTION_TYPE_READ       , function_read       , 0 },
  { "WRITE"      , NULL     , FUNCTION_TYPE_WRITE      , function_write      , 0 },
  { "LSEEK"      , NULL     , FUNCTION_TYPE_LSEEK      , function_lseek      , 0 },
  { "FTRUNCATE"  , NULL     , FUNCTION_TYPE_FTRUNCATE  , function_ftruncate  , 0 },
  { "ISREADABLE" , NULL     , FUNCTION_TYPE_ISREADABLE , function_isreadable , 0 },
  { "ISWRITABLE" , NULL     , FUNCTION_TYPE_ISWRITABLE , function_iswritable , 0 },
  { "FOPEN"      , NULL     , FUNCTION_TYPE_FOPEN      , function_fopen      , 0 },
  { "FDOPEN"     , NULL     , FUNCTION_TYPE_FDOPEN     , function_fdopen     , 0 },
  { "FCLOSE"     , NULL     , FUNCTION_TYPE_FCLOSE     , function_fclose     , 0 },
  { "FILENO"     , NULL     , FUNCTION_TYPE_FILENO     , function_fileno     , 0 },
  { "FEOF"       , NULL     , FUNCTION_TYPE_FEOF       , function_feof       , 0 },
  { "FERROR"     , NULL     , FUNCTION_TYPE_FERROR     , function_ferror     , 0 },
  { "FGETC"      , NULL     , FUNCTION_TYPE_FGETC      , function_fgetc      , 0 },
  { "FPUTC"      , NULL     , FUNCTION_TYPE_FPUTC      , function_fputc      , 0 },
  { "FGETS"      , NULL     , FUNCTION_TYPE_FGETS      , function_fgets      , 0 },
  { "FPUTS"      , NULL     , FUNCTION_TYPE_FPUTS      , function_fputs      , 0 },
  { "FPRINTF"    , NULL     , FUNCTION_TYPE_FPRINTF    , function_fprintf    , 0 },
  { "FREAD"      , NULL     , FUNCTION_TYPE_FREAD      , function_fread      , 0 },
  { "FWRITE"     , NULL     , FUNCTION_TYPE_FWRITE     , function_fwrite     , 0 },
  { "FSEEK"      , NULL     , FUNCTION_TYPE_FSEEK      , function_fseek      , 0 },
  { "QOPEN"      , NULL     , FUNCTION_TYPE_QOPEN      , function_qopen      , 0 },
  { "QCLOSE"     , NULL     , FUNCTION_TYPE_QCLOSE     , function_qclose     , 0 },
  { "QLENGTH"    , "QLEN"   , FUNCTION_TYPE_QLENGTH    , function_qlength    , 0 },
  { "QPUSHF"     , "QPUSH"  , FUNCTION_TYPE_QPUSHF     , function_qpushf     , 0 },
  { "QPOPL"      , "QPOP"   , FUNCTION_TYPE_QPOPL      , function_qpopl      , 0 },
  { "QPUSHL"     , NULL     , FUNCTION_TYPE_QPUSHL     , function_qpushl     , 0 },
  { "QPOPF"      , NULL     , FUNCTION_TYPE_QPOPF      , function_qpopf      , 0 },
#ifdef NLL_NETWORK_FUNCTION
  { "SOCKADDR"   , NULL     , FUNCTION_TYPE_SOCKADDR   , function_sockaddr   , 0 },
  { "SOCKET"     , NULL     , FUNCTION_TYPE_SOCKET     , function_socket     , 0 },
  { "BIND"       , NULL     , FUNCTION_TYPE_BIND       , function_bind       , 0 },
  { "LISTEN"     , NULL     , FUNCTION_TYPE_LISTEN     , function_listen     , 0 },
  { "ACCEPT"     , NULL     , FUNCTION_TYPE_ACCEPT     , function_accept     , 0 },
  { "CONNECT"    , NULL     , FUNCTION_TYPE_CONNECT    , function_connect    , 0 },
  { "SHUTDOWN"   , NULL     , FUNCTION_TYPE_SHUTDOWN   , function_shutdown   , 0 },
  { "RECV"       , NULL     , FUNCTION_TYPE_RECV       , function_recv       , 0 },
  { "SEND"       , NULL     , FUNCTION_TYPE_SEND       , function_send       , 0 },
  { "RECVFROM"   , NULL     , FUNCTION_TYPE_RECVFROM   , function_recvfrom   , 0 },
  { "SENDTO"     , NULL     , FUNCTION_TYPE_SENDTO     , function_sendto     , 0 },
#endif
  { "KEYNAME"    , NULL     , FUNCTION_TYPE_KEYNAME    , function_keyname    , FUNCTION_FLAG_FIXED },
  { "KEYCODE"    , NULL     , FUNCTION_TYPE_KEYCODE    , function_keycode    , FUNCTION_FLAG_FIXED },
  { "SCREEN"     , NULL     , FUNCTION_TYPE_SCREEN     , function_screen     , 0 },
  { "SCRSTAT"    , NULL     , FUNCTION_TYPE_SCRSTAT    , function_scrstat    , 0 },
  { "FLUSH"      , NULL     , FUNCTION_TYPE_FLUSH      , function_flush      , 0 },
  { "GETCOLOR"   , NULL     , FUNCTION_TYPE_GETCOLOR   , function_getcolor   , 0 },
  { "GETFGCOLOR" , NULL     , FUNCTION_TYPE_GETFGCOLOR , function_getfgcolor , 0 },
  { "GETBGCOLOR" , NULL     , FUNCTION_TYPE_GETBGCOLOR , function_getbgcolor , 0 },
  { "SETCOLOR"   , NULL     , FUNCTION_TYPE_SETCOLOR   , function_setcolor   , 0 },
  { "GETATTR"    , NULL     , FUNCTION_TYPE_GETATTR    , function_getattr    , 0 },
  { "SETATTR"    , NULL     , FUNCTION_TYPE_SETATTR    , function_setattr    , 0 },
  { "GETPOS"     , NULL     , FUNCTION_TYPE_GETPOS     , function_getpos     , 0 },
  { "MOVE"       , NULL     , FUNCTION_TYPE_MOVE       , function_move       , 0 },
  { "GETCH"      , NULL     , FUNCTION_TYPE_GETCH      , function_getch      , 0 },
  { "CLEAR"      , NULL     , FUNCTION_TYPE_CLEAR      , function_clear      , 0 },
  { "SCROLL"     , NULL     , FUNCTION_TYPE_SCROLL     , function_scroll     , 0 },
  { "LINE"       , NULL     , FUNCTION_TYPE_LINE       , function_line       , 0 },
  { "BOX"        , NULL     , FUNCTION_TYPE_BOX        , function_box        , 0 },
  { "INKEY"      , "KEY"    , FUNCTION_TYPE_INKEY      , function_inkey      , 0 },
  { "GSCREEN"    , NULL     , FUNCTION_TYPE_GSCREEN    , function_gscreen    , 0 },
  { "GSCRSTAT"   , NULL     , FUNCTION_TYPE_GSCRSTAT   , function_gscrstat   , 0 },
  { "GCOLOR"     , NULL     , FUNCTION_TYPE_GCOLOR     , function_gcolor     , 0 },
  { "GRGB"       , NULL     , FUNCTION_TYPE_GRGB       , function_grgb       , 0 },
  { "GSYNC"      , NULL     , FUNCTION_TYPE_GSYNC      , function_gsync      , 0 },
  { "GFLUSH"     , NULL     , FUNCTION_TYPE_GFLUSH     , function_gflush     , 0 },
  { "GGETMAINIMG", NULL     , FUNCTION_TYPE_GGETMAINIMG, function_ggetmainimg, 0 },
  { "GSETMAINIMG", NULL     , FUNCTION_TYPE_GSETMAINIMG, function_gsetmainimg, 0 },
  { "GGETSIZE"   , NULL     , FUNCTION_TYPE_GGETSIZE   , function_ggetsize   , 0 },
  { "GGETRANGE"  , NULL     , FUNCTION_TYPE_GGETRANGE  , function_ggetrange  , 0 },
  { "GSETRANGE"  , NULL     , FUNCTION_TYPE_GSETRANGE  , function_gsetrange  , 0 },
  { "GGETOFFSET" , NULL     , FUNCTION_TYPE_GGETOFFSET , function_ggetoffset , 0 },
  { "GSETOFFSET" , NULL     , FUNCTION_TYPE_GSETOFFSET , function_gsetoffset , 0 },
  { "GGETSCALE"  , NULL     , FUNCTION_TYPE_GGETSCALE  , function_ggetscale  , 0 },
  { "GSETSCALE"  , NULL     , FUNCTION_TYPE_GSETSCALE  , function_gsetscale  , 0 },
  { "GGETDOTOFFSET", NULL   , FUNCTION_TYPE_GGETDOTOFFSET, function_ggetdotoffset, 0 },
  { "GSETDOTOFFSET", NULL   , FUNCTION_TYPE_GSETDOTOFFSET, function_gsetdotoffset, 0 },
  { "GGETDOTSIZE", NULL     , FUNCTION_TYPE_GGETDOTSIZE, function_ggetdotsize, 0 },
  { "GSETDOTSIZE", NULL     , FUNCTION_TYPE_GSETDOTSIZE, function_gsetdotsize, 0 },
  { "GGETCOLOR"  , NULL     , FUNCTION_TYPE_GGETCOLOR  , function_ggetcolor  , 0 },
  { "GSETCOLOR"  , NULL     , FUNCTION_TYPE_GSETCOLOR  , function_gsetcolor  , 0 },
  { "GGETPIXEL"  , NULL     , FUNCTION_TYPE_GGETPIXEL  , function_ggetpixel  , 0 },
  { "GCLEAR"     , NULL     , FUNCTION_TYPE_GCLEAR     , function_gclear     , 0 },
  { "GSCROLL"    , NULL     , FUNCTION_TYPE_GSCROLL    , function_gscroll    , 0 },
  { "GDOT"       , "GPOINT" , FUNCTION_TYPE_GDOT       , function_gdot       , 0 },
  { "GLINE"      , NULL     , FUNCTION_TYPE_GLINE      , function_gline      , 0 },
  { "GBOX"       , NULL     , FUNCTION_TYPE_GBOX       , function_gbox       , 0 },
  { "GCIRCLE"    , NULL     , FUNCTION_TYPE_GCIRCLE    , function_gcircle    , 0 },
  { "GPAINT"     , NULL     , FUNCTION_TYPE_GPAINT     , function_gpaint     , 0 },
  { "GCOPY"      , NULL     , FUNCTION_TYPE_GCOPY      , function_gcopy      , 0 },
  { "GROTATE"    , NULL     , FUNCTION_TYPE_GROTATE    , function_grotate    , 0 },
  { "GCHAR"      , NULL     , FUNCTION_TYPE_GCHAR      , function_gchar      , 0 },
  { "GPRINT"     , NULL     , FUNCTION_TYPE_GPRINT     , function_gprint     , 0 },
  { "GINKEY"     , "GKEY"   , FUNCTION_TYPE_GINKEY     , function_ginkey     , 0 },
  { "GKEYSTAT"   , NULL     , FUNCTION_TYPE_GKEYSTAT   , function_gkeystat   , 0 },
  { "GMOUSEPOS"  , NULL     , FUNCTION_TYPE_GMOUSEPOS  , function_gmousepos  , 0 },
  { "GINMOUSE"   , NULL     , FUNCTION_TYPE_GINMOUSE   , function_ginmouse   , 0 },
  { "GMOUSESTAT" , NULL     , FUNCTION_TYPE_GMOUSESTAT , function_gmousestat , 0 },
  { "GALLOCIMAGE", NULL     , FUNCTION_TYPE_GALLOCIMAGE, function_gallocimage, 0 },
  { "GFREEIMAGE" , NULL     , FUNCTION_TYPE_GFREEIMAGE , function_gfreeimage , 0 },
  { "GLOADIMAGE" , NULL     , FUNCTION_TYPE_GLOADIMAGE , function_gloadimage , 0 },
  { "GSAVEIMAGE" , NULL     , FUNCTION_TYPE_GSAVEIMAGE , function_gsaveimage , 0 },
  { "GCMPIMAGE"  , NULL     , FUNCTION_TYPE_GCMPIMAGE  , function_gcmpimage  , 0 },
  { "GCHARSET"   , NULL     , FUNCTION_TYPE_GCHARSET   , function_gcharset   , 0 },
  { "ASTOP"      , NULL     , FUNCTION_TYPE_ASTOP      , function_astop      , 0 },
  { "ACLEAR"     , NULL     , FUNCTION_TYPE_ACLEAR     , function_aclear     , 0 },
  { "ASOUND"     , NULL     , FUNCTION_TYPE_ASOUND     , function_asound     , 0 },
  { "ASNDSTAT"   , NULL     , FUNCTION_TYPE_ASNDSTAT   , function_asndstat   , 0 },
  { "APLAYNUM"   , NULL     , FUNCTION_TYPE_APLAYNUM   , function_aplaynum   , 0 },
  { "AWAIT"      , NULL     , FUNCTION_TYPE_AWAIT      , function_await      , 0 },
  { "AUNITSET"   , NULL     , FUNCTION_TYPE_AUNITSET   , function_aunitset   , 0 },
  { "AUNIT"      , NULL     , FUNCTION_TYPE_AUNIT      , function_aunit      , 0 },
  { "AOSC"       , NULL     , FUNCTION_TYPE_AOSC       , function_aosc       , 0 },
  { "AADDOUT"    , NULL     , FUNCTION_TYPE_AADDOUT    , function_aaddout    , 0 },
  { "AENVPOINT"  , NULL     , FUNCTION_TYPE_AENVPOINT  , function_aenvpoint  , 0 },
  { "AENVCOPY"   , NULL     , FUNCTION_TYPE_AENVCOPY   , function_aenvcopy   , 0 },
  { "AFILPOINT"  , NULL     , FUNCTION_TYPE_AFILPOINT  , function_afilpoint  , 0 },
  { "AFILCOPY"   , NULL     , FUNCTION_TYPE_AFILCOPY   , function_afilcopy   , 0 },
  { "APLAY"      , NULL     , FUNCTION_TYPE_APLAY      , function_aplay      , 0 },
  { "AOPEN"      , NULL     , FUNCTION_TYPE_AOPEN      , function_aopen      , 0 },
  { "ACLOSE"     , NULL     , FUNCTION_TYPE_ACLOSE     , function_aclose     , 0 },
  { NULL         , NULL     , FUNCTION_TYPE_NONE       , NULL                , 0 }
};

const char *function_name(function_t function)
{
  return function->name;
}

/* #define NLL_FUNCTION_SHORTNAME */

static int _search(const struct function *functions, const char *name, function_t *functionp)
{
  function_t function;
#ifdef NLL_FUNCTION_SHORTNAME
  int len;
#endif

  if (!functions)
    return NLL_ERRCODE_FORMULA_UNKNOWN_FUNCTION;

  for (function = functions; function->name; function++) {
    if (!strcmp(function->name, name)) {
      *functionp = function;
      return 0;
    }
  }

  for (function = functions; function->name; function++) {
    if (function->other_name && !strcmp(function->other_name, name)) {
      *functionp = function;
      return 0;
    }
  }

#ifdef NLL_FUNCTION_SHORTNAME
  for (len = 0; name[len]; len++) {
    if ((name[len] == '.') && !name[len + 1]) {
      for (function = functions; function->name; function++) {
	if (!strncmp(function->name, name, len)) {
	  *functionp = function;
	  return 0;
	}
      }
      break;
    }
  }
#endif

  return NLL_ERRCODE_FORMULA_UNKNOWN_FUNCTION;
}

int function_search(const char *name, function_t *functionp)
{
  int r;
  r = _search(functions_orig, name, functionp);
#ifdef NLL_EXTEND_FUNCTION
  if (r < 0)
    r = _search(functions_ext, name, functionp);
#endif
  return r;
}

static int _list(const struct function *functions, FILE *fp)
{
  function_t function;

  if (!functions)
    return 0;

  for (function = functions; function->name; function++) {
    nll_wait_output(fp);
    fprintf(fp, "%s", function->name);
    if (function->other_name)
      fprintf(fp, "\t(%s)", function->other_name);
    fprintf(fp, "\n");
  }

  fflush(fp);

  return 0;
}

int function_list(FILE *fp)
{
  _list(functions_orig, fp);
#ifdef NLL_EXTEND_FUNCTION
  _list(functions_ext, fp);
#endif
  return 0;
}

int function_proc(function_t function, value_t *valuep, value_t args)
{
  return function->function(valuep, args);
}

static int function_fargs(value_t *valuep, value_t args)
{
  int r;

  for (; args; args = args->next) {
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_value(*valuep, args)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_copy(value_t *valuep, value_t args)
{
  int r;

  for (; args; args = args->next) {
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_copy_value(*valuep, args)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_true(value_t *valuep, value_t args)
{
  int r;

  if (!args) {
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, 1)) < 0)
      return r;
    valuep = &(*valuep)->next;
  } else {
    for (; args; args = args->next) {
      if ((r = value_extend_value(valuep)) < 0)
	return r;
      if ((r = value_set_integer(*valuep, 1)) < 0)
	return r;
      valuep = &(*valuep)->next;
    }
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_false(value_t *valuep, value_t args)
{
  int r;

  if (!args) {
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, 0)) < 0)
      return r;
    valuep = &(*valuep)->next;
  } else {
    for (; args; args = args->next) {
      if ((r = value_extend_value(valuep)) < 0)
	return r;
      if ((r = value_set_integer(*valuep, 0)) < 0)
	return r;
      valuep = &(*valuep)->next;
    }
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_argnum(value_t *valuep, value_t args)
{
  int r, n;

  n = 0;
  for (; args; args = args->next)
    n++;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, n)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_boolean(value_t *valuep, value_t args)
{
  int r;

  if (!args) {
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, 0)) < 0)
      return r;
    valuep = &(*valuep)->next;
  } else {
    for (; args; args = args->next) {
      if ((r = value_extend_value(valuep)) < 0)
	return r;
      if ((r = value_is_true(args)) < 0)
	return r;
      if ((r = value_set_integer(*valuep, r)) < 0)
	return r;
      valuep = &(*valuep)->next;
    }
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_cond(value_t *valuep, value_t args)
{
  int r, n;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_is_true(args)) < 0)
    return r;
  n = r ? 0 : 1;
  args = args->next;

  for (; args && (n > 0); args = args->next, n--)
    ;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if (!args) {
    if ((r = value_set_null(*valuep)) < 0)
      return r;
  } else {
    if ((r = value_copy_value(*valuep, args)) < 0)
      return r;
  }
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_at(value_t *valuep, value_t args)
{
  int r;
  integer_t integer = 0;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &integer)) < 0)
    return r;
  args = args->next;

  for (; args && (integer > 0); args = args->next, integer--)
    ;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if (!args) {
    if ((r = value_set_null(*valuep)) < 0)
      return r;
  } else {
    if ((r = value_copy_value(*valuep, args)) < 0)
      return r;
  }
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fpush(value_t *valuep, value_t args)
{
  int r, n = 0;

  for (; args; args = args->next, n++) {
    if ((r = stack_push(args)) < 0)
      return r;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, n)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fpop(value_t *valuep, value_t args)
{
  int r, i;
  integer_t n = 1;

  if (args) {
    if ((r = value_get_integer(args, &n)) < 0)
      ;
  }

  for (i = 0; i < n; i++) {
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if (stack_getnum() > 0) {
      if ((r = stack_pop(*valuep)) < 0)
	return r;
    } else {
      if ((r = value_set_null(*valuep)) < 0)
	return r;
    }
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_stacknum(value_t *valuep, value_t args)
{
  int r, n;

  n = stack_getnum();

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, n)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fprint(value_t *valuep, value_t args)
{
  int r, n = 0;

  value_output_values(NULL, args, NULL);

  for (; args; args = args->next, n++)
    ;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, n)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_sprintf(value_t *valuep, value_t args)
{
  int r;
  char *format;
  char *buffer;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &format, NULL)) < 0)
    return r;
  args = args->next;

  format = format ? format : "";
  buffer = string_buffer();

  r = nll_sprintf(buffer, string_buffer_size(), format, args);
  if (r < 0)
    strcpy(buffer, "");

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_string(*valuep, buffer, -1)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_printf(value_t *valuep, value_t args)
{
  int r, n;
  char *format;
  char *buffer;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &format, NULL)) < 0)
    return r;
  args = args->next;

  format = format ? format : "";
  buffer = string_buffer();

  n = nll_sprintf(buffer, string_buffer_size(), format, args);
  if (n > 0) {
#ifdef USE_FRAMEBUF
    framebuf_puts(buffer);
#else
    fputs(buffer, nll_stdout);
#endif
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, n)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_printm(value_t *valuep, value_t args)
{
  int r, result = 0;
  integer_t x = -1, y = -1, fgcolor = -1, bgcolor = -1;
  value_t arg;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  arg = args;
  args = args->next;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &fgcolor)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &bgcolor)) < 0)
      ;
  }

#ifdef USE_FRAMEBUF
  result = framebuf_move_cursor(x, y);
  if (fgcolor >= 0) framebuf_setfgcolor(fgcolor);
  if (bgcolor >= 0) framebuf_setbgcolor(bgcolor);
#else
  fprintf(nll_stdout, "\x1b[%d;%dH", (int)y + 1, (int)x + 1);
  if ((fgcolor >= 0) && (fgcolor <= 9))
    fprintf(nll_stdout, "\x1b[%dm", 30 + (int)fgcolor);
  if ((bgcolor >= 0) && (bgcolor <= 9))
    fprintf(nll_stdout, "\x1b[%dm", 40 + (int)bgcolor);
#endif
  value_output_value(NULL, arg);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_input(value_t *valuep, value_t args)
{
  int r, len;
  char *string;
  char *buffer;

#ifdef USE_FRAMEBUF
  framebuf_enable(0);
#endif

  for (; args; args = args->next) {
    if (value_get_string(args, &string, NULL) < 0)
      continue;
    string = string ? string : "?";
    fprintf(nll_stdout, "%s", string);
  }
  fflush(nll_stdout);

  buffer = string_buffer();

  if (!fgets(buffer, string_buffer_size(), nll_stdin))
    buffer[0] = '\0';

  len = strlen(buffer);
  while ((len > 0) && (buffer[len - 1] == '\n'))
    buffer[--len] = '\0';

#ifdef USE_FRAMEBUF
  framebuf_enable(1);
#endif

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_string(*valuep, buffer, -1)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static integer_t str2val(const char *string)
{
  int base = 10, sign = 1;
  integer_t val;
  const char *p;

  p = string;

  while (isspace(*p))
    p++;

  switch (*p) {
  case '+': sign =  1; p++; break;
  case '-': sign = -1; p++; break;
  default: break;
  }

  if (*p == '0') {
    switch (p[1]) {
    case 'b':
    case 'B': base =  2; p += 2; break;
    case 'o':
    case 'O': base =  8; p += 2; break;
    case 'd':
    case 'D': base = 10; p += 2; break;
    case 'x':
    case 'X': base = 16; p += 2; break;
    default:
      break;
    }
  }

  val = strtol(p, NULL, base);

  if (sign < 0)
    val = -val;

  return val;
}

static int function_inputn(value_t *valuep, value_t args)
{
  int r;
  integer_t integer;
  char *string;
  char *buffer;

#ifdef USE_FRAMEBUF
  framebuf_enable(0);
#endif

  for (; args; args = args->next) {
    if (value_get_string(args, &string, NULL) < 0)
      continue;
    string = string ? string : "?";
    fprintf(nll_stdout, "%s", string);
  }
  fflush(nll_stdout);

  buffer = string_buffer();

  if (!fgets(buffer, string_buffer_size(), nll_stdin))
    buffer[0] = '\0';

#ifdef USE_FRAMEBUF
  framebuf_enable(1);
#endif

  integer = str2val(buffer);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, integer)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fwait(value_t *valuep, value_t args)
{
  int r, usec = 0, sec = 0, rate = -1;
  integer_t integer;

  for (; args; args = args->next) {
    if (value_get_integer(args, &integer) < 0)
      ;
    else {
      if (rate < 0) {
	sec = integer;
	rate = 1000;
      } else {
	usec = usec + (integer * rate);
	sec  += usec / 1000000;
	usec %= 1000000;
	rate /= 1000;
      }
    }
  }

  if (usec)
    nll_usleep(usec);
  if (sec)
    nll_sleep(sec);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, 0)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int _calc_diff_time(struct timeval *tp, struct timeval *t0p, struct timeval *t1p)
{
  struct timeval t;

  t.tv_sec = t.tv_usec = 0;

  if (t0p->tv_usec < t1p->tv_usec) {
    t.tv_sec  = 1;
    t.tv_usec = 1000000;
  }

  tp->tv_sec  = (t0p->tv_sec  - t.tv_sec ) - t1p->tv_sec;
  tp->tv_usec = (t0p->tv_usec + t.tv_usec) - t1p->tv_usec;

  return 0;
}

static int calc_diff_time(struct timeval *tp, struct timeval *t0p, struct timeval *t1p)
{
  int r = 0;

  if ((t0p->tv_sec == t1p->tv_sec) && (t0p->tv_usec == t1p->tv_usec)) {
    tp->tv_sec = tp->tv_usec = 0;
  } else if ((t0p->tv_sec > t1p->tv_sec) ||
	     ((t0p->tv_sec == t1p->tv_sec) && (t0p->tv_usec >= t1p->tv_usec))) {
    _calc_diff_time(tp, t0p, t1p);
    r = 1;
  } else {
    _calc_diff_time(tp, t1p, t0p);
    r = -1;
  }

  return r;
}

static struct timeval timer_time = { 0, 0 };

static int function_timer(value_t *valuep, value_t args)
{
  int r, usec = 0, sec = 0, rate = -1, check_only = 0;
  struct timeval n, a, t, w;
  integer_t integer;

  if (gettimeofday(&n, NULL) < 0)
    n.tv_sec = n.tv_usec = 0;

  if (!args) {
    w.tv_sec  = timer_time.tv_sec  = n.tv_sec;
    w.tv_usec = timer_time.tv_usec = n.tv_usec;
  } else {
    if (!timer_time.tv_sec && !timer_time.tv_usec) {
      timer_time.tv_sec  = n.tv_sec;
      timer_time.tv_usec = n.tv_usec;
    }

    for (; args; args = args->next) {
      if (value_get_integer(args, &integer) < 0)
	;
      else {
	if (rate < 0) {
	  sec = integer;
	  rate = 1000;
	} else {
	  usec = usec + (integer * rate);
	  sec  += usec / 1000000;
	  usec %= 1000000;
	  rate /= 1000;
	}
      }
    }

    if (sec < 0) {
      a.tv_sec  = -sec;
      a.tv_usec = -usec;
      check_only = 1;
    } else {
      a.tv_sec  = sec;
      a.tv_usec = usec;
    }

    t.tv_sec  = timer_time.tv_sec  + a.tv_sec;
    t.tv_usec = timer_time.tv_usec + a.tv_usec;
    t.tv_sec  += t.tv_usec / 1000000;
    t.tv_usec %= 1000000;

    if (calc_diff_time(&w, &t, &n) >= 0) {
      if (!check_only) {
	if (w.tv_sec || w.tv_usec) {
	  nll_sleep(w.tv_sec);
	  nll_usleep(w.tv_usec);
	}
      }
    } else {
      w.tv_sec  = -w.tv_sec;
      w.tv_usec = -w.tv_usec;
    }

    if (!check_only) {
      timer_time.tv_sec  = t.tv_sec;
      timer_time.tv_usec = t.tv_usec;
    }
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, w.tv_sec)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, w.tv_usec / 1000)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, w.tv_usec)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_nosystem(value_t *valuep, value_t args)
{
  int r, result;

  result = nll_nosystem_set();

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_nosyscall(value_t *valuep, value_t args)
{
  int r, result;

  result = nll_nosyscall_set();

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_nonetwork(value_t *valuep, value_t args)
{
  int r, result;

  result = nll_nonetwork_set();

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

#ifdef NLL_STDIO_FUNCTION
static int function_fstdin(value_t *valuep, value_t args)
{
  int r, result;
  char *filename = NULL;
  FILE *fp;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (args) {
    if ((r = value_get_string(args, &filename, NULL)) < 0)
      ;
  }

  if (!filename) {
    result = (nll_stdin_restore() < 0) ? -1 : 0;
  } else {
    fp = fopen(filename, "r");
    if (fp)
      result = (nll_stdin_save(fp) < 0) ? -1 : 0;
    else
      result = -1;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fstdout(value_t *valuep, value_t args)
{
  int r, result;
  char *filename = NULL;
  FILE *fp;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (args) {
    if ((r = value_get_string(args, &filename, NULL)) < 0)
      ;
  }

  if (!filename) {
    result = (nll_stdout_restore() < 0) ? -1 : 0;
  } else {
    fp = fopen(filename, "w");
    if (fp)
      result = (nll_stdout_save(fp) < 0) ? -1 : 0;
    else
      result = -1;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}
#endif

#ifdef NLL_SYSTEM_FUNCTION
static int function_system(value_t *valuep, value_t args)
{
  int r, result;
  char *command;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &command, NULL)) < 0)
    return r;

  if (!command)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

#ifndef USE_NLLIBC
  result = system(command);
#else
  result = -1;
#endif

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}
#endif

#ifdef NLL_SYSCALL_FUNCTION
#define SYSCALL_ARG_MAXNUM 8

static int syscall_call(int syscall_no, int argc, long *args)
{
  int r = -1;

  switch (argc) {
#ifndef WIN32
#ifndef USE_NLLIBC
  case 0: r = syscall(syscall_no                                    ); break;
  case 1: r = syscall(syscall_no, args[0]                           ); break;
  case 2: r = syscall(syscall_no, args[0], args[1]                  ); break;
  case 3: r = syscall(syscall_no, args[0], args[1], args[2]         ); break;
  case 4: r = syscall(syscall_no, args[0], args[1], args[2], args[3]); break;
  case 5: r = syscall(syscall_no, args[0], args[1], args[2], args[3],
		      args[4]                                       ); break;
  case 6: r = syscall(syscall_no, args[0], args[1], args[2], args[3],
		      args[4], args[5]                              ); break;
  case 7: r = syscall(syscall_no, args[0], args[1], args[2], args[3],
		      args[4], args[5], args[6]                     ); break;
  case 8: r = syscall(syscall_no, args[0], args[1], args[2], args[3],
		      args[4], args[5], args[6], args[7]            ); break;
#endif
#endif
  default:
    break;
  }

  return r;
}

static int function_syscall(value_t *valuep, value_t args)
{
  int r, result, argc = 0;
  integer_t syscall_no, integer;
  char *string;
  area_t area;
  long syscall_args[SYSCALL_ARG_MAXNUM];

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
  if (nll_is_nosyscall())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &syscall_no)) < 0)
    return r;
  args = args->next;

  for (; args; args = args->next) {
    if ((r = value_get_integer(args, &integer)) < 0) {
      if ((r = value_get_string(args, &string, NULL)) < 0) {
	if ((r = value_get_area(args, &area)) < 0) {
	  return r;
	} else {
	  syscall_args[argc] = area ? (long)area_get_buffer(area) : 0;
	}
      } else {
	syscall_args[argc] = (long)string;
      }
    } else {
      syscall_args[argc] = (long)integer;
    }
    argc++;
    if (argc == SYSCALL_ARG_MAXNUM)
      break;
  }

  result = syscall_call(syscall_no, argc, syscall_args);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}
#endif

static int function_feval(value_t *valuep, value_t args)
{
  int r;
  char *string;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &string, NULL)) < 0)
    return r;

  if (!string)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  if ((r = value_extend_value(valuep)) < 0)
    return r;

#ifndef NLL_INTERNAL_EXEC_DISABLE
  if ((r = nll_parse_exec(NULL, POSITION_TYPE_EVAL, string, *valuep, NULL)) < 0)
    return r;
#endif

  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fevalf(value_t *valuep, value_t args)
{
  int r;
#ifndef NLL_INTERNAL_EXEC_DISABLE
  int retcode;
#endif
  char *filename = NULL;
  FILE *fp = NULL;
  char buffer[LINE_MAXLEN + 1];

  if (args) {
    if ((r = value_get_string(args, &filename, NULL)) < 0)
      ;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;

  if (!filename) {
    fp = nll_stdin;
  } else {
    fp = fopen(filename, "r");
    if (!fp)
      return NLL_ERRCODE_FILE_NOT_FOUND;
  }

  while (nll_fgets(buffer, LINE_MAXLEN, fp)) {
#ifndef NLL_INTERNAL_EXEC_DISABLE
    if ((r = nll_parse_exec(NULL, POSITION_TYPE_EVAL, buffer, *valuep, &retcode)) < 0)
      break;
    if (retcode)
      break;
#endif
  }

  if (filename)
    fclose(fp);
#ifndef NLL_INTERNAL_EXEC_DISABLE
  if (r < 0)
    return r;
#endif

  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_typeof(value_t *valuep, value_t args)
{
  int r, code;

  for (; args; args = args->next) {
    if ((code = value_typecode(args)) < 0)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, code)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_typename(value_t *valuep, value_t args)
{
  int r;
  const char *name;

  for (; args; args = args->next) {
    if ((name = value_typename(args)) == NULL)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_string(*valuep, name, -1)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_sizeof(value_t *valuep, value_t args)
{
  int r, size;

  for (; args; args = args->next) {
    size = value_size(args);
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, size)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_nzero(value_t *valuep, value_t args)
{
  int r, t = 0;

  for (; args; args = args->next) {
    t = value_is_true(args);
    if (t)
      break;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, t)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_cmp(value_t *valuep, value_t args)
{
  int r, cmp = 0;
  value_t value;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  value = args;
  args = args->next;

  for (; args; args = args->next) {
    if ((r = value_cmp_value(value, args)) < 0)
      return r;
    if (r) {
      cmp = r;
      break;
    }
    value = args;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, cmp)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_rep(value_t *valuep, value_t args)
{
  int r, i;
  integer_t n;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &n)) < 0)
    return r;
  args = args->next;

  for (i = 0; i < n; i++) {
    if ((r = value_copy_values(valuep, args)) < 0)
      return r;
    while (*valuep)
      valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_insert(value_t *valuep, value_t args)
{
  int r, i = 0;
  integer_t n;
  value_t value, arg;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  value = args;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &n)) < 0)
    return r;
  args = args->next;

  if (n < 0) {
    for (arg = args; arg; arg = arg->next)
      n++;
    n++;
  }

  for (;; args = args->next, i++) {
    if (i == n) {
      if ((r = value_extend_value(valuep)) < 0)
	return r;
      if ((r = value_copy_value(*valuep, value)) < 0)
	return r;
      valuep = &(*valuep)->next;
    }
    if (!args)
      break;
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_copy_value(*valuep, args)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_delete(value_t *valuep, value_t args)
{
  int r, i = 0;
  integer_t n;
  value_t arg;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &n)) < 0)
    return r;
  args = args->next;

  if (n < 0) {
    for (arg = args; arg; arg = arg->next)
      n++;
  }

  for (; args; args = args->next, i++) {
    if (i == n)
      continue;
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_copy_value(*valuep, args)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_itoc(value_t *valuep, value_t args)
{
  int r;
  integer_t integer;
  char str[2];

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  for (; args; args = args->next) {
    if ((r = value_get_integer(args, &integer)) < 0)
      return r;
    str[0] = integer;
    str[1] = '\0';
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_string(*valuep, str, -1)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_ctoi(value_t *valuep, value_t args)
{
  int r, i, length;
  integer_t integer;
  char *string;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &string, &length)) < 0)
      return r;
    if (!string)
      continue;
    for (i = 0; i < length; i++) {
      integer = *(unsigned char *)(string + i);
      if ((r = value_extend_value(valuep)) < 0)
	return r;
      if ((r = value_set_integer(*valuep, integer)) < 0)
	return r;
      valuep = &(*valuep)->next;
    }
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_itoa(value_t *valuep, value_t args)
{
  int r;
  integer_t integer;
  char *buffer;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  buffer = string_buffer();

  for (; args; args = args->next) {
    if ((r = value_get_integer(args, &integer)) < 0)
      return r;
    sprintf(buffer, "%ld", integer);
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_string(*valuep, buffer, -1)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_atoi(value_t *valuep, value_t args)
{
  int r;
  integer_t integer;
  char *string;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &string, NULL)) < 0)
      return r;
    if (!string)
      continue;
    integer = str2val(string);
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, integer)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

#ifdef NLL_FLOATING_POINT
static int function_itof(value_t *valuep, value_t args)
{
  int r;
  integer_t integer;
  double f;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  for (; args; args = args->next) {
    if ((r = value_get_integer(args, &integer)) < 0)
      return r;
    f = (double)integer;
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_float(*valuep, f)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_ftoi(value_t *valuep, value_t args)
{
  int r;
  integer_t integer;
  double f;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  for (; args; args = args->next) {
    if ((r = value_get_float(args, &f)) < 0)
      return r;
    integer = (int)f;
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, integer)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_atof(value_t *valuep, value_t args)
{
  int r;
  double f;
  char *string;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &string, NULL)) < 0)
      return r;
    if (!string)
      continue;
#ifdef USE_MATHLIB
    f = atof(string);
#else
    f = 0.0;
#endif
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_float(*valuep, f)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_ftoa(value_t *valuep, value_t args)
{
  int r;
  double f;
  char *buffer;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  buffer = string_buffer();

  for (; args; args = args->next) {
    if ((r = value_get_float(args, &f)) < 0)
      return r;
    sprintf(buffer, "%f", f);
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_string(*valuep, buffer, -1)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}
#endif

static int function_isx(function_type_t type, value_t *valuep, value_t args)
{
  int r, i, length, c;
  char *string;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &string, &length)) < 0)
      return r;
    if (!string)
      continue;
    for (i = 0; i < length; i++) {
      c = *(unsigned char *)(string + i);
      switch (type) {
      case FUNCTION_TYPE_ISALNUM:  c = isalnum(c)  ? 1 : 0; break;
      case FUNCTION_TYPE_ISALPHA:  c = isalpha(c)  ? 1 : 0; break;
      case FUNCTION_TYPE_ISASCII:  c = isascii(c)  ? 1 : 0; break;
      case FUNCTION_TYPE_ISCNTRL:  c = iscntrl(c)  ? 1 : 0; break;
      case FUNCTION_TYPE_ISDIGIT:  c = isdigit(c)  ? 1 : 0; break;
      case FUNCTION_TYPE_ISGRAPH:  c = isgraph(c)  ? 1 : 0; break;
      case FUNCTION_TYPE_ISLOWER:  c = islower(c)  ? 1 : 0; break;
      case FUNCTION_TYPE_ISPRINT:  c = isprint(c)  ? 1 : 0; break;
      case FUNCTION_TYPE_ISPUNCT:  c = ispunct(c)  ? 1 : 0; break;
      case FUNCTION_TYPE_ISSPACE:  c = isspace(c)  ? 1 : 0; break;
      case FUNCTION_TYPE_ISUPPER:  c = isupper(c)  ? 1 : 0; break;
      case FUNCTION_TYPE_ISXDIGIT: c = isxdigit(c) ? 1 : 0; break;
      default:
	return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
      }
      if ((r = value_extend_value(valuep)) < 0)
	return r;
      if ((r = value_set_integer(*valuep, c)) < 0)
	return r;
      valuep = &(*valuep)->next;
    }
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_isalnum(value_t *valuep, value_t args)
{
  return function_isx(FUNCTION_TYPE_ISALNUM, valuep, args);
}

static int function_isalpha(value_t *valuep, value_t args)
{
  return function_isx(FUNCTION_TYPE_ISALPHA, valuep, args);
}

static int function_isascii(value_t *valuep, value_t args)
{
  return function_isx(FUNCTION_TYPE_ISASCII, valuep, args);
}

static int function_iscntrl(value_t *valuep, value_t args)
{
  return function_isx(FUNCTION_TYPE_ISCNTRL, valuep, args);
}

static int function_isdigit(value_t *valuep, value_t args)
{
  return function_isx(FUNCTION_TYPE_ISDIGIT, valuep, args);
}

static int function_isgraph(value_t *valuep, value_t args)
{
  return function_isx(FUNCTION_TYPE_ISGRAPH, valuep, args);
}

static int function_islower(value_t *valuep, value_t args)
{
  return function_isx(FUNCTION_TYPE_ISLOWER, valuep, args);
}

static int function_isprint(value_t *valuep, value_t args)
{
  return function_isx(FUNCTION_TYPE_ISPRINT, valuep, args);
}

static int function_ispunct(value_t *valuep, value_t args)
{
  return function_isx(FUNCTION_TYPE_ISPUNCT, valuep, args);
}

static int function_isspace(value_t *valuep, value_t args)
{
  return function_isx(FUNCTION_TYPE_ISSPACE, valuep, args);
}

static int function_isupper(value_t *valuep, value_t args)
{
  return function_isx(FUNCTION_TYPE_ISUPPER, valuep, args);
}

static int function_isxdigit(value_t *valuep, value_t args)
{
  return function_isx(FUNCTION_TYPE_ISXDIGIT, valuep, args);
}

static int function_tox(function_type_t type, value_t *valuep, value_t args)
{
  int r, i, length, c;
  char *string;
  char *buffer;

  buffer = string_buffer();

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &string, &length)) < 0)
      return r;
    if (!string)
      continue;
    for (i = 0; i < length; i++) {
      c = *(unsigned char *)(string + i);
      switch (type) {
      case FUNCTION_TYPE_TOLOWER: c = tolower(c); break;
      case FUNCTION_TYPE_TOUPPER: c = toupper(c); break;
      default:
	return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
      }
      buffer[i] = c;
    }
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_string(*valuep, buffer, length)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_tolower(value_t *valuep, value_t args)
{
  return function_tox(FUNCTION_TYPE_TOLOWER, valuep, args);
}

static int function_toupper(value_t *valuep, value_t args)
{
  return function_tox(FUNCTION_TYPE_TOUPPER, valuep, args);
}

static int function_left(value_t *valuep, value_t args)
{
  int r, i, length, offset, size;
  integer_t integer;
  char *s, *p;
  char *buffer;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &s, &length)) < 0)
    return r;
  args = args->next;

  if (!s) {
    s = "";
    length = 0;
  }

  offset = 0;
  integer = length;

  if (args) {
    if ((r = value_get_integer(args, &integer)) < 0)
      ;
  }

  size = integer + ((integer < 0) ? length : 0);

  buffer = string_buffer();
  p = buffer;

  for (i = 0; i < size; i++) {
    if ((offset + i >= 0) && (offset + i < length))
      *(p++) = s[offset + i];
  }
  *p = '\0';

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_string(*valuep, buffer, p - buffer)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_right(value_t *valuep, value_t args)
{
  int r, i, length, offset, size;
  integer_t integer;
  char *s, *p;
  char *buffer;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &s, &length)) < 0)
    return r;
  args = args->next;

  if (!s) {
    s = "";
    length = 0;
  }

  integer = length;

  if (args) {
    if ((r = value_get_integer(args, &integer)) < 0)
      ;
  }

  size = integer + ((integer < 0) ? length : 0);
  offset = length - size;

  buffer = string_buffer();
  p = buffer;

  for (i = 0; i < size; i++) {
    if ((offset + i >= 0) && (offset + i < length))
      *(p++) = s[offset + i];
  }
  *p = '\0';

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_string(*valuep, buffer, p - buffer)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_mid(value_t *valuep, value_t args)
{
  int r, i, length, offset, size;
  integer_t integer0 = 0, integer1;
  char *s, *p;
  char *buffer;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &s, &length)) < 0)
    return r;
  args = args->next;

  if (!s) {
    s = "";
    length = 0;
  }

  if (args) {
    if ((r = value_get_integer(args, &integer0)) < 0)
      ;
    args = args->next;
  }

  offset = integer0 + ((integer0 < 0) ? length : 0);
  integer1 = length - offset;

  if (args) {
    if ((r = value_get_integer(args, &integer1)) < 0)
      ;
  }

  size = integer1 + ((integer1 < 0) ? (length - offset) : 0);

  buffer = string_buffer();
  p = buffer;

  for (i = 0; i < size; i++) {
    if ((offset + i >= 0) && (offset + i < length))
      *(p++) = s[offset + i];
  }
  *p = '\0';

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_string(*valuep, buffer, p - buffer)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_instr(value_t *valuep, value_t args)
{
  int r, i, n, length0, length1;
  char *s0, *s1;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &s0, &length0)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &s1, &length1)) < 0)
    return r;

  if (!s0) {
    s0 = "";
    length0 = 0;
  }
  if (!s1) {
    s1 = "";
    length1 = 0;
  }

  n = -1;
  for (i = 0; i <= length0 - length1; i++) {
    if (!memcmp(s0 + i, s1, length1)) {
      n = i;
      break;
    }
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, n)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_strlen(value_t *valuep, value_t args)
{
  int r, length;
  char *string;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &string, &length)) < 0)
      return r;
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, length)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_strcpy(value_t *valuep, value_t args)
{
  int r, length0, length1;
  integer_t offset = -1;
  char *s0, *s1;
  char *buffer;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &s0, &length0)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &s1, &length1)) < 0)
    return r;

  if (!s0) {
    s0 = "";
    length0 = 0;
  }
  if (!s1) {
    s1 = "";
    length1 = 0;
  }

  if (offset < 0)
    offset = length0;

  if (offset + length1 + 1 > string_buffer_size())
    return NLL_ERRCODE_STRING_TOO_LONG;

  buffer = string_buffer();

  memcpy(buffer, s0, length0);
  memcpy(buffer + offset, s1, length1);

  if (offset + length1 > length0)
    length0 = offset + length1;

  buffer[length0] = '\0';

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_string(*valuep, buffer, length0)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_split(value_t *valuep, value_t args)
{
  int r, num, length;
  char *letters, *string, *p, *n;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &letters, &num)) < 0)
    return r;
  args = args->next;

  if (!letters) {
    letters = "";
    num = 0;
  }

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &string, &length)) < 0)
      return r;
    if (!string)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;

    p = string;
    while (1) {
      for (n = p; n - string < length; n++) {
	if (memchr(letters, *n, num))
	  break;
      }

      if ((r = value_extend_value(valuep)) < 0)
	return r;
      if ((r = value_set_string(*valuep, p, n - p)) < 0)
	return r;
      valuep = &(*valuep)->next;

      if (n - string == length)
	break;

      p = n + 1;
    }
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_splits(value_t *valuep, value_t args)
{
  int r, num, length;
  char *letters, *string, *p, *n;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &letters, &num)) < 0)
    return r;
  args = args->next;

  if (!letters) {
    letters = "";
    num = 0;
  }

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &string, &length)) < 0)
      return r;
    if (!string)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;

    p = string;
    while (1) {
      for (n = p; n - string < length; n++) {
	if (memchr(letters, *n, num))
	  break;
      }

      if ((r = value_extend_value(valuep)) < 0)
	return r;
      if ((r = value_set_string(*valuep, p, n - p)) < 0)
	return r;
      valuep = &(*valuep)->next;

      if (n - string == length)
	break;

      for (p = n; p - string < length; p++) {
	if (!memchr(letters, *p, num))
	  break;
      }
    }
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_chomp(value_t *valuep, value_t args)
{
  int r, num, length;
  char *letters, *string;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &letters, &num)) < 0)
    return r;
  args = args->next;

  if (!letters) {
    letters = "";
    num = 0;
  }

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &string, &length)) < 0)
      return r;
    if (!string)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;

    for (; length > 0; string++, length--) {
      if (!memchr(letters, *string, num))
	break;
    }

    for (; length > 0; length--) {
      if (!memchr(letters, string[length - 1], num))
	break;
    }

    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_string(*valuep, string, length)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_lchomp(value_t *valuep, value_t args)
{
  int r, num, length;
  char *letters, *string;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &letters, &num)) < 0)
    return r;
  args = args->next;

  if (!letters) {
    letters = "";
    num = 0;
  }

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &string, &length)) < 0)
      return r;
    if (!string)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;

    for (; length > 0; string++, length--) {
      if (!memchr(letters, *string, num))
	break;
    }

    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_string(*valuep, string, length)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_rchomp(value_t *valuep, value_t args)
{
  int r, num, length;
  char *letters, *string;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &letters, &num)) < 0)
    return r;
  args = args->next;

  if (!letters) {
    letters = "";
    num = 0;
  }

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &string, &length)) < 0)
      return r;
    if (!string)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;

    for (; length > 0; length--) {
      if (!memchr(letters, string[length - 1], num))
	break;
    }

    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_string(*valuep, string, length)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static unsigned int seed = 1;

static unsigned int _rand(void)
{
  seed ^= seed << 13;
  seed ^= seed >> 17;
  seed ^= seed <<  5;
  return seed;
}

static int _randval(void)
{
  volatile int r;

  r = (int)seed;
  if (r < 0)
    r = -r;
  if (r < 0) /* 0x80000000 */
    r = 1;

  return r;
}

static int function_srand(value_t *valuep, value_t args)
{
  int r;
  integer_t s = 0;

  if (args) {
    if ((r = value_get_integer(args, &s)) < 0)
      ;
    seed = !s ? time(NULL) : s;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, seed)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_rand(value_t *valuep, value_t args)
{
  int r, n;
  integer_t range = 0;

  if (!args) {
    _rand();
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, _randval())) < 0)
      return r;
    valuep = &(*valuep)->next;
  } else {
    for (; args; args = args->next) {
      if ((r = value_get_integer(args, &range)) < 0)
	return r;
      n = range;
      if (n >= 0)
	_rand();
      if ((r = value_extend_value(valuep)) < 0)
	return r;
      if ((r = value_set_integer(*valuep, (n > 0) ? (_randval() % n) : _randval())) < 0)
	return r;
      valuep = &(*valuep)->next;
    }
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_int(value_t *valuep, value_t args)
{
  int r;
  integer_t integer;
#ifdef NLL_FLOATING_POINT
  double f;
#endif

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  for (; args; args = args->next) {
    if ((r = value_get_integer(args, &integer)) < 0) {
#ifdef NLL_FLOATING_POINT
      if ((r = value_get_float(args, &f)) < 0)
	return r;
      integer = f;
      while (integer > f)
	integer--;
#else
      return r;
#endif
    }
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, integer)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_abs(value_t *valuep, value_t args)
{
  int r, is_float;
  integer_t integer;
#ifdef NLL_FLOATING_POINT
  double f;
#endif

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  for (; args; args = args->next) {
    is_float = 0;
    if ((r = value_get_integer(args, &integer)) < 0) {
#ifdef NLL_FLOATING_POINT
      if ((r = value_get_float(args, &f)) < 0)
	return r;
      f = (f < 0.0) ? -f : f;
      is_float = 1;
#else
      return r;
#endif
    } else {
      integer = (integer < 0) ? -integer : integer;
    }
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if (is_float) {
#ifdef NLL_FLOATING_POINT
      if ((r = value_set_float(*valuep, f)) < 0)
	return r;
#else
      return NLL_ERRCODE_VALUE_INVALID_TYPE;
#endif
    } else {
      if ((r = value_set_integer(*valuep, integer)) < 0)
	return r;
    }
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_sign(value_t *valuep, value_t args)
{
  int r, is_float;
  integer_t integer;
#ifdef NLL_FLOATING_POINT
  double f;
#endif

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  for (; args; args = args->next) {
    is_float = 0;
    if ((r = value_get_integer(args, &integer)) < 0) {
#ifdef NLL_FLOATING_POINT
      if ((r = value_get_float(args, &f)) < 0)
	return r;
      if      (f < 0.0) f = -1.0;
      else if (f > 0.0) f =  1.0;
      else              f =  0.0;
      is_float = 1;
#else
      return r;
#endif
    } else {
      if      (integer < 0) integer = -1;
      else if (integer > 0) integer =  1;
      else                  integer =  0;
    }
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if (is_float) {
#ifdef NLL_FLOATING_POINT
      if ((r = value_set_float(*valuep, f)) < 0)
	return r;
#else
      return NLL_ERRCODE_VALUE_INVALID_TYPE;
#endif
    } else {
      if ((r = value_set_integer(*valuep, integer)) < 0)
	return r;
    }
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_max(value_t *valuep, value_t args)
{
  int r, has_float = 0, has_integer = 0, max = 0;
  integer_t integer;
#ifdef NLL_FLOATING_POINT
  double f, fmax = 0.0;
#endif

  for (; args; args = args->next) {
    if ((r = value_get_integer(args, &integer)) < 0) {
#ifdef NLL_FLOATING_POINT
      if ((r = value_get_float(args, &f)) < 0)
	return r;
      if (!has_float || (fmax < f))
	fmax = f;
      has_float = 1;
#else
      return r;
#endif
    } else {
      if (!has_integer || (max < integer))
	max = integer;
      has_integer = 1;
    }
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if (has_float) {
#ifdef NLL_FLOATING_POINT
    if (has_integer && (fmax < max))
      fmax = max;
    if ((r = value_set_float(*valuep, fmax)) < 0)
      return r;
#else
    return NLL_ERRCODE_VALUE_INVALID_TYPE;
#endif
  } else {
    if ((r = value_set_integer(*valuep, max)) < 0)
      return r;
  }
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_min(value_t *valuep, value_t args)
{
  int r, has_float = 0, has_integer = 0, min = 0;
  integer_t integer;
#ifdef NLL_FLOATING_POINT
  double f, fmin = 0.0;
#endif

  for (; args; args = args->next) {
    if ((r = value_get_integer(args, &integer)) < 0) {
#ifdef NLL_FLOATING_POINT
      if ((r = value_get_float(args, &f)) < 0)
	return r;
      if (!has_float || (fmin > f))
	fmin = f;
      has_float = 1;
#else
      return r;
#endif
    } else {
      if (!has_integer || (min > integer))
	min = integer;
      has_integer = 1;
    }
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if (has_float) {
#ifdef NLL_FLOATING_POINT
    if (has_integer && (fmin > min))
      fmin = min;
    if ((r = value_set_float(*valuep, fmin)) < 0)
      return r;
#else
    return NLL_ERRCODE_VALUE_INVALID_TYPE;
#endif
  } else {
    if ((r = value_set_integer(*valuep, min)) < 0)
      return r;
  }
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_abs2sum(value_t *valuep, value_t args)
{
  int r, has_float = 0, sum = 0;
  integer_t integer;
#ifdef NLL_FLOATING_POINT
  double f, fsum = 0.0;
#endif

  for (; args; args = args->next) {
    if ((r = value_get_integer(args, &integer)) < 0) {
#ifdef NLL_FLOATING_POINT
      if ((r = value_get_float(args, &f)) < 0)
	return r;
      fsum += f * f;
      has_float = 1;
#else
      return r;
#endif
    } else {
      sum += integer * integer;
    }
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if (has_float) {
#ifdef NLL_FLOATING_POINT
    fsum += sum;
    if ((r = value_set_float(*valuep, fsum)) < 0)
      return r;
#else
    return NLL_ERRCODE_VALUE_INVALID_TYPE;
#endif
  } else {
    if ((r = value_set_integer(*valuep, sum)) < 0)
      return r;
  }
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_time(value_t *valuep, value_t args)
{
  int r;
  struct timeval t;

  if (gettimeofday(&t, NULL) < 0)
    t.tv_sec = t.tv_usec = 0;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, t.tv_sec)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, t.tv_usec / 1000)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, t.tv_usec)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_date(value_t *valuep, value_t args)
{
  int r;
#ifndef USE_NLLIBC
  time_t t;
#endif
  char *s;

#ifndef USE_NLLIBC
  t = time(NULL);
  s = ctime(&t);
#else
  s = "Cannot get date.";
#endif

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_string(*valuep, s, -1)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fdim(value_t *valuep, value_t args)
{
  int r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = array_make_values(*valuep, args)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fmemory(value_t *valuep, value_t args)
{
  int r;
  integer_t integer = -1;
  area_t area = NULL;

  if (args) {
    if ((r = value_get_integer(args, &integer)) < 0)
      ;
  }

  if (integer >= 0) {
    if ((r = area_alloc(&area, integer)) < 0)
      return r;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_area(*valuep, area)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_peek(value_t *valuep, value_t args)
{
  int r;
  integer_t offset = 0, size = -1, integer;
  area_t area;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &area)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
  }

  if (!area)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  if ((r = area_read_integer(area, offset, &integer, size)) < 0)
    return r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, integer)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_poke(value_t *valuep, value_t args)
{
  int r;
  integer_t offset = 0, size = -1, integer;
  area_t area;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &area)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
    args = args->next;
  }

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &integer)) < 0)
    return r;

  if (!area)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  if ((r = area_write_integer(area, offset, integer, size)) < 0)
    return r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, integer)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_mread(value_t *valuep, value_t args)
{
  int r;
  integer_t offset = 0, size = -1;
  area_t area;
  char *buffer;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &area)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
  }

  if (!area)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  if (size < 0)
    size = area_get_size(area) - offset;

  if (size < 0)
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  if (size + 1 > string_buffer_size())
    return NLL_ERRCODE_STRING_TOO_LONG;

  buffer = string_buffer();

  if ((r = area_read(area, offset, buffer, size)) < 0)
    return r;
  buffer[size] = '\0';

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_string(*valuep, buffer, size)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_mwrite(value_t *valuep, value_t args)
{
  int r, length;
  integer_t offset = 0, size = -1;
  area_t area;
  char *string;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &area)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
    args = args->next;
  }

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &string, &length)) < 0)
    return r;

  if (!area)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  if (!string) {
    string = "";
    length = 0;
  }

  if (size < 0)
    size = length;

  if (size > length)
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  if ((r = area_write(area, offset, string, size)) < 0)
    return r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, size)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_mcopy(value_t *valuep, value_t args)
{
  int r;
  integer_t doffset = 0, soffset = 0, size = -1;
  area_t darea, sarea;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &darea)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &doffset)) < 0)
      ;
    args = args->next;
  }

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &sarea)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &soffset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
  }

  if (!darea || !sarea)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  if (size < 0)
    size = area_get_size(sarea) - soffset;

  if (size < 0)
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  if ((r = area_copy_area(darea, doffset, sarea, soffset, size)) < 0)
    return r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, size)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

#ifdef USE_MATHLIB
static int function_mathfunc(function_type_t type, value_t *valuep, value_t args)
{
#ifndef NLL_FLOATING_POINT
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  double f;

  if (!args) {
    switch (type) {
    case FUNCTION_TYPE_PI: f = M_PI; break;
    default:
      return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
    }
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_float(*valuep, f)) < 0)
      return r;
    valuep = &(*valuep)->next;
  } else {
    for (; args; args = args->next) {
      if ((r = value_get_float_integer(args, &f)) < 0)
	return r;
      switch (type) {
      case FUNCTION_TYPE_PI:     f = M_PI * f;                 break;
      case FUNCTION_TYPE_RADIAN: f = (2.0 * M_PI) / 360.0 * f; break;
      case FUNCTION_TYPE_DEGREE: f = 360.0 / (2.0 * M_PI) * f; break;
      case FUNCTION_TYPE_SIN:    f = sin(f);                   break;
      case FUNCTION_TYPE_COS:    f = cos(f);                   break;
      case FUNCTION_TYPE_TAN:    f = tan(f);                   break;
      case FUNCTION_TYPE_ASIN:   f = asin(f);                  break;
      case FUNCTION_TYPE_ACOS:   f = acos(f);                  break;
      case FUNCTION_TYPE_ATAN:   f = atan(f);                  break;
      case FUNCTION_TYPE_SINH:   f = sinh(f);                  break;
      case FUNCTION_TYPE_COSH:   f = cosh(f);                  break;
      case FUNCTION_TYPE_TANH:   f = tanh(f);                  break;
      case FUNCTION_TYPE_EXP:    f = exp(f);                   break;
      case FUNCTION_TYPE_LOG:    f = log(f);                   break;
      case FUNCTION_TYPE_LOG10:  f = log10(f);                 break;
      case FUNCTION_TYPE_SQRT:   f = sqrt(f);                  break;
      default:
	return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
      }
      if ((r = value_extend_value(valuep)) < 0)
	return r;
      if ((r = value_set_float(*valuep, f)) < 0)
	return r;
      valuep = &(*valuep)->next;
    }
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_pi(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_PI, valuep, args);
}

static int function_radian(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_RADIAN, valuep, args);
}

static int function_degree(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_DEGREE, valuep, args);
}

static int function_sin(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_SIN, valuep, args);
}

static int function_cos(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_COS, valuep, args);
}

static int function_tan(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_TAN, valuep, args);
}

static int function_asin(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_ASIN, valuep, args);
}

static int function_acos(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_ACOS, valuep, args);
}

static int function_atan(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_ATAN, valuep, args);
}

static int function_sinh(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_SINH, valuep, args);
}

static int function_cosh(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_COSH, valuep, args);
}

static int function_tanh(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_TANH, valuep, args);
}

static int function_exp(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_EXP, valuep, args);
}

static int function_log(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_LOG, valuep, args);
}

static int function_log10(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_LOG10, valuep, args);
}

static int function_sqrt(value_t *valuep, value_t args)
{
  return function_mathfunc(FUNCTION_TYPE_SQRT, valuep, args);
}

static int function_mathfunc2(function_type_t type, value_t *valuep, value_t args)
{
#ifndef NLL_FLOATING_POINT
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  double f0, f1;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_float_integer(args, &f0)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_float_integer(args, &f1)) < 0)
    return r;

  switch (type) {
  case FUNCTION_TYPE_ATAN2: f0 = atan2(f0, f1); break;
  case FUNCTION_TYPE_POW:   f0 = pow(f0, f1);   break;
  case FUNCTION_TYPE_FMOD:  f0 = fmod(f0, f1);  break;
  default:
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_float(*valuep, f0)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_atan2(value_t *valuep, value_t args)
{
  return function_mathfunc2(FUNCTION_TYPE_ATAN2, valuep, args);
}

static int function_pow(value_t *valuep, value_t args)
{
  return function_mathfunc2(FUNCTION_TYPE_POW, valuep, args);
}

static int function_fmod(value_t *valuep, value_t args)
{
  return function_mathfunc2(FUNCTION_TYPE_FMOD, valuep, args);
}

static int function_mathvalue(function_type_t type, value_t *valuep, value_t args)
{
#ifndef NLL_FLOATING_POINT
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  double f;

  if (!args) {
    switch (type) {
#ifdef USE_MATHBUILTIN
    case FUNCTION_TYPE_INFINITY: f = INFINITY; break;
    case FUNCTION_TYPE_NAN:      f = NAN;      break;
#endif
    default:
      return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
    }
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_float(*valuep, f)) < 0)
      return r;
    valuep = &(*valuep)->next;
  } else {
    for (; args; args = args->next) {
      switch (type) {
#ifdef USE_MATHBUILTIN
      case FUNCTION_TYPE_INFINITY: f = INFINITY; break;
      case FUNCTION_TYPE_NAN:      f = NAN;      break;
#endif
      default:
	return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
      }
      if ((r = value_extend_value(valuep)) < 0)
	return r;
      if ((r = value_set_float(*valuep, f)) < 0)
	return r;
      valuep = &(*valuep)->next;
    }
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_infinity(value_t *valuep, value_t args)
{
  return function_mathvalue(FUNCTION_TYPE_INFINITY, valuep, args);
}

static int function_nan(value_t *valuep, value_t args)
{
  return function_mathvalue(FUNCTION_TYPE_NAN, valuep, args);
}

static int function_mathcheck(function_type_t type, value_t *valuep, value_t args)
{
#ifndef NLL_FLOATING_POINT
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, is = 0;
  double f;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;

  for (; args; args = args->next) {
    if ((r = value_get_float_integer(args, &f)) < 0)
      return r;
    switch (type) {
#ifdef USE_MATHBUILTIN
    case FUNCTION_TYPE_ISFINITE: is = isfinite(f) ? 1 : 0; break;
    case FUNCTION_TYPE_ISINF   : is = isinf(f)    ? 1 : 0; break;
    case FUNCTION_TYPE_ISNAN   : is = isnan(f)    ? 1 : 0; break;
    case FUNCTION_TYPE_ISNORMAL: is = isnormal(f) ? 1 : 0; break;
#endif
    default:
      return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
    }
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, is)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_isfinite(value_t *valuep, value_t args)
{
  return function_mathcheck(FUNCTION_TYPE_ISFINITE, valuep, args);
}

static int function_isinf(value_t *valuep, value_t args)
{
  return function_mathcheck(FUNCTION_TYPE_ISINF, valuep, args);
}

static int function_isnan(value_t *valuep, value_t args)
{
  return function_mathcheck(FUNCTION_TYPE_ISNAN, valuep, args);
}

static int function_isnormal(value_t *valuep, value_t args)
{
  return function_mathcheck(FUNCTION_TYPE_ISNORMAL, valuep, args);
}
#endif

#define FD_FLAG_SOCKET 0x40000000

static int issocket(int fd)
{
  return (fd & FD_FLAG_SOCKET) ? 1 : 0;
}

#ifdef NLL_NETWORK_FUNCTION
static int fd2socket(int fd)
{
  return fd | FD_FLAG_SOCKET;
}
#endif

static int socket2fd(int sockt)
{
  return sockt & ~FD_FLAG_SOCKET;
}

static int function_rename(value_t *valuep, value_t args)
{
  int r, result;
  char *from, *to;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &from, NULL)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &to, NULL)) < 0)
    return r;

  if (!from || !to)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  result = rename(from, to);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_unlink(value_t *valuep, value_t args)
{
  int r, result;
  char *filename;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &filename, NULL)) < 0)
    return r;

  if (!filename)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  result = unlink(filename);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_truncate(value_t *valuep, value_t args)
{
  int r, result;
  char *filename;
  integer_t length = 0;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &filename, NULL)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &length)) < 0)
      ;
  }

  if (!filename)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

#ifndef WIN32
  result = truncate(filename, length);
#else
  result = -1;
#endif

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_mkdir(value_t *valuep, value_t args)
{
  int r, result;
  char *filename;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &filename, NULL)) < 0)
    return r;

  if (!filename)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

#ifndef WIN32
  result = mkdir(filename, 0755);
#else
  result = mkdir(filename);
#endif

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_rmdir(value_t *valuep, value_t args)
{
  int r, result;
  char *filename;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &filename, NULL)) < 0)
    return r;

  if (!filename)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  result = rmdir(filename);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_chdir(value_t *valuep, value_t args)
{
  int r, result;
  char *filename;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &filename, NULL)) < 0)
    return r;

  if (!filename)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  result = chdir(filename);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_open(value_t *valuep, value_t args)
{
  int r, fd = -1;
  integer_t flags = O_RDWR;
  char *filename;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &filename, NULL)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
  }

  if (!filename)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  fd = open(filename, flags);

  if ((r = value_extend_value(valuep)) < 0)
    goto err;
  if ((r = value_set_integer(*valuep, fd)) < 0)
    goto err;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    goto err;

  return 0;

err:
  if (fd >= 0)
    close(fd);
  return r;
}

static int fd_close(int fd)
{
  int r;

  if (issocket(fd)) {
    fd = socket2fd(fd);
#ifdef WIN32
#ifdef NLL_NETWORK_FUNCTION
    r = closesocket(fd);
#else
    r = -1;
#endif
#else
    r = close(fd);
#endif
  } else {
    r = close(fd);
  }

  return r;
}

static int function_close(value_t *valuep, value_t args)
{
  int r, result;
  integer_t fd;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &fd)) < 0)
    return r;

  result = fd_close(fd);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_read(value_t *valuep, value_t args)
{
  int r;
  area_t area;
  integer_t fd, offset = 0, size = -1;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &fd)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &area)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
  }

  if (!area)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  fd = socket2fd(fd);

  if (size < 0)
    size = area_get_size(area) - offset;

  if (size < 0)
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  if ((offset < 0) || (offset + size > area_get_size(area)))
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  size = read(fd, area_get_buffer(area) + offset, size);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, size)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_write(value_t *valuep, value_t args)
{
  int r;
  area_t area;
  integer_t fd, offset = 0, size = -1;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &fd)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &area)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
  }

  if (!area)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  fd = socket2fd(fd);

  if (size < 0)
    size = area_get_size(area) - offset;

  if (size < 0)
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  if ((offset < 0) || (offset + size > area_get_size(area)))
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  size = write(fd, area_get_buffer(area) + offset, size);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, size)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_lseek(value_t *valuep, value_t args)
{
  int r, result;
  integer_t fd, offset = 0, whence = SEEK_SET;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &fd)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &whence)) < 0)
      ;
  }

  fd = socket2fd(fd);

  result = lseek(fd, offset, whence);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_ftruncate(value_t *valuep, value_t args)
{
  int r, result;
  integer_t fd, length = 0;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &fd)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &length)) < 0)
      ;
  }

  fd = socket2fd(fd);

  result = ftruncate(fd, length);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_isreadable(value_t *valuep, value_t args)
{
  int r, fdmax;
  integer_t fd, interval = -1;
  fd_set fds;
  struct timeval t, *tp;

  if (args) {
    if ((r = value_get_integer(args, &interval)) < 0)
      ;
    args = args->next;
  }

  fdmax = -1;
  FD_ZERO(&fds);

  for (; args; args = args->next) {
    if ((r = value_get_integer(args, &fd)) < 0)
      return r;
    fd = socket2fd(fd);
    if (fdmax < fd)
      fdmax = fd;
    FD_SET(fd, &fds);
  }

  if (interval < 0) {
    tp = NULL;
  } else {
    t.tv_sec  = interval / 100;
    t.tv_usec = (interval % 100) * 10000;
    tp = &t;
  }

  r = select(fdmax + 1, &fds, NULL, NULL, tp);

  if (r < 0) {
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, -1)) < 0)
      return r;
    valuep = &(*valuep)->next;
  } else if (r == 0) {
    /* none */
  } else {
    for (fd = 0; fd <= fdmax; fd++) {
      if (FD_ISSET(fd, &fds)) {
	if ((r = value_extend_value(valuep)) < 0)
	  return r;
	if ((r = value_set_integer(*valuep, fd)) < 0)
	  return r;
	valuep = &(*valuep)->next;
      }
    }
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_iswritable(value_t *valuep, value_t args)
{
  int r, fdmax;
  integer_t fd, interval = -1;
  fd_set fds;
  struct timeval t, *tp;

  if (args) {
    if ((r = value_get_integer(args, &interval)) < 0)
      ;
    args = args->next;
  }

  fdmax = -1;
  FD_ZERO(&fds);

  for (; args; args = args->next) {
    if ((r = value_get_integer(args, &fd)) < 0)
      return r;
    fd = socket2fd(fd);
    if (fdmax < fd)
      fdmax = fd;
    FD_SET(fd, &fds);
  }

  if (interval < 0) {
    tp = NULL;
  } else {
    t.tv_sec  = interval / 100;
    t.tv_usec = (interval % 100) * 10000;
    tp = &t;
  }

  r = select(fdmax + 1, NULL, &fds, NULL, tp);

  if (r < 0) {
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, -1)) < 0)
      return r;
    valuep = &(*valuep)->next;
  } else if (r == 0) {
    /* none */
  } else {
    for (fd = 0; fd <= fdmax; fd++) {
      if (FD_ISSET(fd, &fds)) {
	if ((r = value_extend_value(valuep)) < 0)
	  return r;
	if ((r = value_set_integer(*valuep, fd)) < 0)
	  return r;
	valuep = &(*valuep)->next;
      }
    }
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fopen(value_t *valuep, value_t args)
{
  int r;
  char *filename, *mode = "r";
  FILE *fp = NULL;
  fileid_id_t id = 0;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &filename, NULL)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_string(args, &mode, NULL)) < 0)
      ;
    if (!mode)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;
  }

  if (!filename)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  id = fileid_create(NULL);
  if (id < 0)
    return NLL_ERRCODE_MEMORY_BUFFER_OVER;

  fp = fopen(filename, mode);
  if (!fp) {
    if (id > 0)
      fileid_destroy(id);
    id = -1;
  } else {
    if (fileid_set_fp(id, fp) < 0) {
      r = NLL_ERRCODE_VALUE_INVALID_TYPE;
      goto err;
    }
    fp = NULL;
  }

  if ((r = value_extend_value(valuep)) < 0)
    goto err;
  if ((r = value_set_integer(*valuep, id)) < 0)
    goto err;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    goto err;

  return 0;

err:
  if (id > 0)
    fileid_destroy(id);
  if (fp)
    fclose(fp);
  return r;
}

static int function_fdopen(value_t *valuep, value_t args)
{
  int r;
  integer_t fd;
  char *mode = "r";
  FILE *fp = NULL;
  fileid_id_t id = 0;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &fd)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_string(args, &mode, NULL)) < 0)
      ;
    if (!mode)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;
  }

  fd = socket2fd(fd);

  id = fileid_create(NULL);
  if (id < 0)
    return NLL_ERRCODE_MEMORY_BUFFER_OVER;

  fp = fdopen(fd, mode);
  if (!fp) {
    if (id > 0)
      fileid_destroy(id);
    id = -1;
  } else {
    if (fileid_set_fp(id, fp) < 0) {
      r = NLL_ERRCODE_VALUE_INVALID_TYPE;
      goto err;
    }
    fp = NULL;
  }

  if ((r = value_extend_value(valuep)) < 0)
    goto err;
  if ((r = value_set_integer(*valuep, id)) < 0)
    goto err;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    goto err;

  return 0;

err:
  if (id > 0)
    fileid_destroy(id);
  if (fp)
    fclose(fp);
  return r;
}

static int function_fclose(value_t *valuep, value_t args)
{
  int r, result;
  integer_t id;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &id)) < 0)
    return r;

  result = fileid_destroy(id);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fileno(value_t *valuep, value_t args)
{
  int r, result = -1;
  integer_t id;
  FILE *fp;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &id)) < 0)
    return r;

  fp = fileid_get_fp(id);
  if (fp)
    result = fileno(fp);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_feof(value_t *valuep, value_t args)
{
  int r, result = -1;
  integer_t id = 0;
  FILE *fp;

  if (args) {
    if ((r = value_get_integer(args, &id)) < 0)
      ;
  }

  fp = !id ? nll_stdin : fileid_get_fp(id);
  if (fp)
    result = feof(fp);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_ferror(value_t *valuep, value_t args)
{
  int r, result = -1;
  integer_t id = 0;
  FILE *fp;

  if (args) {
    if ((r = value_get_integer(args, &id)) < 0)
      ;
  }

  fp = !id ? nll_stdout : fileid_get_fp(id);
  if (fp)
    result = ferror(fp);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fgetc(value_t *valuep, value_t args)
{
  int r, c = -1;
  integer_t id = 0;
  FILE *fp;

  if (args) {
    if ((r = value_get_integer(args, &id)) < 0)
      ;
  }

  fp = !id ? nll_stdin : fileid_get_fp(id);
  if (fp)
    c = fgetc(fp);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if (c == EOF) {
    if ((r = value_set_null(*valuep)) < 0)
      return r;
  } else {
    if ((r = value_set_integer(*valuep, c)) < 0)
      return r;
  }
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fputc(value_t *valuep, value_t args)
{
  int r, result = -1;
  integer_t id = 0, c = '\n';
  FILE *fp;

  if (args) {
    if ((r = value_get_integer(args, &id)) < 0)
      ;
    args = args->next;
  }

  fp = !id ? nll_stdout : fileid_get_fp(id);

  for (; args; args = args->next) {
    if ((r = value_get_integer(args, &c)) < 0)
      return r;

    if (fp) {
      result = fputc(c, fp);
      fflush(fp);
    } else {
      result = -1;
    }

    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, result)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fgets(value_t *valuep, value_t args)
{
  int r;
  integer_t id = 0;
  char *buffer;
  FILE *fp;

  if (args) {
    if ((r = value_get_integer(args, &id)) < 0)
      ;
  }

  buffer = string_buffer();

  fp = !id ? nll_stdin : fileid_get_fp(id);
  if (fp && fgets(buffer, string_buffer_size(), fp)) {
    ;
  } else {
    buffer = NULL;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if (!buffer) {
    if ((r = value_set_null(*valuep)) < 0)
      return r;
  } else {
    if ((r = value_set_string(*valuep, buffer, -1)) < 0)
      return r;
  }
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fputs(value_t *valuep, value_t args)
{
  int r, length;
  integer_t id = 0;
  char *string;
  FILE *fp;

  if (args) {
    if ((r = value_get_integer(args, &id)) < 0)
      ;
    args = args->next;
  }

  fp = !id ? nll_stdout : fileid_get_fp(id);

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &string, &length)) < 0)
      return r;

    if (!string) {
      string = "";
      length = 0;
    }

    if (fp && (fputs(string, fp) >= 0)) {
      fflush(fp);
    } else {
      length = -1;
    }

    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, length)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fprintf(value_t *valuep, value_t args)
{
  int r, n;
  integer_t id = 0;
  char *format;
  char *buffer;
  FILE *fp;

  if (args) {
    if ((r = value_get_integer(args, &id)) < 0)
      ;
    args = args->next;
  }

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &format, NULL)) < 0)
    return r;
  args = args->next;

  format = format ? format : "";
  buffer = string_buffer();

  n = nll_sprintf(buffer, string_buffer_size(), format, args);
  if (n > 0) {
    fp = !id ? nll_stdout : fileid_get_fp(id);
    if (fp && (fputs(buffer, fp) >= 0)) {
      fflush(fp);
    } else {
      n = -1;
    }
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, n)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fread(value_t *valuep, value_t args)
{
  int r;
  area_t area;
  integer_t id = 0, offset = 0, size = -1;
  FILE *fp;

  if (args) {
    if ((r = value_get_integer(args, &id)) < 0)
      ;
    args = args->next;
  }

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &area)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
  }

  if (!area)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  if (size < 0)
    size = area_get_size(area) - offset;

  if (size < 0)
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  if ((offset < 0) || (offset + size > area_get_size(area)))
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  fp = !id ? nll_stdin : fileid_get_fp(id);
  if (fp) {
    size = fread(area_get_buffer(area) + offset, 1, size, fp);
  } else {
    size = -1;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, size)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fwrite(value_t *valuep, value_t args)
{
  int r;
  area_t area;
  integer_t id = 0, offset = 0, size = -1;
  FILE *fp;

  if (args) {
    if ((r = value_get_integer(args, &id)) < 0)
      ;
    args = args->next;
  }

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &area)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
  }

  if (!area)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  if (size < 0)
    size = area_get_size(area) - offset;

  if (size < 0)
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  if ((offset < 0) || (offset + size > area_get_size(area)))
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  fp = !id ? nll_stdout : fileid_get_fp(id);
  if (fp) {
    size = fwrite(area_get_buffer(area) + offset, 1, size, fp);
    fflush(fp);
  } else {
    size = -1;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, size)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_fseek(value_t *valuep, value_t args)
{
  int r, result = -1;
  integer_t id = 0, offset = 0, whence = SEEK_SET;
  FILE *fp;

  if (args) {
    if ((r = value_get_integer(args, &id)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &whence)) < 0)
      ;
  }

  fp = !id ? nll_stdin : fileid_get_fp(id);
  if (fp)
    result = fseek(fp, offset, whence);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_qopen(value_t *valuep, value_t args)
{
  int r;
  queueid_index_t index;

  index = queueid_create();
  if (index < 0)
    return NLL_ERRCODE_MEMORY_BUFFER_OVER;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, index)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_qclose(value_t *valuep, value_t args)
{
  int r, result;
  integer_t index;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &index)) < 0)
    return r;

  result = queueid_destroy(index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_qlength(value_t *valuep, value_t args)
{
  int r, result;
  integer_t index;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &index)) < 0)
    return r;

  result = queueid_number(index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_qpushf(value_t *valuep, value_t args)
{
  int r, n = 0;
  integer_t index;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &index)) < 0)
    return r;
  args = args->next;

  for (; args; args = args->next, n++) {
    if (queueid_headin(index, args) < 0)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, n)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_qpopl(value_t *valuep, value_t args)
{
  int r, i;
  integer_t index, n = 1;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &index)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &n)) < 0)
      ;
  }

  for (i = 0; i < n; i++) {
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if (queueid_headout(index, *valuep) < 0)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_qpushl(value_t *valuep, value_t args)
{
  int r, n = 0;
  integer_t index;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &index)) < 0)
    return r;
  args = args->next;

  for (; args; args = args->next, n++) {
    if (queueid_tailin(index, args) < 0)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, n)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_qpopf(value_t *valuep, value_t args)
{
  int r, i;
  integer_t index, n = 1;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &index)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &n)) < 0)
      ;
  }

  for (i = 0; i < n; i++) {
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if (queueid_tailout(index, *valuep) < 0)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

#ifdef NLL_NETWORK_FUNCTION
#ifdef WIN32
int winsock_init()
{
  static int initialized = 0;
  WSADATA wsaData;

  if (!initialized) {
    if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;
    initialized = 1;
  }

  return 0;
}
#endif

static int function_sockaddr(value_t *valuep, value_t args)
{
  int r, length;
  integer_t af, port;
  char *addrstr;
  area_t addr;
  struct sockaddr *saddr;
  socklen_t ssize;
#ifndef WIN32
  struct sockaddr_un unaddr;
#endif
  struct sockaddr_in inaddr;
#ifndef WIN32
  struct sockaddr_in6 inaddr6;
#endif

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &af)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &addrstr, &length)) < 0)
    return r;
  args = args->next;

  if (!addrstr)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

#ifdef WIN32
  if ((r = winsock_init()) < 0)
    return r;
#endif

  switch (af) {
#ifndef WIN32
  case AF_UNIX:
    memset(&unaddr, 0, sizeof(unaddr));
    unaddr.sun_family = AF_UNIX;
    if (sizeof(unaddr.sun_path) < length + 1)
      return NLL_ERRCODE_STRING_TOO_LONG;
    strcpy(unaddr.sun_path, addrstr);

    saddr = (struct sockaddr *)&unaddr;
#ifdef SUN_LEN
    ssize = SUN_LEN(&unaddr);
#else
    ssize = sizeof(unaddr);
#endif

    break;
#endif

  case AF_INET:
    if (!args)
      return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
    if ((r = value_get_integer(args, &port)) < 0)
      return r;

    memset(&inaddr, 0, sizeof(inaddr));
    inaddr.sin_family = AF_INET;
    inaddr.sin_port = htons(port);
#ifndef WIN32
    if (inet_aton(addrstr, &inaddr.sin_addr) <= 0)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;
#else
    inaddr.sin_addr.s_addr = inet_addr(addrstr);
#endif

    saddr = (struct sockaddr *)&inaddr;
    ssize = sizeof(inaddr);

    break;

#ifndef WIN32
  case AF_INET6:
    if (!args)
      return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
    if ((r = value_get_integer(args, &port)) < 0)
      return r;

    memset(&inaddr6, 0, sizeof(inaddr6));
    inaddr6.sin6_family = AF_INET6;
    inaddr6.sin6_port = htons(port);
    if (inet_pton(AF_INET6, addrstr, &inaddr6.sin6_addr) <= 0)
      return NLL_ERRCODE_VALUE_INVALID_TYPE;

    saddr = (struct sockaddr *)&inaddr6;
    ssize = sizeof(inaddr6);

    break;
#endif

  default:
    return NLL_ERRCODE_VALUE_INVALID_TYPE;
  }

  if ((r = area_alloc(&addr, ssize)) < 0)
    return r;
  if ((r = area_write(addr, 0, (char *)saddr, ssize)) < 0)
    return r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_area(*valuep, addr)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_socket(value_t *valuep, value_t args)
{
  int r, sockt;
  integer_t domain, type, protocol = 0;

  if (nll_is_nosystem() || nll_is_nonetwork())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &domain)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &type)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &protocol)) < 0)
      ;
  }

#ifdef WIN32
  if ((r = winsock_init()) < 0)
    return r;
#endif

  sockt = socket(domain, type, protocol);
  if (sockt >= 0)
    sockt = fd2socket(sockt);

  if ((r = value_extend_value(valuep)) < 0)
    goto err;
  if ((r = value_set_integer(*valuep, sockt)) < 0)
    goto err;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    goto err;

  return 0;

err:
  fd_close(sockt);
  return r;
}

static int function_bind(value_t *valuep, value_t args)
{
  int r, result;
  integer_t sockt;
  area_t addr;
  struct sockaddr *saddr;
  socklen_t ssize;
#ifndef WIN32
  int optval = 1;
  int *optvalp = &optval;
#else
  BOOL optval = TRUE;
  char *optvalp = (char *)&optval;
#endif

  if (nll_is_nosystem() || nll_is_nonetwork())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &sockt)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &addr)) < 0)
    return r;

  if (!addr)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

#ifdef WIN32
  if ((r = winsock_init()) < 0)
    return r;
#endif

  if (!issocket(sockt))
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  sockt = socket2fd(sockt);

  saddr = (struct sockaddr *)area_get_buffer(addr);
  ssize = area_get_size(addr);

  if (setsockopt(sockt, SOL_SOCKET, SO_REUSEADDR, optvalp, sizeof(optval)) < 0)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  result = bind(sockt, saddr, ssize);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_listen(value_t *valuep, value_t args)
{
  int r, result;
  integer_t sockt, backlog = 5;

  if (nll_is_nosystem() || nll_is_nonetwork())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &sockt)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &backlog)) < 0)
      ;
  }

#ifdef WIN32
  if ((r = winsock_init()) < 0)
    return r;
#endif

  if (!issocket(sockt))
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  sockt = socket2fd(sockt);

  result = listen(sockt, backlog);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_accept(value_t *valuep, value_t args)
{
  int r, result;
  integer_t sockt;
  area_t addr = NULL;
  struct sockaddr *saddr = NULL;
  socklen_t ssize, *ssizep = NULL;

  if (nll_is_nosystem() || nll_is_nonetwork())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &sockt)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_area(args, &addr)) < 0)
      ;
  }

#ifdef WIN32
  if ((r = winsock_init()) < 0)
    return r;
#endif

  if (!issocket(sockt))
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  sockt = socket2fd(sockt);

  if (addr) {
    saddr = (struct sockaddr *)area_get_buffer(addr);
    ssize = area_get_size(addr);
    ssizep = &ssize;
  }

  result = accept(sockt, saddr, ssizep);
  if (result >= 0)
    result = fd2socket(result);

  if ((r = value_extend_value(valuep)) < 0)
    goto err;
  if ((r = value_set_integer(*valuep, result)) < 0)
    goto err;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    goto err;

  return 0;

err:
  fd_close(result);
  return r;
}

static int function_connect(value_t *valuep, value_t args)
{
  int r, result;
  integer_t sockt;
  area_t addr;
  struct sockaddr *saddr;
  socklen_t ssize;

  if (nll_is_nosystem() || nll_is_nonetwork())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &sockt)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &addr)) < 0)
    return r;

  if (!addr)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

#ifdef WIN32
  if ((r = winsock_init()) < 0)
    return r;
#endif

  if (!issocket(sockt))
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  sockt = socket2fd(sockt);

  saddr = (struct sockaddr *)area_get_buffer(addr);
  ssize = area_get_size(addr);

  result = connect(sockt, saddr, ssize);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_shutdown(value_t *valuep, value_t args)
{
  int r, result;
  integer_t sockt, how = 0;

  if (nll_is_nosystem() || nll_is_nonetwork())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &sockt)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &how)) < 0)
      ;
  }

#ifdef WIN32
  if ((r = winsock_init()) < 0)
    return r;
#endif

  if (!issocket(sockt))
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  sockt = socket2fd(sockt);

  result = shutdown(sockt, how);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_recv(value_t *valuep, value_t args)
{
  int r;
  area_t area;
  integer_t sockt, offset = 0, size = -1, flags = 0;

  if (nll_is_nosystem() || nll_is_nonetwork())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &sockt)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &area)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
  }

  if (!area)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

#ifdef WIN32
  if ((r = winsock_init()) < 0)
    return r;
#endif

  if (!issocket(sockt))
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  sockt = socket2fd(sockt);

  if (size < 0)
    size = area_get_size(area) - offset;

  if (size < 0)
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  if ((offset < 0) || (offset + size > area_get_size(area)))
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  size = recv(sockt, area_get_buffer(area) + offset, size, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, size)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_send(value_t *valuep, value_t args)
{
  int r;
  area_t area;
  integer_t sockt, offset = 0, size = -1, flags = 0;

  if (nll_is_nosystem() || nll_is_nonetwork())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &sockt)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &area)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
  }

  if (!area)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

#ifdef WIN32
  if ((r = winsock_init()) < 0)
    return r;
#endif

  if (!issocket(sockt))
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  sockt = socket2fd(sockt);

  if (size < 0)
    size = area_get_size(area) - offset;

  if (size < 0)
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  if ((offset < 0) || (offset + size > area_get_size(area)))
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  size = send(sockt, area_get_buffer(area) + offset, size, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, size)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_recvfrom(value_t *valuep, value_t args)
{
  int r;
  area_t area, addr = NULL;
  integer_t sockt, offset = 0, size = -1, flags = 0;
  struct sockaddr *saddr = NULL;
  socklen_t ssize, *ssizep = NULL;

  if (nll_is_nosystem() || nll_is_nonetwork())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &sockt)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &area)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_area(args, &addr)) < 0)
      ;
  }

  if (!area)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

#ifdef WIN32
  if ((r = winsock_init()) < 0)
    return r;
#endif

  if (!issocket(sockt))
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  sockt = socket2fd(sockt);

  if (size < 0)
    size = area_get_size(area) - offset;

  if (size < 0)
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  if ((offset < 0) || (offset + size > area_get_size(area)))
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  if (addr) {
    saddr = (struct sockaddr *)area_get_buffer(addr);
    ssize = area_get_size(addr);
    ssizep = &ssize;
  }

  size = recvfrom(sockt, area_get_buffer(area) + offset, size, flags,
		  saddr, ssizep);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, size)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_sendto(value_t *valuep, value_t args)
{
  int r;
  area_t area, addr;
  integer_t sockt, offset = 0, size = -1, flags = 0;
  struct sockaddr *saddr;
  socklen_t ssize;

  if (nll_is_nosystem() || nll_is_nonetwork())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &sockt)) < 0)
    return r;
  args = args->next;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &area)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &offset)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &size)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_area(args, &addr)) < 0)
    return r;

  if (!area || !addr)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

#ifdef WIN32
  if ((r = winsock_init()) < 0)
    return r;
#endif

  if (!issocket(sockt))
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  sockt = socket2fd(sockt);

  if (size < 0)
    size = area_get_size(area) - offset;

  if (size < 0)
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  if ((offset < 0) || (offset + size > area_get_size(area)))
    return NLL_ERRCODE_AREA_OUT_OF_RANGE;

  saddr = (struct sockaddr *)area_get_buffer(addr);
  ssize = area_get_size(addr);

  size = sendto(sockt, area_get_buffer(area) + offset, size, flags,
		saddr, ssize);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, size)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}
#endif

static int function_keyname(value_t *valuep, value_t args)
{
  int r;
  integer_t keycode;
  const char *keyname;

  for (; args; args = args->next) {
    if ((r = value_get_integer(args, &keycode)) < 0)
      return r;
    keyname = keyname_get(keycode);
    if (!keyname) keyname = "";
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_string(*valuep, keyname, -1)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_keycode(value_t *valuep, value_t args)
{
  int r;
  char *keyname;
  key_code_t keycode;

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &keyname, NULL)) < 0)
      return r;
    if (!keyname)
      continue;
    keycode = keycode_get(keyname);
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, keycode)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
}

static int function_screen(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t flags = -1, width = -1, height = -1;

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &width)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height)) < 0)
      ;
  }

  result = framebuf_setscreen(flags, width, height);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_scrstat(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, framebuf_get_screen_flags())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, framebuf_get_screen_width())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, framebuf_get_screen_height())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_flush(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t flags = 0;

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
  }

  result = framebuf_flush(flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_getcolor(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, framebuf_get_cursor_fgcolor())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, framebuf_get_cursor_bgcolor())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_getfgcolor(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, framebuf_get_cursor_fgcolor())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_getbgcolor(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, framebuf_get_cursor_bgcolor())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_setcolor(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t fgcolor = -1, bgcolor = -1;

  if (args) {
    if ((r = value_get_integer(args, &fgcolor)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &bgcolor)) < 0)
      ;
  }

  result = framebuf_setfgcolor(fgcolor);
  framebuf_setbgcolor(bgcolor);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_getattr(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, framebuf_get_cursor_effect())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_setattr(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t effect = -1;

  if (args) {
    if ((r = value_get_integer(args, &effect)) < 0)
      ;
  }

  result = framebuf_seteffect(effect);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_getpos(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, framebuf_get_cursor_x())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, framebuf_get_cursor_y())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_move(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x = -1, y = -1, dx = 0, dy = 0;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &dx)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &dy)) < 0)
      ;
  }

  result = framebuf_move_cursor(x, y);

  if      (dx < 0) framebuf_move_left(-dx);
  else if (dx > 0) framebuf_move_right(dx);

  if      (dy < 0) framebuf_move_up(-dy);
  else if (dy > 0) framebuf_move_down(dy);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_getch(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  integer_t x = -1, y = -1;
  int ch;
  char s[2];

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
  }

  ch = framebuf_getch(x, y);

  s[0] = ch;
  s[1] = '\0';

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_string(*valuep, s, -1)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_clear(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t ch = ' ', flags = 0;

  if (args) {
    if ((r = value_get_integer(args, &ch)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
  }

  result = framebuf_clear(ch, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_scroll(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x = 0, y = 0, ch = -1;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &ch)) < 0)
      ;
  }

  result = framebuf_scroll(x, y, ch);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_line(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x0 = NLL_F_CURSORPOS, y0 = NLL_F_CURSORPOS;
  integer_t x1 = NLL_F_CURSORPOS, y1 = NLL_F_CURSORPOS;
  char *string = "";

  if (args) {
    if ((r = value_get_integer_float(args, &x0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &x1)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y1)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_string(args, &string, NULL)) < 0)
      ;
  }

  string = string ? string : "";

  result = framebuf_line(x0, y0, x1, y1, string);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_box(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x0 = NLL_F_CURSORPOS, y0 = NLL_F_CURSORPOS;
  integer_t x1 = NLL_F_CURSORPOS, y1 = NLL_F_CURSORPOS;
  integer_t flags = 0;
  char *string = "";

  if (args) {
    if ((r = value_get_integer_float(args, &x0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &x1)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y1)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_string(args, &string, NULL)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
  }

  string = string ? string : "";

  result = framebuf_box(x0, y0, x1, y1, string, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_inkey(value_t *valuep, value_t args)
{
#ifndef USE_FRAMEBUF
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  integer_t integer;
  char key[2];
  const char *p;

  integer = framebuf_getkey();

  switch (integer) {
  case KEY_CODE_END:
  case KEY_CODE_UP:
  case KEY_CODE_DOWN:
  case KEY_CODE_RIGHT:
  case KEY_CODE_LEFT:
  case KEY_CODE_PAGEUP:
  case KEY_CODE_PAGEDOWN:
    p = keyname_get(integer);
    break;
  default:
    key[0] = integer;
    key[1] = '\0';
    p = key;
    break;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_string(*valuep, p, -1)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gscreen(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t flags = -1, width = -1, height = -1, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &width)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_setscreen(flags, width, height, index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gscrstat(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, graphic_get_screen_flags())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, graphic_get_screen_width())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, graphic_get_screen_height())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, graphic_get_screen_image())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gcolor(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  integer_t red = 0, green = 0, blue = 0;
  int color;

  if (args) {
    if ((r = value_get_integer(args, &red)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &green)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &blue)) < 0)
      ;
  }

  color = graphic_color(red, green, blue);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, color)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_grgb(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  integer_t color = 0;
  int red, green, blue;

  if (args) {
    if ((r = value_get_integer(args, &color)) < 0)
      ;
  }

  graphic_rgb(color, &red, &green, &blue);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, red)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, green)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, blue)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gsync(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;

  result = graphic_sync();

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gflush(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t flags = 0;

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
  }

  result = graphic_flush(flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_ggetmainimg(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;

  result = graphic_getmainimage();

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gsetmainimg(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_setmainimage(index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_ggetsize(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  integer_t index = NLL_G_MAINIMG;
  int width, height;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  width  = graphic_getwidth(index);
  height = graphic_getheight(index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, width)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, height)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_ggetrange(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  integer_t index = NLL_G_MAINIMG;
  int x = 0, y = 0, width = 0, height = 0, mulx = 0, muly = 0;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  graphic_getrange(index, &x, &y, &width, &height, &mulx, &muly);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, x)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, y)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, width)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, height)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, mulx)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, muly)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gsetrange(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x = 0, y = 0, width = 0, height = 0, mulx = 0, muly = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &width)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &mulx)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &muly)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_setrange(index, x, y, width, height, mulx, muly);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_ggetoffset(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  integer_t index = NLL_G_MAINIMG;
  int x = 0, y = 0;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  graphic_getoffset(index, &x, &y);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, x)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, y)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gsetoffset(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x = 0, y = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_setoffset(index, x, y);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_ggetscale(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  integer_t index = NLL_G_MAINIMG;
  int mulx = 0, muly = 0, divx = 0, divy = 0;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  graphic_getscale(index, &mulx, &muly, &divx, &divy);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, mulx)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, muly)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, divx)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, divy)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gsetscale(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t mulx = 0, muly = 0, divx = 0, divy = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &mulx)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &muly)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &divx)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &divy)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_setscale(index, mulx, muly, divx, divy);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_ggetdotoffset(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  integer_t index = NLL_G_MAINIMG;
  int x = 0, y = 0;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  graphic_getdotoffset(index, &x, &y);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, x)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, y)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gsetdotoffset(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x = 0, y = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_setdotoffset(index, x, y);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_ggetdotsize(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  integer_t index = NLL_G_MAINIMG;
  int width = 0, height = 0;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  graphic_getdotsize(index, &width, &height);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, width)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, height)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gsetdotsize(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t width = 0, height = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &width)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_setdotsize(index, width, height);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_ggetcolor(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, color, fgcolor, bgcolor, fromcolor, tocolor;
  integer_t index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  graphic_getcolor(index, &color, &fgcolor, &bgcolor, &fromcolor, &tocolor);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, color)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, fgcolor)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, bgcolor)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, fromcolor)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, tocolor)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gsetcolor(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t color = NLL_G_DEFAULT, fgcolor = NLL_G_DEFAULT, bgcolor = NLL_G_DEFAULT, fromcolor = NLL_G_DEFAULT, tocolor = NLL_G_DEFAULT;
  integer_t flags = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer(args, &color)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &fgcolor)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &bgcolor)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &fromcolor)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &tocolor)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_setcolor(index, color, fgcolor, bgcolor, fromcolor, tocolor, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_ggetpixel(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  integer_t x = -1, y = -1, index = NLL_G_MAINIMG;
  int color;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  color = graphic_getpixel(index, x, y);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, color)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gclear(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t color = 0, flags = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer(args, &color)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_clear(index, color, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gscroll(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x = 0, y = 0, color = 0, flags = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &color)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_scroll(index, x, y, color, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gdot(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x = NLL_G_DEFAULT, y = NLL_G_DEFAULT;
  integer_t color = NLL_G_DEFAULT, flags = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &color)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_dot(index, x, y, color, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gline(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x0 = NLL_G_DEFAULT, y0 = NLL_G_DEFAULT;
  integer_t x1 = NLL_G_DEFAULT, y1 = NLL_G_DEFAULT;
  integer_t color = NLL_G_DEFAULT, flags = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &x1)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y1)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &color)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_line(index, x0, y0, x1, y1, color, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gbox(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x0 = NLL_G_DEFAULT, y0 = NLL_G_DEFAULT;
  integer_t x1 = NLL_G_DEFAULT, y1 = NLL_G_DEFAULT;
  integer_t color = NLL_G_DEFAULT, flags = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &x1)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y1)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &color)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_box(index, x0, y0, x1, y1, color, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gcircle(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x = NLL_G_DEFAULT, y = NLL_G_DEFAULT;
  integer_t rx = 1, ry, color = NLL_G_DEFAULT, flags = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &rx)) < 0)
      ;
    args = args->next;
  }

  ry = rx;

  if (args) {
    if ((r = value_get_integer_float(args, &ry)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &color)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_circle(index, x, y, rx, ry, color, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gpaint(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x = NLL_G_DEFAULT, y = NLL_G_DEFAULT;
  integer_t color = NLL_G_DEFAULT, border = NLL_G_DEFAULT, flags = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &color)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &border)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_paint(index, x, y, color, border, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gcopy(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x0 = NLL_G_DEFAULT, y0 = NLL_G_DEFAULT, width0 = 0, height0 = 0;
  integer_t source = NLL_G_MAINIMG, x = 0, y = 0, width = 0, height = 0;
  integer_t flags = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &width0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &source)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &width)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_copy(index, x0, y0, width0, height0, source, x, y, width, height, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_grotate(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x = NLL_G_DEFAULT, y = NLL_G_DEFAULT, width = 0, height = 0, cx = 0, cy = 0;
  integer_t num = 1, color = 0, flags = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &width)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &cx)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &cy)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &num)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &color)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_rotate(index, x, y, width, height, cx, cy, num, color, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gchar(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x = NLL_G_DEFAULT, y = NLL_G_DEFAULT, width = 0, height = 0;
  integer_t ch = 0, type = NLL_G_FONT8X8;
  integer_t flags = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &width)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &ch)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &type)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_char(index, x, y, width, height, ch, type, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gprint(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result, length = 0;
  integer_t x = NLL_G_DEFAULT, y = NLL_G_DEFAULT, width = 0, height = 0;
  integer_t type = NLL_G_FONT8X8;
  integer_t xgrid = NLL_G_DEFAULT, ygrid = NLL_G_DEFAULT;
  integer_t flags = 0, index = NLL_G_MAINIMG;
  char *string = "";

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &width)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_string(args, &string, &length)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &type)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &xgrid)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &ygrid)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  if (!string) {
    string = "";
    length = 0;
  }

  result = graphic_print(index, x, y, width, height, string, length, type, xgrid, ygrid, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_ginkey(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, keycode;
  const char *keyname;

  keycode = graphic_getkeybuf();
  keyname = keyname_get(keycode);
  if (!keyname) keyname = "";

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_string(*valuep, keyname, -1)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gkeystat(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  char *keyname;
  int keycode, s;

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &keyname, NULL)) < 0)
      return r;
    if (!keyname)
      continue;
    keycode = keycode_get(keyname);
    s = graphic_getkeystatus(keycode);
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, s)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gmousepos(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, x, y;

  if (graphic_getmousepos(&x, &y) < 0) {
    x = -1;
    y = -1;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, x)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, y)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_ginmouse(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, mousecode, x, y;
  const char *mousename;

  mousecode = graphic_getmousebuf(&x, &y);
  mousename = mousename_get(mousecode);
  if (!mousename) {
    mousename = "";
    x = -1;
    y = -1;
  }

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_string(*valuep, mousename, -1)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, x)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, y)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gmousestat(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;
  char *mousename;
  int mousecode, s;

  for (; args; args = args->next) {
    if ((r = value_get_string(args, &mousename, NULL)) < 0)
      return r;
    if (!mousename)
      continue;
    mousecode = mousecode_get(mousename);
    s = graphic_getmousestatus(mousecode);
    if ((r = value_extend_value(valuep)) < 0)
      return r;
    if ((r = value_set_integer(*valuep, s)) < 0)
      return r;
    valuep = &(*valuep)->next;
  }

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gallocimage(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t width = 0, height = 0, flags = 0;

  if (args) {
    if ((r = value_get_integer_float(args, &width)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
  }

  result = graphic_allocimage(width, height, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gfreeimage(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_freeimage(index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gloadimage(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result, width = 0, height = 0;
  integer_t flags = 0;
  char *filename;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &filename, NULL)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
  }

  if (!filename)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  result = graphic_loadimage(filename, &width, &height, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, width)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, height)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gsaveimage(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t source = NLL_G_MAINIMG, x = 0, y = 0, width = 0, height = 0, flags = 0;
  char *filename;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &filename, NULL)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &source)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &width)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
  }

  if (!filename)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  result = graphic_saveimage(filename, source, x, y, width, height, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gcmpimage(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t x0 = NLL_G_DEFAULT, y0 = NLL_G_DEFAULT, width0 = 0, height0 = 0;
  integer_t source = NLL_G_MAINIMG, x = 0, y = 0, width = 0, height = 0;
  integer_t flags = 0, index = NLL_G_MAINIMG;

  if (args) {
    if ((r = value_get_integer_float(args, &x0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &width0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height0)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &source)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &x)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &y)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &width)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer_float(args, &height)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
  }

  result = graphic_cmpimage(index, x0, y0, width0, height0, source, x, y, width, height, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_gcharset(value_t *valuep, value_t args)
{
#ifndef USE_GRAPHIC
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result, width = 0, height = 0, num = 0;
  integer_t type = NLL_G_FONT8X8, flags = 0;

  if (args) {
    if ((r = value_get_integer(args, &type)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
  }

  result = graphic_charset(type, &width, &height, &num, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, width)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, height)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, num)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_astop(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;

  result = audio_stop();

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_aclear(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t aunitset_index = -1;

  if (args) {
    if ((r = value_get_integer(args, &aunitset_index)) < 0)
      ;
  }

  result = audio_clear(aunitset_index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_asound(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t samplefreq = 0;

  if (args) {
    if ((r = value_get_integer(args, &samplefreq)) < 0)
      ;
  }

  result = audio_setsamplefreq(samplefreq);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_asndstat(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, audio_getsamplefreq())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_aplaynum(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, audio_playnum())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_await(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, audio_wait())) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_aunitset(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t aunitset_index = NLL_A_NULLUNITSET;

  if (args) {
    if ((r = value_get_integer(args, &aunitset_index)) < 0)
      ;
  }

  result = audio_unitset(aunitset_index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_aunit(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t output = NLL_A_OUTPUT, amp = AUDIO_PER_NUM, flags = 0, aunitset_index = NLL_A_NULLUNITSET;

  if (args) {
    if ((r = value_get_integer(args, &output)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &amp)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &aunitset_index)) < 0)
      ;
  }

  result = audio_unit(output, amp, flags, aunitset_index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_aosc(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t index = 1, amp = AUDIO_PER_NUM, freq = AUDIO_PER_NUM, phase = 0, type = NLL_A_SIN, mod = NLL_A_PHASE, flags = 0, aunitset_index = NLL_A_NULLUNITSET;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &amp)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &freq)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &phase)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &type)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &mod)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &aunitset_index)) < 0)
      ;
  }

  result = audio_osc(index, amp, freq, phase, type, mod, flags, aunitset_index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_aaddout(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t index = 1, output = NLL_A_OUTPUT, amp = AUDIO_PER_NUM, flags = 0, aunitset_index = NLL_A_NULLUNITSET;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &output)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &amp)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &aunitset_index)) < 0)
      ;
  }

  result = audio_addout(index, output, amp, flags, aunitset_index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_aenvpoint(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t index = 1, n = -1, step = 0, amp = AUDIO_PER_NUM, flags = 0, aunitset_index = NLL_A_NULLUNITSET;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &n)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &step)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &amp)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &aunitset_index)) < 0)
      ;
  }

  result = audio_envpoint(index, n, step, amp, flags, aunitset_index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_aenvcopy(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t index = 1, source = 1, flags = 0, aunitset_index = NLL_A_NULLUNITSET;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &source)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &aunitset_index)) < 0)
      ;
  }

  result = audio_envcopy(index, source, flags, aunitset_index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_afilpoint(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t index = 1, type = NLL_A_FILFW, n = -1, amp = AUDIO_PER_NUM, flags = 0, aunitset_index = NLL_A_NULLUNITSET;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &type)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &n)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &amp)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &aunitset_index)) < 0)
      ;
  }

  result = audio_filpoint(index, type, n, amp, flags, aunitset_index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_afilcopy(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t index = 1, source = 1, flags = 0, aunitset_index = NLL_A_NULLUNITSET;

  if (args) {
    if ((r = value_get_integer(args, &index)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &source)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &aunitset_index)) < 0)
      ;
  }

  result = audio_filcopy(index, source, flags, aunitset_index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_aplay(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  char *mml = NULL, *filename = NULL;
  integer_t flags = NLL_A_FLUSH, aunitset_index = NLL_A_NULLUNITSET;

  if (args) {
    if ((r = value_get_string(args, &mml, NULL)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_integer(args, &aunitset_index)) < 0)
      ;
    args = args->next;
  }

  if (args) {
    if ((r = value_get_string(args, &filename, NULL)) < 0)
      ;
  }

  result = audio_play(mml, flags, aunitset_index, filename);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_aopen(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result, length;
  integer_t flags = 0;
  char *filename;

  if (nll_is_nosystem())
    return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_string(args, &filename, NULL)) < 0)
    return r;
  args = args->next;

  if (args) {
    if ((r = value_get_integer(args, &flags)) < 0)
      ;
  }

  if (!filename)
    return NLL_ERRCODE_VALUE_INVALID_TYPE;

  result = audio_open(filename, &length, flags);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, length)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}

static int function_aclose(value_t *valuep, value_t args)
{
#ifndef USE_AUDIO
  return NLL_ERRCODE_FORMULA_UNSUPPORTED_FUNCTION;
#else
  int r, result;
  integer_t index;

  if (!args)
    return NLL_ERRCODE_FORMULA_LESS_PARAMETER;
  if ((r = value_get_integer(args, &index)) < 0)
    return r;

  result = audio_close(index);

  if ((r = value_extend_value(valuep)) < 0)
    return r;
  if ((r = value_set_integer(*valuep, result)) < 0)
    return r;
  valuep = &(*valuep)->next;

  if ((r = value_shrink_value(valuep)) < 0)
    return r;

  return 0;
#endif
}
