1 ;; Native x86 GNU/Linux Forth System, Direct Threaded Code
3 ;; Copyright (C) 2020 Ketmar Dark // Invisible Vector
5 ;; This program is free software: you can redistribute it and/or modify
6 ;; it under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation, version 3 of the License ONLY.
9 ;; This program is distributed in the hope that it will be useful,
10 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ;; GNU General Public License for more details.
14 ;; You should have received a copy of the GNU General Public License
15 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
16 include "k8utils.inca"
18 format ELF executable
3
19 entry urforth_entry_point
21 segment interpreter readable
22 db "/lib/ld-linux.so.2",0
25 segment dynamic readable
26 ; the only thing we need is .so management functions, so we'll create
27 ; a very simple import table for "libdl.so", with 3 imports:
28 ; "dlopen", "dlclose", "dlsym"
41 ELF32_SYM_SIZE
= 4+4+4+1+1+2
44 ; create minimalistic Elf header with libdl.so import
45 dd DT_NEEDED
,elfhead_str_libdl
-elfhead_strtab
46 dd DT_STRTAB
,elfhead_strtab
47 dd DT_STRSZ
,elfhead_strsz
48 dd DT_SYMTAB
,elfhead_symtab
49 dd DT_SYMENT
,ELF32_SYM_SIZE
51 dd DT_RELSZ
,elfhead_relsz
52 dd DT_RELENT
,ELF32_REL_SIZE
53 dd DT_HASH
,elfhead_hash
56 segment executable readable writeable
57 urforth_code_base_addr
= $$
and 0xfffff000
60 ; NULL import, should always be here
61 dd elfhead_str_null
-elfhead_strtab
64 db 0x12 ; (STB_GLOBAL<<4)|STT_FUNC
68 dd elfhead_str_dlopen
-elfhead_strtab
71 db 0x12 ; (STB_GLOBAL<<4)|STT_FUNC
75 dd elfhead_str_dlclose
-elfhead_strtab
78 db 0x12 ; (STB_GLOBAL<<4)|STT_FUNC
82 dd elfhead_str_dlsym
-elfhead_strtab
85 db 0x12 ; (STB_GLOBAL<<4)|STT_FUNC
91 elfhead_str_libdl
db "libdl.so",0
92 elfhead_str_dlopen
db "dlopen",0
93 elfhead_str_dlclose
db "dlclose",0
94 elfhead_str_dlsym
db "dlsym",0
95 elfhead_strsz
= $
-elfhead_strtab
97 ; importer will use this to fix relocations
101 dd 0x0101 ; high bit is symbol index, low bit is R_386_32
104 dd 0x0201 ; high bit is symbol index, low bit is R_386_32
107 dd 0x0301 ; high bit is symbol index, low bit is R_386_32
108 elfhead_relsz
= $
-elfhead_rel
110 ; fake import hash table with one bucket
112 dd 1,4 ; size of bucket and size of chain
113 dd 0 ; fake bucket, just one hash value
114 times
4 dd % ; chain for all symbol table entries
117 elfhead_size
= $
-urforth_code_base_addr
118 ;display_hex elfhead_size
121 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
122 ;; Forth system wants it like this
123 ;segment readable writeable executable
124 ; ld.so will add import symbol offsets here
130 elfhead_implen
= elfhead_impend
-elfhead_impstart
135 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
136 include "urforth_dprint.asm"
139 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
141 ;; use `urcall urforth_bp` or `ur_bp` for manual breakpoint
143 URFORTH_EXTRA_STACK_CHECKS
= 0
146 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
147 URFORTH_ALIGN_HEADERS
= 0
155 TTYLOW_ALLOW_BUFFERED
= 0
158 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
162 ;; esi: instruction pointer
165 ;; direction flag must NOT be set!
168 ;; WARNING! simply changing this definitions won't work!
169 ;; they are here just to make the code looks better!
176 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
177 if WLIST_HASH_BITS
< 0
178 err
"invalid WLIST_HASH_BITS: should be [0..8]"
181 if WLIST_HASH_BITS
> 8
182 err
"invalid WLIST_HASH_BITS: should be [0..8]"
185 WLIST_HASH_CELLS
= 1 shl WLIST_HASH_BITS
186 WLIST_HASH_BYTES
= WLIST_HASH_CELLS
*4
187 WLIST_HASH_MASK
= (1 shl WLIST_HASH_BITS
)-1
189 include "urforth0_mac.asm"
190 include "urforth0_mac_hlconds.asm"
192 ;; TIB buffer is placed after the main memory allocated with BRK
193 ;; so we will overallocate a little
195 ;;;urword_var "(TIB-BUFFER)",par_tib_buffer
197 ;;;; for debug, i'll put counter here
198 ;;;; this also used as compile-time structured stack
205 ;;;urfhi_csp = fdata_tib_end
208 urword_const
"(ELF-EP)",par_elf_ep
,urforth_entry_point
212 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
213 urword_code
"(URFORTH-SEGFAULT-CODEBLOCK)",par_urforth_nocall_segfault
216 include "urforth0_segfault.asm"
220 urword_code
"(URFORTH-DEBUGGER-CODEBLOCK)",par_urforth_nocall_debugger
223 include "urforth0_dbg.asm"
225 urforth_next_ptr: dd urforth_next_normal
233 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
234 urword_code
"(URFORTH-STARTUP-CODEBLOCK)",par_urforth_nocall_startup
240 ld
[fval_argc_data
],ecx
244 ld
[fconst_argv_data
],eax
246 inc ecx ; skip final 0 argument
250 ld
[fconst_envp_data
],eax
253 ; push several values for safety (so data stack underflow won't destroy cli args and such)
260 ; allocate memory for dictionary
261 ; binary size should be equal to DP
262 ld
eax,[fval_init_mem_size_data
]
264 ;; EAX: start address
266 ld
[fvar_dpend_data
],ebx
269 ; allocate memory for TIB
270 ld
eax,[fval_par_default_tib_size_data
]
271 ; some more bytes for safety
274 ;; EAX: start address
276 add eax,32 ; reserve some TIB memory for various needs
277 ld
[fval_par_default_tib_data
],eax
279 ; allocate memory for PAD
280 ld
eax,[fconst_pad_area_resv_size_data
]
281 add eax,[fconst_pad_area_size_data
]
283 ;; EAX: start address
285 add eax,[fconst_pad_area_resv_size_data
]
286 ld
[fvar_pad_area_data
],eax
288 ; allocate memory for debug buffer
289 ld
eax,[fval_dbuf_size_data
]
291 ;; EAX: start address
293 ld
[fval_dbuf_addr_data
],eax
295 ; allocate memory for tty buffer
296 if TTYLOW_ALLOW_BUFFERED
297 ld
dword [fval_par_ttylow_buffer_pos_data
],0
298 ld
dword [fval_par_ttylow_buffer_addr_data
],0
299 cp
dword [fval_par_ttylow_use_buffer_data
],1
301 ld
eax,[fval_par_ttylow_buffer_size_data
]
305 ;; EAX: start address
307 ld
[fval_par_ttylow_buffer_addr_data
],eax
310 ; allocate memory for current file we are interpreting
311 ld
eax,[fconst_par_tib_curr_fname_size_data
]
313 ;; EAX: start address
315 ld
[fval_par_tib_curr_fname_data
],eax
316 ld
dword [eax],0 ; no file
318 ; allocate memory for debugger/segfault stack
321 ;; EAX: start address
325 ld
[urfsegfault_stack_bottom
],ebx
327 ; prepare data stack (use "push" to trigger stack pages allocation)
328 mov edx,esp ; save current stack pointer
334 loop .dstack_clear_loop
336 ; prepare return stack (use "push" to trigger stack pages allocation)
337 mov ERP
,esp ; setup initial return stack pointer
341 loop .rstack_clear_loop
347 mov [fvar_sp0_data
],esp
348 mov [fvar_rp0_data
],ERP
350 call urforth_setup_segfault_handler
352 ; and start execution
353 jmp fword_cold_firsttime
355 ;; allocate memory via BRK
359 ;; EAX: start address (first byte)
360 ;; EBX: end address (*after* the last byte)
361 ;; other registers and flags are dead (except ESP)
363 ; save size (overallocate a little, for safety)
367 ; get current BRK address
372 ; [esp]: start address
373 ; [esp+4]: alloc size
380 ld
ebx,eax ; EBX=end address
382 ld
eax,[esp] ; start address
383 add eax,[esp+4] ; alloc size
388 ; calc end address, to be precise
390 ; remove overallocated safety margin from end address
396 ; print error and exit
399 mov ecx,.fatal_oom_msg
400 mov edx,.fatal_oom_msg_len
407 .
fatal_oom_msg: db "FATAL: out of memory!",10
408 .fatal_oom_msg_len
= $
-.fatal_oom_msg
412 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
413 urword_code
"(URFORTH-DOFORTH-CODEBLOCK)",par_urforth_nocall_doforth
422 urword_code
"(URFORTH-DOCONST-CODEBLOCK)",par_urforth_nocall_doconst
431 urword_code
"(URFORTH-DOVAR-CODEBLOCK)",par_urforth_nocall_dovar
439 urword_code
"(URFORTH-DOVALUE-CODEBLOCK)",par_urforth_nocall_dovalue
449 urword_code
"(URFORTH-DODEFER-CODEBLOCK)",par_urforth_nocall_dodefer
458 urword_code
"(URFORTH-DODOES-CODEBLOCK)",par_urforth_nocall_dodoes
462 ; pfa is on the stack
470 urword_code
"(URFORTH-DOOVERRIDE-CODEBLOCK)",par_urforth_nocall_dooverride
481 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
482 ;; use this subroutine to call a forth word from a machine code
483 ;; EAX should point to the cfa
484 ;; TOS and other things should be set accordingly
485 ;; direction flag should be cleared
486 ;; no registers are preserved
488 ; move mc return address to rstack
491 ; push current EIP to rstack
494 mov EIP,ur_mc_fcall_justexit
495 ; turn off debugger temporarily, because the debugger is using this
497 ld FREEREG
,[urfdebug_active_flag
]
499 ; special flag, means "no breakpoint checks"
500 ld
dword [urfdebug_active_flag
],0xffffffff
502 ; and execute the word
504 ur_mc_fcall_justexit:
505 dd ur_mc_fcall_fakeret_code
506 ur_mc_fcall_fakeret_code:
507 ; restore debugger state
510 ld
dword [urfdebug_active_flag
],FREEREG
514 ; restore return address
520 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
522 urword_code
"(URFORTH-BP)",urforth_bp
524 call urfdebug_activate_it
530 urword_alias
"DBG",activate_debugger
,urforth_bp
532 urword_code
"DBG",activate_debugger
538 urword_const
"(HAS-DEBUGGER?)",par_has_debugger
,1
539 urword_const
"(NEXT-REF-ADDR)",par_next_ref_addr
,urforth_next_ptr
541 urword_const
"(HAS-DEBUGGER?)",par_has_debugger
,0
542 ;; so i can avoid conditional compilation
544 urword_const
"(NEXT-REF-ADDR)",par_next_ref_addr
,0
548 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
549 include "urforth0_w_syscall.asm"
550 include "urforth0_w_termio_low.asm"
552 urword_const
"TRUE",true
,1
553 urword_const
"FALSE",false
,0
555 urword_const
"CELL",cell
,4
556 urword_const
"BL",bl,32
558 urword_value
"(DEBUGGER-ON-STACK-UNDERFLOW)",par_dbg_on_sunder
,0
561 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
562 include "urforth0_w_litbase.asm"
563 include "urforth0_w_stack.asm"
564 include "urforth0_w_peekpoke.asm"
565 include "urforth0_w_exceptions.asm"
566 include "urforth0_w_math_base.asm"
567 include "urforth0_w_math_muldiv.asm"
568 include "urforth0_w_math_compare.asm"
569 include "urforth0_w_math_dbl_min.asm"
571 include "urforth0_w_osface.asm"
573 include "urforth0_w_countstr.asm"
574 include "urforth0_w_cstr_hash.asm"
576 include "urforth0_w_termio_high.asm"
578 include "urforth0_w_wordlist.asm"
580 include "urforth0_w_dp.asm"
581 include "urforth0_w_temp_pool.asm"
582 include "urforth0_w_dbginfo.asm"
584 include "urforth0_w_tib.asm"
586 include "urforth0_w_numbers.asm"
587 include "urforth0_w_parse.asm"
589 include "urforth0_w_errors.asm"
591 include "urforth0_w_compiler_helpers.asm"
592 include "urforth0_w_compiler_mid.asm"
594 include "urforth0_w_create_and_vocs.asm"
596 include "urforth0_w_save.asm"
599 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
600 urword_forth
"BRK-ALLOC",brk_alloc
603 UF dup
0less errid_out_of_memory qerror
604 UF par_brkq
;; ( size addr )
608 UF over
+ dup par_sbrk
609 UF uless errid_out_of_memory qerror
614 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
615 urword_forth
"ARGV-STR",argv_str
616 ;; ( argnum -- addr count )
617 UF dup
0 less over argc greatequ
or
621 UF
4 umul argv
+ @ zcount
626 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
627 urword_forth
"INTERPRET",interpret
637 UF errid_stack_underflow error
638 UF
1 nbye
;; just in case
645 UF drop exit
;; replace with "BREAK"
654 ;; for default TIB (i.e. terminal session), "QUIT" will do it for us
657 UF exit
;; replace with "BREAK"
661 UF exit
;; replace with "BREAK"
672 UF dup cfa2nfa nfa2ffa ffapeek
675 UF state @
0 equal
; !0 means "compile"
685 ; unknown word, try to parse it as a number
691 UF
type errid_unknown_word error
698 urword_forth
".OK",dotok
703 UF errid_stack_underflow error_message
705 UF false rpush
;; "bracket opened" flag
711 UF base @ rpush
0 dotr rpop base
!
713 ; show BASE if it is not decimal
721 UF pardottype
"; base:" base @ dup rpush decimal
0 dotr rpop base
!
729 urword_forth
"QUIT",quit
733 ;UF state 0poke ; nope, we want multiline definitions to work
736 ; there is no reason to keep debug info activated
738 UF tload_verbose_default
749 urword_forth
"EVALUATE",evaluate
750 ;; ( addr count -- ... )
753 UF par_tibstate_rpush
766 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
767 urword_forth
"(COLD-BUILD-RC-NAME)",par_cold_build_rc_name
769 UF
0 argv_str str_extract_path qdup
773 UF par_tload_fnpad c4s_copy_ac
774 UF
0 argv_str str_extract_base_name par_tload_fnpad c4s_cat_ac
775 UF strlit
".rc" par_tload_fnpad c4s_cat_ac
776 UF par_tload_fnpad c4s_zterm
780 urword_forth
"(COLD-LOAD-RC)",par_cold_load_rc
782 ;; check for "--naked"
787 UF i argv_str strlit
"--naked" strequ_ci
792 UF i argv_str strlit
"--verbose-libs" strequ_ci
795 urto tload_verbose_libs
797 UF i argv_str strlit
"--quiet-libs" strequ_ci
800 urto tload_verbose_libs
802 UF i argv_str strlit
"--verbose-rc" strequ_ci
805 urto tload_verbose_rc
807 UF i argv_str strlit
"--quiet-rc" strequ_ci
810 urto tload_verbose_rc
812 UF i argv_str strlit
"--eval" strequ_ci
816 UF i argv_str strlit
"-e" strequ_ci
822 ;; no "--naked", load .rc
823 UF par_cold_build_rc_name
824 UF par_tload_fnpad count par_is_file
826 UF tload_verbose rpush
830 UF par_cold_build_rc_name
832 UF par_tload_fnpad here c4s_copy
840 urword_forth
"CLI-ARG-SKIP",arg_skip
845 urword_forth
"(COLD-CLI)",par_cold_cli
847 ;; load "urforth.rc" (if present)
850 ;; don't use DO ... LOOP here, use CLI-ARG-NEXT
852 UF arg_next argc less
853 UF arg_next
0great
and
856 UF arg_next argv_str arg_skip
863 UF over cpeek
45 equal
865 ;; "-e" or "--eval" ?
866 UF
2dup strlit
"-e" strequ_ci rpush
867 UF strlit
"--eval" strequ_ci rpop
or
868 ;; note that argv is dropped here
871 UF arg_next argv_str arg_skip evaluate
873 ;; unknown "-..." args are skipped
883 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
884 urword_forth
"(.BANNER)",par_dot_banner
886 UF pardottype
"UrForth v0.0.1-beta" cr
890 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
891 ;; called to print a banner after processing CLI args
892 urword_defer
".BANNER",dot_banner
,par_dot_banner
894 ;; called (once!) to process CLI args
895 urword_defer
"PROCESS-CLI-ARGS",process_cli_args
,par_cold_cli
897 ;; main program loop, should never return
898 urword_defer
"MAIN-LOOP",main_loop
,quit
;; this word should never return
900 ;; default abort calls ABORT-CLEANUP, and then MAIN-LOOP
901 urword_defer
"ABORT-CLEANUP",abort_cleanup
,par_abort_cleanup
903 ;; ye good olde ABORT, vectorized
904 urword_defer
"ABORT",abort
,par_abort
;; this word should never return
906 ;; called when the system needs to abort with error message
908 urword_defer
"ERROR",error
,par_error
;; this word should never return
911 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
912 urword_forth
"(COLD-FIRSTTIME)",cold_firsttime
915 UF sys_gettickcount_init
917 ;; just in case it returns
922 urword_forth
"COLD",cold
925 UF temp_pool_reset tib_reset
926 UF tload_verbose_default
931 UF process_cli
0poke
; no more
936 ;; just in case it returns
941 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
942 urword_value
"TLOAD-VERBOSE-LIBS",tload_verbose_libs
,1
943 urword_value
"TLOAD-VERBOSE",tload_verbose
,1
944 urword_value
"TLOAD-VERBOSE-DEFAULT",tload_verbose_default
,1
945 urword_value
"TLOAD-VERBOSE-RC",tload_verbose_rc
,0
948 urword_forth
"(TLOAD-FNPAD)",par_tload_fnpad
954 urword_forth
"(TLOAD-OPEN-ADD-ALL)",par_tload_open_add_all
957 UF par_tload_fnpad c4s_zterm
958 UF par_tload_fnpad count par_is_dir
960 ;; add trailing slash
961 UF par_tload_fnpad count
+ 1dec cpeek
47 equal
963 UF strlit
"/" par_tload_fnpad c4s_cat_ac
965 UF strlit
"all.f" par_tload_fnpad c4s_cat_ac
966 UF par_tload_fnpad c4s_zterm
970 urword_forth
"(TLOAD-OPEN)",par_tload_open
972 ;; ( addr count -- fd )
973 ;; also, leaves file name as c4str at PAD
976 UF
2drop errid_file_not_found error
979 ;; ! will be replaced with binary path
980 UF over cpeek
33 equal
982 UF
0 argv_str str_extract_path qdup
986 UF par_tload_fnpad c4s_copy_ac
987 UF
1dec swap
1inc swap
988 UF par_tload_fnpad c4s_cat_ac
990 UF par_last_tload_path
993 UF par_last_tload_path par_tload_fnpad c4s_copy
994 ;; ( addr count | addr count )
995 UF par_tload_fnpad c4s_cat_ac
996 UF par_tload_open_add_all
997 UF par_tload_fnpad count
998 ;; ( addr count | addr count )
999 UF o_rdonly
0 par_fopen
1006 UF par_tload_fnpad c4s_copy_ac
1007 UF par_tload_open_add_all
1009 UF par_tload_open_add_all
1010 UF par_tload_fnpad count o_rdonly
0 par_fopen
1013 UF drop endcr pardottype
"file: " par_tload_fnpad count
type errid_file_not_found error
1018 urword_forth
"TLOAD",tload
1019 ;; ( addr count -- )
1020 ;; load forth source file
1021 ;; this loads the whole file into temp pool
1025 UF endcr pardottype
"loading: " par_tload_fnpad count
type cr
1029 UF
0 seek_end rpeek par_lseek
1033 UF drop rpop par_fclose drop
1034 UF errid_file_read_error error
1036 ; seek back to file start
1038 UF
0 seek_set rpeek par_lseek
1040 UF drop rpop par_fclose drop
1041 UF errid_file_read_error error
1043 ; allocate temp pool space
1044 ; this will also take care about too big files
1045 ; FIXME: the file won't be closed if it is too big!
1046 UF rpop temp_pool_mark rpush rpush
1047 ;; ( size | poolmark fd )
1048 UF dup cellinc temp_pool_alloc
1049 ;; ( size addr | poolmark fd )
1050 ; write zeroes at the end (just in case)
1053 UF
2dup swap rpeek par_fread
1054 ;; ( size addr readbytes | poolmark fd )
1056 UF rpop par_fclose drop
1057 ;; ( size addr readbytes | poolmark )
1058 ;; ( addr readbytes | poolmark )
1059 UF rot over
- errid_file_read_error qerror
1060 ;; ( addr readbytes | poolmark )
1061 UF par_tibstate_rpush
1066 ;; ( | poolmark tibstate... )
1067 ;; UF par_tload_fnpad count type cr
1069 UF par_tload_fnpad count str_extract_path
1075 UF dup cellinc temp_pool_alloc
1076 UF par_last_tload_path rpush
1077 urto par_last_tload_path
1078 UF par_last_tload_path c4s_copy_ac
1079 ;; UF par_last_tload_path count type cr
1080 UF cell temp_pool_alloc rpop swap poke
1081 ;; save current file name, and replace it
1082 UF par_tib_curr_fname count_only cellinc temp_pool_alloc
1083 UF rpush
;; old fname at rstack
1084 UF par_tib_curr_fname rpeek over count_only cellinc move
1085 UF par_tload_fnpad par_tib_curr_fname over count_only cellinc move
1088 ;; restore old fname
1089 UF rpop par_tib_curr_fname over count_only cellinc move
1091 UF par_last_tload_path celldec peek
1092 urto par_last_tload_path
1093 UF par_tibstate_rpop
1094 UF rpop temp_pool_release
1095 ;UF pardottype "done!" cr
1100 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1101 urword_code
"NOOP",noop
1106 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1107 urword_const
"WLIST-HASH-BITS",wlist_hash_bits
,WLIST_HASH_BITS
1109 urword_var
"DP",dp
,fdata_freespace
1110 urword_var
"DP-END",dpend
,fdata_freespace
1111 urword_var
"DP-TEMP",dp_temp
,0 ;; this is used to temporarily change HERE
1112 urword_var
"SP0",sp0
,0
1113 urword_var
"RP0",rp0
,0
1115 ;; pad is allocated with BRK; "#PAD-AREA-RESV" is the space BEFORE "PAD-AREA"
1116 urword_var
"PAD-AREA",pad_area
,0 ;; will be set by startup code
1117 urword_const
"#PAD-AREA-RESV",pad_area_resv_size
,2048
1118 urword_const
"#PAD-AREA",pad_area_size
,4096
1120 urword_value
"(INIT-MEM-SIZE)",init_mem_size
,1024*1024*2
1123 urword_var
"STATE",state
,0
1125 urword_value
"ARGC",argc
,0
1126 urword_const
"ARGV",argv
,0
1127 urword_const
"ENVP",envp
,0
1129 urword_const
"URFORTH-LEVEL",par_urforth_level
,0
1131 ;; index of the next CLI arg to process
1132 ;; set to 0, negative or ARGC to stop further processing
1133 urword_value
"CLI-ARG-NEXT",arg_next
,1
1135 ;; this is so COLD will process CLI args only once
1136 urword_var
"(PROCESS-CLI-ARGS)",process_cli
,1
1139 ; mostly controls number parsing for now: "#" prefix is decimal in shit2012
1140 ; bit0: allow 2012 number prefix idiocity and number signs
1141 ; bit1: use non-FIG VARIABLE
1142 urword_value
"(SHIT-2012-IDIOCITY)",shit2012shit
,0
1146 urword_const
"(CODE-BASE-ADDR)",par_code_base_addr
,urforth_code_base_addr
1149 urword_const
"(CODE-IMPORTS-ADDR)",par_code_imports_addr
,elfhead_impstart
1152 urword_const
"(CODE-IMPORTS-SIZE)",par_code_imports_size
,elfhead_implen
1155 urword_const
"(CODE-IMPORTS-END-ADDR)",par_code_imports_end_addr
,elfhead_impend
1158 urword_const
"(CODE-ENTRY-ADDR)",par_code_entry_addr
,urforth_entry_point
1162 urforth_last_word_end_late
= $
1164 urforth_last_word_lfa_late
= urforth_last_word_lfa
1169 display
"UrForth words: "
1170 display_dec urforth_word_count
1176 ;; patch FORTH vocabulary hash table
1179 fht_patch_dpos
= forth_voc_hashtable
1181 while fht_patch_count
< WLIST_HASH_BYTES
1182 load fht_patch_v
dword from
urforth_forth_hashtable:urforth_forth_hash_offset
+fht_patch_count
1183 store
dword fht_patch_v at fht_patch_dpos
1184 fht_patch_count
= fht_patch_count
+4
1185 fht_patch_dpos
= fht_patch_dpos
+4
1190 ;; reserve BSS space, because BRK is completely broken on "modern" distros
1193 store
dword end_dict at fvar_dpend_data