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