cosmopolitan/tool/calc/calc.c

963 lines
24 KiB
C

/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2020 Justine Alexandra Roberts Tunney │
│ │
│ This program is free software; you can redistribute it and/or modify │
│ it under the terms of the GNU General Public License as published by │
│ the Free Software Foundation; version 2 of the License. │
│ │
│ This program is distributed in the hope that it will be useful, but │
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
│ General Public License for more details. │
│ │
│ You should have received a copy of the GNU General Public License │
│ along with this program; if not, write to the Free Software │
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
│ 02110-1301 USA │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/bits/bits.h"
#include "libc/bits/bswap.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/conv/conv.h"
#include "libc/errno.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/bsf.h"
#include "libc/nexgen32e/bsr.h"
#include "libc/nexgen32e/ffs.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/rand/rand.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/o.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
#include "o/tool/calc/calc.c.inc"
#include "o/tool/calc/calc.h.inc"
#include "third_party/gdtoa/gdtoa.h"
#include "tool/calc/calc.h"
/**
* make -j8 o//tool/calc
* rlwrap -A -H ~/.calc -f tool/calc/calc.lst -e\( o//tool/calc/calc.com
* @see https://github.com/hanslub42/rlwrap
*/
static jmp_buf jb;
static int g_line;
static int g_column;
static const char *g_file;
static yyParser g_parser[1];
wontreturn static void Error(const char *msg) {
fprintf(stderr, "%s:%d:%d: %s\n", g_file, g_line, g_column, msg);
longjmp(jb, 1);
}
wontreturn static void SyntaxError(void) {
Error("SYNTAX ERROR");
}
wontreturn static void LexError(void) {
Error("LEX ERROR");
}
wontreturn static void MissingArgumentError(void) {
Error("MISSING ARGUMENT");
}
wontreturn static void MissingFunctionError(void) {
Error("MISSING FUNCTION");
}
wontreturn static void SyscallError(const char *name) {
fprintf(stderr, "ERROR: %s[%s]: %d\n", name, g_file, errno);
exit(1);
}
static void NumbersFree(struct Numbers *n) {
if (n) {
NumbersFree(n->n);
free(n);
}
}
static struct Numbers *NumbersAppend(struct Numbers *n, long double x) {
struct Numbers *a;
a = malloc(sizeof(struct Numbers));
a->n = n;
a->x = x;
return a;
}
static long double ParseNumber(struct Token t) {
char *ep;
ep = t.s + t.n;
if (t.s[0] == '0') {
return strtoumax(t.s, &ep, 0);
} else {
return strtod(t.s, &ep);
}
}
static long double FnRand(struct Numbers *a) {
return rand();
}
static long double FnRand32(struct Numbers *a) {
return rand32();
}
static long double FnRand64(struct Numbers *a) {
return rand64();
}
static long double FnRdrand(struct Numbers *a) {
if (X86_HAVE(RDRND)) {
return rdrand();
} else {
return NAN;
}
}
static long double FnRdseed(struct Numbers *a) {
if (X86_HAVE(RDSEED)) {
return rdseed();
} else {
return NAN;
}
}
static long double FnAtan2(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return atan2l(a->n->x, a->x);
}
static long double FnLdexp(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return ldexpl(a->n->x, a->x);
}
static long double FnCopysign(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return copysignl(a->n->x, a->x);
}
static long double FnFmax(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return fmaxl(a->n->x, a->x);
}
static long double FnFmin(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return fminl(a->n->x, a->x);
}
static long double FnFmod(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return fmodl(a->n->x, a->x);
}
static long double FnHypot(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return hypotl(a->n->x, a->x);
}
static long double FnPowi(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return powil(a->n->x, a->x);
}
static long double FnPow(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return powl(a->n->x, a->x);
}
static long double FnScalb(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return scalbl(a->n->x, a->x);
}
static long double FnIsgreater(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return isgreater(a->n->x, a->x);
}
static long double FnRemainder(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return remainderl(a->n->x, a->x);
}
static long double FnIsgreaterequal(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return isgreaterequal(a->n->x, a->x);
}
static long double FnIsless(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return isless(a->n->x, a->x);
}
static long double FnIslessequal(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return islessequal(a->n->x, a->x);
}
static long double FnIslessgreater(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return islessgreater(a->n->x, a->x);
}
static long double FnIsunordered(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return isunordered(a->n->x, a->x);
}
static long double FnRounddown(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return ROUNDDOWN((int128_t)a->n->x, (int128_t)a->x);
}
static long double FnRoundup(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return ROUNDUP((int128_t)a->n->x, (int128_t)a->x);
}
static long double FnAcos(struct Numbers *a) {
if (!a) MissingArgumentError();
return acosl(a->x);
}
static long double FnAsin(struct Numbers *a) {
if (!a) MissingArgumentError();
return asinl(a->x);
}
static long double FnAtan(struct Numbers *a) {
if (!a) MissingArgumentError();
return atanl(a->x);
}
static long double FnCbrt(struct Numbers *a) {
if (!a) MissingArgumentError();
return cbrtl(a->x);
}
static long double FnCeil(struct Numbers *a) {
if (!a) MissingArgumentError();
return ceill(a->x);
}
static long double FnCos(struct Numbers *a) {
if (!a) MissingArgumentError();
return cosl(a->x);
}
static long double FnExp10(struct Numbers *a) {
if (!a) MissingArgumentError();
return exp10l(a->x);
}
static long double FnExp2(struct Numbers *a) {
if (!a) MissingArgumentError();
return exp2l(a->x);
}
static long double FnExp(struct Numbers *a) {
if (!a) MissingArgumentError();
return expl(a->x);
}
static long double FnExpm1(struct Numbers *a) {
if (!a) MissingArgumentError();
return expm1l(a->x);
}
static long double FnFabs(struct Numbers *a) {
if (!a) MissingArgumentError();
return fabsl(a->x);
}
static long double FnFloor(struct Numbers *a) {
if (!a) MissingArgumentError();
return floorl(a->x);
}
static long double FnIlogb(struct Numbers *a) {
if (!a) MissingArgumentError();
return ilogbl(a->x);
}
static long double FnLog10(struct Numbers *a) {
if (!a) MissingArgumentError();
return log10l(a->x);
}
static long double FnLog1p(struct Numbers *a) {
if (!a) MissingArgumentError();
return log1pl(a->x);
}
static long double FnLog2(struct Numbers *a) {
if (!a) MissingArgumentError();
return log2l(a->x);
}
static long double FnLogb(struct Numbers *a) {
if (!a) MissingArgumentError();
return logbl(a->x);
}
static long double FnLog(struct Numbers *a) {
if (!a) MissingArgumentError();
return logl(a->x);
}
static long double FnLrint(struct Numbers *a) {
if (!a) MissingArgumentError();
return lrintl(a->x);
}
static long double FnLround(struct Numbers *a) {
if (!a) MissingArgumentError();
return lroundl(a->x);
}
static long double FnNearbyint(struct Numbers *a) {
if (!a) MissingArgumentError();
return nearbyintl(a->x);
}
static long double FnRint(struct Numbers *a) {
if (!a) MissingArgumentError();
return rintl(a->x);
}
static long double FnRound(struct Numbers *a) {
if (!a) MissingArgumentError();
return roundl(a->x);
}
static long double FnSignificand(struct Numbers *a) {
if (!a) MissingArgumentError();
return significandl(a->x);
}
static long double FnSin(struct Numbers *a) {
if (!a) MissingArgumentError();
return sinl(a->x);
}
static long double FnSqrt(struct Numbers *a) {
if (!a) MissingArgumentError();
return sqrtl(a->x);
}
static long double FnTan(struct Numbers *a) {
if (!a) MissingArgumentError();
return tanl(a->x);
}
static long double FnTrunc(struct Numbers *a) {
if (!a) MissingArgumentError();
return truncl(a->x);
}
static long double FnIsinf(struct Numbers *a) {
if (!a) MissingArgumentError();
return isinf(a->x);
}
static long double FnIsnan(struct Numbers *a) {
if (!a) MissingArgumentError();
return isnan(a->x);
}
static long double FnIsfinite(struct Numbers *a) {
if (!a) MissingArgumentError();
return isfinite(a->x);
}
static long double FnIsnormal(struct Numbers *a) {
if (!a) MissingArgumentError();
return isnormal(a->x);
}
static long double FnSignbit(struct Numbers *a) {
if (!a) MissingArgumentError();
return signbit(a->x);
}
static long double FnFpclassify(struct Numbers *a) {
if (!a) MissingArgumentError();
return fpclassify(a->x);
}
static long double FnBswap16(struct Numbers *a) {
if (!a) MissingArgumentError();
return bswap_16((uint16_t)a->x);
}
static long double FnBswap32(struct Numbers *a) {
if (!a) MissingArgumentError();
return bswap_32((uint32_t)a->x);
}
static long double FnBswap64(struct Numbers *a) {
if (!a) MissingArgumentError();
return bswap_64((uint64_t)a->x);
}
static long double FnBsr(struct Numbers *a) {
if (!a) MissingArgumentError();
return bsr(a->x);
}
static long double FnBsrl(struct Numbers *a) {
if (!a) MissingArgumentError();
return bsrl(a->x);
}
static long double FnBsfl(struct Numbers *a) {
if (!a) MissingArgumentError();
return bsfl(a->x);
}
static long double FnFfs(struct Numbers *a) {
if (!a) MissingArgumentError();
return ffs(a->x);
}
static long double FnFfsl(struct Numbers *a) {
if (!a) MissingArgumentError();
return ffsl(a->x);
}
static long double FnGray(struct Numbers *a) {
if (!a) MissingArgumentError();
return gray(a->x);
}
static long double FnUngray(struct Numbers *a) {
if (!a) MissingArgumentError();
return ungray(a->x);
}
static long double FnRounddown2pow(struct Numbers *a) {
if (!a) MissingArgumentError();
return rounddown2pow(a->x);
}
static long double FnRoundup2pow(struct Numbers *a) {
if (!a) MissingArgumentError();
return roundup2pow(a->x);
}
static long double FnRoundup2log(struct Numbers *a) {
if (!a) MissingArgumentError();
return roundup2log(a->x);
}
static long double FnBitreverse8(struct Numbers *a) {
if (!a) MissingArgumentError();
return bitreverse8(a->x);
}
static long double FnBitreverse16(struct Numbers *a) {
if (!a) MissingArgumentError();
return bitreverse16(a->x);
}
static long double FnBitreverse32(struct Numbers *a) {
if (!a) MissingArgumentError();
return bitreverse32(a->x);
}
static long double FnBitreverse64(struct Numbers *a) {
if (!a) MissingArgumentError();
return bitreverse64(a->x);
}
static int8_t sarb(int8_t x, uint8_t y) {
return x >> (y & 7);
}
static int16_t sarw(int16_t x, uint8_t y) {
return x >> (y & 15);
}
static int32_t sarl(int32_t x, uint8_t y) {
return x >> (y & 31);
}
static int64_t sarq(int64_t x, uint8_t y) {
return x >> (y & 63);
}
static long double FnSarb(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return sarb(a->n->x, a->x);
}
static long double FnSarw(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return sarw(a->n->x, a->x);
}
static long double FnSarl(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return sarl(a->n->x, a->x);
}
static long double FnSarq(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return sarq(a->n->x, a->x);
}
static long double FnSar(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return sarq(a->n->x, a->x);
}
static uint8_t rorb(uint8_t x, uint8_t y) {
return x >> (y & 7) | x << (8 - (y & 7));
}
static uint16_t rorw(uint16_t x, uint8_t y) {
return x >> (y & 15) | x << (16 - (y & 15));
}
static uint32_t rorl(uint32_t x, uint8_t y) {
return x >> (y & 31) | x << (32 - (y & 31));
}
static uint64_t rorq(uint64_t x, uint8_t y) {
return x >> (y & 63) | x << (64 - (y & 63));
}
static long double FnRorb(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return rorb(a->n->x, a->x);
}
static long double FnRorw(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return rorw(a->n->x, a->x);
}
static long double FnRorl(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return rorl(a->n->x, a->x);
}
static long double FnRorq(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return rorq(a->n->x, a->x);
}
static long double FnRor(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return rorq(a->n->x, a->x);
}
static uint8_t rolb(uint8_t x, uint8_t y) {
return x << (y & 7) | x >> (8 - (y & 7));
}
static uint16_t rolw(uint16_t x, uint8_t y) {
return x << (y & 15) | x >> (16 - (y & 15));
}
static uint32_t roll(uint32_t x, uint8_t y) {
return x << (y & 31) | x >> (32 - (y & 31));
}
static uint64_t rolq(uint64_t x, uint8_t y) {
return x << (y & 63) | x >> (64 - (y & 63));
}
static long double FnRolb(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return rolb(a->n->x, a->x);
}
static long double FnRolw(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return rolw(a->n->x, a->x);
}
static long double FnRoll(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return roll(a->n->x, a->x);
}
static long double FnRolq(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return rolq(a->n->x, a->x);
}
static long double FnRol(struct Numbers *a) {
if (!a || !a->n) MissingArgumentError();
return rolq(a->n->x, a->x);
}
static long double FnTime(struct Numbers *a) {
return nowl();
}
static long double FnBin(struct Numbers *a) {
if (!a) MissingArgumentError();
printf("0b%jb\n", (uint128_t)a->x);
return 0;
}
static long double FnOct(struct Numbers *a) {
if (!a) MissingArgumentError();
printf("0%jo\n", (uint128_t)a->x);
return 0;
}
static long double FnHex(struct Numbers *a) {
if (!a) MissingArgumentError();
printf("0x%jx\n", (uint128_t)a->x);
return 0;
}
static void PrintNumber(long double x) {
char buf[32];
g_xfmt_p(buf, &x, 15, sizeof(buf), 0);
fputs(buf, stdout);
}
static void Print(struct Numbers *a) {
if (a) {
Print(a->n);
if (a->n) fputc(' ', stdout);
PrintNumber(a->x);
}
}
static long double FnPrint(struct Numbers *a) {
Print(a);
fputc('\n', stdout);
return 0;
}
static const struct Fn {
const char *s;
long double (*f)(struct Numbers *);
} kFunctions[] = {
{"abs", FnFabs},
{"acos", FnAcos},
{"asin", FnAsin},
{"atan", FnAtan},
{"atan2", FnAtan2},
{"bin", FnBin},
{"bitreverse16", FnBitreverse16},
{"bitreverse32", FnBitreverse32},
{"bitreverse64", FnBitreverse64},
{"bitreverse8", FnBitreverse8},
{"bsfl", FnBsfl},
{"bsfl", FnBsfl},
{"bsr", FnBsr},
{"bsrl", FnBsrl},
{"bswap16", FnBswap16},
{"bswap32", FnBswap32},
{"bswap64", FnBswap64},
{"cbrt", FnCbrt},
{"ceil", FnCeil},
{"copysign", FnCopysign},
{"cos", FnCos},
{"exp", FnExp},
{"exp10", FnExp10},
{"exp2", FnExp2},
{"expm1", FnExpm1},
{"fabs", FnFabs},
{"ffs", FnFfs},
{"ffsl", FnFfsl},
{"floor", FnFloor},
{"fmax", FnFmax},
{"fmin", FnFmin},
{"fmod", FnFmod},
{"fpclassify", FnFpclassify},
{"gray", FnGray},
{"hex", FnHex},
{"hypot", FnHypot},
{"ilogb", FnIlogb},
{"isfinite", FnIsfinite},
{"isgreater", FnIsgreater},
{"isgreaterequal", FnIsgreaterequal},
{"isinf", FnIsinf},
{"isless", FnIsless},
{"islessequal", FnIslessequal},
{"islessgreater", FnIslessgreater},
{"isnan", FnIsnan},
{"isnormal", FnIsnormal},
{"isunordered", FnIsunordered},
{"ldexp", FnLdexp},
{"ldexp", FnLdexp},
{"log", FnLog},
{"log10", FnLog10},
{"log1p", FnLog1p},
{"log2", FnLog2},
{"logb", FnLogb},
{"lrint", FnLrint},
{"lround", FnLround},
{"max", FnFmax},
{"min", FnFmin},
{"nearbyint", FnNearbyint},
{"oct", FnOct},
{"pow", FnPow},
{"powi", FnPowi},
{"print", FnPrint},
{"rand", FnRand},
{"rand32", FnRand32},
{"rand64", FnRand64},
{"rdrand", FnRdrand},
{"rdseed", FnRdseed},
{"remainder", FnRemainder},
{"rint", FnRint},
{"rol", FnRol},
{"rolb", FnRolb},
{"roll", FnRoll},
{"rolq", FnRolq},
{"rolw", FnRolw},
{"ror", FnRor},
{"rorb", FnRorb},
{"rorl", FnRorl},
{"rorq", FnRorq},
{"rorw", FnRorw},
{"round", FnRound},
{"rounddown", FnRounddown},
{"rounddown2pow", FnRounddown2pow},
{"roundup", FnRoundup},
{"roundup2log", FnRoundup2log},
{"roundup2pow", FnRoundup2pow},
{"sar", FnSar},
{"sarb", FnSarb},
{"sarl", FnSarl},
{"sarq", FnSarq},
{"sarw", FnSarw},
{"scalb", FnScalb},
{"signbit", FnSignbit},
{"signbit", FnSignbit},
{"significand", FnSignificand},
{"sin", FnSin},
{"sqrt", FnSqrt},
{"tan", FnTan},
{"time", FnTime},
{"trunc", FnTrunc},
{"ungray", FnUngray},
};
static long double CallFunction(struct Token fn, struct Numbers *args) {
int l, r, m, p;
l = 0;
r = ARRAYLEN(kFunctions) - 1;
while (l <= r) {
m = (l + r) >> 1;
p = strncmp(kFunctions[m].s, fn.s, fn.n);
if (p < 0) {
l = m + 1;
} else if (p > 0) {
r = m - 1;
} else {
return kFunctions[m].f(args);
}
}
MissingFunctionError();
}
static void Tokenize(const char *s, size_t size) {
size_t n;
char *se;
for (se = s + size; s < se; s += n, ++g_column) {
n = 1;
switch (*s & 0xff) {
case ' ':
case '\t':
case '\v':
case '\r':
break;
case '\n':
++g_line;
g_column = 0;
break;
case 'A' ... 'Z':
case 'a' ... 'z':
n = strspn(s, "0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz");
Parse(g_parser, SYMBOL, (struct Token){s, n});
break;
case '0':
n = strspn(s, "xXbB0123456789abcdefABCDEF");
Parse(g_parser, NUMBER, (struct Token){s, n});
n += strspn(s + n, "LUlu");
break;
case '1' ... '9':
n = strspn(s, "0123456789.");
if (s[n] == 'e' || s[n] == 'E') {
++n;
if (s[n] == '+' || s[n] == '-') ++n;
n += strspn(s + n, "0123456789");
}
Parse(g_parser, NUMBER, (struct Token){s, n});
n += strspn(s + n, "LUlu");
break;
case '(':
Parse(g_parser, LP, (struct Token){0, 0});
break;
case ')':
Parse(g_parser, RP, (struct Token){0, 0});
break;
case ',':
Parse(g_parser, COMMA, (struct Token){0, 0});
break;
case '^':
Parse(g_parser, XOR, (struct Token){0, 0});
break;
case '%':
Parse(g_parser, REM, (struct Token){0, 0});
break;
case '+':
Parse(g_parser, PLUS, (struct Token){0, 0});
break;
case '-':
Parse(g_parser, MINUS, (struct Token){0, 0});
break;
case '~':
Parse(g_parser, NOT, (struct Token){0, 0});
break;
case '/':
if (s[1] == '/') {
Parse(g_parser, DDIV, (struct Token){0, 0});
++n;
} else {
Parse(g_parser, DIV, (struct Token){0, 0});
}
break;
case '*':
if (s[1] == '*') {
Parse(g_parser, EXP, (struct Token){0, 0});
++n;
} else {
Parse(g_parser, MUL, (struct Token){0, 0});
}
break;
case '|':
if (s[1] == '|') {
Parse(g_parser, LOR, (struct Token){0, 0});
++n;
} else {
Parse(g_parser, OR, (struct Token){0, 0});
}
break;
case '&':
if (s[1] == '&') {
Parse(g_parser, LAND, (struct Token){0, 0});
++n;
} else {
Parse(g_parser, AND, (struct Token){0, 0});
}
break;
case '!':
if (s[1] == '=') {
Parse(g_parser, NE, (struct Token){0, 0});
++n;
} else {
Parse(g_parser, LNOT, (struct Token){0, 0});
}
break;
case '=':
if (s[1] == '=') {
Parse(g_parser, EQ, (struct Token){0, 0});
++n;
} else {
LexError();
}
break;
case '>':
if (s[1] == '=') {
Parse(g_parser, GE, (struct Token){0, 0});
++n;
} else if (s[1] == '>') {
Parse(g_parser, SHR, (struct Token){0, 0});
++n;
} else {
Parse(g_parser, GT, (struct Token){0, 0});
}
break;
case '<':
if (s[1] == '=') {
Parse(g_parser, LE, (struct Token){0, 0});
++n;
} else if (s[1] == '<') {
Parse(g_parser, SHL, (struct Token){0, 0});
++n;
} else {
Parse(g_parser, LT, (struct Token){0, 0});
}
break;
default:
LexError();
}
}
}
int main(int argc, char *argv[]) {
int i;
int ec;
int fd;
size_t n;
char *buf;
ssize_t rc;
size_t bufcap;
if (!(ec = setjmp(jb))) {
if (argc > 1) {
ParseInit(g_parser);
bufcap = BIGPAGESIZE;
buf = malloc(bufcap);
for (i = 1; i < argc; ++i) {
g_file = argv[i];
g_line = 0;
g_column = 0;
n = 0; /* wut */
if ((fd = open(g_file, O_RDONLY)) == -1) SyscallError("open");
for (;;) {
if ((rc = read(fd, buf, bufcap)) == -1) SyscallError("read");
if (!(n = rc)) break;
Tokenize(buf, n);
}
close(fd);
Parse(g_parser, 0, (struct Token){0, 0});
}
ParseFinalize(g_parser);
} else {
g_file = "/dev/stdin";
g_line = 0;
g_column = 0;
buf = NULL;
bufcap = 0;
while (getline(&buf, &bufcap, stdin) != -1) {
if ((n = strlen(buf))) {
ParseInit(g_parser);
if (!setjmp(jb)) {
Tokenize("print(", 6);
Tokenize(buf, n);
Tokenize(")", 1);
Parse(g_parser, 0, (struct Token){0, 0});
}
ParseFinalize(g_parser);
}
}
}
}
free(buf);
return ec;
}