Basic housekeeping code is required by all EMBOSS and EMBASSY applications. This includes code to process the command line and application ACD file, handle user inputs, retrieve AJAX objects corresponding to data definitions in the ACD file, and to exit cleanly.
Every application must process the ACD file and user input. It must:
Read in local database definitions
Find the right ACD file to use and parse it
Parse the command line
Prompt the user for required values not specified on the command line
Validate user input and reprompt for any incorrect values
Allocate memory for an AJAX object for each ACD data definition
Open input and output files
Read input files (the first sequence from any input sequence stream is read)
Initialise the AJAX objects (from reading the input files)
A single call is made to handle all of the above.
For EMBOSS applications:
embInit(" |
For EMBASSY applications:
embInitP(" |
All applications must call one of the above right at the start of the application. ApplicationName
is the name of the ACD file to parse (ApplicationName
.acd). PackageName
is the name of the EMBASSY package, for example "myemboss"
. The command line is required which is why argc
and argv
from main
are passed. Once these functions return then no further interaction with the user occurs. All input is read and held in memory before the application proper begins. An AJAX object for each ACD data definition is allocated.
For a simple program with no ACD data definitions, the first few lines of the program would look like this:
int main(int argc, char **argv) { embInit("helloworld", argc, argv);
The ajAcdGet*
family of functions return AJAX objects for data definitions in the application ACD file. They are defined in ajacd.h/c
and have the general name:
ajAcdGet |
where Datatype
is one of the supported ACD datatypes (Section A.2, “Datatypes”).
A prefix ajAcdGet
function is provided for each ACD datatype. They are not constructor functions as such, but instead return a pointer to an appropriate AJAX object that has been allocated by a call to embInit
or embInitP
. For example, when retrieving an ACD string
, ajAcdGetString
returns a pointer to the string (an AjPStr
object) created by embInit
. Attributes in the data definition and user input gathered at the command line are used to initialise the object. Memory for any new objects must be freed later on in main()
.
ACD datatype | AJAX datatype (return value) | AJAX Function |
---|---|---|
align | AjPAlign | ajAcdGetAlign |
array | AjPFloat | ajAcdGetArray |
boolean | AjBool | ajAcdGetBoolean |
codon | AjPCod | ajAcdGetCodon |
cpdb | AjPFile | ajAcdGetCpdb |
datafile | AjPFile | ajAcdGetDatafile |
directory | AjPDir | ajAcdGetDirectory |
| AjPStr | ajAcdGetDirectoryName |
dirlist | AjPList | ajAcdGetDirlist |
discretestates | AjPPhyloState* | ajAcdGetDiscretestates |
| AjPPhyloState | ajAcdGetDiscretestatesSingle |
distances | AjPPhyloDist* | ajAcdGetDistances |
| AjPPhyloDist | ajAcdGetDistancesSingle |
featout | AjPFeattabOut | ajAcdGetFeatout |
features | AjPFeattable | ajAcdGetFeatures |
filelist | AjPList | ajAcdGetFilelist |
float | float | ajAcdGetFloat |
| double | ajAcdGetFloatDouble |
frequencies | AjPPhyloFreq | ajAcdGetFrequencies |
graph | AjPGraph | ajAcdGetGraph |
graphxy | AjPGraph | ajAcdGetGraphxy |
infile | AjPFile | ajAcdGetInfile |
int | ajint | ajAcdGetInt |
| ajlong | ajAcdGetIntLong |
list | AjPStr* | ajAcdGetList |
| AjPStr | ajAcdGetListSingle |
matrix | AjPMatrix | ajAcdGetMatrix |
matrixf | AjPMatrixf | ajAcdGetMatrixf |
outcodon | AjPOutfile | ajAcdGetOutcodon |
outcpdb | AjPOutfile | ajAcdGetOutcpdb |
outdata | AjPOutfile | ajAcdGetOutdata |
outdir | AjPDirout | ajAcdGetOutdir |
| AjPStr | ajAcdGetOutdirName |
outdiscrete | AjPOutfile | ajAcdGetOutdiscrete |
outdistance | AjPOutfile | ajAcdGetOutdistance |
outfile | AjPFile | ajAcdGetOutfile |
outfileall | AjPFile | ajAcdGetOutfileall |
outfreq | AjPOutfile | ajAcdGetOutfreq |
outmatrix | AjPOutfile | ajAcdGetOutmatrix |
outmatrixf | AjPOutfile | ajAcdGetOutmatrixf |
outproperties | AjPOutfile | ajAcdGetOutproperties |
outscop | AjPOutfile | ajAcdGetOutscop |
outtree | AjPOutfile | ajAcdGetOuttree |
pattern | AjPPatlistSeq | ajAcdGetPattern |
properties | AjPPhyloProp | ajAcdGetProperties |
range | AjPRange | ajAcdGetRange |
regexp | AjPPatlistRegex | ajAcdGetRegexp |
| AjPRegexp | ajAcdGetRegexpSingle |
report | AjPReport | ajAcdGetReport |
scop | AjPFile | ajAcdGetScop |
select | AjPStr* | ajAcdGetSelect |
| AjPStr | ajAcdGetSelectSingle |
seq | AjPSeq | ajAcdGetSeq |
seqall | AjPSeqall | ajAcdGetSeqall |
seqout | AjPSeqout | ajAcdGetSeqout |
seqoutall | AjPSeqout | ajAcdGetSeqoutall |
seqoutset | AjPSeqout | ajAcdGetSeqoutset |
seqset | AjPSeqset | ajAcdGetSeqset |
seqsetall | AjPSeqset* | ajAcdGetSeqsetall |
| AjPSeqset | ajAcdGetSeqsetallSingle |
string | AjPStr | ajAcdGetString |
toggle | AjBool | ajAcdGetToggle |
tree | AjPPhyloTree* | ajAcdGetTree |
| AjPPhyloTree | ajAcdGetTreeSingle |
It's recommended that variables for handling ACD datatypes should have the same name as the parameter or qualifier in question i.e. the name given in the ACD data definition. This is not strictly required but it makes the code much easier to understand. For the same reason all calls to ajAcdGet*
functions should be given in a single block of code for ease of reading.
Example. Consider the following ACD file:
application: example [ documentation: "Example application." ] string: astring [ default: "String to be printed to screen." ]
Here is the C source code to print astring
to the screen:
int main(int argc, char **argv) { AjPStr astring = NULL; embInit("example", argc, argv); astring = ajAcdGetString("astring") ajFmtPrint("%S\n", astring); ajStrDel(&astring); embExit(); return 0; }
The code declares an AJAX string object (AjPStr
) and calls embInit
to invoke ACD file processing. embInit
allocates memory for the string object which is why the above code does not call a string constructor function explicitly. Nonetheless a string object was created by embInit
and should be freed once you are done with it. That is why ajStrDel
is called.
There are several alternative ACD retrieval functions. In all cases token
is the name of the ACD data definition (the name of the parameter or qualifier):
AjPStr ajAcdGetDirectoryName (const char *token); AjPPhyloState ajAcdGetDiscretestatesSingle (const char *token); AjPStr ajAcdGetListSingle(const char *token); AjPStr ajAcdGetOutdirName (const char *token); AjPRegexp ajAcdGetRegexpSingle (const char *token); AjPStr ajAcdGetSelectSingle (const char *token); AjPSeqset ajAcdGetSeqsetallSingle (const char *token); AjPPhyloTree ajAcdGetTreeSingle (const char *token);
In contrast to the standard retrieval functions these return a value derived from the ACD datatype, such as the first sequence from a set of sequences or the name of a directory. For example ajAcdGetOutdirName
returns an AjPStr
holding the name of an output directory whereas the standard retrieval function ajAcdGetOutdir
returns an AjPDir
i.e. the directory itself. Their use is explained in the appropriate programming guide (Appendix B, Libraries Reference).
The alternative functions are provided for convenience where the full object is not required. ACD takes care of the memory management for any objects that have not been passed to the main program. Alternative functions with the suffix Single
return an element of the object that would normally be returned by the standard retrieval function. This saves the calling program from stepping through a list of values when only one value can be selected form the list (i.e. the ACD file defines a minimum and maximum of 1 value to be returned). You only need to free the single string that was returned. Similarly, alternative functions with the suffix Name
return an entirely new string. You need only free this string later, ACD takes care of freeing the full object when the program exits.
Consider the following ACD file:
application: example [ documentation: "Example application." ] directory: dir [ help: "Directory for reading." ]
The program below would print the name of the directory:
int main(int argc, char **argv) { embInit("example", argc, argv); AjPStr name = NULL; name = ajAcdGetOutdirName("dir"); ajFmtPrint("Directory name is %S\n", name); ajStrDel(&name); embExit(); return 0;
Your application must exit cleanly. In other words all memory that has been allocated must be freed and an appropriate code returned to the operating system.
Memory management is covered in detail elsewhere (Section 5.5, “Programming with Objects”). In brief, memory is allocated by:
embInit
or embInitP
allocate memory for an AJAX object for each ACD data definition, a pointer to which is returned by the ajAcdGet*
functions
embInit
or embInitP
also allocate some memory for housekeeping purposes
Explicit calls to memory allocation macros
Explicit calls to constructor functions
Implicit calls to constructor functions, which are made by some functions as a failsafe mechanism where an object is required but an unallocated object pointer was passed
All allocation macros must be matched to a corresponding freeing macro. All constructor calls, explicit or implicit, including calls to ajAcdGet*
functions, must be matched to a corresponding destructor function. To free the memory allocated by EMBOSS for housekeeping you must call one of:
void embExit (void); |
void embExitBad (void); |
These functions are defined in embexit.h/c
. embExit
returns the success code (0
) whereas embExit
returns the failure code (0
).
The last two lines of most EMBOSS applications are therefore:
embExit(); return 0;