diff options
Diffstat (limited to 'libslang/doc/tm/tools')
-rw-r--r-- | libslang/doc/tm/tools/Makefile | 46 | ||||
-rw-r--r-- | libslang/doc/tm/tools/README | 67 | ||||
-rw-r--r-- | libslang/doc/tm/tools/sl2tm.c | 216 | ||||
-rw-r--r-- | libslang/doc/tm/tools/tm2txt.c | 726 |
4 files changed, 1055 insertions, 0 deletions
diff --git a/libslang/doc/tm/tools/Makefile b/libslang/doc/tm/tools/Makefile new file mode 100644 index 0000000..94ec197 --- /dev/null +++ b/libslang/doc/tm/tools/Makefile @@ -0,0 +1,46 @@ +# -*- sh -*- +ELF= +EXECS_TO_BUILD = tm2txt sl2tm +EXECS_TO_INSTALL = tm2txt sl2tm +SYMLINK_DIR=$(HOME)/sys/$(ARCH)/objs/slang/doc/tm/tools +SRCDIR=$(HOME)/src/slang/doc/tm/tools +OBJDIR=$(SRCDIR)/$(ARCH)objs# + +SLANGDIR=$(SRCDIR)/../../src +EXECLIBS = -L$(SLANGDIR)/$(ARCH)$(ELF)objs -lslang -lm +EXECINC = -I$(SLANGDIR) + +COMPILE_CMD=$(CC) -c $(CFLAGS) $(EXECINC) +LINK_CMD=$(CC) $(LDFLAGS) + +all: $(OBJDIR) $(EXECS_TO_BUILD) +clean: + $(RM) $(OBJDIR)/* *~ #* + +tm2txt: $(OBJDIR)/tm2txt + @echo tm2txt created in $(OBJDIR) +$(OBJDIR)/tm2txt: $(OBJDIR)/tm2txt.o $(EXEC_EXTRA_OBJS) + cd $(OBJDIR); $(LINK_CMD) tm2txt.o -o tm2txt $(EXECLIBS) +$(OBJDIR)/tm2txt.o: tm2txt.c $(tm2txt_O_DEP) + cd $(OBJDIR); $(COMPILE_CMD) $(SRCDIR)/tm2txt.c -o tm2txt.o +sl2tm: $(OBJDIR)/sl2tm + @echo sl2tm created in $(OBJDIR) +$(OBJDIR)/sl2tm: $(OBJDIR)/sl2tm.o $(EXEC_EXTRA_OBJS) + cd $(OBJDIR); $(LINK_CMD) sl2tm.o -o sl2tm $(EXECLIBS) +$(OBJDIR)/sl2tm.o: sl2tm.c $(sl2tm_O_DEP) + cd $(OBJDIR); $(COMPILE_CMD) $(SRCDIR)/sl2tm.c -o sl2tm.o + +$(OBJDIR): + -mkdir $(OBJDIR) + +install: $(EXECS_TO_INSTALL) + @for x in $(EXECS_TO_INSTALL); do \ + echo Installing $$x in $(BINDIR); \ + $(INSTALL_CMD) $(OBJDIR)/$$x $(BINDIR); \ + done + +symlinks: + -/bin/rm -f $(ARCH)objs + -mkdir -p $(SYMLINK_DIR) + ln -s $(SYMLINK_DIR) $(ARCH)objs + diff --git a/libslang/doc/tm/tools/README b/libslang/doc/tm/tools/README new file mode 100644 index 0000000..627c3a2 --- /dev/null +++ b/libslang/doc/tm/tools/README @@ -0,0 +1,67 @@ +This directory includes two programs: + +tm2txt: + This program processes one or more specially formatted .tm + source files and writes the result on stdout. By specially + formatted, it is meant that the .tm files are formatted + into sections such as: + +\function{my_function} +\synopsis{Short Description} +\usage{int my_function (void);} +\description + \var{my_function} does something special and returns an integer. +\example + Here is an example of its use: +#v+ + if (-1 == my_function ()) + exit (1); +#v- +\seealso{my_other_function, your_function} +\done + + Run this README file through tm2txt and see the result. + + +sl2tm: + This program strips the specially formatted documentation described + above from C files and S-Lang files. Here is an example of how the + documentation would appear in the C source: + +/*%+ + *\function{my_other_function} + *\synopsis{Just another function} + *\usage{int my_other_function(void)} + *\description + * \var{my_other_function} is similar to \var{my_function} except that + * it returns a \em{random} integer. + *\example + * Here is an example: + *#v+ + * (void) my_other_function (); + *#v- + *\notes + * This function is obsolete. Use \var{my_new_function} instead. + *\seealso{my_function, my_new_function} + *%- Note that \done should not be used. `*%-' implies \done + */ + +In S-Lang files, the format is similar: + +%!%+ Lines that start with this denotes the start of documentation +%\function{my_other_function} +%\synopsis{Just another function} +%\usage{int my_other_function(void)} +%\description +% \var{my_other_function} is similar to \var{my_function} except that +% it returns a \em{random} integer. +%\example +% Here is an example: +%#v+ +% (void) my_other_function (); +%#v- +%\notes +% This function is obsolete. Use \var{my_new_function} instead. +%\seealso{my_function, my_new_function} +%!%- Note that \done should not be used. `%!%-' implies \done + diff --git a/libslang/doc/tm/tools/sl2tm.c b/libslang/doc/tm/tools/sl2tm.c new file mode 100644 index 0000000..9d8c3ab --- /dev/null +++ b/libslang/doc/tm/tools/sl2tm.c @@ -0,0 +1,216 @@ +/* This program has a simple purpose: strip the documentation from + * one or more slang .sl files or .c files. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +typedef struct +{ + char *lang; + char *doc_start_string; + char *doc_end_string; + char *doc_prefix_string; +} +Doc_File_Type; + +Doc_File_Type Doc_Files [] = +{ + { "sl", + "%!%+", + "%!%-", + "%" + }, + { + "c", + "/*%+", + " *%-", + " *" + }, + { + NULL, NULL, NULL, NULL + } +}; + + +static Doc_File_Type *get_doc_type (char *lang) +{ + Doc_File_Type *dt; + + dt = Doc_Files; + + while (dt->lang != NULL) + { + if (0 == strcmp (dt->lang, lang)) + return dt; + + dt++; + } + return NULL; +} + + +static char *Tm_Comment_String = "#c"; + +static int doc_strip (char *file, FILE *in, FILE *out, Doc_File_Type *df) +{ + char line[1024]; + char ch_start, ch_end, ch_prefix; + unsigned int start_len, end_len, prefix_len; + int level; + char *start, *end, *prefix; + unsigned int linenum; + + if (df == NULL) + return -1; + + start = df->doc_start_string; + end = df->doc_end_string; + prefix = df->doc_prefix_string; + + ch_start = *start; + start_len = strlen (start); + ch_end = *end; + end_len = strlen (end); + ch_prefix = *prefix; + prefix_len = strlen (prefix); + + linenum = 0; + level = 0; + while (NULL != fgets (line, sizeof (line), in)) + { + linenum++; + if (level == 0) + { + if ((*line == ch_start) + && (0 == strncmp (line, start, start_len))) + { + level = 1; + fprintf (out, "%s __LINE__: %u\n", Tm_Comment_String, linenum); + } + continue; + } + + if ((*line == ch_end) + && (0 == strncmp (line, end, end_len))) + { + fputs ("\\done\n", out); + level = 0; + continue; + } + + if ((*line == ch_prefix) + && (0 == strncmp (line, prefix, prefix_len))) + fputs (line + prefix_len, out); + else + { + fprintf (stderr, "%s:%u: expecting %s\n", file, linenum, prefix); + fputs ("\\done\n", out); + return -1; + /* fputs (line, out); */ + } + } + return 0; +} + +static char *guess_language (char *file) +{ + unsigned int len; + char *f; + + len = strlen (file); + f = file + len; + + while ((f > file) && (*f != '.')) + f--; + + if (*f == '.') f++; + if (0 == strcmp (f, "c")) return "c"; + if (0 == strcmp (f, "sl")) return "sl"; + + return "sl"; /* default */ +} + +static void usage (char *pgm) +{ + fprintf (stderr, "Usage: %s [-c] [-sl] file.... > docfile\n", pgm); +} + +int main (int argc, char **argv) +{ + FILE *fpin; + FILE *fpout; + char *pgm; + int i; + char *language; + + pgm = "sl2tm"; + + fpout = stdout; + + + language = NULL; + + for (i = 1; i < argc; i++) + { + if (*argv[i] != '-') + break; + + if (0 == strcmp (argv[i], "-c")) + language = "c"; + else if (0 == strcmp (argv[i], "-sl")) + language = "sl"; + else + { + usage (pgm); + return 1; + } + } + + if (i >= argc) + { + if (isatty (0)) + { + usage (pgm); + return 1; + } + + if (language == NULL) language = "sl"; + (void) doc_strip ("<stdin>", stdin, fpout, get_doc_type (language)); + return 0; + } + + while (i < argc) + { + char *file; + char *lang; + Doc_File_Type *dt; + + file = argv[i]; + i++; + + lang = language; + + if ((lang == NULL) + && (NULL == (lang = guess_language (file)))) + lang = "sl"; + + if (NULL == (dt = get_doc_type (lang))) + continue; + + if (NULL == (fpin = fopen (file, "r"))) + { + fprintf (stderr, "Unable to open %s -- skipping it.\n", file); + continue; + } + + fprintf (stdout, "%s __FILE__: %s\n", Tm_Comment_String, file); + (void) doc_strip (file, fpin, fpout, dt); + fclose (fpin); + } + + if (fpout != stdout) fclose (fpout); + return 0; +} diff --git a/libslang/doc/tm/tools/tm2txt.c b/libslang/doc/tm/tools/tm2txt.c new file mode 100644 index 0000000..b1c4858 --- /dev/null +++ b/libslang/doc/tm/tools/tm2txt.c @@ -0,0 +1,726 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> + +/* This program is a quick hack to turn the run-time library .tm files into + * a decent looking ascii text file. The currently available SGML-tools are + * not up to my standards for doing that. + */ + +static int Run_Silent; +static int Top_Level; + +typedef struct +{ + char *name; + char *value; +} +Macro_String_Type; + +static Macro_String_Type Macro_Strings [] = +{ + {"slang", "S-Lang"}, + {"jed", "jed"}, + {"NULL", "NULL"}, + {"-1", "-1"}, + {"0", "0"}, + {"1", "1"}, + {"2", "2"}, + {"3", "3"}, + {"4", "4"}, + {"5", "5"}, + {"6", "6"}, + {"7", "7"}, + {"8", "8"}, + {"9", "9"}, + {NULL, NULL} +}; + +typedef struct Section_Type +{ + char *section_name; + int (*format_fun) (struct Section_Type *); + unsigned int flags; +} +Section_Type; + +static int format_function (Section_Type *); +static int format_synopsis (Section_Type *); +static int format_usage (Section_Type *); +static int format_description (Section_Type *); +static int format_example (Section_Type *); +static int format_notes (Section_Type *); +static int format_see_also (Section_Type *); +static int format_done (Section_Type *); + +static Section_Type Sections [] = +{ + { + "function", + format_function, + 0 + }, + { + "synopsis", + format_synopsis, + 0 + }, + { + "usage", + format_usage, + 0 + }, + { + "description", + format_description, + 0 + }, + { + "example", + format_example, + 0 + }, + { + "notes", + format_notes, + 0 + }, + { + "seealso", + format_see_also, + 0 + }, + { + "done", + format_done, + 0 + }, + { + "variable", + format_function, + 0 + }, + { + NULL, NULL, 0 + } +}; + +static FILE *Input_File_Ptr; +static FILE *Output_File_Ptr; + +#define MAX_BUF_LEN 1024 +static char Input_Buffer [MAX_BUF_LEN]; +static unsigned int Line_Number; +static int Input_Buffer_Pushed; +static int Line_Type; +static char *This_Filename; + + +#define END_OF_FILE 1 +#define SECTION_LINE 2 +#define VERBATUM_LINE 3 + +static char Source_File[MAX_BUF_LEN]; + +static int set_source_file (char *s) +{ + strncpy (Source_File, s, MAX_BUF_LEN); + Source_File[MAX_BUF_LEN-1] = 0; + This_Filename = Source_File; + return 0; +} + +static int set_source_linenum (char *s) +{ + unsigned int n; + + if (1 == sscanf (s, "%u", &n)) + Line_Number = n; + + return 0; +} + +static int unget_input (char *buf) +{ + if (buf != NULL) + { + char *inp = Input_Buffer; + while (*buf != 0) + { + *inp++ = *buf++; + } + *inp = 0; + } + Input_Buffer_Pushed++; + return 0; +} + + +static int begin_verbatum (void); +static int end_verbatum (void); +static int indent (unsigned int); + +static int verbatum_mode (void) +{ + begin_verbatum (); + while (NULL != fgets (Input_Buffer, MAX_BUF_LEN, Input_File_Ptr)) + { + Line_Number++; + + if (Input_Buffer[0] == '#') + { + if ((Input_Buffer[1] != 'v') + || (Input_Buffer[2] != '-')) + { + fprintf (stderr, "%s:%u:Expecting verbatum end\n", This_Filename, Line_Number); + return -1; + } + break; + } + + indent (3); + fputs (Input_Buffer, stdout); + } + end_verbatum (); + return 0; +} + + + +static int get_next_line (void) +{ + unsigned int len; + + while (1) + { + if (Input_Buffer_Pushed == 0) + { + if (NULL == fgets (Input_Buffer, MAX_BUF_LEN, Input_File_Ptr)) + { + Line_Type = END_OF_FILE; + return -1; + } + Line_Number++; + } + + Input_Buffer_Pushed = 0; + len = strlen (Input_Buffer); + if (len && (Input_Buffer[len - 1] == '\n')) + Input_Buffer [len - 1] = 0; + + switch (*Input_Buffer) + { + case ';': + case '%': + break; + + case '#': + if (Input_Buffer[1] == 'v') + { + if (Input_Buffer[2] == '+') + { + if (-1 == verbatum_mode ()) + return -1; + } + else + { + fprintf (stderr, "%s:%u:Expecting verbatum start\n", This_Filename, Line_Number); + return -1; + } + break; + } + if (Input_Buffer[1] == 'c') + { + if (0 == strncmp (Input_Buffer, "#c __FILE__: ", 13)) + { + set_source_file (Input_Buffer + 13); + break; + } + if (0 == strncmp (Input_Buffer, "#c __LINE__: ", 13)) + { + set_source_linenum (Input_Buffer + 13); + break; + } + break; + } + + break; + + + case '\\': + Line_Type = SECTION_LINE; + return 1; + + default: + Line_Type = 0; + return 0; + } + } +} + +static Section_Type *get_section (char *buf) +{ + char *name; + Section_Type *sec; + int has_colon; + + if (*buf == '\\') buf++; + + name = buf; + has_colon = 0; + while (*buf != 0) + { + if ((*buf == '\n') + || (*buf == ' ') + || (*buf == '\t')) + { + *buf = 0; + break; + } + if (*buf == '{') + { + has_colon = 1; + *buf = 0; + break; + } + buf++; + } + + sec = Sections; + while (1) + { + if (sec->section_name == NULL) + { + if (Run_Silent == 0) + fprintf (stderr, "%s:%u:Unknown section '%s'\n", This_Filename, Line_Number, name); + return NULL; + } + + if (0 == strcmp (sec->section_name, name)) + break; + + sec++; + } + + if (has_colon) + { + unget_input (buf + 1); + } + + return sec; +} + + +static int process_file (FILE *fp) +{ + Section_Type *sec; + + Input_File_Ptr = fp; + Output_File_Ptr = stdout; + Line_Number = 0; + Top_Level = 1; + Line_Type = 0; + + while (1) + { + while ((Line_Type != SECTION_LINE) + && (Line_Type != END_OF_FILE)) + get_next_line (); + + if (Line_Type == END_OF_FILE) + break; + + if (NULL == (sec = get_section (Input_Buffer))) + { + if (Run_Silent == 0) + fprintf (stderr, "%s:%u:Error ignored.\n", This_Filename, Line_Number); + get_next_line (); + continue; + } + + if (sec->format_fun == NULL) + { + get_next_line (); + continue; + } + + if (-1 == (*sec->format_fun)(sec)) + { + fprintf (stderr, "%s:%u:Fatal error\n", This_Filename, Line_Number); + return -1; + } + } + return 0; +} + + +static void usage (void) +{ + char *pgm = "tm2txt"; + + fprintf (stderr, "%s usage:\n", pgm); + fprintf (stderr, "%s [--help] [--quiet] [files...]\n", pgm); +} + +int main (int argc, char **argv) +{ + if ((argc > 1) + && ((0 == strcmp (argv[1], "--help")) || (0 == strcmp (argv[1], "-h")))) + { + usage (); + return 1; + } + + if ((argc > 1) && (0 == strcmp (argv[1], "--quiet"))) + { + Run_Silent = 1; + argc--; + argv++; + } + + if ((argc == 1) && isatty (fileno(stdin))) + { + usage (); + return 1; + } + + if (argc == 1) + { + This_Filename = "<stdin>"; + process_file (stdin); + } + else + { + int i; + + for (i = 1; i < argc; i++) + { + char *file = argv[i]; + FILE *fp; + + if (NULL == (fp = fopen (file, "r"))) + { + fprintf (stderr, "Unable to open %s, skipping it.\n", file); + continue; + } + This_Filename = file; + + if (-1 == process_file (fp)) + { + fprintf (stderr, "Fatal error encountered processing %s\n", + file); + fclose (fp); + return 1; + } + + fclose (fp); + } + } + + return 0; +} + +static int write_boldface (char *s) +{ + fprintf (Output_File_Ptr, "%s", s); + return 0; +} + +#if 0 +static int write_tt (char *s) +{ + fprintf (Output_File_Ptr, "`%s'", s); + return 0; +} +#endif +static int newline (void) +{ + fputs ("\n", Output_File_Ptr); + return 0; +} + + +static int write_section_name (char *s) +{ + newline (); + fputs (" ", Output_File_Ptr); + write_boldface (s); + newline (); + return 0; +} + +static char *write_verbatum_output (char *buf) +{ + while (*buf && (*buf != '}')) + { + if (*buf == '\\') + { + buf++; + if (*buf == 0) + break; + } + + putc (*buf, Output_File_Ptr); + buf++; + } + if (*buf == '}') buf++; + return buf; +} + + +static char *write_macro (char *s) +{ + char *s1; + char ch; + Macro_String_Type *m; + + s1 = s; + while ((ch = *s1) != 0) + { + if ((0 == isalnum (ch)) + && (ch != '-') + && (ch != '_')) + break; + + s1++; + } + *s1 = 0; + + m = Macro_Strings; + while (m->name != NULL) + { + if (0 == strcmp (m->name, s)) + { + fputs (m->value, Output_File_Ptr); + *s1 = ch; + return s1; + } + m++; + } + fprintf (Output_File_Ptr, "\\%s", s); + if (Run_Silent == 0) + fprintf (stderr, "%s:%u:%s not defined\n", This_Filename, Line_Number, s); + *s1 = ch; + return s1; +} + + +static int write_with_escape (char *buf) +{ + char ch; + + while (1) + { + ch = *buf++; + switch (ch) + { + case 0: + return 0; + + case '\\': + if (*buf == '\\') + { + putc (*buf, Output_File_Ptr); + buf++; + break; + } + + if ((0 == strncmp ("var{", buf, 4)) + || (0 == strncmp ("par{", buf, 4)) + || (0 == strncmp ("fun{", buf, 4))) + { + putc ('`', Output_File_Ptr); + buf = write_verbatum_output (buf + 4); + putc ('\'', Output_File_Ptr); + break; + } + + if ((0 == strncmp ("exmp{", buf, 5)) + || (0 == strncmp ("ifun{", buf, 5)) + || (0 == strncmp ("cfun{", buf, 5)) + || (0 == strncmp ("sfun{", buf, 5)) + || (0 == strncmp ("ivar{", buf, 5)) + || (0 == strncmp ("cvar{", buf, 5)) + || (0 == strncmp ("svar{", buf, 5))) + { + putc ('`', Output_File_Ptr); + buf = write_verbatum_output (buf + 5); + putc ('\'', Output_File_Ptr); + break; + } + + if (0 == strncmp ("em{", buf, 3)) + { + putc ('_', Output_File_Ptr); + buf = write_verbatum_output (buf + 3); + putc ('_', Output_File_Ptr); + break; + } + + buf = write_macro (buf); + break; + + default: + putc (ch, Output_File_Ptr); + break; + + } + } +} + + + + +static int indent (unsigned int n) +{ + while (n) + { + putc (' ', Output_File_Ptr); + n--; + } + + return 0; +} + +static int write_line (void) +{ + char *s = Input_Buffer; + unsigned int min_indent = 3; + + while ((*s == ' ') && min_indent) + { + s++; + min_indent--; + } + + indent (min_indent); + write_with_escape (Input_Buffer); + newline (); + return 0; +} + + +static int format_function (Section_Type *sec) +{ + (void) sec; + if (Top_Level == 0) + { + fprintf (stderr, "%s:%u:\\function or \\variable not at top-level\n", + This_Filename, Line_Number); + fprintf (stderr, " Input line: %s\n", Input_Buffer); + return -1; + } + Top_Level = 0; + + write_verbatum_output (Input_Buffer); + newline (); + get_next_line (); + return 0; +} + + +static int format_usage (Section_Type *sec) +{ + (void) sec; + write_section_name ("USAGE"); + indent (3); + write_verbatum_output (Input_Buffer); + newline (); + + get_next_line (); + return 0; +} + +static int format_description (Section_Type *sec) +{ + (void) sec; + write_section_name ("DESCRIPTION"); + + while (0 == get_next_line ()) + { + write_line (); + } + return 0; + +} + +static int format_example (Section_Type *sec) +{ + (void) sec; + write_section_name ("EXAMPLE"); + + while (0 == get_next_line ()) + { + write_line (); + } + return 0; +} + +static int format_notes (Section_Type *sec) +{ + (void) sec; + write_section_name ("NOTES"); + + while (0 == get_next_line ()) + { + write_line (); + } + return 0; +} + +static int format_see_also (Section_Type *sec) +{ + (void) sec; + write_section_name ("SEE ALSO"); + indent (3); + write_verbatum_output (Input_Buffer); + newline (); + get_next_line (); + return 0; +} + + +int format_synopsis (Section_Type *sec) +{ + (void) sec; + write_section_name ("SYNOPSIS"); + indent (3); + write_verbatum_output (Input_Buffer); + newline (); + get_next_line (); + return 0; +} + +int format_done (Section_Type *sec) +{ + (void) sec; + if (Top_Level) + { + fprintf (stderr, "%s:%u:\\done seen at top-level\n", + This_Filename, Line_Number); + return -1; + } + + fputs ("--------------------------------------------------------------\n", + Output_File_Ptr); + newline (); + while (0 == get_next_line ()) + ; + Top_Level = 1; + return 0; +} + + +static int begin_verbatum (void) +{ + newline (); + return 0; +} + +static int end_verbatum (void) +{ + newline (); + return 0; +} |