*! 2.0.0 NJC 12 January 2011
* 1.1.0 NJC 21 December 2010
* 1.0.0 NJC 20 December 2010
program fromroman
	version 9
	syntax varname(string) [if] [in] , Generate(str) [re(str)]

	quietly {
		marksample touse, strok
		count if `touse'
		if r(N) == 0 error 2000

		confirm new variable `generate'

		if "`re'" == "" {
			local re  ^M*(C|CC|CCC|CD|D|DC|DCC|DCCC|CM)?
			local re `re'(X|XX|XXX|XL|L|LX|LXX|LXXX|XC)?
			local re `re'(I|II|III|IV|V|VI|VII|VIII|IX)?$
		}

		tempvar work totry
		gen `work' = upper(subinstr(`varlist', " ", "",.)) if `touse'
		gen byte `totry' = `touse' & regexm(`work', "`re'")
		mata : from_roman("`work'", "`generate'", "`totry'")

		replace `generate' = . if `work' != "" & `touse'
		compress `generate'
		count if `work' != "" & `touse'
	}

	if r(N) {
		di _n as txt "Problematic input: "
		list `varlist' if `work' != "" & `touse'
	}
end

mata :

void from_roman(string scalar varname,
string scalar genname,
string scalar usename) {
	string colvector sin, sin2, rom
	real colvector nout, num
	real scalar i

	sin = st_sdata(., varname, usename)
	nout = J(rows(sin), 1, 0)
	rom = ("CM", "CD", "XC", "XL", "IX", "IV", "M", "D", "C", "L",
		"X", "V", "I")'
	num = (900, 400, 90, 40, 9, 4, 1000, 500, 100, 50, 10, 5, 1)'

	for (i = 1; i <= rows(rom); i++) {
		sin2 = subinstr(sin, rom[i], "", .)
		nout = nout + num[i] *
			(strlen(sin) - strlen(sin2)) / strlen(rom[i])
		sin = sin2
	}

	(void) st_addvar("long", genname)
	st_store(., genname, usename, nout)
	st_sstore(., varname, usename, sin)
}

end