From owner-freebsd-current@FreeBSD.ORG Sun Nov 11 00:53:14 2012 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id EC17B47C; Sun, 11 Nov 2012 00:53:14 +0000 (UTC) (envelope-from Devin.Teske@fisglobal.com) Received: from mx1.fisglobal.com (mx1.fisglobal.com [199.200.24.190]) by mx1.freebsd.org (Postfix) with ESMTP id 988AA8FC08; Sun, 11 Nov 2012 00:53:14 +0000 (UTC) Received: from smtp.fisglobal.com ([10.132.206.16]) by ltcfislmsgpa05.fnfis.com (8.14.5/8.14.5) with ESMTP id qAB0rDpP030457 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NOT); Sat, 10 Nov 2012 18:53:13 -0600 Received: from [10.0.0.101] (10.14.152.61) by smtp.fisglobal.com (10.132.206.16) with Microsoft SMTP Server (TLS) id 14.2.309.2; Sat, 10 Nov 2012 18:53:11 -0600 From: Devin Teske Content-Type: multipart/mixed; boundary="Apple-Mail=_A9909A1E-E6A9-43DD-8CBB-D93045B73375" Subject: HEADS UP: Forth Optimizations Date: Sat, 10 Nov 2012 16:53:10 -0800 Message-ID: To: MIME-Version: 1.0 (Apple Message framework v1283) X-Mailer: Apple Mail (2.1283) X-Originating-IP: [10.14.152.61] X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.9.8185, 1.0.431, 0.0.0000 definitions=2012-11-10_08:2012-11-10,2012-11-10,1970-01-01 signatures=0 Cc: Adrian Chadd , Devin Teske X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: Devin Teske List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 11 Nov 2012 00:53:15 -0000 --Apple-Mail=_A9909A1E-E6A9-43DD-8CBB-D93045B73375 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="us-ascii" Hi Everybody, Adrian (my co-mentor) wanted some additional eyes/names for review on a pat= ch I'm making to sys/boot/forth (patch attached as patch.txt). The patch makes no changes to user experience or functionality (but _does_ = fix one incident of stack leakage -- among other things). I wrote/tested this over a 2-day period using (as usual) VMware. I booted u= p several times (10+) and fiddled with many things (twiddled every knob, dr= opped to the loader prompt and went back to the menu several times, tried t= hrowing various options like boot_single=3D"YES" and boot_verbose=3D"YES" i= nto loader.conf(5) to make sure dynamic initialization is still working etc= .). The only thing I noticed after applying the patch was a drop in heap usage = (one of the goals of the patch), showing that the optimizations did their j= ob to make a leaner running menu. Also, the code is a lot more readable and= got slightly reduced in size during the process. Can someone help review this for the commit log? --=20 Devin =3D=3D=3D + This patch does not change user experience or functionality + Cleanup syntax, slim-down code, and make things more readable + Introduce new +c! operator and ilk to reduce heap usage/allocations + Fix a stack leak in [unused] cycle_menuitem function while we're here (required misconfiguration and/or missing environment vars to occur) + Add safemode_enabled? safemode_enable and safemode_disable functions + Add singleuser_enabled? singleuser_enable singleuser_disable functions + Add verbose_enabled? verbose_enable and verbose_disable functions + Centralize strings (also to reduce heap usage) PR: Submitted by: Reviewed by: Your_Name_Here, adrian (co-mentor) [pending his/your review] Approved by: adrian (co-mentor) [pending his approval] Obtained from: MFC after: Security: --This line, and those below, will be ignored-- > Description of fields to fill in above: 76 columns --| > PR: If a GNATS PR is affected by the change. > Submitted by: If someone else sent in the change. > Reviewed by: If someone else reviewed your modification. > Approved by: If you needed approval for this commit. > Obtained from: If the change is from a third party. > MFC after: N [day[s]|week[s]|month[s]]. Request a reminder email. > Security: Vulnerability reference (one per line) or description. > Empty fields above will be automatically removed. M forth/menu-commands.4th M forth/menu.4th _____________ The information contained in this message is proprietary and/or confidentia= l. If you are not the intended recipient, please: (i) delete the message an= d all copies; (ii) do not disclose, distribute or use the message in any ma= nner; and (iii) notify the sender immediately. In addition, please be aware= that any message addressed to our domain is subject to archiving and revie= w by persons other than the intended recipient. Thank you. --Apple-Mail=_A9909A1E-E6A9-43DD-8CBB-D93045B73375 Content-Disposition: attachment; filename="patch.txt" Content-Type: text/plain; name="patch.txt" Content-Transfer-Encoding: quoted-printable Index: menu-commands.4th =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- menu-commands.4th (revision 242835) +++ menu-commands.4th (working copy) @@ -31,6 +31,10 @@ include /boot/menusets.4th variable kernel_state variable root_state =20 +\=20 +\ ACPI +\=20 + : acpi_enable ( -- ) s" set acpi_load=3DYES" evaluate \ XXX deprecated but harmless s" set hint.acpi.0.disabled=3D0" evaluate @@ -58,9 +62,38 @@ variable root_state TRUE \ loop menu again ; =20 +\=20 +\ Safe Mode +\=20 + +: safemode_enabled? ( -- flag ) + s" kern.smp.disabled" getenv -1 <> dup if + swap drop ( c-addr flag -- flag ) + then +; + +: safemode_enable ( -- ) + s" set kern.smp.disabled=3D1" evaluate + s" set hw.ata.ata_dma=3D0" evaluate + s" set hw.ata.atapi_dma=3D0" evaluate + s" set hw.ata.wc=3D0" evaluate + s" set hw.eisa_slots=3D0" evaluate + s" set kern.eventtimer.periodic=3D1" evaluate + s" set kern.geom.part.check_integrity=3D0" evaluate +; + +: safemode_disable ( -- ) + s" kern.smp.disabled" unsetenv + s" hw.ata.ata_dma" unsetenv + s" hw.ata.atapi_dma" unsetenv + s" hw.ata.wc" unsetenv + s" hw.eisa_slots" unsetenv + s" kern.eventtimer.periodic" unsetenv + s" kern.geom.part.check_integrity" unsetenv +; + : init_safemode ( N -- N ) - s" kern.smp.disabled" getenv -1 <> if - drop ( n c-addr -- n ) \ unused + safemode_enabled? if toggle_menuitem ( n -- n ) then ; @@ -70,25 +103,10 @@ variable root_state =20 \ Now we're going to make the change effective =20 - s" toggle_stateN @" \ base name of toggle state var - -rot 2dup 12 + c! rot \ replace 'N' with ASCII numeral - - evaluate 0=3D if - s" kern.smp.disabled" unsetenv - s" hw.ata.ata_dma" unsetenv - s" hw.ata.atapi_dma" unsetenv - s" hw.ata.wc" unsetenv - s" hw.eisa_slots" unsetenv - s" kern.eventtimer.periodic" unsetenv - s" kern.geom.part.check_integrity" unsetenv + dup toggle_stateN @ 0=3D if + safemode_disable else - s" set kern.smp.disabled=3D1" evaluate - s" set hw.ata.ata_dma=3D0" evaluate - s" set hw.ata.atapi_dma=3D0" evaluate - s" set hw.ata.wc=3D0" evaluate - s" set hw.eisa_slots=3D0" evaluate - s" set kern.eventtimer.periodic=3D1" evaluate - s" set kern.geom.part.check_integrity=3D0" evaluate + safemode_enable then =20 menu-redraw @@ -96,9 +114,26 @@ variable root_state TRUE \ loop menu again ; =20 +\=20 +\ Single User Mode +\=20 + +: singleuser_enabled? ( -- flag ) + s" boot_single" getenv -1 <> dup if + swap drop ( c-addr flag -- flag ) + then +; + +: singleuser_enable ( -- ) + s" set boot_single=3DYES" evaluate +; + +: singleuser_disable ( -- ) + s" boot_single" unsetenv +; + : init_singleuser ( N -- N ) - s" boot_single" getenv -1 <> if - drop ( n c-addr -- n ) \ unused + singleuser_enabled? if toggle_menuitem ( n -- n ) then ; @@ -109,21 +144,35 @@ variable root_state =20 \ Now we're going to make the change effective =20 - s" toggle_stateN @" \ base name of toggle state var - -rot 2dup 12 + c! rot \ replace 'N' with ASCII numeral - - evaluate 0=3D if - s" boot_single" unsetenv + dup toggle_stateN @ 0=3D if + singleuser_disable else - s" set boot_single=3DYES" evaluate + singleuser_enable then =20 TRUE \ loop menu again ; =20 +\=20 +\ Verbose Boot +\=20 + +: verbose_enabled? ( -- flag ) + s" boot_verbose" getenv -1 <> dup if + swap drop ( c-addr flag -- flag ) + then +; + +: verbose_enable ( -- ) + s" set boot_verbose=3DYES" evaluate +; + +: verbose_disable ( -- ) + s" boot_verbose" unsetenv +; + : init_verbose ( N -- N ) - s" boot_verbose" getenv -1 <> if - drop ( n c-addr -- n ) \ unused + verbose_enabled? if toggle_menuitem ( n -- n ) then ; @@ -134,18 +183,19 @@ variable root_state =20 \ Now we're going to make the change effective =20 - s" toggle_stateN @" \ base name of toggle state var - -rot 2dup 12 + c! rot \ replace 'N' with ASCII numeral - - evaluate 0=3D if - s" boot_verbose" unsetenv + dup toggle_stateN @ 0=3D if + verbose_disable else - s" set boot_verbose=3DYES" evaluate + verbose_enable then =20 TRUE \ loop menu again ; =20 +\=20 +\ Escape to Prompt +\=20 + : goto_prompt ( N -- N FALSE ) =20 s" set autoboot_delay=3DNO" evaluate @@ -158,11 +208,12 @@ variable root_state FALSE \ exit the menu ; =20 +\=20 +\ Cyclestate (used by kernel/root below) +\=20 + : init_cyclestate ( N K -- N ) - over ( n k -- n k n ) - s" cycle_stateN" ( n k n -- n k n c-addr u ) - -rot tuck 11 + c! swap ( n k n c-addr u -- n k c-addr u ) - evaluate ( n k c-addr u -- n k addr ) + over cycle_stateN ( n k -- n k addr ) begin tuck @ ( n k addr -- n addr k c ) over <> ( n addr k c -- n addr k 0|-1 ) @@ -174,6 +225,10 @@ variable root_state 2drop ( n k addr -- n ) ; =20 +\ +\ Kernel +\=20 + : init_kernel ( N -- N ) kernel_state @ ( n -- n k ) init_cyclestate ( n k -- n ) @@ -185,21 +240,21 @@ variable root_state =20 \ Now we're going to make the change effective =20 - s" cycle_stateN" \ base name of array state var - -rot 2dup 11 + c! rot \ replace 'N' with ASCII numeral - evaluate \ translate name into address - @ \ dereference address into value + dup cycle_stateN @ dup kernel_state ! \ save a copy for re-initialization 48 + \ convert to ASCII numeral =20 s" set kernel=3D${kernel_prefix}${kernel[N]}${kernel_suffix}" - \ command to assemble full kernel-path - -rot tuck 36 + c! swap \ replace 'N' with array index value - evaluate \ sets $kernel to full kernel-path + 36 +c! \ replace 'N' with ASCII numeral + evaluate =20 TRUE \ loop menu again ; =20 +\=20 +\ Root +\=20 + : init_root ( N -- N ) root_state @ ( n -- n k ) init_cyclestate ( n k -- n ) @@ -211,21 +266,21 @@ variable root_state =20 \ Now we're going to make the change effective =20 - s" cycle_stateN" \ base name of array state var - -rot 2dup 11 + c! rot \ replace 'N' with ASCII numeral - evaluate \ translate name into address - @ \ dereference address into value + dup cycle_stateN @ dup root_state ! \ save a copy for re-initialization 48 + \ convert to ASCII numeral =20 s" set root=3D${root_prefix}${root[N]}${root_suffix}" - \ command to assemble root image-path - -rot tuck 30 + c! swap \ replace 'N' with array index value - evaluate \ sets $kernel to full kernel-path + 30 +c! \ replace 'N' with ASCII numeral + evaluate =20 TRUE \ loop menu again ; =20 +\=20 +\ Menusets +\=20 + : goto_menu ( N M -- N TRUE ) menu-unset menuset-loadsetnum ( n m -- n ) Index: menu.4th =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- menu.4th (revision 242835) +++ menu.4th (working copy) @@ -116,6 +116,48 @@ create init_text6 255 allot create init_text7 255 allot create init_text8 255 allot =20 +: +c! ( N C-ADDR/U K -- C-ADDR/U ) + 3 pick 3 pick ( n c-addr/u k -- n c-addr/u k n c-addr ) + rot + c! ( n c-addr/u k n c-addr -- n c-addr/u ) + rot drop ( n c-addr/u -- c-addr/u ) +; + +: menukeyN ( N -- ADDR ) s" menukeyN" 7 +c! evaluate ; +: init_stateN ( N -- ADDR ) s" init_stateN" 10 +c! evaluate ; +: toggle_stateN ( N -- ADDR ) s" toggle_stateN" 12 +c! evaluate ; +: cycle_stateN ( N -- ADDR ) s" cycle_stateN" 11 +c! evaluate ; +: init_textN ( N -- C-ADDR ) s" init_textN" 9 +c! evaluate ; + +: str_loader_menu_title ( -- C-ADDR/U ) s" loader_menu_title" ; +: str_loader_menu_timeout_x ( -- C-ADDR/U ) s" loader_menu_timeout_x" ; +: str_loader_menu_timeout_y ( -- C-ADDR/U ) s" loader_menu_timeout_y" ; +: str_menu_init ( -- C-ADDR/U ) s" menu_init" ; +: str_menu_timeout_command ( -- C-ADDR/U ) s" menu_timeout_command" ; +: str_menu_reboot ( -- C-ADDR/U ) s" menu_reboot" ; +: str_menu_acpi ( -- C-ADDR/U ) s" menu_acpi" ; +: str_menu_options ( -- C-ADDR/U ) s" menu_options" ; +: str_menu_optionstext ( -- C-ADDR/U ) s" menu_optionstext" ; + +: str_menu_init[x] ( -- C-ADDR/U ) s" menu_init[x]" ; +: str_menu_command[x] ( -- C-ADDR/U ) s" menu_command[x]" ; +: str_menu_caption[x] ( -- C-ADDR/U ) s" menu_caption[x]" ; +: str_ansi_caption[x] ( -- C-ADDR/U ) s" ansi_caption[x]" ; +: str_menu_keycode[x] ( -- C-ADDR/U ) s" menu_keycode[x]" ; +: str_toggled_text[x] ( -- C-ADDR/U ) s" toggled_text[x]" ; +: str_toggled_ansi[x] ( -- C-ADDR/U ) s" toggled_ansi[x]" ; +: str_menu_caption[x][y] ( -- C-ADDR/U ) s" menu_caption[x][y]" ; +: str_ansi_caption[x][y] ( -- C-ADDR/U ) s" ansi_caption[x][y]" ; + +: menu_init[x] ( N -- C-ADDR/U ) str_menu_init[x] 10 +c! = ; +: menu_command[x] ( N -- C-ADDR/U ) str_menu_command[x] 13 +c! = ; +: menu_caption[x] ( N -- C-ADDR/U ) str_menu_caption[x] 13 +c! = ; +: ansi_caption[x] ( N -- C-ADDR/U ) str_ansi_caption[x] 13 +c! = ; +: menu_keycode[x] ( N -- C-ADDR/U ) str_menu_keycode[x] 13 +c! = ; +: toggled_text[x] ( N -- C-ADDR/U ) str_toggled_text[x] 13 +c! = ; +: toggled_ansi[x] ( N -- C-ADDR/U ) str_toggled_ansi[x] 13 +c! = ; +: menu_caption[x][y] ( N M -- C-ADDR/U ) str_menu_caption[x][y] 16 +c! = 13 +c! ; +: ansi_caption[x][y] ( N M -- C-ADDR/U ) str_ansi_caption[x][y] 16 +c! = 13 +c! ; + : arch-i386? ( -- BOOL ) \ Returns TRUE (-1) on i386, FALSE (0) = otherwise. s" arch-i386" environment? dup if drop @@ -172,10 +214,7 @@ create init_text8 255 allot \ ASCII numeral equal to user-selected menu item must be on the = stack. \ We do not modify the stack, so the ASCII numeral is left on = top. =20 - s" init_textN" \ base name of buffer - -rot 2dup 9 + c! rot \ replace 'N' with ASCII num - - evaluate c@ 0=3D if + dup init_textN c@ 0=3D if \ NOTE: no need to check toggle_stateN since the first = time we \ are called, we will populate init_textN. Further, we = don't \ need to test whether menu_caption[x] (ansi_caption[x] = when @@ -184,18 +223,15 @@ create init_text8 255 allot =20 \ base name of environment variable loader_color? if - s" ansi_caption[x]" + dup ansi_caption[x] else - s" menu_caption[x]" + dup menu_caption[x] then=09 - -rot 2dup 13 + c! rot \ replace 'x' with ASCII = numeral =20 getenv dup -1 <> if =20 - s" init_textN" \ base name of buffer - 4 pick \ copy ASCII num to top - rot tuck 9 + c! swap \ replace 'N' with ASCII = num - evaluate + 2 pick ( n c-addr/u -- n c-addr/u n ) + init_textN ( n c-addr/u n -- n c-addr/u c-addr ) =20 \ now we have the buffer c-addr on top \ ( followed by c-addr/u of current caption ) @@ -227,36 +263,26 @@ create init_text8 255 allot \ negate the toggled state so that we reverse the flow on = subsequent \ calls. =20 - s" toggle_stateN @" \ base name of toggle state var - -rot 2dup 12 + c! rot \ replace 'N' with ASCII numeral - - evaluate 0=3D if + dup toggle_stateN @ 0=3D if \ state is OFF, toggle to ON =20 - \ base name of toggled text var + dup loader_color? if - s" toggled_ansi[x]" + toggled_ansi[x] else - s" toggled_text[x]" + toggled_text[x] then - -rot 2dup 13 + c! rot \ replace 'x' with ASCII num - getenv dup -1 <> if \ Assign toggled text to menu caption - - \ base name of caption var + 2 pick loader_color? if - s" ansi_caption[x]" + ansi_caption[x] else - s" menu_caption[x]" + menu_caption[x] then - 4 pick \ copy ASCII num to top - rot tuck 13 + c! swap \ replace 'x' with = ASCII num - - setenv \ set new caption + setenv else \ No toggled text, keep the same caption - drop then =20 @@ -264,30 +290,22 @@ create init_text8 255 allot else \ state is ON, toggle to OFF =20 - s" init_textN" \ base name of initial text = buffer - -rot 2dup 9 + c! rot \ replace 'N' with ASCII = numeral - evaluate \ convert string to c-addr - count \ convert c-addr to c-addr/u + dup init_textN count ( n -- n c-addr/u ) =20 - \ base name of caption var + \ Assign init_textN text to menu caption + 2 pick loader_color? if - s" ansi_caption[x]" + ansi_caption[x] else - s" menu_caption[x]" + menu_caption[x] then - 4 pick \ copy ASCII num to top - rot tuck 13 + c! swap \ replace 'x' with ASCII = numeral + setenv =20 - setenv \ set new caption - false \ new value of toggle state var (to be stored = below) + false \ new value of toggle state var (to be stored = below) then =20 \ now we'll store the new toggle state (on top of stack) - s" toggle_stateN" \ base name of toggle state var - 3 pick \ copy ASCII numeral to top - rot tuck 12 + c! swap \ replace 'N' with ASCII numeral - evaluate \ convert string to addr - ! \ store new value + over toggle_stateN ! ; =20 : cycle_menuitem ( N -- N ) \ cycles through array of choices for a = menuitem @@ -295,13 +313,8 @@ create init_text8 255 allot \ ASCII numeral equal to user-selected menu item must be on the = stack. \ We do not modify the stack, so the ASCII numeral is left on = top. =20 - s" cycle_stateN" \ base name of array state var - -rot 2dup 11 + c! rot \ replace 'N' with ASCII numeral + dup cycle_stateN dup @ 1+ \ get value and increment =20 - evaluate \ we now have a pointer to the proper variable - dup @ \ resolve the pointer (but leave it on the stack) - 1+ \ increment the value - \ Before assigning the (incremented) value back to the pointer, \ let's test for the existence of this particular array element. \ If the element exists, we'll store index value and move on. @@ -309,14 +322,12 @@ create init_text8 255 allot =20 dup 48 + \ duplicate Array index and convert to ASCII numeral =20 - \ base name of array caption text + 3 pick swap loader_color? if - s" ansi_caption[x][y]" =20 + ansi_caption[x][y] else - s" menu_caption[x][y]" =20 + menu_caption[x][y] then - -rot tuck 16 + c! swap \ replace 'y' with Array index - 4 pick rot tuck 13 + c! swap \ replace 'x' with menu choice =20 \ Now test for the existence of our incremented array index in = the \ form of $menu_caption[x][y] ($ansi_caption[x][y] with = loader_color @@ -329,19 +340,18 @@ create init_text8 255 allot drop ( incremented array index ) 0 ( new array index that will be stored later ) =20 - \ base name of caption var + 2 pick [char] 0 loader_color? if - s" ansi_caption[x][0]" + ansi_caption[x][y] else - s" menu_caption[x][0]" + menu_caption[x][y] then - 4 pick rot tuck 13 + c! swap \ replace 'x' with menu = choice - getenv dup -1 =3D if \ This is highly unlikely to occur, but to make \ sure that things move along smoothly, allocate \ a temporary NULL string =20 + drop ( getenv cruft ) s" " then then @@ -357,14 +367,14 @@ create init_text8 255 allot \=20 \ Let's perform what we need to with the above. =20 - \ base name of menuitem caption var + \ Assign array value text to menu caption + 4 pick loader_color? if - s" ansi_caption[x]" + ansi_caption[x] else - s" menu_caption[x]" + menu_caption[x] then - 6 pick rot tuck 13 + c! swap \ replace 'x' with menu choice - setenv \ set the new caption + setenv =20 swap ! \ update array state variable ; @@ -400,15 +410,15 @@ create init_text8 255 allot acpipresent? if acpienabled? if loader_color? if - s" toggled_ansi[x]" + str_toggled_ansi[x] else - s" toggled_text[x]" + str_toggled_text[x] then else loader_color? if - s" ansi_caption[x]" + str_ansi_caption[x] else - s" menu_caption[x]" + str_menu_caption[x] then then else @@ -426,7 +436,7 @@ create init_text8 255 allot : menu-create ( -- ) =20 \ Print the frame caption at (x,y) - s" loader_menu_title" getenv dup -1 =3D if + str_loader_menu_title getenv dup -1 =3D if drop s" Welcome to FreeBSD" then 24 over 2 / - 9 at-xy type=20 @@ -435,7 +445,7 @@ create init_text8 255 allot \ constructed dynamically -- as this function could conceivably = set \ the remaining environment variables to construct the menu = entirely). \=20 - s" menu_init" getenv dup -1 <> if + str_menu_init getenv dup -1 <> if evaluate else drop @@ -460,7 +470,7 @@ create init_text8 255 allot \ Initialize the ACPI option status. \=20 0 menuacpi ! - s" menu_acpi" getenv -1 <> if + str_menu_acpi getenv -1 <> if c@ dup 48 > over 57 < and if ( '1' <=3D c1 <=3D '8' ) menuacpi ! arch-i386? if acpipresent? if @@ -468,10 +478,7 @@ create init_text8 255 allot \ Set menu toggle state to active state \ (required by generic toggle_menuitem) \=20 - menuacpi @ - s" acpienabled? toggle_stateN !" - -rot tuck 25 + c! swap - evaluate + acpienabled? menuacpi @ toggle_stateN ! then then else drop @@ -482,7 +489,7 @@ create init_text8 255 allot \ Initialize the menu_options visual separator. \=20 0 menuoptions ! - s" menu_options" getenv -1 <> if + str_menu_options getenv -1 <> if c@ dup 48 > over 57 < and if ( '1' <=3D c1 <=3D '8' ) menuoptions ! else @@ -502,7 +509,7 @@ create init_text8 255 allot \ If the "Options:" separator, print it. dup menuoptions @ =3D if \ Optionally add a reboot option to the menu - s" menu_reboot" getenv -1 <> if + str_menu_reboot getenv -1 <> if drop s" Reboot" printmenuitem menureboot ! true menurebootadded ! @@ -512,7 +519,7 @@ create init_text8 255 allot menurow @ 2 + menurow ! menurow @ menuY @ + at-xy - s" menu_optionstext" getenv dup -1 <> if + str_menu_optionstext getenv dup -1 <> if type else drop ." Options:" @@ -521,17 +528,20 @@ create init_text8 255 allot =20 \ If this is the ACPI menu option, act accordingly. dup menuacpi @ =3D if - acpimenuitem ( -- C-Addr/U | -1 ) + dup acpimenuitem ( n -- n n c-addr/u | n n -1 ) + dup -1 <> if + 13 +c! ( n n c-addr/u -- n ) \ replace = 'x' + else + swap drop ( n n -1 -- n -1 ) + over menu_command[x] unsetenv + then else \ make sure we have not already initialized this = item - s" init_stateN" - -rot 2dup 10 + c! rot \ repace 'N' - evaluate dup @ 0=3D if + dup init_stateN dup @ 0=3D if 1 swap ! =20 \ If this menuitem has an initializer, = run it - s" menu_init[x]" - -rot 2dup 10 + c! rot \ replace 'x' + dup menu_init[x] getenv dup -1 <> if evaluate else @@ -542,34 +552,22 @@ create init_text8 255 allot then =20 loader_color? if - s" ansi_caption[x]" + dup ansi_caption[x] else - s" menu_caption[x]" + dup menu_caption[x] then then =20 - ( C-Addr/U | -1 ) dup -1 <> if - \ replace 'x' with current iteration - -rot 2dup 13 + c! rot - =20 \ test for environment variable getenv dup -1 <> if - printmenuitem ( C-Addr/U -- N ) - =20 - s" menukeyN !" \ generate cmd to store = result - -rot 2dup 7 + c! rot - =20 - evaluate + printmenuitem ( c-addr/u -- n ) + dup menukeyN ! else drop then else drop - - s" menu_command[x]" - -rot 2dup 13 + c! rot ( replace 'x' ) - unsetenv then =20 1+ dup 56 > \ add 1 to iterator, continue if less than = 57 @@ -578,7 +576,7 @@ create init_text8 255 allot =20 \ Optionally add a reboot option to the menu menurebootadded @ true <> if - s" menu_reboot" getenv -1 <> if + str_menu_reboot getenv -1 <> if drop \ no need for the value s" Reboot" \ menu caption (required by = printmenuitem) =20 @@ -596,45 +594,22 @@ create init_text8 255 allot \=20 : menu-timeout-update ( N -- ) =20 - dup 9 > if ( N N 9 -- N ) - drop ( N -- ) - 9 ( maximum: -- N ) - then + \ Enforce minimum/maximum + dup 9 > if drop 9 then + dup 0 < if drop 0 then =20 - dup 0 < if ( N N 0 -- N ) - drop ( N -- ) - 0 ( minimum: -- N ) - then + s" Autoboot in N seconds. [Space] to pause" ( n -- n c-addr/u ) =20 - 48 + ( convert single-digit numeral to ASCII: N 48 -- N ) + 2 pick 0> if + rot 48 + -rot ( n c-addr/u -- n' c-addr/u ) \ convert to = ASCII + 12 +c! ( n' c-addr/u -- c-addr/u ) \ replace = 'N' above =20 - s" Autoboot in N seconds. [Space] to pause" ( N -- N Addr C ) - - 2 pick 48 - 0> if ( N Addr C N 48 -- N Addr C ) - - \ Modify 'N' (Addr+12) above to reflect time-left - - -rot ( N Addr C -- C N Addr ) - tuck ( C N Addr -- C Addr N Addr ) - 12 + ( C Addr N Addr -- C Addr N Addr2 ) - c! ( C Addr N Addr2 -- C Addr ) - swap ( C Addr -- Addr C ) - - menu_timeout_x @ - menu_timeout_y @ - at-xy ( position cursor: Addr C N N -- Addr C ) - - type ( print message: Addr C -- ) - - else ( N Addr C N -- N Addr C ) - - menu_timeout_x @ - menu_timeout_y @ - at-xy ( position cursor: N Addr C N N -- N Addr C ) - - spaces ( erase message: N Addr C -- N Addr ) - 2drop ( N Addr -- ) - + menu_timeout_x @ menu_timeout_y @ at-xy \ position = cursor + type ( c-Addr/u -- ) \ print message + else + menu_timeout_x @ menu_timeout_y @ at-xy \ position = cursor + spaces ( n c-addr/u -- n c-addr ) \ erase message + 2drop ( n c-addr -- ) then =20 0 25 at-xy ( position cursor back at bottom-left ) @@ -682,7 +657,7 @@ create init_text8 255 allot \ (user did not cancel by = pressing ANY \ key) =20 - s" menu_timeout_command" getenv = dup + str_menu_timeout_command getenv = dup -1 =3D if drop \ clean-up else @@ -765,7 +740,7 @@ create init_text8 255 allot 0 menu_timeout_enabled ! \ start with automatic timeout disabled =20 \ check indication that automatic execution after delay is = requested - s" menu_timeout_command" getenv -1 <> if ( Addr C -1 -- | Addr ) + str_menu_timeout_command getenv -1 <> if ( Addr C -1 -- | Addr ) drop ( just testing existence right now: Addr -- ) =20 \ initialize state variables @@ -801,7 +776,7 @@ create init_text8 255 allot =20 menu_timeout_enabled @ 1 =3D if \ read custom column position (if set) - s" loader_menu_timeout_x" getenv dup -1 =3D if + str_loader_menu_timeout_x getenv dup -1 =3D if drop \ no custom column position menu_timeout_default_x \ use default = setting else @@ -813,7 +788,7 @@ create init_text8 255 allot menu_timeout_x ! ( store value on stack from = above ) =20 \ read custom row position (if set) - s" loader_menu_timeout_y" getenv dup -1 =3D if + str_loader_menu_timeout_y getenv dup -1 =3D if drop \ no custom row position menu_timeout_default_y \ use default = setting else @@ -852,13 +827,9 @@ create init_text8 255 allot =20 49 \ Iterator start (loop range 49 to 56; ASCII '1' to = '8') begin - s" menukeyN @" + dup menukeyN @ + rot tuck =3D if =20 - \ replace 'N' with current iteration - -rot 2dup 7 + c! rot - - evaluate rot tuck =3D if - \ Adjust for missing ACPI menuitem on = non-i386 arch-i386? true <> menuacpi @ 0<> and if menuacpi @ over 2dup < -rot =3D = or @@ -868,13 +839,8 @@ create init_text8 255 allot then then =20 - \ base env name for the value (x is a = number) - s" menu_command[x]" - - \ Copy ASCII number to string at offset = 13 - -rot 2dup 13 + c! rot - \ Test for the environment variable + dup menu_command[x] getenv dup -1 <> if \ Execute the stored procedure evaluate @@ -909,16 +875,14 @@ create init_text8 255 allot \=20 \ Check for menu keycode shortcut(s) \=20 - s" menu_keycode[x]" - -rot 2dup 13 + c! rot + dup menu_keycode[x] getenv dup -1 =3D if drop else ?number 0<> if rot tuck =3D if swap - s" menu_command[x]" - -rot 2dup 13 + c! rot + dup menu_command[x] getenv dup -1 <> if evaluate 0=3D if @@ -950,100 +914,43 @@ create init_text8 255 allot =20 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8') begin - \ Unset variables in-order of appearance in menu.4th(8) + dup menu_init[x] unsetenv \ menu initializer + dup menu_command[x] unsetenv \ menu command + dup menu_caption[x] unsetenv \ menu caption + dup ansi_caption[x] unsetenv \ ANSI caption + dup menu_keycode[x] unsetenv \ menu keycode + dup toggled_text[x] unsetenv \ toggle_menuitem = caption + dup toggled_ansi[x] unsetenv \ toggle_menuitem ANSI = caption =20 - s" menu_caption[x]" \ basename for caption variable - -rot 2dup 13 + c! rot \ replace 'x' with current = iteration - unsetenv \ not erroneous to unset unknown = var - - s" menu_command[x]" \ command basename - -rot 2dup 13 + c! rot \ replace 'x' - unsetenv - - s" menu_init[x]" \ initializer basename - -rot 2dup 10 + c! rot \ replace 'x' - unsetenv - - s" menu_keycode[x]" \ keycode basename - -rot 2dup 13 + c! rot \ replace 'x' - unsetenv - - s" ansi_caption[x]" \ ANSI caption basename - -rot 2dup 13 + c! rot \ replace 'x' - unsetenv - - s" toggled_text[x]" \ toggle_menuitem caption = basename - -rot 2dup 13 + c! rot \ replace 'x' - unsetenv - - s" toggled_ansi[x]" \ toggle_menuitem ANSI caption = basename - -rot 2dup 13 + c! rot \ replace 'x' - unsetenv - - s" menu_caption[x][y]" \ cycle_menuitem caption - -rot 2dup 13 + c! rot \ replace 'x' - 48 -rot + 48 \ Iterator start (inner range 48 to 57; ASCII '0' to = '9') begin - 16 2over rot + c! \ replace 'y' - 2dup unsetenv - - rot 1+ dup 57 > 2swap rot + \ cycle_menuitem caption and ANSI caption + 2dup menu_caption[x][y] unsetenv + 2dup ansi_caption[x][y] unsetenv + 1+ dup 57 > until - 2drop drop + drop \ inner iterator =20 - s" ansi_caption[x][y]" \ cycle_menuitem ANSI caption - -rot 2dup 13 + c! rot \ replace 'x' - 48 -rot - begin - 16 2over rot + c! \ replace 'y' - 2dup unsetenv + 0 over menukeyN ! \ used by menu-create, = menu-display + 0 over init_stateN ! \ used by menu-create + 0 over toggle_stateN ! \ used by toggle_menuitem + 0 over init_textN c! \ used by toggle_menuitem + 0 over cycle_stateN ! \ used by cycle_menuitem =20 - rot 1+ dup 57 > 2swap rot - until - 2drop drop - - s" 0 menukeyN !" \ basename for key association = var - -rot 2dup 9 + c! rot \ replace 'N' with current = iteration - evaluate \ assign zero (0) to key assoc. = var - - s" 0 init_stateN !" \ used by menu-create - -rot 2dup 12 + c! rot \ replace 'N' - evaluate - - s" 0 toggle_stateN !" \ used by toggle_menuitem - -rot 2dup 14 + c! rot \ replace 'N' - evaluate - - s" 0 cycle_stateN !" \ used by cycle_menuitem - -rot 2dup 13 + c! rot \ replace 'N' - evaluate - - s" 0 init_textN c!" \ used by toggle_menuitem - -rot 2dup 11 + c! rot \ replace 'N' - evaluate - 1+ dup 56 > \ increment, continue if less than 57 until drop \ iterator =20 - \ unset the timeout command - s" menu_timeout_command" unsetenv + str_menu_timeout_command unsetenv \ menu timeout command + str_menu_reboot unsetenv \ Reboot menu option = flag + str_menu_acpi unsetenv \ ACPI menu option flag + str_menu_options unsetenv \ Options separator flag + str_menu_optionstext unsetenv \ separator display text + str_menu_init unsetenv \ menu initializer =20 - \ clear the "Reboot" menu option flag - s" menu_reboot" unsetenv 0 menureboot ! - - \ clear the ACPI menu option flag - s" menu_acpi" unsetenv 0 menuacpi ! - - \ clear the "Options" menu separator flag - s" menu_options" unsetenv - s" menu_optionstext" unsetenv 0 menuoptions ! - - \ clear the menu initializer - s" menu_init" unsetenv ; =20 \ This function both unsets menu variables and visually erases the menu = area --Apple-Mail=_A9909A1E-E6A9-43DD-8CBB-D93045B73375--