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