words[]: type FD = { } ; const bool yes = 1 , no = 0 ; const bool true = 1 , false = 0 ; extern { uint8 msbit ( uint16 ) ; uint8 msbit ( uint32 ) ; int sign ( int16 ) ; int sign ( int32 ) ; uint16 abs ( int16 ) ; uint32 abs ( int32 ) ; uint16 swap_bytes ( uint16 ) ; uint32 revert_bytes ( uint32 ) ; uint32 swap_words ( uint32 ) ; uint16 random ( ) ; uint32 mul_wwl ( uint16 , uint16 ) ; void flip ( int8 [ to ] ) = opcode flip ; void rol ( int8 [ to ] ) = opcode rol ; void ror ( int8 [ to ] ) = opcode ror ; void sort ( int8 [ to ] ) = opcode sort ; void rsort ( int8 [ to ] ) = opcode rsort ; void shuffle ( int8 [ to ] ) = opcode shuffle ; void revert ( int8 [ to ] ) = opcode revert ; int8 [ ] join ( int8 [ ] [ ] ¢ , int8 ) = opcode join ; int8 [ ] join ( int8 [ ] [ ] ¢ , int8 [ ] ¢ ) = opcode join ; int8 [ ] [ ] split ( int8 [ ] ¢ , int8 ) = opcode split ; int8 [ ] [ ] split ( int8 [ ] ¢ , int8 [ ] ¢ ) = opcode split ; int8 min ( int8 , int8 ) ; int8 min ( int8 , int8 , int8 ) ; int8 min ( int8 [ to ] ) ; int8 max ( int8 , int8 ) ; int8 max ( int8 , int8 , int8 ) ; int8 max ( int8 [ to ] ) ; uint find ( int8 [ to ] , int8 ) = opcode find ; uint find ( int8 [ to ] , int8 [ ] ¢ ) = opcode find ; uint rfind ( int8 [ to ] , int8 ) = opcode rfind ; uint rfind ( int8 [ to ] , int8 [ ] ¢ ) = opcode rfind ; void shrinktofit ( int8 [ ] & ) ; int8 [ to ] substr ( int8 [ ] ¢ , uint a , uint e ) ; int8 [ to ] midstr ( int8 [ ] ¢ , uint i , uint n ) ; int8 [ to ] leftstr ( int8 [ ] ¢ , uint n ) ; int8 [ to ] rightstr ( int8 [ ] ¢ , uint n ) ; int8 numval ( utf8str ¢ ) ; int8 numval ( ucs1str ¢ ) ; int8 numval ( ucs2str ¢ ) ; void flip ( uint8 [ to ] ) = opcode flip ; void rol ( uint8 [ to ] ) = opcode rol ; void ror ( uint8 [ to ] ) = opcode ror ; void sort ( uint8 [ to ] ) = opcode sort ; void rsort ( uint8 [ to ] ) = opcode rsort ; void shuffle ( uint8 [ to ] ) = opcode shuffle ; void revert ( uint8 [ to ] ) = opcode revert ; uint8 [ ] join ( uint8 [ ] [ ] ¢ , uint8 ) = opcode join ; uint8 [ ] join ( uint8 [ ] [ ] ¢ , uint8 [ ] ¢ ) = opcode join ; uint8 [ ] [ ] split ( uint8 [ ] ¢ , uint8 ) = opcode split ; uint8 [ ] [ ] split ( uint8 [ ] ¢ , uint8 [ ] ¢ ) = opcode split ; uint8 min ( uint8 , uint8 ) ; uint8 min ( uint8 , uint8 , uint8 ) ; uint8 min ( uint8 [ to ] ) ; uint8 max ( uint8 , uint8 ) ; uint8 max ( uint8 , uint8 , uint8 ) ; uint8 max ( uint8 [ to ] ) ; uint find ( uint8 [ to ] , uint8 ) = opcode find ; uint find ( uint8 [ to ] , uint8 [ ] ¢ ) = opcode find ; uint rfind ( uint8 [ to ] , uint8 ) = opcode rfind ; uint rfind ( uint8 [ to ] , uint8 [ ] ¢ ) = opcode rfind ; void shrinktofit ( uint8 [ ] & ) ; uint8 [ to ] substr ( uint8 [ ] ¢ , uint a , uint e ) ; uint8 [ to ] midstr ( uint8 [ ] ¢ , uint i , uint n ) ; uint8 [ to ] leftstr ( uint8 [ ] ¢ , uint n ) ; uint8 [ to ] rightstr ( uint8 [ ] ¢ , uint n ) ; uint8 numval ( utf8str ¢ ) ; uint8 numval ( ucs1str ¢ ) ; uint8 numval ( ucs2str ¢ ) ; void flip ( int16 [ to ] ) = opcode flip ; void rol ( int16 [ to ] ) = opcode rol ; void ror ( int16 [ to ] ) = opcode ror ; void sort ( int16 [ to ] ) = opcode sort ; void rsort ( int16 [ to ] ) = opcode rsort ; void shuffle ( int16 [ to ] ) = opcode shuffle ; void revert ( int16 [ to ] ) = opcode revert ; int16 [ ] join ( int16 [ ] [ ] ¢ , int16 ) = opcode join ; int16 [ ] join ( int16 [ ] [ ] ¢ , int16 [ ] ¢ ) = opcode join ; int16 [ ] [ ] split ( int16 [ ] ¢ , int16 ) = opcode split ; int16 [ ] [ ] split ( int16 [ ] ¢ , int16 [ ] ¢ ) = opcode split ; int16 min ( int16 , int16 ) ; int16 min ( int16 , int16 , int16 ) ; int16 min ( int16 [ to ] ) ; int16 max ( int16 , int16 ) ; int16 max ( int16 , int16 , int16 ) ; int16 max ( int16 [ to ] ) ; uint find ( int16 [ to ] , int16 ) = opcode find ; uint find ( int16 [ to ] , int16 [ ] ¢ ) = opcode find ; uint rfind ( int16 [ to ] , int16 ) = opcode rfind ; uint rfind ( int16 [ to ] , int16 [ ] ¢ ) = opcode rfind ; void shrinktofit ( int16 [ ] & ) ; int16 [ to ] substr ( int16 [ ] ¢ , uint a , uint e ) ; int16 [ to ] midstr ( int16 [ ] ¢ , uint i , uint n ) ; int16 [ to ] leftstr ( int16 [ ] ¢ , uint n ) ; int16 [ to ] rightstr ( int16 [ ] ¢ , uint n ) ; int16 numval ( utf8str ¢ ) ; int16 numval ( ucs1str ¢ ) ; int16 numval ( ucs2str ¢ ) ; void flip ( uint16 [ to ] ) = opcode flip ; void rol ( uint16 [ to ] ) = opcode rol ; void ror ( uint16 [ to ] ) = opcode ror ; void sort ( uint16 [ to ] ) = opcode sort ; void rsort ( uint16 [ to ] ) = opcode rsort ; void shuffle ( uint16 [ to ] ) = opcode shuffle ; void revert ( uint16 [ to ] ) = opcode revert ; uint16 [ ] join ( uint16 [ ] [ ] ¢ , uint16 ) = opcode join ; uint16 [ ] join ( uint16 [ ] [ ] ¢ , uint16 [ ] ¢ ) = opcode join ; uint16 [ ] [ ] split ( uint16 [ ] ¢ , uint16 ) = opcode split ; uint16 [ ] [ ] split ( uint16 [ ] ¢ , uint16 [ ] ¢ ) = opcode split ; uint16 min ( uint16 , uint16 ) ; uint16 min ( uint16 , uint16 , uint16 ) ; uint16 min ( uint16 [ to ] ) ; uint16 max ( uint16 , uint16 ) ; uint16 max ( uint16 , uint16 , uint16 ) ; uint16 max ( uint16 [ to ] ) ; uint find ( uint16 [ to ] , uint16 ) = opcode find ; uint find ( uint16 [ to ] , uint16 [ ] ¢ ) = opcode find ; uint rfind ( uint16 [ to ] , uint16 ) = opcode rfind ; uint rfind ( uint16 [ to ] , uint16 [ ] ¢ ) = opcode rfind ; void shrinktofit ( uint16 [ ] & ) ; uint16 [ to ] substr ( uint16 [ ] ¢ , uint a , uint e ) ; uint16 [ to ] midstr ( uint16 [ ] ¢ , uint i , uint n ) ; uint16 [ to ] leftstr ( uint16 [ ] ¢ , uint n ) ; uint16 [ to ] rightstr ( uint16 [ ] ¢ , uint n ) ; uint16 numval ( utf8str ¢ ) ; uint16 numval ( ucs1str ¢ ) ; uint16 numval ( ucs2str ¢ ) ; void flip ( int32 [ to ] ) = opcode flip ; void rol ( int32 [ to ] ) = opcode rol ; void ror ( int32 [ to ] ) = opcode ror ; void sort ( int32 [ to ] ) = opcode sort ; void rsort ( int32 [ to ] ) = opcode rsort ; void shuffle ( int32 [ to ] ) = opcode shuffle ; void revert ( int32 [ to ] ) = opcode revert ; int32 [ ] join ( int32 [ ] [ ] ¢ , int32 ) = opcode join ; int32 [ ] join ( int32 [ ] [ ] ¢ , int32 [ ] ¢ ) = opcode join ; int32 [ ] [ ] split ( int32 [ ] ¢ , int32 ) = opcode split ; int32 [ ] [ ] split ( int32 [ ] ¢ , int32 [ ] ¢ ) = opcode split ; int32 min ( int32 , int32 ) ; int32 min ( int32 , int32 , int32 ) ; int32 min ( int32 [ to ] ) ; int32 max ( int32 , int32 ) ; int32 max ( int32 , int32 , int32 ) ; int32 max ( int32 [ to ] ) ; uint find ( int32 [ to ] , int32 ) = opcode find ; uint find ( int32 [ to ] , int32 [ ] ¢ ) = opcode find ; uint rfind ( int32 [ to ] , int32 ) = opcode rfind ; uint rfind ( int32 [ to ] , int32 [ ] ¢ ) = opcode rfind ; void shrinktofit ( int32 [ ] & ) ; int32 [ to ] substr ( int32 [ ] ¢ , uint a , uint e ) ; int32 [ to ] midstr ( int32 [ ] ¢ , uint i , uint n ) ; int32 [ to ] leftstr ( int32 [ ] ¢ , uint n ) ; int32 [ to ] rightstr ( int32 [ ] ¢ , uint n ) ; int32 numval ( utf8str ¢ ) ; int32 numval ( ucs1str ¢ ) ; int32 numval ( ucs2str ¢ ) ; void flip ( uint32 [ to ] ) = opcode flip ; void rol ( uint32 [ to ] ) = opcode rol ; void ror ( uint32 [ to ] ) = opcode ror ; void sort ( uint32 [ to ] ) = opcode sort ; void rsort ( uint32 [ to ] ) = opcode rsort ; void shuffle ( uint32 [ to ] ) = opcode shuffle ; void revert ( uint32 [ to ] ) = opcode revert ; uint32 [ ] join ( uint32 [ ] [ ] ¢ , uint32 ) = opcode join ; uint32 [ ] join ( uint32 [ ] [ ] ¢ , uint32 [ ] ¢ ) = opcode join ; uint32 [ ] [ ] split ( uint32 [ ] ¢ , uint32 ) = opcode split ; uint32 [ ] [ ] split ( uint32 [ ] ¢ , uint32 [ ] ¢ ) = opcode split ; uint32 min ( uint32 , uint32 ) ; uint32 min ( uint32 , uint32 , uint32 ) ; uint32 min ( uint32 [ to ] ) ; uint32 max ( uint32 , uint32 ) ; uint32 max ( uint32 , uint32 , uint32 ) ; uint32 max ( uint32 [ to ] ) ; uint find ( uint32 [ to ] , uint32 ) = opcode find ; uint find ( uint32 [ to ] , uint32 [ ] ¢ ) = opcode find ; uint rfind ( uint32 [ to ] , uint32 ) = opcode rfind ; uint rfind ( uint32 [ to ] , uint32 [ ] ¢ ) = opcode rfind ; void shrinktofit ( uint32 [ ] & ) ; uint32 [ to ] substr ( uint32 [ ] ¢ , uint a , uint e ) ; uint32 [ to ] midstr ( uint32 [ ] ¢ , uint i , uint n ) ; uint32 [ to ] leftstr ( uint32 [ ] ¢ , uint n ) ; uint32 [ to ] rightstr ( uint32 [ ] ¢ , uint n ) ; uint32 numval ( utf8str ¢ ) ; uint32 numval ( ucs1str ¢ ) ; uint32 numval ( ucs2str ¢ ) ; void flip ( utf8char [ to ] ) = opcode flip ; void rol ( utf8char [ to ] ) = opcode rol ; void ror ( utf8char [ to ] ) = opcode ror ; void sort ( utf8char [ to ] ) = opcode sort ; void rsort ( utf8char [ to ] ) = opcode rsort ; void shuffle ( utf8char [ to ] ) = opcode shuffle ; void revert ( utf8char [ to ] ) = opcode revert ; utf8char [ ] join ( utf8char [ ] [ ] ¢ , utf8char ) = opcode join ; utf8char [ ] join ( utf8char [ ] [ ] ¢ , utf8char [ ] ¢ ) = opcode join ; utf8char [ ] [ ] split ( utf8char [ ] ¢ , utf8char ) = opcode split ; utf8char [ ] [ ] split ( utf8char [ ] ¢ , utf8char [ ] ¢ ) = opcode split ; utf8char min ( utf8char , utf8char ) ; utf8char min ( utf8char , utf8char , utf8char ) ; utf8char min ( utf8char [ to ] ) ; utf8char max ( utf8char , utf8char ) ; utf8char max ( utf8char , utf8char , utf8char ) ; utf8char max ( utf8char [ to ] ) ; uint find ( utf8char [ to ] , utf8char ) = opcode find ; uint find ( utf8char [ to ] , utf8char [ ] ¢ ) = opcode find ; uint rfind ( utf8char [ to ] , utf8char ) = opcode rfind ; uint rfind ( utf8char [ to ] , utf8char [ ] ¢ ) = opcode rfind ; void shrinktofit ( utf8char [ ] & ) ; utf8char [ to ] substr ( utf8char [ ] ¢ , uint a , uint e ) ; utf8char [ to ] midstr ( utf8char [ ] ¢ , uint i , uint n ) ; utf8char [ to ] leftstr ( utf8char [ ] ¢ , uint n ) ; utf8char [ to ] rightstr ( utf8char [ ] ¢ , uint n ) ; utf8char numval ( utf8str ¢ ) ; utf8char numval ( ucs1str ¢ ) ; utf8char numval ( ucs2str ¢ ) ; void flip ( ucs1char [ to ] ) = opcode flip ; void rol ( ucs1char [ to ] ) = opcode rol ; void ror ( ucs1char [ to ] ) = opcode ror ; void sort ( ucs1char [ to ] ) = opcode sort ; void rsort ( ucs1char [ to ] ) = opcode rsort ; void shuffle ( ucs1char [ to ] ) = opcode shuffle ; void revert ( ucs1char [ to ] ) = opcode revert ; ucs1char [ ] join ( ucs1char [ ] [ ] ¢ , ucs1char ) = opcode join ; ucs1char [ ] join ( ucs1char [ ] [ ] ¢ , ucs1char [ ] ¢ ) = opcode join ; ucs1char [ ] [ ] split ( ucs1char [ ] ¢ , ucs1char ) = opcode split ; ucs1char [ ] [ ] split ( ucs1char [ ] ¢ , ucs1char [ ] ¢ ) = opcode split ; ucs1char min ( ucs1char , ucs1char ) ; ucs1char min ( ucs1char , ucs1char , ucs1char ) ; ucs1char min ( ucs1char [ to ] ) ; ucs1char max ( ucs1char , ucs1char ) ; ucs1char max ( ucs1char , ucs1char , ucs1char ) ; ucs1char max ( ucs1char [ to ] ) ; uint find ( ucs1char [ to ] , ucs1char ) = opcode find ; uint find ( ucs1char [ to ] , ucs1char [ ] ¢ ) = opcode find ; uint rfind ( ucs1char [ to ] , ucs1char ) = opcode rfind ; uint rfind ( ucs1char [ to ] , ucs1char [ ] ¢ ) = opcode rfind ; void shrinktofit ( ucs1char [ ] & ) ; ucs1char [ to ] substr ( ucs1char [ ] ¢ , uint a , uint e ) ; ucs1char [ to ] midstr ( ucs1char [ ] ¢ , uint i , uint n ) ; ucs1char [ to ] leftstr ( ucs1char [ ] ¢ , uint n ) ; ucs1char [ to ] rightstr ( ucs1char [ ] ¢ , uint n ) ; ucs1char numval ( utf8str ¢ ) ; ucs1char numval ( ucs1str ¢ ) ; ucs1char numval ( ucs2str ¢ ) ; void flip ( ucs2char [ to ] ) = opcode flip ; void rol ( ucs2char [ to ] ) = opcode rol ; void ror ( ucs2char [ to ] ) = opcode ror ; void sort ( ucs2char [ to ] ) = opcode sort ; void rsort ( ucs2char [ to ] ) = opcode rsort ; void shuffle ( ucs2char [ to ] ) = opcode shuffle ; void revert ( ucs2char [ to ] ) = opcode revert ; ucs2char [ ] join ( ucs2char [ ] [ ] ¢ , ucs2char ) = opcode join ; ucs2char [ ] join ( ucs2char [ ] [ ] ¢ , ucs2char [ ] ¢ ) = opcode join ; ucs2char [ ] [ ] split ( ucs2char [ ] ¢ , ucs2char ) = opcode split ; ucs2char [ ] [ ] split ( ucs2char [ ] ¢ , ucs2char [ ] ¢ ) = opcode split ; ucs2char min ( ucs2char , ucs2char ) ; ucs2char min ( ucs2char , ucs2char , ucs2char ) ; ucs2char min ( ucs2char [ to ] ) ; ucs2char max ( ucs2char , ucs2char ) ; ucs2char max ( ucs2char , ucs2char , ucs2char ) ; ucs2char max ( ucs2char [ to ] ) ; uint find ( ucs2char [ to ] , ucs2char ) = opcode find ; uint find ( ucs2char [ to ] , ucs2char [ ] ¢ ) = opcode find ; uint rfind ( ucs2char [ to ] , ucs2char ) = opcode rfind ; uint rfind ( ucs2char [ to ] , ucs2char [ ] ¢ ) = opcode rfind ; void shrinktofit ( ucs2char [ ] & ) ; ucs2char [ to ] substr ( ucs2char [ ] ¢ , uint a , uint e ) ; ucs2char [ to ] midstr ( ucs2char [ ] ¢ , uint i , uint n ) ; ucs2char [ to ] leftstr ( ucs2char [ ] ¢ , uint n ) ; ucs2char [ to ] rightstr ( ucs2char [ ] ¢ , uint n ) ; ucs2char numval ( utf8str ¢ ) ; ucs2char numval ( ucs1str ¢ ) ; ucs2char numval ( ucs2str ¢ ) ; bool is_letter ( char ) ; bool is_bin_digit ( char ) ; bool is_dec_digit ( char ) ; bool is_hex_digit ( char ) ; uint digit_value ( char ) ; } ; float64 round ( float64 ) ; float64 floor ( float64 ) ; float64 ceil ( float64 ) ; float64 integ ( float64 ) ; float64 fract ( float64 ) ; int sign ( float64 ) ; float64 abs ( float64 ) ; float64 min ( float64 , float64 ) ; float64 max ( float64 , float64 ) ; float64 min ( float64 , float64 , float64 ) ; float64 max ( float64 , float64 , float64 ) ; float64 random ( ) ; float64 random ( float64 ) ; float64 sin ( float64 ) ; float64 cos ( float64 ) ; float64 tan ( float64 ) ; float64 asin ( float64 ) ; float64 acos ( float64 ) ; float64 atan ( float64 ) ; float64 sinh ( float64 ) ; float64 cosh ( float64 ) ; float64 tanh ( float64 ) ; float64 exp10 ( float64 ) ; float64 log10 ( float64 ) ; float64 exp2 ( float64 ) ; float64 log2 ( float64 ) ; float64 expe ( float64 ) ; float64 loge ( float64 ) ; float64 exp ( float64 , float64 ) ; float64 log ( float64 , float64 ) ; float64 pow ( float64 , int ) ; float64 sqrt ( float64 ) ; str numstr ( float64 ) ; float64 numval ( str ¢ ) ; float64 min ( float64 [ ] ¢ ) ; float64 min ( float64 [ to ] ) ; float64 max ( float64 [ ] ¢ ) ; float64 max ( float64 [ to ] ) ; scope ucs2str { ucs2char [ ] spacestr ( uint ) ucs2char [ ] spacestr ( uint , ucs2char ) ucs2char [ ] charstr ( uint ) ucs2char hexchar ( uint ) ucs2char [ ] hexstr ( uint8 ) ucs2char [ ] hexstr ( uint16 ) ucs2char [ ] hexstr ( uint32 ) ucs2char [ ] hexstr ( uint , uint digits ) ucs2char [ ] hexstr ( ulong , uint digits ) ucs2char [ ] binstr ( uint8 ) ucs2char [ ] binstr ( uint16 ) ucs2char [ ] binstr ( uint32 ) ucs2char [ ] binstr ( uint , uint digits ) ucs2char [ ] binstr ( ulong , uint digits ) ucs2char [ ] binstr ( uint , ucs2char [ ] ¢ o , ucs2char [ ] ¢ l ) ucs2char [ ] binstr ( ulong , ucs2char [ ] ¢ o , ucs2char [ ] ¢ l ) ucs2char [ ] numstr ( int ) ucs2char [ ] numstr ( uint ) ucs2char [ ] numstr ( long ) ucs2char [ ] numstr ( ulong ) ucs2char [ ] toupper ( ucs2char [ ] ¢ ) ucs2char [ ] tolower ( ucs2char [ ] ¢ ) ucs2char [ ] escape ( ucs2char [ ] ¢ , ucs2char leftquote ) ucs2char [ ] unescape ( ucs2char [ ] ¢ ) ucs2char [ ] urlencode ( ucs2char [ ] ¢ ) ucs2char [ ] urldecode ( ucs2char [ ] ¢ ) ucs2char [ ] entab ( ucs2char [ ] ¢ , uint tabwidth ) ucs2char [ ] detab ( ucs2char [ ] ¢ , uint tabwidth ) ucs2char [ ] toupper ( ucs2char [ to ] ) ucs2char [ ] tolower ( ucs2char [ to ] ) ucs2char [ ] escape ( ucs2char [ to ] , ucs2char leftquote ) ucs2char [ ] unescape ( ucs2char [ to ] ) ucs2char [ ] urlencode ( ucs2char [ to ] ) ucs2char [ ] urldecode ( ucs2char [ to ] ) ucs2char [ ] entab ( ucs2char [ to ] , uint tabwidth ) ucs2char [ ] detab ( ucs2char [ to ] , uint tabwidth ) ucs1str toucs1 ( ucs2char [ ] ¢ ) ucs2str toucs2 ( ucs2char [ ] ¢ ) utf8str toutf8 ( ucs2char [ ] ¢ ) ucs1str toucs1 ( ucs2char [ to ] ) ucs2str toucs2 ( ucs2char [ to ] ) utf8str toutf8 ( ucs2char [ to ] ) ucs2char [ ] min ( ucs2char [ ] , ucs2char [ ] ) ucs2char [ ] min ( ucs2char [ ] , ucs2char [ ] ¢ ) ucs2char [ ] min ( ucs2char [ ] ¢ , ucs2char [ ] ) ucs2char [ ] ¢ min ( ucs2char [ ] ¢ , ucs2char [ ] ¢ ) ucs2char [ ] ¢ min ( ucs2char [ ] [ ] ¢ ) ucs2char [ ] ¢ min ( ucs2char [ ] [ to ] ) ucs2char [ ] max ( ucs2char [ ] , ucs2char [ ] ) ucs2char [ ] max ( ucs2char [ ] , ucs2char [ ] ¢ ) ucs2char [ ] max ( ucs2char [ ] ¢ , ucs2char [ ] ) ucs2char [ ] ¢ max ( ucs2char [ ] ¢ , ucs2char [ ] ¢ ) ucs2char [ ] ¢ max ( ucs2char [ ] [ ] ¢ ) ucs2char [ ] ¢ max ( ucs2char [ ] [ to ] ) void flip ( ucs2char [ ] [ to ] ) void rol ( ucs2char [ ] [ to ] ) void ror ( ucs2char [ ] [ to ] ) void sort ( ucs2char [ ] [ to ] ) void rsort ( ucs2char [ ] [ to ] ) void shuffle ( ucs2char [ ] [ to ] ) void revert ( ucs2char [ ] [ to ] ) } scope ucs1str { ucs1char [ ] spacestr ( uint ) ucs1char [ ] spacestr ( uint , ucs1char ) ucs1char [ ] charstr ( uint ) ucs1char hexchar ( uint ) ucs1char [ ] hexstr ( uint8 ) ucs1char [ ] hexstr ( uint16 ) ucs1char [ ] hexstr ( uint32 ) ucs1char [ ] hexstr ( uint , uint digits ) ucs1char [ ] hexstr ( ulong , uint digits ) ucs1char [ ] binstr ( uint8 ) ucs1char [ ] binstr ( uint16 ) ucs1char [ ] binstr ( uint32 ) ucs1char [ ] binstr ( uint , uint digits ) ucs1char [ ] binstr ( ulong , uint digits ) ucs1char [ ] binstr ( uint , ucs1char [ ] ¢ o , ucs1char [ ] ¢ l ) ucs1char [ ] binstr ( ulong , ucs1char [ ] ¢ o , ucs1char [ ] ¢ l ) ucs1char [ ] numstr ( int ) ucs1char [ ] numstr ( uint ) ucs1char [ ] numstr ( long ) ucs1char [ ] numstr ( ulong ) ucs1char [ ] toupper ( ucs1char [ ] ¢ ) ucs1char [ ] tolower ( ucs1char [ ] ¢ ) ucs1char [ ] escape ( ucs1char [ ] ¢ , ucs1char leftquote ) ucs1char [ ] unescape ( ucs1char [ ] ¢ ) ucs1char [ ] urlencode ( ucs1char [ ] ¢ ) ucs1char [ ] urldecode ( ucs1char [ ] ¢ ) ucs1char [ ] entab ( ucs1char [ ] ¢ , uint tabwidth ) ucs1char [ ] detab ( ucs1char [ ] ¢ , uint tabwidth ) ucs1char [ ] toupper ( ucs1char [ to ] ) ucs1char [ ] tolower ( ucs1char [ to ] ) ucs1char [ ] escape ( ucs1char [ to ] , ucs1char leftquote ) ucs1char [ ] unescape ( ucs1char [ to ] ) ucs1char [ ] urlencode ( ucs1char [ to ] ) ucs1char [ ] urldecode ( ucs1char [ to ] ) ucs1char [ ] entab ( ucs1char [ to ] , uint tabwidth ) ucs1char [ ] detab ( ucs1char [ to ] , uint tabwidth ) ucs1str toucs1 ( ucs1char [ ] ¢ ) ucs2str toucs2 ( ucs1char [ ] ¢ ) utf8str toutf8 ( ucs1char [ ] ¢ ) ucs1str toucs1 ( ucs1char [ to ] ) ucs2str toucs2 ( ucs1char [ to ] ) utf8str toutf8 ( ucs1char [ to ] ) ucs1char [ ] min ( ucs1char [ ] , ucs1char [ ] ) ucs1char [ ] min ( ucs1char [ ] , ucs1char [ ] ¢ ) ucs1char [ ] min ( ucs1char [ ] ¢ , ucs1char [ ] ) ucs1char [ ] ¢ min ( ucs1char [ ] ¢ , ucs1char [ ] ¢ ) ucs1char [ ] ¢ min ( ucs1char [ ] [ ] ¢ ) ucs1char [ ] ¢ min ( ucs1char [ ] [ to ] ) ucs1char [ ] max ( ucs1char [ ] , ucs1char [ ] ) ucs1char [ ] max ( ucs1char [ ] , ucs1char [ ] ¢ ) ucs1char [ ] max ( ucs1char [ ] ¢ , ucs1char [ ] ) ucs1char [ ] ¢ max ( ucs1char [ ] ¢ , ucs1char [ ] ¢ ) ucs1char [ ] ¢ max ( ucs1char [ ] [ ] ¢ ) ucs1char [ ] ¢ max ( ucs1char [ ] [ to ] ) void flip ( ucs1char [ ] [ to ] ) void rol ( ucs1char [ ] [ to ] ) void ror ( ucs1char [ ] [ to ] ) void sort ( ucs1char [ ] [ to ] ) void rsort ( ucs1char [ ] [ to ] ) void shuffle ( ucs1char [ ] [ to ] ) void revert ( ucs1char [ ] [ to ] ) } scope utf8str { utf8char [ ] spacestr ( uint ) utf8char [ ] spacestr ( uint , utf8char ) utf8char [ ] charstr ( uint ) char hexchar ( uint ) utf8char [ ] hexstr ( uint8 ) utf8char [ ] hexstr ( uint16 ) utf8char [ ] hexstr ( uint32 ) utf8char [ ] hexstr ( uint , uint digits ) utf8char [ ] hexstr ( ulong , uint digits ) utf8char [ ] binstr ( uint8 ) utf8char [ ] binstr ( uint16 ) utf8char [ ] binstr ( uint32 ) utf8char [ ] binstr ( uint , uint digits ) utf8char [ ] binstr ( ulong , uint digits ) utf8char [ ] binstr ( uint , utf8char [ ] ¢ o , utf8char [ ] ¢ l ) utf8char [ ] binstr ( ulong , utf8char [ ] ¢ o , utf8char [ ] ¢ l ) utf8char [ ] numstr ( int ) utf8char [ ] numstr ( uint ) utf8char [ ] numstr ( long ) utf8char [ ] numstr ( ulong ) utf8char [ ] toupper ( utf8char [ ] ¢ ) utf8char [ ] tolower ( utf8char [ ] ¢ ) utf8char [ ] escape ( utf8char [ ] ¢ , char leftquote ) utf8char [ ] unescape ( utf8char [ ] ¢ ) utf8char [ ] urlencode ( utf8char [ ] ¢ ) utf8char [ ] urldecode ( utf8char [ ] ¢ ) utf8char [ ] entab ( utf8char [ ] ¢ , uint tabwidth ) utf8char [ ] detab ( utf8char [ ] ¢ , uint tabwidth ) utf8char [ ] toupper ( utf8char [ to ] ) utf8char [ ] tolower ( utf8char [ to ] ) utf8char [ ] escape ( utf8char [ to ] , char leftquote ) utf8char [ ] unescape ( utf8char [ to ] ) utf8char [ ] urlencode ( utf8char [ to ] ) utf8char [ ] urldecode ( utf8char [ to ] ) utf8char [ ] entab ( utf8char [ to ] , uint tabwidth ) utf8char [ ] detab ( utf8char [ to ] , uint tabwidth ) ucs1str toucs1 ( utf8char [ ] ¢ ) ucs2str toucs2 ( utf8char [ ] ¢ ) utf8str toutf8 ( utf8char [ ] ¢ ) ucs1str toucs1 ( utf8char [ to ] ) ucs2str toucs2 ( utf8char [ to ] ) utf8str toutf8 ( utf8char [ to ] ) utf8char [ ] min ( utf8char [ ] , utf8char [ ] ) utf8char [ ] min ( utf8char [ ] , utf8char [ ] ¢ ) utf8char [ ] min ( utf8char [ ] ¢ , utf8char [ ] ) utf8char [ ] ¢ min ( utf8char [ ] ¢ , utf8char [ ] ¢ ) utf8char [ ] ¢ min ( utf8char [ ] [ ] ¢ ) utf8char [ ] ¢ min ( utf8char [ ] [ to ] ) utf8char [ ] max ( utf8char [ ] , utf8char [ ] ) utf8char [ ] max ( utf8char [ ] , utf8char [ ] ¢ ) utf8char [ ] max ( utf8char [ ] ¢ , utf8char [ ] ) utf8char [ ] ¢ max ( utf8char [ ] ¢ , utf8char [ ] ¢ ) utf8char [ ] ¢ max ( utf8char [ ] [ ] ¢ ) utf8char [ ] ¢ max ( utf8char [ ] [ to ] ) void flip ( utf8char [ ] [ to ] ) void rol ( utf8char [ ] [ to ] ) void ror ( utf8char [ ] [ to ] ) void sort ( utf8char [ ] [ to ] ) void rsort ( utf8char [ ] [ to ] ) void shuffle ( utf8char [ ] [ to ] ) void revert ( utf8char [ ] [ to ] ) } ucs1char [ ] spacestr ( uint ) ucs1char [ ] spacestr ( uint , ucs1char ) ucs1char [ ] charstr ( uint ) ucs1char hexchar ( uint ) ucs1char [ ] hexstr ( uint8 ) ucs1char [ ] hexstr ( uint16 ) ucs1char [ ] hexstr ( uint32 ) ucs1char [ ] hexstr ( uint , uint digits ) ucs1char [ ] hexstr ( ulong , uint digits ) ucs1char [ ] binstr ( uint8 ) ucs1char [ ] binstr ( uint16 ) ucs1char [ ] binstr ( uint32 ) ucs1char [ ] binstr ( uint , uint digits ) ucs1char [ ] binstr ( ulong , uint digits ) ucs1char [ ] binstr ( uint , ucs1char [ ] ¢ o , ucs1char [ ] ¢ l ) ucs1char [ ] binstr ( ulong , ucs1char [ ] ¢ o , ucs1char [ ] ¢ l ) ucs1char [ ] numstr ( int ) ucs1char [ ] numstr ( uint ) ucs1char [ ] numstr ( long ) ucs1char [ ] numstr ( ulong ) ucs1char [ ] toupper ( ucs1char [ ] ¢ ) ucs1char [ ] tolower ( ucs1char [ ] ¢ ) ucs1char [ ] escape ( ucs1char [ ] ¢ , ucs1char leftquote ) ucs1char [ ] unescape ( ucs1char [ ] ¢ ) ucs1char [ ] urlencode ( ucs1char [ ] ¢ ) ucs1char [ ] urldecode ( ucs1char [ ] ¢ ) ucs1char [ ] entab ( ucs1char [ ] ¢ , uint tabwidth ) ucs1char [ ] detab ( ucs1char [ ] ¢ , uint tabwidth ) ucs1char [ ] toupper ( ucs1char [ to ] ) ucs1char [ ] tolower ( ucs1char [ to ] ) ucs1char [ ] escape ( ucs1char [ to ] , ucs1char leftquote ) ucs1char [ ] unescape ( ucs1char [ to ] ) ucs1char [ ] urlencode ( ucs1char [ to ] ) ucs1char [ ] urldecode ( ucs1char [ to ] ) ucs1char [ ] entab ( ucs1char [ to ] , uint tabwidth ) ucs1char [ ] detab ( ucs1char [ to ] , uint tabwidth ) ucs1str toucs1 ( ucs1char [ ] ¢ ) ucs2str toucs2 ( ucs1char [ ] ¢ ) utf8str toutf8 ( ucs1char [ ] ¢ ) ucs1str toucs1 ( ucs1char [ to ] ) ucs2str toucs2 ( ucs1char [ to ] ) utf8str toutf8 ( ucs1char [ to ] ) ucs1char [ ] min ( ucs1char [ ] , ucs1char [ ] ) ucs1char [ ] min ( ucs1char [ ] , ucs1char [ ] ¢ ) ucs1char [ ] min ( ucs1char [ ] ¢ , ucs1char [ ] ) ucs1char [ ] ¢ min ( ucs1char [ ] ¢ , ucs1char [ ] ¢ ) ucs1char [ ] ¢ min ( ucs1char [ ] [ ] ¢ ) ucs1char [ ] ¢ min ( ucs1char [ ] [ to ] ) ucs1char [ ] max ( ucs1char [ ] , ucs1char [ ] ) ucs1char [ ] max ( ucs1char [ ] , ucs1char [ ] ¢ ) ucs1char [ ] max ( ucs1char [ ] ¢ , ucs1char [ ] ) ucs1char [ ] ¢ max ( ucs1char [ ] ¢ , ucs1char [ ] ¢ ) ucs1char [ ] ¢ max ( ucs1char [ ] [ ] ¢ ) ucs1char [ ] ¢ max ( ucs1char [ ] [ to ] ) void flip ( ucs1char [ ] [ to ] ) void rol ( ucs1char [ ] [ to ] ) void ror ( ucs1char [ ] [ to ] ) void sort ( ucs1char [ ] [ to ] ) void rsort ( ucs1char [ ] [ to ] ) void shuffle ( ucs1char [ ] [ to ] ) void revert ( ucs1char [ ] [ to ] ) enum { tm_utc = 0 , tm_localtime = 1 , tm_time = 2 , tm_date = 4 , tm_timezone = 8 , tm_sec = 16 , tm_msec = 32 } extern { float now ( ) ; str timestr ( float seconds , uint flags ) ; float timeval ( str ¢ , uint flags ) ; } enum uint8 { c_reset = 0 , c_speed = 1 , c_hwhsk = 2 , c_swhsk = 3 , c_flushin = 4 , c_availin = 4 , c_flushout = 5 , c_availout = 5 , c_clk_hsk = 6 , c_log2blocksize = 7 , c_totalblocks_lo = 8 , c_totalblocks_hi = 9 , c_reserved2 = 10 } ; enum uint8 OSErr = { ok = 0 , parameter_error = 1 , function_not_supported = 1 , io_error = 2 , device_not_responding = 3 , file_error , filesystem_invalid , device_not_found , directory_not_found , file_not_found , not_a_directory , is_a_directory , file_already_open_for_writing , file_already_open , file_exists , file_not_writable , end_of_file , disk_full , directory_corrupted , filesystem_corrupted } ; extern { OSErr errno ; OSErr error ( ) ; void clear_error ( ) ; void set_error ( OSErr ) ; bool yes_with_error ( OSErr ) ; void * null_with_error ( OSErr ) ; } enum uint8 NodeType = { t_endmarker = 0 , t_file = 1 , t_dir = 2 , t_ser = 3 , t_block = 4 , m_erased = 128 } ; scope NodeType { NodeType operator | ( NodeType , NodeType ) = opcode operator | ; NodeType operator & ( NodeType , NodeType ) = opcode operator & ; } type FD_Handlers = { uint ( FD ¢ , uint8 fu ) getctl ; void ( FD ¢ , uint8 fu , uint ) setctl ; uint ( FD ¢ ) avail_in ; uint ( FD ¢ ) avail_out ; char ( FD ¢ ) getc ; void ( FD ¢ , char ) putc ; bool ( FD ¢ , uint8 [ to ] ) read ; bool ( FD ¢ , uint8 [ to ] ) write ; bool ( FD ¢ , uint32 , uint8 [ ] ¢ ) read_block ; bool ( FD ¢ , uint32 , uint8 [ ] ¢ ) write_block ; void ( FD ¢ ) kill ; ulong ( FD ¢ ) getfpos ; bool ( FD ¢ , ulong fpos ) setfpos ; } extern { uint no_avail_in ( FD ¢ ) uint no_avail_out ( FD ¢ ) = no_avail_in ; char no_getc ( FD ¢ ) = no_avail_in ; void no_putc ( FD ¢ , char ) ulong no_getfpos ( FD ¢ ) bool no_setfpos ( FD ¢ , ulong ) bool no_read ( FD ¢ , uint8 [ to ] ) bool no_write ( FD ¢ , uint8 [ to ] ) = no_read ; bool no_read_block ( FD ¢ , uint32 , uint8 [ ] ¢ ) bool no_write_block ( FD ¢ , uint32 , uint8 [ ] ¢ ) = no_read_block ; } type FD = { FD_Handlers ¢ handlers ; NodeType nodetype ; str name ; } extern { uint avail_in ( ) ; uint avail_out ( ) ; const uint delimiters = 1 << 0 + 1 << 4 + 1 << 10 + 1 << 12 + 1 << 13 ; char getc ( ) ; void putc ( char c ) ; str gets ( uint delimiters ) ; void puts ( str ¢ ) ; void puts ( str ) ; void putnum ( uint ) ; void putnum ( int ) ; bool read ( uint8 [ to ] ) ; bool write ( uint8 [ to ] ) ; } scope FD { extern { void init ( FD ¢ , NodeType , str ¢ name , FD_Handlers ¢ ) ; void kill ( FD ¢ ) ; FD kill ( FD ) ; uint getctl ( FD ¢ , uint8 fu ) void setctl ( FD ¢ , uint8 fu , uint n ) uint avail_in ( FD ¢ ) ; uint avail_out ( FD ¢ ) ; char getc ( FD ¢ ) ; void putc ( FD ¢ , char c ) ; str gets ( FD ¢ , uint delimiters ) ; void puts ( FD ¢ , str ¢ ) ; void puts ( FD ¢ , str ) ; void putnum ( FD ¢ , uint ) ; void putnum ( FD ¢ , int ) ; bool read ( FD ¢ , uint8 [ to ] ) bool write ( FD ¢ , uint8 [ to ] ) bool read_block ( FD ¢ , uint32 blk , uint8 [ ] ¢ ) ; bool write_block ( FD ¢ , uint32 blk , uint8 [ ] ¢ ) ; ulong getfpos ( FD ¢ ) bool setfpos ( FD ¢ , ulong fpos ) bool is_dir ( FD ¢ ) ; bool is_file ( FD ¢ ) ; } } extern const { bool option_a5 = true ; uint8 bSIO_SELECT = 1 ; uint8 bIDE_SELECT = 2 ; uint8 mSIO_SELECT = 255 - 1 << bSIO_SELECT ; uint8 mIDE_SELECT = 255 - 2 << bSIO_SELECT ; } ; type FD = { } ; type BlockDevice = { } ; type IdeBlockDevice = { } ; type I2cBlockDevice = { } ; type SerialDevice = { } ; type Range = { } ; type File = { } ; type FD_Handlers = { } ; extern { uint8 k1_irpt_mask ; uint8 sysflags ; uint32 systemtime ; uint16 period ; uint32 timestamp ; uint16 tsmsec ; char * romdate ; char * romtime ; FD [ ] devs ; File [ ] fds ; FD stdin ; FD stdout ; SerialDevice sio1A ; SerialDevice sio1B ; IdeBlockDevice ide2A ; IdeBlockDevice ide2B ; I2cBlockDevice sio1rom ; I2cBlockDevice ide2rom ; OSErr errno ; void di ( ) void ei ( ) ; void ei_all ( ) ; void select ( uint8 ) uint8 in ( uint8 ) void out ( uint8 , uint8 ) void wait ( ) void memcpy ( void * z , void * q , uint cnt ) void memset ( void * z , uint c , uint cnt ) void memclr ( void * z , uint cnt ) void set_red_led ( ) ; void set_yellow_led ( ) ; void set_both_leds ( ) ; void clear_both_leds ( ) ; OSErr lock_eeprom ( ) ; OSErr unlock_eeprom ( ) ; void write_eeprom ( void * q , void * z , uint16 cnt ) ; void download_firmware ( ) ; void abort ( ) = opcode abort ; void panic ( uint8 blinkcode ) ; void assert1 ( bool ) ; void assert0 ( bool ) ; uint mem_get_free ( ) ; uint mem_get_free_total ( ) ; void download_firmware ( ) ; uint8 fd_function_not_supported ( ) ; void sio_init_channel ( SerialDevice ¢ , str ¢ name , uint8 devselbit , uint8 ch ) ; void ide_init_blockdevice ( BlockDevice ¢ ) ; void i2c_init_blockdevice ( BlockDevice ¢ ) ; } ; type File = { } ; type BlockDevice = FD + { uint blocksize ; uint blockmask ; uint8 log2blocksize ; uint32 totalblocks ; bool wide ; File [ ] open_files ; } ; scope BlockDevice { extern void init ( BlockDevice ¢ , NodeType , str ¢ name , FD_Handlers ¢ , uint8 log2blksz , uint32 totalblocks ) ; extern void kill ( BlockDevice ¢ ) = void FD . kill ( FD ¢ ) ; extern uint getctl ( BlockDevice ¢ fd , uint8 fu ) ; extern void setctl ( BlockDevice ¢ fd , uint8 fu , uint n ) ; } ; type Range = { uint32 start ; uint32 count ; } ; extern Range new ( uint32 start , uint32 count ) ; scope Range { uint32 ende ( Range ¢ r ) ; } type Ranges = Range [ ] ; extern Ranges new ( Range ) ; extern Ranges new ( uint32 start , uint32 count ) ; scope Ranges { extern uint32 totalblocks ( Ranges ¢ ) ; extern Range pop ( Ranges ¢ ) ; } type FileType = NodeType ; type File = BlockDevice + { uint32 parent ; BlockDevice device ; uint32 fsize ; Range [ ] ranges ; bool writable ; bool file_dirty ; bool buffer_dirty ; bool buffer_valid ; uint8 [ ] buffer ; uint32 blkno ; uint32 fpos ; uint ri ; uint32 bi ; } ; scope File { File kill ( File ) = FD FD . kill ( FD ) ; void kill ( File ¢ ) ; extern { uint getctl ( File ¢ , uint8 fu ) ; void setctl ( File ¢ , uint8 fu , uint n ) ; uint bu_free ( File ¢ ) ; uint bu_avail ( File ¢ ) ; uint avail_in ( File ¢ ) = bu_avail ; uint avail_out ( File ¢ ) = bu_free ; uint32 getfpos ( File ¢ ) ; uint32 getfsize ( File ¢ ) ; uint32 getfavail ( File ¢ ) ; bool setfpos ( File ¢ , uint32 fpos ) ; bool rewind ( File ¢ ) ; bool seek_end ( File ¢ ) ; bool skip ( File ¢ , int32 offs ) ; bool truncate ( File ¢ ) ; bool readbyte ( File ¢ , uint8 & ) ; bool writebyte ( File ¢ , uint8 ) ; char getc ( File ¢ ) ; void putc ( File ¢ , char c ) ; void puts ( File ¢ , str ¢ s ) ; void puts ( File ¢ , str s ) ; bool write ( File ¢ , uint8 [ ] ¢ , uint a , uint e ) ; bool read ( File ¢ , uint8 [ ] ¢ , uint a , uint e ) ; bool write ( File ¢ , uint8 [ to ] ) = bool write ( File ¢ , uint8 [ ] ¢ , uint , uint ) ; bool read ( File ¢ , uint8 [ to ] ) = bool read ( File ¢ , uint8 [ ] ¢ , uint , uint ) ; bool write_block ( File ¢ , uint32 , uint8 [ ] ¢ ) ; bool read_block ( File ¢ , uint32 , uint8 [ ] ¢ ) ; bool copy_block ( File ¢ fd , uint32 z , uint32 q , uint32 n ) ; bool open_gap ( File ¢ fd , uint32 start , uint32 size ) ; bool close_gap ( File ¢ fd , uint32 start , uint32 size ) ; bool sync ( File ¢ ) ; bool purge_buffer ( File ¢ ) ; uint32 block0 ( File ¢ ) ; void _rewind ( File ¢ fd ) } } ; scope BlockDevice { extern Range allocate_blocks ( BlockDevice ¢ bdev , uint32 maxnum , uint32 bestpos ) ; } extern FD_Handlers file_handlers ; type BYTE = uint16 ; type WORD = uint32 ; type CHAR = ucs2char ; const WORD FSMagic1 = 4547 ; const WORD FSMagic2 = 28102 ; const WORD DirMagic = 147 ; type FileInfo = { FileType filetype ; WORD fsize ; WORD mdate ; str name ; } ; extern FileInfo new ( FileType ft , uint32 fsize , uint32 mdate , str ¢ name ) ; enum uint8 FileMode = { ReadOnly , Truncate , ReadWrite , NewFile , NewDir , Default = ReadOnly } ; scope File { extern { bool rewind_directory ( File ¢ ) ; uint num_direntries ( File ¢ ) ; FileInfo next_fileinfo ( File ¢ ) ; str next_filename ( File ¢ ) ; FileType seek_direntry ( File ¢ , str ¢ name ) ; File newFileAtFpos ( File ¢ , FileType ) ; File open ( File ¢ dir , str ¢ name , FileMode ) ; bool sync ( File ¢ ) ; bool rename ( File ¢ dir , str ¢ name , str ¢ newname ) ; bool move ( File ¢ dir , str ¢ name , File ¢ zdir , str ¢ newname ) ; bool move ( File ¢ dir , str ¢ name , str ¢ zdir ) ; str fullpath ( File ¢ ) ; } } scope BlockDevice { extern bool writeFilesystem ( BlockDevice ¢ , str ¢ name , bool wide ) ; File newDeviceFile ( BlockDevice ¢ bdev ) ; File ¢ getRootDirectory ( BlockDevice ¢ bdev ) ; File ¢ getFreeBlocksFile ( BlockDevice ¢ bdev ) ; } const more_sdir = 1 ; const more_sfile = 2 ; const more_wdir = 4 ; const more_wfile = 16 ; const uint32 seconds_per_day = 86400 ; uint8 [ ] scratch = alloc uint8 [ 4 ] ( ) ; void TODO ( ) = void abort ( ) ; extern const uint8 ERROR_OUT_OF_MEMORY ; extern uint8 * heap_end ; extern uint8 * handles_start ; extern void shrink ( uint8 [ ] ¢ this , uint max ) extern void grow ( uint8 [ ] ¢ this , uint min ) extern void MEM_COMPACT ( ) ; void shrink ( uint8 [ ] ¢ this , uint new_max ) { uint this_count = this . count ( ) ; if ( this_count <= new_max ) return ; if ( & this [ this_count ] == heap_end ) { memclr ( & this [ new_max ] , this_count - new_max ) ; heap_end = & this [ new_max ] ; } else if ( new_max == this_count - 1 ) { uint8 [ ] that = alloc uint8 [ ] ( new_max ) ; memcpy ( & that [ 0 ] , & this [ 0 ] , new_max ) ; swap ( * ( byte * * ) this , * ( byte * * ) that ) ; return ; } else { * ( uint * ) & this [ new_max ] = this_count - new_max - 2 ; } * ( uint * ) & this [ - 2 ] = new_max ; } void grow ( uint8 [ ] ¢ this , uint new_size ) { uint old_size = this . count ( ) ; if ( old_size >= new_size ) return ; if ( & this [ old_size ] != heap_end ) { uint8 [ ] that = alloc uint8 [ ] ( old_size ) ; memcpy ( & that [ 0 ] , & this [ 0 ] , old_size ) ; swap ( * ( byte * * ) this , * ( byte * * ) that ) ; } uint8 * new_end = & this [ new_size ] ; if ( new_end > handles_start ) { MEM_COMPACT ( ) ; if ( new_end > handles_start ) panic ( ERROR_OUT_OF_MEMORY ) ; } heap_end = new_end ; * ( uint * ) & this [ - 2 ] = new_size ; } bool yes_with_cond_error ( OSErr e ) { return error ( ) || yes_with_error ( e ) ; } FileInfo new ( FileType ft , uint32 fsize , uint32 mdate , str ¢ name ) { FileInfo this = alloc FileInfo ( ) ; this . filetype = ft ; this . fsize = fsize ; this . mdate = mdate ; this . name := name ; return this ; } scope BlockDevice { Range allocate_blocks ( BlockDevice ¢ bdev , uint32 maxnum , uint32 bestpos ) ; void return_blocks ( BlockDevice ¢ bdev , Range ¢ range ) ; File new_file ( BlockDevice ¢ q , FileType ft , str ¢ name , uint32 parent , Range [ ] ¢ ranges ) ; File new_dir ( BlockDevice ¢ q , str ¢ name , uint32 parent , uint32 block0 ) ; } scope File { uint16 read_byte ( File ¢ fd ) { return error ( ) ? 0 : fd . wide ? read ( fd , scratch , 0 , 2 ) ? 0 : * ( uint16 * ) & scratch [ 0 ] : fd . getc ( ) ; } uint32 read_word ( File ¢ fd ) { if ( error ( ) ) return 0 ; * ( uint16 * ) & scratch [ 1 ] = 0 ; return read ( fd , scratch , 0 , 2 << fd . wide ) ? 0 : * ( uint32 * ) & scratch [ 0 ] ; } void write_byte ( File ¢ fd , uint16 n ) { if ( error ( ) ) return ; if ( fd . wide ) { * ( uint16 * ) & scratch [ 0 ] = n ; ( void ) fd . write ( scratch , 0 , 2 ) ; } else { fd . putc ( ( char ) n ) ; } } void write_word ( File ¢ fd , uint32 n ) { if ( error ( ) ) return ; if ( fd . wide ) { * ( uint32 * ) & scratch [ 0 ] = n ; ( void ) fd . write ( scratch , 0 , 4 ) ; } else { * ( uint16 * ) & scratch [ 0 ] = n . lo ; ( void ) fd . write ( scratch , 0 , 2 ) ; } } void write_words ( File ¢ fd , uint32 a , uint32 b ) { fd . write_word ( a ) ; fd . write_word ( b ) ; } void skip_bytes ( File ¢ fd , uint n ) { if ( error ( ) == ok ) { ( void ) fd . skip ( n << fd . wide ) } } str read_name ( File ¢ fd ) { uint n = fd . read_byte ( ) ; str s = alloc str ( n ) ; uint i = 0 ; do { while i < n ; s [ i ++ ] = ( char ) fd . read_byte ( ) ; } return error ( ) ? null : s ; } void write_name ( File ¢ fd , str ¢ name ) { uint i = 0 ; fd . write_byte ( name . count ( ) ) ; do { until i == name . count ( ) ; fd . write_byte ( name [ i ++ ] ) ; } } void skip_name ( File ¢ fd ) { fd . skip_bytes ( fd . read_byte ( ) ) ; } FileType read_filetype ( File ¢ fd ) { FileType ft ; do { ft = ( FileType ) fd . read_byte ( ) ; while ft & m_erased ; fd . skip_bytes ( ft & 127 ) ; } switch ( ft ) { default : set_error ( directory_corrupted ) ; return t_endmarker ; case t_dir : case t_file : case t_endmarker : } return ft ; } void read_range_at ( File ¢ fd , uint fpos , uint32 & a , uint32 & n ) { if ( ! error ( ) ) { ( void ) fd . setfpos ( fpos ) ; } a = fd . read_word ( ) ; n = fd . read_word ( ) ; } void write_range_at ( File ¢ fd , uint fpos , uint32 a , uint32 n ) { if ( ! error ( ) ) { ( void ) fd . setfpos ( fpos ) ; } fd . write_words ( a , n ) ; } void skip_ranges ( File ¢ fd ) { fd . skip_bytes ( fd . read_byte ( ) << 2 ) ; } void skip_ranges ( File ¢ fd , FileType ft ) { if ( ft == t_dir ) fd . skip_bytes ( 2 ) ; else fd . skip_ranges ( ) ; } void write_ranges ( File ¢ fd , Range [ ] ¢ ranges ) { uint i = 0 ; fd . write_byte ( ranges . count ( ) ) ; do { until i == ranges . count ( ) ; fd . write_words ( ranges [ i ] . start , ranges [ i ++ ] . count ) ; } } Ranges read_ranges ( File ¢ fd , bool dir ) { uint n = fd . read_byte ( ) ; if ( n == 0 && dir ) return null_with_error ( directory_corrupted ) ; Ranges ranges = alloc Ranges ( n ) ; uint i = 0 ; do { while i < n ; ranges [ i ] := alloc Range ( ) ; ranges [ i ] . start = fd . read_word ( ) ; ranges [ i ++ ] . count = fd . read_word ( ) ; if ( dir ) { dir = no ; if ( fd . block0 ( ) != ranges [ 0 ] . start ) return null_with_error ( directory_corrupted ) ; else fd . ranges = ranges ; } } return ranges ; } void write_direntry ( File ¢ dir , File ¢ file ) { dir . write_words ( file . fsize , dir . wide ? systemtime : systemtime / seconds_per_day ) ; dir . write_name ( file . name ) ; if ( file . nodetype == t_dir ) dir . write_word ( file . block0 ( ) ) ; else dir . write_ranges ( file . ranges ) ; } bool rewind_directory ( File ¢ fd ) { clear_error ( ) ; if ( fd . rewind ( ) ) return yes ; if ( fd . read_byte ( ) != DirMagic ) return yes_with_cond_error ( not_a_directory ) ; fd . skip_bytes ( 2 ) ; fd . skip_ranges ( ) ; return error ( ) != ok ; } FileInfo next_fileinfo ( File ¢ fd ) { clear_error ( ) ; FileType ft = fd . read_filetype ( ) ; if ( ft == t_endmarker ) return null ; FileInfo fi = new FileInfo ( ft , fd . read_word ( ) , fd . read_word ( ) , fd . read_name ( ) ) ; fd . skip_ranges ( ft ) ; return error ( ) ? null : fi ; } str next_filename ( File ¢ fd ) { clear_error ( ) FileType ft = fd . read_filetype ( ) ; if ( ft == t_endmarker ) return null ; if ( ft != t_dir ) fd . skip_bytes ( 4 ) ; str fname = fd . read_name ( ) ; fd . skip_ranges ( ft ) ; return error ( ) ? null : fname ; } FileType seek_direntry ( File ¢ fd , str ¢ name ) { if ( ! fd . rewind_directory ( ) ) { do { FileType ft = fd . read_filetype ( ) ; while ft != t_endmarker ; uint32 fpos = fd . fpos ; if ( ft != t_dir ) fd . skip_bytes ( 4 ) ; uint slen = fd . read_byte ( ) ; if ( slen == name . count ( ) ) { int i = 0 ; do { if ( slen == i ) return error ( ) || fd . setfpos ( fpos ) ? t_endmarker : ft ; while name [ i ++ ] == fd . read_byte ( ) ; } slen -= i ; } fd . skip_bytes ( slen ) ; fd . skip_ranges ( ft ) ; } } return t_endmarker ; } bool skip_direntry ( File ¢ fd ) { FileType ft = fd . read_filetype ( ) ; if ( ft == t_endmarker ) return yes ; if ( ft != t_dir ) fd . skip_bytes ( 4 ) ; fd . skip_name ( ) ; fd . skip_ranges ( ft ) ; return error ( ) != ok ; } bool seek_dir_endmarker ( File ¢ dir ) { if ( dir . rewind_directory ( ) ) return yes ; do { until dir . skip_direntry ( ) ; } return error ( ) || dir . skip ( - 1 << dir . wide ) ; } uint num_direntries ( File ¢ fd ) { ( void ) fd . rewind_directory ( ) ; uint n = 0 ; do { until fd . skip_direntry ( ) ; n ++ ; } return error ( ) ? 0 : n ; } File newFileAtFpos ( File ¢ dir , FileType ft ) { clear_error ( ) ; TODO ( ) ; uint32 fsize = dir . read_word ( ) ; dir . skip_bytes ( 2 ) ; str name = dir . read_name ( ) ; if ( ft == t_dir ) { return dir . device . new_dir ( name , dir . block0 ( ) , dir . read_word ( ) ) ; } else { File z = dir . device . new_file ( ft , name , dir . block0 ( ) , dir . read_ranges ( no ) ) ; z . fsize = fsize ; } return error ( ) ? null : dir ; } File newFileAtFpos ( File ¢ dir ) { TODO ( ) ; return null ; } File open ( File ¢ dir , str ¢ name , FileMode filemode ) { FileType ft = dir . seek_direntry ( name ) ; if ( filemode == Truncate && ft == t_dir ) return null_with_error ( is_a_directory ) ; if ( ft == t_endmarker ) { if ( filemode == ReadOnly ) return null_with_error ( file_not_found ) ; if ( filemode == NewDir ) { TODO ( ) ; File file = dir . device . new_file ( t_dir , name , dir . block0 ( ) , alloc Ranges ( 0 ) ) ; if ( file ) { file . writable = yes ; file . write_byte ( DirMagic ) ; file . write_word ( file . parent ) ; file . write_ranges ( file . ranges ) ; file . write_byte ( t_endmarker ) ; file . writable = no ; return file ; } } else { File file = dir . device . new_file ( t_file , name , dir . block0 ( ) , alloc Ranges ( 0 ) ) ; if ( file ) { file . writable = yes ; return file ; } } } else { if ( NewDir == NewFile + 1 ) { if ( filemode - NewFile <= 1 ) return null_with_error ( file_exists ) ; } else { if ( filemode == NewFile || filemode == NewDir ) return null_with_error ( file_exists ) ; } File file = dir . newFileAtFpos ( ft ) ; if ( file ) { file . writable = filemode != ReadOnly ; if ( filemode == Truncate && file . truncate ( ) ) return null ; file . parent = dir . block0 ( ) ; if ( file . is_dir ( ) ) { if ( file . rewind_directory ( ) ) return null ; do { until file . skip_direntry ( ) ; } if ( error ( ) ) return null ; file . fsize = file . fpos ; } return file ; } } return null ; } bool sync ( File ¢ ) { return yes } bool rename ( File ¢ dir , str ¢ name , str ¢ newname ) { return yes } bool move ( File ¢ dir , str ¢ oldname , File ¢ zdir , str ¢ newname ) { return yes } bool move ( File ¢ dir , str ¢ oldname , str ¢ zdir ) { return yes } str fullpath ( File ¢ ) { return null } } scope BlockDevice { File new_file ( BlockDevice ¢ q , FileType ft , str ¢ name , uint32 parent , Range [ ] ¢ ranges ) { File z = alloc File ( ) ; BlockDevice . init ( z , ft , name , file_handlers , q . log2blocksize , ranges . totalblocks ( ) ) ; z . device := q ; z . wide = q . wide ; z . parent = parent ; z . ranges := ranges ; return z ; } File new_dir ( BlockDevice ¢ bdev , str ¢ name , uint32 parent , uint32 block0 ) { File fd = bdev . new_file ( t_dir , name , parent , new Ranges ( block0 , 32768 ) ) ; fd . fsize . hi = 1 ; if ( fd . read_byte ( ) != DirMagic ) return null_with_error ( directory_corrupted ) ; if ( fd . read_word ( ) != fd . parent ) return null_with_error ( directory_corrupted ) ; fd . fsize = fd . read_word ( ) ; fd . skip_bytes ( 2 ) ; fd . totalblocks = fd . read_ranges ( yes ) . totalblocks ( ) ; if ( error ( ) ) return null ; if ( ( fd . fsize - 1 ) >> fd . log2blocksize >= fd . totalblocks ) return null_with_error ( directory_corrupted ) ; return fd ; } str get_fsname ( BlockDevice ¢ bdev ) { File fd = bdev . new_file ( t_file , null , 0 , new Ranges ( 0 , 1 ) ) ; fd . wide = yes ; do { until ( fd . read_word ( ) == FSMagic1 && fd . read_word ( ) == FSMagic2 ) ; if ( error ( ) ) return null ; if ( ! fd . wide ) return null_with_error ( filesystem_invalid ) ; fd . wide = no ; fd . fpos . lo = 0 ; } if ( fd . read_byte ( ) != bdev . log2blocksize ) return null_with_error ( filesystem_invalid ) ; fd . skip_bytes ( 2 ) ; bdev . wide = fd . wide ; return fd . read_name ( ) ; } File ¢ getRootDirectory ( BlockDevice ¢ bdev ) { clear_error ( ) ; if ( bdev . open_files ) return bdev . open_files [ 0 ] ; str fsname = bdev . get_fsname ( ) ; if ( ! fsname ) return null ; File rootdir = bdev . new_dir ( fsname , 0 , 1 ) ; if ( ! rootdir ) return null ; File fd = rootdir . newFileAtFpos ( ) ; if ( fd && fd . is_file ( ) ) { fd . writable = yes ; bdev . open_files := alloc File [ ] ( 4 ) ; bdev . open_files [ 0 ] := rootdir ; bdev . open_files [ 1 ] := fd ; return rootdir ; } else return null_with_error ( directory_corrupted ) ; } File ¢ getFreeBlocksFile ( BlockDevice ¢ bdev ) { return bdev . open_files ? bdev . open_files [ 1 ] : null ; } File newDeviceFile ( BlockDevice ¢ bdev ) { return bdev . new_file ( t_file , bdev . name , 0 , new Ranges ( 0 , bdev . totalblocks ) ) ; } bool writeFilesystem ( BlockDevice ¢ bdev , str ¢ name , bool wide ) { assert1 ( wide || bdev . totalblocks < 32768 ) ; assert1 ( ! bdev . open_files ) ; const uint root_i = 1 ; const uint root_n = 2 ; const uint free_i = root_i + root_n ; const uint root_size = ( 1 + 6 + 5 + 1 + 4 + 1 + 5 + 1 ) ; clear_error ( ) ; bdev . wide = wide ; uint32 mdate = wide ? systemtime : systemtime / seconds_per_day ; File fd = bdev . newDeviceFile ( ) ; fd . write_words ( FSMagic1 , FSMagic2 ) ; fd . write_byte ( fd . log2blocksize ) ; fd . write_word ( fd . totalblocks ) ; fd . write_name ( name ) ; ( void ) fd . setfpos ( fd . blocksize ) ; fd . write_byte ( DirMagic ) ; fd . write_word ( 0 ) ; fd . write_words ( root_size << wide , mdate ) ; fd . write_byte ( 1 ) ; fd . write_words ( root_i , root_n ) ; fd . write_byte ( t_file ) ; fd . write_words ( 4 << wide , mdate ) ; fd . write_byte ( 0 ) ; fd . write_byte ( 1 ) ; fd . write_words ( free_i , fd . totalblocks - free_i ) ; fd . write_byte ( t_endmarker ) ; return error ( ) || fd . purge_buffer ( ) ; } uint find_range ( File ¢ fd , uint32 bpos ) { uint wsize = 2 << fd . wide ; uint rmask = 65532 << fd . wide ; uint a = 0 ; uint e = fd . fsize ; * ( uint16 * ) & scratch [ 1 ] = 0 ; if ( e == 0 || fd . setfpos ( e + rmask ) || fd . read ( scratch , 0 , wsize ) || bpos < * ( uint32 * ) & scratch [ 0 ] ) return e ; do { while a < e ; uint m = ( ( a + e ) >> 1 ) & rmask ; until fd . setfpos ( m ) ; until fd . read ( scratch , 0 , wsize ) ; if ( bpos >= * ( uint32 * ) & scratch [ 0 ] ) e = m ; else a = m - rmask ; } return e ; } void return_blocks ( BlockDevice ¢ bdev , Range ¢ range ) { File ¢ fd = bdev . getFreeBlocksFile ( ) ; if ( ! fd ) return ; if ( ! range ) return ; if ( range . count == 0 ) return ; uint fpos = fd . find_range ( range . start ) ; if ( error ( ) ) return ; uint32 lstart ; uint32 lcount ; uint32 hstart ; uint32 hcount ; uint rsize = 4 << fd . wide ; if ( fpos < fd . fsize ) fd . read_range_at ( fpos , lstart , lcount ) ; bool merge_l = range . start == lstart + lcount ; if ( fpos ) fd . read_range_at ( fpos - rsize , hstart , hcount ) ; bool merge_h = range . start + range . count == hstart ; if ( merge_l ) { if ( merge_h ) { fd . write_range_at ( fpos - rsize , lstart , lcount + range . count + hcount ) ; ( void ) fd . close_gap ( fpos , rsize ) ; } else { fd . write_range_at ( fpos , lstart , lcount + range . count ) ; } } else { if ( merge_h ) { fd . write_range_at ( fpos - rsize , range . start , range . count + hcount ) ; } else { if ( fd . fsize == fd . totalblocks << fd . log2blocksize ) { fd . ranges += range ; fd . totalblocks += range . count ; fd . file_dirty = yes ; } else if ( fpos < fd . fsize ) { ( void ) fd . open_gap ( fpos , rsize ) ; } fd . write_range_at ( fpos , range . start , range . count ) ; } } } Range allocate_blocks ( BlockDevice ¢ bdev , uint32 maxnum , uint32 bestpos ) { assert1 ( maxnum >= 1 ) ; File ¢ fd = bdev . getFreeBlocksFile ( ) ; if ( ! fd ) return null ; if ( fd . fsize == 0 ) { Ranges ¢ ranges = fd . ranges ; if ( ranges . count ( ) == 0 ) return null_with_error ( disk_full ) ; fd . file_dirty = yes ; Range ¢ r = ranges [ ranges . count ( ) - 1 ] ; if ( r . count <= maxnum ) { fd . totalblocks -= r . count ; return ranges . pop ( ) ; } else { fd . totalblocks -= maxnum ; r . start += maxnum ; r . count -= maxnum ; return new Range ( r . start - maxnum , maxnum ) ; } } uint fpos = fd . find_range ( bestpos ) ; if ( error ( ) ) return null ; uint rsize = 4 << fd . wide ; if ( fpos == fd . fsize ) fpos -= rsize ; uint32 rstart ; uint32 rcount ; fd . read_range_at ( fpos , rstart , rcount ) ; if ( error ( ) ) return null ; if ( rstart < bestpos && fpos != 0 ) { fpos -= rsize ; fd . read_range_at ( fpos , rstart , rcount ) ; if ( error ( ) ) return null ; } if ( rcount > maxnum ) { fd . write_range_at ( fpos , rstart + maxnum , rcount - maxnum ) ; return new Range ( rstart , maxnum ) ; } else { ( void ) fd . close_gap ( fpos , rsize ) ; return new Range ( rstart , rcount ) ; } } } ""