release: v4.0.0-alpha.4 #163
@@ -1,5 +1,9 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-11-10 — LithosAnanke v4.0.0-alpha.4: the plug-and-play stick
|
||||
|
||||
The plug-and-play stick (#92), the BAM flush (#155), the Book of Fabric (#138), the Dictionary of v4 (#157), and the .com’s Downloads and Documents pages (#126, #161).
|
||||
|
||||
## 2026-11-07 — LithosAnanke v4.0.0-alpha.3: the first published alpha
|
||||
|
||||
`v4.0.0-alpha.2` (`2d43db25`) used the image's HOL-Library as intended, but its release run (200) ran
|
||||
|
||||
@@ -78,7 +78,7 @@ BOARD_DIR := $(if $(TARGET),$(BOARD_DIR_$(TARGET)))
|
||||
SUBMAKE := $(MAKE) --no-print-directory
|
||||
|
||||
.DEFAULT_GOAL := all
|
||||
.PHONY: all boot_image boot_images write_stick docs clean clean-docs kernel boards help help-hosted sbom sbom-board \
|
||||
.PHONY: all boot_image boot_images write_stick docs fabric dictionary clean clean-docs kernel boards help help-hosted sbom sbom-board \
|
||||
qemu qemu-esp qemu-gdb init
|
||||
|
||||
# ARCH given on the command line and no TARGET: `clean` is the kernel's for that
|
||||
@@ -203,6 +203,14 @@ docs:
|
||||
fi
|
||||
@$(SUBMAKE) -f docs/book/Makefile BOARD=$(BOARD_DIR) BOARD_NAME=$(TARGET)
|
||||
|
||||
# fabric -- The Book of Fabric (#138): build/docs/BookOfFabric.pdf
|
||||
fabric:
|
||||
@$(SUBMAKE) -f docs/book/Makefile fabric
|
||||
|
||||
# dictionary -- The Dictionary of v4 (#157): build/docs/Dictionary.pdf
|
||||
dictionary:
|
||||
@$(SUBMAKE) -f docs/book/Makefile dictionary
|
||||
|
||||
clean-docs:
|
||||
rm -rf build/docs
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# LithosAnanke v4.0.0-alpha.3
|
||||
# LithosAnanke v4.0.0-alpha.4
|
||||
|
||||
**UEFI-bootable FORTH microkernel.** Boots from firmware, initialises memory and interrupts, then
|
||||
runs StarForth as its sole userspace runtime. No libc. No OS. Just stone and necessity.
|
||||
@@ -7,8 +7,8 @@ runs StarForth as its sole userspace runtime. No libc. No OS. Just stone and nec
|
||||
|
||||
**Try it in your browser:** [starshipos-f18.com](https://starshipos-f18.com/) — a StarshipOS
|
||||
machine of your own, booted to `[zuse@Hera] ok>`, thrown away when you leave. **Releases:**
|
||||
[v4.0.0-alpha.3](https://gitea.starshipos-f18.org/rajames/LithosAnanke/releases) (pre-release),
|
||||
the kernel `4.0.0-alpha.3` with the StarForth engine `3.2.0`.
|
||||
[v4.0.0-alpha.4](https://gitea.starshipos-f18.org/rajames/LithosAnanke/releases) (pre-release),
|
||||
the kernel `4.0.0-alpha.4` with the StarForth engine `3.2.0`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+64
-5
@@ -57,8 +57,24 @@ chapter_name = $(word 1,$(subst :, ,$(1)))
|
||||
chapter_src = $(word 2,$(subst :, ,$(1)))
|
||||
FRAGMENTS := $(foreach c,$(CHAPTERS),$(GEN)/$(call chapter_name,$(c)).tex)
|
||||
|
||||
.PHONY: all tools FORCE
|
||||
# The Book of Fabric (#138): the FABRIC design record alone, as one book, from
|
||||
# the same fragments -- `make fabric` -> build/docs/BookOfFabric.pdf.
|
||||
FABRIC_DIR := $(OUT)/fabric
|
||||
FABRIC_PDF := $(OUT)/BookOfFabric.pdf
|
||||
FABRIC_FRAGS := $(foreach n,fabric-0 fabric-1 fabric-2 fabric-3 fabric-3-5 fabric-3-6 fabric-3-7 fabric-4,$(GEN)/$(n).tex)
|
||||
|
||||
# The Dictionary of v4 (#157): every live word, alphabetical, with its stack
|
||||
# notation and description -- `make dictionary` -> build/docs/Dictionary.pdf.
|
||||
# Its names are the booted system's (v4/tools/mkdictionary.py); the check
|
||||
# refuses a table that has fallen behind them.
|
||||
DICT_DIR := $(OUT)/dictionary
|
||||
DICT_PDF := $(OUT)/Dictionary.pdf
|
||||
DICT_TSV := docs/reference/v4-dictionary.tsv
|
||||
|
||||
.PHONY: all fabric dictionary tools FORCE
|
||||
all: $(PDF)
|
||||
fabric: $(FABRIC_PDF)
|
||||
dictionary: $(DICT_PDF)
|
||||
|
||||
tools:
|
||||
@missing=""; \
|
||||
@@ -86,25 +102,34 @@ $(GEN)/pandoc-highlighting.tex: $(BOOK_DIR)/pandoc/highlighting.latex | tools
|
||||
@mkdir -p $(GEN)
|
||||
@printf '```c\nx\n```\n' | $(PANDOC) -f gfm -t latex -s --template=$< -o $@
|
||||
|
||||
# Per-build facts the book prints: the commit every \datasource refers to,
|
||||
# Per-build facts the books print: the commit every \datasource refers to,
|
||||
# the version (git describe: a release's tag, or the tag and the commits since),
|
||||
# and which board appendix (if any) is included.
|
||||
$(VAR_DIR)/meta.tex: FORCE
|
||||
@mkdir -p $(VAR_DIR)
|
||||
define meta_cmds
|
||||
@mkdir -p $(dir $@)
|
||||
@{ \
|
||||
c=$$(git rev-parse --short=12 HEAD 2>/dev/null || echo unknown); \
|
||||
git diff --quiet HEAD -- 2>/dev/null || c="$$c (+ uncommitted changes)"; \
|
||||
printf '\\newcommand{\\bookcommit}{%s}\n' "$$c"; \
|
||||
printf '\\newcommand{\\bookdate}{%s}\n' "$$(date -u +%Y-%m-%d)"; \
|
||||
printf '\\newcommand{\\bookversion}{%s}\n' "$$(git describe --tags --always 2>/dev/null || echo unknown)"; \
|
||||
printf '\\def\\bookboard{%s}\n' "$(BOARD_NAME)"; \
|
||||
$(if $(BOARD),printf '\\newcommand{\\bookboardappendix}{board-%s}\n' "$(BOARD)";) \
|
||||
} > $@.tmp
|
||||
@cmp -s $@.tmp $@ && rm -f $@.tmp || mv $@.tmp $@
|
||||
endef
|
||||
$(VAR_DIR)/meta.tex: FORCE
|
||||
$(meta_cmds)
|
||||
$(FABRIC_DIR)/meta.tex: FORCE
|
||||
$(meta_cmds)
|
||||
$(DICT_DIR)/meta.tex: FORCE
|
||||
$(meta_cmds)
|
||||
|
||||
FORCE:
|
||||
|
||||
TEXINPUTS_BOOK := $(abspath $(VAR_DIR)):$(abspath $(GEN)):$(abspath $(BOOK_DIR)):
|
||||
|
||||
$(PDF): $(BOOK_DIR)/main.tex $(FRAGMENTS) $(GEN)/pandoc-highlighting.tex $(VAR_DIR)/meta.tex | tools
|
||||
$(PDF): $(BOOK_DIR)/main.tex $(BOOK_DIR)/preamble.tex $(FRAGMENTS) $(GEN)/pandoc-highlighting.tex $(VAR_DIR)/meta.tex | tools
|
||||
@echo " LATEXMK $(BOOK_DIR)/main.tex -> $@"
|
||||
@TEXINPUTS=$(TEXINPUTS_BOOK) $(LATEXMK) -xelatex -interaction=nonstopmode -halt-on-error \
|
||||
-file-line-error -outdir=$(VAR_DIR) $(BOOK_DIR)/main.tex > $(VAR_DIR)/latexmk.log 2>&1 || { \
|
||||
@@ -112,3 +137,37 @@ $(PDF): $(BOOK_DIR)/main.tex $(FRAGMENTS) $(GEN)/pandoc-highlighting.tex $(VAR_D
|
||||
echo "Error: LaTeX failed; full log: $(VAR_DIR)/main.log"; exit 1; }
|
||||
@cp $(VAR_DIR)/main.pdf $@
|
||||
@echo " PDF $@"
|
||||
|
||||
TEXINPUTS_FABRIC := $(abspath $(FABRIC_DIR)):$(abspath $(GEN)):$(abspath $(BOOK_DIR)):
|
||||
|
||||
$(FABRIC_PDF): $(BOOK_DIR)/fabric.tex $(BOOK_DIR)/preamble.tex $(FABRIC_FRAGS) $(GEN)/pandoc-highlighting.tex $(FABRIC_DIR)/meta.tex | tools
|
||||
@echo " LATEXMK $(BOOK_DIR)/fabric.tex -> $@"
|
||||
@TEXINPUTS=$(TEXINPUTS_FABRIC) $(LATEXMK) -xelatex -interaction=nonstopmode -halt-on-error \
|
||||
-file-line-error -outdir=$(FABRIC_DIR) $(BOOK_DIR)/fabric.tex > $(FABRIC_DIR)/latexmk.log 2>&1 || { \
|
||||
grep -A4 -E '^(.*:[0-9]+:|!)' $(FABRIC_DIR)/fabric.log | head -40; \
|
||||
echo "Error: LaTeX failed; full log: $(FABRIC_DIR)/fabric.log"; exit 1; }
|
||||
@cp $(FABRIC_DIR)/fabric.pdf $@
|
||||
@echo " PDF $@"
|
||||
|
||||
# the live word list needs the hosted v4; the check fails the build on a word with no entry, an
|
||||
# unfinished entry, or an entry for a word the system no longer has
|
||||
$(GEN)/dictionary-words.md: $(DICT_TSV) v4/tools/mkdictionary.py FORCE | tools
|
||||
@mkdir -p $(GEN)
|
||||
@$(MAKE) --no-print-directory -C v4 hosted >/dev/null
|
||||
@python3 v4/tools/mkdictionary.py check $(DICT_TSV)
|
||||
@python3 v4/tools/mkdictionary.py md $(DICT_TSV) $@
|
||||
|
||||
$(GEN)/dictionary-words.tex: $(GEN)/dictionary-words.md $(PANDOC_FILTERS) | tools
|
||||
@echo " PANDOC $< -> $@"
|
||||
@$(PANDOC) $(PANDOC_FLAGS) --id-prefix=dictionary- $< -o $@
|
||||
|
||||
TEXINPUTS_DICT := $(abspath $(DICT_DIR)):$(abspath $(GEN)):$(abspath $(BOOK_DIR)):
|
||||
|
||||
$(DICT_PDF): $(BOOK_DIR)/dictionary.tex $(BOOK_DIR)/preamble.tex $(GEN)/dictionary-words.tex $(GEN)/pandoc-highlighting.tex $(DICT_DIR)/meta.tex | tools
|
||||
@echo " LATEXMK $(BOOK_DIR)/dictionary.tex -> $@"
|
||||
@TEXINPUTS=$(TEXINPUTS_DICT) $(LATEXMK) -xelatex -interaction=nonstopmode -halt-on-error \
|
||||
-file-line-error -outdir=$(DICT_DIR) $(BOOK_DIR)/dictionary.tex > $(DICT_DIR)/latexmk.log 2>&1 || { \
|
||||
grep -A4 -E '^(.*:[0-9]+:|!)' $(DICT_DIR)/dictionary.log | head -40; \
|
||||
echo "Error: LaTeX failed; full log: $(DICT_DIR)/dictionary.log"; exit 1; }
|
||||
@cp $(DICT_DIR)/dictionary.pdf $@
|
||||
@echo " PDF $@"
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
% docs/book/dictionary.tex -- master file of The Dictionary of v4 (#157):
|
||||
% every word StarForth v4 boots with, alphabetical, with its stack notation,
|
||||
% a description and where it is defined (Captain Bob, 2026-11-08: "a
|
||||
% 'dictionary' document with the word, stack notations and descriptions.
|
||||
% Alphabetical."; v4's words only).
|
||||
%
|
||||
% Built by `make dictionary` (docs/book/Makefile): v4/tools/mkdictionary.py
|
||||
% checks docs/reference/v4-dictionary.tsv against the live system and writes
|
||||
% the Markdown that pandoc turns into the fragment input below.
|
||||
\documentclass[11pt,openany]{book}
|
||||
|
||||
\input{preamble}
|
||||
|
||||
\title{The Dictionary of StarForth v4\\[0.5em]\large Every word, its stack notation, and what it does}
|
||||
\author{Robert A. James (Captain Bob)}
|
||||
\date{Version \texttt{\bookversion}\\Built \bookdate{} from commit \texttt{\bookcommit}}
|
||||
|
||||
\begin{document}
|
||||
\frontmatter
|
||||
\maketitle
|
||||
|
||||
\chapter{How to read it}
|
||||
Every word of the dictionary StarForth v4 boots with is here, in
|
||||
alphabetical order. The names are not typed by hand: they are the booted
|
||||
system's own list (\texttt{WORDS}, and the kernel's words of the node), and
|
||||
the build refuses a dictionary that has fallen behind it.
|
||||
|
||||
\textbf{Stack notation.} \texttt{( before -{}- after )}: the values a word
|
||||
takes from the stack, the top on the right, and what it leaves there.
|
||||
\texttt{( R: ... )} is the return stack. \texttt{n} a signed number,
|
||||
\texttt{u} an unsigned one, \texttt{d} and \texttt{ud} double-cell numbers,
|
||||
\texttt{q} a Q48.16 fixed-point number, \texttt{x} any cell, \texttt{flag}
|
||||
a truth value (0 false, -1 true), \texttt{c} a character, \texttt{addr} a
|
||||
cell address, \texttt{baddr} a byte address, \texttt{xt} an execution token.
|
||||
|
||||
\textbf{xxx.} Where a word reads a name or text from the input stream, the
|
||||
description shows it, as \texttt{' xxx} or \texttt{.\textquotedbl{} text\textquotedbl}.
|
||||
|
||||
\mainmatter
|
||||
\input{dictionary-words}
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,69 @@
|
||||
% docs/book/fabric.tex -- master file of The Book of Fabric (#138): the FABRIC
|
||||
% design record as one book, published with every release (Captain Bob,
|
||||
% 2026-11-07: "build a 'The Book of Fabric' and publish it as version
|
||||
% <version> every release"; 2026-11-08: "Publish. Fabric is all about steady
|
||||
% state.").
|
||||
%
|
||||
% Built by `make fabric` (docs/book/Makefile) with xelatex, from the same
|
||||
% pandoc fragments as the book (fabric-0 ... fabric-4, from docs/fabric/).
|
||||
\documentclass[11pt,openany]{book}
|
||||
|
||||
\input{preamble}
|
||||
|
||||
\title{The Book of Fabric\\[0.5em]\large The StarshipOS design record}
|
||||
\author{Robert A. James (Captain Bob)}
|
||||
\date{Version \texttt{\bookversion}\\Built \bookdate{} from commit \texttt{\bookcommit}}
|
||||
|
||||
\begin{document}
|
||||
\frontmatter
|
||||
\maketitle
|
||||
\tableofcontents
|
||||
|
||||
\chapter{About this book}
|
||||
FABRIC is the design record of StarshipOS, LithosAnanke and StarForth: every
|
||||
ruling, the reasoning behind it, what was built, what was found, and what was
|
||||
abandoned, written as the work happened. It is reproduced here as written --
|
||||
struck-through corrections, superseded plans and all -- because the record of
|
||||
what was believed, and when, is part of the record.
|
||||
|
||||
One document is living at a time; when its topic closes, it is closed and a
|
||||
successor opens. Part~I is the living document. Part~II holds the closed
|
||||
ones, in the order they were written; each states, at its head, when and why
|
||||
it closed. Part~III holds the forward-looking notes.
|
||||
|
||||
Each chapter is the Markdown file named below, converted when this book is
|
||||
built; the version and commit on the title page say exactly which.
|
||||
|
||||
\begin{longtable}{@{}lll@{}}
|
||||
\toprule
|
||||
Document & Topic & Status \\
|
||||
\midrule
|
||||
\endhead
|
||||
FABRIC-3 & Bare metal boot & Living \\
|
||||
FABRIC-0 & The Stadium & Closed 2026-08-12 \\
|
||||
FABRIC-1 & The Stadium, continued & Closed 2026-08-25 \\
|
||||
FABRIC-2 & The Stadium, continued again & Closed 2026-09-04 \\
|
||||
FABRIC-3.5 & The Tripod/kernel reshuffle & Closed 2026-09-22 \\
|
||||
FABRIC-3.6 & The reshuffle's execution log & Closed 2026-09-22 \\
|
||||
FABRIC-3.7 & Phase 8 PKI: the elevation entrypoint & Closed 2026-10-14 \\
|
||||
FABRIC-4 & Forward-looking design notes & Notes \\
|
||||
\bottomrule
|
||||
\end{longtable}
|
||||
|
||||
\mainmatter
|
||||
|
||||
\part{The living record}
|
||||
\input{fabric-3}
|
||||
|
||||
\part{The closed records}
|
||||
\input{fabric-0}
|
||||
\input{fabric-1}
|
||||
\input{fabric-2}
|
||||
\input{fabric-3-5}
|
||||
\input{fabric-3-6}
|
||||
\input{fabric-3-7}
|
||||
|
||||
\part{Forward-looking notes}
|
||||
\input{fabric-4}
|
||||
|
||||
\end{document}
|
||||
+1
-93
@@ -6,99 +6,7 @@
|
||||
% build/docs/gen/; meta.tex is generated per build. Neither is committed.
|
||||
\documentclass[11pt,openany]{book}
|
||||
|
||||
\usepackage{amsmath,amssymb}
|
||||
\usepackage{fontspec}
|
||||
% fonts-dejavu-core has no serif/sans italics (fonts-dejavu-extra does); when a
|
||||
% shape is missing, slant the upright one rather than silently drop emphasis.
|
||||
\setmainfont{DejaVu Serif}[AutoFakeSlant=0.2]
|
||||
\setsansfont{DejaVu Sans}[AutoFakeSlant=0.2]
|
||||
\setmonofont{DejaVu Sans Mono}[Scale=0.85]
|
||||
\newfontfamily\symbolfont{DejaVu Sans}
|
||||
|
||||
\usepackage[letterpaper,margin=1in]{geometry}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{longtable,booktabs,array,calc,multirow}
|
||||
\usepackage{fancyvrb}
|
||||
\usepackage[normalem]{ulem}
|
||||
\usepackage{enumitem}
|
||||
\usepackage{newunicodechar}
|
||||
\usepackage{pgfplots}
|
||||
\usepackage{pgfplotstable}
|
||||
\pgfplotsset{compat=1.18}
|
||||
\usepackage[hidelinks]{hyperref}
|
||||
\usepackage{bookmark}
|
||||
|
||||
% --- what pandoc's LaTeX fragments expect (normally from its own template)
|
||||
\providecommand{\tightlist}{\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
|
||||
\providecommand{\pandocbounded}[1]{#1}
|
||||
\providecommand{\st}[1]{\sout{#1}}
|
||||
\newcounter{none} % pandoc: {\def\LTcaptype{none} ...} marks unnumbered tables
|
||||
\usepackage{etoolbox}
|
||||
\makeatletter
|
||||
\def\fnum@table{\tablename~\thetable}
|
||||
\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{}
|
||||
\makeatother
|
||||
\usepackage{fvextra}
|
||||
\input{pandoc-highlighting}
|
||||
% Code and diagrams are wider than the page in places: wrap, never overflow.
|
||||
\RecustomVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\},breaklines,breakanywhere,fontsize=\small}
|
||||
\RecustomVerbatimEnvironment{verbatim}{Verbatim}{breaklines,breakanywhere,fontsize=\small}
|
||||
\setlistdepth{9}
|
||||
\renewlist{itemize}{itemize}{9}
|
||||
\setlist[itemize]{label=\textbullet}
|
||||
\renewlist{enumerate}{enumerate}{9}
|
||||
\setlist[enumerate]{label=\arabic*.}
|
||||
% Running heads: chapter on the left page, section on the right, both cut to
|
||||
% the page width (several design-record titles are a full sentence long).
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage[fit]{truncate}
|
||||
\pagestyle{fancy}
|
||||
\fancyhf{}
|
||||
\renewcommand{\chaptermark}[1]{\markboth{#1}{}}
|
||||
\renewcommand{\sectionmark}[1]{\markright{#1}}
|
||||
\fancyhead[LE]{\small\truncate{\dimexpr\headwidth-3em}{\leftmark}}
|
||||
\fancyhead[RO]{\small\truncate{\dimexpr\headwidth-3em}{\rightmark}}
|
||||
\fancyhead[RE,LO]{\small\thepage}
|
||||
\renewcommand{\headrulewidth}{0.4pt}
|
||||
\setlength{\headheight}{14pt}
|
||||
\fancypagestyle{plain}{\fancyhf{}\fancyfoot[C]{\small\thepage}\renewcommand{\headrulewidth}{0pt}}
|
||||
\setlength{\emergencystretch}{3em}
|
||||
\setlength{\parindent}{0pt}
|
||||
\setlength{\parskip}{0.5em}
|
||||
|
||||
% --- glyphs DejaVu Serif lacks: the status marks used across the docs
|
||||
\newunicodechar{✅}{{\symbolfont ✔}}
|
||||
\newunicodechar{✓}{{\symbolfont ✓}}
|
||||
\newunicodechar{❌}{{\symbolfont ✘}}
|
||||
\newunicodechar{✗}{{\symbolfont ✗}}
|
||||
\newunicodechar{⬜}{{\symbolfont ☐}}
|
||||
\newunicodechar{⭐}{{\symbolfont ★}}
|
||||
\newunicodechar{🔶}{{\symbolfont ◆}}
|
||||
\newunicodechar{⚠}{{\symbolfont ⚠}}
|
||||
\newunicodechar{📋}{}
|
||||
\newunicodechar{🐛}{[bug]}
|
||||
\newunicodechar{🎯}{[goal]}
|
||||
\newunicodechar{🟡}{{\symbolfont ●}}
|
||||
\newunicodechar{📍}{{\symbolfont ▸}}
|
||||
\newunicodechar{🔓}{[unlocked]}
|
||||
\newunicodechar{❓}{?}
|
||||
\newunicodechar{⟺}{\ensuremath{\Longleftrightarrow}}
|
||||
\newunicodechar{⋯}{\ensuremath{\cdots}}
|
||||
\newunicodechar{^^^^fe0f}{}
|
||||
|
||||
% --- the documents number their own sections (§III.1, D-3, ...)
|
||||
\setcounter{secnumdepth}{0}
|
||||
\setcounter{tocdepth}{1}
|
||||
|
||||
\input{meta}
|
||||
|
||||
% \datasource{path/to/data.csv}: cite the data behind a figure or table.
|
||||
% Every figure or table of measured numbers reads its CSV at build time
|
||||
% (\addplot table / \pgfplotstabletypeset) and is followed by this line, so
|
||||
% the reader can find the exact file at the exact commit.
|
||||
\newcommand{\datasource}[1]{%
|
||||
\par{\small Data: \texttt{\detokenize{#1}} at commit \texttt{\bookcommit}.}\par}
|
||||
\input{preamble}
|
||||
|
||||
\title{LithosAnanke and StarForth}
|
||||
\author{}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
% docs/book/preamble.tex -- what both books share: the packages, the fonts,
|
||||
% what pandoc's fragments expect, the glyphs, the running heads, and meta.tex
|
||||
% (the commit, the date, the version). Input by main.tex (the book) and
|
||||
% fabric.tex (the Book of Fabric, #138).
|
||||
\usepackage{amsmath,amssymb}
|
||||
\usepackage{fontspec}
|
||||
% fonts-dejavu-core has no serif/sans italics (fonts-dejavu-extra does); when a
|
||||
% shape is missing, slant the upright one rather than silently drop emphasis.
|
||||
\setmainfont{DejaVu Serif}[AutoFakeSlant=0.2]
|
||||
\setsansfont{DejaVu Sans}[AutoFakeSlant=0.2]
|
||||
\setmonofont{DejaVu Sans Mono}[Scale=0.85]
|
||||
\newfontfamily\symbolfont{DejaVu Sans}
|
||||
|
||||
\usepackage[letterpaper,margin=1in]{geometry}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{longtable,booktabs,array,calc,multirow}
|
||||
\usepackage{fancyvrb}
|
||||
\usepackage[normalem]{ulem}
|
||||
\usepackage{enumitem}
|
||||
\usepackage{newunicodechar}
|
||||
\usepackage{pgfplots}
|
||||
\usepackage{pgfplotstable}
|
||||
\pgfplotsset{compat=1.18}
|
||||
\usepackage[hidelinks]{hyperref}
|
||||
\usepackage{bookmark}
|
||||
|
||||
% --- what pandoc's LaTeX fragments expect (normally from its own template)
|
||||
\providecommand{\tightlist}{\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
|
||||
\providecommand{\pandocbounded}[1]{#1}
|
||||
\providecommand{\st}[1]{\sout{#1}}
|
||||
\newcounter{none} % pandoc: {\def\LTcaptype{none} ...} marks unnumbered tables
|
||||
\usepackage{etoolbox}
|
||||
\makeatletter
|
||||
\def\fnum@table{\tablename~\thetable}
|
||||
\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{}
|
||||
\makeatother
|
||||
\usepackage{fvextra}
|
||||
\input{pandoc-highlighting}
|
||||
% Code and diagrams are wider than the page in places: wrap, never overflow.
|
||||
\RecustomVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\},breaklines,breakanywhere,fontsize=\small}
|
||||
\RecustomVerbatimEnvironment{verbatim}{Verbatim}{breaklines,breakanywhere,fontsize=\small}
|
||||
\setlistdepth{9}
|
||||
\renewlist{itemize}{itemize}{9}
|
||||
\setlist[itemize]{label=\textbullet}
|
||||
\renewlist{enumerate}{enumerate}{9}
|
||||
\setlist[enumerate]{label=\arabic*.}
|
||||
% Running heads: chapter on the left page, section on the right, both cut to
|
||||
% the page width (several design-record titles are a full sentence long).
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage[fit]{truncate}
|
||||
\pagestyle{fancy}
|
||||
\fancyhf{}
|
||||
\renewcommand{\chaptermark}[1]{\markboth{#1}{}}
|
||||
\renewcommand{\sectionmark}[1]{\markright{#1}}
|
||||
\fancyhead[LE]{\small\truncate{\dimexpr\headwidth-3em}{\leftmark}}
|
||||
\fancyhead[RO]{\small\truncate{\dimexpr\headwidth-3em}{\rightmark}}
|
||||
\fancyhead[RE,LO]{\small\thepage}
|
||||
\renewcommand{\headrulewidth}{0.4pt}
|
||||
\setlength{\headheight}{14pt}
|
||||
\fancypagestyle{plain}{\fancyhf{}\fancyfoot[C]{\small\thepage}\renewcommand{\headrulewidth}{0pt}}
|
||||
\setlength{\emergencystretch}{3em}
|
||||
\setlength{\parindent}{0pt}
|
||||
\setlength{\parskip}{0.5em}
|
||||
|
||||
% --- glyphs DejaVu Serif lacks: the status marks used across the docs
|
||||
\newunicodechar{✅}{{\symbolfont ✔}}
|
||||
\newunicodechar{✓}{{\symbolfont ✓}}
|
||||
\newunicodechar{❌}{{\symbolfont ✘}}
|
||||
\newunicodechar{✗}{{\symbolfont ✗}}
|
||||
\newunicodechar{⬜}{{\symbolfont ☐}}
|
||||
\newunicodechar{⭐}{{\symbolfont ★}}
|
||||
\newunicodechar{🔶}{{\symbolfont ◆}}
|
||||
\newunicodechar{⚠}{{\symbolfont ⚠}}
|
||||
\newunicodechar{📋}{}
|
||||
\newunicodechar{🐛}{[bug]}
|
||||
\newunicodechar{🎯}{[goal]}
|
||||
\newunicodechar{🟡}{{\symbolfont ●}}
|
||||
\newunicodechar{📍}{{\symbolfont ▸}}
|
||||
\newunicodechar{🔓}{[unlocked]}
|
||||
\newunicodechar{❓}{?}
|
||||
\newunicodechar{⟺}{\ensuremath{\Longleftrightarrow}}
|
||||
\newunicodechar{⋯}{\ensuremath{\cdots}}
|
||||
\newunicodechar{^^^^fe0f}{}
|
||||
|
||||
% --- the documents number their own sections (§III.1, D-3, ...)
|
||||
\setcounter{secnumdepth}{0}
|
||||
\setcounter{tocdepth}{1}
|
||||
|
||||
\input{meta}
|
||||
|
||||
% \datasource{path/to/data.csv}: cite the data behind a figure or table.
|
||||
% Every figure or table of measured numbers reads its CSV at build time
|
||||
% (\addplot table / \pgfplotstabletypeset) and is followed by this line, so
|
||||
% the reader can find the exact file at the exact commit.
|
||||
\newcommand{\datasource}[1]{%
|
||||
\par{\small Data: \texttt{\detokenize{#1}} at commit \texttt{\bookcommit}.}\par}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,32 @@
|
||||
# alpha.4's documents and pages -- progress (kept current, one line per increment)
|
||||
|
||||
Captain Bob, 2026-11-10: "Do it" -- the rest of alpha.4 that lives in the tree, after #92 (merged,
|
||||
#160). #133 and #134 are the server's (Captain Bob's).
|
||||
|
||||
## #138 -- The Book of Fabric
|
||||
- [x] `docs/book/fabric.tex`: the FABRIC record as one book -- Part I the living record (FABRIC-3),
|
||||
Part II the closed ones in order, Part III the forward-looking notes; title page with the
|
||||
version (`git describe --tags`) and the commit. The book's preamble moved into
|
||||
`docs/book/preamble.tex`, shared by both books (the book itself builds unchanged, 821 pages).
|
||||
- [x] `make fabric` -> `build/docs/BookOfFabric.pdf` (722 pages, 42 s).
|
||||
- [x] `scripts/nightly.sh docs` builds it (`$DOCS/fabric.pdf`); `publish` sends it as
|
||||
`org.starship:documentation:<version>`, classifier `fabric`; `gitea-release` attaches every
|
||||
PDF in `$DOCS`, so the release carries it.
|
||||
|
||||
## #157 -- the dictionary of v4, and the .com's Documents page
|
||||
- [x] the live word list of the built system (318 words): `v4/tools/mkdictionary.py words` -- the hosted v4's `WORDS` (317) plus the kernel's `sk_v4_words[]` (`MINT-ZUSE`)
|
||||
- [x] the table in the tree, `docs/reference/v4-dictionary.tsv`: all 318 entries, written in three alphabetical batches against v4's own definitions (the source gave 54 stacks and 105 descriptions to start from); `check` passes
|
||||
- [x] the check: `mkdictionary.py check` -- every live word has a finished entry, every entry a live word; run by `make dictionary`, so a stale table fails the build and the nightly
|
||||
- [x] the PDF, alphabetical: `make dictionary` -> `build/docs/Dictionary.pdf` (20 pages; `docs/book/dictionary.tex`); the nightly's docs stage builds it, `publish` sends classifier `dictionary`, the release attaches it
|
||||
- [x] the Documents page: the canvas artboard (`project/Documents.dc.html`, canvas v17: the Book of Fabric and the Dictionary first, then the book, the volumes, the API; each with its SHA-256; the SSRN paper), then `site/com/canvas/Documents.dc.html`
|
||||
|
||||
## #126 -- the Downloads page live
|
||||
- [x] `site/com/build.py --release TAG --sums SHA256SUMS` builds Downloads and Documents: `[TAG]`, `[RELEASE]/<file>` (the
|
||||
Gitea release's file), `[SHA:<file>]`; a file not in SHA256SUMS fails the build. Without a release it builds the three
|
||||
pages as before, byte for byte, with no link to the two. `install.sh` installs them when they are built. The release's
|
||||
SHA256SUMS now covers every file it attaches (the images, the PDFs, the Root CA's certificate): `nightly.sh gitea-release`
|
||||
- [x] the nav links on Home, Try it, Inquiries (canvas v17; shown only when the two pages are built)
|
||||
|
||||
**At the alpha.4 release** (after `gitea-release`): download the release's `SHA256SUMS`, then
|
||||
`python3 site/com/build.py --release v4.0.0-alpha.4 --sums SHA256SUMS` and
|
||||
`XWIKI_USER=rajames XWIKI_PASSWORD=... site/com/install.sh` (Captain Bob's; the .com's login).
|
||||
+1
-1
@@ -112,7 +112,7 @@ endif
|
||||
# the messaging layer was replaced by kernel-Hermes, PLOT/FB-* relocated to Hestia —
|
||||
# all dictionary-visible, no FORTH-79 word semantics changed.
|
||||
VERSION ?= 3.2.0
|
||||
LITHOS_VERSION ?= 4.0.0-alpha.3
|
||||
LITHOS_VERSION ?= 4.0.0-alpha.4
|
||||
|
||||
# ==============================================================================
|
||||
# BUILD PATHS
|
||||
|
||||
+22
-6
@@ -42,7 +42,9 @@
|
||||
# The book (make docs), the formal volumes (make -C docs/formal vols) and the API reference
|
||||
# (make -C docs/formal doxygen), into build/nightly-docs/.
|
||||
# scripts/nightly.sh publish-docs <URL>
|
||||
# org.starship:documentation:<VERSION>: classifier book, vol1, vol2, vol3, api (pdf).
|
||||
# org.starship:documentation:<VERSION>: classifier book, fabric (The Book of Fabric, #138),
|
||||
# dictionary (The Dictionary of v4, #157 -- it fails the stage if a live word has no entry),
|
||||
# vol1, vol2, vol3, api (pdf).
|
||||
#
|
||||
# VERSION is <LITHOS_VERSION>-SNAPSHOT, or NIGHTLY_VERSION when set (a release sets it from its
|
||||
# tag). NEXUS_USER (default ci-publisher) and NEXUS_PASSWORD; publishing needs mvn and a JRE.
|
||||
@@ -173,8 +175,12 @@ publish)
|
||||
docs)
|
||||
rm -rf "$DOCS"; mkdir -p "$DOCS"
|
||||
make --no-print-directory docs
|
||||
make --no-print-directory fabric
|
||||
make --no-print-directory dictionary
|
||||
make --no-print-directory -C docs/formal vols doxygen
|
||||
cp build/docs/LithosAnanke.pdf "$DOCS/book.pdf"
|
||||
cp build/docs/BookOfFabric.pdf "$DOCS/fabric.pdf"
|
||||
cp build/docs/Dictionary.pdf "$DOCS/dictionary.pdf"
|
||||
for v in 1 2 3; do cp "docs/formal/build/vol$v/main.pdf" "$DOCS/vol$v.pdf"; done
|
||||
cp docs/formal/build/doxygen/StarForth-API-Reference.pdf "$DOCS/api.pdf"
|
||||
(cd "$DOCS" && sha256sum ./*.pdf | tee SHA256SUMS)
|
||||
@@ -189,15 +195,23 @@ gitea-release)
|
||||
: "${RELEASE_TOKEN:?RELEASE_TOKEN: a token that may write the repository}"
|
||||
api=${GITEA_API:-${GITHUB_SERVER_URL:-https://gitea.starshipos-f18.org}/api/v1/repos/${GITHUB_REPOSITORY:-rajames/LithosAnanke}}
|
||||
need "$OUT/StarshipOS.iso" "$OUT/pc-stick.img.xz" "$OUT/raspi5.img.xz" "$OUT/MilkV.img.xz" "$OUT/SHA256SUMS"
|
||||
files=("$OUT/StarshipOS.iso" "$OUT/pc-stick.img.xz" "$OUT/raspi5.img.xz" "$OUT/MilkV.img.xz" "$OUT/SHA256SUMS")
|
||||
for f in "$DOCS"/*.pdf ci/pki/starshipos-root-ca.pem; do [ -f "$f" ] && files+=("$f"); done
|
||||
# The release's SHA256SUMS covers every file it attaches -- the images' sums as the images
|
||||
# stage wrote them, then the documents and the Root CA's certificate -- so that
|
||||
# `sha256sum -c SHA256SUMS` checks all of it, and the .com's Documents page (site/com/build.py,
|
||||
# #157) finds each document's sum. The Nexus artifacts keep their own SHA256SUMS.
|
||||
rel=$(mktemp -d)
|
||||
cp "$OUT/SHA256SUMS" "$rel/SHA256SUMS"
|
||||
extra=("$DOCS"/*.pdf ci/pki/starshipos-root-ca.pem)
|
||||
for f in "${extra[@]}"; do [ -f "$f" ] && (cd "$(dirname "$f")" && sha256sum "$(basename "$f")") >> "$rel/SHA256SUMS"; done
|
||||
files=("$OUT/StarshipOS.iso" "$OUT/pc-stick.img.xz" "$OUT/raspi5.img.xz" "$OUT/MilkV.img.xz" "$rel/SHA256SUMS")
|
||||
for f in "${extra[@]}"; do [ -f "$f" ] && files+=("$f"); done
|
||||
gitea() { curl -fsS -H "Authorization: token $RELEASE_TOKEN" "$@"; }
|
||||
body=$(python3 -c '
|
||||
import json, sys
|
||||
notes, sums, version = sys.argv[1], open(sys.argv[2]).read(), sys.argv[3]
|
||||
print(json.dumps(notes.strip() + "\n\n## Checksums (SHA-256)\n\n```\n" + sums.strip() + "\n```\n\n"
|
||||
"Also in Nexus: `org.starship:kernelImage:" + version + "` and `org.starship:documentation:" + version + "`.\n"))' \
|
||||
"$(git tag -l --format='%(contents)' "$tag")" "$OUT/SHA256SUMS" "$VERSION")
|
||||
"$(git tag -l --format='%(contents)' "$tag")" "$rel/SHA256SUMS" "$VERSION")
|
||||
id=$(gitea "$api/releases/tags/$tag" 2>/dev/null | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])' 2>/dev/null || true)
|
||||
if [ -z "$id" ]; then
|
||||
pre=false; case "$tag" in *-*) pre=true;; esac
|
||||
@@ -214,11 +228,13 @@ print(json.dumps(notes.strip() + "\n\n## Checksums (SHA-256)\n\n```\n" + sums.st
|
||||
case " $have " in *" $n "*) echo " $n: there"; continue;; esac
|
||||
gitea -o /dev/null -X POST -F "attachment=@$f" "$api/releases/$id/assets?name=$n" && echo " $n: attached"
|
||||
done
|
||||
rm -f "$rel/SHA256SUMS" && rmdir "$rel"
|
||||
;;
|
||||
publish-docs)
|
||||
url=${2:-}; [ -n "$url" ] || usage
|
||||
need "$DOCS/book.pdf" "$DOCS/vol1.pdf" "$DOCS/vol2.pdf" "$DOCS/vol3.pdf" "$DOCS/api.pdf"
|
||||
deploy "$url" documentation "$DOCS/book.pdf" pdf book \
|
||||
need "$DOCS/book.pdf" "$DOCS/fabric.pdf" "$DOCS/dictionary.pdf" "$DOCS/vol1.pdf" "$DOCS/vol2.pdf" "$DOCS/vol3.pdf" "$DOCS/api.pdf"
|
||||
deploy "$url" documentation "$DOCS/book.pdf" pdf book "$DOCS/fabric.pdf" pdf fabric \
|
||||
"$DOCS/dictionary.pdf" pdf dictionary \
|
||||
"$DOCS/vol1.pdf" pdf vol1 "$DOCS/vol2.pdf" pdf vol2 "$DOCS/vol3.pdf" pdf vol3 \
|
||||
"$DOCS/api.pdf" pdf api
|
||||
;;
|
||||
|
||||
@@ -91,19 +91,19 @@ html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #c
|
||||
<h2 style="margin: 0; font-family: 'Exo 2', sans-serif; font-size: 24px">Or write directly</h2>
|
||||
<div style="border-top: 1px solid #22324D !important; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2 !important">General</div>
|
||||
<a href="mailto:info@starshipos.com" style="font-size: 16px">info@starshipos.com</a>
|
||||
<a href="mailto:rajames440@gmail.com" style="font-size: 16px">rajames440@gmail.com</a>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #22324D !important; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2 !important">Licensing & partnerships</div>
|
||||
<a href="mailto:licensing@starshipos.com" style="font-size: 16px">licensing@starshipos.com</a>
|
||||
<a href="mailto:rajames440@gmail.com" style="font-size: 16px">rajames440@gmail.com</a>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #22324D !important; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2 !important">Press & media</div>
|
||||
<a href="mailto:press@starshipos.com" style="font-size: 16px">press@starshipos.com</a>
|
||||
<a href="mailto:rajames440@gmail.com" style="font-size: 16px">rajames440@gmail.com</a>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #22324D !important; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2 !important">Security reports</div>
|
||||
<a href="mailto:security@starshipos.org" style="font-size: 16px">security@starshipos.org</a>
|
||||
<a href="mailto:rajames440@gmail.com" style="font-size: 16px">rajames440@gmail.com</a>
|
||||
</div>
|
||||
<p style="margin: 0; padding-top: 16px; border-top: 1px solid #22324D !important; font-size: 13px; color: #A3AEC2 !important">StarshipOS is developed in Ashland, Ohio.</p>
|
||||
</aside>
|
||||
|
||||
@@ -134,7 +134,7 @@ html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #c
|
||||
<h2 id="signup-h" style="margin: 0 0 8px; font-family: 'Exo 2', sans-serif; font-size: 28px">Launch announcements</h2>
|
||||
<p style="margin: 0; color: #A3AEC2 !important; font-size: 14px">Milestones, releases and papers. Low volume. Unsubscribe anytime.</p>
|
||||
</div>
|
||||
<form action="mailto:info@starshipos.com?subject=Subscribe%20to%20launch%20announcements" method="post" enctype="text/plain" style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">
|
||||
<form action="mailto:rajames440@gmail.com?subject=Subscribe%20to%20launch%20announcements" method="post" enctype="text/plain" style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">
|
||||
<label for="sub-email" style="position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0)">Email address</label>
|
||||
<input id="sub-email" name="email" type="email" required placeholder="you@example.com" style="flex: 1 1 240px; min-height: 48px; padding: 0 16px; background: #0A1222 !important; border: 1px solid #34486A !important; border-radius: 4px; color: #EEF2F7 !important; font-family: inherit; font-size: 15px">
|
||||
<button type="submit" style="min-height: 48px; padding: 0 24px; background: #F5891F !important; color: #0A1222 !important; border: 0 !important; border-radius: 4px; font-family: inherit; font-weight: 700; font-size: 15px; cursor: pointer">Subscribe</button>
|
||||
@@ -145,7 +145,7 @@ html, body, #xwikimaincontainer, #xwikimaincontainerinner, #contentcontainer, #c
|
||||
<footer style="border-top: 1px solid #22324D !important">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2 !important">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="/bin/view/Inquiries/" style="color: #C8D1DE !important">Inquiries</a><a href="mailto:info@starshipos.com" style="color: #C8D1DE !important">info@starshipos.com</a><a href="https://starshipos-f18.org/" style="color: #C8D1DE !important">starshipos-f18.org</a></span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="/bin/view/Inquiries/" style="color: #C8D1DE !important">Inquiries</a><a href="mailto:rajames440@gmail.com" style="color: #C8D1DE !important">rajames440@gmail.com</a><a href="https://starshipos-f18.org/" style="color: #C8D1DE !important">starshipos-f18.org</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
+48
-7
@@ -3,7 +3,9 @@
|
||||
# Copyright (c) 2023-2026 Robert A. James
|
||||
"""build.py -- the starshipos-f18.com XWiki pages, made from the "StarshipOS.com" design canvas.
|
||||
|
||||
site/com/build.py canvas/{Main,Inquiries,TryIt}.dc.html -> {Main,Inquiries,TryIt}.WebHome.xwiki
|
||||
site/com/build.py [--release TAG --sums SHA256SUMS]
|
||||
canvas/{Main,Inquiries,TryIt}.dc.html -> {Main,Inquiries,TryIt}.WebHome.xwiki,
|
||||
and with a release, canvas/{Downloads,Documents}.dc.html too
|
||||
|
||||
The canvas is the source: its artboards are copied into canvas/ as they are, and this turns each into
|
||||
one {{html}} block (which needs a page author with script rights). What changes on the way:
|
||||
@@ -15,6 +17,10 @@ one {{html}} block (which needs a page author with script rights). What changes
|
||||
- Try it: the drawn console becomes the real one, an iframe of try.starshipos-f18.com;
|
||||
- the inquiry form posts to the .org's PublicInquiry, which files it under Inquiries there
|
||||
(admin-only, site/org/inquiries); the announcements form, which has no server, sends by e-mail;
|
||||
- Downloads and Documents (#126, #157) are built from a release: --release TAG and the release's
|
||||
SHA256SUMS fill in [TAG], [RELEASE]/<file> (the file on the Gitea release) and [SHA:<file>].
|
||||
Without a release they are not built, and the other pages' links to them are taken out, so
|
||||
nothing on the site points at a page that is not there (they go live with alpha.4);
|
||||
|
||||
install.sh puts the pages and the images on the wiki.
|
||||
"""
|
||||
@@ -31,6 +37,8 @@ FONTS = ('<link rel="preconnect" href="https://fonts.googleapis.com">\n'
|
||||
'&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">')
|
||||
ORG = "https://starshipos-f18.org/"
|
||||
PAGES = ["Main", "Inquiries", "TryIt"]
|
||||
RELEASE_PAGES = ["Downloads", "Documents"]
|
||||
RELEASES = "https://gitea.starshipos-f18.org/rajames/LithosAnanke/releases/download/"
|
||||
IMAGES = {"/_blob/5b564d54d98e02ad600c913a9a1888f2": "badge.jpg",
|
||||
"/_blob/5483451f292782a8b366e437181c4bcf": "captain-bob.jpg"}
|
||||
|
||||
@@ -44,11 +52,15 @@ CONSOLE = '''<div style="background: #050A14; border: 1px solid #34486A; border-
|
||||
<p style="margin: 12px 0 0; font-size: 13px; color: #A3AEC2">If the console does not connect, every machine is in use: try again in a few minutes.</p>'''
|
||||
|
||||
|
||||
def body(src):
|
||||
def body(src, pages):
|
||||
m = re.search(r"<x-dc>(.*)</x-dc>", src, re.S)
|
||||
html = re.sub(r"<helmet>.*?</helmet>", "", m.group(1), flags=re.S).strip()
|
||||
html = html.replace("{{accent}}", ACCENT)
|
||||
for p in PAGES:
|
||||
# a page not built this time is not linked to: its <a> taken out (the nav, the footers)
|
||||
for p in RELEASE_PAGES:
|
||||
if p not in pages:
|
||||
html = re.sub(r'<a href="%s\.dc\.html"[^>]*>[^<]*</a>\n?' % p, "", html)
|
||||
for p in pages:
|
||||
html = html.replace('href="%s.dc.html"' % p, 'href="/bin/view/%s/"' % p)
|
||||
html = html.replace('href="https://starshipos.org"', 'href="%s"' % ORG)
|
||||
html = html.replace(">starshipos.org</a>", ">starshipos-f18.org</a>")
|
||||
@@ -68,7 +80,7 @@ def try_it(html):
|
||||
def forms(html, page):
|
||||
if page == "Main":
|
||||
html = html.replace('<form style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">',
|
||||
'<form action="mailto:info@starshipos.com?subject=Subscribe%20to%20launch%20announcements" method="post" enctype="text/plain" style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">')
|
||||
'<form action="mailto:rajames440@gmail.com?subject=Subscribe%20to%20launch%20announcements" method="post" enctype="text/plain" style="flex: 1 1 420px; display: flex; flex-wrap: wrap; gap: 12px" aria-label="Subscribe to announcements">')
|
||||
html = html.replace('<input id="sub-email" type="email"', '<input id="sub-email" name="email" type="email" required')
|
||||
html = html.replace('<button type="button" style="min-height: 48px; padding: 0 24px',
|
||||
'<button type="submit" style="min-height: 48px; padding: 0 24px')
|
||||
@@ -90,14 +102,43 @@ def forms(html, page):
|
||||
return html
|
||||
|
||||
|
||||
def release(html, tag, sums):
|
||||
"""[TAG], [RELEASE]/<file> and [SHA:<file>] from the release; a file it has not is an error."""
|
||||
html = html.replace("[TAG]", tag)
|
||||
html = html.replace("[RELEASE]/", RELEASES + tag + "/")
|
||||
|
||||
def sha(m):
|
||||
if m.group(1) not in sums:
|
||||
sys.exit("build: %s is not in the release's SHA256SUMS" % m.group(1))
|
||||
return sums[m.group(1)]
|
||||
return re.sub(r"\[SHA:([^\]]+)\]", sha, html)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--release", help="the release's tag, e.g. v4.0.0-alpha.4")
|
||||
ap.add_argument("--sums", help="the release's SHA256SUMS")
|
||||
a = ap.parse_args()
|
||||
if bool(a.release) != bool(a.sums):
|
||||
sys.exit("build: --release and --sums go together")
|
||||
sums = {}
|
||||
if a.sums:
|
||||
for l in open(a.sums).read().split("\n"):
|
||||
f = l.split()
|
||||
if len(f) == 2:
|
||||
sums[f[1].lstrip("*").lstrip("./")] = f[0]
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
for p in PAGES:
|
||||
html = forms(body(open("canvas/%s.dc.html" % p).read()), p)
|
||||
pages = PAGES + (RELEASE_PAGES if a.release else [])
|
||||
for p in pages:
|
||||
html = forms(body(open("canvas/%s.dc.html" % p).read(), pages), p)
|
||||
if p in RELEASE_PAGES:
|
||||
html = release(html, a.release, sums)
|
||||
if p == "TryIt":
|
||||
html = try_it(html)
|
||||
html = colorlock.lock(html, '<div style="background: #0A1222')
|
||||
assert "{{" not in html.replace(colorlock.STYLE, "") and "[SSRN" not in html and ".dc.html" not in html and "_blob" not in html, p
|
||||
assert "[TAG]" not in html and "[RELEASE]" not in html and "[SHA:" not in html, p
|
||||
with open("%s.WebHome.xwiki" % p, "w") as f:
|
||||
f.write(colorlock.GUEST_CHROME + '{{html clean="false"}}\n%s\n%s\n{{/html}}\n' % (FONTS, html))
|
||||
print("wrote", ", ".join("%s.WebHome.xwiki" % p for p in PAGES))
|
||||
print("wrote", ", ".join("%s.WebHome.xwiki" % p for p in pages))
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>StarshipOS — Documents</title>
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body{margin:0;background:#0A1222}
|
||||
a{color:#F5891F}a:hover{color:#FFB061}
|
||||
</style>
|
||||
</helmet>
|
||||
<div style="background: #0A1222; color: #EEF2F7; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 100vh">
|
||||
|
||||
<header style="border-bottom: 1px solid #22324D">
|
||||
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
|
||||
<a href="Main.dc.html" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: {{accent}}">OS</span></a>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
|
||||
<a href="Main.dc.html" style="color: #C8D1DE; text-decoration: none">Home</a>
|
||||
<a href="TryIt.dc.html" style="color: #C8D1DE; text-decoration: none">Try it</a>
|
||||
<a href="Downloads.dc.html" style="color: #C8D1DE; text-decoration: none">Downloads</a>
|
||||
<a href="Documents.dc.html" aria-current="page" style="color: #EEF2F7; text-decoration: none; border-bottom: 2px solid {{accent}}">Documents</a>
|
||||
<a href="Inquiries.dc.html" style="color: #C8D1DE; text-decoration: none">Inquiries</a>
|
||||
<a href="https://starshipos.org" style="color: {{accent}}; text-decoration: none">Contributors →</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 32px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0">ok> documents</p>
|
||||
<h1 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: clamp(36px, 5vw, 56px); line-height: 1.1">How it was built, and what it says.</h1>
|
||||
<p style="margin: 0 0 24px; max-width: 720px; font-size: 18px; color: #C8D1DE">Every release builds its documents from the same tree as its images: the design record, the dictionary of every word, the book, the formal volumes. Each is a PDF on the release, with its checksum.</p>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; gap: 12px; font-size: 14px">
|
||||
<span style="display: inline-block; padding: 4px 12px; border-radius: 4px; background: #111C30; border: 1px solid #34486A; color: #EEF2F7">[TAG]</span>
|
||||
<a href="[RELEASE]/SHA256SUMS" style="color: #C8D1DE">SHA256SUMS →</a>
|
||||
<a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/releases" style="color: #C8D1DE">All releases →</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="new-h" style="max-width: 1120px; margin: 0 auto; padding: 32px 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">Start here</p>
|
||||
<h2 id="new-h" style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 36px; line-height: 1.15">Two books, kept with every release.</h2>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 24px">
|
||||
|
||||
<article style="background: #111C30; border: 1px solid #34486A; border-radius: 6px; padding: 32px; display: flex; flex-direction: column; gap: 14px">
|
||||
<div><h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 28px">The Book of Fabric</h3><p style="margin: 0; font-size: 13px; color: {{accent}}">the design record, as it happened</p></div>
|
||||
<p style="margin: 0; color: #C8D1DE; font-size: 15px">Every ruling, the reasoning behind it, what was built and what was abandoned, written as the work went -- reproduced as written, corrections and all. The living record first, then the closed ones in order. Fabric is about steady state: this is how it was reached.</p>
|
||||
<div style="font-size: 12px; color: #A3AEC2; word-break: break-all">SHA-256 [SHA:fabric.pdf]</div>
|
||||
<a href="[RELEASE]/fabric.pdf" style="display: inline-block; align-self: flex-start; padding: 12px 20px; background: {{accent}}; color: #0A1222; font-weight: 700; text-decoration: none; border-radius: 4px">fabric.pdf</a>
|
||||
</article>
|
||||
|
||||
<article style="background: #111C30; border: 1px solid #34486A; border-radius: 6px; padding: 32px; display: flex; flex-direction: column; gap: 14px">
|
||||
<div><h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 28px">The Dictionary of v4</h3><p style="margin: 0; font-size: 13px; color: {{accent}}">every word, alphabetical</p></div>
|
||||
<p style="margin: 0; color: #C8D1DE; font-size: 15px">Every word StarForth v4 boots with: its stack notation, what it does, and where it is defined. The names come from the booted system itself, and the build refuses a dictionary that has fallen behind it.</p>
|
||||
<pre style="margin: 0; padding: 12px 14px; background: #0A1222; border: 1px solid #22324D; border-radius: 4px; font-size: 12px; color: #EEF2F7; white-space: pre-wrap">DUP ( x -- x x ) Copy the top value.
|
||||
MINT-ZUSE ( -- ) Mint the real Zuse onto a second stick.</pre>
|
||||
<div style="font-size: 12px; color: #A3AEC2; word-break: break-all">SHA-256 [SHA:dictionary.pdf]</div>
|
||||
<a href="[RELEASE]/dictionary.pdf" style="display: inline-block; align-self: flex-start; padding: 12px 20px; background: {{accent}}; color: #0A1222; font-weight: 700; text-decoration: none; border-radius: 4px">dictionary.pdf</a>
|
||||
</article>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="more-h" style="max-width: 1120px; margin: 0 auto; padding: 32px 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">And the rest</p>
|
||||
<h2 id="more-h" style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 30px; line-height: 1.15">The book, the formal set, the API.</h2>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px">
|
||||
<a href="[RELEASE]/book.pdf" style="display: block; background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 20px; text-decoration: none"><div style="font-family: 'Exo 2', sans-serif; font-size: 18px; color: #EEF2F7">The book</div><div style="font-size: 13px; color: #A3AEC2">StarshipOS, end to end</div><div style="margin-top: 8px; font-size: 11px; color: #6B7A93; word-break: break-all">[SHA:book.pdf]</div></a>
|
||||
<a href="[RELEASE]/vol1.pdf" style="display: block; background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 20px; text-decoration: none"><div style="font-family: 'Exo 2', sans-serif; font-size: 18px; color: #EEF2F7">Volume I</div><div style="font-size: 13px; color: #A3AEC2">the formal set</div><div style="margin-top: 8px; font-size: 11px; color: #6B7A93; word-break: break-all">[SHA:vol1.pdf]</div></a>
|
||||
<a href="[RELEASE]/vol2.pdf" style="display: block; background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 20px; text-decoration: none"><div style="font-family: 'Exo 2', sans-serif; font-size: 18px; color: #EEF2F7">Volume II</div><div style="font-size: 13px; color: #A3AEC2">the formal set</div><div style="margin-top: 8px; font-size: 11px; color: #6B7A93; word-break: break-all">[SHA:vol2.pdf]</div></a>
|
||||
<a href="[RELEASE]/vol3.pdf" style="display: block; background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 20px; text-decoration: none"><div style="font-family: 'Exo 2', sans-serif; font-size: 18px; color: #EEF2F7">Volume III</div><div style="font-size: 13px; color: #A3AEC2">the formal set</div><div style="margin-top: 8px; font-size: 11px; color: #6B7A93; word-break: break-all">[SHA:vol3.pdf]</div></a>
|
||||
<a href="[RELEASE]/api.pdf" style="display: block; background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 20px; text-decoration: none"><div style="font-family: 'Exo 2', sans-serif; font-size: 18px; color: #EEF2F7">API reference</div><div style="font-size: 13px; color: #A3AEC2">StarForth's C, generated</div><div style="margin-top: 8px; font-size: 11px; color: #6B7A93; word-break: break-all">[SHA:api.pdf]</div></a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="paper-h" style="max-width: 1120px; margin: 0 auto; padding: 48px 24px 96px">
|
||||
<div style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 32px 40px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 24px">
|
||||
<div style="flex: 1 1 420px; min-width: 0">
|
||||
<p style="margin: 0 0 8px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">The paper</p>
|
||||
<h2 id="paper-h" style="margin: 0 0 8px; font-family: 'Exo 2', sans-serif; font-size: 26px">The ideas behind it, on SSRN.</h2>
|
||||
<p style="margin: 0; color: #C8D1DE; font-size: 15px">The whitepaper the design starts from.</p>
|
||||
</div>
|
||||
<a href="https://papers.ssrn.com/sol3/papers.cfm?abstract_id=5930134" style="display: inline-block; padding: 12px 20px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px">Read the paper →</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer style="border-top: 1px solid #22324D">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="Main.dc.html" style="color: #C8D1DE">Home</a><a href="Downloads.dc.html" style="color: #C8D1DE">Downloads</a><a href="Inquiries.dc.html" style="color: #C8D1DE">Inquiries</a><a href="https://starshipos.org" style="color: #C8D1DE">starshipos.org</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F5891F","options":["#F5891F","#5FD3C4","#8FB8FF"]},"$preview":{"width":1280,"height":2400}}'>
|
||||
class Component extends DCLogic {
|
||||
renderVals() {
|
||||
return { accent: this.props.accent ?? '#F5891F' };
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,145 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>StarshipOS — Downloads</title>
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Exo+2:wght@600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body{margin:0;background:#0A1222}
|
||||
a{color:#F5891F}a:hover{color:#FFB061}
|
||||
</style>
|
||||
</helmet>
|
||||
<div style="background: #0A1222; color: #EEF2F7; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; line-height: 1.6; min-height: 100vh">
|
||||
|
||||
<header style="border-bottom: 1px solid #22324D">
|
||||
<nav aria-label="Main" style="max-width: 1120px; margin: 0 auto; padding: 20px 24px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px">
|
||||
<a href="Main.dc.html" style="font-family: 'Exo 2', sans-serif; font-weight: 700; font-size: 22px; color: #EEF2F7; text-decoration: none; letter-spacing: 0.02em">starship<span style="color: {{accent}}">OS</span></a>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
|
||||
<a href="Main.dc.html" style="color: #C8D1DE; text-decoration: none">Home</a>
|
||||
<a href="TryIt.dc.html" style="color: #C8D1DE; text-decoration: none">Try it</a>
|
||||
<a href="Downloads.dc.html" aria-current="page" style="color: #EEF2F7; text-decoration: none; border-bottom: 2px solid {{accent}}">Downloads</a>
|
||||
<a href="Documents.dc.html" style="color: #C8D1DE; text-decoration: none">Documents</a>
|
||||
<a href="Inquiries.dc.html" style="color: #C8D1DE; text-decoration: none">Inquiries</a>
|
||||
<a href="https://starshipos.org" style="color: {{accent}}; text-decoration: none">Contributors →</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<section style="max-width: 1120px; margin: 0 auto; padding: 80px 24px 32px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: #4FD1B0">ok> downloads</p>
|
||||
<h1 style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: clamp(36px, 5vw, 56px); line-height: 1.1">StarshipOS, on a machine of yours.</h1>
|
||||
<p style="margin: 0 0 24px; max-width: 700px; font-size: 18px; color: #C8D1DE">One image per board, straight from the release. Write it to a USB stick or an SD card, boot, and the first boot makes you Zuse, the superuser: your identity lives on the stick.</p>
|
||||
<div style="display: flex; flex-wrap: wrap; align-items: center; gap: 12px; font-size: 14px">
|
||||
<span style="display: inline-block; padding: 4px 12px; border-radius: 4px; background: #111C30; border: 1px solid #34486A; color: #EEF2F7">[TAG]</span>
|
||||
<span style="display: inline-block; padding: 4px 12px; border-radius: 4px; border: 1px solid {{accent}}; color: {{accent}}">alpha · pre-release</span>
|
||||
<a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke/releases" style="color: #C8D1DE">All releases →</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-label="What an alpha means" style="max-width: 1120px; margin: 0 auto; padding: 16px 24px 48px">
|
||||
<div style="background: #111C30; border: 1px solid #34486A; border-left-width: 1px; border-radius: 6px; padding: 24px 28px; display: flex; flex-wrap: wrap; gap: 16px 40px">
|
||||
<div style="flex: 1 1 300px; min-width: 0">
|
||||
<h2 style="margin: 0 0 8px; font-family: 'Exo 2', sans-serif; font-size: 22px">An alpha, honestly.</h2>
|
||||
<p style="margin: 0; color: #C8D1DE; font-size: 15px">Every release is booted in QEMU on amd64, aarch64 and riscv64, passes its 538 power-on checks on each, and its proofs, before it is published. On real hardware it has not been booted yet. If you try it, tell us what happened.</p>
|
||||
</div>
|
||||
<div style="flex: 0 1 260px; display: flex; flex-direction: column; justify-content: center; gap: 8px; font-size: 14px">
|
||||
<div><span style="color: #4FD1B0">✓</span> <span style="color: #C8D1DE">QEMU, three architectures</span></div>
|
||||
<div><span style="color: #A3AEC2">○</span> <span style="color: #C8D1DE">Real hardware: not yet</span></div>
|
||||
<a href="Inquiries.dc.html" style="font-size: 14px">Report how it went →</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="images-h" style="max-width: 1120px; margin: 0 auto; padding: 32px 24px 48px">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">The images</p>
|
||||
<h2 id="images-h" style="margin: 0 0 32px; font-family: 'Exo 2', sans-serif; font-size: 36px; line-height: 1.15">Pick your board.</h2>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 24px">
|
||||
|
||||
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px; display: flex; flex-direction: column; gap: 14px">
|
||||
<div><h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">PC</h3><p style="margin: 0; font-size: 13px; color: {{accent}}">any x86-64 PC that boots UEFI from USB</p></div>
|
||||
<p style="margin: 0; color: #C8D1DE; font-size: 15px">A USB stick image. Its first boot makes your Zuse on the stick: no account, no password — the stick is your key.</p>
|
||||
<div style="font-size: 13px; color: #A3AEC2">Write it (it replaces everything on the stick):</div>
|
||||
<pre style="margin: 0; padding: 12px 14px; background: #0A1222; border: 1px solid #22324D; border-radius: 4px; font-size: 12px; color: #EEF2F7; white-space: pre-wrap">xz -dc pc-stick.img.xz | sudo dd of=/dev/sdX bs=4M conv=fsync status=progress</pre>
|
||||
<p style="margin: 0; font-size: 13px; color: #A3AEC2">or balenaEtcher, which reads the .xz as it is.</p>
|
||||
<a href="[RELEASE]/pc-stick.img.xz" style="display: inline-block; align-self: flex-start; padding: 12px 20px; background: {{accent}}; color: #0A1222; font-weight: 700; text-decoration: none; border-radius: 4px">pc-stick.img.xz</a>
|
||||
</article>
|
||||
|
||||
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px; display: flex; flex-direction: column; gap: 14px">
|
||||
<div><h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">Raspberry Pi 5</h3><p style="margin: 0; font-size: 13px; color: {{accent}}">an SD card</p></div>
|
||||
<p style="margin: 0; color: #C8D1DE; font-size: 15px">Boots straight from the Pi's own firmware. Until first-boot Zuse reaches this board, it needs a Zuse identity drive made on a PC.</p>
|
||||
<div style="font-size: 13px; color: #A3AEC2">Write it with Raspberry Pi Imager (Use custom), or:</div>
|
||||
<pre style="margin: 0; padding: 12px 14px; background: #0A1222; border: 1px solid #22324D; border-radius: 4px; font-size: 12px; color: #EEF2F7; white-space: pre-wrap">xz -dc raspi5.img.xz | sudo dd of=/dev/sdX bs=4M conv=fsync status=progress</pre>
|
||||
<a href="[RELEASE]/raspi5.img.xz" style="display: inline-block; align-self: flex-start; padding: 12px 20px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px">raspi5.img.xz</a>
|
||||
</article>
|
||||
|
||||
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px; display: flex; flex-direction: column; gap: 14px">
|
||||
<div><h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">Milk-V Mars</h3><p style="margin: 0; font-size: 13px; color: {{accent}}">RISC-V, an SD card</p></div>
|
||||
<p style="margin: 0; color: #C8D1DE; font-size: 15px">Found by the board's own U-Boot. Until first-boot Zuse reaches this board, it needs a Zuse identity drive made on a PC.</p>
|
||||
<div style="font-size: 13px; color: #A3AEC2">Write it:</div>
|
||||
<pre style="margin: 0; padding: 12px 14px; background: #0A1222; border: 1px solid #22324D; border-radius: 4px; font-size: 12px; color: #EEF2F7; white-space: pre-wrap">xz -dc MilkV.img.xz | sudo dd of=/dev/sdX bs=4M conv=fsync status=progress</pre>
|
||||
<a href="[RELEASE]/MilkV.img.xz" style="display: inline-block; align-self: flex-start; padding: 12px 20px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px">MilkV.img.xz</a>
|
||||
</article>
|
||||
|
||||
<article style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 28px; display: flex; flex-direction: column; gap: 14px">
|
||||
<div><h3 style="margin: 0 0 4px; font-family: 'Exo 2', sans-serif; font-size: 24px">QEMU</h3><p style="margin: 0; font-size: 13px; color: {{accent}}">for developers</p></div>
|
||||
<p style="margin: 0; color: #C8D1DE; font-size: 15px">The ISO every release's amd64 acceptance boots, byte for byte. To boot it the way we do, see the developer guide in the repository.</p>
|
||||
<a href="https://gitea.starshipos-f18.org/rajames/LithosAnanke" style="font-size: 14px">The repository →</a>
|
||||
<a href="[RELEASE]/StarshipOS.iso" style="display: inline-block; align-self: flex-start; padding: 12px 20px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px">StarshipOS.iso</a>
|
||||
</article>
|
||||
|
||||
</div>
|
||||
<p style="margin: 24px 0 0; font-size: 14px; color: #A3AEC2">Rather not write anything? <a href="TryIt.dc.html">Try it in your browser</a> — a real machine, at its prompt in seconds.</p>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="verify-h" style="max-width: 1120px; margin: 0 auto; padding: 48px 24px">
|
||||
<div style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 40px; display: flex; flex-wrap: wrap; gap: 40px">
|
||||
<div style="flex: 999 1 460px; min-width: 0">
|
||||
<p style="margin: 0 0 12px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">Verify</p>
|
||||
<h2 id="verify-h" style="margin: 0 0 16px; font-family: 'Exo 2', sans-serif; font-size: 30px; line-height: 1.2">Know it's ours.</h2>
|
||||
<p style="margin: 0 0 16px; color: #C8D1DE">Every file's SHA-256 is in the release's SHA256SUMS. Inside each image, every capsule the system loads is signed by StarshipOS Capsule Signing, issued by the StarshipOS Root CA, and checked at boot.</p>
|
||||
<pre style="margin: 0; padding: 12px 14px; background: #0A1222; border: 1px solid #22324D; border-radius: 4px; font-size: 13px; color: #EEF2F7">sha256sum -c SHA256SUMS --ignore-missing</pre>
|
||||
</div>
|
||||
<div style="flex: 1 1 300px; min-width: 0; display: flex; flex-direction: column; gap: 12px">
|
||||
<div style="font-size: 13px; color: #A3AEC2">StarshipOS Root CA, SHA-256</div>
|
||||
<code style="display: block; padding: 12px 14px; background: #0A1222; border: 1px solid #22324D; border-radius: 4px; font-size: 12px; color: #EEF2F7; word-break: break-all">DA:A7:40:56:65:41:1A:FE:E6:08:85:3F:6E:AD:83:3A:38:30:83:E6:F0:6D:69:A6:A8:9E:92:BD:85:93:39:81</code>
|
||||
<a href="[RELEASE]/SHA256SUMS" style="font-size: 14px">SHA256SUMS →</a>
|
||||
<a href="[RELEASE]/starshipos-root-ca.pem" style="font-size: 14px">The Root CA's certificate →</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="docs-h" style="max-width: 1120px; margin: 0 auto; padding: 48px 24px 96px">
|
||||
<div style="background: #111C30; border: 1px solid #22324D; border-radius: 6px; padding: 32px 40px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 24px">
|
||||
<div style="flex: 1 1 420px; min-width: 0">
|
||||
<p style="margin: 0 0 8px; font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: {{accent}}">Read</p>
|
||||
<h2 id="docs-h" style="margin: 0 0 8px; font-family: 'Exo 2', sans-serif; font-size: 26px">The documents of this release.</h2>
|
||||
<p style="margin: 0; color: #C8D1DE; font-size: 15px">The Book of Fabric, the Dictionary of v4, the book and the formal set -- built from the same tree as these images.</p>
|
||||
</div>
|
||||
<a href="Documents.dc.html" style="display: inline-block; padding: 12px 20px; border: 1px solid #34486A; color: #EEF2F7; text-decoration: none; border-radius: 4px">Documents →</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer style="border-top: 1px solid #22324D">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="Main.dc.html" style="color: #C8D1DE">Home</a><a href="Inquiries.dc.html" style="color: #C8D1DE">Inquiries</a><a href="https://starshipos.org" style="color: #C8D1DE">starshipos.org</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props='{"accent":{"editor":"color","default":"#F5891F","options":["#F5891F","#5FD3C4","#8FB8FF"]},"$preview":{"width":1280,"height":2700}}'>
|
||||
class Component extends DCLogic {
|
||||
renderVals() {
|
||||
return { accent: this.props.accent ?? '#F5891F' };
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -23,6 +23,8 @@ a{color:#F5891F}a:hover{color:#FFB061}
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
|
||||
<a href="Main.dc.html" style="color: #C8D1DE; text-decoration: none">Home</a>
|
||||
<a href="TryIt.dc.html" style="color: #C8D1DE; text-decoration: none">Try it</a>
|
||||
<a href="Downloads.dc.html" style="color: #C8D1DE; text-decoration: none">Downloads</a>
|
||||
<a href="Documents.dc.html" style="color: #C8D1DE; text-decoration: none">Documents</a>
|
||||
<a href="Inquiries.dc.html" aria-current="page" style="color: #EEF2F7; text-decoration: none; border-bottom: 2px solid {{accent}}">Inquiries</a>
|
||||
<a href="https://starshipos.org" style="color: {{accent}}; text-decoration: none">Contributors →</a>
|
||||
</div>
|
||||
@@ -80,19 +82,19 @@ a{color:#F5891F}a:hover{color:#FFB061}
|
||||
<h2 style="margin: 0; font-family: 'Exo 2', sans-serif; font-size: 24px">Or write directly</h2>
|
||||
<div style="border-top: 1px solid #22324D; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2">General</div>
|
||||
<a href="mailto:info@starshipos.com" style="font-size: 16px">info@starshipos.com</a>
|
||||
<a href="mailto:rajames440@gmail.com" style="font-size: 16px">rajames440@gmail.com</a>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #22324D; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2">Licensing & partnerships</div>
|
||||
<a href="mailto:licensing@starshipos.com" style="font-size: 16px">licensing@starshipos.com</a>
|
||||
<a href="mailto:rajames440@gmail.com" style="font-size: 16px">rajames440@gmail.com</a>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #22324D; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2">Press & media</div>
|
||||
<a href="mailto:press@starshipos.com" style="font-size: 16px">press@starshipos.com</a>
|
||||
<a href="mailto:rajames440@gmail.com" style="font-size: 16px">rajames440@gmail.com</a>
|
||||
</div>
|
||||
<div style="border-top: 1px solid #22324D; padding-top: 16px">
|
||||
<div style="font-size: 13px; color: #A3AEC2">Security reports</div>
|
||||
<a href="mailto:security@starshipos.org" style="font-size: 16px">security@starshipos.org</a>
|
||||
<a href="mailto:rajames440@gmail.com" style="font-size: 16px">rajames440@gmail.com</a>
|
||||
</div>
|
||||
<p style="margin: 0; padding-top: 16px; border-top: 1px solid #22324D; font-size: 13px; color: #A3AEC2">StarshipOS is developed in Ashland, Ohio.</p>
|
||||
</aside>
|
||||
|
||||
@@ -25,6 +25,8 @@ a{color:#F5891F}a:hover{color:#FFB061}
|
||||
<a href="#research" style="color: #C8D1DE; text-decoration: none">Research</a>
|
||||
<a href="#silicon" style="color: #C8D1DE; text-decoration: none">Silicon</a>
|
||||
<a href="TryIt.dc.html" style="color: #C8D1DE; text-decoration: none">Try it</a>
|
||||
<a href="Downloads.dc.html" style="color: #C8D1DE; text-decoration: none">Downloads</a>
|
||||
<a href="Documents.dc.html" style="color: #C8D1DE; text-decoration: none">Documents</a>
|
||||
<a href="Inquiries.dc.html" style="color: #C8D1DE; text-decoration: none">Inquiries</a>
|
||||
<a href="https://starshipos.org" style="color: {{accent}}; text-decoration: none">Contributors →</a>
|
||||
</div>
|
||||
@@ -135,7 +137,7 @@ a{color:#F5891F}a:hover{color:#FFB061}
|
||||
<footer style="border-top: 1px solid #22324D">
|
||||
<div style="max-width: 1120px; margin: 0 auto; padding: 32px 24px; display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between; font-size: 13px; color: #A3AEC2">
|
||||
<span>© 2026 Robert Allan James · A Starship Foundation project (in formation)</span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="Inquiries.dc.html" style="color: #C8D1DE">Inquiries</a><a href="mailto:info@starshipos.com" style="color: #C8D1DE">info@starshipos.com</a><a href="https://starshipos.org" style="color: #C8D1DE">starshipos.org</a></span>
|
||||
<span style="display: flex; flex-wrap: wrap; gap: 24px"><a href="Inquiries.dc.html" style="color: #C8D1DE">Inquiries</a><a href="mailto:rajames440@gmail.com" style="color: #C8D1DE">rajames440@gmail.com</a><a href="https://starshipos.org" style="color: #C8D1DE">starshipos.org</a></span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ a{color:#F5891F}a:hover{color:#FFB061}
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px">
|
||||
<a href="Main.dc.html" style="color: #C8D1DE; text-decoration: none">Home</a>
|
||||
<a href="TryIt.dc.html" aria-current="page" style="color: #EEF2F7; text-decoration: none; border-bottom: 2px solid {{accent}}">Try it</a>
|
||||
<a href="Downloads.dc.html" style="color: #C8D1DE; text-decoration: none">Downloads</a>
|
||||
<a href="Documents.dc.html" style="color: #C8D1DE; text-decoration: none">Documents</a>
|
||||
<a href="Inquiries.dc.html" style="color: #C8D1DE; text-decoration: none">Inquiries</a>
|
||||
<a href="https://starshipos.org" style="color: {{accent}}; text-decoration: none">Contributors →</a>
|
||||
</div>
|
||||
|
||||
+8
-1
@@ -39,10 +39,17 @@ attach Main badge.jpg
|
||||
attach Main captain-bob.jpg
|
||||
page Inquiries "Inquiries" Inquiries.WebHome.xwiki
|
||||
page TryIt "Try StarshipOS" TryIt.WebHome.xwiki
|
||||
# Downloads and Documents exist once build.py has been given a release (#126, #157)
|
||||
pages="/bin/view/Main/ /bin/view/Inquiries/ /bin/view/TryIt/"
|
||||
if [ -f Downloads.WebHome.xwiki ] && [ -f Documents.WebHome.xwiki ]; then
|
||||
page Downloads "Downloads" Downloads.WebHome.xwiki
|
||||
page Documents "Documents" Documents.WebHome.xwiki
|
||||
pages="$pages /bin/view/Downloads/ /bin/view/Documents/"
|
||||
fi
|
||||
|
||||
echo "=== as a guest"
|
||||
bad=
|
||||
for u in /bin/view/Main/ /bin/view/Inquiries/ /bin/view/TryIt/ \
|
||||
for u in $pages \
|
||||
/bin/download/Main/WebHome/badge.jpg /bin/download/Main/WebHome/captain-bob.jpg; do
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' "$base$u")
|
||||
if [ "$code" = 200 ]; then echo " $u: 200"; else echo " $u: $code -- NOT readable"; bad=1; fi
|
||||
|
||||
@@ -15,6 +15,7 @@ Needs the programming right.
|
||||
#if (!$c.get('announcements'))#set ($d = $c.addBooleanField('announcements', 'Wants announcements', 'yesno'))#set ($changed = true)#end
|
||||
#if (!$c.get('source'))#set ($d = $c.addTextField('source', 'Source', 60))#set ($changed = true)#end
|
||||
#if (!$c.get('status'))#set ($d = $c.addStaticListField('status', 'Status', 1, false, 'new|read|answered|closed'))#set ($changed = true)#end
|
||||
#if (!$c.get('mailed'))#set ($d = $c.addBooleanField('mailed', 'E-mailed to Captain Bob', 'yesno'))#set ($changed = true)#end
|
||||
#if ($changed)
|
||||
#set ($d = $xdoc.setTitle('Inquiry class'))
|
||||
#set ($d = $xwiki.getXWiki().saveDocument($xdoc, 'The inquiry fields', $xcontext.getContext()))
|
||||
|
||||
@@ -12,6 +12,7 @@ This page holds no inquiry.
|
||||
|=Organization|$doc.display('organization', $o)
|
||||
|=Topic|$doc.display('topic', $o)
|
||||
|=Announcements|$doc.display('announcements', $o)
|
||||
|=E-mailed|$doc.display('mailed', $o)
|
||||
|=Source|$doc.display('source', $o)
|
||||
|
||||
== Message ==
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
## rights (getDocumentAsAuthor, saveAsAuthor): a guest can reach nothing but this. Nothing a visitor
|
||||
## sends is ever written into this page's output or an entry's title: with this author's rights,
|
||||
## text that reached the wiki markup could run a macro.
|
||||
## Each inquiry filed is also e-mailed to Captain Bob (#161; ruled 2026-11-10: "server emails each
|
||||
## one"), plain text, through the wiki's mail service (Administration > Email > Mail Sending: the
|
||||
## SMTP account is set there, not here). Reply-To is the visitor's address, which has passed the
|
||||
## address check above; the subject is fixed but for the topic, its line breaks removed. If the
|
||||
## mail is not sent the inquiry is filed all the same, and its entry says so (its E-mailed field: no).
|
||||
#macro (field $n $max)#set ($v = "$!request.getParameter($n)")#set ($v = $v.trim())#if ($v.length() > $max)#set ($v = $v.substring(0, $max))#end#end
|
||||
#if ($request.method != 'POST')
|
||||
This page receives the inquiry form on [[starshipos-f18.com>>https://starshipos-f18.com/bin/view/Inquiries/]].
|
||||
@@ -35,6 +40,33 @@ This page receives the inquiry form on [[starshipos-f18.com>>https://starshipos-
|
||||
#set ($d = $o.set('source', 'starshipos-f18.com'))
|
||||
#set ($d = $o.set('status', 'new'))
|
||||
#set ($d = $entry.saveAsAuthor('An inquiry from the .com form'))
|
||||
## the e-mail: every visitor-given value is plain text in a text/plain part, never markup
|
||||
#set ($subjectTopic = $topic.replaceAll('[\r\n]+', ' '))
|
||||
#set ($body = "A new inquiry from starshipos-f18.com, filed as ${ref}:
|
||||
${xwiki.getURL($ref, 'view')}
|
||||
|
||||
Name: $name
|
||||
E-mail: $email
|
||||
Organization: $org
|
||||
Topic: $topic
|
||||
Announcements: #if ($wants)yes#{else}no#end
|
||||
|
||||
|
||||
$message
|
||||
")
|
||||
#set ($mail = $services.mail.sender.createMessage('rajames440@gmail.com', "Inquiry from starshipos-f18.com: $subjectTopic"))
|
||||
#if ($mail)
|
||||
#set ($d = $mail.addPart('text/plain', $body))
|
||||
#set ($d = $mail.setHeader('Reply-To', $email))
|
||||
#set ($sent = $services.mail.sender.send($mail))
|
||||
#set ($ok = $sent && !$services.mail.sender.lastError)
|
||||
#if ($ok)#set ($ok = $sent.statusResult.waitTillProcessed(30000))#set ($ok = !$sent.statusResult.allErrors.hasNext())#end
|
||||
#else
|
||||
#set ($ok = false)
|
||||
#end
|
||||
#set ($e2 = $xwiki.getDocumentAsAuthor($ref))
|
||||
#set ($o2 = $e2.getObject('Inquiries.Code.InquiryClass'))
|
||||
#if ($o2)#if ($ok)#set ($d = $o2.set('mailed', 1))#else#set ($d = $o2.set('mailed', 0))#end#set ($d = $e2.saveAsAuthor('Whether the inquiry was e-mailed'))#end
|
||||
{{html}}<p>Thank you. Your inquiry has been received; every message is read by a human, and replies usually come within a few days.</p><p><a href="https://starshipos-f18.com/">Back to starshipos-f18.com</a></p>{{/html}}
|
||||
#end
|
||||
#end
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: LicenseRef-Starship-1.0
|
||||
# Copyright (c) 2023-2026 Robert A. James
|
||||
"""mkdictionary.py -- the dictionary of v4 (#157): every word the system boots with, alphabetical,
|
||||
with its stack notation, a description, and where it is defined.
|
||||
|
||||
v4/tools/mkdictionary.py words the live word list, one per line
|
||||
v4/tools/mkdictionary.py draft TSV a table for every live word not in TSV yet, appended,
|
||||
its stack and description taken from the source where
|
||||
the source has them (to be read and finished by hand)
|
||||
v4/tools/mkdictionary.py check TSV every live word has an entry with a stack and a
|
||||
description, and every entry is a live word: 0, or 1
|
||||
with what is wrong
|
||||
v4/tools/mkdictionary.py md TSV OUT.md the dictionary as Markdown, alphabetical, for the book
|
||||
|
||||
The live word list is the system's own: the hosted v4 (`make -C v4 hosted`) booted and asked
|
||||
`WORDS`, plus the kernel's words of the lone node (`sk_v4_words[]` in kernel/src/v4/sk_v4.c) --
|
||||
the words a booted StarshipOS has. The table (docs/reference/v4-dictionary.tsv) holds the stack
|
||||
notation and the description, which only a person can write; the names are never typed by hand.
|
||||
"""
|
||||
import os, re, subprocess, sys
|
||||
|
||||
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
HOSTED = os.path.join(ROOT, "v4", "build", "starforth4-amd64")
|
||||
SOURCES = ([os.path.join("capsules/v4/sys", f) for f in sorted(os.listdir(os.path.join(ROOT, "capsules/v4/sys")))
|
||||
if f.endswith(".f18")] +
|
||||
[os.path.join("capsules/v4", f) for f in sorted(os.listdir(os.path.join(ROOT, "capsules/v4")))
|
||||
if f.endswith(".4th")])
|
||||
KERNEL_WORDS_SRC = "kernel/src/v4/sk_v4.c"
|
||||
|
||||
|
||||
def live_words():
|
||||
"""The hosted system's WORDS, then the kernel's own words not among them."""
|
||||
if not os.path.exists(HOSTED):
|
||||
sys.exit(f"mkdictionary: {HOSTED} is missing: make -C v4 hosted")
|
||||
out = subprocess.run([HOSTED], input="WORDS\n", capture_output=True, text=True, timeout=120).stdout
|
||||
lines = out.split("\n")
|
||||
try:
|
||||
start = next(k for k, l in enumerate(lines) if l.startswith("ok> ") and l[4:].strip())
|
||||
except StopIteration:
|
||||
sys.exit("mkdictionary: the hosted system printed no WORDS")
|
||||
got = []
|
||||
for l in lines[start:]:
|
||||
if l.startswith("ok> ") and got:
|
||||
break
|
||||
got.append(l[4:] if l.startswith("ok> ") else l)
|
||||
text = " ".join(got)
|
||||
if " ok" in text:
|
||||
text = text[:text.rfind(" ok")]
|
||||
words = text.split()
|
||||
src = open(os.path.join(ROOT, KERNEL_WORDS_SRC)).read()
|
||||
m = re.search(r"sk_v4_words\[\]\s*=\s*\{([^}]*)\}", src)
|
||||
for k in re.findall(r'"([^"]+)"', m.group(1) if m else ""):
|
||||
if k not in words:
|
||||
words.append(k)
|
||||
return words
|
||||
|
||||
|
||||
def definitions():
|
||||
"""Where each name is defined, and what its source says of it: {name: (file, stack, text)}."""
|
||||
found = {}
|
||||
for rel in SOURCES:
|
||||
lines = open(os.path.join(ROOT, rel), errors="replace").read().split("\n")
|
||||
for i, l in enumerate(lines):
|
||||
names = []
|
||||
if rel.endswith(".f18"):
|
||||
names = re.findall(r'",\s+(\S+)\s+#,', l)
|
||||
else:
|
||||
names = re.findall(r"(?:^|\s):\s+(\S+)", l)
|
||||
names += re.findall(r"\b(?:CONSTANT|VARIABLE|DEFER|CREATE|VOCABULARY)\s+(\S+)", l)
|
||||
for n in names:
|
||||
if n in found:
|
||||
continue
|
||||
stack, text = "", ""
|
||||
inline = re.search(r":\s+" + re.escape(n) + r"\s+(\([^)]*\))", l)
|
||||
if inline:
|
||||
stack = inline.group(1)
|
||||
# the comment block just above
|
||||
j, block = i - 1, []
|
||||
while j >= 0 and lines[j].startswith("\\"):
|
||||
block.insert(0, lines[j].lstrip("\\").strip())
|
||||
j -= 1
|
||||
comment = " ".join(b for b in block if b)
|
||||
cm = re.match(r"(\([^)]*--[^)]*\))\s*(.*)", comment)
|
||||
if cm and not stack:
|
||||
stack, comment = cm.group(1), cm.group(2)
|
||||
text = comment
|
||||
found[n] = (rel, stack, text)
|
||||
for k in re.findall(r'"([^"]+)"', re.search(r"sk_v4_words\[\]\s*=\s*\{([^}]*)\}",
|
||||
open(os.path.join(ROOT, KERNEL_WORDS_SRC)).read()).group(1)):
|
||||
found.setdefault(k, (KERNEL_WORDS_SRC, "", ""))
|
||||
return found
|
||||
|
||||
|
||||
def read_table(path):
|
||||
table = {}
|
||||
if os.path.exists(path):
|
||||
for l in open(path).read().split("\n"):
|
||||
# a comment is a line beginning with # that has no tab: a row always has tabs, and
|
||||
# some words begin with # (#, #>, #S)
|
||||
if not l.strip() or (l.startswith("#") and "\t" not in l):
|
||||
continue
|
||||
f = l.split("\t")
|
||||
while len(f) < 3:
|
||||
f.append("")
|
||||
table[f[0]] = (f[1].strip(), f[2].strip())
|
||||
return table
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
sys.exit(__doc__)
|
||||
mode = sys.argv[1]
|
||||
if mode == "words":
|
||||
print("\n".join(live_words()))
|
||||
return
|
||||
path = sys.argv[2]
|
||||
table = read_table(path)
|
||||
words = live_words()
|
||||
if mode == "draft":
|
||||
defs = definitions()
|
||||
new = [w for w in words if w not in table]
|
||||
with open(path, "a") as f:
|
||||
if not table:
|
||||
f.write("# docs/reference/v4-dictionary.tsv -- the dictionary of v4 (#157): name, stack notation,\n"
|
||||
"# description, tab-separated. The names are the live system's (v4/tools/mkdictionary.py\n"
|
||||
"# check refuses a missing or a stale one). A row whose description starts TODO is a draft.\n")
|
||||
for w in sorted(new):
|
||||
rel, stack, text = defs.get(w, ("", "", ""))
|
||||
desc = ("TODO " + text) if text else "TODO"
|
||||
f.write(f"{w}\t{stack}\t{desc}\n")
|
||||
print(f"mkdictionary: {len(words)} live words; {len(new)} drafted into {path}")
|
||||
return
|
||||
if mode == "check":
|
||||
bad = []
|
||||
for w in words:
|
||||
if w not in table:
|
||||
bad.append(f"no entry: {w}")
|
||||
elif not table[w][0] or not table[w][1] or table[w][1].startswith("TODO"):
|
||||
bad.append(f"unfinished: {w}")
|
||||
for w in table:
|
||||
if w not in words:
|
||||
bad.append(f"not a live word: {w}")
|
||||
if bad:
|
||||
print("\n".join(bad))
|
||||
print(f"mkdictionary: {len(bad)} problem(s) in {path} ({len(words)} live words)")
|
||||
sys.exit(1)
|
||||
print(f"mkdictionary: {path} covers all {len(words)} live words")
|
||||
return
|
||||
if mode == "md":
|
||||
defs = definitions()
|
||||
out = sys.argv[3]
|
||||
with open(out, "w") as f:
|
||||
f.write("# The dictionary of v4\n\n")
|
||||
f.write(f"Every word StarForth v4 boots with -- {len(words)} of them -- in alphabetical order: its "
|
||||
"stack notation (what it takes and leaves: `( before -- after )`), what it does, and "
|
||||
"where it is defined.\n\n")
|
||||
f.write("| Word | Stack | Description | Defined in |\n|---|---|---|---|\n")
|
||||
for w in sorted(words, key=lambda x: (x.upper(), x)):
|
||||
stack, desc = table.get(w, ("", ""))
|
||||
rel = defs.get(w, ("", "", ""))[0]
|
||||
cell = lambda x: x.replace("|", "\\|")
|
||||
# a token with a quote in it is FORTH (." text" S" ABORT"): set as code, so its
|
||||
# quotes print straight, not as typographic ones
|
||||
desc = re.sub(r'(\S*"\S*)', lambda mm: "`" + mm.group(1) + "`", desc)
|
||||
f.write(f"| `{cell(w)}` | `{cell(stack)}` | {cell(desc)} | `{rel}` |\n")
|
||||
print(f"mkdictionary: {out}, {len(words)} words")
|
||||
return
|
||||
sys.exit(__doc__)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user