mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-12 09:17:53 +00:00
256 lines
6.6 KiB
C
256 lines
6.6 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 2022 Justine Alexandra Roberts Tunney │
|
|||
|
│ │
|
|||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
|||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
|||
|
│ above copyright notice and this permission notice appear in all copies. │
|
|||
|
│ │
|
|||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
|||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
|||
|
#include "tool/build/lib/case.h"
|
|||
|
#include "tool/plinko/lib/char.h"
|
|||
|
#include "tool/plinko/lib/plinko.h"
|
|||
|
#include "tool/plinko/lib/print.h"
|
|||
|
#include "tool/plinko/lib/tree.h"
|
|||
|
|
|||
|
int PrintDot(int fd) {
|
|||
|
return PrintChar(fd, L'.');
|
|||
|
}
|
|||
|
|
|||
|
int PrintSpace(int fd) {
|
|||
|
return PrintChar(fd, L' ');
|
|||
|
}
|
|||
|
|
|||
|
void PrintNewline(int fd) {
|
|||
|
PrintChar(fd, L'\n');
|
|||
|
}
|
|||
|
|
|||
|
int PrintIndent(int fd, int n) {
|
|||
|
int i;
|
|||
|
for (i = 0; n > 0; --n) {
|
|||
|
i += PrintSpace(fd);
|
|||
|
}
|
|||
|
return i;
|
|||
|
}
|
|||
|
|
|||
|
int PrintZeroes(int fd, int n) {
|
|||
|
int i;
|
|||
|
for (i = 0; n > 0; --n) {
|
|||
|
i += PrintChar(fd, L'0');
|
|||
|
}
|
|||
|
return i;
|
|||
|
}
|
|||
|
|
|||
|
int PrintDepth(int fd, int n) {
|
|||
|
int i, j;
|
|||
|
for (j = i = 0; n > 0; --n, ++j) {
|
|||
|
if (j < ARRAYLEN(g_depths)) {
|
|||
|
i += PrintChar(fd, g_depths[j][0]);
|
|||
|
i += PrintChar(fd, g_depths[j][1]);
|
|||
|
i += PrintChar(fd, g_depths[j][2]);
|
|||
|
}
|
|||
|
}
|
|||
|
return i;
|
|||
|
}
|
|||
|
|
|||
|
int PrintListDot(int fd, int x) {
|
|||
|
int n;
|
|||
|
n = PrintSpace(fd);
|
|||
|
n += PrintDot(fd);
|
|||
|
n += PrintSpace(fd);
|
|||
|
n += Print(fd, x);
|
|||
|
return n;
|
|||
|
}
|
|||
|
|
|||
|
bool ShouldForceDot(int x) {
|
|||
|
return Cdr(x) < 0 && (Car(Cdr(x)) == kClosure || Car(Cdr(x)) == kLambda ||
|
|||
|
Car(Cdr(x)) == kMacro);
|
|||
|
}
|
|||
|
|
|||
|
bool ShouldConcealClosure(int x) {
|
|||
|
return !logc &&
|
|||
|
(Car(x) == kClosure /* && Cdr(x) < 0 && Car(Cdr(x)) < 0 && */
|
|||
|
/* Car(Car(Cdr(x))) == kLambda && CountAtoms(x, 256, 0) >= 256 */);
|
|||
|
}
|
|||
|
|
|||
|
int PrintList(int fd, int x) {
|
|||
|
int n = 0;
|
|||
|
DCHECK_LE(x, 0);
|
|||
|
if (x < cx) {
|
|||
|
n += PrintChar(fd, L'!');
|
|||
|
n += PrintInt(fd, x, 0, 0, 0, 10, true);
|
|||
|
} else {
|
|||
|
if (ShouldConcealClosure(x)) {
|
|||
|
x = Car(Cdr(x));
|
|||
|
}
|
|||
|
n += PrintChar(fd, L'(');
|
|||
|
if (x < 0) {
|
|||
|
n += Print(fd, Car(x));
|
|||
|
if (ShouldForceDot(x)) {
|
|||
|
n += PrintListDot(fd, Cdr(x));
|
|||
|
} else {
|
|||
|
while ((x = Cdr(x))) {
|
|||
|
if (x < 0) {
|
|||
|
n += PrintSpace(fd);
|
|||
|
n += Print(fd, Car(x));
|
|||
|
} else {
|
|||
|
n += PrintListDot(fd, x);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
n += PrintChar(fd, L')');
|
|||
|
}
|
|||
|
return n;
|
|||
|
}
|
|||
|
|
|||
|
bool HasWeirdCharacters(int x) {
|
|||
|
int c;
|
|||
|
dword e;
|
|||
|
do {
|
|||
|
e = Get(x);
|
|||
|
c = LO(e);
|
|||
|
x = HI(e);
|
|||
|
if (c == L'`' || c == L'"' || c == L'\'' || IsSpace(c) || IsParen(c) ||
|
|||
|
IsSpace(c) || IsLower(c) || IsC0(c)) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
} while (x != TERM);
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
int PrintString(int fd, int x) {
|
|||
|
dword e;
|
|||
|
int c, u, n;
|
|||
|
n = PrintChar(fd, L'"');
|
|||
|
do {
|
|||
|
e = Get(x);
|
|||
|
c = LO(e);
|
|||
|
x = HI(e);
|
|||
|
DCHECK_GT(c, 0);
|
|||
|
DCHECK_LT(c, TERM);
|
|||
|
if (c < 0200) {
|
|||
|
u = c;
|
|||
|
c = L'\\';
|
|||
|
switch (c) {
|
|||
|
CASE(L'\a', c |= L'a' << 010);
|
|||
|
CASE(L'\b', c |= L'b' << 010);
|
|||
|
CASE(00033, c |= L'e' << 010);
|
|||
|
CASE(L'\f', c |= L'f' << 010);
|
|||
|
CASE(L'\n', c |= L'n' << 010);
|
|||
|
CASE(L'\r', c |= L'r' << 010);
|
|||
|
CASE(L'\t', c |= L't' << 010);
|
|||
|
CASE(L'\v', c |= L'v' << 010);
|
|||
|
CASE(L'\\', c |= L'\\' << 010);
|
|||
|
CASE(L'"', c |= L'"' << 010);
|
|||
|
default:
|
|||
|
if (32 <= c && c < 127) {
|
|||
|
c = u;
|
|||
|
} else {
|
|||
|
c |= ((L'0' + c / 8 / 8 % 8) << 010 | (L'0' + c / 8 % 8) << 020 |
|
|||
|
(L'0' + c % 8) << 030);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
do {
|
|||
|
n += PrintChar(fd, c & 255);
|
|||
|
} while ((c >>= 010));
|
|||
|
} else {
|
|||
|
n += PrintChar(fd, c);
|
|||
|
}
|
|||
|
} while (x != TERM);
|
|||
|
n += PrintChar(fd, L'"');
|
|||
|
return n;
|
|||
|
}
|
|||
|
|
|||
|
int PrintAtom(int fd, int x) {
|
|||
|
dword e;
|
|||
|
int c, n = 0;
|
|||
|
DCHECK_GE(x, 0);
|
|||
|
if (x == 0) {
|
|||
|
if (symbolism && !literally) {
|
|||
|
n += PrintChar(fd, L'⊥');
|
|||
|
} else {
|
|||
|
n += PrintChar(fd, L'N');
|
|||
|
n += PrintChar(fd, L'I');
|
|||
|
n += PrintChar(fd, L'L');
|
|||
|
}
|
|||
|
} else if (x == 1) {
|
|||
|
if (symbolism && !literally) {
|
|||
|
n += PrintChar(fd, L'⊤');
|
|||
|
} else {
|
|||
|
n += PrintChar(fd, L'T');
|
|||
|
}
|
|||
|
} else if (x >= TERM) {
|
|||
|
n += PrintChar(fd, L'!');
|
|||
|
n += PrintInt(fd, x, 0, 0, 0, 10, true);
|
|||
|
} else if (symbolism && (c = Symbolize(x)) != -1) {
|
|||
|
n += PrintChar(fd, c);
|
|||
|
} else {
|
|||
|
if (!literally && HasWeirdCharacters(x)) {
|
|||
|
n += PrintString(fd, x);
|
|||
|
} else {
|
|||
|
do {
|
|||
|
e = Get(x);
|
|||
|
c = LO(e);
|
|||
|
n += PrintChar(fd, c);
|
|||
|
} while ((x = HI(e)) != TERM);
|
|||
|
}
|
|||
|
}
|
|||
|
return n;
|
|||
|
}
|
|||
|
|
|||
|
int EnterPrint(int x) {
|
|||
|
#if 0
|
|||
|
int i;
|
|||
|
if (x < 0) {
|
|||
|
DCHECK_GE(pdp, 0);
|
|||
|
DCHECK_LT(pdp, ARRAYLEN(g_print));
|
|||
|
if (x < 0) {
|
|||
|
for (i = 0; i < pdp; ++i) {
|
|||
|
if (x == g_print[i]) {
|
|||
|
x = kCycle;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
g_print[pdp++] = x;
|
|||
|
if (pdp == ARRAYLEN(g_print)) {
|
|||
|
x = kTrench;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
return x;
|
|||
|
}
|
|||
|
|
|||
|
void LeavePrint(int x) {
|
|||
|
#if 0
|
|||
|
if (x < 0) {
|
|||
|
--pdp;
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
int Print(int fd, int x) {
|
|||
|
int n;
|
|||
|
GetName(&x);
|
|||
|
x = EnterPrint(x);
|
|||
|
if (1. / x < 0) {
|
|||
|
n = PrintList(fd, x);
|
|||
|
} else {
|
|||
|
n = PrintAtom(fd, x);
|
|||
|
}
|
|||
|
LeavePrint(x);
|
|||
|
return n;
|
|||
|
}
|