File : peh.adb
1 ------------------------------------------------------------------------------
2 ------------------------------------------------------------------------------
3 -- This file is part of 'Finite Field Arithmetic', aka 'FFA'. --
4 -- --
5 -- (C) 2019 Stanislav Datskovskiy ( www.loper-os.org ) --
6 -- http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html --
7 -- --
8 -- You do not have, nor can you ever acquire the right to use, copy or --
9 -- distribute this software ; Should you use this software for any purpose, --
10 -- or copy and distribute it to anyone or in any manner, you are breaking --
11 -- the laws of whatever soi-disant jurisdiction, and you promise to --
12 -- continue doing so for the indefinite future. In any case, please --
13 -- always : read and understand any software ; verify any PGP signatures --
14 -- that you use - for any purpose. --
15 -- --
16 -- See also http://trilema.com/2015/a-new-software-licensing-paradigm . --
17 ------------------------------------------------------------------------------
18 ------------------------------------------------------------------------------
19
20 with OS; use OS;
21 with CmdLine; use CmdLine;
22 with FFA_RNG; use FFA_RNG;
23 with FFA_Calc; use FFA_Calc;
24
25
26 -- This is the 'main' procedure of Peh for all Unixlike OS.
27 procedure Peh is
28
29 PehDim : Peh_Dimensions; -- Operator-specified spacetime footprint.
30
31 RNG : RNG_Device; -- The selected RNG device. Peh requires a RNG.
32
33 begin
34
35 -- If a valid number of command line params was NOT given, print a likbez :
36 if Arg_Count < 5 or Arg_Count > 6 then
37 Eggog("Usage: ./peh WIDTH HEIGHT TAPESPACE LIFE [/dev/rng]");
38 end if;
39
40 declare
41 Arg1 : CmdLineArg;
42 Arg2 : CmdLineArg;
43 Arg3 : CmdLineArg;
44 Arg4 : CmdLineArg;
45 begin
46
47 -- Get commandline args:
48 Get_Argument(1, Arg1); -- First mandatory arg : Width
49 Get_Argument(2, Arg2); -- Second mandatory arg : Height
50 Get_Argument(3, Arg3); -- Third mandatory arg : TapeSpace
51 Get_Argument(4, Arg4); -- Fourth mandatory arg : Life
52
53 if Arg_Count = 6 then
54
55 -- A RNG was specified (Arg_Count includes program name itself)
56 declare
57 Arg5 : CmdLineArg;
58 begin
59 Get_Argument(5, Arg5); -- Fifth arg (optional) : RNG device
60
61 -- Ada.Sequential_IO chokes on paths with trailing whitespace!
62 -- So we have to give it a trimmed path. But we can't use
63 -- Ada.Strings.Fixed.Trim, because it suffers from
64 -- SecondaryStackism-syphilis. Instead we are stuck doing this:
65 Init_RNG(RNG, Arg5(Arg5'First .. Len_Arg(5)));
66 end;
67
68 else
69
70 -- If RNG was NOT explicitly specified:
71 Init_RNG(RNG); -- Use the machine default. The '?' Op requires a RNG.
72
73 -- Warn the operator that we are going to use the default system RNG:
74 Achtung("WARNING: The '?' command will use DEFAULT entropy source : "
75 & Default_RNG_Path & " !");
76 -- Generally, you do NOT want this, outside of noob exploration/tests.
77
78 end if;
79
80 -- Parse the four mandatory arguments into Positives:
81 PehDim.Width := Positive'Value( Arg1 );
82 PehDim.Height := Positive'Value( Arg2 );
83 PehDim.TapeSpace := Peh_Tape_Range'Value( Arg3 );
84 PehDim.Life := Natural'Value( Arg4 );
85
86 exception
87
88 -- There was an attempt to parse garbage in the init parameters:
89 when others =>
90 Eggog("Invalid arguments!");
91
92 end;
93
94 -- Validate requested Peh Dimensions. If invalid, program will terminate.
95 Validate_Peh_Dimensions(PehDim);
96
97 -- Read, from Unix 'standard input' , and then execute, the Tape:
98 declare
99
100 -- The current Tape input symbol
101 Tape_Read_Char : Character;
102
103 -- The TapeSpace
104 TapeSpace : Peh_Tapes(1 .. PehDim.TapeSpace) := (others => ' ');
105
106 -- 'End of File' condition when reading :
107 EOF : Boolean := False;
108
109 -- Will contain the Verdict produced by the Tape:
110 Verdict : Peh_Verdicts;
111
112 begin
113
114 -- Attempt to read the entire expected Tapespace length, and no more:
115 for TapePosition in TapeSpace'Range loop
116
117 -- Attempt to receive a symbol from the standard input:
118 if Read_Char(Tape_Read_Char) then
119
120 -- Save the successfully-read symbol to the TapeSpace:
121 TapeSpace(TapePosition) := Tape_Read_Char;
122
123 else
124
125 -- Got an EOF instead of a symbol:
126 EOF := True;
127 if TapePosition /= TapeSpace'Length then
128 Achtung("WARNING: Short Tape: Tapespace filled to position:" &
129 Peh_Tape_Range'Image(TapePosition) & " of" &
130 Peh_Tape_Range'Image(TapeSpace'Last) & ".");
131 end if;
132
133 end if;
134
135 exit when EOF; -- When EOF, halt reading, and proceed to execution.
136
137 end loop;
138
139 -- Execute Peh over the given Tape, on Peh Machine with given dimensions:
140 Verdict := Peh_Machine(Dimensions => PehDim,
141 Tape => TapeSpace,
142 RNG => RNG);
143
144 -- A correctly-written Peh Tape is expected to produce a Verdict.
145 -- On Unix, we will give it to the caller process via the usual means:
146 case Verdict is
147
148 -- Tape produced a Verdict of 'Yes' :
149 when Yes =>
150 Quit(Yes_Code);
151
152 -- Tape produced a Verdict of 'No' :
153 when No =>
154 Quit(No_Code);
155
156 -- Tape ran to completion without producing any Verdict at all.
157 -- Outside of simple test scenarios, noob explorations, etc.,
158 -- this usually means that there is a logical mistake in the
159 -- Tape somewhere, and we will warn the operator:
160 when Mu =>
161 Achtung("WARNING: Tape terminated without a Verdict.");
162 Quit(Mu_Code);
163
164 end case;
165
166 -- If the Tape aborted on account of a fatal error condition (e.g. div0)
167 -- Peh will Quit(Sad_Code) (see E(..) in ffa_calc.adb .)
168 -- Therefore, Peh ALWAYS returns one of FOUR possible Unix return-codes:
169 -- -2, -1, 0, 1. (see os.ads .)
170
171 end;
172
173 end Peh;