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