1 \ Copyright (c) 1999 Daniel C. Sobral <dcs@freebsd.org>
4 \ Redistribution and use in source and binary forms, with or without
5 \ modification, are permitted provided that the following conditions
7 \ 1. Redistributions of source code must retain the above copyright
8 \ notice, this list of conditions and the following disclaimer.
9 \ 2. Redistributions in binary form must reproduce the above copyright
10 \ notice, this list of conditions and the following disclaimer in the
11 \ documentation and/or other materials provided with the distribution.
13 \ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 \ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 \ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 \ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 \ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 \ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 \ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 \ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 \ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 \ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 \ Loader.rc support functions:
29 \ initialize_support ( -- ) initialize global variables
30 \ initialize ( addr len -- ) as above, plus load_conf_files
31 \ load_conf ( addr len -- ) load conf file given
32 \ include_conf_files ( -- ) load all conf files in load_conf_files
33 \ print_syntax_error ( -- ) print line and marker of where a syntax
35 \ print_line ( -- ) print last line processed
36 \ load_kernel ( -- ) load kernel
37 \ load_modules ( -- ) load modules flagged
39 \ Exported structures:
41 \ string counted string structure
42 \ cell .addr string address
43 \ cell .len string length
44 \ module module loading information structure
45 \ cell module.flag should we load it?
46 \ string module.name module's name
47 \ string module.loadname name to be used in loading the module
48 \ string module.type module's type
49 \ string module.args flags to be passed during load
50 \ string module.beforeload command to be executed before load
51 \ string module.afterload command to be executed after load
52 \ string module.loaderror command to be executed if load fails
53 \ cell module.next list chain
55 \ Exported global variables;
57 \ string conf_files configuration files to be loaded
58 \ string password password
59 \ cell modules_options pointer to first module information
60 \ value verbose? indicates if user wants a verbose loading
61 \ value any_conf_read? indicates if a conf file was succesfully read
63 \ Other exported words:
65 \ strdup ( addr len -- addr' len) similar to strdup(3)
66 \ strcat ( addr len addr' len' -- addr len+len' ) similar to strcat(3)
67 \ strlen ( addr -- len ) similar to strlen(3)
68 \ s' ( | string' -- addr len | ) similar to s"
69 \ rudimentary structure support
73 1 constant syntax_error
74 2 constant out_of_memory
80 8 constant before_load_error
81 9 constant after_load_error
93 \ Crude structure support
96 create here 0 , ['] drop , 0
97 does> create here swap dup @ allot cell+ @ execute
99 : member: create dup , over , + does> cell+ @ + ;
100 : ;structure swap ! ;
101 : constructor! >body cell+ ! ;
102 : constructor: over :noname ;
103 : ;constructor postpone ; swap cell+ ! ; immediate
104 : sizeof ' >body @ state @ if postpone literal then ; immediate
105 : offsetof ' >body cell+ @ state @ if postpone literal then ; immediate
106 : ptr 1 cells member: ;
107 : int 1 cells member: ;
121 \ Module options linked list
125 sizeof string member: module.name
126 sizeof string member: module.loadname
127 sizeof string member: module.type
128 sizeof string member: module.args
129 sizeof string member: module.beforeload
130 sizeof string member: module.afterload
131 sizeof string member: module.loaderror
135 \ Internal loader structures
136 structure: preloaded_file
140 ptr pf.metadata \ file_metadata
144 ptr pf.modules \ kernel_module
145 ptr pf.next \ preloaded_file
148 structure: kernel_module
151 ptr km.fp \ preloaded_file
152 ptr km.next \ kernel_module
155 structure: file_metadata
157 2 member: md.type \ this is not ANS Forth compatible (XXX)
158 ptr md.next \ file_metadata
159 0 member: md.data \ variable size
162 structure: config_resource
166 1 constant RES_STRING
171 structure: config_device
174 int cd.resource_count
175 ptr cd.resources \ config_resource
178 structure: STAILQ_HEAD
179 ptr stqh_first \ type*
180 ptr stqh_last \ type**
183 structure: STAILQ_ENTRY
184 ptr stqe_next \ type*
187 structure: pnphandler
193 ptr pnpid.ident \ char*
194 sizeof STAILQ_ENTRY cells member: pnpid.link \ pnpident
200 ptr pnpi.module \ (char*) module args
203 ptr pnpi.handler \ pnphandler
204 sizeof STAILQ_HEAD member: pnpi.ident \ pnpident
205 sizeof STAILQ_ENTRY member: pnpi.link \ pnpinfo
212 create module_options sizeof module.next allot 0 module_options !
213 create last_module_option sizeof module.next allot 0 last_module_option !
216 \ Support string functions
218 : strdup ( addr len -- addr' len )
219 >r r@ allocate if out_of_memory throw then
224 : strcat { addr len addr' len' -- addr len+len' }
225 addr' addr len + len' move
229 : strlen ( addr -- len )
244 : 2>r postpone >r postpone >r ; immediate
245 : 2r> postpone r> postpone r> ; immediate
246 : 2r@ postpone 2r> postpone 2dup postpone 2>r ; immediate
250 -1 = if false else drop true then
253 \ Private definitions
255 vocabulary support-functions
256 only forth also support-functions definitions
258 \ Some control characters constants
268 80 constant read_buffer_size
272 : load_module_suffix s" _load" ;
273 : module_loadname_suffix s" _name" ;
274 : module_type_suffix s" _type" ;
275 : module_args_suffix s" _flags" ;
276 : module_beforeload_suffix s" _before" ;
277 : module_afterload_suffix s" _after" ;
278 : module_loaderror_suffix s" _error" ;
285 \ Assorted support funcitons
287 : free-memory free if free_error throw then ;
289 \ Assignment data temporary storage
294 \ Line by line file reading functions
303 vocabulary line-reading
304 also line-reading definitions also
306 \ File data temporary storage
309 0 value read_buffer_ptr
311 \ File's line reading function
313 support-functions definitions
319 line-reading definitions
323 read_buffer .len @ read_buffer_ptr >
325 read_buffer .addr @ read_buffer_ptr + c@ lf = if
326 read_buffer_ptr char+ to read_buffer_ptr
333 : scan_buffer ( -- addr len )
336 read_buffer .len @ r@ >
338 read_buffer .addr @ r@ + c@ lf = if
339 read_buffer .addr @ read_buffer_ptr + ( -- addr )
340 r@ read_buffer_ptr - ( -- len )
341 r> to read_buffer_ptr
346 read_buffer .addr @ read_buffer_ptr + ( -- addr )
347 r@ read_buffer_ptr - ( -- len )
348 r> to read_buffer_ptr
351 : line_buffer_resize ( len -- len )
353 line_buffer .len @ if
355 line_buffer .len @ r@ +
356 resize if out_of_memory throw then
358 r@ allocate if out_of_memory throw then
364 : append_to_line_buffer ( addr len -- )
365 line_buffer .addr @ line_buffer .len @
372 scan_buffer ( -- addr len )
373 line_buffer_resize ( len -- len )
374 append_to_line_buffer ( addr len -- )
378 read_buffer .len @ read_buffer_ptr =
384 read_buffer .addr @ 0= if
385 read_buffer_size allocate if out_of_memory throw then
388 fd @ read_buffer .addr @ read_buffer_size fread
389 dup -1 = if read_error throw then
390 dup 0= if true to end_of_file? then
395 line_buffer .addr @ ?dup if
398 0 line_buffer .addr !
402 support-functions definitions
419 only forth also support-functions definitions
421 \ Conf file line parser:
422 \ <line> ::= <spaces><name><spaces>'='<spaces><value><spaces>[<comment>] |
423 \ <spaces>[<comment>]
424 \ <name> ::= <letter>{<letter>|<digit>|'_'}
425 \ <value> ::= '"'{<character_set>|'\'<anything>}'"' | <name>
426 \ <character_set> ::= ASCII 32 to 126, except '\' and '"'
427 \ <comment> ::= '#'{<anything>}
435 vocabulary file-processing
436 also file-processing definitions
444 also parser definitions also
446 0 value parsing_function
450 line_pointer end_of_line =
469 line_pointer c@ [char] " =
473 line_pointer c@ [char] = =
477 line_pointer c@ [char] # =
482 line_pointer c@ tab = or
486 line_pointer c@ [char] \ =
490 line_pointer c@ [char] _ =
494 line_pointer c@ [char] . =
498 line_pointer char+ to line_pointer
501 : skip_to_end_of_line
502 end_of_line to line_pointer
510 end_of_line? if exit then
514 : parse_name ( -- addr len )
517 letter? digit? underscore? dot? or or or
530 : remove_backslashes { addr len | addr' len' -- addr' len' }
531 len allocate if out_of_memory throw then
535 addr c@ [char] \ <> if
536 addr c@ addr' len' + c!
546 : parse_quote ( -- addr len )
549 end_of_line? if syntax_error throw then
555 end_of_line? if syntax_error throw then
558 end_of_line? if syntax_error throw then
566 parse_name ( -- addr len )
573 parse_quote ( -- addr len )
575 parse_name ( -- addr len )
587 comment? if ['] comment to parsing_function exit then
588 end_of_line? 0= if syntax_error throw then
593 ['] white_space_4 to parsing_function
598 letter? digit? quote? or or if
599 ['] variable_value to parsing_function exit
606 ['] white_space_3 to parsing_function
611 assignment_sign? if ['] assignment_sign to parsing_function exit then
617 ['] white_space_2 to parsing_function
622 letter? if ['] variable_name to parsing_function exit then
623 comment? if ['] comment to parsing_function exit then
624 end_of_line? 0= if syntax_error throw then
627 file-processing definitions
630 line_buffer .addr @ line_buffer .len @ + to end_of_line
631 line_buffer .addr @ to line_pointer
632 ['] white_space_1 to parsing_function
636 parsing_function execute
638 parsing_function ['] comment =
639 parsing_function ['] white_space_1 =
640 parsing_function ['] white_space_4 =
641 or or 0= if syntax_error throw then
644 only forth also support-functions also file-processing definitions also
648 : assignment_type? ( addr len -- flag )
649 name_buffer .addr @ name_buffer .len @
653 : suffix_type? ( addr len -- flag )
654 name_buffer .len @ over <= if 2drop false exit then
655 name_buffer .len @ over - name_buffer .addr @ +
660 s" loader_conf_files" assignment_type?
664 s" verbose_loading" assignment_type?
668 s" exec" assignment_type?
672 s" password" assignment_type?
676 load_module_suffix suffix_type?
680 module_loadname_suffix suffix_type?
684 module_type_suffix suffix_type?
688 module_args_suffix suffix_type?
692 module_beforeload_suffix suffix_type?
696 module_afterload_suffix suffix_type?
700 module_loaderror_suffix suffix_type?
704 conf_files .addr @ ?dup if
707 value_buffer .addr @ c@ [char] " = if
708 value_buffer .addr @ char+ value_buffer .len @ 2 chars -
710 value_buffer .addr @ value_buffer .len @
713 conf_files .len ! conf_files .addr !
716 : append_to_module_options_list ( addr -- )
717 module_options @ 0= if
721 dup last_module_option @ module.next !
726 : set_module_name ( addr -- )
727 name_buffer .addr @ name_buffer .len @
729 >r over module.name .addr !
730 r> swap module.name .len !
734 value_buffer .addr @ value_buffer .len @
735 2dup s' "YES"' compare >r
736 2dup s' "yes"' compare >r
737 2dup s" YES" compare >r
738 s" yes" compare r> r> r> and and and 0=
741 : find_module_option ( -- addr | 0 )
746 dup module.name dup .addr @ swap .len @
747 name_buffer .addr @ name_buffer .len @
748 compare 0= if exit then
753 : new_module_option ( -- addr )
754 sizeof module allocate if out_of_memory throw then
755 dup sizeof module erase
756 dup append_to_module_options_list
760 : get_module_option ( -- addr )
762 ?dup 0= if new_module_option then
766 name_buffer .len @ load_module_suffix nip - name_buffer .len !
767 yes_value? get_module_option module.flag !
771 name_buffer .len @ module_args_suffix nip - name_buffer .len !
772 get_module_option module.args
773 dup .addr @ ?dup if free-memory then
774 value_buffer .addr @ value_buffer .len @
775 over c@ [char] " = if
776 2 chars - swap char+ swap
783 : set_module_loadname
784 name_buffer .len @ module_loadname_suffix nip - name_buffer .len !
785 get_module_option module.loadname
786 dup .addr @ ?dup if free-memory then
787 value_buffer .addr @ value_buffer .len @
788 over c@ [char] " = if
789 2 chars - swap char+ swap
797 name_buffer .len @ module_type_suffix nip - name_buffer .len !
798 get_module_option module.type
799 dup .addr @ ?dup if free-memory then
800 value_buffer .addr @ value_buffer .len @
801 over c@ [char] " = if
802 2 chars - swap char+ swap
809 : set_module_beforeload
810 name_buffer .len @ module_beforeload_suffix nip - name_buffer .len !
811 get_module_option module.beforeload
812 dup .addr @ ?dup if free-memory then
813 value_buffer .addr @ value_buffer .len @
814 over c@ [char] " = if
815 2 chars - swap char+ swap
822 : set_module_afterload
823 name_buffer .len @ module_afterload_suffix nip - name_buffer .len !
824 get_module_option module.afterload
825 dup .addr @ ?dup if free-memory then
826 value_buffer .addr @ value_buffer .len @
827 over c@ [char] " = if
828 2 chars - swap char+ swap
835 : set_module_loaderror
836 name_buffer .len @ module_loaderror_suffix nip - name_buffer .len !
837 get_module_option module.loaderror
838 dup .addr @ ?dup if free-memory then
839 value_buffer .addr @ value_buffer .len @
840 over c@ [char] " = if
841 2 chars - swap char+ swap
848 : set_environment_variable
850 value_buffer .len @ +
852 allocate if out_of_memory throw then
853 dup 0 ( addr -- addr addr len )
855 name_buffer .addr @ name_buffer .len @ strcat
857 value_buffer .addr @ value_buffer .len @ strcat
858 ['] evaluate catch if
867 yes_value? to verbose?
871 value_buffer .addr @ value_buffer .len @
872 over c@ [char] " = if
875 ['] evaluate catch if exec_error throw then
879 password .addr @ ?dup if free if free_error throw then then
880 value_buffer .addr @ c@ [char] " = if
881 value_buffer .addr @ char+ value_buffer .len @ 2 - strdup
882 value_buffer .addr @ free if free_error throw then
884 value_buffer .addr @ value_buffer .len @
886 password .len ! password .addr !
887 0 value_buffer .addr !
891 name_buffer .len @ 0= if exit then
892 loader_conf_files? if set_conf_files exit then
893 verbose_flag? if set_verbose exit then
894 execute? if execute_command exit then
895 password? if set_password exit then
896 module_load? if set_module_flag exit then
897 module_loadname? if set_module_loadname exit then
898 module_type? if set_module_type exit then
899 module_args? if set_module_args exit then
900 module_beforeload? if set_module_beforeload exit then
901 module_afterload? if set_module_afterload exit then
902 module_loaderror? if set_module_loaderror exit then
903 set_environment_variable
908 \ Free some pointers if needed. The code then tests for errors
909 \ in freeing, and throws an exception if needed. If a pointer is
910 \ not allocated, it's value (0) is used as flag.
913 name_buffer .addr @ dup if free then
914 value_buffer .addr @ dup if free then
915 or if free_error throw then
918 : reset_assignment_buffers
919 0 name_buffer .addr !
921 0 value_buffer .addr !
922 0 value_buffer .len !
925 \ Higher level file processing
927 support-functions definitions
933 reset_assignment_buffers
936 ['] process_assignment catch
937 ['] free_buffers catch
942 only forth also support-functions definitions
944 \ Interface to loading conf files
946 : load_conf ( addr len -- )
950 fd @ -1 = if open_error throw then
951 ['] process_conf catch
957 line_buffer .addr @ line_buffer .len @ type cr
961 line_buffer .addr @ line_buffer .len @ type cr
973 \ Depuration support functions
975 only forth definitions also support-functions
978 ['] load_conf catch dup .
979 syntax_error = if cr print_syntax_error then
982 : show-module-options
987 ." Name: " dup module.name dup .addr @ swap .len @ type cr
988 ." Path: " dup module.loadname dup .addr @ swap .len @ type cr
989 ." Type: " dup module.type dup .addr @ swap .len @ type cr
990 ." Flags: " dup module.args dup .addr @ swap .len @ type cr
991 ." Before load: " dup module.beforeload dup .addr @ swap .len @ type cr
992 ." After load: " dup module.afterload dup .addr @ swap .len @ type cr
993 ." Error: " dup module.loaderror dup .addr @ swap .len @ type cr
994 ." Status: " dup module.flag @ if ." Load" else ." Don't load" then cr
999 only forth also support-functions definitions
1001 \ Variables used for processing multiple conf files
1003 string current_file_name
1004 variable current_conf_files
1006 \ Indicates if any conf file was succesfully read
1008 0 value any_conf_read?
1010 \ loader_conf_files processing support functions
1012 : set_current_conf_files
1013 conf_files .addr @ current_conf_files !
1017 conf_files .addr @ conf_files .len @ strdup
1020 : recurse_on_conf_files?
1021 current_conf_files @ conf_files .addr @ <>
1024 : skip_leading_spaces { addr len pos -- addr len pos' }
1026 pos len = if addr len pos exit then
1034 : get_file_name { addr len pos -- addr len pos' addr' len' || 0 }
1036 addr free abort" Fatal error freeing memory"
1045 addr len pos addr r@ + pos r> - exit
1048 addr len pos addr r@ + pos r> -
1051 : get_next_file ( addr len ptr -- addr len ptr' addr' len' | 0 )
1056 : set_current_file_name
1057 over current_file_name .addr !
1058 dup current_file_name .len !
1061 : print_current_file
1062 current_file_name .addr @ current_file_name .len @ type
1065 : process_conf_errors
1066 dup 0= if true to any_conf_read? drop exit then
1068 dup syntax_error = if
1069 ." Warning: syntax error on file " print_current_file cr
1070 print_syntax_error drop exit
1073 ." Warning: bad definition on file " print_current_file cr
1074 print_line drop exit
1077 ." Warning: error reading file " print_current_file cr drop exit
1080 verbose? if ." Warning: unable to open file " print_current_file cr then
1083 dup free_error = abort" Fatal error freeing memory"
1084 dup out_of_memory = abort" Out of memory"
1085 throw \ Unknown error -- pass ahead
1088 \ Process loader_conf_files recursively
1089 \ Interface to loader_conf_files processing
1091 : include_conf_files
1092 set_current_conf_files
1097 set_current_file_name
1100 recurse_on_conf_files? if recurse then
1104 \ Module loading functions
1110 : load_parameters ( addr -- addr addrN lenN ... addr1 len1 N )
1112 r@ module.args .addr @ r@ module.args .len @
1113 r@ module.loadname .len @ if
1114 r@ module.loadname .addr @ r@ module.loadname .len @
1116 r@ module.name .addr @ r@ module.name .len @
1118 r@ module.type .len @ if
1119 r@ module.type .addr @ r@ module.type .len @
1121 4 ( -t type name flags )
1128 : before_load ( addr -- addr )
1129 dup module.beforeload .len @ if
1130 dup module.beforeload .addr @ over module.beforeload .len @
1131 ['] evaluate catch if before_load_error throw then
1135 : after_load ( addr -- addr )
1136 dup module.afterload .len @ if
1137 dup module.afterload .addr @ over module.afterload .len @
1138 ['] evaluate catch if after_load_error throw then
1142 : load_error ( addr -- addr )
1143 dup module.loaderror .len @ if
1144 dup module.loaderror .addr @ over module.loaderror .len @
1145 evaluate \ This we do not intercept so it can throw errors
1149 : pre_load_message ( addr -- addr )
1151 dup module.name .addr @ over module.name .len @ type
1156 : load_error_message verbose? if ." failed!" cr then ;
1158 : load_succesful_message verbose? if ." ok" cr then ;
1161 load_parameters load
1164 : process_module ( addr -- addr )
1168 ['] load_module catch if
1169 dup module.loaderror .len @ if
1170 load_error \ Command should return a flag!
1172 load_error_message true \ Do not retry
1176 load_succesful_message true \ Succesful, do not retry
1181 : process_module_errors ( addr ior -- )
1182 dup before_load_error = if
1185 dup module.name .addr @ over module.name .len @ type
1186 dup module.loadname .len @ if
1187 ." (" dup module.loadname .addr @ over module.loadname .len @ type ." )"
1190 ." Error executing "
1191 dup module.beforeload .addr @ over module.afterload .len @ type cr
1195 dup after_load_error = if
1198 dup module.name .addr @ over module.name .len @ type
1199 dup module.loadname .len @ if
1200 ." (" dup module.loadname .addr @ over module.loadname .len @ type ." )"
1203 ." Error executing "
1204 dup module.afterload .addr @ over module.afterload .len @ type cr
1208 throw \ Don't know what it is all about -- pass ahead
1211 \ Module loading interface
1213 : load_modules ( -- ) ( throws: abort & user-defined )
1219 ['] process_module catch
1220 process_module_errors
1226 \ h00h00 magic used to try loading either a kernel with a given name,
1227 \ or a kernel with the default name in a directory of a given name
1230 : bootpath s" /boot/" ;
1231 : modulepath s" module_path" ;
1233 \ Functions used to save and restore module_path's value.
1234 : saveenv ( addr len | -1 -- addr' len | 0 -1 )
1235 dup -1 = if 0 swap exit then
1238 : freeenv ( addr len | 0 -1 )
1239 -1 = if drop else free abort" Freeing error" then
1241 : restoreenv ( addr len | 0 -1 -- )
1242 dup -1 = if ( it wasn't set )
1248 r> free abort" Freeing error"
1252 : clip_args \ Drop second string if only one argument is passed
1263 \ Parse filename from a comma-separated list
1265 : parse-; ( addr len -- addr' len-x addr x )
1281 \ Try loading one of multiple kernels specified
1283 : try_multiple_kernels ( addr len addr' len' args -- flag )
1289 s" DEBUG" getenv? if
1290 s" echo Module_path: ${module_path}" evaluate
1291 ." Kernel : " >r 2dup type r> cr
1292 dup 2 = if ." Flags : " >r 2over type r> cr then
1307 \ Try to load a kernel; the kernel name is taken from one of
1308 \ the following lists, as ordered:
1310 \ 1. The "bootfile" environment variable
1311 \ 2. The "kernel" environment variable
1313 \ Flags are passed, if available. If not, dummy values must be given.
1315 \ The kernel gets loaded from the current module_path.
1317 : load_a_kernel ( flags len 1 | x x 0 -- flag )
1323 \ Check if a default kernel name exists at all, exits if not
1324 s" bootfile" getenv dup -1 <> if
1326 flags kernel args 1+ try_multiple_kernels
1331 s" kernel" getenv dup -1 <> if
1338 \ Try all default kernel names
1339 flags kernel args 1+ try_multiple_kernels
1342 \ Try to load a kernel; the kernel name is taken from one of
1343 \ the following lists, as ordered:
1345 \ 1. The "bootfile" environment variable
1346 \ 2. The "kernel" environment variable
1348 \ Flags are passed, if provided.
1350 \ The kernel will be loaded from a directory computed from the
1351 \ path given. Two directories will be tried in the following order:
1356 \ The module_path variable is overridden if load is succesful, by
1357 \ prepending the successful path.
1359 : load_from_directory ( path len 1 | flags len' path len 2 -- flag )
1362 args 1 = if 0 0 then
1364 0 0 2local oldmodulepath
1365 0 0 2local newmodulepath
1368 \ Set the environment variable module_path, and try loading
1370 modulepath getenv saveenv to oldmodulepath
1372 \ Try prepending /boot/ first
1373 bootpath nip path nip +
1374 oldmodulepath nip dup -1 = if
1380 if ( out of memory )
1387 2dup to newmodulepath
1390 \ Try all default kernel names
1391 flags args 1- load_a_kernel
1393 oldmodulepath nip -1 <> if
1394 newmodulepath s" ;" strcat
1395 oldmodulepath strcat
1397 newmodulepath drop free-memory
1398 oldmodulepath drop free-memory
1403 \ Well, try without the prepended /boot/
1404 path newmodulepath drop swap move
1405 newmodulepath drop path nip
1406 2dup to newmodulepath
1409 \ Try all default kernel names
1410 flags args 1- load_a_kernel
1411 if ( failed once more )
1412 oldmodulepath restoreenv
1413 newmodulepath drop free-memory
1416 oldmodulepath nip -1 <> if
1417 newmodulepath s" ;" strcat
1418 oldmodulepath strcat
1420 newmodulepath drop free-memory
1421 oldmodulepath drop free-memory
1427 \ Try to load a kernel; the kernel name is taken from one of
1428 \ the following lists, as ordered:
1430 \ 1. The "bootfile" environment variable
1431 \ 2. The "kernel" environment variable
1432 \ 3. The "path" argument
1434 \ Flags are passed, if provided.
1436 \ The kernel will be loaded from a directory computed from the
1437 \ path given. Two directories will be tried in the following order:
1442 \ Unless "path" is meant to be kernel name itself. In that case, it
1443 \ will first be tried as a full path, and, next, search on the
1444 \ directories pointed by module_path.
1446 \ The module_path variable is overridden if load is succesful, by
1447 \ prepending the successful path.
1449 : load_directory_or_file ( path len 1 | flags len' path len 2 -- flag )
1452 args 1 = if 0 0 then
1456 \ First, assume path is an absolute path to a directory
1457 flags path args clip_args load_from_directory
1458 dup 0= if exit else drop then
1460 \ Next, assume path points to the kernel
1461 flags path args try_multiple_kernels
1464 : initialize ( addr len -- )
1465 strdup conf_files .len ! conf_files .addr !
1468 : kernel_options ( -- addr len 1 | 0 )
1469 s" kernel_options" getenv
1470 dup -1 = if drop 0 else 1 then
1473 : standard_kernel_search ( flags 1 | 0 -- flag )
1478 dup -1 = if 0 swap then
1482 path nip -1 = if ( there isn't a "kernel" environment variable )
1483 flags args load_a_kernel
1485 flags path args 1+ clip_args load_directory_or_file
1489 : load_kernel ( -- ) ( throws: abort )
1490 kernel_options standard_kernel_search
1491 abort" Unable to load a kernel!"
1494 : set_defaultoptions ( -- )
1495 s" kernel_options" getenv dup -1 = if
1498 s" temp_options" setenv
1502 : argv[] ( aN uN ... a1 u1 N i -- aN uN ... a1 u1 N ai+1 ui+1 )
1503 2dup = if 0 0 exit then
1505 1+ 2* ( skip N and ui )
1508 1+ 2* ( skip N and ai )
1512 : drop_args ( aN uN ... a1 u1 N -- )
1520 : queue_argv ( aN uN ... a1 u1 N a u -- a u aN uN ... a1 u1 N+1 )
1528 : unqueue_argv ( aN uN ... a1 u1 N -- aN uN ... a2 u2 N-1 a1 u1 )
1533 dup 0= if 0 exit then
1548 : concat_argv ( aN uN ... a1 u1 N -- a u )
1549 strlen(argv) allocate if out_of_memory throw then
1565 : set_tempoptions ( addrN lenN ... addr1 len1 N -- addr len 1 | 0 )
1566 \ Save the first argument, if it exists and is not a flag
1568 0 argv[] drop c@ [char] - <> if
1569 unqueue_argv 2>r \ Filename
1570 1 >r \ Filename present
1572 0 >r \ Filename not present
1575 0 >r \ Filename not present
1578 \ If there are other arguments, assume they are flags
1581 2dup s" temp_options" setenv
1582 drop free if free_error throw then
1587 \ Bring back the filename, if one was provided
1588 r> if 2r> 1 else 0 then
1591 : get_arguments ( -- addrN lenN ... addr1 len1 N )
1594 \ Get next word on the command line
1599 drop ( empty string )
1602 : load_kernel_and_modules ( args -- flag )
1605 s" temp_options" getenv dup -1 <> if
1610 r> if ( a path was passed )
1611 load_directory_or_file
1613 standard_kernel_search
1615 ?dup 0= if ['] load_modules catch then
1618 : read-password { size | buf len -- }
1619 size allocate if out_of_memory throw then
1627 backspace emit bl emit backspace emit
1633 dup <cr> = if cr drop buf len exit then
1645 \ Go back to straight forth vocabulary
1647 only forth also definitions