\ ========== Copyright Header Begin ========================================== \ \ Hypervisor Software File: stresc.fth \ \ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. \ \ - Do no alter or remove copyright notices \ \ - Redistribution and use of this software in source and binary forms, with \ or without modification, are permitted provided that the following \ conditions are met: \ \ - Redistribution of source code must retain the above copyright notice, \ this list of conditions and the following disclaimer. \ \ - Redistribution in binary form must reproduce the above copyright notice, \ this list of conditions and the following disclaimer in the \ documentation and/or other materials provided with the distribution. \ \ Neither the name of Sun Microsystems, Inc. or the names of contributors \ may be used to endorse or promote products derived from this software \ without specific prior written permission. \ \ This software is provided "AS IS," without a warranty of any kind. \ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, \ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A \ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN \ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR \ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR \ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN \ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR \ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE \ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, \ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF \ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. \ \ You acknowledge that this software is not designed, licensed or \ intended for use in the design, construction, operation or maintenance of \ any nuclear facility. \ \ ========== Copyright Header End ============================================ id: @(#)stresc.fth 1.17 02/05/02 purpose: copyright: Copyright 1991-2002 Sun Microsystems, Inc. All Rights Reserved copyright: Use is subject to license terms. \ Copyright 1985-1990 Bradley Forthware \ These words use the string-scanning routines to get strings out of \ the input stream. \ ", --> given string, emplace the string at here and allot space \ ," --> accept a "-terminated string and emplace it. \ " --> accept a "-terminated string and leave addr len on the stack \ "" --> accept a blank delimited string and leave it's address on the stac \ [""]--> accept a blank delimited string and emplace it. \ At run time, leave it's address on the stack \ The improvements allow control characters and 8-bit binary numbers to \ be embedded into string literals. This is similar in principle to the \ "\n" convention in C, but syntactically tuned for Forth. \ \ The escape character is '"'. Here is the list of escapes: \ \ "" " \ "n newline \ "r carret \ "t tab \ "f formfeed \ "l linefeed \ "b backspace \ "! bell \ "^x control x, where x is any printable character \ "(HhHh) Sequence of bytes, one byte for each pair of hex digits Hh \ Non-hex characters will be ignored \ \ " terminates the string, as usual \ \ " followed by any other printable character not mentioned above is \ equivalent to that character. \ \ This new syntax is completely backwards compatible with old code, since \ the only legal previous usage was " \ \ Contrived example: \ \ " This is "(01,328e)"nA test xyzzy "!"! abcdefg""hijk"^bl" \ \ ^^^^^^ ^ ^ ^ ^ ^ \ 3 bytes newline 2 bells " control b \ \ The "(HhHhHhHh) should come in particularly handy. \ \ Note: "n (newline) happens to be the same as "l (linefeed) under Unix, \ but this is not true for all operating systems. [ifndef] run-time headerless nuser stringbuf nuser "select nuser '"temp \ Packed strings are 255 bytes + 1 NULL + 1 Paranoia. h# 258 constant /stringbuf \ Alloc an 4K buffer for string use chain: init ( -- ) h# 1000 alloc-mem dup stringbuf ! '"temp ! 0 "select ! ; \ Each string temp buffer is 512 bytes long. \ Note this is longer than a packed string can deal with - this is intentional headers : "temp ( -- adr ) "select dup @ tuck 1+ 7 and swap ! ( n ) d# 9 << '"temp @ + 0 over c! ( n ) ; : $save ( adr1 len1 adr2 -- adr2 len1 ) pack count ; : $add ( src,len dest,len -- dest,len' ) 2 pick over + >r over >r ( src,len dest,len ) + ( str,len dest' ) swap cmove ( ) r> r> ( dest,len' ) ; : $cat ( adr len pstr -- ) \ Append adr len to the end of pstr >r r@ count nip ( addr len len' ) ( r: pstr ) d# 255 swap - min ( addr len' ) ( r: pstr ) r@ count + ( adr len end-adr ) ( r: pstr ) swap dup >r ( adr endadr len ) ( r: pstr len ) cmove r> r> ( len pstr ) dup c@ rot + swap c! ; headerless : add-char ( buffer char -- ) over count + c! dup c@ ca1+ swap c! ; : nextchar ( adr len -- false | adr' len' char true ) dup 0= if nip exit then ( adr len ) over c@ >r 1 /string r> ( adr' len' char ) caps @ if lcc then true ; : nexthex ( adr len -- false | adr' len' digit true ) begin nextchar if ( adr' len' char ) d# 16 digit if ( adr' len' digit ) true true ( adr' len' digit true done ) else ( adr' len' char ) drop false ( adr' len' notdone ) then ( adr' len' digit true done | adr' len' notdone ) else ( ) false true ( false done ) then until ; : get-hex-bytes ( strbuf -- ) >r ( ) ( r: strbuf ) ascii ) parse ( adr len ) ( r: strbuf ) begin nexthex while ( adr' len' digit1 ) ( r: strbuf ) >r nexthex 0= ( ?? ) abort" Odd number of hex digits in string" r> ( adr'' len'' digit2 digit1 ) ( r: strbuf ) 4 lshift + ( adr'' len'' byte ) ( r: strbuf ) r@ swap add-char ( adr'' len'' ) ( r: strbuf ) repeat r> drop ( ) ; \ : get-char ( -- char ) input-file @ fgetc ; : get-char ( -- char|-1 ) source >in @ /string if c@ 1 >in +! else drop -1 then ; headers : get-string ( -- adr len ) "temp ( strbuf ) begin ( strbuf ) dup ascii " parse rot $cat dup ( strbuf strbuf ) get-char dup bl <= if ( strbuf strbuf r tuck r@ swap cmove ( len ) r@ + 0 swap c! r> ; : even (s n -- n | n+1 ) dup 1 and + ; \ Nullfix : +str (s pstr -- adr ) count + 1+ taligned ; \ Copy a packed string from "from-pstr" to "to-pstr" : "copy (s from-pstr to-pstr -- ) >r count r> place ; \ Copy a packed string from "from-pstr" to "to-pstr", returning "to-pstr" : "move (s from-pstr to-pstr -- to-pstr ) >r count r> pack ; \ : count (s adr -- adr+1 len ) dup 1+ swap c@ ; : /string ( adr len cnt -- adr' len' ) tuck - -rot + swap ; : printable? ( n -- flag ) \ true if n is a printable ascii character dup bl th 7f within swap th 80 th ff between or ; : white-space? ( n -- flag ) \ true is n is non-printable? or a blank dup printable? 0= swap bl = or ; : -leading ( adr len -- adr' len' ) begin dup while ( adr' len' ) over c@ white-space? 0= if exit then swap 1+ swap 1- repeat ; : -trailing (s adr len -- adr len' ) dup 0 ?do 2dup + 1- c@ white-space? 0= ?leave 1- loop ; : upper (s adr len -- ) bounds ?do i dup c@ upc swap c! loop ; : lower (s adr len -- ) bounds ?do i dup c@ lcc swap c! loop ; nuser caps : f83-compare (s adr adr2 len -- -1 | 0 | 1 ) caps @ if caps-comp else comp then ; headers \ Unpacked string comparison : +-1 ( n -- -1|0|+1 ) 0< 2* 1+ ; : compare (s adr1 len1 adr2 len2 -- same? ) rot 2dup 2>r min ( adr1 adr2 min-len ) ( r: len2 len1 ) comp dup if ( +-1 ) 2r> 2drop ( +-1 ) \ Initial substrings differ else ( 0 ) drop 2r> - ( diff ) \ Initial substrings are the same \ This is tricky. We want to convert zero to zero, positive \ numbers to -1, and negative numbers to +1. Here's how it works: \ "dup if .. then" leave 0 unchanged, and nonzero number are \ transformed as follows: \ +n -n \ 0> -1 0 \ 2* -2 0 \ 1+ -1 1 dup if 0> 2* 1+ then then ; \ $= can be defined as "compare 0=", but $= is used much more often, \ and doesn't require all the tricky argument fixups, so it makes \ sense to define $= directly, so it runs quite a bit faster. : $= (s adr1 len1 adr2 len2 -- same? ) rot tuck <> if 3drop false exit then ( adr1 adr2 len1 ) comp 0= ;