Copyright (C) 2003 W. Michael Petullo <mike@flyn.org>

scald is Markup language for generating source code

= OVERVIEW =================================================================
	
Scald can assist lazy developers. Scald is a tool to generate 
program code from an HTML-like XML description. For example, scald 
will process an XML description into C code that prints an HTML 
form and saves user input data into a configuration file.

= BUILDING =================================================================

To build, cross your fingers and try...

 1. ./configure
 2. make
 3. make install

Read the ``INSTALL'' file for generic detailed information on installing
this program.
	
= NASTY DETAILS ============================================================
	
There are many XSLT processors available to developers. The following 
examples use xmllint from libxml2 and xsltproc from libxslt. Here is 
example.xml, an example XML document that follows the scald schema:


<?xml version="1.0"?>

<!DOCTYPE webapp PUBLIC "-//Flyn Computing//DTD Scald XML Unstable//EN"
                           "http://www.flyn.org/xml/dtd/unstable/webapp.dtd">

<webapp name="/cgi-bin/example.cgi" short-name="example" description="Example">

	<form name="example" save-data-as="config" save-to-dir="/tmp/">
		<input name="example-input" type="text" label="Example Input"/>
		<submit value="Save"/>
	</form>

</webapp>



The file example.xml may be validated with the command xmllint 
--noout example.xml and processed with xsltproc 
http://www.flyn.org/xml/xslt/unstable/webapp-c.xslt example.xml. The result 
will be several functions, written in C:

void print_form(char *sidebar)
    Creates and prints an HTML form, selecting default values from a 
    configuration file, if available.

void save_data(s_cgi *cgi)
    Reads a form and saves its values to a configuration file or spool.

char *get_post_mode(s_cgi *cgi)
    Returns the CGI mode of execution.

After you process an XML file to generate C code, you should write 
a main function that calls these three functions. One useful 
technique is to write a system configuration daemon. After running 
save_data, the main function may notify this daemon, which will then 
reconfigure a system service based on the updated configuration file 
(it may be a bad idea to allow your webserver the rights required 
to update system configurations directly).

The scald schema also allows for dependencies between inputs. For 
example, the fragment below describes an input, password, that is 
only enabled if another input, authenticate, is selected. This 
dependency is enforced by Javascript code that scald automatically generates.


<input name="authenticate" type="checkbox" label="Use Authentication"/>
<input name="password" type="password" label="Password"
       enabled-by="document.formname.authenticate"/>


The call-print- entites allow one to generate custom HTML at run 
runtime. The following fragment indicates that options should be 
generated at runtime by a custom function:


<form name="initialize" save-data-as="config" save-to-dir="/tmp/">
	<select name="device">
		<call-print-options-fn/>
	</select>
</form>


Scald will generate code that expects the function 
print_document_initialize_device_options() to be defined in a seperate 
file and linked against the C output that scald generates. Here is 
a simple implementation of print_document_initialize_device_options():


void print_document_initialize_device_options(char *obj)
{
        printf("<option value=\"foo\">Foo</option>");
	printf("<option value=\"bar\">Bar</option>");
}


A more general-purpose entity is call-print-input-fn. This may be used 
to generate any HTML input tags:


<form name="initialize" save-data-as="spool" save-to-dir="/tmp/">
	<call-print-input-fn name="example"/>
</form>


This requires one to define both a print and save function:


void save_to_spool_document_initialize_example_input(s_cgi *cgi,
                                                     char *dir, char *obj)
{
	/* Code to read data from s_cgi *cgi and write it to spool file
	 * in char *dir
	 */
}

void print_document_initialize_example_input(char *obj)
{
	/*  Code to print HTML form */
}


The onclick option is available to the input tag. This may be set 
to a Javascript function that will execute when the input is 
clicked. The Javascript function may be either provided by the XML 
document or dynamically generated using a call-print- entity as in 
the following example:


<form name="initialize" save-data-as="config" save-to-dir="/tmp/">
	<input label="Host" name="destination" value="host" type="radio" onclick="populate_with_hosts"/><br/>
	<input label="Disk" name="destination" value="disk" type="radio" onclick="populate_with_disks"/><br/>
	<select label="Destination" name="dest">
		<call-print-options-fn/>
	</select>
</form>


The following is the implementation that will be called by the code 
generated by the call-print-options-fn entity. It prints the two 
Javascript functions that are referenced by the onclick options above. 
It also calls the populate_with_hosts function that it defines in 
order to initially populate the options list. Clicking between the 
radio buttons defined above will switch the options available.


void print_document_initialize_dest_options(char *obj)
{
        printf ("<script type=\"text/javascript\">");
	printf ("function populate_with_hosts() {");
	printf ("document.backup.dest.length = 0;");
	/* C Code to print Javascript that assigns hosts, e.g.: */
	for (i = 0; i < num_opts; i++) {
		printf ("%s[%d] = new Option(\"%s\", \"%s\", false);\n", obj, 
			i, "example.com", "example.com");
	}
	if (0 == i) {
		printf("for (i = %s.options.length; i >= 0; i--) { \
			%s[i] = null; \
			}\n", obj, obj);
	}
	printf ("}");
	printf ("function populate_with_disks() {");
	printf ("document.backup.dest.length = 0;");
	/* Code to print disks */
	printf ("}");
	printf ("populate_with_hosts(%s);", obj);
	printf ("</script>");
}


