xref: /freebsd/stand/forth/support.4th (revision ca987d4641cdcd7f27e153db17c5bf064934faf5)
1*ca987d46SWarner Losh\ Copyright (c) 1999 Daniel C. Sobral <dcs@FreeBSD.org>
2*ca987d46SWarner Losh\ All rights reserved.
3*ca987d46SWarner Losh\
4*ca987d46SWarner Losh\ Redistribution and use in source and binary forms, with or without
5*ca987d46SWarner Losh\ modification, are permitted provided that the following conditions
6*ca987d46SWarner Losh\ are met:
7*ca987d46SWarner Losh\ 1. Redistributions of source code must retain the above copyright
8*ca987d46SWarner Losh\    notice, this list of conditions and the following disclaimer.
9*ca987d46SWarner Losh\ 2. Redistributions in binary form must reproduce the above copyright
10*ca987d46SWarner Losh\    notice, this list of conditions and the following disclaimer in the
11*ca987d46SWarner Losh\    documentation and/or other materials provided with the distribution.
12*ca987d46SWarner Losh\
13*ca987d46SWarner Losh\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14*ca987d46SWarner Losh\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15*ca987d46SWarner Losh\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16*ca987d46SWarner Losh\ ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17*ca987d46SWarner Losh\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18*ca987d46SWarner Losh\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19*ca987d46SWarner Losh\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20*ca987d46SWarner Losh\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21*ca987d46SWarner Losh\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22*ca987d46SWarner Losh\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23*ca987d46SWarner Losh\ SUCH DAMAGE.
24*ca987d46SWarner Losh\
25*ca987d46SWarner Losh\ $FreeBSD$
26*ca987d46SWarner Losh
27*ca987d46SWarner Losh\ Loader.rc support functions:
28*ca987d46SWarner Losh\
29*ca987d46SWarner Losh\ initialize ( addr len -- )	as above, plus load_conf_files
30*ca987d46SWarner Losh\ load_conf ( addr len -- )	load conf file given
31*ca987d46SWarner Losh\ include_conf_files ( -- )	load all conf files in load_conf_files
32*ca987d46SWarner Losh\ print_syntax_error ( -- )	print line and marker of where a syntax
33*ca987d46SWarner Losh\				error was detected
34*ca987d46SWarner Losh\ print_line ( -- )		print last line processed
35*ca987d46SWarner Losh\ load_kernel ( -- )		load kernel
36*ca987d46SWarner Losh\ load_modules ( -- )		load modules flagged
37*ca987d46SWarner Losh\
38*ca987d46SWarner Losh\ Exported structures:
39*ca987d46SWarner Losh\
40*ca987d46SWarner Losh\ string			counted string structure
41*ca987d46SWarner Losh\	cell .addr			string address
42*ca987d46SWarner Losh\	cell .len			string length
43*ca987d46SWarner Losh\ module			module loading information structure
44*ca987d46SWarner Losh\	cell module.flag		should we load it?
45*ca987d46SWarner Losh\	string module.name		module's name
46*ca987d46SWarner Losh\	string module.loadname		name to be used in loading the module
47*ca987d46SWarner Losh\	string module.type		module's type
48*ca987d46SWarner Losh\	string module.args		flags to be passed during load
49*ca987d46SWarner Losh\	string module.beforeload	command to be executed before load
50*ca987d46SWarner Losh\	string module.afterload		command to be executed after load
51*ca987d46SWarner Losh\	string module.loaderror		command to be executed if load fails
52*ca987d46SWarner Losh\	cell module.next		list chain
53*ca987d46SWarner Losh\
54*ca987d46SWarner Losh\ Exported global variables;
55*ca987d46SWarner Losh\
56*ca987d46SWarner Losh\ string conf_files		configuration files to be loaded
57*ca987d46SWarner Losh\ cell modules_options		pointer to first module information
58*ca987d46SWarner Losh\ value verbose?		indicates if user wants a verbose loading
59*ca987d46SWarner Losh\ value any_conf_read?		indicates if a conf file was successfully read
60*ca987d46SWarner Losh\
61*ca987d46SWarner Losh\ Other exported words:
62*ca987d46SWarner Losh\    note, strlen is internal
63*ca987d46SWarner Losh\ strdup ( addr len -- addr' len)			similar to strdup(3)
64*ca987d46SWarner Losh\ strcat ( addr len addr' len' -- addr len+len' )	similar to strcat(3)
65*ca987d46SWarner Losh\ s' ( | string' -- addr len | )			similar to s"
66*ca987d46SWarner Losh\ rudimentary structure support
67*ca987d46SWarner Losh
68*ca987d46SWarner Losh\ Exception values
69*ca987d46SWarner Losh
70*ca987d46SWarner Losh1 constant ESYNTAX
71*ca987d46SWarner Losh2 constant ENOMEM
72*ca987d46SWarner Losh3 constant EFREE
73*ca987d46SWarner Losh4 constant ESETERROR	\ error setting environment variable
74*ca987d46SWarner Losh5 constant EREAD	\ error reading
75*ca987d46SWarner Losh6 constant EOPEN
76*ca987d46SWarner Losh7 constant EEXEC	\ XXX never catched
77*ca987d46SWarner Losh8 constant EBEFORELOAD
78*ca987d46SWarner Losh9 constant EAFTERLOAD
79*ca987d46SWarner Losh
80*ca987d46SWarner Losh\ I/O constants
81*ca987d46SWarner Losh
82*ca987d46SWarner Losh0 constant SEEK_SET
83*ca987d46SWarner Losh1 constant SEEK_CUR
84*ca987d46SWarner Losh2 constant SEEK_END
85*ca987d46SWarner Losh
86*ca987d46SWarner Losh0 constant O_RDONLY
87*ca987d46SWarner Losh1 constant O_WRONLY
88*ca987d46SWarner Losh2 constant O_RDWR
89*ca987d46SWarner Losh
90*ca987d46SWarner Losh\ Crude structure support
91*ca987d46SWarner Losh
92*ca987d46SWarner Losh: structure:
93*ca987d46SWarner Losh  create here 0 , ['] drop , 0
94*ca987d46SWarner Losh  does> create here swap dup @ allot cell+ @ execute
95*ca987d46SWarner Losh;
96*ca987d46SWarner Losh: member: create dup , over , + does> cell+ @ + ;
97*ca987d46SWarner Losh: ;structure swap ! ;
98*ca987d46SWarner Losh: constructor! >body cell+ ! ;
99*ca987d46SWarner Losh: constructor: over :noname ;
100*ca987d46SWarner Losh: ;constructor postpone ; swap cell+ ! ; immediate
101*ca987d46SWarner Losh: sizeof ' >body @ state @ if postpone literal then ; immediate
102*ca987d46SWarner Losh: offsetof ' >body cell+ @ state @ if postpone literal then ; immediate
103*ca987d46SWarner Losh: ptr 1 cells member: ;
104*ca987d46SWarner Losh: int 1 cells member: ;
105*ca987d46SWarner Losh
106*ca987d46SWarner Losh\ String structure
107*ca987d46SWarner Losh
108*ca987d46SWarner Loshstructure: string
109*ca987d46SWarner Losh	ptr .addr
110*ca987d46SWarner Losh	int .len
111*ca987d46SWarner Losh	constructor:
112*ca987d46SWarner Losh	  0 over .addr !
113*ca987d46SWarner Losh	  0 swap .len !
114*ca987d46SWarner Losh	;constructor
115*ca987d46SWarner Losh;structure
116*ca987d46SWarner Losh
117*ca987d46SWarner Losh
118*ca987d46SWarner Losh\ Module options linked list
119*ca987d46SWarner Losh
120*ca987d46SWarner Loshstructure: module
121*ca987d46SWarner Losh	int module.flag
122*ca987d46SWarner Losh	sizeof string member: module.name
123*ca987d46SWarner Losh	sizeof string member: module.loadname
124*ca987d46SWarner Losh	sizeof string member: module.type
125*ca987d46SWarner Losh	sizeof string member: module.args
126*ca987d46SWarner Losh	sizeof string member: module.beforeload
127*ca987d46SWarner Losh	sizeof string member: module.afterload
128*ca987d46SWarner Losh	sizeof string member: module.loaderror
129*ca987d46SWarner Losh	ptr module.next
130*ca987d46SWarner Losh;structure
131*ca987d46SWarner Losh
132*ca987d46SWarner Losh\ Internal loader structures (preloaded_file, kernel_module, file_metadata)
133*ca987d46SWarner Losh\ must be in sync with the C struct in stand/common/bootstrap.h
134*ca987d46SWarner Loshstructure: preloaded_file
135*ca987d46SWarner Losh	ptr pf.name
136*ca987d46SWarner Losh	ptr pf.type
137*ca987d46SWarner Losh	ptr pf.args
138*ca987d46SWarner Losh	ptr pf.metadata	\ file_metadata
139*ca987d46SWarner Losh	int pf.loader
140*ca987d46SWarner Losh	int pf.addr
141*ca987d46SWarner Losh	int pf.size
142*ca987d46SWarner Losh	ptr pf.modules	\ kernel_module
143*ca987d46SWarner Losh	ptr pf.next	\ preloaded_file
144*ca987d46SWarner Losh;structure
145*ca987d46SWarner Losh
146*ca987d46SWarner Loshstructure: kernel_module
147*ca987d46SWarner Losh	ptr km.name
148*ca987d46SWarner Losh	\ ptr km.args
149*ca987d46SWarner Losh	ptr km.fp	\ preloaded_file
150*ca987d46SWarner Losh	ptr km.next	\ kernel_module
151*ca987d46SWarner Losh;structure
152*ca987d46SWarner Losh
153*ca987d46SWarner Loshstructure: file_metadata
154*ca987d46SWarner Losh	int		md.size
155*ca987d46SWarner Losh	2 member:	md.type	\ this is not ANS Forth compatible (XXX)
156*ca987d46SWarner Losh	ptr		md.next	\ file_metadata
157*ca987d46SWarner Losh	0 member:	md.data	\ variable size
158*ca987d46SWarner Losh;structure
159*ca987d46SWarner Losh
160*ca987d46SWarner Losh\ end of structures
161*ca987d46SWarner Losh
162*ca987d46SWarner Losh\ Global variables
163*ca987d46SWarner Losh
164*ca987d46SWarner Loshstring conf_files
165*ca987d46SWarner Loshstring nextboot_conf_file
166*ca987d46SWarner Loshcreate module_options sizeof module.next allot 0 module_options !
167*ca987d46SWarner Loshcreate last_module_option sizeof module.next allot 0 last_module_option !
168*ca987d46SWarner Losh0 value verbose?
169*ca987d46SWarner Losh0 value nextboot?
170*ca987d46SWarner Losh
171*ca987d46SWarner Losh\ Support string functions
172*ca987d46SWarner Losh: strdup { addr len -- addr' len' }
173*ca987d46SWarner Losh  len allocate if ENOMEM throw then
174*ca987d46SWarner Losh  addr over len move len
175*ca987d46SWarner Losh;
176*ca987d46SWarner Losh
177*ca987d46SWarner Losh: strcat  { addr len addr' len' -- addr len+len' }
178*ca987d46SWarner Losh  addr' addr len + len' move
179*ca987d46SWarner Losh  addr len len' +
180*ca987d46SWarner Losh;
181*ca987d46SWarner Losh
182*ca987d46SWarner Losh: strchr { addr len c -- addr' len' }
183*ca987d46SWarner Losh  begin
184*ca987d46SWarner Losh    len
185*ca987d46SWarner Losh  while
186*ca987d46SWarner Losh    addr c@ c = if addr len exit then
187*ca987d46SWarner Losh    addr 1 + to addr
188*ca987d46SWarner Losh    len 1 - to len
189*ca987d46SWarner Losh  repeat
190*ca987d46SWarner Losh  0 0
191*ca987d46SWarner Losh;
192*ca987d46SWarner Losh
193*ca987d46SWarner Losh: s' \ same as s", allows " in the string
194*ca987d46SWarner Losh  [char] ' parse
195*ca987d46SWarner Losh  state @ if postpone sliteral then
196*ca987d46SWarner Losh; immediate
197*ca987d46SWarner Losh
198*ca987d46SWarner Losh: 2>r postpone >r postpone >r ; immediate
199*ca987d46SWarner Losh: 2r> postpone r> postpone r> ; immediate
200*ca987d46SWarner Losh: 2r@ postpone 2r> postpone 2dup postpone 2>r ; immediate
201*ca987d46SWarner Losh
202*ca987d46SWarner Losh: getenv?  getenv -1 = if false else drop true then ;
203*ca987d46SWarner Losh
204*ca987d46SWarner Losh\ determine if a word appears in a string, case-insensitive
205*ca987d46SWarner Losh: contains? ( addr1 len1 addr2 len2 -- 0 | -1 )
206*ca987d46SWarner Losh	2 pick 0= if 2drop 2drop true exit then
207*ca987d46SWarner Losh	dup 0= if 2drop 2drop false exit then
208*ca987d46SWarner Losh	begin
209*ca987d46SWarner Losh		begin
210*ca987d46SWarner Losh			swap dup c@ dup 32 = over 9 = or over 10 = or
211*ca987d46SWarner Losh			over 13 = or over 44 = or swap drop
212*ca987d46SWarner Losh		while 1+ swap 1- repeat
213*ca987d46SWarner Losh		swap 2 pick 1- over <
214*ca987d46SWarner Losh	while
215*ca987d46SWarner Losh		2over 2over drop over compare-insensitive 0= if
216*ca987d46SWarner Losh			2 pick over = if 2drop 2drop true exit then
217*ca987d46SWarner Losh			2 pick tuck - -rot + swap over c@ dup 32 =
218*ca987d46SWarner Losh			over 9 = or over 10 = or over 13 = or over 44 = or
219*ca987d46SWarner Losh			swap drop if 2drop 2drop true exit then
220*ca987d46SWarner Losh		then begin
221*ca987d46SWarner Losh			swap dup c@ dup 32 = over 9 = or over 10 = or
222*ca987d46SWarner Losh			over 13 = or over 44 = or swap drop
223*ca987d46SWarner Losh			if false else true then 2 pick 0> and
224*ca987d46SWarner Losh		while 1+ swap 1- repeat
225*ca987d46SWarner Losh		swap
226*ca987d46SWarner Losh	repeat
227*ca987d46SWarner Losh	2drop 2drop false
228*ca987d46SWarner Losh;
229*ca987d46SWarner Losh
230*ca987d46SWarner Losh: boot_serial? ( -- 0 | -1 )
231*ca987d46SWarner Losh	s" console" getenv dup -1 <> if
232*ca987d46SWarner Losh		s" comconsole" 2swap contains?
233*ca987d46SWarner Losh	else drop false then
234*ca987d46SWarner Losh	s" boot_serial" getenv dup -1 <> if
235*ca987d46SWarner Losh		swap drop 0>
236*ca987d46SWarner Losh	else drop false then
237*ca987d46SWarner Losh	or \ console contains comconsole ( or ) boot_serial
238*ca987d46SWarner Losh	s" boot_multicons" getenv dup -1 <> if
239*ca987d46SWarner Losh		swap drop 0>
240*ca987d46SWarner Losh	else drop false then
241*ca987d46SWarner Losh	or \ previous boolean ( or ) boot_multicons
242*ca987d46SWarner Losh;
243*ca987d46SWarner Losh
244*ca987d46SWarner Losh\ Private definitions
245*ca987d46SWarner Losh
246*ca987d46SWarner Loshvocabulary support-functions
247*ca987d46SWarner Loshonly forth also support-functions definitions
248*ca987d46SWarner Losh
249*ca987d46SWarner Losh\ Some control characters constants
250*ca987d46SWarner Losh
251*ca987d46SWarner Losh7 constant bell
252*ca987d46SWarner Losh8 constant backspace
253*ca987d46SWarner Losh9 constant tab
254*ca987d46SWarner Losh10 constant lf
255*ca987d46SWarner Losh13 constant <cr>
256*ca987d46SWarner Losh
257*ca987d46SWarner Losh\ Read buffer size
258*ca987d46SWarner Losh
259*ca987d46SWarner Losh80 constant read_buffer_size
260*ca987d46SWarner Losh
261*ca987d46SWarner Losh\ Standard suffixes
262*ca987d46SWarner Losh
263*ca987d46SWarner Losh: load_module_suffix		s" _load" ;
264*ca987d46SWarner Losh: module_loadname_suffix	s" _name" ;
265*ca987d46SWarner Losh: module_type_suffix		s" _type" ;
266*ca987d46SWarner Losh: module_args_suffix		s" _flags" ;
267*ca987d46SWarner Losh: module_beforeload_suffix	s" _before" ;
268*ca987d46SWarner Losh: module_afterload_suffix	s" _after" ;
269*ca987d46SWarner Losh: module_loaderror_suffix	s" _error" ;
270*ca987d46SWarner Losh
271*ca987d46SWarner Losh\ Support operators
272*ca987d46SWarner Losh
273*ca987d46SWarner Losh: >= < 0= ;
274*ca987d46SWarner Losh: <= > 0= ;
275*ca987d46SWarner Losh
276*ca987d46SWarner Losh\ Assorted support functions
277*ca987d46SWarner Losh
278*ca987d46SWarner Losh: free-memory free if EFREE throw then ;
279*ca987d46SWarner Losh
280*ca987d46SWarner Losh: strget { var -- addr len } var .addr @ var .len @ ;
281*ca987d46SWarner Losh
282*ca987d46SWarner Losh\ assign addr len to variable.
283*ca987d46SWarner Losh: strset  { addr len var -- } addr var .addr !  len var .len !  ;
284*ca987d46SWarner Losh
285*ca987d46SWarner Losh\ free memory and reset fields
286*ca987d46SWarner Losh: strfree { var -- } var .addr @ ?dup if free-memory 0 0 var strset then ;
287*ca987d46SWarner Losh
288*ca987d46SWarner Losh\ free old content, make a copy of the string and assign to variable
289*ca987d46SWarner Losh: string= { addr len var -- } var strfree addr len strdup var strset ;
290*ca987d46SWarner Losh
291*ca987d46SWarner Losh: strtype ( str -- ) strget type ;
292*ca987d46SWarner Losh
293*ca987d46SWarner Losh\ assign a reference to what is on the stack
294*ca987d46SWarner Losh: strref { addr len var -- addr len }
295*ca987d46SWarner Losh  addr var .addr ! len var .len ! addr len
296*ca987d46SWarner Losh;
297*ca987d46SWarner Losh
298*ca987d46SWarner Losh\ unquote a string
299*ca987d46SWarner Losh: unquote ( addr len -- addr len )
300*ca987d46SWarner Losh  over c@ [char] " = if 2 chars - swap char+ swap then
301*ca987d46SWarner Losh;
302*ca987d46SWarner Losh
303*ca987d46SWarner Losh\ Assignment data temporary storage
304*ca987d46SWarner Losh
305*ca987d46SWarner Loshstring name_buffer
306*ca987d46SWarner Loshstring value_buffer
307*ca987d46SWarner Losh
308*ca987d46SWarner Losh\ Line by line file reading functions
309*ca987d46SWarner Losh\
310*ca987d46SWarner Losh\ exported:
311*ca987d46SWarner Losh\	line_buffer
312*ca987d46SWarner Losh\	end_of_file?
313*ca987d46SWarner Losh\	fd
314*ca987d46SWarner Losh\	read_line
315*ca987d46SWarner Losh\	reset_line_reading
316*ca987d46SWarner Losh
317*ca987d46SWarner Loshvocabulary line-reading
318*ca987d46SWarner Loshalso line-reading definitions
319*ca987d46SWarner Losh
320*ca987d46SWarner Losh\ File data temporary storage
321*ca987d46SWarner Losh
322*ca987d46SWarner Loshstring read_buffer
323*ca987d46SWarner Losh0 value read_buffer_ptr
324*ca987d46SWarner Losh
325*ca987d46SWarner Losh\ File's line reading function
326*ca987d46SWarner Losh
327*ca987d46SWarner Loshget-current ( -- wid ) previous definitions
328*ca987d46SWarner Losh
329*ca987d46SWarner Loshstring line_buffer
330*ca987d46SWarner Losh0 value end_of_file?
331*ca987d46SWarner Loshvariable fd
332*ca987d46SWarner Losh
333*ca987d46SWarner Losh>search ( wid -- ) definitions
334*ca987d46SWarner Losh
335*ca987d46SWarner Losh: skip_newlines
336*ca987d46SWarner Losh  begin
337*ca987d46SWarner Losh    read_buffer .len @ read_buffer_ptr >
338*ca987d46SWarner Losh  while
339*ca987d46SWarner Losh    read_buffer .addr @ read_buffer_ptr + c@ lf = if
340*ca987d46SWarner Losh      read_buffer_ptr char+ to read_buffer_ptr
341*ca987d46SWarner Losh    else
342*ca987d46SWarner Losh      exit
343*ca987d46SWarner Losh    then
344*ca987d46SWarner Losh  repeat
345*ca987d46SWarner Losh;
346*ca987d46SWarner Losh
347*ca987d46SWarner Losh: scan_buffer  ( -- addr len )
348*ca987d46SWarner Losh  read_buffer_ptr >r
349*ca987d46SWarner Losh  begin
350*ca987d46SWarner Losh    read_buffer .len @ r@ >
351*ca987d46SWarner Losh  while
352*ca987d46SWarner Losh    read_buffer .addr @ r@ + c@ lf = if
353*ca987d46SWarner Losh      read_buffer .addr @ read_buffer_ptr +  ( -- addr )
354*ca987d46SWarner Losh      r@ read_buffer_ptr -                   ( -- len )
355*ca987d46SWarner Losh      r> to read_buffer_ptr
356*ca987d46SWarner Losh      exit
357*ca987d46SWarner Losh    then
358*ca987d46SWarner Losh    r> char+ >r
359*ca987d46SWarner Losh  repeat
360*ca987d46SWarner Losh  read_buffer .addr @ read_buffer_ptr +  ( -- addr )
361*ca987d46SWarner Losh  r@ read_buffer_ptr -                   ( -- len )
362*ca987d46SWarner Losh  r> to read_buffer_ptr
363*ca987d46SWarner Losh;
364*ca987d46SWarner Losh
365*ca987d46SWarner Losh: line_buffer_resize  ( len -- len )
366*ca987d46SWarner Losh  >r
367*ca987d46SWarner Losh  line_buffer .len @ if
368*ca987d46SWarner Losh    line_buffer .addr @
369*ca987d46SWarner Losh    line_buffer .len @ r@ +
370*ca987d46SWarner Losh    resize if ENOMEM throw then
371*ca987d46SWarner Losh  else
372*ca987d46SWarner Losh    r@ allocate if ENOMEM throw then
373*ca987d46SWarner Losh  then
374*ca987d46SWarner Losh  line_buffer .addr !
375*ca987d46SWarner Losh  r>
376*ca987d46SWarner Losh;
377*ca987d46SWarner Losh
378*ca987d46SWarner Losh: append_to_line_buffer  ( addr len -- )
379*ca987d46SWarner Losh  line_buffer strget
380*ca987d46SWarner Losh  2swap strcat
381*ca987d46SWarner Losh  line_buffer .len !
382*ca987d46SWarner Losh  drop
383*ca987d46SWarner Losh;
384*ca987d46SWarner Losh
385*ca987d46SWarner Losh: read_from_buffer
386*ca987d46SWarner Losh  scan_buffer            ( -- addr len )
387*ca987d46SWarner Losh  line_buffer_resize     ( len -- len )
388*ca987d46SWarner Losh  append_to_line_buffer  ( addr len -- )
389*ca987d46SWarner Losh;
390*ca987d46SWarner Losh
391*ca987d46SWarner Losh: refill_required?
392*ca987d46SWarner Losh  read_buffer .len @ read_buffer_ptr =
393*ca987d46SWarner Losh  end_of_file? 0= and
394*ca987d46SWarner Losh;
395*ca987d46SWarner Losh
396*ca987d46SWarner Losh: refill_buffer
397*ca987d46SWarner Losh  0 to read_buffer_ptr
398*ca987d46SWarner Losh  read_buffer .addr @ 0= if
399*ca987d46SWarner Losh    read_buffer_size allocate if ENOMEM throw then
400*ca987d46SWarner Losh    read_buffer .addr !
401*ca987d46SWarner Losh  then
402*ca987d46SWarner Losh  fd @ read_buffer .addr @ read_buffer_size fread
403*ca987d46SWarner Losh  dup -1 = if EREAD throw then
404*ca987d46SWarner Losh  dup 0= if true to end_of_file? then
405*ca987d46SWarner Losh  read_buffer .len !
406*ca987d46SWarner Losh;
407*ca987d46SWarner Losh
408*ca987d46SWarner Loshget-current ( -- wid ) previous definitions >search ( wid -- )
409*ca987d46SWarner Losh
410*ca987d46SWarner Losh: reset_line_reading
411*ca987d46SWarner Losh  0 to read_buffer_ptr
412*ca987d46SWarner Losh;
413*ca987d46SWarner Losh
414*ca987d46SWarner Losh: read_line
415*ca987d46SWarner Losh  line_buffer strfree
416*ca987d46SWarner Losh  skip_newlines
417*ca987d46SWarner Losh  begin
418*ca987d46SWarner Losh    read_from_buffer
419*ca987d46SWarner Losh    refill_required?
420*ca987d46SWarner Losh  while
421*ca987d46SWarner Losh    refill_buffer
422*ca987d46SWarner Losh  repeat
423*ca987d46SWarner Losh;
424*ca987d46SWarner Losh
425*ca987d46SWarner Loshonly forth also support-functions definitions
426*ca987d46SWarner Losh
427*ca987d46SWarner Losh\ Conf file line parser:
428*ca987d46SWarner Losh\ <line> ::= <spaces><name><spaces>'='<spaces><value><spaces>[<comment>] |
429*ca987d46SWarner Losh\            <spaces>[<comment>]
430*ca987d46SWarner Losh\ <name> ::= <letter>{<letter>|<digit>|'_'}
431*ca987d46SWarner Losh\ <value> ::= '"'{<character_set>|'\'<anything>}'"' | <name>
432*ca987d46SWarner Losh\ <character_set> ::= ASCII 32 to 126, except '\' and '"'
433*ca987d46SWarner Losh\ <comment> ::= '#'{<anything>}
434*ca987d46SWarner Losh\
435*ca987d46SWarner Losh\ exported:
436*ca987d46SWarner Losh\	line_pointer
437*ca987d46SWarner Losh\	process_conf
438*ca987d46SWarner Losh
439*ca987d46SWarner Losh0 value line_pointer
440*ca987d46SWarner Losh
441*ca987d46SWarner Loshvocabulary file-processing
442*ca987d46SWarner Loshalso file-processing definitions
443*ca987d46SWarner Losh
444*ca987d46SWarner Losh\ parser functions
445*ca987d46SWarner Losh\
446*ca987d46SWarner Losh\ exported:
447*ca987d46SWarner Losh\	get_assignment
448*ca987d46SWarner Losh
449*ca987d46SWarner Loshvocabulary parser
450*ca987d46SWarner Loshalso parser definitions
451*ca987d46SWarner Losh
452*ca987d46SWarner Losh0 value parsing_function
453*ca987d46SWarner Losh0 value end_of_line
454*ca987d46SWarner Losh
455*ca987d46SWarner Losh: end_of_line?  line_pointer end_of_line = ;
456*ca987d46SWarner Losh
457*ca987d46SWarner Losh\ classifiers for various character classes in the input line
458*ca987d46SWarner Losh
459*ca987d46SWarner Losh: letter?
460*ca987d46SWarner Losh  line_pointer c@ >r
461*ca987d46SWarner Losh  r@ [char] A >=
462*ca987d46SWarner Losh  r@ [char] Z <= and
463*ca987d46SWarner Losh  r@ [char] a >=
464*ca987d46SWarner Losh  r> [char] z <= and
465*ca987d46SWarner Losh  or
466*ca987d46SWarner Losh;
467*ca987d46SWarner Losh
468*ca987d46SWarner Losh: digit?
469*ca987d46SWarner Losh  line_pointer c@ >r
470*ca987d46SWarner Losh  r@ [char] - =
471*ca987d46SWarner Losh  r@ [char] 0 >=
472*ca987d46SWarner Losh  r> [char] 9 <= and
473*ca987d46SWarner Losh  or
474*ca987d46SWarner Losh;
475*ca987d46SWarner Losh
476*ca987d46SWarner Losh: quote?  line_pointer c@ [char] " = ;
477*ca987d46SWarner Losh
478*ca987d46SWarner Losh: assignment_sign?  line_pointer c@ [char] = = ;
479*ca987d46SWarner Losh
480*ca987d46SWarner Losh: comment?  line_pointer c@ [char] # = ;
481*ca987d46SWarner Losh
482*ca987d46SWarner Losh: space?  line_pointer c@ bl = line_pointer c@ tab = or ;
483*ca987d46SWarner Losh
484*ca987d46SWarner Losh: backslash?  line_pointer c@ [char] \ = ;
485*ca987d46SWarner Losh
486*ca987d46SWarner Losh: underscore?  line_pointer c@ [char] _ = ;
487*ca987d46SWarner Losh
488*ca987d46SWarner Losh: dot?  line_pointer c@ [char] . = ;
489*ca987d46SWarner Losh
490*ca987d46SWarner Losh\ manipulation of input line
491*ca987d46SWarner Losh: skip_character line_pointer char+ to line_pointer ;
492*ca987d46SWarner Losh
493*ca987d46SWarner Losh: skip_to_end_of_line end_of_line to line_pointer ;
494*ca987d46SWarner Losh
495*ca987d46SWarner Losh: eat_space
496*ca987d46SWarner Losh  begin
497*ca987d46SWarner Losh    end_of_line? if 0 else space? then
498*ca987d46SWarner Losh  while
499*ca987d46SWarner Losh    skip_character
500*ca987d46SWarner Losh  repeat
501*ca987d46SWarner Losh;
502*ca987d46SWarner Losh
503*ca987d46SWarner Losh: parse_name  ( -- addr len )
504*ca987d46SWarner Losh  line_pointer
505*ca987d46SWarner Losh  begin
506*ca987d46SWarner Losh    end_of_line? if 0 else letter? digit? underscore? dot? or or or then
507*ca987d46SWarner Losh  while
508*ca987d46SWarner Losh    skip_character
509*ca987d46SWarner Losh  repeat
510*ca987d46SWarner Losh  line_pointer over -
511*ca987d46SWarner Losh  strdup
512*ca987d46SWarner Losh;
513*ca987d46SWarner Losh
514*ca987d46SWarner Losh: remove_backslashes  { addr len | addr' len' -- addr' len' }
515*ca987d46SWarner Losh  len allocate if ENOMEM throw then
516*ca987d46SWarner Losh  to addr'
517*ca987d46SWarner Losh  addr >r
518*ca987d46SWarner Losh  begin
519*ca987d46SWarner Losh    addr c@ [char] \ <> if
520*ca987d46SWarner Losh      addr c@ addr' len' + c!
521*ca987d46SWarner Losh      len' char+ to len'
522*ca987d46SWarner Losh    then
523*ca987d46SWarner Losh    addr char+ to addr
524*ca987d46SWarner Losh    r@ len + addr =
525*ca987d46SWarner Losh  until
526*ca987d46SWarner Losh  r> drop
527*ca987d46SWarner Losh  addr' len'
528*ca987d46SWarner Losh;
529*ca987d46SWarner Losh
530*ca987d46SWarner Losh: parse_quote  ( -- addr len )
531*ca987d46SWarner Losh  line_pointer
532*ca987d46SWarner Losh  skip_character
533*ca987d46SWarner Losh  end_of_line? if ESYNTAX throw then
534*ca987d46SWarner Losh  begin
535*ca987d46SWarner Losh    quote? 0=
536*ca987d46SWarner Losh  while
537*ca987d46SWarner Losh    backslash? if
538*ca987d46SWarner Losh      skip_character
539*ca987d46SWarner Losh      end_of_line? if ESYNTAX throw then
540*ca987d46SWarner Losh    then
541*ca987d46SWarner Losh    skip_character
542*ca987d46SWarner Losh    end_of_line? if ESYNTAX throw then
543*ca987d46SWarner Losh  repeat
544*ca987d46SWarner Losh  skip_character
545*ca987d46SWarner Losh  line_pointer over -
546*ca987d46SWarner Losh  remove_backslashes
547*ca987d46SWarner Losh;
548*ca987d46SWarner Losh
549*ca987d46SWarner Losh: read_name
550*ca987d46SWarner Losh  parse_name		( -- addr len )
551*ca987d46SWarner Losh  name_buffer strset
552*ca987d46SWarner Losh;
553*ca987d46SWarner Losh
554*ca987d46SWarner Losh: read_value
555*ca987d46SWarner Losh  quote? if
556*ca987d46SWarner Losh    parse_quote		( -- addr len )
557*ca987d46SWarner Losh  else
558*ca987d46SWarner Losh    parse_name		( -- addr len )
559*ca987d46SWarner Losh  then
560*ca987d46SWarner Losh  value_buffer strset
561*ca987d46SWarner Losh;
562*ca987d46SWarner Losh
563*ca987d46SWarner Losh: comment
564*ca987d46SWarner Losh  skip_to_end_of_line
565*ca987d46SWarner Losh;
566*ca987d46SWarner Losh
567*ca987d46SWarner Losh: white_space_4
568*ca987d46SWarner Losh  eat_space
569*ca987d46SWarner Losh  comment? if ['] comment to parsing_function exit then
570*ca987d46SWarner Losh  end_of_line? 0= if ESYNTAX throw then
571*ca987d46SWarner Losh;
572*ca987d46SWarner Losh
573*ca987d46SWarner Losh: variable_value
574*ca987d46SWarner Losh  read_value
575*ca987d46SWarner Losh  ['] white_space_4 to parsing_function
576*ca987d46SWarner Losh;
577*ca987d46SWarner Losh
578*ca987d46SWarner Losh: white_space_3
579*ca987d46SWarner Losh  eat_space
580*ca987d46SWarner Losh  letter? digit? quote? or or if
581*ca987d46SWarner Losh    ['] variable_value to parsing_function exit
582*ca987d46SWarner Losh  then
583*ca987d46SWarner Losh  ESYNTAX throw
584*ca987d46SWarner Losh;
585*ca987d46SWarner Losh
586*ca987d46SWarner Losh: assignment_sign
587*ca987d46SWarner Losh  skip_character
588*ca987d46SWarner Losh  ['] white_space_3 to parsing_function
589*ca987d46SWarner Losh;
590*ca987d46SWarner Losh
591*ca987d46SWarner Losh: white_space_2
592*ca987d46SWarner Losh  eat_space
593*ca987d46SWarner Losh  assignment_sign? if ['] assignment_sign to parsing_function exit then
594*ca987d46SWarner Losh  ESYNTAX throw
595*ca987d46SWarner Losh;
596*ca987d46SWarner Losh
597*ca987d46SWarner Losh: variable_name
598*ca987d46SWarner Losh  read_name
599*ca987d46SWarner Losh  ['] white_space_2 to parsing_function
600*ca987d46SWarner Losh;
601*ca987d46SWarner Losh
602*ca987d46SWarner Losh: white_space_1
603*ca987d46SWarner Losh  eat_space
604*ca987d46SWarner Losh  letter?  if ['] variable_name to parsing_function exit then
605*ca987d46SWarner Losh  comment? if ['] comment to parsing_function exit then
606*ca987d46SWarner Losh  end_of_line? 0= if ESYNTAX throw then
607*ca987d46SWarner Losh;
608*ca987d46SWarner Losh
609*ca987d46SWarner Loshget-current ( -- wid ) previous definitions >search ( wid -- )
610*ca987d46SWarner Losh
611*ca987d46SWarner Losh: get_assignment
612*ca987d46SWarner Losh  line_buffer strget + to end_of_line
613*ca987d46SWarner Losh  line_buffer .addr @ to line_pointer
614*ca987d46SWarner Losh  ['] white_space_1 to parsing_function
615*ca987d46SWarner Losh  begin
616*ca987d46SWarner Losh    end_of_line? 0=
617*ca987d46SWarner Losh  while
618*ca987d46SWarner Losh    parsing_function execute
619*ca987d46SWarner Losh  repeat
620*ca987d46SWarner Losh  parsing_function ['] comment =
621*ca987d46SWarner Losh  parsing_function ['] white_space_1 =
622*ca987d46SWarner Losh  parsing_function ['] white_space_4 =
623*ca987d46SWarner Losh  or or 0= if ESYNTAX throw then
624*ca987d46SWarner Losh;
625*ca987d46SWarner Losh
626*ca987d46SWarner Loshonly forth also support-functions also file-processing definitions
627*ca987d46SWarner Losh
628*ca987d46SWarner Losh\ Process line
629*ca987d46SWarner Losh
630*ca987d46SWarner Losh: assignment_type?  ( addr len -- flag )
631*ca987d46SWarner Losh  name_buffer strget
632*ca987d46SWarner Losh  compare 0=
633*ca987d46SWarner Losh;
634*ca987d46SWarner Losh
635*ca987d46SWarner Losh: suffix_type?  ( addr len -- flag )
636*ca987d46SWarner Losh  name_buffer .len @ over <= if 2drop false exit then
637*ca987d46SWarner Losh  name_buffer .len @ over - name_buffer .addr @ +
638*ca987d46SWarner Losh  over compare 0=
639*ca987d46SWarner Losh;
640*ca987d46SWarner Losh
641*ca987d46SWarner Losh: loader_conf_files?  s" loader_conf_files" assignment_type?  ;
642*ca987d46SWarner Losh
643*ca987d46SWarner Losh: nextboot_flag?  s" nextboot_enable" assignment_type?  ;
644*ca987d46SWarner Losh
645*ca987d46SWarner Losh: nextboot_conf? s" nextboot_conf" assignment_type?  ;
646*ca987d46SWarner Losh
647*ca987d46SWarner Losh: verbose_flag? s" verbose_loading" assignment_type?  ;
648*ca987d46SWarner Losh
649*ca987d46SWarner Losh: execute? s" exec" assignment_type?  ;
650*ca987d46SWarner Losh
651*ca987d46SWarner Losh: module_load? load_module_suffix suffix_type? ;
652*ca987d46SWarner Losh
653*ca987d46SWarner Losh: module_loadname?  module_loadname_suffix suffix_type?  ;
654*ca987d46SWarner Losh
655*ca987d46SWarner Losh: module_type?  module_type_suffix suffix_type?  ;
656*ca987d46SWarner Losh
657*ca987d46SWarner Losh: module_args?  module_args_suffix suffix_type?  ;
658*ca987d46SWarner Losh
659*ca987d46SWarner Losh: module_beforeload?  module_beforeload_suffix suffix_type?  ;
660*ca987d46SWarner Losh
661*ca987d46SWarner Losh: module_afterload?  module_afterload_suffix suffix_type?  ;
662*ca987d46SWarner Losh
663*ca987d46SWarner Losh: module_loaderror?  module_loaderror_suffix suffix_type?  ;
664*ca987d46SWarner Losh
665*ca987d46SWarner Losh\ build a 'set' statement and execute it
666*ca987d46SWarner Losh: set_environment_variable
667*ca987d46SWarner Losh  name_buffer .len @ value_buffer .len @ + 5 chars + \ size of result string
668*ca987d46SWarner Losh  allocate if ENOMEM throw then
669*ca987d46SWarner Losh  dup 0  \ start with an empty string and append the pieces
670*ca987d46SWarner Losh  s" set " strcat
671*ca987d46SWarner Losh  name_buffer strget strcat
672*ca987d46SWarner Losh  s" =" strcat
673*ca987d46SWarner Losh  value_buffer strget strcat
674*ca987d46SWarner Losh  ['] evaluate catch if
675*ca987d46SWarner Losh    2drop free drop
676*ca987d46SWarner Losh    ESETERROR throw
677*ca987d46SWarner Losh  else
678*ca987d46SWarner Losh    free-memory
679*ca987d46SWarner Losh  then
680*ca987d46SWarner Losh;
681*ca987d46SWarner Losh
682*ca987d46SWarner Losh: set_conf_files
683*ca987d46SWarner Losh  set_environment_variable
684*ca987d46SWarner Losh  s" loader_conf_files" getenv conf_files string=
685*ca987d46SWarner Losh;
686*ca987d46SWarner Losh
687*ca987d46SWarner Losh: set_nextboot_conf
688*ca987d46SWarner Losh  value_buffer strget unquote nextboot_conf_file string=
689*ca987d46SWarner Losh;
690*ca987d46SWarner Losh
691*ca987d46SWarner Losh: append_to_module_options_list  ( addr -- )
692*ca987d46SWarner Losh  module_options @ 0= if
693*ca987d46SWarner Losh    dup module_options !
694*ca987d46SWarner Losh    last_module_option !
695*ca987d46SWarner Losh  else
696*ca987d46SWarner Losh    dup last_module_option @ module.next !
697*ca987d46SWarner Losh    last_module_option !
698*ca987d46SWarner Losh  then
699*ca987d46SWarner Losh;
700*ca987d46SWarner Losh
701*ca987d46SWarner Losh: set_module_name  { addr -- }	\ check leaks
702*ca987d46SWarner Losh  name_buffer strget addr module.name string=
703*ca987d46SWarner Losh;
704*ca987d46SWarner Losh
705*ca987d46SWarner Losh: yes_value?
706*ca987d46SWarner Losh  value_buffer strget	\ XXX could use unquote
707*ca987d46SWarner Losh  2dup s' "YES"' compare >r
708*ca987d46SWarner Losh  2dup s' "yes"' compare >r
709*ca987d46SWarner Losh  2dup s" YES" compare >r
710*ca987d46SWarner Losh  s" yes" compare r> r> r> and and and 0=
711*ca987d46SWarner Losh;
712*ca987d46SWarner Losh
713*ca987d46SWarner Losh: find_module_option  ( -- addr | 0 ) \ return ptr to entry matching name_buffer
714*ca987d46SWarner Losh  module_options @
715*ca987d46SWarner Losh  begin
716*ca987d46SWarner Losh    dup
717*ca987d46SWarner Losh  while
718*ca987d46SWarner Losh    dup module.name strget
719*ca987d46SWarner Losh    name_buffer strget
720*ca987d46SWarner Losh    compare 0= if exit then
721*ca987d46SWarner Losh    module.next @
722*ca987d46SWarner Losh  repeat
723*ca987d46SWarner Losh;
724*ca987d46SWarner Losh
725*ca987d46SWarner Losh: new_module_option  ( -- addr )
726*ca987d46SWarner Losh  sizeof module allocate if ENOMEM throw then
727*ca987d46SWarner Losh  dup sizeof module erase
728*ca987d46SWarner Losh  dup append_to_module_options_list
729*ca987d46SWarner Losh  dup set_module_name
730*ca987d46SWarner Losh;
731*ca987d46SWarner Losh
732*ca987d46SWarner Losh: get_module_option  ( -- addr )
733*ca987d46SWarner Losh  find_module_option
734*ca987d46SWarner Losh  ?dup 0= if new_module_option then
735*ca987d46SWarner Losh;
736*ca987d46SWarner Losh
737*ca987d46SWarner Losh: set_module_flag
738*ca987d46SWarner Losh  name_buffer .len @ load_module_suffix nip - name_buffer .len !
739*ca987d46SWarner Losh  yes_value? get_module_option module.flag !
740*ca987d46SWarner Losh;
741*ca987d46SWarner Losh
742*ca987d46SWarner Losh: set_module_args
743*ca987d46SWarner Losh  name_buffer .len @ module_args_suffix nip - name_buffer .len !
744*ca987d46SWarner Losh  value_buffer strget unquote
745*ca987d46SWarner Losh  get_module_option module.args string=
746*ca987d46SWarner Losh;
747*ca987d46SWarner Losh
748*ca987d46SWarner Losh: set_module_loadname
749*ca987d46SWarner Losh  name_buffer .len @ module_loadname_suffix nip - name_buffer .len !
750*ca987d46SWarner Losh  value_buffer strget unquote
751*ca987d46SWarner Losh  get_module_option module.loadname string=
752*ca987d46SWarner Losh;
753*ca987d46SWarner Losh
754*ca987d46SWarner Losh: set_module_type
755*ca987d46SWarner Losh  name_buffer .len @ module_type_suffix nip - name_buffer .len !
756*ca987d46SWarner Losh  value_buffer strget unquote
757*ca987d46SWarner Losh  get_module_option module.type string=
758*ca987d46SWarner Losh;
759*ca987d46SWarner Losh
760*ca987d46SWarner Losh: set_module_beforeload
761*ca987d46SWarner Losh  name_buffer .len @ module_beforeload_suffix nip - name_buffer .len !
762*ca987d46SWarner Losh  value_buffer strget unquote
763*ca987d46SWarner Losh  get_module_option module.beforeload string=
764*ca987d46SWarner Losh;
765*ca987d46SWarner Losh
766*ca987d46SWarner Losh: set_module_afterload
767*ca987d46SWarner Losh  name_buffer .len @ module_afterload_suffix nip - name_buffer .len !
768*ca987d46SWarner Losh  value_buffer strget unquote
769*ca987d46SWarner Losh  get_module_option module.afterload string=
770*ca987d46SWarner Losh;
771*ca987d46SWarner Losh
772*ca987d46SWarner Losh: set_module_loaderror
773*ca987d46SWarner Losh  name_buffer .len @ module_loaderror_suffix nip - name_buffer .len !
774*ca987d46SWarner Losh  value_buffer strget unquote
775*ca987d46SWarner Losh  get_module_option module.loaderror string=
776*ca987d46SWarner Losh;
777*ca987d46SWarner Losh
778*ca987d46SWarner Losh: set_nextboot_flag
779*ca987d46SWarner Losh  yes_value? to nextboot?
780*ca987d46SWarner Losh;
781*ca987d46SWarner Losh
782*ca987d46SWarner Losh: set_verbose
783*ca987d46SWarner Losh  yes_value? to verbose?
784*ca987d46SWarner Losh;
785*ca987d46SWarner Losh
786*ca987d46SWarner Losh: execute_command
787*ca987d46SWarner Losh  value_buffer strget unquote
788*ca987d46SWarner Losh  ['] evaluate catch if EEXEC throw then
789*ca987d46SWarner Losh;
790*ca987d46SWarner Losh
791*ca987d46SWarner Losh: process_assignment
792*ca987d46SWarner Losh  name_buffer .len @ 0= if exit then
793*ca987d46SWarner Losh  loader_conf_files?	if set_conf_files exit then
794*ca987d46SWarner Losh  nextboot_flag?	if set_nextboot_flag exit then
795*ca987d46SWarner Losh  nextboot_conf?	if set_nextboot_conf exit then
796*ca987d46SWarner Losh  verbose_flag?		if set_verbose exit then
797*ca987d46SWarner Losh  execute?		if execute_command exit then
798*ca987d46SWarner Losh  module_load?		if set_module_flag exit then
799*ca987d46SWarner Losh  module_loadname?	if set_module_loadname exit then
800*ca987d46SWarner Losh  module_type?		if set_module_type exit then
801*ca987d46SWarner Losh  module_args?		if set_module_args exit then
802*ca987d46SWarner Losh  module_beforeload?	if set_module_beforeload exit then
803*ca987d46SWarner Losh  module_afterload?	if set_module_afterload exit then
804*ca987d46SWarner Losh  module_loaderror?	if set_module_loaderror exit then
805*ca987d46SWarner Losh  set_environment_variable
806*ca987d46SWarner Losh;
807*ca987d46SWarner Losh
808*ca987d46SWarner Losh\ free_buffer  ( -- )
809*ca987d46SWarner Losh\
810*ca987d46SWarner Losh\ Free some pointers if needed. The code then tests for errors
811*ca987d46SWarner Losh\ in freeing, and throws an exception if needed. If a pointer is
812*ca987d46SWarner Losh\ not allocated, it's value (0) is used as flag.
813*ca987d46SWarner Losh
814*ca987d46SWarner Losh: free_buffers
815*ca987d46SWarner Losh  name_buffer strfree
816*ca987d46SWarner Losh  value_buffer strfree
817*ca987d46SWarner Losh;
818*ca987d46SWarner Losh
819*ca987d46SWarner Losh\ Higher level file processing
820*ca987d46SWarner Losh
821*ca987d46SWarner Loshget-current ( -- wid ) previous definitions >search ( wid -- )
822*ca987d46SWarner Losh
823*ca987d46SWarner Losh: process_conf
824*ca987d46SWarner Losh  begin
825*ca987d46SWarner Losh    end_of_file? 0=
826*ca987d46SWarner Losh  while
827*ca987d46SWarner Losh    free_buffers
828*ca987d46SWarner Losh    read_line
829*ca987d46SWarner Losh    get_assignment
830*ca987d46SWarner Losh    ['] process_assignment catch
831*ca987d46SWarner Losh    ['] free_buffers catch
832*ca987d46SWarner Losh    swap throw throw
833*ca987d46SWarner Losh  repeat
834*ca987d46SWarner Losh;
835*ca987d46SWarner Losh
836*ca987d46SWarner Losh: peek_file ( addr len -- )
837*ca987d46SWarner Losh  0 to end_of_file?
838*ca987d46SWarner Losh  reset_line_reading
839*ca987d46SWarner Losh  O_RDONLY fopen fd !
840*ca987d46SWarner Losh  fd @ -1 = if EOPEN throw then
841*ca987d46SWarner Losh  free_buffers
842*ca987d46SWarner Losh  read_line
843*ca987d46SWarner Losh  get_assignment
844*ca987d46SWarner Losh  ['] process_assignment catch
845*ca987d46SWarner Losh  ['] free_buffers catch
846*ca987d46SWarner Losh  fd @ fclose
847*ca987d46SWarner Losh  swap throw throw
848*ca987d46SWarner Losh;
849*ca987d46SWarner Losh
850*ca987d46SWarner Loshonly forth also support-functions definitions
851*ca987d46SWarner Losh
852*ca987d46SWarner Losh\ Interface to loading conf files
853*ca987d46SWarner Losh
854*ca987d46SWarner Losh: load_conf  ( addr len -- )
855*ca987d46SWarner Losh  0 to end_of_file?
856*ca987d46SWarner Losh  reset_line_reading
857*ca987d46SWarner Losh  O_RDONLY fopen fd !
858*ca987d46SWarner Losh  fd @ -1 = if EOPEN throw then
859*ca987d46SWarner Losh  ['] process_conf catch
860*ca987d46SWarner Losh  fd @ fclose
861*ca987d46SWarner Losh  throw
862*ca987d46SWarner Losh;
863*ca987d46SWarner Losh
864*ca987d46SWarner Losh: print_line line_buffer strtype cr ;
865*ca987d46SWarner Losh
866*ca987d46SWarner Losh: print_syntax_error
867*ca987d46SWarner Losh  line_buffer strtype cr
868*ca987d46SWarner Losh  line_buffer .addr @
869*ca987d46SWarner Losh  begin
870*ca987d46SWarner Losh    line_pointer over <>
871*ca987d46SWarner Losh  while
872*ca987d46SWarner Losh    bl emit char+
873*ca987d46SWarner Losh  repeat
874*ca987d46SWarner Losh  drop
875*ca987d46SWarner Losh  ." ^" cr
876*ca987d46SWarner Losh;
877*ca987d46SWarner Losh
878*ca987d46SWarner Losh
879*ca987d46SWarner Losh\ Debugging support functions
880*ca987d46SWarner Losh
881*ca987d46SWarner Loshonly forth definitions also support-functions
882*ca987d46SWarner Losh
883*ca987d46SWarner Losh: test-file
884*ca987d46SWarner Losh  ['] load_conf catch dup .
885*ca987d46SWarner Losh  ESYNTAX = if cr print_syntax_error then
886*ca987d46SWarner Losh;
887*ca987d46SWarner Losh
888*ca987d46SWarner Losh\ find a module name, leave addr on the stack (0 if not found)
889*ca987d46SWarner Losh: find-module ( <module> -- ptr | 0 )
890*ca987d46SWarner Losh  bl parse ( addr len )
891*ca987d46SWarner Losh  module_options @ >r ( store current pointer )
892*ca987d46SWarner Losh  begin
893*ca987d46SWarner Losh    r@
894*ca987d46SWarner Losh  while
895*ca987d46SWarner Losh    2dup ( addr len addr len )
896*ca987d46SWarner Losh    r@ module.name strget
897*ca987d46SWarner Losh    compare 0= if drop drop r> exit then ( found it )
898*ca987d46SWarner Losh    r> module.next @ >r
899*ca987d46SWarner Losh  repeat
900*ca987d46SWarner Losh  type ."  was not found" cr r>
901*ca987d46SWarner Losh;
902*ca987d46SWarner Losh
903*ca987d46SWarner Losh: show-nonempty ( addr len mod -- )
904*ca987d46SWarner Losh  strget dup verbose? or if
905*ca987d46SWarner Losh    2swap type type cr
906*ca987d46SWarner Losh  else
907*ca987d46SWarner Losh    drop drop drop drop
908*ca987d46SWarner Losh  then ;
909*ca987d46SWarner Losh
910*ca987d46SWarner Losh: show-one-module { addr -- addr }
911*ca987d46SWarner Losh  ." Name:        " addr module.name strtype cr
912*ca987d46SWarner Losh  s" Path:        " addr module.loadname show-nonempty
913*ca987d46SWarner Losh  s" Type:        " addr module.type show-nonempty
914*ca987d46SWarner Losh  s" Flags:       " addr module.args show-nonempty
915*ca987d46SWarner Losh  s" Before load: " addr module.beforeload show-nonempty
916*ca987d46SWarner Losh  s" After load:  " addr module.afterload show-nonempty
917*ca987d46SWarner Losh  s" Error:       " addr module.loaderror show-nonempty
918*ca987d46SWarner Losh  ." Status:      " addr module.flag @ if ." Load" else ." Don't load" then cr
919*ca987d46SWarner Losh  cr
920*ca987d46SWarner Losh  addr
921*ca987d46SWarner Losh;
922*ca987d46SWarner Losh
923*ca987d46SWarner Losh: show-module-options
924*ca987d46SWarner Losh  module_options @
925*ca987d46SWarner Losh  begin
926*ca987d46SWarner Losh    ?dup
927*ca987d46SWarner Losh  while
928*ca987d46SWarner Losh    show-one-module
929*ca987d46SWarner Losh    module.next @
930*ca987d46SWarner Losh  repeat
931*ca987d46SWarner Losh;
932*ca987d46SWarner Losh
933*ca987d46SWarner Losh: free-one-module { addr -- addr }
934*ca987d46SWarner Losh  addr module.name strfree
935*ca987d46SWarner Losh  addr module.loadname strfree
936*ca987d46SWarner Losh  addr module.type strfree
937*ca987d46SWarner Losh  addr module.args strfree
938*ca987d46SWarner Losh  addr module.beforeload strfree
939*ca987d46SWarner Losh  addr module.afterload strfree
940*ca987d46SWarner Losh  addr module.loaderror strfree
941*ca987d46SWarner Losh  addr
942*ca987d46SWarner Losh;
943*ca987d46SWarner Losh
944*ca987d46SWarner Losh: free-module-options
945*ca987d46SWarner Losh  module_options @
946*ca987d46SWarner Losh  begin
947*ca987d46SWarner Losh    ?dup
948*ca987d46SWarner Losh  while
949*ca987d46SWarner Losh    free-one-module
950*ca987d46SWarner Losh    dup module.next @
951*ca987d46SWarner Losh    swap free-memory
952*ca987d46SWarner Losh  repeat
953*ca987d46SWarner Losh  0 module_options !
954*ca987d46SWarner Losh  0 last_module_option !
955*ca987d46SWarner Losh;
956*ca987d46SWarner Losh
957*ca987d46SWarner Loshonly forth also support-functions definitions
958*ca987d46SWarner Losh
959*ca987d46SWarner Losh\ Variables used for processing multiple conf files
960*ca987d46SWarner Losh
961*ca987d46SWarner Loshstring current_file_name_ref	\ used to print the file name
962*ca987d46SWarner Losh
963*ca987d46SWarner Losh\ Indicates if any conf file was successfully read
964*ca987d46SWarner Losh
965*ca987d46SWarner Losh0 value any_conf_read?
966*ca987d46SWarner Losh
967*ca987d46SWarner Losh\ loader_conf_files processing support functions
968*ca987d46SWarner Losh
969*ca987d46SWarner Losh: get_conf_files ( -- addr len )  \ put addr/len on stack, reset var
970*ca987d46SWarner Losh  conf_files strget 0 0 conf_files strset
971*ca987d46SWarner Losh;
972*ca987d46SWarner Losh
973*ca987d46SWarner Losh: skip_leading_spaces  { addr len pos -- addr len pos' }
974*ca987d46SWarner Losh  begin
975*ca987d46SWarner Losh    pos len = if 0 else addr pos + c@ bl = then
976*ca987d46SWarner Losh  while
977*ca987d46SWarner Losh    pos char+ to pos
978*ca987d46SWarner Losh  repeat
979*ca987d46SWarner Losh  addr len pos
980*ca987d46SWarner Losh;
981*ca987d46SWarner Losh
982*ca987d46SWarner Losh\ return the file name at pos, or free the string if nothing left
983*ca987d46SWarner Losh: get_file_name  { addr len pos -- addr len pos' addr' len' || 0 }
984*ca987d46SWarner Losh  pos len = if
985*ca987d46SWarner Losh    addr free abort" Fatal error freeing memory"
986*ca987d46SWarner Losh    0 exit
987*ca987d46SWarner Losh  then
988*ca987d46SWarner Losh  pos >r
989*ca987d46SWarner Losh  begin
990*ca987d46SWarner Losh    \ stay in the loop until have chars and they are not blank
991*ca987d46SWarner Losh    pos len = if 0 else addr pos + c@ bl <> then
992*ca987d46SWarner Losh  while
993*ca987d46SWarner Losh    pos char+ to pos
994*ca987d46SWarner Losh  repeat
995*ca987d46SWarner Losh  addr len pos addr r@ + pos r> -
996*ca987d46SWarner Losh;
997*ca987d46SWarner Losh
998*ca987d46SWarner Losh: get_next_file  ( addr len ptr -- addr len ptr' addr' len' | 0 )
999*ca987d46SWarner Losh  skip_leading_spaces
1000*ca987d46SWarner Losh  get_file_name
1001*ca987d46SWarner Losh;
1002*ca987d46SWarner Losh
1003*ca987d46SWarner Losh: print_current_file
1004*ca987d46SWarner Losh  current_file_name_ref strtype
1005*ca987d46SWarner Losh;
1006*ca987d46SWarner Losh
1007*ca987d46SWarner Losh: process_conf_errors
1008*ca987d46SWarner Losh  dup 0= if true to any_conf_read? drop exit then
1009*ca987d46SWarner Losh  >r 2drop r>
1010*ca987d46SWarner Losh  dup ESYNTAX = if
1011*ca987d46SWarner Losh    ." Warning: syntax error on file " print_current_file cr
1012*ca987d46SWarner Losh    print_syntax_error drop exit
1013*ca987d46SWarner Losh  then
1014*ca987d46SWarner Losh  dup ESETERROR = if
1015*ca987d46SWarner Losh    ." Warning: bad definition on file " print_current_file cr
1016*ca987d46SWarner Losh    print_line drop exit
1017*ca987d46SWarner Losh  then
1018*ca987d46SWarner Losh  dup EREAD = if
1019*ca987d46SWarner Losh    ." Warning: error reading file " print_current_file cr drop exit
1020*ca987d46SWarner Losh  then
1021*ca987d46SWarner Losh  dup EOPEN = if
1022*ca987d46SWarner Losh    verbose? if ." Warning: unable to open file " print_current_file cr then
1023*ca987d46SWarner Losh    drop exit
1024*ca987d46SWarner Losh  then
1025*ca987d46SWarner Losh  dup EFREE = abort" Fatal error freeing memory"
1026*ca987d46SWarner Losh  dup ENOMEM = abort" Out of memory"
1027*ca987d46SWarner Losh  throw  \ Unknown error -- pass ahead
1028*ca987d46SWarner Losh;
1029*ca987d46SWarner Losh
1030*ca987d46SWarner Losh\ Process loader_conf_files recursively
1031*ca987d46SWarner Losh\ Interface to loader_conf_files processing
1032*ca987d46SWarner Losh
1033*ca987d46SWarner Losh: include_conf_files
1034*ca987d46SWarner Losh  get_conf_files 0	( addr len offset )
1035*ca987d46SWarner Losh  begin
1036*ca987d46SWarner Losh    get_next_file ?dup ( addr len 1 | 0 )
1037*ca987d46SWarner Losh  while
1038*ca987d46SWarner Losh    current_file_name_ref strref
1039*ca987d46SWarner Losh    ['] load_conf catch
1040*ca987d46SWarner Losh    process_conf_errors
1041*ca987d46SWarner Losh    conf_files .addr @ if recurse then
1042*ca987d46SWarner Losh  repeat
1043*ca987d46SWarner Losh;
1044*ca987d46SWarner Losh
1045*ca987d46SWarner Losh: get_nextboot_conf_file ( -- addr len )
1046*ca987d46SWarner Losh  nextboot_conf_file strget
1047*ca987d46SWarner Losh;
1048*ca987d46SWarner Losh
1049*ca987d46SWarner Losh: rewrite_nextboot_file ( -- )
1050*ca987d46SWarner Losh  get_nextboot_conf_file
1051*ca987d46SWarner Losh  O_WRONLY fopen fd !
1052*ca987d46SWarner Losh  fd @ -1 = if EOPEN throw then
1053*ca987d46SWarner Losh  fd @ s' nextboot_enable="NO" ' fwrite ( fd buf len -- nwritten ) drop
1054*ca987d46SWarner Losh  fd @ fclose
1055*ca987d46SWarner Losh;
1056*ca987d46SWarner Losh
1057*ca987d46SWarner Losh: include_nextboot_file ( -- )
1058*ca987d46SWarner Losh  get_nextboot_conf_file
1059*ca987d46SWarner Losh  ['] peek_file catch if 2drop then
1060*ca987d46SWarner Losh  nextboot? if
1061*ca987d46SWarner Losh    get_nextboot_conf_file
1062*ca987d46SWarner Losh    current_file_name_ref strref
1063*ca987d46SWarner Losh    ['] load_conf catch
1064*ca987d46SWarner Losh    process_conf_errors
1065*ca987d46SWarner Losh    ['] rewrite_nextboot_file catch if 2drop then
1066*ca987d46SWarner Losh  then
1067*ca987d46SWarner Losh;
1068*ca987d46SWarner Losh
1069*ca987d46SWarner Losh\ Module loading functions
1070*ca987d46SWarner Losh
1071*ca987d46SWarner Losh: load_parameters  { addr -- addr addrN lenN ... addr1 len1 N }
1072*ca987d46SWarner Losh  addr
1073*ca987d46SWarner Losh  addr module.args strget
1074*ca987d46SWarner Losh  addr module.loadname .len @ if
1075*ca987d46SWarner Losh    addr module.loadname strget
1076*ca987d46SWarner Losh  else
1077*ca987d46SWarner Losh    addr module.name strget
1078*ca987d46SWarner Losh  then
1079*ca987d46SWarner Losh  addr module.type .len @ if
1080*ca987d46SWarner Losh    addr module.type strget
1081*ca987d46SWarner Losh    s" -t "
1082*ca987d46SWarner Losh    4 ( -t type name flags )
1083*ca987d46SWarner Losh  else
1084*ca987d46SWarner Losh    2 ( name flags )
1085*ca987d46SWarner Losh  then
1086*ca987d46SWarner Losh;
1087*ca987d46SWarner Losh
1088*ca987d46SWarner Losh: before_load  ( addr -- addr )
1089*ca987d46SWarner Losh  dup module.beforeload .len @ if
1090*ca987d46SWarner Losh    dup module.beforeload strget
1091*ca987d46SWarner Losh    ['] evaluate catch if EBEFORELOAD throw then
1092*ca987d46SWarner Losh  then
1093*ca987d46SWarner Losh;
1094*ca987d46SWarner Losh
1095*ca987d46SWarner Losh: after_load  ( addr -- addr )
1096*ca987d46SWarner Losh  dup module.afterload .len @ if
1097*ca987d46SWarner Losh    dup module.afterload strget
1098*ca987d46SWarner Losh    ['] evaluate catch if EAFTERLOAD throw then
1099*ca987d46SWarner Losh  then
1100*ca987d46SWarner Losh;
1101*ca987d46SWarner Losh
1102*ca987d46SWarner Losh: load_error  ( addr -- addr )
1103*ca987d46SWarner Losh  dup module.loaderror .len @ if
1104*ca987d46SWarner Losh    dup module.loaderror strget
1105*ca987d46SWarner Losh    evaluate  \ This we do not intercept so it can throw errors
1106*ca987d46SWarner Losh  then
1107*ca987d46SWarner Losh;
1108*ca987d46SWarner Losh
1109*ca987d46SWarner Losh: pre_load_message  ( addr -- addr )
1110*ca987d46SWarner Losh  verbose? if
1111*ca987d46SWarner Losh    dup module.name strtype
1112*ca987d46SWarner Losh    ." ..."
1113*ca987d46SWarner Losh  then
1114*ca987d46SWarner Losh;
1115*ca987d46SWarner Losh
1116*ca987d46SWarner Losh: load_error_message verbose? if ." failed!" cr then ;
1117*ca987d46SWarner Losh
1118*ca987d46SWarner Losh: load_successful_message verbose? if ." ok" cr then ;
1119*ca987d46SWarner Losh
1120*ca987d46SWarner Losh: load_module
1121*ca987d46SWarner Losh  load_parameters load
1122*ca987d46SWarner Losh;
1123*ca987d46SWarner Losh
1124*ca987d46SWarner Losh: process_module  ( addr -- addr )
1125*ca987d46SWarner Losh  pre_load_message
1126*ca987d46SWarner Losh  before_load
1127*ca987d46SWarner Losh  begin
1128*ca987d46SWarner Losh    ['] load_module catch if
1129*ca987d46SWarner Losh      dup module.loaderror .len @ if
1130*ca987d46SWarner Losh        load_error			\ Command should return a flag!
1131*ca987d46SWarner Losh      else
1132*ca987d46SWarner Losh        load_error_message true		\ Do not retry
1133*ca987d46SWarner Losh      then
1134*ca987d46SWarner Losh    else
1135*ca987d46SWarner Losh      after_load
1136*ca987d46SWarner Losh      load_successful_message true	\ Successful, do not retry
1137*ca987d46SWarner Losh    then
1138*ca987d46SWarner Losh  until
1139*ca987d46SWarner Losh;
1140*ca987d46SWarner Losh
1141*ca987d46SWarner Losh: process_module_errors  ( addr ior -- )
1142*ca987d46SWarner Losh  dup EBEFORELOAD = if
1143*ca987d46SWarner Losh    drop
1144*ca987d46SWarner Losh    ." Module "
1145*ca987d46SWarner Losh    dup module.name strtype
1146*ca987d46SWarner Losh    dup module.loadname .len @ if
1147*ca987d46SWarner Losh      ." (" dup module.loadname strtype ." )"
1148*ca987d46SWarner Losh    then
1149*ca987d46SWarner Losh    cr
1150*ca987d46SWarner Losh    ." Error executing "
1151*ca987d46SWarner Losh    dup module.beforeload strtype cr	\ XXX there was a typo here
1152*ca987d46SWarner Losh    abort
1153*ca987d46SWarner Losh  then
1154*ca987d46SWarner Losh
1155*ca987d46SWarner Losh  dup EAFTERLOAD = if
1156*ca987d46SWarner Losh    drop
1157*ca987d46SWarner Losh    ." Module "
1158*ca987d46SWarner Losh    dup module.name .addr @ over module.name .len @ type
1159*ca987d46SWarner Losh    dup module.loadname .len @ if
1160*ca987d46SWarner Losh      ." (" dup module.loadname strtype ." )"
1161*ca987d46SWarner Losh    then
1162*ca987d46SWarner Losh    cr
1163*ca987d46SWarner Losh    ." Error executing "
1164*ca987d46SWarner Losh    dup module.afterload strtype cr
1165*ca987d46SWarner Losh    abort
1166*ca987d46SWarner Losh  then
1167*ca987d46SWarner Losh
1168*ca987d46SWarner Losh  throw  \ Don't know what it is all about -- pass ahead
1169*ca987d46SWarner Losh;
1170*ca987d46SWarner Losh
1171*ca987d46SWarner Losh\ Module loading interface
1172*ca987d46SWarner Losh
1173*ca987d46SWarner Losh\ scan the list of modules, load enabled ones.
1174*ca987d46SWarner Losh: load_modules  ( -- ) ( throws: abort & user-defined )
1175*ca987d46SWarner Losh  module_options @	( list_head )
1176*ca987d46SWarner Losh  begin
1177*ca987d46SWarner Losh    ?dup
1178*ca987d46SWarner Losh  while
1179*ca987d46SWarner Losh    dup module.flag @ if
1180*ca987d46SWarner Losh      ['] process_module catch
1181*ca987d46SWarner Losh      process_module_errors
1182*ca987d46SWarner Losh    then
1183*ca987d46SWarner Losh    module.next @
1184*ca987d46SWarner Losh  repeat
1185*ca987d46SWarner Losh;
1186*ca987d46SWarner Losh
1187*ca987d46SWarner Losh\ h00h00 magic used to try loading either a kernel with a given name,
1188*ca987d46SWarner Losh\ or a kernel with the default name in a directory of a given name
1189*ca987d46SWarner Losh\ (the pain!)
1190*ca987d46SWarner Losh
1191*ca987d46SWarner Losh: bootpath s" /boot/" ;
1192*ca987d46SWarner Losh: modulepath s" module_path" ;
1193*ca987d46SWarner Losh
1194*ca987d46SWarner Losh\ Functions used to save and restore module_path's value.
1195*ca987d46SWarner Losh: saveenv ( addr len | -1 -- addr' len | 0 -1 )
1196*ca987d46SWarner Losh  dup -1 = if 0 swap exit then
1197*ca987d46SWarner Losh  strdup
1198*ca987d46SWarner Losh;
1199*ca987d46SWarner Losh: freeenv ( addr len | 0 -1 )
1200*ca987d46SWarner Losh  -1 = if drop else free abort" Freeing error" then
1201*ca987d46SWarner Losh;
1202*ca987d46SWarner Losh: restoreenv  ( addr len | 0 -1 -- )
1203*ca987d46SWarner Losh  dup -1 = if ( it wasn't set )
1204*ca987d46SWarner Losh    2drop
1205*ca987d46SWarner Losh    modulepath unsetenv
1206*ca987d46SWarner Losh  else
1207*ca987d46SWarner Losh    over >r
1208*ca987d46SWarner Losh    modulepath setenv
1209*ca987d46SWarner Losh    r> free abort" Freeing error"
1210*ca987d46SWarner Losh  then
1211*ca987d46SWarner Losh;
1212*ca987d46SWarner Losh
1213*ca987d46SWarner Losh: clip_args   \ Drop second string if only one argument is passed
1214*ca987d46SWarner Losh  1 = if
1215*ca987d46SWarner Losh    2swap 2drop
1216*ca987d46SWarner Losh    1
1217*ca987d46SWarner Losh  else
1218*ca987d46SWarner Losh    2
1219*ca987d46SWarner Losh  then
1220*ca987d46SWarner Losh;
1221*ca987d46SWarner Losh
1222*ca987d46SWarner Loshalso builtins
1223*ca987d46SWarner Losh
1224*ca987d46SWarner Losh\ Parse filename from a semicolon-separated list
1225*ca987d46SWarner Losh
1226*ca987d46SWarner Losh\ replacement, not working yet
1227*ca987d46SWarner Losh: newparse-; { addr len | a1 -- a' len-x addr x }
1228*ca987d46SWarner Losh  addr len [char] ; strchr dup if	( a1 len1 )
1229*ca987d46SWarner Losh    swap to a1	( store address )
1230*ca987d46SWarner Losh    1 - a1 @ 1 + swap ( remove match )
1231*ca987d46SWarner Losh    addr a1 addr -
1232*ca987d46SWarner Losh  else
1233*ca987d46SWarner Losh    0 0 addr len
1234*ca987d46SWarner Losh  then
1235*ca987d46SWarner Losh;
1236*ca987d46SWarner Losh
1237*ca987d46SWarner Losh: parse-; ( addr len -- addr' len-x addr x )
1238*ca987d46SWarner Losh  over 0 2swap			( addr 0 addr len )
1239*ca987d46SWarner Losh  begin
1240*ca987d46SWarner Losh    dup 0 <>			( addr 0 addr len )
1241*ca987d46SWarner Losh  while
1242*ca987d46SWarner Losh    over c@ [char] ; <>		( addr 0 addr len flag )
1243*ca987d46SWarner Losh  while
1244*ca987d46SWarner Losh    1- swap 1+ swap
1245*ca987d46SWarner Losh    2swap 1+ 2swap
1246*ca987d46SWarner Losh  repeat then
1247*ca987d46SWarner Losh  dup 0 <> if
1248*ca987d46SWarner Losh    1- swap 1+ swap
1249*ca987d46SWarner Losh  then
1250*ca987d46SWarner Losh  2swap
1251*ca987d46SWarner Losh;
1252*ca987d46SWarner Losh
1253*ca987d46SWarner Losh\ Try loading one of multiple kernels specified
1254*ca987d46SWarner Losh
1255*ca987d46SWarner Losh: try_multiple_kernels ( addr len addr' len' args -- flag )
1256*ca987d46SWarner Losh  >r
1257*ca987d46SWarner Losh  begin
1258*ca987d46SWarner Losh    parse-; 2>r
1259*ca987d46SWarner Losh    2over 2r>
1260*ca987d46SWarner Losh    r@ clip_args
1261*ca987d46SWarner Losh    s" DEBUG" getenv? if
1262*ca987d46SWarner Losh      s" echo Module_path: ${module_path}" evaluate
1263*ca987d46SWarner Losh      ." Kernel     : " >r 2dup type r> cr
1264*ca987d46SWarner Losh      dup 2 = if ." Flags      : " >r 2over type r> cr then
1265*ca987d46SWarner Losh    then
1266*ca987d46SWarner Losh    1 load
1267*ca987d46SWarner Losh  while
1268*ca987d46SWarner Losh    dup 0=
1269*ca987d46SWarner Losh  until
1270*ca987d46SWarner Losh    1 >r \ Failure
1271*ca987d46SWarner Losh  else
1272*ca987d46SWarner Losh    0 >r \ Success
1273*ca987d46SWarner Losh  then
1274*ca987d46SWarner Losh  2drop 2drop
1275*ca987d46SWarner Losh  r>
1276*ca987d46SWarner Losh  r> drop
1277*ca987d46SWarner Losh;
1278*ca987d46SWarner Losh
1279*ca987d46SWarner Losh\ Try to load a kernel; the kernel name is taken from one of
1280*ca987d46SWarner Losh\ the following lists, as ordered:
1281*ca987d46SWarner Losh\
1282*ca987d46SWarner Losh\   1. The "bootfile" environment variable
1283*ca987d46SWarner Losh\   2. The "kernel" environment variable
1284*ca987d46SWarner Losh\
1285*ca987d46SWarner Losh\ Flags are passed, if available. If not, dummy values must be given.
1286*ca987d46SWarner Losh\
1287*ca987d46SWarner Losh\ The kernel gets loaded from the current module_path.
1288*ca987d46SWarner Losh
1289*ca987d46SWarner Losh: load_a_kernel ( flags len 1 | x x 0 -- flag )
1290*ca987d46SWarner Losh  local args
1291*ca987d46SWarner Losh  2local flags
1292*ca987d46SWarner Losh  0 0 2local kernel
1293*ca987d46SWarner Losh  end-locals
1294*ca987d46SWarner Losh
1295*ca987d46SWarner Losh  \ Check if a default kernel name exists at all, exits if not
1296*ca987d46SWarner Losh  s" bootfile" getenv dup -1 <> if
1297*ca987d46SWarner Losh    to kernel
1298*ca987d46SWarner Losh    flags kernel args 1+ try_multiple_kernels
1299*ca987d46SWarner Losh    dup 0= if exit then
1300*ca987d46SWarner Losh  then
1301*ca987d46SWarner Losh  drop
1302*ca987d46SWarner Losh
1303*ca987d46SWarner Losh  s" kernel" getenv dup -1 <> if
1304*ca987d46SWarner Losh    to kernel
1305*ca987d46SWarner Losh  else
1306*ca987d46SWarner Losh    drop
1307*ca987d46SWarner Losh    1 exit \ Failure
1308*ca987d46SWarner Losh  then
1309*ca987d46SWarner Losh
1310*ca987d46SWarner Losh  \ Try all default kernel names
1311*ca987d46SWarner Losh  flags kernel args 1+ try_multiple_kernels
1312*ca987d46SWarner Losh;
1313*ca987d46SWarner Losh
1314*ca987d46SWarner Losh\ Try to load a kernel; the kernel name is taken from one of
1315*ca987d46SWarner Losh\ the following lists, as ordered:
1316*ca987d46SWarner Losh\
1317*ca987d46SWarner Losh\   1. The "bootfile" environment variable
1318*ca987d46SWarner Losh\   2. The "kernel" environment variable
1319*ca987d46SWarner Losh\
1320*ca987d46SWarner Losh\ Flags are passed, if provided.
1321*ca987d46SWarner Losh\
1322*ca987d46SWarner Losh\ The kernel will be loaded from a directory computed from the
1323*ca987d46SWarner Losh\ path given. Two directories will be tried in the following order:
1324*ca987d46SWarner Losh\
1325*ca987d46SWarner Losh\   1. /boot/path
1326*ca987d46SWarner Losh\   2. path
1327*ca987d46SWarner Losh\
1328*ca987d46SWarner Losh\ The module_path variable is overridden if load is successful, by
1329*ca987d46SWarner Losh\ prepending the successful path.
1330*ca987d46SWarner Losh
1331*ca987d46SWarner Losh: load_from_directory ( path len 1 | flags len' path len 2 -- flag )
1332*ca987d46SWarner Losh  local args
1333*ca987d46SWarner Losh  2local path
1334*ca987d46SWarner Losh  args 1 = if 0 0 then
1335*ca987d46SWarner Losh  2local flags
1336*ca987d46SWarner Losh  0 0 2local oldmodulepath \ like a string
1337*ca987d46SWarner Losh  0 0 2local newmodulepath \ like a string
1338*ca987d46SWarner Losh  end-locals
1339*ca987d46SWarner Losh
1340*ca987d46SWarner Losh  \ Set the environment variable module_path, and try loading
1341*ca987d46SWarner Losh  \ the kernel again.
1342*ca987d46SWarner Losh  modulepath getenv saveenv to oldmodulepath
1343*ca987d46SWarner Losh
1344*ca987d46SWarner Losh  \ Try prepending /boot/ first
1345*ca987d46SWarner Losh  bootpath nip path nip + 	\ total length
1346*ca987d46SWarner Losh  oldmodulepath nip dup -1 = if
1347*ca987d46SWarner Losh    drop
1348*ca987d46SWarner Losh  else
1349*ca987d46SWarner Losh    1+ +			\ add oldpath -- XXX why the 1+ ?
1350*ca987d46SWarner Losh  then
1351*ca987d46SWarner Losh  allocate if ( out of memory ) 1 exit then \ XXX throw ?
1352*ca987d46SWarner Losh
1353*ca987d46SWarner Losh  0
1354*ca987d46SWarner Losh  bootpath strcat
1355*ca987d46SWarner Losh  path strcat
1356*ca987d46SWarner Losh  2dup to newmodulepath
1357*ca987d46SWarner Losh  modulepath setenv
1358*ca987d46SWarner Losh
1359*ca987d46SWarner Losh  \ Try all default kernel names
1360*ca987d46SWarner Losh  flags args 1- load_a_kernel
1361*ca987d46SWarner Losh  0= if ( success )
1362*ca987d46SWarner Losh    oldmodulepath nip -1 <> if
1363*ca987d46SWarner Losh      newmodulepath s" ;" strcat
1364*ca987d46SWarner Losh      oldmodulepath strcat
1365*ca987d46SWarner Losh      modulepath setenv
1366*ca987d46SWarner Losh      newmodulepath drop free-memory
1367*ca987d46SWarner Losh      oldmodulepath drop free-memory
1368*ca987d46SWarner Losh    then
1369*ca987d46SWarner Losh    0 exit
1370*ca987d46SWarner Losh  then
1371*ca987d46SWarner Losh
1372*ca987d46SWarner Losh  \ Well, try without the prepended /boot/
1373*ca987d46SWarner Losh  path newmodulepath drop swap move
1374*ca987d46SWarner Losh  newmodulepath drop path nip
1375*ca987d46SWarner Losh  2dup to newmodulepath
1376*ca987d46SWarner Losh  modulepath setenv
1377*ca987d46SWarner Losh
1378*ca987d46SWarner Losh  \ Try all default kernel names
1379*ca987d46SWarner Losh  flags args 1- load_a_kernel
1380*ca987d46SWarner Losh  if ( failed once more )
1381*ca987d46SWarner Losh    oldmodulepath restoreenv
1382*ca987d46SWarner Losh    newmodulepath drop free-memory
1383*ca987d46SWarner Losh    1
1384*ca987d46SWarner Losh  else
1385*ca987d46SWarner Losh    oldmodulepath nip -1 <> if
1386*ca987d46SWarner Losh      newmodulepath s" ;" strcat
1387*ca987d46SWarner Losh      oldmodulepath strcat
1388*ca987d46SWarner Losh      modulepath setenv
1389*ca987d46SWarner Losh      newmodulepath drop free-memory
1390*ca987d46SWarner Losh      oldmodulepath drop free-memory
1391*ca987d46SWarner Losh    then
1392*ca987d46SWarner Losh    0
1393*ca987d46SWarner Losh  then
1394*ca987d46SWarner Losh;
1395*ca987d46SWarner Losh
1396*ca987d46SWarner Losh\ Try to load a kernel; the kernel name is taken from one of
1397*ca987d46SWarner Losh\ the following lists, as ordered:
1398*ca987d46SWarner Losh\
1399*ca987d46SWarner Losh\   1. The "bootfile" environment variable
1400*ca987d46SWarner Losh\   2. The "kernel" environment variable
1401*ca987d46SWarner Losh\   3. The "path" argument
1402*ca987d46SWarner Losh\
1403*ca987d46SWarner Losh\ Flags are passed, if provided.
1404*ca987d46SWarner Losh\
1405*ca987d46SWarner Losh\ The kernel will be loaded from a directory computed from the
1406*ca987d46SWarner Losh\ path given. Two directories will be tried in the following order:
1407*ca987d46SWarner Losh\
1408*ca987d46SWarner Losh\   1. /boot/path
1409*ca987d46SWarner Losh\   2. path
1410*ca987d46SWarner Losh\
1411*ca987d46SWarner Losh\ Unless "path" is meant to be kernel name itself. In that case, it
1412*ca987d46SWarner Losh\ will first be tried as a full path, and, next, search on the
1413*ca987d46SWarner Losh\ directories pointed by module_path.
1414*ca987d46SWarner Losh\
1415*ca987d46SWarner Losh\ The module_path variable is overridden if load is successful, by
1416*ca987d46SWarner Losh\ prepending the successful path.
1417*ca987d46SWarner Losh
1418*ca987d46SWarner Losh: load_directory_or_file ( path len 1 | flags len' path len 2 -- flag )
1419*ca987d46SWarner Losh  local args
1420*ca987d46SWarner Losh  2local path
1421*ca987d46SWarner Losh  args 1 = if 0 0 then
1422*ca987d46SWarner Losh  2local flags
1423*ca987d46SWarner Losh  end-locals
1424*ca987d46SWarner Losh
1425*ca987d46SWarner Losh  \ First, assume path is an absolute path to a directory
1426*ca987d46SWarner Losh  flags path args clip_args load_from_directory
1427*ca987d46SWarner Losh  dup 0= if exit else drop then
1428*ca987d46SWarner Losh
1429*ca987d46SWarner Losh  \ Next, assume path points to the kernel
1430*ca987d46SWarner Losh  flags path args try_multiple_kernels
1431*ca987d46SWarner Losh;
1432*ca987d46SWarner Losh
1433*ca987d46SWarner Losh: initialize  ( addr len -- )
1434*ca987d46SWarner Losh  strdup conf_files strset
1435*ca987d46SWarner Losh;
1436*ca987d46SWarner Losh
1437*ca987d46SWarner Losh: kernel_options ( -- addr len 1 | 0 )
1438*ca987d46SWarner Losh  s" kernel_options" getenv
1439*ca987d46SWarner Losh  dup -1 = if drop 0 else 1 then
1440*ca987d46SWarner Losh;
1441*ca987d46SWarner Losh
1442*ca987d46SWarner Losh: standard_kernel_search  ( flags 1 | 0 -- flag )
1443*ca987d46SWarner Losh  local args
1444*ca987d46SWarner Losh  args 0= if 0 0 then
1445*ca987d46SWarner Losh  2local flags
1446*ca987d46SWarner Losh  s" kernel" getenv
1447*ca987d46SWarner Losh  dup -1 = if 0 swap then
1448*ca987d46SWarner Losh  2local path
1449*ca987d46SWarner Losh  end-locals
1450*ca987d46SWarner Losh
1451*ca987d46SWarner Losh  path nip -1 = if ( there isn't a "kernel" environment variable )
1452*ca987d46SWarner Losh    flags args load_a_kernel
1453*ca987d46SWarner Losh  else
1454*ca987d46SWarner Losh    flags path args 1+ clip_args load_directory_or_file
1455*ca987d46SWarner Losh  then
1456*ca987d46SWarner Losh;
1457*ca987d46SWarner Losh
1458*ca987d46SWarner Losh: load_kernel  ( -- ) ( throws: abort )
1459*ca987d46SWarner Losh  kernel_options standard_kernel_search
1460*ca987d46SWarner Losh  abort" Unable to load a kernel!"
1461*ca987d46SWarner Losh;
1462*ca987d46SWarner Losh
1463*ca987d46SWarner Losh: load_xen ( -- flag )
1464*ca987d46SWarner Losh  s" xen_kernel" getenv dup -1 <> if
1465*ca987d46SWarner Losh    1 1 load ( c-addr/u flag N -- flag )
1466*ca987d46SWarner Losh  else
1467*ca987d46SWarner Losh    drop
1468*ca987d46SWarner Losh    0 ( -1 -- flag )
1469*ca987d46SWarner Losh  then
1470*ca987d46SWarner Losh;
1471*ca987d46SWarner Losh
1472*ca987d46SWarner Losh: load_xen_throw ( -- ) ( throws: abort )
1473*ca987d46SWarner Losh  load_xen
1474*ca987d46SWarner Losh  abort" Unable to load Xen!"
1475*ca987d46SWarner Losh;
1476*ca987d46SWarner Losh
1477*ca987d46SWarner Losh: set_defaultoptions  ( -- )
1478*ca987d46SWarner Losh  s" kernel_options" getenv dup -1 = if
1479*ca987d46SWarner Losh    drop
1480*ca987d46SWarner Losh  else
1481*ca987d46SWarner Losh    s" temp_options" setenv
1482*ca987d46SWarner Losh  then
1483*ca987d46SWarner Losh;
1484*ca987d46SWarner Losh
1485*ca987d46SWarner Losh\ pick the i-th argument, i starts at 0
1486*ca987d46SWarner Losh: argv[]  ( aN uN ... a1 u1 N i -- aN uN ... a1 u1 N ai+1 ui+1 )
1487*ca987d46SWarner Losh  2dup = if 0 0 exit then	\ out of range
1488*ca987d46SWarner Losh  dup >r
1489*ca987d46SWarner Losh  1+ 2* ( skip N and ui )
1490*ca987d46SWarner Losh  pick
1491*ca987d46SWarner Losh  r>
1492*ca987d46SWarner Losh  1+ 2* ( skip N and ai )
1493*ca987d46SWarner Losh  pick
1494*ca987d46SWarner Losh;
1495*ca987d46SWarner Losh
1496*ca987d46SWarner Losh: drop_args  ( aN uN ... a1 u1 N -- )
1497*ca987d46SWarner Losh  0 ?do 2drop loop
1498*ca987d46SWarner Losh;
1499*ca987d46SWarner Losh
1500*ca987d46SWarner Losh: argc
1501*ca987d46SWarner Losh  dup
1502*ca987d46SWarner Losh;
1503*ca987d46SWarner Losh
1504*ca987d46SWarner Losh: queue_argv  ( aN uN ... a1 u1 N a u -- a u aN uN ... a1 u1 N+1 )
1505*ca987d46SWarner Losh  >r
1506*ca987d46SWarner Losh  over 2* 1+ -roll
1507*ca987d46SWarner Losh  r>
1508*ca987d46SWarner Losh  over 2* 1+ -roll
1509*ca987d46SWarner Losh  1+
1510*ca987d46SWarner Losh;
1511*ca987d46SWarner Losh
1512*ca987d46SWarner Losh: unqueue_argv  ( aN uN ... a1 u1 N -- aN uN ... a2 u2 N-1 a1 u1 )
1513*ca987d46SWarner Losh  1- -rot
1514*ca987d46SWarner Losh;
1515*ca987d46SWarner Losh
1516*ca987d46SWarner Losh\ compute the length of the buffer including the spaces between words
1517*ca987d46SWarner Losh: strlen(argv) ( aN uN .. a1 u1 N -- aN uN .. a1 u1 N len )
1518*ca987d46SWarner Losh  dup 0= if 0 exit then
1519*ca987d46SWarner Losh  0 >r	\ Size
1520*ca987d46SWarner Losh  0 >r	\ Index
1521*ca987d46SWarner Losh  begin
1522*ca987d46SWarner Losh    argc r@ <>
1523*ca987d46SWarner Losh  while
1524*ca987d46SWarner Losh    r@ argv[]
1525*ca987d46SWarner Losh    nip
1526*ca987d46SWarner Losh    r> r> rot + 1+
1527*ca987d46SWarner Losh    >r 1+ >r
1528*ca987d46SWarner Losh  repeat
1529*ca987d46SWarner Losh  r> drop
1530*ca987d46SWarner Losh  r>
1531*ca987d46SWarner Losh;
1532*ca987d46SWarner Losh
1533*ca987d46SWarner Losh: concat_argv  ( aN uN ... a1 u1 N -- a u )
1534*ca987d46SWarner Losh  strlen(argv) allocate if ENOMEM throw then
1535*ca987d46SWarner Losh  0 2>r ( save addr 0 on return stack )
1536*ca987d46SWarner Losh
1537*ca987d46SWarner Losh  begin
1538*ca987d46SWarner Losh    dup
1539*ca987d46SWarner Losh  while
1540*ca987d46SWarner Losh    unqueue_argv ( ... N a1 u1 )
1541*ca987d46SWarner Losh    2r> 2swap	 ( old a1 u1 )
1542*ca987d46SWarner Losh    strcat
1543*ca987d46SWarner Losh    s"  " strcat ( append one space ) \ XXX this gives a trailing space
1544*ca987d46SWarner Losh    2>r		( store string on the result stack )
1545*ca987d46SWarner Losh  repeat
1546*ca987d46SWarner Losh  drop_args
1547*ca987d46SWarner Losh  2r>
1548*ca987d46SWarner Losh;
1549*ca987d46SWarner Losh
1550*ca987d46SWarner Losh: set_tempoptions  ( addrN lenN ... addr1 len1 N -- addr len 1 | 0 )
1551*ca987d46SWarner Losh  \ Save the first argument, if it exists and is not a flag
1552*ca987d46SWarner Losh  argc if
1553*ca987d46SWarner Losh    0 argv[] drop c@ [char] - <> if
1554*ca987d46SWarner Losh      unqueue_argv 2>r  \ Filename
1555*ca987d46SWarner Losh      1 >r		\ Filename present
1556*ca987d46SWarner Losh    else
1557*ca987d46SWarner Losh      0 >r		\ Filename not present
1558*ca987d46SWarner Losh    then
1559*ca987d46SWarner Losh  else
1560*ca987d46SWarner Losh    0 >r		\ Filename not present
1561*ca987d46SWarner Losh  then
1562*ca987d46SWarner Losh
1563*ca987d46SWarner Losh  \ If there are other arguments, assume they are flags
1564*ca987d46SWarner Losh  ?dup if
1565*ca987d46SWarner Losh    concat_argv
1566*ca987d46SWarner Losh    2dup s" temp_options" setenv
1567*ca987d46SWarner Losh    drop free if EFREE throw then
1568*ca987d46SWarner Losh  else
1569*ca987d46SWarner Losh    set_defaultoptions
1570*ca987d46SWarner Losh  then
1571*ca987d46SWarner Losh
1572*ca987d46SWarner Losh  \ Bring back the filename, if one was provided
1573*ca987d46SWarner Losh  r> if 2r> 1 else 0 then
1574*ca987d46SWarner Losh;
1575*ca987d46SWarner Losh
1576*ca987d46SWarner Losh: get_arguments ( -- addrN lenN ... addr1 len1 N )
1577*ca987d46SWarner Losh  0
1578*ca987d46SWarner Losh  begin
1579*ca987d46SWarner Losh    \ Get next word on the command line
1580*ca987d46SWarner Losh    parse-word
1581*ca987d46SWarner Losh  ?dup while
1582*ca987d46SWarner Losh    queue_argv
1583*ca987d46SWarner Losh  repeat
1584*ca987d46SWarner Losh  drop ( empty string )
1585*ca987d46SWarner Losh;
1586*ca987d46SWarner Losh
1587*ca987d46SWarner Losh: load_kernel_and_modules  ( args -- flag )
1588*ca987d46SWarner Losh  set_tempoptions
1589*ca987d46SWarner Losh  argc >r
1590*ca987d46SWarner Losh  s" temp_options" getenv dup -1 <> if
1591*ca987d46SWarner Losh    queue_argv
1592*ca987d46SWarner Losh  else
1593*ca987d46SWarner Losh    drop
1594*ca987d46SWarner Losh  then
1595*ca987d46SWarner Losh  load_xen
1596*ca987d46SWarner Losh  ?dup 0= if ( success )
1597*ca987d46SWarner Losh    r> if ( a path was passed )
1598*ca987d46SWarner Losh      load_directory_or_file
1599*ca987d46SWarner Losh    else
1600*ca987d46SWarner Losh      standard_kernel_search
1601*ca987d46SWarner Losh    then
1602*ca987d46SWarner Losh    ?dup 0= if ['] load_modules catch then
1603*ca987d46SWarner Losh  then
1604*ca987d46SWarner Losh;
1605*ca987d46SWarner Losh
1606*ca987d46SWarner Loshonly forth definitions
1607