Skip to content

Commit

Permalink
nix: generate postscript file from include files
Browse files Browse the repository at this point in the history
Generates the committed postscript and runs diff to make sure that the
reconstruction was faithful. Currently this simply reproduces the
existing code, though it autogenerates the numbers to make it easier
to rearrange things and/or add blank pages.

Later PRs will abstract out the setup code, improve best practices (e.g.
wrapping every page in "10 dict ... end") and add additional targets
which produce e.g. individual worksheets in their own postscript.

We will also use the Nix mechanism to add illustrations, rather than
using PHP.
  • Loading branch information
apoelstra committed Mar 20, 2023
1 parent 9946318 commit 865b397
Show file tree
Hide file tree
Showing 14 changed files with 2,532 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ mathematical-companion/*.log
mathematical-companion/*.out
mathematical-companion/*.pdf
mathematical-companion/*.toc

result
222 changes: 222 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
{ pkgs ? import <nixpkgs> { }
, stdenv ? pkgs.stdenv
, lib ? pkgs.lib
, ghostscript ? pkgs.ghostscript
, ref ? null
, doPdfGeneration ? true
# Checks whether the generated output matches the checked-in SSS32.ps.
# When doing development you may want to shut this off to obtain the
# output file that you need to check in.
, doOutputDiff ? true
}:

let
src =
if isNull ref
then lib.sourceFilesBySuffices ./. [ ".ps" ".inc" ]
else
fetchGit {
url = ./.;
inherit ref;
};
shortId = lib.optionalString (! isNull ref) ("-" + builtins.substring 0 8 src.rev);


setup = rec {
# Will be broken into multiple sub-files in a later PR.
fullSetup = {
content = builtins.readFile "${src}/include/setup.ps.inc";
dependencies = [ ];
};
};
# Dependencies that every page has
standardDependencies = [ setup.fullSetup ];

allPages = {
title = {
sourceHeader = "Title Page";
content = builtins.readFile "${src}/include/title.ps.inc";
dependencies = [ ];
};
license = {
sourceHeader = "License Information";
drawPageContent = true;
content = builtins.readFile "${src}/include/license.ps.inc";
dependencies = [ ];
};
reference = {
sourceHeader = "Reference Sheet";
drawPageContent = true;
content = builtins.readFile "${src}/include/reference.ps.inc";
dependencies = [ ];
};
principalTables = {
sourceHeader = "Arithmetic Tables";
content = builtins.readFile "${src}/include/principal-tables.ps.inc";
dependencies = [ ];
};

additionBottom = {
content = "{xor} (Addition) code dup perm drawBottomWheelPage\n";
dependencies = [ ];
};
additionTop = {
content = "showTopWheelPage\n";
dependencies = [ ];
};
recovery = {
content = builtins.readFile "${src}/include/volvelle-recovery.ps.inc";
dependencies = [ ];
};
fusionInner = {
content = builtins.readFile "${src}/include/volvelle-fusion-1.ps.inc";
dependencies = [ ];
};
fusionOuter = {
content = builtins.readFile "${src}/include/volvelle-fusion-2.ps.inc";
dependencies = [ ];
};

generationInstructions = {
content = builtins.readFile "${src}/include/page7.ps.inc";
dependencies = [ ];
};

checksumTable1 = {
content = builtins.readFile "${src}/include/checksum-table-1.ps.inc";
isLandscape = true;
dependencies = [ ];
};
checksumTable2 = {
content = builtins.readFile "${src}/include/checksum-table-2.ps.inc";
isLandscape = true;
dependencies = [ ];
};
checksumWorksheet = {
content = builtins.readFile "${src}/include/checksum-worksheet.ps.inc";
isLandscape = true;
dependencies = [ ];
};

shareTable = a: b: c: d: {
content = "${toString a} ${toString b} ${toString c} ${toString d} showShareTablePage\n";
dependencies = [ ];
};
};

fullBooklet = {
name = "SSS32.ps";
pages = with allPages; [
title
license
reference
principalTables
additionBottom
additionTop
generationInstructions
(shareTable 29 24 13 25)
(shareTable 9 8 23 18)
(shareTable 22 31 27 19)
(shareTable 1 0 3 16)
(shareTable 11 28 12 14)
(shareTable 6 4 2 15)
(shareTable 10 17 21 20)
(shareTable 26 30 7 5)
recovery
fusionInner
fusionOuter
checksumTable1
checksumTable2
checksumWorksheet
];
};

dependencyContentRecur = content: builtins.concatMap
(item: (dependencyContentRecur item.dependencies) ++ [ item.content ])
content;
dependencyContent = pages: lib.lists.unique (
(map (dep: dep.content) standardDependencies) ++
(builtins.concatMap (page: dependencyContentRecur page.dependencies) pages)
);

renderBooklet = booklet:
let
addPage = content: pageData: {
content = content.content + lib.optionalString (pageData ? sourceHeader) ''
%****************************************************************
%*
%* ${pageData.sourceHeader}
%*
%****************************************************************
'' + ''
%%Page: ${toString content.nextPgIdx} ${toString content.nextPgIdx}
${lib.optionalString (pageData ? isLandscape) "%%PageOrientation: Landscape\n"}%%BeginPageSetup
/pgsave save def
%%EndPageSetup
'' + (
if pageData ? drawPageContent
then
if pageData ? isLandscape
then "landscapePage begin ${toString content.nextCtIdx} drawPageContent\n"
else "portraitPage begin ${toString content.nextCtIdx} drawPageContent\n"
else
if pageData ? isLandscape
then "90 rotate\n"
else ""
) + ''
${pageData.content}
${lib.optionalString (pageData ? drawPageContent) "end\n"}pgsave restore
showpage
'';
nextCtIdx = content.nextCtIdx + (if pageData ? drawPageContent then 1 else 0);
nextPgIdx = content.nextPgIdx + 1;
};
initialContent = {
content = ''
%!PS-Adobe-3.0
%%Orientation: Portrait
%%Pages: ${toString (builtins.length booklet.pages)}
%%EndComments
%%BeginSetup
${toString (dependencyContent (booklet.pages))}%%EndSetup
%************************************************************************
%************************************************************************
%*
%* Section Three: Page Rendering
%*
%************************************************************************
%************************************************************************
'';
nextPgIdx = 1;
nextCtIdx = 1;
};
finalContent = builtins.foldl' addPage initialContent booklet.pages;
in
pkgs.writeTextFile {
name = booklet.name;
text = finalContent.content + ''
%%EOF
'';
};
in
stdenv.mkDerivation {
name = "codex32${shortId}";

buildInputs = if doPdfGeneration then [ ghostscript ] else [ ];

phases = [ "buildPhase" ];
buildPhase = ''
set -e
mkdir "$out"
cd "$out"
cp ${renderBooklet fullBooklet} SSS32.ps
${lib.optionalString doOutputDiff "diff -C 5 ${src}/SSS32.ps SSS32.ps"}
sed -i 's/(revision \(.*\))/(revision \1${shortId})/' ./SSS32.ps
${lib.optionalString doPdfGeneration "ps2pdf -dPDFSETTINGS=/prepress SSS32.ps"}
'';
}

19 changes: 19 additions & 0 deletions include/checksum-table-1.ps.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
10 dict begin
pgsize aload pop
/pageW exch def
/pageH exch def

0 pageH neg translate

/Helvetica-Bold findfont 10 scalefont setfont
pageW 2 div pageH 48 sub moveto (MS32 Checksum Table) centreshow

/Courier findfont 8.5 scalefont setfont
36 pageH 64 sub % x y
pageW 64 sub pageH 144 sub 2 div % w h
0 drawChecksumTable

36 pageH 2 div 16 sub % x y
pageW 64 sub pageH 144 sub 2 div % w h
8 drawChecksumTable
end
19 changes: 19 additions & 0 deletions include/checksum-table-2.ps.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
10 dict begin
pgsize aload pop
/pageW exch def
/pageH exch def

0 pageH neg translate

/Helvetica-Bold findfont 10 scalefont setfont
pageW 2 div pageH 48 sub moveto (MS32 Checksum Table) centreshow

/Courier findfont 8.5 scalefont setfont
36 pageH 64 sub % x y
pageW 64 sub pageH 144 sub 2 div % w h
16 drawChecksumTable

36 pageH 2 div 16 sub % x y
pageW 64 sub pageH 144 sub 2 div % w h
24 drawChecksumTable
end
83 changes: 83 additions & 0 deletions include/checksum-worksheet.ps.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
% 0 pgsize aload pop pop neg translate
0 -750 translate

/Helvetica-Bold findfont 10 scalefont setfont
pgsize aload pop exch pop 2 div 700
moveto (ms32 Checksum Worksheet) centreshow

gsave
50 680 translate
ladder begin
drawgrid
% (2NAMES5GS8YDXGMLUW34LEN0PRDAK9GLF307N04SN6SKL) fillgrid
% (2NAMES5GS8YDXGMLUW34LEN0PRDAK9GL ) fillgrid
end
grestore

100 420 moveto
/Helvetica-Bold findfont 10 scalefont setfont
(Verifying Checksums) show
100 400 moveto
/Helvetica findfont 9 scalefont setfont
(Write out the 45 character data portion in the) show
100 390 moveto
(bold boxes, two at a time, starting on the top) show
100 380 moveto
(row. Working from the top row down, look up) show
100 370 moveto
(the first two characters of each odd row in the) show
100 360 moveto
(ms32 Checksum Table and write the ) polymodulus length 10 string cvs concatstrings show
100 350 moveto
(character word into the even row below it. Fill) show
100 340 moveto
(in the odd rows by adding the two characters) show
100 330 moveto
(above each cell. You may use either the) show
100 320 moveto
(addition wheel table. The first few boxes are) show
100 310 moveto
(already filled in for you. The last row will sum) show
100 300 moveto
(to ) show checksumstring {glyphshow} forall ( if the checksum is valid.) show
100 260 moveto
/Helvetica-Bold findfont 10 scalefont setfont
(Creating Checksums) show
100 240 moveto
/Helvetica findfont 9 scalefont setfont
(Follow the "Verifying Checksums" instructions) show
100 230 moveto
(to fill in everything but the shaded cells. To fill in) show
100 220 moveto
(the shaded cells, write ) show checksumstring {glyphshow} forall ( into the bottom) show
100 210 moveto
(row. Working from the bottom up, fill in the) show
100 200 moveto
(shaded cells by adding the two characters below) show
100 190 moveto
(each cell. The ) polymodulus length 10 string cvs ( characters in the bold shaded) concatstrings concatstrings show
100 180 moveto
(boxes will be the checksum.) show

450 650
/offsety exch def
/offsetx exch def
/Courier findfont 10 scalefont setfont
20 offsetx add offsety moveto (Addition Table) show
/Courier-Bold findfont 8 scalefont setfont
0 1 31 {
dup 2 add 7 mul offsetx add offsety 10 sub moveto
perm exch get
code exch get glyphshow
} for

0 1 31 {
/Courier-Bold findfont 8 scalefont setfont
offsetx 34.5 7 mul add offsety 20 sub 2 index 8 mul sub moveto
dup code exch perm exch get get glyphshow
/Courier findfont 8 scalefont setfont
dup 1 31 {
dup 2 add 7 mul offsetx add offsety 20 sub 3 index 8 mul sub moveto
perm exch get
perm 2 index get gf32add code exch get glyphshow
} for pop } for
8 changes: 8 additions & 0 deletions include/license.ps.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/Helvetica findfont 6 scalefont setfont
marginX1 marginY1 16 sub moveto
MIT {gsave ((c)) search {show pop /copyright glyphshow} if show grestore 0 -8 rmoveto} forall
/Helvetica findfont 6 scalefont setfont
warning {gsave show grestore 0 -7 rmoveto} forall
0 -16 rmoveto
/Helvetica findfont 8 scalefont setfont
README {gsave show grestore 0 -10 rmoveto} forall
Loading

0 comments on commit 865b397

Please sign in to comment.