[comp.unix.programmer] Extracting documentation from C code.

benny@vlss.amdahl.com (Benny Schnaider) (05/16/91)

Hi,

I am looking for a utility to extract documentation from a "C"
program. I want to have the documentation source as part of the "C" code
(comments) which can be easily extracted in a troff (man page)
format. The output should be similar to man 3 output format.

Thanks,
Benny
--
-----------------------------------------------------------------
Benny Schnaider    benny@vlss.amdahl.com
                   Amdahl Corporation, 1250 EAST Arques Avenue,
                   M/S 246, Sunnyvale CA, 94088-3470
                   (408) 296 - 0596, (408) 746-3440
-----------------------------------------------------------------

ghost@nrl-cmf.UUCP (Glenn Host) (05/16/91)

In article <BENNY.91May15185447@dimona.vlss.amdahl.com> benny@vlss.amdahl.com
	(Benny Schnaider) writes:
>I am looking for a utility to extract documentation from a "C"
>program. I want to have the documentation source as part of the "C" code
>(comments) which can be easily extracted in a troff (man page)
>format. The output should be similar to man 3 output format.

As far as I know there is no such generic utility.  Two years ago I had
to write such a package to translate C-documentation into text for transfer
to a Mac for processing.  Before I wrote it, we looked for such a utility 
but were unsucessful.

It is actually easy to write such a utility IF you write before you start
writing the code - otherwise you send almost as much time modifying the
original documents as you would typing them again.

Good Luck

-- 
Glenn Host - Senior Systems Analyst (ghost@ra.nrl.navy.mil)
NRL Code 5800, 4555 Overlook Ave.; Washington, DC 20375   (202) 767-2046
12307 Tigers Eye Court ; Reston, VA 22091                 (703) 620-1141 
 -----  Don't mind me - I don't run the place, I only live here. -----

barnett@grymoire.crd.ge.com (Bruce Barnett) (05/17/91)

In article <BENNY.91May15185447@dimona.vlss.amdahl.com> benny@vlss.amdahl.com (Benny Schnaider) writes:
>   I am looking for a utility to extract documentation from a "C"
>   program. I want to have the documentation source as part of the "C" code
>   (comments) which can be easily extracted in a troff (man page)
>   format. The output should be similar to man 3 output format.

I suggest you use the convention that comments always have a "*" as
the second character on the line:
/* This is a comment
 * more ...
 */


etc.

Then if you want to include nroff code in a program, use another
convention,
say - If the second character is a "*", and the third is a "|", then
it's nroff text:

/* nroff document
 *|.\"	@(#)ease.l	(FLUKE) 25-feb-87
 *|.\"
 *|.TH EASE LOCAL "Feb 13, 1991"
 */

Then you can use grep/sed to get the documents:

	grep '^.\*|' file | sed 's/^.\*|//' >file.man

You can get fancier, but you have to set up these policies yourself
ahead of time. 

--
Bruce G. Barnett	barnett@crdgw1.ge.com	uunet!crdgw1!barnett

Dan_Jacobson@ATT.COM (05/17/91)

> In article <BENNY.91May15185447@dimona.vlss.amdahl.com> benny@vlss.amdahl.com (Benny Schnaider) writes:
>   I am looking for a utility to extract documentation from a "C"
>   program. I want to have the documentation source as part of the "C" code

I think the CWEB system might have what you want... perhaps some
comp.text.tex'ers will comment.

>   (comments) which can be easily extracted in a troff (man page)
>   format. The output should be similar to man 3 output format.

oh, well, still check out CWEB.  I think it's on labrea.stanford.edu.

PPH93@DMSWWU1A.BITNET (Thomas Heller) (05/17/91)

In article <BENNY.91May15185447@dimona.vlss.amdahl.com>, benny@vlss.amdahl.com
(Benny Schnaider) says:
>
>Hi,
>
>I am looking for a utility to extract documentation from a "C"
>program. I want to have the documentation source as part of the "C" code
>(comments) which can be easily extracted in a troff (man page)
>format. The output should be similar to man 3 output format.
>
>Thanks,
>Benny

