#!/bin/arena /* * Manual transformation into different formats * * This Arena script can be used to transform the Arena language * manual ASCII master into a number of different output formats, * most notably HTML and LaTeX. */ /* * Helper functions */ void usage() { print("Usage: transform file [mode]\n"); print("Available modes:\n"); print("\thtml HTML (default)\n"); print("\thtmltoc HTML table of contents\n"); print("\tlatex LaTeX\n"); print("\ttext Plain text\n"); exit(0); } string rtrim(string str) { while (strlen(str) > 0 && isspace(substr(str, strlen(str) - 1, 1))) { str = substr(str, 0, strlen(str) - 1); } return str; } /* * HTML formatting functions */ void html_start() { print('\n'); print('\n\n'); print("\n"); print("\n"); print("Arena Language Manual\n"); print('\n'); print("\n"); print("\n\n"); print("

Arena Language Manual

\n\n"); print("(C) 2006, Pascal Schmidt <arena-language@ewetel.net>
\n"); } void html_heading(int level, string num, string content) { print('\n'); print("", num, " ", content, "\n"); } void html_line(string line) { print(line, "\n"); } void html_start_verbatim() { print("
\n");
}

void html_end_verbatim()
{
  print("
\n"); } void html_blank_line() { print("

\n\n"); } string html_escape(string line) { in = line; out = ""; while (strlen(in) > 0) { brk = strpbrk(in, "<>&"); if (is_void(brk)) { out = strcat(out, in); in = ""; } else { out = strcat(out, substr(in, 0, brk)); part = substr(in, brk, 1); in = substr(in, brk + 1); switch (part) { case "<": replace = "<"; break; case ">": replace = ">"; break; case "&": replace = "&"; break; } out = strcat(out, replace); } } return out; } void html_end() { print("\n\n"); print("\n"); } /* * HTML table of contents functions */ void htmltoc_nop() { } void htmltoc_start() { print("

Contents

\n"); } void htmltoc_heading(int level, string num, string content) { if (strlen(num) == 1 && num != "1") { print('
\n'); } for (i = 0; i < level - 1; i++) { print('    '); } print(num, '
', content, '
\n'); } /* * LaTeX formatting functions */ void latex_start() { print("\\documentclass[12pt,oneside,headsepline]{scrbook}\n"); print("\\usepackage{listings}\n\n"); print("\\ifx\\pdfoutput\\undefined\n"); print("\\usepackage[dvips]{color}\n"); print("\\else\n"); print("\\usepackage[pdftex]{color}\n"); print("\\fi\n\n"); print("\\definecolor{lightgray}{rgb}{0.90,0.90,0.90}\n\n"); print("\\lstset{language={}}\n"); print("\\lstset{backgroundcolor=\\color{lightgray}}\n"); print("\\lstset{frame=lines}\n"); print("\\lstset{aboveskip=14pt}\n"); print("\\lstset{aboveskip=14pt}\n"); print("\\lstset{basicstyle=\\ttfamily\\small}\n\n"); print("\\setcounter{secnumdepth}{3}\n"); print("\\setcounter{tocdepth}{3}\n\n"); print("\\title{Arena language manual}\n"); print("\\author{Pascal Schmidt\\\\arena-language@ewetel.net}\n\n"); print("\\begin{document}\n\n"); print("\\frontmatter\n"); print("\\maketitle\n"); print("\\newpage\n"); print("\\tableofcontents\n"); print("\\newpage\n"); print("\\mainmatter\n\n"); } void latex_heading(int level, string num, string content) { switch (level) { case 1: hdrtype = "chapter"; break; case 2: hdrtype = "section"; break; case 3: hdrtype = "subsection"; break; default: hdrtype = "subsubsection"; } print("\\", hdrtype, "{", content, "}\n"); } void latex_line(string line) { print(line, "\n"); } void latex_start_verbatim() { print("\\begin{lstlisting}\n"); } void latex_end_verbatim() { print("\\end{lstlisting}\n"); } void latex_blank_line() { printf("\n"); } string latex_escape(string line) { in = line; out = ""; while (strlen(in) > 0) { brk = strpbrk(in, "#$%&~_^\\{}|"); if (is_void(brk)) { out = strcat(out, in); in = ""; } else { out = strcat(out, substr(in, 0, brk)); part = substr(in, brk, 1); in = substr(in, brk + 1); switch (part) { case "\\": replace = "$\\backslash$"; break; case "|": replace = "\\verb'|'"; break; case "~": case "^": replace = strcat("\\", part, "{}"); break; case "_": replace = strcat("\\", part, "\\-"); break; default: replace = strcat("\\", part); } out = strcat(out, replace); } } impl = strstr(out, "implementation"); if (!is_void(impl)) { before = substr(out, 0, impl); after = substr(out, impl + strlen("implementation")); out = strcat(before, "im\\-ple\\-men\\-tation", after); } return out; } string latex_verbatim_escape(string line) { return strcat(" ", substr(line, 1)); } void latex_end() { print("\n\\end{document}\n"); } /* * Plain text formatting functions */ void text_nop() { } string text_nop_return(string line) { return line; } void text_start() { print("Arena Language Manual\n"); print("(C) 2006, Pascal Schmidt \n"); } void text_heading(int level, string num, string content) { print("\n", num, " ", content, "\n"); } void text_line(string line) { print(line, "\n"); } void text_blank_line() { print("\n"); } /* * Formatting callback definitions */ htmlfuncs = mkstruct(); htmlfuncs.start = html_start; htmlfuncs.heading = html_heading; htmlfuncs.line = html_line; htmlfuncs.start_verbatim = html_start_verbatim; htmlfuncs.end_verbatim = html_end_verbatim; htmlfuncs.blank_line = html_blank_line; htmlfuncs.escape = html_escape; htmlfuncs.verbatim_escape = html_escape; htmlfuncs.end = html_end; htocfuncs = mkstruct(); htocfuncs.start = htmltoc_start; htocfuncs.heading = htmltoc_heading; htocfuncs.line = htmltoc_nop; htocfuncs.start_verbatim = htmltoc_nop; htocfuncs.end_verbatim = htmltoc_nop; htocfuncs.blank_line = htmltoc_nop; htocfuncs.escape = html_escape; htocfuncs.verbatim_escape = htmltoc_nop; htocfuncs.end = htmltoc_nop; latexfuncs = mkstruct(); latexfuncs.start = latex_start; latexfuncs.line = latex_line; latexfuncs.heading = latex_heading; latexfuncs.start_verbatim = latex_start_verbatim; latexfuncs.end_verbatim = latex_end_verbatim; latexfuncs.blank_line = latex_blank_line; latexfuncs.escape = latex_escape; latexfuncs.verbatim_escape = latex_verbatim_escape; latexfuncs.end = latex_end; textfuncs = mkstruct(); textfuncs.start = text_start; textfuncs.heading = text_heading; textfuncs.line = text_line; textfuncs.start_verbatim = text_nop; textfuncs.end_verbatim = text_nop; textfuncs.blank_line = text_blank_line; textfuncs.escape = text_nop_return; textfuncs.verbatim_escape = text_nop_return; textfuncs.end = text_nop; callbacks = mkstruct(); callbacks.html = htmlfuncs; callbacks.htmltoc = htocfuncs; callbacks.latex = latexfuncs; callbacks.text = textfuncs; /* * Main program */ if (argc < 2) { usage(); } filename = argv[1]; if (argc > 2) { mode = argv[2]; } else { mode = "html"; } if (is_field(callbacks, mode)) { callback = struct_get(callbacks, mode); } else { print("Unknown transformation mode '", mode, "' given\n"); usage(); } fp = fopen(filename, "r"); if (is_void(fp)) { print("Could not open file '", filename, "' for input\n"); exit(1); } callback.start(); /* * true if in verbatim mode */ verbatim = false; /* * true if previous output has implicit additonal vertical spacing */ spacing = false; /* * initial values for chapter/section/etc counters */ levels = mkarray(0, 0, 0, 0); /* * loop until end of file */ while (!feof(fp)) { line = rtrim((string) fgets(fp)); /* * line with initial tab starts verbatim mode, * following line with no initiab tab ends verbatim mode */ if (substr(line, 0, 1) == "\t") { if (!verbatim) callback.start_verbatim(); verbatim = true; } else { if (verbatim) callback.end_verbatim(); verbatim = false; } hdrlevel = strspn(line, "."); if (!verbatim && hdrlevel > 0) { /* * line that starts with dots is a section heading */ ++levels[hdrlevel - 1]; for (i = hdrlevel; i < 4; i++) { levels[i] = 0; } hdrnum = ""; for (i = 0; i < 4; i++) { if (levels[i] > 0) { hdrnum = strcat(hdrnum, levels[i], "."); } } hdrnum = substr(hdrnum, 0, strlen(hdrnum) - 1); hdrtext = substr(line, hdrlevel, strlen(line) - hdrlevel); hdrtext = callback.escape(hdrtext); callback.heading(hdrlevel, hdrnum, hdrtext); spacing = true; } else if (strlen(line) == 0 && !spacing) { /* * output empty line if empty line in input and * previous output did not have implicit empty line */ callback.blank_line(); spacing = true; } else { /* * normal text, escape according to current mode */ if (!verbatim) { line = callback.escape(line); } else { line = callback.verbatim_escape(line); } callback.line(line); spacing = false; } } /* * end of file, end verbatim mode if still active */ if (verbatim) callback.end_verbatim(); callback.end(); fclose(fp);