From c99f96051839bbc87146e32e7462d61e1b4768d3 Mon Sep 17 00:00:00 2001 From: Michael Livshin Date: Thu, 31 May 2001 13:15:54 +0000 Subject: [PATCH] * guile-snarf-docs.in, guile-snarf-docs-texi.in, filter-doc-snarfage.c: new files. * Makefile.am: add stuff to [build,] use and distribute guile-snarf-docs, guile-snarf-docs-texi, guile_filter_doc_snarfage. * guile-snarf.in: grok the new snarf output. * snarf.h: make the output both texttools- and `read'-friendly. * guile-doc-snarf.in (bindir): reimplement in terms of guile-snarf and guile-snarf-docs. (should also deprecate, I guess. maybe not). --- libguile/ChangeLog | 16 ++ libguile/Makefile.am | 33 +++-- libguile/filter-doc-snarfage.c | 234 ++++++++++++++++++++++++++++++ libguile/guile-doc-snarf.in | 23 +-- libguile/guile-snarf-docs-texi.in | 60 ++++++++ libguile/guile-snarf-docs.in | 32 ++++ libguile/guile-snarf.in | 4 +- libguile/snarf.h | 48 +++--- 8 files changed, 396 insertions(+), 54 deletions(-) create mode 100644 libguile/filter-doc-snarfage.c create mode 100755 libguile/guile-snarf-docs-texi.in create mode 100755 libguile/guile-snarf-docs.in diff --git a/libguile/ChangeLog b/libguile/ChangeLog index 10948b747..f24f54e68 100644 --- a/libguile/ChangeLog +++ b/libguile/ChangeLog @@ -1,3 +1,19 @@ +2001-05-31 Michael Livshin + + * guile-snarf-docs.in, guile-snarf-docs-texi.in, + filter-doc-snarfage.c: new files. + + * Makefile.am: add stuff to [build,] use and distribute + guile-snarf-docs, guile-snarf-docs-texi, guile_filter_doc_snarfage. + + * guile-snarf.in: grok the new snarf output. + + * snarf.h: make the output both texttools- and `read'-friendly. + + * guile-doc-snarf.in (bindir): reimplement in terms of guile-snarf + and guile-snarf-docs. (should also deprecate, I guess. maybe + not). + 2001-05-31 Marius Vollmer * print.c (scm_simple_format): Support "~~" and "~%". Signal diff --git a/libguile/Makefile.am b/libguile/Makefile.am index 5a8cc58e1..baf34f5aa 100644 --- a/libguile/Makefile.am +++ b/libguile/Makefile.am @@ -32,12 +32,14 @@ ETAGS_ARGS = --regex='/SCM_\(GLOBAL_\)?\(G?PROC\|G?PROC1\|SYMBOL\|VCELL\|CONST_L --regex='/[ \t]*SCM_[G]?DEFINE1?[ \t]*(\([^,]*\),[^,]*/\1/' lib_LTLIBRARIES = libguile.la -bin_PROGRAMS = guile +bin_PROGRAMS = guile guile_filter_doc_snarfage guile_SOURCES = guile.c guile_LDADD = libguile.la ${THREAD_LIBS_LOCAL} guile_LDFLAGS = @DLPREOPEN@ +guile_filter_doc_snarfage_SOURCES = filter-doc-snarfage.c + libguile_la_SOURCES = alist.c arbiters.c async.c backtrace.c boolean.c \ chars.c continuations.c debug.c deprecation.c dynl.c dynwind.c \ environments.c eq.c error.c eval.c evalext.c extensions.c \ @@ -87,7 +89,7 @@ DOT_DOC_FILES = alist.doc arbiters.doc async.doc backtrace.doc \ EXTRA_DOT_DOC_FILES = @EXTRA_DOT_DOC_FILES@ BUILT_SOURCES = cpp_err_symbols.c cpp_sig_symbols.c libpath.h scmconfig.h \ - $(DOT_X_FILES) $(EXTRA_DOT_X_FILES) $(DOT_DOC_FILES) + $(DOT_X_FILES) $(EXTRA_DOT_X_FILES) EXTRA_libguile_la_SOURCES = _scm.h \ alloca.c inet_aton.c memmove.c putenv.c strerror.c \ @@ -95,6 +97,8 @@ EXTRA_libguile_la_SOURCES = _scm.h \ filesys.c posix.c net_db.c socket.c \ ramap.c unif.c debug-malloc.c +Makefile: $(DOT_X_FILES) + ## In next release, threads will be factored out of libguile. ## Until then, the machine specific headers is a temporary kludge. OMIT_DEPENDENCIES = libguile.h ltdl.h \ @@ -133,10 +137,13 @@ modinclude_HEADERS = __scm.h alist.h arbiters.h async.h backtrace.h boolean.h \ ## and not a header -- headers are included in the distribution. modinclude_DATA = scmconfig.h -bin_SCRIPTS = guile-snarf guile-doc-snarf guile-snarf.awk guile-func-name-check +bin_SCRIPTS = guile-snarf guile-doc-snarf guile-snarf-docs \ + guile-snarf-docs-texi guile-func-name-check EXTRA_DIST = ChangeLog-gh ChangeLog-scm ChangeLog-threads cpp_signal.c \ cpp_errno.c cpp_err_symbols.in cpp_sig_symbols.in cpp_cnvt.awk +# $(DOT_DOC_FILES) $(EXTRA_DOT_DOC_FILES) \ +# guile-procedures.txt guile.texi ## FIXME: Consider using timestamp file, to avoid unnecessary rebuilds. libpath.h: $(srcdir)/Makefile.in $(top_builddir)/config.status @@ -178,22 +185,24 @@ libpath.h: $(srcdir)/Makefile.in $(top_builddir)/config.status SUFFIXES = .x .doc .c.x: - ./guile-doc-snarf $< $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $< > $@ \ + ./guile-snarf $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $< > $@ \ || { rm $@; false; } -.x.doc: - ./guile-doc-snarf $(srcdir)/$*.c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(srcdir)/$*.c > /dev/null \ +.c.doc: + -(test -n "${AWK+set}" || AWK="@AWK@"; ${AWK} -f ./guile-func-name-check $<) + ./guile-snarf-docs $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $< > $@ \ || { rm $@; false; } -*.x: snarf.h guile-doc-snarf.in -*.doc: guile-snarf.awk.in +$(DOT_X_FILES) $(EXTRA_DOT_DOC_FILES): snarf.h guile-snarf.in + +$(DOT_DOC_FILES) $(EXTRA_DOT_DOC_FILES): snarf.h guile-snarf-docs.in guile_filter_doc_snarfage error.x: cpp_err_symbols.c posix.x: cpp_sig_symbols.c load.x: libpath.h -guile.texi: $(DOT_DOC_FILES) $(EXTRA_DOT_DOC_FILES) - echo "@paragraphindent 0" > $@ - cat *.doc >> $@ +guile.texi: $(DOT_DOC_FILES) $(EXTRA_DOT_DOC_FILES) guile-snarf-docs-texi.in guile + ./guile-snarf-docs-texi $(DOT_DOC_FILES) $(EXTRA_DOT_DOC_FILES) > $@ \ + || { rm $@; false; } guile-procedures.txt: guile.texi rm -f $@ @@ -250,4 +259,4 @@ MOSTLYCLEANFILES = \ cpp_err_symbols_here cpp_err_symbols_diff cpp_err_symbols_new \ cpp_sig_symbols_here cpp_sig_symbols_diff cpp_sig_symbols_new -CLEANFILES = libpath.h *.x *.doc +CLEANFILES = libpath.h *.x *.doc guile-procedures.txt guile.texi diff --git a/libguile/filter-doc-snarfage.c b/libguile/filter-doc-snarfage.c new file mode 100644 index 000000000..c403b0ebf --- /dev/null +++ b/libguile/filter-doc-snarfage.c @@ -0,0 +1,234 @@ +#include +#include +#include + +static void init_state_machine (void); + +static void process (void); + +static void check_end_conditions (void); + +int +main (int argc, char *argv[]) +{ + init_state_machine (); + process (); + check_end_conditions (); + + return EXIT_SUCCESS; +} + +typedef enum state_t + { + SKIP, + SKIP_COOKIE, + + MULTILINE, + + MULTILINE_COOKIE, + STRINGS, + + SINGLELINE, + + } state_t; + +state_t state = SKIP; + +static void die (const char *msg); +static void process_strings (void); +static void process_single_line (void); + +void +process () +{ + int want_cookie = 0; + int ch; + + while ((ch = getc (stdin)) != EOF) { + char c = (char)ch; + + switch (state) { + case SKIP: + if (c == '^') { + if (want_cookie) { + state = SKIP_COOKIE; + want_cookie = 0; + } else + want_cookie = 1; + } else + want_cookie = 0; + break; + case SKIP_COOKIE: + switch (c) { + case '[': + fputs ("(doc-check\n", stdout); + state = SINGLELINE; + break; + case '{': + fputs ("(doc-block (\n", stdout); + state = MULTILINE; + break; + default: + die ("bad snarf cookie"); + break; + } + break; + case MULTILINE: + if (c == '^') { + if (want_cookie) { + fputs ("\n)\n(\n", stdout); + state = MULTILINE_COOKIE; + want_cookie = 0; + } else + want_cookie = 1; + } else { + want_cookie = 0; + putc (c, stdout); + } + break; + case MULTILINE_COOKIE: + switch (c) { + case '(': + state = STRINGS; + break; + case ' ': + state = MULTILINE; + break; + case '}': + fputs ("))\n", stdout); + state = SKIP; + break; + default: + die ("bad snarf cookie in multiline context"); + break; + } + break; + case STRINGS: + process_strings (); + state = MULTILINE; + break; + case SINGLELINE: + process_single_line (); + fputs ("\n)\n", stdout); + state = SKIP; + break; + default: + abort (); + break; + } + } +} + +void +init_state_machine () +{} + +void +die (const char *msg) +{ + fprintf (stderr, "%s\n", msg); + exit (EXIT_FAILURE); +} + +void +check_end_conditions () +{ + if (state != SKIP) + die ("something is unterminated"); +} + +typedef enum str_state_t + { + STR_SKIP, + STR_INSIDE, + STR_HAD_ESCAPE, + STR_EXIT + } str_state_t; + +void +process_strings () +{ + /* read well-formed strings up to a ')', and break them up in the + process if they are too long */ + int count = 0; + int ch; + str_state_t state = STR_SKIP; + + fputs ("docstring\n", stdout); + +#define PUTC(c) putc (c, stdout); if (++count >= 512) { fputs ("\"\nstring \"", stdout); count = 0; } + + while (!(((ch = getc (stdin)) == EOF) + || (state == STR_EXIT))) { + char c = (char) ch; + + switch (state) { + case STR_SKIP: + switch (c) { + case '"': + fputs ("\nstring ", stdout); + count = 0; + PUTC (c); + state = STR_INSIDE; + break; + case ')': + state = STR_EXIT; + break; + default: + if (!isspace (c)) + die ("stray stuff where should be only strings"); + break; + } + break; + case STR_INSIDE: + switch (c) { + case '\\': + putc (c, stdout); + ++count; + state = STR_HAD_ESCAPE; + break; + case '"': + putc (c, stdout); + state = STR_SKIP; + break; + default: + PUTC (c); + break; + } + break; + case STR_HAD_ESCAPE: + PUTC (c); + state = STR_INSIDE; + break; + default: + abort (); + break; + } + } + + if (state != STR_EXIT) + die ("docstrings don't terminate"); +} + +void +process_single_line () +{ + /* read up to a ']' */ + int ch; + while (!(((ch = getc (stdin)) == EOF) + || ((char) ch == ']'))) { + char c = (char) ch; + + putc (c, stdout); + } + + if ((char) ch != ']') + die ("bad checking snarfage"); +} + + +/* + Local Variables: + c-file-style: "gnu" + End: +*/ diff --git a/libguile/guile-doc-snarf.in b/libguile/guile-doc-snarf.in index 954075592..36e1a9453 100755 --- a/libguile/guile-doc-snarf.in +++ b/libguile/guile-doc-snarf.in @@ -18,33 +18,18 @@ # the Free Software Foundation, Inc., 59 Temple Place, Suite 330, # Boston, MA 02111-1307 USA -fullfilename=$1; shift +fullfilename=$1 # strip path to source directory filename=`basename $fullfilename` -# we need to be sure that the .x file exists -# since the .c/.cc file may include it -# (the old guile-snarf did not have this problem -# because the makefile redirects output to the .x file -# which creates the file before the inclusion occurs) -# --12/12/99 gjb no_ext=`echo $filename | sed 's/\.[^.]*$//g'` dot_doc=${no_ext}.doc -temp="/tmp/snarf.$$" -trap "rm -f $temp" 0 1 2 15 +bindir=`dirname $0` -## Let the user override the preprocessor & awk autoconf found. -test -n "${CPP+set}" || CPP="@CPP@" -test -n "${AWK+set}" || AWK="@AWK@" +${bindir}/guile-snarf-docs "$@" > $dot_doc -## Must run guile-func-name-check on the unpreprocessed source -${AWK} -f `dirname $0`/guile-func-name-check "$fullfilename" - -## We must use a temporary file here, instead of a pipe, because we -## need to know if CPP exits with a non-zero status. -${CPP} -DSCM_MAGIC_SNARFER "$@" > ${temp} || exit $? -cut -c1-1023 ${temp} | ${AWK} -f `dirname $0`/guile-snarf.awk ${dot_doc} +${bindir}/guile-snarf "$@" # guile-doc-snarf ends here diff --git a/libguile/guile-snarf-docs-texi.in b/libguile/guile-snarf-docs-texi.in new file mode 100755 index 000000000..2dbc4aecc --- /dev/null +++ b/libguile/guile-snarf-docs-texi.in @@ -0,0 +1,60 @@ +#!/bin/sh +# Massage the snarfed docs to texinfo. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place, Suite 330, +# Boston, MA 02111-1307 USA + +srcdir=@srcdir@ +bindir=`dirname $0` + +bindir=`(cd $bindir; pwd)` +srcdir=`(cd $srcdir; pwd)` + +temp0="/tmp/snarf.0.$$" +temp1="/tmp/snarf.1.$$" +trap "rm -f $temp0 $temp1" 0 1 2 15 + +# cat all the small files together: +cat "$@" > ${temp1} + +## massage the arglists + +# lose the SCM types and commas, and texi-quote @'s in names and args +< ${temp1} sed -e '/^arglist/s/[ ]*SCM[ ]*//g' \ + -e '/^arglist/s/,/ /g' \ + -e '/^arglist/s/([ ]*void[ ]*)/()/g' \ + -e '/^fname/s/@/@@/g' \ + -e '/^arglist/s/@/@@/g' \ + > ${temp0} + +# nothing to do with the docstrings +< ${temp0} sed -e 's/^string //' > ${temp1} + +# we're too lame to check argpos assertions other then for straight names, so... +< ${temp1} sed -e 's/^argpos.*[(\[].*//' > ${temp0} + +echo "@paragraphindent 0" + +# now run the script that will generate texinfo +main='(module-ref (resolve-module '\''(scripts snarf-check-and-output-texi)) '\''main)' +apply_main="(apply $main (cdr (command-line)))" + +if [ `basename ${bindir}` = libguile ]; then + GUILE_LOAD_PATH=${srcdir}/.. ${bindir}/guile -c "${apply_main}" < ${temp0} +else + ${bindir}/guile -c "${apply_main}" < ${temp0} +fi diff --git a/libguile/guile-snarf-docs.in b/libguile/guile-snarf-docs.in new file mode 100755 index 000000000..338b710d7 --- /dev/null +++ b/libguile/guile-snarf-docs.in @@ -0,0 +1,32 @@ +#!/bin/sh +# Extract the doc stuff for builtin things. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place, Suite 330, +# Boston, MA 02111-1307 USA + +bindir=`dirname $0` + +temp="/tmp/snarf.$$" +trap "rm -f $temp" 0 1 2 15 + +## Let the user override the preprocessor autoconf found. +test -n "${CPP+set}" || CPP="@CPP@" + +## We must use a temporary file here, instead of a pipe, because we +## need to know if CPP exits with a non-zero status. +${CPP} -DSCM_MAGIC_SNARF_DOCS "$@" > ${temp} || exit $? +< ${temp} ${bindir}/guile_filter_doc_snarfage diff --git a/libguile/guile-snarf.in b/libguile/guile-snarf.in index d41f34c70..41542dcfc 100644 --- a/libguile/guile-snarf.in +++ b/libguile/guile-snarf.in @@ -26,8 +26,8 @@ test -n "${CPP+set}" || CPP="@CPP@" ## We must use a temporary file here, instead of a pipe, because we ## need to know if CPP exits with a non-zero status. -${CPP} -DSCM_MAGIC_SNARFER "$@" > ${temp} || exit $? -< ${temp} grep "^ *SCM_SNARF_INIT_START" | sed -e "s/^ *SCM_SNARF_INIT_START//" -e 's/SCM_SNARF_DOC_START.*$//g' +${CPP} -DSCM_MAGIC_SNARF_INITS "$@" > ${temp} || exit $? +< ${temp} grep "^ *\^\^" | sed -e "s/^ *\^\^//" ## Apparently, AIX's preprocessor is unhappy if you try to #include an ## empty file. diff --git a/libguile/snarf.h b/libguile/snarf.h index ac7a59baa..045e63441 100644 --- a/libguile/snarf.h +++ b/libguile/snarf.h @@ -76,14 +76,28 @@ * line, if any. */ -#ifndef SCM_MAGIC_SNARFER -# define SCM_SNARF_HERE(X) X -# define SCM_SNARF_INIT(X) -# define SCM_SNARF_DOCS(X) +#ifdef SCM_MAGIC_SNARF_INITS +# define SCM_SNARF_HERE(X) +# define SCM_SNARF_INIT(X) ^^ X +# define SCM_SNARF_DOCS(TYPE, FNAME, ARGLIST, REQ, OPT, VAR, DOCSTRING) #else +# ifdef SCM_MAGIC_SNARF_DOCS # define SCM_SNARF_HERE(X) -# define SCM_SNARF_INIT(X) SCM_SNARF_INIT_START X -# define SCM_SNARF_DOCS(X) X +# define SCM_SNARF_INIT(X) +# define SCM_SNARF_DOCS(TYPE, FNAME, ARGLIST, REQ, OPT, VAR, DOCSTRING) \ +^^{ \ +^^ fname . FNAME \ +^^ type . TYPE \ +^^ location __FILE__ . __LINE__ \ +^^ arglist . ARGLIST \ +^^ argsig REQ OPT VAR \ +^^(DOCSTRING) \ +^^} +# else +# define SCM_SNARF_HERE(X) X +# define SCM_SNARF_INIT(X) +# define SCM_SNARF_DOCS(TYPE, FNAME, ARGLIST, REQ, OPT, VAR, DOCSTRING) +# endif #endif #define SCM_DEFINE(FNAME, PRIMNAME, REQ, OPT, VAR, ARGLIST, DOCSTRING) \ @@ -95,10 +109,7 @@ SCM_SNARF_INIT(\ scm_c_define_gsubr (s_ ## FNAME, REQ, OPT, VAR, \ (SCM_FUNC_CAST_ARBITRARY_ARGS) FNAME); \ )\ -SCM_SNARF_DOCS(\ -SCM_SNARF_DOC_STARTP PRIMNAME #ARGLIST | REQ | OPT | VAR | __FILE__:__LINE__ | \ - SCM_SNARF_DOCSTRING_START DOCSTRING SCM_SNARF_DOCSTRING_END \ -) +SCM_SNARF_DOCS(primitive, PRIMNAME, ARGLIST, REQ, OPT, VAR, DOCSTRING) #define SCM_DEFINE1(FNAME, PRIMNAME, TYPE, ARGLIST, DOCSTRING) \ SCM_SNARF_HERE(\ @@ -106,10 +117,7 @@ static const char s_ ## FNAME [] = PRIMNAME; \ SCM FNAME ARGLIST\ )\ SCM_SNARF_INIT(scm_c_define_subr (s_ ## FNAME, TYPE, FNAME); ) \ -SCM_SNARF_DOCS(\ -SCM_SNARF_DOC_START1 PRIMNAME #ARGLIST | 2 | 0 | 0 | __FILE__:__LINE__ | \ - SCM_SNARF_DOCSTRING_START DOCSTRING SCM_SNARF_DOCSTRING_END \ -) +SCM_SNARF_DOCS(1, PRIMNAME, ARGLIST, 2, 0, 0, DOCSTRING) #define SCM_PROC(RANAME, STR, REQ, OPT, VAR, CFN) \ SCM_SNARF_HERE(static const char RANAME[]=STR) \ @@ -120,10 +128,8 @@ SCM_SNARF_INIT(scm_c_define_gsubr (RANAME, REQ, OPT, VAR, \ SCM_SNARF_HERE(static const char RANAME[]=STR) \ SCM_SNARF_INIT(scm_c_define_gsubr (RANAME, REQ, OPT, VAR, \ (SCM_FUNC_CAST_ARBITRARY_ARGS) CFN);) \ -SCM_SNARF_DOCS(\ -SCM_SNARF_DOC_STARTR STR | REQ | OPT | VAR | __FILE__:__LINE__ | \ - SCM_SNARF_DOCSTRING_START CFN SCM_SNARF_DOCSTRING_END \ -) +SCM_SNARF_DOCS(register, STR, (), REQ, OPT, VAR, \ + "implemented by the C function \"" #CFN "\"") #define SCM_GPROC(RANAME, STR, REQ, OPT, VAR, CFN, GF) \ SCM_SNARF_HERE(\ @@ -211,10 +217,10 @@ SCM_SNARF_INIT(c_name = scm_permanent_object (scm_sysintern (scheme_name, init_v #endif /* (SCM_DEBUG_DEPRECATED == 0) */ -#ifdef SCM_MAGIC_SNARFER +#ifdef SCM_MAGIC_SNARF_DOCS #undef SCM_ASSERT -#define SCM_ASSERT(_cond, _arg, _pos, _subr) *&*&*&*SCM_ARG_BETTER_BE_IN_POSITION(_arg,_pos,__LINE__) -#endif /* SCM_MAGIC_SNARFER */ +#define SCM_ASSERT(_cond, _arg, _pos, _subr) ^^[ argpos _arg _pos __LINE__ ] +#endif /* SCM_MAGIC_SNARF_DOCS */ #endif /* LIBGUILE_SNARF_H */ -- 2.20.1