support.4th revision 50477
1\ Copyright (c) 1999 Daniel C. Sobral <dcs@freebsd.org> 2\ All rights reserved. 3\ 4\ Redistribution and use in source and binary forms, with or without 5\ modification, are permitted provided that the following conditions 6\ are met: 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. 12\ 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 23\ SUCH DAMAGE. 24\ 25\ $FreeBSD: head/sys/boot/forth/support.4th 50477 1999-08-28 01:08:13Z peter $ 26 27\ Loader.rc support functions: 28\ 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 34\ error was detected 35\ print_line ( -- ) print last line processed 36\ load_kernel ( -- ) load kernel 37\ load_modules ( -- ) load modules flagged 38\ 39\ Exported structures: 40\ 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 54\ 55\ Exported global variables; 56\ 57\ string conf_files configuration files to be loaded 58\ cell modules_options pointer to first module information 59\ value verbose? indicates if user wants a verbose loading 60\ value any_conf_read? indicates if a conf file was succesfully read 61\ 62\ Other exported words: 63\ 64\ strdup ( addr len -- addr' len) similar to strdup(3) 65\ strcat ( addr len addr' len' -- addr len+len' ) similar to strcat(3) 66\ s' ( | string' -- addr len | ) similar to s" 67\ rudimentary structure support 68 69\ Exception values 70 711 constant syntax_error 722 constant out_of_memory 733 constant free_error 744 constant set_error 755 constant read_error 766 constant open_error 777 constant exec_error 788 constant before_load_error 799 constant after_load_error 80 81\ Crude structure support 82 83: structure: create here 0 , 0 does> create @ allot ; 84: member: create dup , over , + does> cell+ @ + ; 85: ;structure swap ! ; 86: sizeof ' >body @ state @ if postpone literal then ; immediate 87: offsetof ' >body cell+ @ state @ if postpone literal then ; immediate 88: ptr 1 cells member: ; 89: int 1 cells member: ; 90 91\ String structure 92 93structure: string 94 ptr .addr 95 int .len 96;structure 97 98\ Module options linked list 99 100structure: module 101 int module.flag 102 sizeof string member: module.name 103 sizeof string member: module.loadname 104 sizeof string member: module.type 105 sizeof string member: module.args 106 sizeof string member: module.beforeload 107 sizeof string member: module.afterload 108 sizeof string member: module.loaderror 109 ptr module.next 110;structure 111 112\ Global variables 113 114string conf_files 115create module_options sizeof module.next allot 116create last_module_option sizeof module.next allot 1170 value verbose? 118 119\ Support string functions 120 121: strdup ( addr len -- addr' len ) 122 >r r@ allocate if out_of_memory throw then 123 tuck r@ move 124 r> 125; 126 127: strcat { addr len addr' len' -- addr len+len' } 128 addr' addr len + len' move 129 addr len len' + 130; 131 132: s' 133 [char] ' parse 134 state @ if 135 postpone sliteral 136 then 137; immediate 138 139\ Private definitions 140 141vocabulary support-functions 142only forth also support-functions definitions 143 144\ Some control characters constants 145 1469 constant tab 14710 constant lf 148 149\ Read buffer size 150 15180 constant read_buffer_size 152 153\ Standard suffixes 154 155: load_module_suffix s" _load" ; 156: module_loadname_suffix s" _name" ; 157: module_type_suffix s" _type" ; 158: module_args_suffix s" _flags" ; 159: module_beforeload_suffix s" _before" ; 160: module_afterload_suffix s" _after" ; 161: module_loaderror_suffix s" _error" ; 162 163\ Support operators 164 165: >= < 0= ; 166: <= > 0= ; 167 168\ Assorted support funcitons 169 170: free-memory free if free_error throw then ; 171 172\ Assignment data temporary storage 173 174string name_buffer 175string value_buffer 176 177\ File data temporary storage 178 179string line_buffer 180string read_buffer 1810 value read_buffer_ptr 182 183\ File's line reading function 184 1850 value end_of_file? 186variable fd 187 188: skip_newlines 189 begin 190 read_buffer .len @ read_buffer_ptr > 191 while 192 read_buffer .addr @ read_buffer_ptr + c@ lf = if 193 read_buffer_ptr char+ to read_buffer_ptr 194 else 195 exit 196 then 197 repeat 198; 199 200: scan_buffer ( -- addr len ) 201 read_buffer_ptr >r 202 begin 203 read_buffer .len @ r@ > 204 while 205 read_buffer .addr @ r@ + c@ lf = if 206 read_buffer .addr @ read_buffer_ptr + ( -- addr ) 207 r@ read_buffer_ptr - ( -- len ) 208 r> to read_buffer_ptr 209 exit 210 then 211 r> char+ >r 212 repeat 213 read_buffer .addr @ read_buffer_ptr + ( -- addr ) 214 r@ read_buffer_ptr - ( -- len ) 215 r> to read_buffer_ptr 216; 217 218: line_buffer_resize ( len -- len ) 219 >r 220 line_buffer .len @ if 221 line_buffer .addr @ 222 line_buffer .len @ r@ + 223 resize if out_of_memory throw then 224 else 225 r@ allocate if out_of_memory throw then 226 then 227 line_buffer .addr ! 228 r> 229; 230 231: append_to_line_buffer ( addr len -- ) 232 line_buffer .addr @ line_buffer .len @ 233 2swap strcat 234 line_buffer .len ! 235 drop 236; 237 238: read_from_buffer 239 scan_buffer ( -- addr len ) 240 line_buffer_resize ( len -- len ) 241 append_to_line_buffer ( addr len -- ) 242; 243 244: refill_required? 245 read_buffer .len @ read_buffer_ptr = 246 end_of_file? 0= and 247; 248 249: refill_buffer 250 0 to read_buffer_ptr 251 read_buffer .addr @ 0= if 252 read_buffer_size allocate if out_of_memory throw then 253 read_buffer .addr ! 254 then 255 fd @ read_buffer .addr @ read_buffer_size fread 256 dup -1 = if read_error throw then 257 dup 0= if true to end_of_file? then 258 read_buffer .len ! 259; 260 261: reset_line_buffer 262 0 line_buffer .addr ! 263 0 line_buffer .len ! 264; 265 266: read_line 267 reset_line_buffer 268 skip_newlines 269 begin 270 read_from_buffer 271 refill_required? 272 while 273 refill_buffer 274 repeat 275; 276 277\ Conf file line parser: 278\ <line> ::= <spaces><name><spaces>'='<spaces><value><spaces>[<comment>] | 279\ <spaces>[<comment>] 280\ <name> ::= <letter>{<letter>|<digit>|'_'} 281\ <value> ::= '"'{<character_set>|'\'<anything>}'"' | <name> 282\ <character_set> ::= ASCII 32 to 126, except '\' and '"' 283\ <comment> ::= '#'{<anything>} 284 2850 value parsing_function 286 2870 value end_of_line 2880 value line_pointer 289 290: end_of_line? 291 line_pointer end_of_line = 292; 293 294: letter? 295 line_pointer c@ >r 296 r@ [char] A >= 297 r@ [char] Z <= and 298 r@ [char] a >= 299 r> [char] z <= and 300 or 301; 302 303: digit? 304 line_pointer c@ >r 305 r@ [char] 0 >= 306 r> [char] 9 <= and 307; 308 309: quote? 310 line_pointer c@ [char] " = 311; 312 313: assignment_sign? 314 line_pointer c@ [char] = = 315; 316 317: comment? 318 line_pointer c@ [char] # = 319; 320 321: space? 322 line_pointer c@ bl = 323 line_pointer c@ tab = or 324; 325 326: backslash? 327 line_pointer c@ [char] \ = 328; 329 330: underscore? 331 line_pointer c@ [char] _ = 332; 333 334: dot? 335 line_pointer c@ [char] . = 336; 337 338: skip_character 339 line_pointer char+ to line_pointer 340; 341 342: skip_to_end_of_line 343 end_of_line to line_pointer 344; 345 346: eat_space 347 begin 348 space? 349 while 350 skip_character 351 end_of_line? if exit then 352 repeat 353; 354 355: parse_name ( -- addr len ) 356 line_pointer 357 begin 358 letter? digit? underscore? dot? or or or 359 while 360 skip_character 361 end_of_line? if 362 line_pointer over - 363 strdup 364 exit 365 then 366 repeat 367 line_pointer over - 368 strdup 369; 370 371: remove_backslashes { addr len | addr' len' -- addr' len' } 372 len allocate if out_of_memory throw then 373 to addr' 374 addr >r 375 begin 376 addr c@ [char] \ <> if 377 addr c@ addr' len' + c! 378 len' char+ to len' 379 then 380 addr char+ to addr 381 r@ len + addr = 382 until 383 r> drop 384 addr' len' 385; 386 387: parse_quote ( -- addr len ) 388 line_pointer 389 skip_character 390 end_of_line? if syntax_error throw then 391 begin 392 quote? 0= 393 while 394 backslash? if 395 skip_character 396 end_of_line? if syntax_error throw then 397 then 398 skip_character 399 end_of_line? if syntax_error throw then 400 repeat 401 skip_character 402 line_pointer over - 403 remove_backslashes 404; 405 406: read_name 407 parse_name ( -- addr len ) 408 name_buffer .len ! 409 name_buffer .addr ! 410; 411 412: read_value 413 quote? if 414 parse_quote ( -- addr len ) 415 else 416 parse_name ( -- addr len ) 417 then 418 value_buffer .len ! 419 value_buffer .addr ! 420; 421 422: comment 423 skip_to_end_of_line 424; 425 426: white_space_4 427 eat_space 428 comment? if ['] comment to parsing_function exit then 429 end_of_line? 0= if syntax_error throw then 430; 431 432: variable_value 433 read_value 434 ['] white_space_4 to parsing_function 435; 436 437: white_space_3 438 eat_space 439 letter? digit? quote? or or if 440 ['] variable_value to parsing_function exit 441 then 442 syntax_error throw 443; 444 445: assignment_sign 446 skip_character 447 ['] white_space_3 to parsing_function 448; 449 450: white_space_2 451 eat_space 452 assignment_sign? if ['] assignment_sign to parsing_function exit then 453 syntax_error throw 454; 455 456: variable_name 457 read_name 458 ['] white_space_2 to parsing_function 459; 460 461: white_space_1 462 eat_space 463 letter? if ['] variable_name to parsing_function exit then 464 comment? if ['] comment to parsing_function exit then 465 end_of_line? 0= if syntax_error throw then 466; 467 468: get_assignment 469 line_buffer .addr @ line_buffer .len @ + to end_of_line 470 line_buffer .addr @ to line_pointer 471 ['] white_space_1 to parsing_function 472 begin 473 end_of_line? 0= 474 while 475 parsing_function execute 476 repeat 477 parsing_function ['] comment = 478 parsing_function ['] white_space_1 = 479 parsing_function ['] white_space_4 = 480 or or 0= if syntax_error throw then 481; 482 483\ Process line 484 485: assignment_type? ( addr len -- flag ) 486 name_buffer .addr @ name_buffer .len @ 487 compare 0= 488; 489 490: suffix_type? ( addr len -- flag ) 491 name_buffer .len @ over <= if 2drop false exit then 492 name_buffer .len @ over - name_buffer .addr @ + 493 over compare 0= 494; 495 496: loader_conf_files? 497 s" loader_conf_files" assignment_type? 498; 499 500: verbose_flag? 501 s" verbose_loading" assignment_type? 502; 503 504: execute? 505 s" exec" assignment_type? 506; 507 508: module_load? 509 load_module_suffix suffix_type? 510; 511 512: module_loadname? 513 module_loadname_suffix suffix_type? 514; 515 516: module_type? 517 module_type_suffix suffix_type? 518; 519 520: module_args? 521 module_args_suffix suffix_type? 522; 523 524: module_beforeload? 525 module_beforeload_suffix suffix_type? 526; 527 528: module_afterload? 529 module_afterload_suffix suffix_type? 530; 531 532: module_loaderror? 533 module_loaderror_suffix suffix_type? 534; 535 536: set_conf_files 537 conf_files .addr @ ?dup if 538 free-memory 539 then 540 value_buffer .addr @ c@ [char] " = if 541 value_buffer .addr @ char+ value_buffer .len @ 2 chars - 542 else 543 value_buffer .addr @ value_buffer .len @ 544 then 545 strdup 546 conf_files .len ! conf_files .addr ! 547; 548 549: append_to_module_options_list ( addr -- ) 550 module_options @ 0= if 551 dup module_options ! 552 last_module_option ! 553 else 554 dup last_module_option @ module.next ! 555 last_module_option ! 556 then 557; 558 559: set_module_name ( addr -- ) 560 name_buffer .addr @ name_buffer .len @ 561 strdup 562 >r over module.name .addr ! 563 r> swap module.name .len ! 564; 565 566: yes_value? 567 value_buffer .addr @ value_buffer .len @ 568 2dup s' "YES"' compare >r 569 2dup s' "yes"' compare >r 570 2dup s" YES" compare >r 571 s" yes" compare r> r> r> and and and 0= 572; 573 574: find_module_option ( -- addr | 0 ) 575 module_options @ 576 begin 577 dup 578 while 579 dup module.name dup .addr @ swap .len @ 580 name_buffer .addr @ name_buffer .len @ 581 compare 0= if exit then 582 module.next @ 583 repeat 584; 585 586: new_module_option ( -- addr ) 587 sizeof module allocate if out_of_memory throw then 588 dup sizeof module erase 589 dup append_to_module_options_list 590 dup set_module_name 591; 592 593: get_module_option ( -- addr ) 594 find_module_option 595 ?dup 0= if new_module_option then 596; 597 598: set_module_flag 599 name_buffer .len @ load_module_suffix nip - name_buffer .len ! 600 yes_value? get_module_option module.flag ! 601; 602 603: set_module_args 604 name_buffer .len @ module_args_suffix nip - name_buffer .len ! 605 get_module_option module.args 606 dup .addr @ ?dup if free-memory then 607 value_buffer .addr @ value_buffer .len @ 608 over c@ [char] " = if 609 2 chars - swap char+ swap 610 then 611 strdup 612 >r over .addr ! 613 r> swap .len ! 614; 615 616: set_module_loadname 617 name_buffer .len @ module_loadname_suffix nip - name_buffer .len ! 618 get_module_option module.loadname 619 dup .addr @ ?dup if free-memory then 620 value_buffer .addr @ value_buffer .len @ 621 over c@ [char] " = if 622 2 chars - swap char+ swap 623 then 624 strdup 625 >r over .addr ! 626 r> swap .len ! 627; 628 629: set_module_type 630 name_buffer .len @ module_type_suffix nip - name_buffer .len ! 631 get_module_option module.type 632 dup .addr @ ?dup if free-memory then 633 value_buffer .addr @ value_buffer .len @ 634 over c@ [char] " = if 635 2 chars - swap char+ swap 636 then 637 strdup 638 >r over .addr ! 639 r> swap .len ! 640; 641 642: set_module_beforeload 643 name_buffer .len @ module_beforeload_suffix nip - name_buffer .len ! 644 get_module_option module.beforeload 645 dup .addr @ ?dup if free-memory then 646 value_buffer .addr @ value_buffer .len @ 647 over c@ [char] " = if 648 2 chars - swap char+ swap 649 then 650 strdup 651 >r over .addr ! 652 r> swap .len ! 653; 654 655: set_module_afterload 656 name_buffer .len @ module_afterload_suffix nip - name_buffer .len ! 657 get_module_option module.afterload 658 dup .addr @ ?dup if free-memory then 659 value_buffer .addr @ value_buffer .len @ 660 over c@ [char] " = if 661 2 chars - swap char+ swap 662 then 663 strdup 664 >r over .addr ! 665 r> swap .len ! 666; 667 668: set_module_loaderror 669 name_buffer .len @ module_loaderror_suffix nip - name_buffer .len ! 670 get_module_option module.loaderror 671 dup .addr @ ?dup if free-memory then 672 value_buffer .addr @ value_buffer .len @ 673 over c@ [char] " = if 674 2 chars - swap char+ swap 675 then 676 strdup 677 >r over .addr ! 678 r> swap .len ! 679; 680 681: set_environment_variable 682 name_buffer .len @ 683 value_buffer .len @ + 684 5 chars + 685 allocate if out_of_memory throw then 686 dup 0 ( addr -- addr addr len ) 687 s" set " strcat 688 name_buffer .addr @ name_buffer .len @ strcat 689 s" =" strcat 690 value_buffer .addr @ value_buffer .len @ strcat 691 ['] evaluate catch if 692 2drop free drop 693 set_error throw 694 else 695 free-memory 696 then 697; 698 699: set_verbose 700 yes_value? to verbose? 701; 702 703: execute_command 704 value_buffer .addr @ value_buffer .len @ 705 over c@ [char] " = if 706 2 chars - swap char+ swap 707 then 708 ['] evaluate catch if exec_error throw then 709; 710 711: process_assignment 712 name_buffer .len @ 0= if exit then 713 loader_conf_files? if set_conf_files exit then 714 verbose_flag? if set_verbose exit then 715 execute? if execute_command exit then 716 module_load? if set_module_flag exit then 717 module_loadname? if set_module_loadname exit then 718 module_type? if set_module_type exit then 719 module_args? if set_module_args exit then 720 module_beforeload? if set_module_beforeload exit then 721 module_afterload? if set_module_afterload exit then 722 module_loaderror? if set_module_loaderror exit then 723 set_environment_variable 724; 725 726: free_buffers 727 line_buffer .addr @ dup if free then 728 name_buffer .addr @ dup if free then 729 value_buffer .addr @ dup if free then 730 or or if free_error throw then 731; 732 733: reset_assignment_buffers 734 0 name_buffer .addr ! 735 0 name_buffer .len ! 736 0 value_buffer .addr ! 737 0 value_buffer .len ! 738; 739 740\ Higher level file processing 741 742: process_conf 743 begin 744 end_of_file? 0= 745 while 746 reset_assignment_buffers 747 read_line 748 get_assignment 749 ['] process_assignment catch 750 ['] free_buffers catch 751 swap throw throw 752 repeat 753; 754 755: create_null_terminated_string { addr len -- addr' len } 756 len char+ allocate if out_of_memory throw then 757 >r 758 addr r@ len move 759 0 r@ len + c! 760 r> len 761; 762 763\ Interface to loading conf files 764 765: load_conf ( addr len -- ) 766 0 to end_of_file? 767 0 to read_buffer_ptr 768 create_null_terminated_string 769 over >r 770 fopen fd ! 771 r> free-memory 772 fd @ -1 = if open_error throw then 773 ['] process_conf catch 774 fd @ fclose 775 throw 776; 777 778: initialize_support 779 0 read_buffer .addr ! 780 0 conf_files .addr ! 781 0 module_options ! 782 0 last_module_option ! 783 0 to verbose? 784; 785 786: print_line 787 line_buffer .addr @ line_buffer .len @ type cr 788; 789 790: print_syntax_error 791 line_buffer .addr @ line_buffer .len @ type cr 792 line_buffer .addr @ 793 begin 794 line_pointer over <> 795 while 796 bl emit 797 char+ 798 repeat 799 drop 800 ." ^" cr 801; 802 803\ Depuration support functions 804 805only forth definitions also support-functions 806 807: test-file 808 ['] load_conf catch dup . 809 syntax_error = if cr print_syntax_error then 810; 811 812: show-module-options 813 module_options @ 814 begin 815 ?dup 816 while 817 ." Name: " dup module.name dup .addr @ swap .len @ type cr 818 ." Path: " dup module.loadname dup .addr @ swap .len @ type cr 819 ." Type: " dup module.type dup .addr @ swap .len @ type cr 820 ." Flags: " dup module.args dup .addr @ swap .len @ type cr 821 ." Before load: " dup module.beforeload dup .addr @ swap .len @ type cr 822 ." After load: " dup module.afterload dup .addr @ swap .len @ type cr 823 ." Error: " dup module.loaderror dup .addr @ swap .len @ type cr 824 ." Status: " dup module.flag @ if ." Load" else ." Don't load" then cr 825 module.next @ 826 repeat 827; 828 829only forth also support-functions definitions 830 831\ Variables used for processing multiple conf files 832 833string current_file_name 834variable current_conf_files 835 836\ Indicates if any conf file was succesfully read 837 8380 value any_conf_read? 839 840\ loader_conf_files processing support functions 841 842: set_current_conf_files 843 conf_files .addr @ current_conf_files ! 844; 845 846: get_conf_files 847 conf_files .addr @ conf_files .len @ strdup 848; 849 850: recurse_on_conf_files? 851 current_conf_files @ conf_files .addr @ <> 852; 853 854: skip_leading_spaces { addr len ptr -- addr len ptr' } 855 begin 856 ptr len = if addr len ptr exit then 857 addr ptr + c@ bl = 858 while 859 ptr char+ to ptr 860 repeat 861 addr len ptr 862; 863 864: get_file_name { addr len ptr -- addr len ptr' addr' len' || 0 } 865 ptr len = if 866 addr free abort" Fatal error freeing memory" 867 0 exit 868 then 869 ptr >r 870 begin 871 addr ptr + c@ bl <> 872 while 873 ptr char+ to ptr 874 ptr len = if 875 addr len ptr addr r@ + ptr r> - exit 876 then 877 repeat 878 addr len ptr addr r@ + ptr r> - 879; 880 881: get_next_file ( addr len ptr -- addr len ptr' addr' len' | 0 ) 882 skip_leading_spaces 883 get_file_name 884; 885 886: set_current_file_name 887 over current_file_name .addr ! 888 dup current_file_name .len ! 889; 890 891: print_current_file 892 current_file_name .addr @ current_file_name .len @ type 893; 894 895: process_conf_errors 896 dup 0= if true to any_conf_read? drop exit then 897 >r 2drop r> 898 dup syntax_error = if 899 ." Warning: syntax error on file " print_current_file cr 900 print_syntax_error drop exit 901 then 902 dup set_error = if 903 ." Warning: bad definition on file " print_current_file cr 904 print_line drop exit 905 then 906 dup read_error = if 907 ." Warning: error reading file " print_current_file cr drop exit 908 then 909 dup open_error = if 910 verbose? if ." Warning: unable to open file " print_current_file cr then 911 drop exit 912 then 913 dup free_error = abort" Fatal error freeing memory" 914 dup out_of_memory = abort" Out of memory" 915 throw \ Unknown error -- pass ahead 916; 917 918\ Process loader_conf_files recursively 919\ Interface to loader_conf_files processing 920 921: include_conf_files 922 set_current_conf_files 923 get_conf_files 0 924 begin 925 get_next_file ?dup 926 while 927 set_current_file_name 928 ['] load_conf catch 929 process_conf_errors 930 recurse_on_conf_files? if recurse then 931 repeat 932; 933 934\ Module loading functions 935 936: load_module? 937 module.flag @ 938; 939 940: load_parameters ( addr -- addr addrN lenN ... addr1 len1 N ) 941 dup >r 942 r@ module.args .addr @ r@ module.args .len @ 943 r@ module.loadname .len @ if 944 r@ module.loadname .addr @ r@ module.loadname .len @ 945 else 946 r@ module.name .addr @ r@ module.name .len @ 947 then 948 r@ module.type .len @ if 949 r@ module.type .addr @ r@ module.type .len @ 950 s" -t " 951 4 ( -t type name flags ) 952 else 953 2 ( name flags ) 954 then 955 r> drop 956; 957 958: before_load ( addr -- addr ) 959 dup module.beforeload .len @ if 960 dup module.beforeload .addr @ over module.beforeload .len @ 961 ['] evaluate catch if before_load_error throw then 962 then 963; 964 965: after_load ( addr -- addr ) 966 dup module.afterload .len @ if 967 dup module.afterload .addr @ over module.afterload .len @ 968 ['] evaluate catch if after_load_error throw then 969 then 970; 971 972: load_error ( addr -- addr ) 973 dup module.loaderror .len @ if 974 dup module.loaderror .addr @ over module.loaderror .len @ 975 evaluate \ This we do not intercept so it can throw errors 976 then 977; 978 979: pre_load_message ( addr -- addr ) 980 verbose? if 981 dup module.name .addr @ over module.name .len @ type 982 ." ..." 983 then 984; 985 986: load_error_message verbose? if ." failed!" cr then ; 987 988: load_succesful_message verbose? if ." ok" cr then ; 989 990: load_module 991 load_parameters load 992; 993 994: process_module ( addr -- addr ) 995 pre_load_message 996 before_load 997 begin 998 ['] load_module catch if 999 dup module.loaderror .len @ if 1000 load_error \ Command should return a flag! 1001 else 1002 load_error_message true \ Do not retry 1003 then 1004 else 1005 after_load 1006 load_succesful_message true \ Succesful, do not retry 1007 then 1008 until 1009; 1010 1011: process_module_errors ( addr ior -- ) 1012 dup before_load_error = if 1013 drop 1014 ." Module " 1015 dup module.name .addr @ over module.name .len @ type 1016 dup module.loadname .len @ if 1017 ." (" dup module.loadname .addr @ over module.loadname .len @ type ." )" 1018 then 1019 cr 1020 ." Error executing " 1021 dup module.beforeload .addr @ over module.afterload .len @ type cr 1022 abort 1023 then 1024 1025 dup after_load_error = if 1026 drop 1027 ." Module " 1028 dup module.name .addr @ over module.name .len @ type 1029 dup module.loadname .len @ if 1030 ." (" dup module.loadname .addr @ over module.loadname .len @ type ." )" 1031 then 1032 cr 1033 ." Error executing " 1034 dup module.afterload .addr @ over module.afterload .len @ type cr 1035 abort 1036 then 1037 1038 throw \ Don't know what it is all about -- pass ahead 1039; 1040 1041\ Module loading interface 1042 1043: load_modules ( -- ) ( throws: abort & user-defined ) 1044 module_options @ 1045 begin 1046 ?dup 1047 while 1048 dup load_module? if 1049 ['] process_module catch 1050 process_module_errors 1051 then 1052 module.next @ 1053 repeat 1054; 1055 1056\ Additional functions used in "start" 1057 1058: initialize ( addr len -- ) 1059 initialize_support 1060 strdup conf_files .len ! conf_files .addr ! 1061; 1062 1063: load_kernel ( -- ) ( throws: abort ) 1064 s" load ${kernel} ${kernel_options}" ['] evaluate catch 1065 if s" echo Unable to load kernel: ${kernel_name}" evaluate abort then 1066; 1067 1068\ Go back to straight forth vocabulary 1069 1070only forth also definitions 1071 1072