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 1933630506bSToomas Soome: strspn { addr len addr1 len1 | paddr plen -- addr' len' } 1943630506bSToomas Soome begin 1953630506bSToomas Soome len 1963630506bSToomas Soome while 1973630506bSToomas Soome addr1 to paddr 1983630506bSToomas Soome len1 to plen 1993630506bSToomas Soome begin 2003630506bSToomas Soome plen 2013630506bSToomas Soome while 2023630506bSToomas Soome addr c@ paddr c@ = if addr len exit then 2033630506bSToomas Soome paddr 1+ to paddr 2043630506bSToomas Soome plen 1- to plen 2053630506bSToomas Soome repeat 2063630506bSToomas Soome addr 1 + to addr 2073630506bSToomas Soome len 1 - to len 2083630506bSToomas Soome repeat 2093630506bSToomas Soome 0 0 2103630506bSToomas Soome; 2113630506bSToomas Soome 212ca987d46SWarner Losh: s' \ same as s", allows " in the string 213ca987d46SWarner Losh [char] ' parse 214ca987d46SWarner Losh state @ if postpone sliteral then 215ca987d46SWarner Losh; immediate 216ca987d46SWarner Losh 217ca987d46SWarner Losh: 2>r postpone >r postpone >r ; immediate 218ca987d46SWarner Losh: 2r> postpone r> postpone r> ; immediate 219ca987d46SWarner Losh: 2r@ postpone 2r> postpone 2dup postpone 2>r ; immediate 220ca987d46SWarner Losh 221ca987d46SWarner Losh: getenv? getenv -1 = if false else drop true then ; 222ca987d46SWarner Losh 2233630506bSToomas Soome\ execute xt for each device listed in console variable. 2243630506bSToomas Soome\ this allows us to have device specific output for logos, menu frames etc 2253630506bSToomas Soome: console-iterate { xt | caddr clen taddr tlen -- } 2263630506bSToomas Soome \ get current console and save it 2273630506bSToomas Soome s" console" getenv 2283630506bSToomas Soome ['] strdup catch if 2drop exit then 2293630506bSToomas Soome to clen to caddr 2303630506bSToomas Soome 2313630506bSToomas Soome clen to tlen 2323630506bSToomas Soome caddr to taddr 2333630506bSToomas Soome begin 2343630506bSToomas Soome tlen 2353630506bSToomas Soome while 2363630506bSToomas Soome taddr tlen s" , " strspn 2373630506bSToomas Soome \ we need to handle 3 cases for addr len pairs on stack: 2383630506bSToomas Soome \ addr len are 0 0 - there was no comma nor space 2393630506bSToomas Soome \ addr len are x 0 - the first char is either comma or space 2403630506bSToomas Soome \ addr len are x y. 2413630506bSToomas Soome 2dup + 0= if 2423630506bSToomas Soome \ there was no comma nor space. 2433630506bSToomas Soome 2drop 2443630506bSToomas Soome taddr tlen s" console" setenv 2453630506bSToomas Soome xt execute 2463630506bSToomas Soome 0 to tlen 2473630506bSToomas Soome else dup 0= if 2483630506bSToomas Soome 2drop 2493630506bSToomas Soome else 2503630506bSToomas Soome dup ( taddr' tlen' tlen' ) 2513630506bSToomas Soome tlen swap - dup 2523630506bSToomas Soome 0= if \ sequence of comma and space? 2533630506bSToomas Soome drop 2543630506bSToomas Soome else 2553630506bSToomas Soome taddr swap s" console" setenv 2563630506bSToomas Soome xt execute 2573630506bSToomas Soome then 2583630506bSToomas Soome to tlen 2593630506bSToomas Soome to taddr 2603630506bSToomas Soome then then 2613630506bSToomas Soome tlen 0> if \ step over separator 2623630506bSToomas Soome tlen 1- to tlen 2633630506bSToomas Soome taddr 1+ to taddr 2643630506bSToomas Soome then 2653630506bSToomas Soome repeat 2663630506bSToomas Soome caddr clen s" console" setenv \ restore console setup 2673630506bSToomas Soome caddr free drop 2683630506bSToomas Soome; 2693630506bSToomas Soome 270ca987d46SWarner Losh\ determine if a word appears in a string, case-insensitive 271ca987d46SWarner Losh: contains? ( addr1 len1 addr2 len2 -- 0 | -1 ) 272ca987d46SWarner Losh 2 pick 0= if 2drop 2drop true exit then 273ca987d46SWarner Losh dup 0= if 2drop 2drop false exit then 274ca987d46SWarner Losh begin 275ca987d46SWarner Losh begin 276ca987d46SWarner Losh swap dup c@ dup 32 = over 9 = or over 10 = or 277ca987d46SWarner Losh over 13 = or over 44 = or swap drop 278ca987d46SWarner Losh while 1+ swap 1- repeat 279ca987d46SWarner Losh swap 2 pick 1- over < 280ca987d46SWarner Losh while 281ca987d46SWarner Losh 2over 2over drop over compare-insensitive 0= if 282ca987d46SWarner Losh 2 pick over = if 2drop 2drop true exit then 283ca987d46SWarner Losh 2 pick tuck - -rot + swap over c@ dup 32 = 284ca987d46SWarner Losh over 9 = or over 10 = or over 13 = or over 44 = or 285ca987d46SWarner Losh swap drop if 2drop 2drop true exit then 286ca987d46SWarner Losh then begin 287ca987d46SWarner Losh swap dup c@ dup 32 = over 9 = or over 10 = or 288ca987d46SWarner Losh over 13 = or over 44 = or swap drop 289ca987d46SWarner Losh if false else true then 2 pick 0> and 290ca987d46SWarner Losh while 1+ swap 1- repeat 291ca987d46SWarner Losh swap 292ca987d46SWarner Losh repeat 293ca987d46SWarner Losh 2drop 2drop false 294ca987d46SWarner Losh; 295ca987d46SWarner Losh 296ca987d46SWarner Losh: boot_serial? ( -- 0 | -1 ) 297ca987d46SWarner Losh s" console" getenv dup -1 <> if 298ca987d46SWarner Losh s" comconsole" 2swap contains? 299ca987d46SWarner Losh else drop false then 3003630506bSToomas Soome\ s" boot_serial" getenv dup -1 <> if 3013630506bSToomas Soome\ swap drop 0> 3023630506bSToomas Soome\ else drop false then 3033630506bSToomas Soome\ or \ console contains comconsole ( or ) boot_serial 3043630506bSToomas Soome\ s" boot_multicons" getenv dup -1 <> if 3053630506bSToomas Soome\ swap drop 0> 3063630506bSToomas Soome\ else drop false then 3073630506bSToomas Soome\ or \ previous boolean ( or ) boot_multicons 3083630506bSToomas Soome; 3093630506bSToomas Soome 3103630506bSToomas Soome: framebuffer? ( -- t ) 3113630506bSToomas Soome s" console" getenv 3123630506bSToomas Soome 2dup s" efi" compare 0<> >r 3133630506bSToomas Soome s" vidconsole" compare 0<> r> and if 3143630506bSToomas Soome FALSE exit 3153630506bSToomas Soome then 3163630506bSToomas Soome s" screen.depth" getenv? 317ca987d46SWarner Losh; 318ca987d46SWarner Losh 319ca987d46SWarner Losh\ Private definitions 320ca987d46SWarner Losh 321ca987d46SWarner Loshvocabulary support-functions 322ca987d46SWarner Loshonly forth also support-functions definitions 323ca987d46SWarner Losh 324ca987d46SWarner Losh\ Some control characters constants 325ca987d46SWarner Losh 326ca987d46SWarner Losh7 constant bell 327ca987d46SWarner Losh8 constant backspace 328ca987d46SWarner Losh9 constant tab 329ca987d46SWarner Losh10 constant lf 330ca987d46SWarner Losh13 constant <cr> 331ca987d46SWarner Losh 332ca987d46SWarner Losh\ Read buffer size 333ca987d46SWarner Losh 334ca987d46SWarner Losh80 constant read_buffer_size 335ca987d46SWarner Losh 336ca987d46SWarner Losh\ Standard suffixes 337ca987d46SWarner Losh 338ca987d46SWarner Losh: load_module_suffix s" _load" ; 339ca987d46SWarner Losh: module_loadname_suffix s" _name" ; 340ca987d46SWarner Losh: module_type_suffix s" _type" ; 341ca987d46SWarner Losh: module_args_suffix s" _flags" ; 342ca987d46SWarner Losh: module_beforeload_suffix s" _before" ; 343ca987d46SWarner Losh: module_afterload_suffix s" _after" ; 344ca987d46SWarner Losh: module_loaderror_suffix s" _error" ; 345ca987d46SWarner Losh 346ca987d46SWarner Losh\ Support operators 347ca987d46SWarner Losh 348ca987d46SWarner Losh: >= < 0= ; 349ca987d46SWarner Losh: <= > 0= ; 350ca987d46SWarner Losh 351ca987d46SWarner Losh\ Assorted support functions 352ca987d46SWarner Losh 353ca987d46SWarner Losh: free-memory free if EFREE throw then ; 354ca987d46SWarner Losh 355ca987d46SWarner Losh: strget { var -- addr len } var .addr @ var .len @ ; 356ca987d46SWarner Losh 357ca987d46SWarner Losh\ assign addr len to variable. 358ca987d46SWarner Losh: strset { addr len var -- } addr var .addr ! len var .len ! ; 359ca987d46SWarner Losh 360ca987d46SWarner Losh\ free memory and reset fields 361ca987d46SWarner Losh: strfree { var -- } var .addr @ ?dup if free-memory 0 0 var strset then ; 362ca987d46SWarner Losh 363ca987d46SWarner Losh\ free old content, make a copy of the string and assign to variable 364ca987d46SWarner Losh: string= { addr len var -- } var strfree addr len strdup var strset ; 365ca987d46SWarner Losh 366ca987d46SWarner Losh: strtype ( str -- ) strget type ; 367ca987d46SWarner Losh 368ca987d46SWarner Losh\ assign a reference to what is on the stack 369ca987d46SWarner Losh: strref { addr len var -- addr len } 370ca987d46SWarner Losh addr var .addr ! len var .len ! addr len 371ca987d46SWarner Losh; 372ca987d46SWarner Losh 373ca987d46SWarner Losh\ unquote a string 374ca987d46SWarner Losh: unquote ( addr len -- addr len ) 375ca987d46SWarner Losh over c@ [char] " = if 2 chars - swap char+ swap then 376ca987d46SWarner Losh; 377ca987d46SWarner Losh 378ca987d46SWarner Losh\ Assignment data temporary storage 379ca987d46SWarner Losh 380ca987d46SWarner Loshstring name_buffer 381ca987d46SWarner Loshstring value_buffer 382ca987d46SWarner Losh 383ca987d46SWarner Losh\ Line by line file reading functions 384ca987d46SWarner Losh\ 385ca987d46SWarner Losh\ exported: 386ca987d46SWarner Losh\ line_buffer 387ca987d46SWarner Losh\ end_of_file? 388ca987d46SWarner Losh\ fd 389ca987d46SWarner Losh\ read_line 390ca987d46SWarner Losh\ reset_line_reading 391ca987d46SWarner Losh 392ca987d46SWarner Loshvocabulary line-reading 393ca987d46SWarner Loshalso line-reading definitions 394ca987d46SWarner Losh 395ca987d46SWarner Losh\ File data temporary storage 396ca987d46SWarner Losh 397ca987d46SWarner Loshstring read_buffer 398ca987d46SWarner Losh0 value read_buffer_ptr 399ca987d46SWarner Losh 400ca987d46SWarner Losh\ File's line reading function 401ca987d46SWarner Losh 402ca987d46SWarner Loshget-current ( -- wid ) previous definitions 403ca987d46SWarner Losh 404ca987d46SWarner Loshstring line_buffer 405ca987d46SWarner Losh0 value end_of_file? 406ca987d46SWarner Loshvariable fd 407ca987d46SWarner Losh 408ca987d46SWarner Losh>search ( wid -- ) definitions 409ca987d46SWarner Losh 410ca987d46SWarner Losh: skip_newlines 411ca987d46SWarner Losh begin 412ca987d46SWarner Losh read_buffer .len @ read_buffer_ptr > 413ca987d46SWarner Losh while 414ca987d46SWarner Losh read_buffer .addr @ read_buffer_ptr + c@ lf = if 415ca987d46SWarner Losh read_buffer_ptr char+ to read_buffer_ptr 416ca987d46SWarner Losh else 417ca987d46SWarner Losh exit 418ca987d46SWarner Losh then 419ca987d46SWarner Losh repeat 420ca987d46SWarner Losh; 421ca987d46SWarner Losh 422ca987d46SWarner Losh: scan_buffer ( -- addr len ) 423ca987d46SWarner Losh read_buffer_ptr >r 424ca987d46SWarner Losh begin 425ca987d46SWarner Losh read_buffer .len @ r@ > 426ca987d46SWarner Losh while 427ca987d46SWarner Losh read_buffer .addr @ r@ + c@ lf = if 428ca987d46SWarner Losh read_buffer .addr @ read_buffer_ptr + ( -- addr ) 429ca987d46SWarner Losh r@ read_buffer_ptr - ( -- len ) 430ca987d46SWarner Losh r> to read_buffer_ptr 431ca987d46SWarner Losh exit 432ca987d46SWarner Losh then 433ca987d46SWarner Losh r> char+ >r 434ca987d46SWarner Losh repeat 435ca987d46SWarner Losh read_buffer .addr @ read_buffer_ptr + ( -- addr ) 436ca987d46SWarner Losh r@ read_buffer_ptr - ( -- len ) 437ca987d46SWarner Losh r> to read_buffer_ptr 438ca987d46SWarner Losh; 439ca987d46SWarner Losh 440ca987d46SWarner Losh: line_buffer_resize ( len -- len ) 4411781ad70SToomas Soome dup 0= if exit then 442ca987d46SWarner Losh >r 443ca987d46SWarner Losh line_buffer .len @ if 444ca987d46SWarner Losh line_buffer .addr @ 445ca987d46SWarner Losh line_buffer .len @ r@ + 446ca987d46SWarner Losh resize if ENOMEM throw then 447ca987d46SWarner Losh else 448ca987d46SWarner Losh r@ allocate if ENOMEM throw then 449ca987d46SWarner Losh then 450ca987d46SWarner Losh line_buffer .addr ! 451ca987d46SWarner Losh r> 452ca987d46SWarner Losh; 453ca987d46SWarner Losh 454ca987d46SWarner Losh: append_to_line_buffer ( addr len -- ) 4551781ad70SToomas Soome dup 0= if 2drop exit then 456ca987d46SWarner Losh line_buffer strget 457ca987d46SWarner Losh 2swap strcat 458ca987d46SWarner Losh line_buffer .len ! 459ca987d46SWarner Losh drop 460ca987d46SWarner Losh; 461ca987d46SWarner Losh 462ca987d46SWarner Losh: read_from_buffer 463ca987d46SWarner Losh scan_buffer ( -- addr len ) 464ca987d46SWarner Losh line_buffer_resize ( len -- len ) 465ca987d46SWarner Losh append_to_line_buffer ( addr len -- ) 466ca987d46SWarner Losh; 467ca987d46SWarner Losh 468ca987d46SWarner Losh: refill_required? 469ca987d46SWarner Losh read_buffer .len @ read_buffer_ptr = 470ca987d46SWarner Losh end_of_file? 0= and 471ca987d46SWarner Losh; 472ca987d46SWarner Losh 473ca987d46SWarner Losh: refill_buffer 474ca987d46SWarner Losh 0 to read_buffer_ptr 475ca987d46SWarner Losh read_buffer .addr @ 0= if 476ca987d46SWarner Losh read_buffer_size allocate if ENOMEM throw then 477ca987d46SWarner Losh read_buffer .addr ! 478ca987d46SWarner Losh then 479ca987d46SWarner Losh fd @ read_buffer .addr @ read_buffer_size fread 480ca987d46SWarner Losh dup -1 = if EREAD throw then 481ca987d46SWarner Losh dup 0= if true to end_of_file? then 482ca987d46SWarner Losh read_buffer .len ! 483ca987d46SWarner Losh; 484ca987d46SWarner Losh 485ca987d46SWarner Loshget-current ( -- wid ) previous definitions >search ( wid -- ) 486ca987d46SWarner Losh 487ca987d46SWarner Losh: reset_line_reading 488*4783fb73SWarner Losh 0 to read_buffer_ptr 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