You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

502 lines
11 KiB
Plaintext

7 months ago
*! version 1.2.11 18feb2010
program define sjlog
if _caller() < 8.0 {
sjlog_7 `0'
exit
}
version 8.0
local vv : display _caller()
gettoken cmd 0 : 0, parse(" ,")
local l = length(`"`cmd'"')
if `"`cmd'"' == "using" | `"`cmd'"' == "open" {
LogOpen `0'
}
else if `"`cmd'"' == "close" {
LogClose `0'
}
else if `"`cmd'"' == "do" {
LogDo `vv' `0'
}
else if `"`cmd'"' == "clean" {
LogClean `0'
}
else if `"`cmd'"' == "type" {
LogType `0'
}
else if `"`cmd'"' == substr("basename",1,`l') {
LogBaseName `0'
}
else if `"`cmd'"' == "" {
log
}
else {
di as err "`cmd' invalid"
exit 198
}
end
program define LogSetup
syntax [, clear ]
if "`clear'" != "" {
clear
program drop _all
}
capture log close
set rmsg off
set more off
set trace off
end
program define StripQuotes
syntax anything(name=name id="name") [, string(string) ]
c_local `name' `"`string'"'
end
/* basename *****************************************************************/
program define LogBaseName, rclass
syntax anything(name=file id="filename") [, Display ]
StripQuotes file , string(`file')
local dirsep "/"
/* strip off the directory path */
gettoken dir rest : file, parse("/\:")
while `"`rest'"' != "" {
if `"`dir'"' == "\" {
local dir `"`dirsep'"'
}
local dirname `"`dirname'`dir'"'
gettoken dir rest : rest , parse("\/:")
}
if `"`dirname'"' == "" {
local dirname .`dirsep'
}
/* strip off the extension */
gettoken ext rest : dir, parse(".")
while `"`rest'"' != "" {
local basename `basename'`ext'
gettoken ext rest : rest , parse(".")
}
if `"`basename'"' == "" {
local basename `ext'
local ext
}
else {
/* remove the last "." from `basename' */
local l = length(`"`basename'"') - 1
local basename = substr(`"`basename'"',1,`l')
}
/* saved results */
return local ext = cond(`"`ext'"'=="","",".") + `"`ext'"'
return local base `"`basename'"'
return local dir `"`dirname'"'
return local fn `"`file'"'
if `"`display'"' != "" {
display as txt `"fn: `return(fn)'"'
display as txt `"dir: `return(dir)'"'
display as txt `"base: `return(base)'"'
display as txt `"ext: `return(ext)'"'
}
end
/* using/close/do: subroutines **********************************************/
program define LogOpen
syntax anything(name=file id="filename") [, append replace ]
LogSetup
LogBaseName `file'
local ext `"`r(ext)'"'
if `"`ext'"' != ".smcl" {
local file `"`r(fn)'.smcl"'
}
quietly log using `"`file'"', smcl `append' `replace'
end
program define LogClose, rclass
syntax [, /*
*/ book /*
*/ replace /*
*/ noCLEAN /*
*/ noLOGfile /*
*/ sjlogdo /* internal only, NOT documented
*/ ]
if `"`sjlogdo'"' == "" {
local logtype sjlog
}
else local logtype `sjlogdo'
quietly log
LogBaseName `"`r(filename)'"'
local dir `"`r(dir)'"'
local base `"`r(base)'"'
local ext `"`r(ext)'"'
local file `"`r(fn)'"'
local dbase `"`dir'`base'"'
quietly log close
/* log assumed to be a smcl file */
if `"`ext'"' != ".smcl" {
di in red "assumption failed -- log file not smcl"
exit 198
}
if `"`clean'"' == "" {
LogClean `"`file'"', `logtype'
erase `"`r(fnbak)'"'
}
/* get TeX version of log */
qui log texman `"`file'"' `"`dbase'.log.tex"', `replace' `book'
if `"`logfile'"' == "" {
/* get plain text version of log */
qui translate `"`file'"' `"`dbase'.log"', `replace'
}
/* saved results */
if `"`logfile'"' == "" {
return local fn_log `"`dbase'.log"'
}
return local fn_tex `"`dbase'.log.tex"'
return local fn_smcl `"`dbase'.smcl"'
end
program define LogDo
version 8.0
gettoken vv 0 : 0
local vv "version `vv':"
syntax anything(name=file id="filename") [, ///
clear ///
replace ///
book ///
nostop ///
SAVing(string) ///
]
if "`saving'" != "" {
capture confirm name `saving'
if _rc {
di as err ///
"'`saving'' found where saving() option requires a valid name"
exit 198
}
}
LogSetup, `clear'
LogBaseName `file'
local base = cond("`saving'"=="","`r(base)'","`saving'")
local dbase `"`r(dir)'`base'"'
local ext `"`r(ext)'"'
local file `"`r(fn)'"'
if `"`ext'"' != ".do" {
local dbase `"`dbase'`ext'"'
}
LogOpen `dbase', `replace'
capture noisily `vv' do `file', `stop'
local rc = _rc
if `rc' {
local cap capture
}
`cap' LogClose, `replace' sjlogdo `book'
exit `rc'
end
/* clean: subroutines *******************************************************/
program define LogClean, rclass
syntax anything(name=file id="filename") [, /*
*/ log /*
*/ logclose /*
*/ sjlog /*
*/ sjlogdo /*
*/ ]
/* validate arguments and options */
local logsrc `log' `logclose' `sjlog' `sjlogdo'
local wc : word count `logsrc'
if `wc' > 1 {
di as err "options `logsrc' may not be combined"
exit 198
}
StripQuotes file , string(`file')
confirm file `"`file'"'
/* open files */
tempname rf wf
tempfile newfile
file open `rf' using `"`file'"', read text
file open `wf' using `"`newfile'"', write text
/* clean file */
capture noisily {
if `"`logsrc'"' == "logclose" {
CleanLogclose `rf' `wf'
}
else if `"`logsrc'"' == "sjlog" {
CleanSJLog `rf' `wf'
}
else if `"`logsrc'"' == "sjlogdo" {
CleanSJLogDo `rf' `wf'
}
else { /* Default: `"`logsrc'"' == "log" */
CleanLog `rf' `wf'
}
} // capture noisily
local rc = _rc
/* close files */
file close `wf'
file close `rf'
if (`rc') exit `rc'
/* make a backup copy of the input file (rf) and save the output file
* (wf) using the given filename
*/
local backup `file'.bak
copy `"`file'"' `"`backup'"', replace
copy `"`newfile'"' `"`file'"', replace
/* saved results */
return local fnbak `"`backup'"'
return local fn `"`file'"'
end
/* Clean log produced by -sjlog do-.
*
* This subroutine has a 3 line buffer; the end of a log from -sjlog do- will
* always have:
*
* 1. a blank line
* 2. a line with the text: "."
* 3. a line with the text: "end of do-file"
*
* This subroutine also works with smcl files, and TeX files generated from
* smcl files using -log texman- (its original purpose).
*/
program define CleanSJLogDo
args rf wf
/* skip the smcl header lines */
file read `rf' line1
if `"`line1'"' == "{smcl}" {
file read `rf' line1
/* skip next line too, if is part of the smcl header */
if `"`line1'"' == "{com}{sf}{ul off}{txt}" {
file read `rf' line1
}
file read `rf' line2
}
else {
file read `rf' line2
}
file read `rf' line3
local break 0
while r(eof)==0 {
if substr(`"`line3'"',-14,.) == "end of do-file" {
local break 1
continue, break
}
file write `wf' `"`macval(line1)'"' _n
local line1 `"`macval(line2)'"'
local line2 `"`macval(line3)'"'
file read `rf' line3
}
if ! `break' {
file write `wf' `"`macval(line1)'"' _n
file write `wf' `"`macval(line2)'"' _n
}
else {
if !inlist(`"`macval(line1)'"',"{txt}","{res}{txt}") {
file write `wf' `"`macval(line1)'"' _n
}
}
end
/* Clean log produced by -sjlog using- and -sjlog close-. */
program define CleanSJLog
args rf wf
CleanLogUsingHeader `rf'
/* skip the smcl header lines */
file read `rf' line1
if `"`line1'"' == "{smcl}" {
file read `rf' line1
/* skip next line too, if is part of the smcl header */
if `"`line1'"' == "{com}{sf}{ul off}{txt}" {
file read `rf' line1
}
file read `rf' line2
}
else {
file read `rf' line2
}
local break 0
while r(eof)==0 {
if index(`"`line2'"',". sjlog close") {
local break 1
continue, break
}
file write `wf' `"`macval(line1)'"' _n
local line1 `"`macval(line2)'"'
file read `rf' line2
}
if ! `break' | !inlist(`"`macval(line1)'"', "", "{res}{txt}") {
file write `wf' `"`macval(line1)'"' _n
}
end
/* Clean log produced by Stata's -log using- and -log close- commands. */
program define CleanLog
args rf wf
CleanLogUsingHeader `rf'
file read `rf' line
local break 0
while r(eof)==0 {
/* stop when we encounter the -log close- command. */
if substr(`"`line'"',-11,.) == ". log close" {
local break 1
continue, break
}
file write `wf' `"`macval(line)'"' _n
file read `rf' line
}
end
/* Clean log produced by Stata's -log using- command and -logclose-. */
program define CleanLogclose
args rf wf
CleanLogUsingHeader `rf'
file read `rf' line
local break 0
while r(eof)==0 {
/* stop when we encounter the -log close- command. */
if substr(`"`line'"',-10,.) == ". logclose" {
local break 1
continue, break
}
file write `wf' `"`macval(line)'"' _n
file read `rf' line
}
end
/* Skip first 5 lines comprising the header output from -log using-. */
program define CleanLogUsingHeader
args rf
/* hline */
file read `rf' line
if `"`line'"' == "{smcl}" {
file read `rf' line
file read `rf' line
}
else if index(`"`line'"', "-----") {
file read `rf' line
}
if ! index(`"`line'"', "log:") {
file seek `rf' tof
exit
}
file read `rf' line
if ! index(`"`line'"', "log type:") {
file seek `rf' tof
exit
}
file read `rf' line
if ! index(`"`line'"', "opened on:") {
file seek `rf' tof
exit
}
/* blank line */
file read `rf' line
end
/* type: subroutines ********************************************************/
program define LogType, rclass
syntax anything(name=file id="filename") [, /*
*/ replace /*
*/ find /*
*/ path(passthru) /*
*/ LOGfile /*
*/ SMCLfile /*
*/ ]
LogSetup
if "`logfile'" == "" {
local logfile nologfile
}
StripQuotes file , string(`file')
if `"`find'"' != "" {
capture which findfile
if _rc {
di as err "option find requires Stata 8 or later"
exit 111
}
quietly findfile `"`file'"', `path'
local file `r(fn)'
}
LogBaseName `file'
local file `"`r(fn)'"'
local dbase `"`r(dir)'`r(base)'"'
local ext `"`r(ext)'"'
if ! inlist(`"`ext'"',".smcl",".hlp") {
local dbase `"`dbase'`ext'"'
}
capture noisily {
tempfile tt
LogOpen `tt'
type `"`file'"'
LogClose, noclean `logfile'
copy `"`tt'.log.tex"' `"`dbase'.log.tex"', `replace'
return local fn_tex `"`dbase'.log.tex"'
if "`logfile'" == "logfile" {
copy `"`tt'.log"' `"`dbase'.log"', `replace'
return local fn_log `"`dbase'.log"'
}
}
local rc = _rc
if "`smclfile'" != "" {
copy `"`tt'.smcl"' `"`dbase'.smcl"', `replace'
return local fn_smcl `"`dbase'.smcl"'
}
capture erase `"`tt'.smcl"'
capture erase `"`tt'.log.tex"'
exit `rc'
end
exit