..
/
download
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <stdbool.h>
#include <string.h>
#include <libxml/tree.h>
#include <libxml/debugXML.h>
#include <libxslt/xslt.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include "s1kd_tools.h"
#include "dmrl.h"
#define PROG_NAME "s1kd-dmrl"
#define VERSION "1.12.0"
static void showHelp(void)
{
puts("Usage: " PROG_NAME " [options] <DML>...");
puts("");
puts("Options:");
puts(" -$, --issue <iss> Which issue of the spec to use.");
puts(" -@, --out <dir> Output to specified directory.");
puts(" -%, --templates <dir> Custom XML template directory.");
puts(" -D, --dmtypes <path> Specify .dmtypes file name.");
puts(" -d, --defaults <path> Specify .defaults file name.");
#ifndef _WIN32
puts(" -F, --fail Fail on first error from s1kd-new* commands.");
#endif
puts(" -f, --overwrite Overwrite existing CSDB objects.");
puts(" -h, -?, --help Show usage message.");
puts(" -m, --use-remarks Use the remarks for entries in the objects.");
puts(" -N, --omit-issue Omit issue/inwork numbers.");
puts(" -q, --quiet Don't report errors if objects exist.");
puts(" -s, --commands Output s1kd-new* commands only.");
puts(" -v, --verbose Print the names of newly created objects.");
puts(" --version Show version information.");
LIBXML2_PARSE_LONGOPT_HELP
}
static void show_version(void)
{
printf("%s (s1kd-tools) %s\n", PROG_NAME, VERSION);
printf("Using libxml %s and libxslt %s\n", xmlParserVersion, xsltEngineVersion);
}
int main(int argc, char **argv)
{
int i;
xmlDocPtr dmrl;
xsltStylesheetPtr dmrlStylesheet;
int err = 0;
bool execute = true;
bool noIssue = false;
#ifndef _WIN32
bool failOnFirstErr = false;
#endif
bool overwrite = false;
bool noOverwriteError = false;
bool verbose = false;
char *specIssue = NULL;
char *templateDir = NULL;
char *outDir = NULL;
char *defaultsFname = NULL;
char *dmtypesFname = NULL;
bool use_remarks = false;
const char *sopts = "D:d:smNfFq$:%:@:vh?";
struct option lopts[] = {
{"version" , no_argument , 0, 0},
{"help" , no_argument , 0, 'h'},
{"defaults" , required_argument, 0, 'd'},
{"dmtypes" , required_argument, 0, 'D'},
{"commands" , no_argument , 0, 's'},
{"use-remarks", no_argument , 0, 'm'},
{"omit-issue" , no_argument , 0, 'N'},
{"overwrite" , no_argument , 0, 'f'},
{"fail" , no_argument , 0, 'F'},
{"quiet" , no_argument , 0, 'q'},
{"issue" , required_argument, 0, '$'},
{"verbose" , no_argument , 0, 'v'},
{"templates" , required_argument, 0, '%'},
{"out" , required_argument, 0, '@'},
LIBXML2_PARSE_LONGOPT_DEFS
{0, 0, 0, 0}
};
int loptind = 0;
dmrl = read_xml_mem((const char *) dmrl_xsl, dmrl_xsl_len);
dmrlStylesheet = xsltParseStylesheetDoc(dmrl);
while ((i = getopt_long(argc, argv, sopts, lopts, &loptind)) != -1) {
switch (i) {
case 0:
if (strcmp(lopts[loptind].name, "version") == 0) {
show_version();
return 0;
}
LIBXML2_PARSE_LONGOPT_HANDLE(lopts, loptind, optarg)
break;
case 'd':
defaultsFname = strdup(optarg);
break;
case 'D':
dmtypesFname = strdup(optarg);
break;
case 's':
execute = false;
break;
case 'm':
use_remarks = true;
break;
case 'N':
noIssue = true;
break;
case 'f':
overwrite = true;
break;
#ifndef _WIN32
case 'F':
failOnFirstErr = true;
break;
#endif
case 'q':
noOverwriteError = true;
break;
case '$':
specIssue = strdup(optarg);
break;
case 'v':
verbose = true;
break;
case '%':
templateDir = strdup(optarg);
break;
case '@':
outDir = strdup(optarg);
break;
case 'h':
case '?':
showHelp();
return 0;
}
}
for (i = optind; i < argc; ++i) {
xmlDocPtr in, out;
xmlChar *content;
const char *params[21];
char iss[8];
char *templs = NULL;
char *outd = NULL;
char *defname = NULL;
char *dmtname = NULL;
if (!(in = read_xml_doc(argv[i]))) {
continue;
}
params[0] = "no-issue";
params[1] = noIssue ? "true()" : "false()";
params[2] = "overwrite";
params[3] = overwrite ? "true()" : "false()";
params[4] = "no-overwrite-error";
params[5] = noOverwriteError ? "true()" : "false()";
params[6] = "spec-issue";
if (specIssue) {
snprintf(iss, 8, "\"%s\"", specIssue);
params[7] = iss;
} else {
params[7] = "false()";
}
params[8] = "verbose";
params[9] = verbose ? "true()" : "false()";
params[10] = "templates";
if (templateDir) {
templs = malloc(strlen(templateDir) + 3);
sprintf(templs, "\"%s\"", templateDir);
params[11] = templs;
} else {
params[11] = "false()";
}
params[12] = "outdir";
if (outDir) {
outd = malloc(strlen(outDir) + 3);
sprintf(outd, "\"%s\"", outDir);
params[13] = outd;
} else {
params[13] = "false()";
}
params[14] = "defaults";
if (defaultsFname) {
defname = malloc(strlen(defaultsFname) + 3);
sprintf(defname, "\"%s\"", defaultsFname);
params[15] = defname;
} else {
params[15] = "false()";
}
params[16] = "dmtypes";
if (dmtypesFname) {
dmtname = malloc(strlen(dmtypesFname) + 3);
sprintf(dmtname, "\"%s\"", dmtypesFname);
params[17] = dmtname;
} else {
params[17] = "false()";
}
params[18] = "use-remarks";
params[19] = use_remarks ? "true()" : "false()";
params[20] = NULL;
out = xsltApplyStylesheet(dmrlStylesheet, in, params);
free(templs);
free(outd);
free(defname);
free(dmtname);
xmlFreeDoc(in);
content = xmlNodeGetContent(out->children);
if (execute) {
#ifdef _WIN32
/* FIXME: Implement alternative to fmemopen and
* WEXITSTATUS in order to use the -F ("fail on first
* error") option on a Windows system.
*/
char *line = NULL;
while ((line = strtok(line ? NULL : (char *) content, "\n"))) {
system(line);
}
#else
FILE *lines;
char line[LINE_MAX];
lines = fmemopen(content, xmlStrlen(content), "r");
while (fgets(line, LINE_MAX, lines))
if ((err += WEXITSTATUS(system(line))) != 0 && failOnFirstErr) break;
fclose(lines);
#endif
} else {
fputs((char *) content, stdout);
}
xmlFree(content);
xmlFreeDoc(out);
}
xsltFreeStylesheet(dmrlStylesheet);
free(specIssue);
free(templateDir);
free(outDir);
free(defaultsFname);
free(dmtypesFname);
xsltCleanupGlobals();
xmlCleanupParser();
return err;
}
gopher://khzae.net/0/s1000d/s1kd-tools/src/tools/s1kd-dmrl/s1kd-dmrl.c