I've written a number of Mata routines but am unsure of the "best" way
to compile them to object code. (I've included an example of one of my
source files - be cautious of linewraps to handle the perennial
problem of popping filenames off the end of strings or getting a
"bare-ended" path to which one can add a "`c(dirsep)'" to prevent
problems arising from having a ...\' at the end of directory strings.
The undocumented _getfilename.ado works but I find the path handling
functions of Mata to be more useful. The various pathparts are
returned as sreturn macros.)
Since Mata files are compiled into object code as *.mo files (or added
into a mlib), if one wants to save the source code, there has to be an
intermediate step of saving and then compiling the source (or
compiling and saving the command history in the case of an interactive
session). In [M-1] source -- Viewing the source code we learn that
the convention for Mata source is to save as a *.mata file. In the
manual [M-1] Working with Object code I & II and [M-3] mata mosave
there are no examples of creating source files and then compiling them
to *.mo although there are some examples of "doing" *.mata files to
compile them and then saving the functions to a mlib library. I wrote
the pathparts.mata example below with a -mosave- step appended at the
end, so it is not a "pure" *.mata source file. -mosave- must be done
one file/function at a time, while the -mlib- process can optionally
occur as a batch, perhaps at the end of a file defining several
functions.
So I'm interested in how others, including Stata, have handled the
maintenance of source files, compiling to *.mo or *.mlib files. I'm
in the process of writing a compile_mo and a compile_mlib command and
would like to come up with something that makes sense in terms of how
people manage creating and saving functions.
pathparts.mata source
X--------------------------------------X
*! version 1.1 2007-06-14
*! function to return a pathname
*! split into component parts
*! each saved in a sreturn macro
*! David C. Elliott MD, MSc dcelliott[at]gmail.com
version 9.0
mata:
mata clear
void pathparts(string scalar path)
{
string scalar pathname, filename, fileext, pathnoext, filenoext, swidth
real scalar width
// Create the parts
pathsplit(path, pathname="", filename="")
fileext = pathsuffix(path)
pathnoext = pathrmsuffix(path)
pathsplit(pathnoext, pathname, filenoext="")
// Save the parts
st_global("s(fileext)", fileext)
st_global("s(filenoext)", filenoext)
st_global("s(pathnoext)", pathnoext)
st_global("s(filename)", filename)
st_global("s(pathname)", pathname)
st_global("s(path)", path)
// Display the parts
width = strlen(path) + 1
if (width > c("linesize") + 16) { // check against current linesize
width = c("linesize") - 16
}
swidth = strofreal(width)
line = sprintf("{txt}\nsreturn macro {c |} {center " + swidth +
":contains}\n")
line = line + sprintf("{txt:{hline 14}{c +}{hline " + swidth + "}}\n")
line = line + sprintf("{txt}{ralign 13:s(path)} {c |} {res}%-" +
swidth + "s\n",path)
line = line + sprintf("{txt}{ralign 13:s(pathname)} {c |} {res}%-"
+ swidth + "s\n",pathname)
line = line + sprintf("{txt}{ralign 13:s(filename)} {c |} {res}%-"
+ swidth + "s\n",filename)
line = line + sprintf("{txt}{ralign 13:s(pathnoext)} {c |}
{res}%-" + swidth + "s\n",pathnoext)
line = line + sprintf("{txt}{ralign 13:s(filenoext)} {c |}
{res}%-" + swidth + "s\n",filenoext)
line = line + sprintf("{txt}{ralign 13:s(fileext)} {c |} {res}%-"
+ swidth + "s\n",fileext)
line = subinstr(line, char(10), "\n") // this line sidesteps a
Mata bug involving the handling
// of hex numbers in the middle of strings
printf(line)
}
mata mosave pathparts(), dir(PERSONAL) replace // edit dir() to
reflect location choice for Mata object code
end
X--------------------------------------X
--
David Elliott
*
* For searches and help try:
* http://www.stata.com/support/faqs/res/findit.html
* http://www.stata.com/support/statalist/faq
* http://www.ats.ucla.edu/stat/stata/