program cleancmdline, rclass
*!	Version 1.5 by Mead Over 31Jan2019
*	This programs accepts the command line from either a single or a
*	multiequation estimator and returns a simplified command line which
*	begins with the dependent variable.  For a multiequaiton command like
*	-sureg- or -reg3-, this program strips e(cmdline) of the estimation command,
*	the equation name (identified because it is followed by a colon) and all
*	parentheses.

	syntax , cmdline(string) [NEWDepvar]

	// The program ordinarily requires the dependent variable to already
	// be present in the data in memory.  Specifying the option -newdepvar-
	// directs the program to proceed despite the dependent variable
	// not being in memory.

	local origcmdline `cmdline'
	tokenize `"`cmdline'"', parse(" (")

	// If the first or second token in the command line is a left parenthesis,
	// strip everything up to and including the -(- character from the beginning of the -cmdline-
	if "`1'"=="(" | "`2'"=="(" {
		local cmdline = substr(`"`cmdline'"',strpos(`"`cmdline'"',"(")+1,.)

		//	If the second token was a -(-, then the first is an estimation command
		if "`2'"=="(" {
			local estcmd `1'
		}
	}
	else {  //  Confirm that the first token is an estimation command and remove it
		local token1 `1'
		if strpos("`token1'", ".") >0 {
			local token1 = substr("`token1'",strpos("`token1'", ".")+1,.)
		}
		cap which `token1'
			if _rc>0 {
				local nothere nothere
				local whatshere word
				cap confirm numeric variable `token1'
				if _rc=0 {
					local isnumvar isnumvar
					local whatshere numeric variable
				}
			}
		if "`nothere'`isnumvar'"~="" {
			di as err "First word in the command line should be one of Stata's"  ///
			_n "estimation commands that is linear in the parameters."  ///
			_n "Examples include {help reg}, {help sureg}, {help frontier},"  ///
			_n "{help ivregress} and the user written commmands {help ivreg2} and {reghdfe}, etc.."  ///
			_n "Here the first word in the command line is the `whatshere': " as res "`1'"
			exit 198
		}
		else {  // Strip the estimation command from the beginning of the command line
			local estcmd `1'
			macro shift
			local cmdline `*'
			if "`estcmd'"=="ivregress" {
				local ivmethod `1'
				macro shift
				local cmdline `*'
			}
		}
	}

	//	Now consider the command line without the estimation command or the
	//	equation binding prefixes.
	tokenize `"`cmdline'"', parse(" :")

	if "`2'"==":" {
		local eqname `1'
		local depvar `3'
		local cmdline = substr(`"`cmdline'"',strpos(`"`cmdline'"',":")+1,.)
	}
	else {
		local eqname = word("`e(eqnames)'",1)
		local depvar `1'     //  Changed back to `1' from `2' in ver. 1.31
	}

	capture confirm numeric variable `depvar'
		if _rc~=0 {
			di as err _n "The dependent variable extracted from the command line, `depvar', is not in the data."
			if "`newdepvar'"=="" {
				exit 198
			}
			else {
				di as err "Option -newdepvar- allows execution to continue." _n
			}
		}

	//	Keep the part of the command line before the first left parenthesis
	local firstparen = min(strpos(`"`cmdline'"',"("),strpos(`"`cmdline'"',")"))
	if `firstparen' >0 & `firstparen' < . {
		local dep_exogr = substr(`"`cmdline'"',1,`firstparen'-1)
		if "`estcmd'"=="ivregress" | "`estcmd'"=="ivreg2" |  ///
			"`estcmd'"=="ivreghdfe" | "`estcmd'"=="xtivreg" {
				local firstequals = strpos(`"`cmdline'"',"=")
				local instd = substr(`"`cmdline'"',`firstparen'+1,`firstequals'-`firstparen'-1)
				local closeparen = min(strpos(`"`cmdline'"',")"),length(`"`cmdline'"'))
				local morestuff = substr(`"`cmdline'"',`closeparen'+1,.)
		}
		local cmdline `dep_exogr' `instd' `morestuff'
	}

	//	Truncate the command line after the [in] [if] [using] [weights] or comma,
	//	whichever comes first
	local cmdlngth = length(`"`cmdline'"')
	local endofeq = min(  ///
		cond(strpos(`"`cmdline'"',"(")>0,     strpos(`"`cmdline'"',"("),`cmdlngth'),  ///
		cond(strpos(`"`cmdline'"',",")>0,     strpos(`"`cmdline'"',","),`cmdlngth'),  ///
		cond(strpos(`"`cmdline'"',"[")>0,     strpos(`"`cmdline'"',"["),`cmdlngth'),  ///
		cond(strpos(`"`cmdline'"',"if")>0,    strpos(`"`cmdline'"',"if"),`cmdlngth'),  ///
		cond(strpos(`"`cmdline'"',"in")>0,    strpos(`"`cmdline'"',"in"),`cmdlngth'),  ///
		cond(strpos(`"`cmdline'"',"using")>0, strpos(`"`cmdline'"',"using"),`cmdlngth'),  ///
		cond(strpos(`"`cmdline'"',"weight")>0,strpos(`"`cmdline'"',"weight"),`cmdlngth'),  ///
		cond(strpos(`"`cmdline'"',"fw")>0,    strpos(`"`cmdline'"',"fw"),`cmdlngth'),  ///
		cond(strpos(`"`cmdline'"',"pw")>0,    strpos(`"`cmdline'"',"pw"),`cmdlngth'),  ///
		cond(strpos(`"`cmdline'"',"aw")>0,    strpos(`"`cmdline'"',"aw"),`cmdlngth'),  ///
		cond(strpos(`"`cmdline'"',"iw")>0,    strpos(`"`cmdline'"',"iw"),`cmdlngth'))
	if `endofeq' >0 & `endofeq' < `cmdlngth' {
		local cmdline = substr(`"`cmdline'"',1,`endofeq'-1)
	}

	return local ivmethod `ivmethod'
	return local cmdline `cmdline'
	return local origcmdline `origcmdline'
	return local estcmd `estcmd'
	return local eqname `eqname'
	return local depvar `depvar'

end /* End of program cleancmdline */
*	Version 1.0 13July2016
*	Version 1.1 13July2016		Only change is to edit the comment in line 20
*	Version 1.2 19Aug2016		Clean simple command lines like: "reg y x1 x2 x1*x2"
*	Version 1.21 23Feb2017		Void the equation name for simple command line
*	Version 1.3 1May2018		Truncate the command line after the comma.
*	Version 1.31 11May2018		Change back from `2' to `1' in line 61
*	Version 1.4 23May2018		Option -newdepvar- allows excecution even
*		if dependent variable is not present
*	Version 1.5 31Jan2019		Accommodate IV estimators. No options added.