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
25 \ $FreeBSD: src/sys/boot/forth/support.4th,v 1.15 2002/05/24 02:28:58 gordon Exp $
26 \ $DragonFly: src/sys/boot/forth/support.4th,v 1.3 2003/11/10 06:08:34 dillon Exp $
28 \ Loader.rc support functions:
30 \ initialize_support ( -- ) initialize global variables
31 \ initialize ( addr len -- ) as above, plus load_conf_files
32 \ load_conf ( addr len -- ) load conf file given
33 \ include_conf_files ( -- ) load all conf files in load_conf_files
34 \ print_syntax_error ( -- ) print line and marker of where a syntax
36 \ print_line ( -- ) print last line processed
37 \ load_kernel ( -- ) load kernel
38 \ load_modules ( -- ) load modules flagged
40 \ Exported structures:
42 \ string counted string structure
43 \ cell .addr string address
44 \ cell .len string length
45 \ module module loading information structure
46 \ cell module.flag should we load it?
47 \ string module.name module's name
48 \ string module.loadname name to be used in loading the module
49 \ string module.type module's type
50 \ string module.args flags to be passed during load
51 \ string module.beforeload command to be executed before load
52 \ string module.afterload command to be executed after load
53 \ string module.loaderror command to be executed if load fails
54 \ cell module.next list chain
56 \ Exported global variables;
58 \ string conf_files configuration files to be loaded
59 \ string password password
60 \ cell modules_options pointer to first module information
61 \ value verbose? indicates if user wants a verbose loading
62 \ value any_conf_read? indicates if a conf file was succesfully read
64 \ Other exported words:
66 \ strdup ( addr len -- addr' len) similar to strdup(3)
67 \ strcat ( addr len addr' len' -- addr len+len' ) similar to strcat(3)
68 \ strlen ( addr -- len ) similar to strlen(3)
69 \ s' ( | string' -- addr len | ) similar to s"
70 \ rudimentary structure support
74 1 constant syntax_error
75 2 constant out_of_memory
81 8 constant before_load_error
82 9 constant after_load_error
94 \ Crude structure support
97 create here 0 , ['] drop , 0
98 does> create here swap dup @ allot cell+ @ execute
100 : member: create dup , over , + does> cell+ @ + ;
101 : ;structure swap ! ;
102 : constructor! >body cell+ ! ;
103 : constructor: over :noname ;
104 : ;constructor postpone ; swap cell+ ! ; immediate
105 : sizeof ' >body @ state @ if postpone literal then ; immediate
106 : offsetof ' >body cell+ @ state @ if postpone literal then ; immediate
107 : ptr 1 cells member: ;
108 : int 1 cells member: ;
122 \ Module options linked list
126 sizeof string member: module.name
127 sizeof string member: module.loadname
128 sizeof string member: module.type
129 sizeof string member: module.args
130 sizeof string member: module.beforeload
131 sizeof string member: module.afterload
132 sizeof string member: module.loaderror
136 \ Internal loader structures
137 structure: preloaded_file
141 ptr pf.metadata \ file_metadata
145 ptr pf.modules \ kernel_module
146 ptr pf.next \ preloaded_file
149 structure: kernel_module
152 ptr km.fp \ preloaded_file
153 ptr km.next \ kernel_module
156 structure: file_metadata
158 2 member: md.type \ this is not ANS Forth compatible (XXX)
159 ptr md.next \ file_metadata
160 0 member: md.data \ variable size
163 structure: config_resource
167 1 constant RES_STRING
172 structure: config_device
175 int cd.resource_count
176 ptr cd.resources \ config_resource
179 structure: STAILQ_HEAD
180 ptr stqh_first \ type*
181 ptr stqh_last \ type**
184 structure: STAILQ_ENTRY
185 ptr stqe_next \ type*
188 structure: pnphandler
194 ptr pnpid.ident \ char*
195 sizeof STAILQ_ENTRY cells member: pnpid.link \ pnpident
201 ptr pnpi.module \ (char*) module args
204 ptr pnpi.handler \ pnphandler
205 sizeof STAILQ_HEAD member: pnpi.ident \ pnpident
206 sizeof STAILQ_ENTRY member: pnpi.link \ pnpinfo
212 string nextboot_conf_file
214 create module_options sizeof module.next allot 0 module_options !
215 create last_module_option sizeof module.next allot 0 last_module_option !
219 \ Support string functions
221 : strdup ( addr len -- addr' len )
222 >r r@ allocate if out_of_memory throw then
227 : strcat { addr len addr' len' -- addr len+len' }
228 addr' addr len + len' move
232 : strlen ( addr -- len )
247 : 2>r postpone >r postpone >r ; immediate
248 : 2r> postpone r> postpone r> ; immediate
249 : 2r@ postpone 2r> postpone 2dup postpone 2>r ; immediate
253 -1 = if false else drop true then
256 \ Private definitions
258 vocabulary support-functions
259 only forth also support-functions definitions
261 \ Some control characters constants
271 80 constant read_buffer_size
275 : load_module_suffix s" _load" ;
276 : module_loadname_suffix s" _name" ;
277 : module_type_suffix s" _type" ;
278 : module_args_suffix s" _flags" ;
279 : module_beforeload_suffix s" _before" ;
280 : module_afterload_suffix s" _after" ;
281 : module_loaderror_suffix s" _error" ;
288 \ Assorted support funcitons
290 : free-memory free if free_error throw then ;
292 \ Assignment data temporary storage
297 \ Line by line file reading functions
306 vocabulary line-reading
307 also line-reading definitions also
309 \ File data temporary storage
312 0 value read_buffer_ptr
314 \ File's line reading function
316 support-functions definitions
322 line-reading definitions
326 read_buffer .len @ read_buffer_ptr >
328 read_buffer .addr @ read_buffer_ptr + c@ lf = if
329 read_buffer_ptr char+ to read_buffer_ptr
336 : scan_buffer ( -- addr len )
339 read_buffer .len @ r@ >
341 read_buffer .addr @ r@ + c@ lf = if
342 read_buffer .addr @ read_buffer_ptr + ( -- addr )
343 r@ read_buffer_ptr - ( -- len )
344 r> to read_buffer_ptr
349 read_buffer .addr @ read_buffer_ptr + ( -- addr )
350 r@ read_buffer_ptr - ( -- len )
351 r> to read_buffer_ptr
354 : line_buffer_resize ( len -- len )
356 line_buffer .len @ if
358 line_buffer .len @ r@ +
359 resize if out_of_memory throw then
361 r@ allocate if out_of_memory throw then
367 : append_to_line_buffer ( addr len -- )
368 line_buffer .addr @ line_buffer .len @
375 scan_buffer ( -- addr len )
376 line_buffer_resize ( len -- len )
377 append_to_line_buffer ( addr len -- )
381 read_buffer .len @ read_buffer_ptr =
387 read_buffer .addr @ 0= if
388 read_buffer_size allocate if out_of_memory throw then
391 fd @ read_buffer .addr @ read_buffer_size fread
392 dup -1 = if read_error throw then
393 dup 0= if true to end_of_file? then
398 line_buffer .addr @ ?dup if
401 0 line_buffer .addr !
405 support-functions definitions
422 only forth also support-functions definitions
424 \ Conf file line parser:
425 \ <line> ::= <spaces><name><spaces>'='<spaces><value><spaces>[<comment>] |
426 \ <spaces>[<comment>]
427 \ <name> ::= <letter>{<letter>|<digit>|'_'}
428 \ <value> ::= '"'{<character_set>|'\'<anything>}'"' | <name>
429 \ <character_set> ::= ASCII 32 to 126, except '\' and '"'
430 \ <comment> ::= '#'{<anything>}
438 vocabulary file-processing
439 also file-processing definitions
447 also parser definitions also
449 0 value parsing_function
453 line_pointer end_of_line =
472 line_pointer c@ [char] " =
476 line_pointer c@ [char] = =
480 line_pointer c@ [char] # =
485 line_pointer c@ tab = or
489 line_pointer c@ [char] \ =
493 line_pointer c@ [char] _ =
497 line_pointer c@ [char] . =
501 line_pointer char+ to line_pointer
504 : skip_to_end_of_line
505 end_of_line to line_pointer
513 end_of_line? if exit then
517 : parse_name ( -- addr len )
520 letter? digit? underscore? dot? or or or
533 : remove_backslashes { addr len | addr' len' -- addr' len' }
534 len allocate if out_of_memory throw then
538 addr c@ [char] \ <> if
539 addr c@ addr' len' + c!
549 : parse_quote ( -- addr len )
552 end_of_line? if syntax_error throw then
558 end_of_line? if syntax_error throw then
561 end_of_line? if syntax_error throw then
569 parse_name ( -- addr len )
576 parse_quote ( -- addr len )
578 parse_name ( -- addr len )
590 comment? if ['] comment to parsing_function exit then
591 end_of_line? 0= if syntax_error throw then
596 ['] white_space_4 to parsing_function
601 letter? digit? quote? or or if
602 ['] variable_value to parsing_function exit
609 ['] white_space_3 to parsing_function
614 assignment_sign? if ['] assignment_sign to parsing_function exit then
620 ['] white_space_2 to parsing_function
625 letter? if ['] variable_name to parsing_function exit then
626 comment? if ['] comment to parsing_function exit then
627 end_of_line? 0= if syntax_error throw then
630 file-processing definitions
633 line_buffer .addr @ line_buffer .len @ + to end_of_line
634 line_buffer .addr @ to line_pointer
635 ['] white_space_1 to parsing_function
639 parsing_function execute
641 parsing_function ['] comment =
642 parsing_function ['] white_space_1 =
643 parsing_function ['] white_space_4 =
644 or or 0= if syntax_error throw then
647 only forth also support-functions also file-processing definitions also
651 : assignment_type? ( addr len -- flag )
652 name_buffer .addr @ name_buffer .len @
656 : suffix_type? ( addr len -- flag )
657 name_buffer .len @ over <= if 2drop false exit then
658 name_buffer .len @ over - name_buffer .addr @ +
663 s" loader_conf_files" assignment_type?
667 s" nextboot_enable" assignment_type?
671 s" nextboot_conf" assignment_type?
675 s" verbose_loading" assignment_type?
679 s" exec" assignment_type?
683 s" password" assignment_type?
687 load_module_suffix suffix_type?
691 module_loadname_suffix suffix_type?
695 module_type_suffix suffix_type?
699 module_args_suffix suffix_type?
703 module_beforeload_suffix suffix_type?
707 module_afterload_suffix suffix_type?
711 module_loaderror_suffix suffix_type?
715 conf_files .addr @ ?dup if
718 value_buffer .addr @ c@ [char] " = if
719 value_buffer .addr @ char+ value_buffer .len @ 2 chars -
721 value_buffer .addr @ value_buffer .len @
724 conf_files .len ! conf_files .addr !
728 nextboot_conf_file .addr @ ?dup if
731 value_buffer .addr @ c@ [char] " = if
732 value_buffer .addr @ char+ value_buffer .len @ 2 chars -
734 value_buffer .addr @ value_buffer .len @
737 nextboot_conf_file .len ! nextboot_conf_file .addr !
740 : append_to_module_options_list ( addr -- )
741 module_options @ 0= if
745 dup last_module_option @ module.next !
750 : set_module_name ( addr -- )
751 name_buffer .addr @ name_buffer .len @
753 >r over module.name .addr !
754 r> swap module.name .len !
758 value_buffer .addr @ value_buffer .len @
759 2dup s' "YES"' compare >r
760 2dup s' "yes"' compare >r
761 2dup s" YES" compare >r
762 s" yes" compare r> r> r> and and and 0=
765 : find_module_option ( -- addr | 0 )
770 dup module.name dup .addr @ swap .len @
771 name_buffer .addr @ name_buffer .len @
772 compare 0= if exit then
777 : new_module_option ( -- addr )
778 sizeof module allocate if out_of_memory throw then
779 dup sizeof module erase
780 dup append_to_module_options_list
784 : get_module_option ( -- addr )
786 ?dup 0= if new_module_option then
790 name_buffer .len @ load_module_suffix nip - name_buffer .len !
791 yes_value? get_module_option module.flag !
795 name_buffer .len @ module_args_suffix nip - name_buffer .len !
796 get_module_option module.args
797 dup .addr @ ?dup if free-memory then
798 value_buffer .addr @ value_buffer .len @
799 over c@ [char] " = if
800 2 chars - swap char+ swap
807 : set_module_loadname
808 name_buffer .len @ module_loadname_suffix nip - name_buffer .len !
809 get_module_option module.loadname
810 dup .addr @ ?dup if free-memory then
811 value_buffer .addr @ value_buffer .len @
812 over c@ [char] " = if
813 2 chars - swap char+ swap
821 name_buffer .len @ module_type_suffix nip - name_buffer .len !
822 get_module_option module.type
823 dup .addr @ ?dup if free-memory then
824 value_buffer .addr @ value_buffer .len @
825 over c@ [char] " = if
826 2 chars - swap char+ swap
833 : set_module_beforeload
834 name_buffer .len @ module_beforeload_suffix nip - name_buffer .len !
835 get_module_option module.beforeload
836 dup .addr @ ?dup if free-memory then
837 value_buffer .addr @ value_buffer .len @
838 over c@ [char] " = if
839 2 chars - swap char+ swap
846 : set_module_afterload
847 name_buffer .len @ module_afterload_suffix nip - name_buffer .len !
848 get_module_option module.afterload
849 dup .addr @ ?dup if free-memory then
850 value_buffer .addr @ value_buffer .len @
851 over c@ [char] " = if
852 2 chars - swap char+ swap
859 : set_module_loaderror
860 name_buffer .len @ module_loaderror_suffix nip - name_buffer .len !
861 get_module_option module.loaderror
862 dup .addr @ ?dup if free-memory then
863 value_buffer .addr @ value_buffer .len @
864 over c@ [char] " = if
865 2 chars - swap char+ swap
872 : set_environment_variable
874 value_buffer .len @ +
876 allocate if out_of_memory throw then
877 dup 0 ( addr -- addr addr len )
879 name_buffer .addr @ name_buffer .len @ strcat
881 value_buffer .addr @ value_buffer .len @ strcat
882 ['] evaluate catch if
891 yes_value? to nextboot?
895 yes_value? to verbose?
899 value_buffer .addr @ value_buffer .len @
900 over c@ [char] " = if
903 ['] evaluate catch if exec_error throw then
907 password .addr @ ?dup if free if free_error throw then then
908 value_buffer .addr @ c@ [char] " = if
909 value_buffer .addr @ char+ value_buffer .len @ 2 - strdup
910 value_buffer .addr @ free if free_error throw then
912 value_buffer .addr @ value_buffer .len @
914 password .len ! password .addr !
915 0 value_buffer .addr !
919 name_buffer .len @ 0= if exit then
920 loader_conf_files? if set_conf_files exit then
921 nextboot_flag? if set_nextboot_flag exit then
922 nextboot_conf? if set_nextboot_conf exit then
923 verbose_flag? if set_verbose exit then
924 execute? if execute_command exit then
925 password? if set_password exit then
926 module_load? if set_module_flag exit then
927 module_loadname? if set_module_loadname exit then
928 module_type? if set_module_type exit then
929 module_args? if set_module_args exit then
930 module_beforeload? if set_module_beforeload exit then
931 module_afterload? if set_module_afterload exit then
932 module_loaderror? if set_module_loaderror exit then
933 set_environment_variable
938 \ Free some pointers if needed. The code then tests for errors
939 \ in freeing, and throws an exception if needed. If a pointer is
940 \ not allocated, it's value (0) is used as flag.
943 name_buffer .addr @ dup if free then
944 value_buffer .addr @ dup if free then
945 or if free_error throw then
948 : reset_assignment_buffers
949 0 name_buffer .addr !
951 0 value_buffer .addr !
952 0 value_buffer .len !
955 \ Higher level file processing
957 support-functions definitions
963 reset_assignment_buffers
966 ['] process_assignment catch
967 ['] free_buffers catch
976 fd @ -1 = if open_error throw then
977 reset_assignment_buffers
980 ['] process_assignment catch
981 ['] free_buffers catch
985 only forth also support-functions definitions
987 \ Interface to loading conf files
989 : load_conf ( addr len -- )
993 fd @ -1 = if open_error throw then
994 ['] process_conf catch
1000 line_buffer .addr @ line_buffer .len @ type cr
1003 : print_syntax_error
1004 line_buffer .addr @ line_buffer .len @ type cr
1007 line_pointer over <>
1016 \ Depuration support functions
1018 only forth definitions also support-functions
1021 ['] load_conf catch dup .
1022 syntax_error = if cr print_syntax_error then
1025 : show-module-options
1030 ." Name: " dup module.name dup .addr @ swap .len @ type cr
1031 ." Path: " dup module.loadname dup .addr @ swap .len @ type cr
1032 ." Type: " dup module.type dup .addr @ swap .len @ type cr
1033 ." Flags: " dup module.args dup .addr @ swap .len @ type cr
1034 ." Before load: " dup module.beforeload dup .addr @ swap .len @ type cr
1035 ." After load: " dup module.afterload dup .addr @ swap .len @ type cr
1036 ." Error: " dup module.loaderror dup .addr @ swap .len @ type cr
1037 ." Status: " dup module.flag @ if ." Load" else ." Don't load" then cr
1042 only forth also support-functions definitions
1044 \ Variables used for processing multiple conf files
1046 string current_file_name
1047 variable current_conf_files
1049 \ Indicates if any conf file was succesfully read
1051 0 value any_conf_read?
1053 \ loader_conf_files processing support functions
1055 : set_current_conf_files
1056 conf_files .addr @ current_conf_files !
1060 conf_files .addr @ conf_files .len @ strdup
1063 : recurse_on_conf_files?
1064 current_conf_files @ conf_files .addr @ <>
1067 : skip_leading_spaces { addr len pos -- addr len pos' }
1069 pos len = if addr len pos exit then
1077 : get_file_name { addr len pos -- addr len pos' addr' len' || 0 }
1079 addr free abort" Fatal error freeing memory"
1088 addr len pos addr r@ + pos r> - exit
1091 addr len pos addr r@ + pos r> -
1094 : get_next_file ( addr len ptr -- addr len ptr' addr' len' | 0 )
1099 : set_current_file_name
1100 over current_file_name .addr !
1101 dup current_file_name .len !
1104 : print_current_file
1105 current_file_name .addr @ current_file_name .len @ type
1108 : process_conf_errors
1109 dup 0= if true to any_conf_read? drop exit then
1111 dup syntax_error = if
1112 ." Warning: syntax error on file " print_current_file cr
1113 print_syntax_error drop exit
1116 ." Warning: bad definition on file " print_current_file cr
1117 print_line drop exit
1120 ." Warning: error reading file " print_current_file cr drop exit
1123 verbose? if ." Warning: unable to open file " print_current_file cr then
1126 dup free_error = abort" Fatal error freeing memory"
1127 dup out_of_memory = abort" Out of memory"
1128 throw \ Unknown error -- pass ahead
1131 \ Process loader_conf_files recursively
1132 \ Interface to loader_conf_files processing
1134 : include_conf_files
1135 set_current_conf_files
1140 set_current_file_name
1143 recurse_on_conf_files? if recurse then
1147 : get_nextboot_conf_file ( -- addr len )
1148 nextboot_conf_file .addr @ nextboot_conf_file .len @ strdup
1151 : rewrite_nextboot_file ( -- )
1152 get_nextboot_conf_file
1154 fd @ -1 = if open_error throw then
1155 fd @ s' nextboot_enable="NO" ' fwrite
1159 : include_nextboot_file
1160 get_nextboot_conf_file
1163 get_nextboot_conf_file
1166 ['] rewrite_nextboot_file catch
1170 \ Module loading functions
1176 : load_parameters ( addr -- addr addrN lenN ... addr1 len1 N )
1178 r@ module.args .addr @ r@ module.args .len @
1179 r@ module.loadname .len @ if
1180 r@ module.loadname .addr @ r@ module.loadname .len @
1182 r@ module.name .addr @ r@ module.name .len @
1184 r@ module.type .len @ if
1185 r@ module.type .addr @ r@ module.type .len @
1187 4 ( -t type name flags )
1194 : before_load ( addr -- addr )
1195 dup module.beforeload .len @ if
1196 dup module.beforeload .addr @ over module.beforeload .len @
1197 ['] evaluate catch if before_load_error throw then
1201 : after_load ( addr -- addr )
1202 dup module.afterload .len @ if
1203 dup module.afterload .addr @ over module.afterload .len @
1204 ['] evaluate catch if after_load_error throw then
1208 : load_error ( addr -- addr )
1209 dup module.loaderror .len @ if
1210 dup module.loaderror .addr @ over module.loaderror .len @
1211 evaluate \ This we do not intercept so it can throw errors
1215 : pre_load_message ( addr -- addr )
1217 dup module.name .addr @ over module.name .len @ type
1222 : load_error_message verbose? if ." failed!" cr then ;
1224 : load_succesful_message verbose? if ." ok" cr then ;
1227 load_parameters load
1230 : process_module ( addr -- addr )
1234 ['] load_module catch if
1235 dup module.loaderror .len @ if
1236 load_error \ Command should return a flag!
1238 load_error_message true \ Do not retry
1242 load_succesful_message true \ Succesful, do not retry
1247 : process_module_errors ( addr ior -- )
1248 dup before_load_error = if
1251 dup module.name .addr @ over module.name .len @ type
1252 dup module.loadname .len @ if
1253 ." (" dup module.loadname .addr @ over module.loadname .len @ type ." )"
1256 ." Error executing "
1257 dup module.beforeload .addr @ over module.afterload .len @ type cr
1261 dup after_load_error = if
1264 dup module.name .addr @ over module.name .len @ type
1265 dup module.loadname .len @ if
1266 ." (" dup module.loadname .addr @ over module.loadname .len @ type ." )"
1269 ." Error executing "
1270 dup module.afterload .addr @ over module.afterload .len @ type cr
1274 throw \ Don't know what it is all about -- pass ahead
1277 \ Module loading interface
1279 : load_modules ( -- ) ( throws: abort & user-defined )
1285 ['] process_module catch
1286 process_module_errors
1292 \ h00h00 magic used to try loading either a kernel with a given name,
1293 \ or a kernel with the default name in a directory of a given name
1296 : bootpath s" /boot/" ;
1297 : modulepath s" module_path" ;
1299 \ Functions used to save and restore module_path's value.
1300 : saveenv ( addr len | -1 -- addr' len | 0 -1 )
1301 dup -1 = if 0 swap exit then
1304 : freeenv ( addr len | 0 -1 )
1305 -1 = if drop else free abort" Freeing error" then
1307 : restoreenv ( addr len | 0 -1 -- )
1308 dup -1 = if ( it wasn't set )
1314 r> free abort" Freeing error"
1318 : clip_args \ Drop second string if only one argument is passed
1329 \ Parse filename from a comma-separated list
1331 : parse-; ( addr len -- addr' len-x addr x )
1347 \ Try loading one of multiple kernels specified
1349 : try_multiple_kernels ( addr len addr' len' args -- flag )
1355 s" DEBUG" getenv? if
1356 s" echo Module_path: ${module_path}" evaluate
1357 ." Kernel : " >r 2dup type r> cr
1358 dup 2 = if ." Flags : " >r 2over type r> cr then
1373 \ Try to load a kernel; the kernel name is taken from one of
1374 \ the following lists, as ordered:
1376 \ 1. The "bootfile" environment variable
1377 \ 2. The "kernel" environment variable
1379 \ Flags are passed, if available. If not, dummy values must be given.
1381 \ The kernel gets loaded from the current module_path.
1383 : load_a_kernel ( flags len 1 | x x 0 -- flag )
1389 \ Check if a default kernel name exists at all, exits if not
1390 s" bootfile" getenv dup -1 <> if
1392 flags kernel args 1+ try_multiple_kernels
1397 s" kernel" getenv dup -1 <> if
1404 \ Try all default kernel names
1405 flags kernel args 1+ try_multiple_kernels
1408 \ Try to load a kernel; the kernel name is taken from one of
1409 \ the following lists, as ordered:
1411 \ 1. The "bootfile" environment variable
1412 \ 2. The "kernel" environment variable
1414 \ Flags are passed, if provided.
1416 \ The kernel will be loaded from a directory computed from the
1417 \ path given. Two directories will be tried in the following order:
1422 \ The module_path variable is overridden if load is succesful, by
1423 \ prepending the successful path.
1425 : load_from_directory ( path len 1 | flags len' path len 2 -- flag )
1428 args 1 = if 0 0 then
1430 0 0 2local oldmodulepath
1431 0 0 2local newmodulepath
1434 \ Set the environment variable module_path, and try loading
1436 modulepath getenv saveenv to oldmodulepath
1438 \ Try prepending /boot/ first
1439 bootpath nip path nip +
1440 oldmodulepath nip dup -1 = if
1446 if ( out of memory )
1453 2dup to newmodulepath
1456 \ Try all default kernel names
1457 flags args 1- load_a_kernel
1459 oldmodulepath nip -1 <> if
1460 newmodulepath s" ;" strcat
1461 oldmodulepath strcat
1463 newmodulepath drop free-memory
1464 oldmodulepath drop free-memory
1469 \ Well, try without the prepended /boot/
1470 path newmodulepath drop swap move
1471 newmodulepath drop path nip
1472 2dup to newmodulepath
1475 \ Try all default kernel names
1476 flags args 1- load_a_kernel
1477 if ( failed once more )
1478 oldmodulepath restoreenv
1479 newmodulepath drop free-memory
1482 oldmodulepath nip -1 <> if
1483 newmodulepath s" ;" strcat
1484 oldmodulepath strcat
1486 newmodulepath drop free-memory
1487 oldmodulepath drop free-memory
1493 \ Try to load a kernel; the kernel name is taken from one of
1494 \ the following lists, as ordered:
1496 \ 1. The "bootfile" environment variable
1497 \ 2. The "kernel" environment variable
1498 \ 3. The "path" argument
1500 \ Flags are passed, if provided.
1502 \ The kernel will be loaded from a directory computed from the
1503 \ path given. Two directories will be tried in the following order:
1508 \ Unless "path" is meant to be kernel name itself. In that case, it
1509 \ will first be tried as a full path, and, next, search on the
1510 \ directories pointed by module_path.
1512 \ The module_path variable is overridden if load is succesful, by
1513 \ prepending the successful path.
1515 : load_directory_or_file ( path len 1 | flags len' path len 2 -- flag )
1518 args 1 = if 0 0 then
1522 \ First, assume path is an absolute path to a directory
1523 flags path args clip_args load_from_directory
1524 dup 0= if exit else drop then
1526 \ Next, assume path points to the kernel
1527 flags path args try_multiple_kernels
1530 : initialize ( addr len -- )
1531 strdup conf_files .len ! conf_files .addr !
1534 : kernel_options ( -- addr len 1 | 0 )
1535 s" kernel_options" getenv
1536 dup -1 = if drop 0 else 1 then
1539 : standard_kernel_search ( flags 1 | 0 -- flag )
1544 dup -1 = if 0 swap then
1548 path nip -1 = if ( there isn't a "kernel" environment variable )
1549 flags args load_a_kernel
1551 flags path args 1+ clip_args load_directory_or_file
1555 : load_kernel ( -- ) ( throws: abort )
1556 kernel_options standard_kernel_search
1557 abort" Unable to load a kernel!"
1560 : set_defaultoptions ( -- )
1561 s" kernel_options" getenv dup -1 = if
1564 s" temp_options" setenv
1568 : argv[] ( aN uN ... a1 u1 N i -- aN uN ... a1 u1 N ai+1 ui+1 )
1569 2dup = if 0 0 exit then
1571 1+ 2* ( skip N and ui )
1574 1+ 2* ( skip N and ai )
1578 : drop_args ( aN uN ... a1 u1 N -- )
1586 : queue_argv ( aN uN ... a1 u1 N a u -- a u aN uN ... a1 u1 N+1 )
1594 : unqueue_argv ( aN uN ... a1 u1 N -- aN uN ... a2 u2 N-1 a1 u1 )
1599 dup 0= if 0 exit then
1614 : concat_argv ( aN uN ... a1 u1 N -- a u )
1615 strlen(argv) allocate if out_of_memory throw then
1631 : set_tempoptions ( addrN lenN ... addr1 len1 N -- addr len 1 | 0 )
1632 \ Save the first argument, if it exists and is not a flag
1634 0 argv[] drop c@ [char] - <> if
1635 unqueue_argv 2>r \ Filename
1636 1 >r \ Filename present
1638 0 >r \ Filename not present
1641 0 >r \ Filename not present
1644 \ If there are other arguments, assume they are flags
1647 2dup s" temp_options" setenv
1648 drop free if free_error throw then
1653 \ Bring back the filename, if one was provided
1654 r> if 2r> 1 else 0 then
1657 : get_arguments ( -- addrN lenN ... addr1 len1 N )
1660 \ Get next word on the command line
1665 drop ( empty string )
1668 : load_kernel_and_modules ( args -- flag )
1671 s" temp_options" getenv dup -1 <> if
1676 r> if ( a path was passed )
1677 load_directory_or_file
1679 standard_kernel_search
1681 ?dup 0= if ['] load_modules catch then
1684 : read-password { size | buf len -- }
1685 size allocate if out_of_memory throw then
1693 backspace emit bl emit backspace emit
1699 dup <cr> = if cr drop buf len exit then
1711 \ Go back to straight forth vocabulary
1713 only forth also definitions