*! version 0.9.1 June 17, 1998 @ 12:28:08
*! Extracts command lines and comments from logfile, excludes command
*! leading to errors and comments out line feeds
program define log2do
version 5.0
*--------+---------+---------+---------+---------+---------+---------+---------+
* Project:    ADO
* Program:    cmdlog.ado
* Version:    0.8 (test version - backup of files recommended)
* Author:     Morten Andersen
* Created:    1998-04-24
* Modified:   1998-05-28
* Requires:   Stata log file "filename.log"
* Parameter:  "filename"
* Function:   Extracts command lines and comments from log, excludes commands
*             leading to errors and comments out line feeds
* Result:     ASCII file "filename.do" (overwrites existing file)
* Note:       File in some cases needs tidying up in a text processor
*--------+---------+---------+---------+---------+---------+---------+---------+
	if _N {
		display in red "log2do must be run in an empty data set"
		exit 18
		}
	parse "`*'", parse(",")
	local source "`1'"
	mac shift
	local options "replace"
	parse "`*'"
	if "`replace'"=="" {
		confirm new file `source'.do
		}
	display "Source file `source'.log"

	capture n {
		quietly {
			/* import source file as string variable in dataset */
			infix str80 line 1-80 using `source'.log

			/* identify 1st and following lines of commands, */
			/* comments and errors and only keep these */
			gen str2 first2 = substr(line,1,2)
			gen str1 first1 = substr(first2,1,1)
			/* remove blank lines */
			drop if line=="." | line==""
			/* generate line numbers */
			gen int lno = _n
			/* identify 1st line of each command */
			gen byte cl1 = first2==". "
			/* identify wrapped lines of commands */
			gen byte clf = 0
			replace clf = ( first2=="> " & ( cl1[_n-1] | clf[_n-1]) ) in 2/l
			/* identify commands inserted by automatic log program */
			gen byte com = ( first1=="*" )
			/* identify errors */
			gen byte err = first2=="r(" & index(line,");")
			/* keep the interesting lines */
			keep if com | cl1 | clf | err
			/* command numbers */
			gen int cno = sum(cl1)
			/* remove commands with errors */
			count if err
			noisily display %4.0f _result(1), " commands dropped due to errors"
			sort cno err
			qui by cno: replace err = err[_N]
			drop if err
			/* command line numbers */
			sort cno lno
			qui by cno: gen byte clno = _n
			quietly by cno: gen byte mclno = _N
			/* remove . and > */
			replace line = substr(line,3,.) if (cl1 | clf)
			/* move excess characters to next line */
			gen byte exc = length(line)-76 if clf
			sort cno clno
			qui by cno: gen byte sumexc = sum(exc)
			gen str20 mov = substr(line,-sumexc,.) if sumexc > 0
			replace line = substr(line,1,length(line)-sumexc) if sumexc > 0
			replace line = mov[_n-1] + line if sumexc[_n-1] > 0
			/* add new lines if excess characters on last line */
			count if sumexc > 0 & clno==mclno
			if _result(1) > 0 {
            tempfile tmp
			   save `tmp', replace
            keep if sumexc > 0 & clno==mclno
            replace line = mov
            replace clno = clno + 1
            append using `tmp'
				}
			sort cno clno
			/* comment out line feeds */
			replace line = "*/" + line if clf
			replace line = line + "/*" if clf[_n+1]  & _n<_N
		 	/* output to result file */
			sort cno clno
			keep line
			/* get rid of final log close (if applicable) */
			if line[_N]=="log close" {
				drop in l
				}
			outsheet using `source'.do, noquote nonames `replace'
			noisily display %4.0f _N, "command lines extracted and saved"
			noisily display "Result file `source'.do"
			}	/* end quietly block */
		}	/* end capture block */
	local rc = _rc
	clear
	exit `rc'
end

* End program
*--------+---------+---------+---------+---------+---------+---------+---------+