*! log2do2.ado v1.0.1 Nicholas Winter 16oct2002 program define log2do2 version 7 syntax anything(id="input file") , saving(string) [ replace append ] tempname bin tout num num1 file open `bin' using `anything', binary read file open `tout' using `"`saving'"' , text write `replace' `append' file read `bin' %1bu `num' file read `bin' %1bu `num1' while !r(eof) { if char(`num')=="." & char(`num1')==" " { GetLine `bin' `tout' `num' `num1' 0 /* zero means not in forX loop */ local line `s(line)' if (index(`"`line'"',"forval") | /* */ index(`"`line'"',"foreach")) & /* check for forX, and grab until over */ !index(`"`line'"',"}") { local nbrace 1 while `nbrace'>0 { GetLine `bin' `tout' `num' `num1' `nbrace' local nbrace=`s(nbrace)' } } } else { SkipLine `bin' `num' `num1' } } di `"{txt}Created {res}`saving'"' end program define GetLine, sclass args bin tout num num1 nbrace if `nbrace'>0 { tempname num2 file read `bin' %1bu `num2' local x = char(`num')+char(`num1')+char(`num2') cap confirm number `x' if _rc { scalar `num'=`num2' /* is not a numbered line; so just transfer the next char */ } else { file read `bin' %1bu `num' /* is a numbered line; so skip the period and grab next char */ file read `bin' %1bu `num' } } else { /* not in forX loop, so just get the next character */ file read `bin' %1bu `num' } local done 0 local line while !`done' { if !(`num'==10 | `num'==13) { if `num'==96 { /* only way to output the ` character */ file write `tout' "`" local line `line'` } else { if `num'==32 { local c " " /* only way to assign " " to the local c */ local line `"`line' "' } else { local c=char(`num') local line `line'`c' } file write `tout' `"`c'"' } file read `bin' %1bu `num' } else { /* reached eol character */ while `num'==10 | `num'==13 { file read `bin' %1bu `num' /* slither past */ } file read `bin' %1bu `num1' /* get next character to set up num & num1 */ if (char(`num')==">" & char(`num1')==" ") { /* check for continuation */ file read `bin' %1bu `num' /* ... if so, just keep going */ } else { file write `tout' _n /* ... otherwise terminate line */ local done 1 sreturn local line `"`line'"' if `nbrace'>0 { local line : subinstr local line "{" "{" , all count(local o) local line : subinstr local line "}" "}" , all count(local c) local nbrace = `nbrace'+`o'-`c' sreturn local nbrace `nbrace' } } } } end /* If there is a < for___ ... { > construct, the following lines begin with a number and a period, *OR* with the traditional ". ", if there was a blank line The problem is that the numbered lines are indistinguishable from what is produced by -list- So: check each line for -forval- or -foreach- if yes, count open { and close } take each line until {} is at zero as a command line each of these command lines begins with ". " OR "nnn." where nnn is a right-justified number Note that nested for___ {} constructs will be fine, because they are all listed together, before any output However, the counting of braces will be messed up if any are in comments. Need to think about this. */ program define SkipLine args bin num num1 win *current `num' and `num1' are first two characters of the line to be skipped local done=(`num'==10 | `num'==13) /* we've reached the end */ while !`done' { scalar `num' = `num1' file read `bin' %1bu `num1' local done=(`num'==10 | `num'==13) } while (`num'==10 | `num'==13 | `num1'==10 | `num1'==13) { /* slither past the eol char(s) */ scalar `num' = `num1' file read `bin' %1bu `num1' } end