What do you think about this approach:
(One problem is that this no longer looks very much like a C-program).

----save the following as dummy.c----
#if 0
echo "extracting man-page"
cat <<MAN_PAGE >dummy.1
.TH DUMMY 1L
.SH NAME
dummy \- do nothing
.SH DESCRIPTION
.B dummy
does nothing.
It uses therefor the file
.I dummy.data .
.SH FILES
dummy.data
.SH BUGS
none
MAN_PAGE
echo "extracting database"
cat <<DATA_BASE >dummy.data
1 2 3 4 5
DATA_BASE
exit 0
#endif
main() {}
---cut here---
----------------------------------------------
Thomas Heller, University of Muenster, Germany   <PPH93@DMSWWU1A.BITNET>

cdl@chiton.ucsd.edu (Carl Lowenstein) (05/17/91)

In article <271@ra.nrl-cmf.UUCP> ghost@ra.UUCP (Glenn Host) writes:
|In article <BENNY.91May15185447@dimona.vlss.amdahl.com> benny@vlss.amdahl.com
|	(Benny Schnaider) writes:
|>I am looking for a utility to extract documentation from a "C"
|>program. I want to have the documentation source as part of the "C" code
|>(comments) which can be easily extracted in a troff (man page)
|>format. The output should be similar to man 3 output format.
|
|As far as I know there is no such generic utility.  
|
|It is actually easy to write such a utility IF you write before you start
|writing the code - otherwise you send almost as much time modifying the
|original documents as you would typing them again.

It's pretty old, but an organized scheme for keeping documentation in
the same file as source code is part of DECUS C.  Of course, the doc's
were in RUNOFF format, but that's not too bad.  There was a program for
extracting the document and adding the appropriate RUNOFF headers.

DECUS 11-SP-018, as I remember the part number.
-- 
        carl lowenstein         marine physical lab     u.c. san diego
        {decvax|ucbvax} !ucsd!mpl!cdl                 cdl@mpl.ucsd.edu
                                                  clowenstein@ucsd.edu

les@chinet.chi.il.us (Leslie Mikesell) (05/17/91)

In article <BENNY.91May15185447@dimona.vlss.amdahl.com> benny@vlss.amdahl.com (Benny Schnaider) writes:

>I am looking for a utility to extract documentation from a "C"
>program. I want to have the documentation source as part of the "C" code
>(comments) which can be easily extracted in a troff (man page)
>format. The output should be similar to man 3 output format.

There was a nice shell script to do this included in the PC-MAIL program
posted to comp.sources.misc.  The aux/srctoman.sh file was in part
4 of the posting, v10i036.

Les Mikesell
  les@chinet.chi.il.us

tsacas@ipac.ilog.fr (Stephane Tsacas) (05/18/91)

Hi,

Why don't you use CWEB ?


  ,
Stephane
--
  ,
Stephane Tsacas 		UUCP: tsacas@ilog.fr
ILOG				...!{uunet,mcvax,inria}!ilog!tsacas
2 av Gallieni			tsacas%ilog@uunet.UU.NET
BP85 - 94253 Gentilly		Phone: (33-1) 46 63 6666
FRANCE				<<PUSHJ P, POPJ P, recursively>>

gtoal@tardis.computer-science.edinburgh.ac.uk (05/18/91)

In article <BENNY.91May15185447@dimona.vlss.amdahl.com> benny@vlss.amdahl.com (Benny Schnaider) writes:
:Hi,
:
:I am looking for a utility to extract documentation from a "C"
:program. I want to have the documentation source as part of the "C" code
:(comments) which can be easily extracted in a troff (man page)
:format. The output should be similar to man 3 output format.
:
:Thanks,
:Benny

There are a whole suite of tools to do this used by the TeX community;
you write your program in a format called 'web', which can be
processed to produce either a source file or a TeX documenty.

Web originally handled Pascal, but there are now many webs 
available, including at least two implementations for C.

