\ rename.fs - little tool which renames tracks of a ripped audio-cd \ (via cdda2wav named audio_$d.wav ) to their real names according to \ a provided cddb-file : unblank ( caddr1 u -- ) \ substitutes each blank (space) with an _ in the given string bounds +do i c@ bl = if 95 i c! endif 1 chars +loop ; \ just to demonstrate, how fast learning forth can be: \ this version was coded 2h before the above one \ : unblank ( caddr1 u -- caddr2 u ) \ \ substitutes each blank (space) with an _ in the given string \ { u } \ u dup \ here swap chars allot \ swap 0 u+do ( caddr1 caddr2 ) \ over i chars + c@ bl = if ( caddr1 caddr2 ) \ 95 over i chars + c! \ else ( caddr1 caddr2 ) \ over i chars + c@ ( caddr1 caddr2 c ) \ over i chars + c! \ endif ( caddr1 caddr2 ) \ loop \ nip u ; : concat ( caddr1 u1 caddr2 u2 -- caddr3 u3 ) \ concatenate 2 strings 2swap rot 2dup + dup >r here swap chars allot ( c2 c1 u1 u2 c3 ) 2swap rot over over + ( c2 u2 c1 u1 c3 c3' ) >r dup 2swap rot swap cmove ( c2 u2 c3 ) rot rot r> swap cmove r> ; : commandprefix ( -- caddr u ) s" mv audio_" ; : extension ( -- caddr u ) s" .wav " ; : num2str ( n -- caddr u ) \ take a number < 100 and make a string out of it i.e. ( 99 -> "99" ) here 2 chars allot swap 10 /mod 48 + rot dup rot swap c! dup rot 48 + swap char+ c! 2 ; : str2num ( caddr u -- u ) \ converts the provided string to an unsigned number, should any character \ be not between 48 ( ascii 0 ) and 57 ( ascii 9 ) an exception is thrown 0 rot rot bounds +do i c@ dup 48 < ( n c f ) over 57 > or if ( n c ) 1 throw else 48 - swap 10 * + endif 1 chars +loop ; : indexof ( c caddr u -- n ) \ searches the string for first occurence of character c and returns its index over >r 0 rot rot ( c 0 caddr u ) bounds +do drop i c@ ( c c' ) over = if i leave else i 1 + endif 1 chars +loop r> - nip ; : prefix ( c caddr1 u1 -- caddr2 u2 ) \ searches the string for the character c, copies all characters up to, \ but not including, the first occurence of c, if the string does not contain c \ simply returns input { c ad u } c ad u indexof ( n ) u over = if drop ad u else ( n ) here over chars allot ( n c2 ) swap 2dup ad rot rot ( c1 c2 n ) cmove ( c2 n ) endif ; : postfix ( c caddr1 u1 -- caddr2 u2 ) \ like prefix but copies the reminder after the first occurence or result points to the end of string and u2 = 0 { c ad u } c ad u indexof ( n ) u over = if drop ad u + 0 else 1+ dup ad + swap ( c1' n ) u swap - here over chars allot ( c1' n' c2 ) swap 2dup >r >r cmove r> r> endif ; : cddb2cmd ( caddr u -- ) \ takes a line from the cddbfile - if it is a trackline (starting with TTITLE ) \ "builds " the command for moving it ( i.e. "mv audio$d.wav real_name.wav") \ and executes it 2dup s" TTITLE" string-prefix? if ( caddr u ) commandprefix >r >r 6 /string ( caddr u ) 2dup 61 rot rot prefix ( caddr1 u1 caddr2 u2 ) str2num 1+ num2str extension concat ( caddr u ) \ 2dup type r> r> 2swap concat >r >r ( caddr1 u1 ) 2dup 61 rot rot postfix 2dup unblank extension concat r> r> 2swap concat \ type system endif 2drop ; 0 Value cddb-in 256 Constant max-line Create cddbline max-line 2 + allot : opencddb ( caddr u -- ) \ open the cddb file, the name whichof is stored in the string at caddr and \ create a Value for the file r/o open-file throw to cddb-in ; : closecddb ( -- ) cddb-in close-file throw ; : rename ( caddr u -- ) \ opens file with the provided name and renames the tracks accordingly opencddb begin cddbline max-line cddb-in read-line throw ( u f ) while cddbline swap cddb2cmd repeat closecddb ;