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