The only drawback of this system is that the actual file that you
edit isn't as readable as you'ld like - the readable version is
the formatted output.  If you have a good graphics system, an
interactive TeX previewer, and a fast CPU to run all this stuff, it
can't be beaten.

Check your local TeX group/guru's for details.  Find Knuth's paper
'literate programming in web'.

Regards
Graham
PS Sorry it's not troff, so maybe it isn't really appropriate for
your particular job, but I thought I'd post anyway as others
might be interested...

brad@SSD.CSD.HARRIS.COM (Brad Appleton) (05/20/91)

I originally had replied only to the original poster but there seems to be
enough interest that I thought Id reply here. I have written a ksh script
that uses nawk to implement just such a beast (Im working on a replacement
written in perl). You can embed your documentation in ANY type of
source file you wish (C, C++, Pascal, etc).

Here is the script and a sample C source file for those of you that 
are interested. Let me know of any comments you might have.

______________________ "And miles to go before I sleep." ______________________
 Brad Appleton           brad@ssd.csd.harris.com       Harris Computer Systems
                             uunet!hcx1!brad           Fort Lauderdale, FL USA
~~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my company! ~~~~~~~~~~~~~~~~~~~

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  xdoc.ksh strsplit.c
# Wrapped by brad@hcx1 on Thu May 16 14:23:24 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'xdoc.ksh' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xdoc.ksh'\"
else
echo shar: Extracting \"'xdoc.ksh'\" \(6282 characters\)
sed "s/^X//" >'xdoc.ksh' <<'END_OF_FILE'
X#!/bin/ksh
X#
X# xdoc - eXtract DOCumentation from structured C-Comments
X#
X# Created  by Brad Appleton
X
XNAME="`basename $0`"
X
XSYNOPSIS="\
X$NAME  [-n] [-f function] [-i string] [-p pattern] [-mname] [-s section]
X             [-t type=name] [-I subsection(s)] [-X subsection(s)]
X             [file ...]\
X"
X
XDESCRIPTION="\
X$NAME will extract the documentation associated with the named section from
Xthe given files. If no section is given, then FILE is assumed.\
X"
X
XOPTIONS="\
X-n              Dont print section title
X-f function     Extract text for the given function
X-i string       Indent text using the given string (default=3-spaces)
X-p pattern      Specify the pattern to trim of the beginning of each line
X                (default=\"[ \\t]\")
X-m name         Use the {t,n}roff -mname macros to format the ouput
X-s section      Extract text for the named section
X-t type=name    Extract text for the named type
X-I subsections  Specify which subsection(s) of the named section are to be
X                included in the output. If multiple subsections are desired
X                then the list must be placed in a single command-line argument.
X                By default, all subsections are printed.
X-X subsections  Specify which subsection(s) of the named section are to be
X                excluded from the output. If multiple subsections are desired
X                then the list must be placed in a single command-line argument.
X                By default, no subsections are excluded.
X"
X
Xset +o nounset
X
Xfunction print_usage {
X  print -u2 "\nUsage: ${SYNOPSIS}"
X  if [ "$OPTIONS" ] ; then
X    print -u2 "\n${OPTIONS}"
X  fi
X  if [ "$DESCRIPTION" ] ; then
X    print -u2 "\n${DESCRIPTION}"
X  fi
X  print
X  exit ${1-:2}
X}
X
Xalias warn_user="print -u2 '** '"
X
Xfunction error_msg {
X  print -u2 "${NAME}: $*"
X}
X
Xfunction fatal_msg {
X  print -u2 "${NAME}: $*"
X  exit 2
X}
X
XSTARTPAT='^[ 	]'
XKWD='FILE'; isFUNC=0; isSECTION=0; isTYPE=0; NOHEADINGS=0;
XINCLUDES='.*'; EXCLUDES='';
X
X## trim all leading and trailing whitespace, and compress whitespace
Xfunction tidylist {
X   print "$*" | sed -e 's/^[ 	]//' -e 's/[ 	]*$//' -e 's/[ 	][ 	]*/ /g'
X}
X
X## parse options
Xwhile getopts ':f:m:s:t:i:p:I:X:' OPT
X  do case "$OPT" in
X    n) NOTITLE='TRUE';;
X	f) KWD='FUNCTION'; IDENT="$OPTARG" ; isFUNC=1;;
X    s) KWD='SECTION'; IDENT="$OPTARG"; isSECTION=1 ;;
X    t) KWD="$(print ${OPTARG%=*} | tr '[a-z]' '[A-Z]')"; IDENT="${OPTARG#*=}";
X       isTYPE=1 ;;
X    i) INDENT="${OPTARG}" ;;
X    p) STARTPAT="^${OPTARG#\^}" ;;
X    m) MACROS="-m${OPTARG}" ;;
X    I) INCLUDES="${OPTARG}" ;;
X    X) EXCLUDES="${OPTARG}" ;;
X	:) error_msg "$OPTARG requires a value"; print_usage ;;
X	\?) error_msg "unknown option $OPTARG"; print_usage ;;
X  esac
Xdone
Xshift OPTIND-1
X
Xif [ $# -eq 0  -a  -t 1 ] ; then
X  print_usage;
X  exit 2;
Xfi
X
Xtest $isFUNC -ne 0  -a  $isSECTION -ne 0  &&  badopts='TRUE'
Xtest $isFUNC -ne 0  -a  $isTYPE -ne 0  &&  badopts='TRUE'
Xtest $isTYPE -ne 0  -a  $isSECTION -ne 0  &&  badopts='TRUE'
Xif [ "$badopts" ] ; then
X  fatal_msg "only one of -f, -s, and -t may be used"
Xfi
X
XPATTERN="\^${KWD}:${IDENT:+[ 	]*${IDENT}[^A-Z0-9]*}"
X
X## trim and compress all spaces and tabs in subsection lists
XINCLUDES="$( tidylist $INCLUDES )"
XEXCLUDES="$( tidylist $EXCLUDES )"
X
Xif [ "$NOTITLE" ] ; then
X  ENTITLED='1'
Xelse
X  ENTITLED='0'
Xfi
X
Xawk '
X  BEGIN {
X    processing=0; ignore=0; entitled='$ENTITLED'; indent="'"${INDENT:-   }"'";
X    keyword="'"$KWD"'"; section='$isSECTION'; macros="'"${MACROS:-}"'";
X    startpat="'"$STARTPAT"'";
X    nincl = split( "'"$INCLUDES"'", includes, " " );
X    nexcl = split( "'"$EXCLUDES"'", excludes, " " );
X  }
X
X  function is_needed(subsection) {
X    ## first see if it is excluded
X    for ( i = 1 ; i <= nexcl ; i++ )
X      if ( match(subsection, excludes[i]) )  return  0;  ## not-needed
X    
X    ## now see if it is included
X    for ( i = 1 ; i <= nincl ; i++ )
X      if ( match(subsection, includes[i]) )  return  1;  ## needed
X
X    return  0;  ## not-needed
X  }
X
X  function uncomment(filename, textline) {
X    text = textline;
X    if ( match(filename, "^.*\.[CHchly]$") ) {  ## C and C++ comments
X      gsub( /\/\//, "", text );
X      gsub( /\/\*/, "", text );
X      gsub( /\*\//, "", text );
X      sub( /^[ \t]*\*\**/, "", text );
X    }
X    else {  ## assume sh, csh, or ksh comments
X      sub( /^[ \t]*##*/, "", text );
X    }
X
X    return  text;
X  }
X
X  function print_heading( level, heading, name, purpose ) {
X    if ( macros == "-man" )
X      printf( ".SH \"%s\"\n", heading );
X    else if ( macros == "-me" )
X      printf( ".sh %d \"%s\"\n", level, heading );
X    else if ( macros == "-mm" )
X      printf( ".H %d \"%s\"\n", level, heading );
X    else
X      printf( "%s:\n", heading );
X
X    if ( name != "" ) {
X      if ( macros != "" )
X        printf( "%s \\- %s\n", name, purpose );
X      else
X        printf( "%s%s -- %s\n", indent, name, purpose );
X    }
X  }
X
X  function start_paragraph( str ) {
X    if ( macros == "-man" )
X      printf( ".PP\n" );
X    else if ( macros == "-me" )
X      printf( ".pp\n" );
X    else if ( macros == "-mm" )
X      printf( ".P\n" );
X    else
X      printf( "%s", str );
X  }
X
X  /\^\^/ {
X    processing=0; ignore=0; next;
X  }
X
X  /'"$PATTERN"'/ {
X    ++processing; purpose=$0; name="'"$IDENT"'";
X    if ( name == "" )  name=FILENAME;
X    re = sprintf( "^.*:[ \t]*%s[-:=# \t]*", name );
X    if ( re != "" )  sub( re, "", purpose );
X    if ( section ) {
X      if ( !entitled ) {
X        ++entitled;
X        print_heading( 1, name, "", "" );
X        start_paragraph( "" );
X      }
X      else
X        start_paragraph( "\n" );
X    }
X    else { 
X      if ( !entitled ) {
X        ++entitled;
X        print_heading( 1, keyword, name, purpose );
X      }
X    }
X    next;
X  }
X
X  /\^[A-Z][-_A-Z0-9]*:/ {
X    if ( !processing )  next;
X    title=$0;
X    sub( "^.*\\^", "", title );
X    sub( ":.*$", "", title );
X    gsub( "[-_]", " ", title );
X    if ( is_needed(title) ) {
X      ignore=0;
X      print_heading( 2, title, "", "" );
X      start_paragraph( "" );
X    }
X    else {
X      ++ignore;
X    }
X    next;
X  }
X
X  {
X    if ( !processing )  next;
X    if ( ignore )  next;
X    line = uncomment(FILENAME, $0);
X    if ( startpat != "" )  sub( startpat, "", line );
X    if ( macros == "" ) {
X       printf( "%s", indent );
X    }
X    print line;
X  }
X' "$@"
X
END_OF_FILE
if test 6282 -ne `wc -c <'xdoc.ksh'`; then
    echo shar: \"'xdoc.ksh'\" unpacked with wrong size!
fi
chmod +x 'xdoc.ksh'
# end of 'xdoc.ksh'
fi
if test -f 'strsplit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'strsplit.c'\"
else
echo shar: Extracting \"'strsplit.c'\" \(6901 characters\)
sed "s/^X//" >'strsplit.c' <<'END_OF_FILE'
X/**************************************************************************
X** ^FILE: strsplit.c - split and join strings
X**
X** ^DESCRIPTION:
X**    This file implemets the following functions:
X**
X**       strsplit() -- split a string up into a vector of tokens
X**       strjoin() -- join a vector of tokens into a single string
X**
X** ^HISTORY:
X**    01/02/91 	Brad Appleton 	<brad@ssd.csd.harris.com> 	Created
X***^^**********************************************************************/
X
X#include <stdio.h>
X#include <ctype.h>
X
X#define  CHARNULL  (vhar *)NULL
Xstatic char WhiteSpace[] = " \t\n\r\v\f";
X
X
X/***************************************************************************
X** ^FUNCTION: strsplit - split a string into tokens
X**
X** ^SYNOPSIS:
X*/
X#ifndef __ANSI_C__
X   int  strsplit( vec, token_str, separators )
X/*
X** ^PARAMETERS:
X*/
X   char **vec[];
X/*    -- pointer to the string vector to be allocated
X*/
X   char token_str[];
X/*    -- the string to be split up
X*/
X   char separators[];
X/*    -- the delimiters that separate tokens
X*/
X#endif  /* !__ANSI_C__ */
X
X/* ^DESCRIPTION:
X**    Strsplit will split token_str up into  a vector of tokens that are
X**    separated by one or more characters from <separators>. The number
X**    of tokens found is returned and storage is allocated for the given
X**    vector (which may later be deallocated using free()).
X**
X**    If <separators> is NULL or empty, then the set of whitespace characters
X**    is used as the token delimiters.
X**
X** ^REQUIREMENTS:
X**    vec must be non-NULL (it must be a valid address).
X**    token_str should be non-null and non-empty
X**
X** ^SIDE-EFECTS:
X**    All leading and trailing characters from <separators> are removed
X**    from token_str. Furthermore, all remaining sequences in token_str
X**    of characters from <separators> are replaced with a single NUL-byte.
X**
X**    Token_str holds the actual storage for all the strings in the newly
X**    created vector.
X**
X** ^RETURN-VALUE:
X**    The number of tokens parsed.
X**
X** ^ALGORITHM:
X**    - count the number of tokens present while at the same time removing
X**      all leading and trailing delimiters, and replacing all other sequences
X**      of delimiters with the NUL character.
X**    - allocate a vector large enough to point to all the token strings.
X**    - for i in 0 .. (numtokens - 1) do
X**         - vector[i] = token_str
X**         - advance token_str to point at the next character past the
X**           rightmost NUL-byte (which should be the start of the next token).
X**      end-for
X**    - return the number of tokens parsed.
X***^^**********************************************************************/
X#ifdef __ANSI_C__
X   int strsplit( char **vec[], char token_str[], const char separators[] )
X#endif
X{
X   register   char c, *pread, *pwrite;
X   int   i, count = 0;
X
X   if ( !token_str )    return   0;
X      /* if delim-string is NULL, whitespace is used */
X   if ( !separators )   separators = WhiteSpace;
X
X      /* trim leading separators */
X   pread = token_str;
X   while ( strchr(separators, *pread) )   ++pread;
X   token_str = pwrite = pread;
X
X      /*
X      ** make first pass through string, counting # of tokens and
X      ** separating all tokens by a single '\0'
X      */
X   while ( c = *pread++ ) {
X      if ( !strchr(separators, c) )   {
X         *pwrite++ = c;
X      }
X      else {
X         *pwrite++ = '\0';   /* null terminate this token */
X         ++count;                /* update token count */
X         while ( strchr(separators, *pread) )   ++pread;
X      }
X   }/*while*/
X   if ( *(pwrite - 1) )  {
X      ++count;         /* dont forget last token */
X      *pwrite = '\0';   /* null-terminate */
X   }
X
X      /* allocate space for the caller's vector (remember NULL at the end) */
X   (*vec) = (char **)malloc( (1 + count) * sizeof( char * ) );
X   if ( !*vec ) {
X      fprintf( stderr, "out of memory in strsplit() - aborting\n" );
X      exit( -1 );
X   }
X
X      /* now go thru token-string again assigning pointers from vector */
X   pread = token_str;
X   for ( i = 0 ; i < count ; i++ ) {
X      (*vec)[i] = pread;   /* assign pointer */
X      pread += strlen( pread ) + 1;
X   }/* end-for */
X
X      /* set up the trailing pointer to NULL at the end */
X   (*vec)[ count ] = CHARNULL;
X   return   count;
X}
X
X
X/***************************************************************************
X** ^FUNCTION: strjoin - join a vector of tokens together
X**
X** ^SYNOPSIS:
X*/
X#ifndef __ANSI_C__
X   char  *strjoin( argv, separator )
X/*
X** ^PARAMETERS:
X*/
X   char *argv[];
X/*    -- pointer to the string vector to join together
X*/
X   char separator[];
X/*    -- the the string to use to separate tokens (if NULL, " " is used)
X*/
X#endif  /* !__ANSI_C__ */
X
X/* ^DESCRIPTION:
X**    Strjoin will make a single string out of the given vector by copying
X**    all the tokens from the given vector (in order) to a newly allocated
X**    string. Tokens will be separated by a single occurence of <separator>.
X**
X**    If <separator> is NULL then a single space is used as the separator.
X**    If <separator> is empty, then no separator is used and the tokens are
X**    simply concatenated together.
X**
X** ^REQUIREMENTS:
X**    argv must be non-NULL (it must be a valid address), and must be
X**    terminated by a pointer to NULL (argv[last+1] == NULL).
X**
X** ^SIDE-EFECTS:
X**    Storage is allocated.
X**
X** ^RETURN-VALUE:
X**    The address of the newly-joined result (which should be deallocated
X**    using free()). Returns NULL if nothing was joined.
X**
X** ^ALGORITHM:
X**    - count the number of characters to place in the joined-result.
X**    - allocate a string large-enough to copy the joined-result into.
X**    - copy each string into the string (with <separator> between tokens).
X**    - 0 return the result.
X***^^**********************************************************************/
X#ifdef __ANSI_C__
X   char *strjoin( const char *argv[], const char separator[] )
X#endif
X{
X   size_t  sz = 0;
X   register char *p;
X   register CONST char *a, **av;
X   register int  seplen;
X   char *result;
X
X      /* if argv is NULL, nothing to do */
X   if ( !argv )  return  CHARNULL;
X   if ( !separator )  separator = " ";
X   seplen = strlen( separator );
X
X      /* figure out how much space we need */
X   for ( av = argv ; *av ; av++ ) {
X      if ( !**av )  continue;
X      sz += strlen( *av );
X      if ( seplen  &&  *(av + 1) )  sz += seplen;
X   }
X
X      /* allocate space */
X   result = (char *)malloc( (sz + 1) * sizeof(char) );
X   if ( !result )  syserr( "malloc failed in strjoin()" );
X
X      /* join the strings together */
X   *result = '\0';
X   for ( av = argv, p = result ; (a = *av) ; av++ ) {
X      if ( !*a )  continue;
X      while ( (*p = *a++) ) ++p;  /* copy token */
X      if ( seplen  &&  *(av + 1) ) {
X         a = separator;
X         while ( (*p = *a++) ) ++p;  /* copy separator */
X      }/*end-if*/
X   }/*end-for*/
X
X   return  result;
X}
END_OF_FILE
if test 6901 -ne `wc -c <'strsplit.c'`; then
    echo shar: \"'strsplit.c'\" unpacked with wrong size!
fi
# end of 'strsplit.c'
fi
echo shar: End of shell archive.
exit 0
______________________ "And miles to go before I sleep." ______________________
 Brad Appleton           brad@ssd.csd.harris.com       Harris Computer Systems
                             uunet!hcx1!brad           Fort Lauderdale, FL USA
~~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my company! ~~~~~~~~~~~~~~~~~~~

Dan_Jacobson@ATT.COM (05/21/91)

>>>>> On 17 May 91 22:29:06 GMT, tsacas@ipac.ilog.fr (Stephane Tsacas) said:

Stephane> Why don't you use CWEB ?

also, I saw this on comp.text.tex:

J> To: TeXhax@CS.WASHINGTON.EDU
J> Date: Wed, 01 May 91 07:19:39 -0400
J> From: ramsdell@linus.mitre.org
J> Subject: c2latex is on sun.soe.clarkson.edu
J> Keywords: c2latex, clarkson
J> 
J> c2latex is available via anonymous FTP from sun.soe.clarkson.edu in
J> the tex programs directory.  Some people have reported problems with
J> indentation in formatted listings.  As near as I can tell, the problems
J> disappear when the most recent version of LaTeX is used.
J> 
J> John
J> 
J> 			       c2latex
J> 
J> c2latex provides simple support for literate programming in C.  Given
J> a C source file in which the comments have been written in LaTeX,
J> c2latex converts the C source file into a LaTeX source file.  It can
J> be used to produce typeset listings of C programs and/or documentation
J> associated with the program.

wirzeniu@klaava.Helsinki.FI (Lars Wirzenius) (05/26/91)

In article <91137.144344PPH93@DMSWWU1A.BITNET> PPH93@DMSWWU1A.BITNET (Thomas Heller) writes:
>#if 0
> [nroff source for manual page]
>#endif
>main() {}

The problem with this approach, is that all that nroff source still
needs to be valid C tokens.  You can't, for example, write a line that
only consists of the word can't, since that would introduce an
unterminated character constant. 

Not all compilers check this (but some do), of course, but it isn't
valid according to the ANSI standard for C, so it is not good planning
for to future.
-- 
Lars Wirzenius     wirzeniu@cc.helsinki.fi

ivanp@mc.UUCP (Ivan Peters) (06/06/91)

In article <BENNY.91May15185447@dimona.vlss.amdahl.com>, benny@vlss.amdahl.com (Benny Schnaider) writes:
|> Hi,
|> 
|> I am looking for a utility to extract documentation from a "C"
|> program. I want to have the documentation source as part of the "C" code
|> (comments) which can be easily extracted in a troff (man page)
|> format. The output should be similar to man 3 output format.
|> 
|> Thanks,
|> Benny
|> --

Heres another way, among many...
We have the following format for standard headers in the src...

file headers:
/*M***************************************************************************
*
*   File Name:      filename.c
*
*   Description:    This module .....
*
*
*   Functions:
*                   function_name
*                   function_name
*
*
*
*
*   Revision History:
*   Date        Engineer        Comment
*   mm/dd/yy    I. Software     xxxxxxxxxxxxxxxxxx
*
****************************************************************************M*/
functions in files:
/*F****************************************************************************
*
*   Function Name:  function_name
*
*   Description:    This function ..
*
*   Input:
*
*
*   Output:
*
*
*   Return:
*
*
*   Notes:
*
*
*
*
****************************************************************************F*/
include file headers:
/*I***************************************************************************
*
*   File Name:      filename.h
*
*   Description:    Common equates for files
*
*
*   Revision History:
*   Date        Engineer        Comment
*   mm/dd/yy    I. Software     xxxxxxxxxxxxxxxxxx
*
****************************************************************************I*/

I have a combination awk/sed script that will generate manpages of the stuff
in those headers as follows:


awk '/\*M\*/,/\*\*M\*/
     /\*F\*/,/\*\*F\*/
     /\*I\*/,/\*\*I\*/' | \
sed -e 's%\/\*F\*%    %g' \
    -e 's%\*F\*\/%    %g' \
    -e 's%\/\*M\*%    %g' \
    -e 's%\*M\*\/%    %g' \
    -e 's%\*% %g' |\
awk '
BEGIN { f=0 }
{if (($1 ~ /File/) && ($2 ~ /Name/)) { {print ".TH",$3, "3"} ; f++}
else {if ($1 ~ /Description\:/) {print ".SH",$0}
else {if ($1 ~ /Functions\:/) {print ".SH",$0}
else {if (($1 ~ /Revision/) && ($2 ~ /History\:/)) {print ".SH",$0}
else {if (($1 ~ /Function/) && ($2 ~ /Name\:/)) {print ".TH",$3, "3"}
else {if ($1 ~ /Input\:/) {print ".SH",$0}
else {if ($1 ~ /Output\:/) {print ".SH",$0}
else {if ($1 ~ /Return\:/) {print ".SH",$0}
else {if (f > 0) {print $0 }  }
}
}
}
}
}
}
}
}
' | \
awk '
BEGIN {n=0}
{ for (i=1; i<=NF; i++)
    {{printf "%s ",$i}
    {if (i ==NF)
       {
       {printf "\n"}
       {n++}
       }
    }
}
}
{if (NR >= n+1 ) {
    {printf "\n"}
    {n = NR}
}
}
------------------
Known bug: It strips any info, on the same line (following) a key word.
  example: Description xxxxx          (will remove xxxxx)
This can easily be fixed with a awk function but I did not have the time yet.

Since this is a awk/sed script, it is easily modified, and portable.  One
can change the keyword searches, in the comments to whatever...  One could
also change this for other comment styles/headers/src other than 'c' easily.

Excuse me for useing awk/sed (for you alt lang types) in advance.   Perl
might be able to do this easier, but I have not yet graduated from awk/sed 
land yet...  :-).

This generates the man format.

(If you see him, Say hi to Mark Schrandt@Amdahl for me...:-) )