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