sorted-doc.c 6.92 KB
Newer Older
Richard M. Stallman's avatar
Richard M. Stallman committed
1
/* Give this program DOC-mm.nn.oo as standard input and it outputs to
Gerd Moellmann's avatar
Gerd Moellmann committed
2
   standard output a file of texinfo input containing the doc strings.
Pavel Janík's avatar
Pavel Janík committed
3

4
Copyright (C) 1989, 1992, 1994, 1996, 1999, 2000, 2001, 2002, 2003,
Glenn Morris's avatar
Glenn Morris committed
5
              2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
Gerd Moellmann's avatar
Gerd Moellmann committed
6

7
This file is part of GNU Emacs.
Gerd Moellmann's avatar
Gerd Moellmann committed
8

9 10 11 12
GNU Emacs 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 3 of the License, or
(at your option) any later version.
Gerd Moellmann's avatar
Gerd Moellmann committed
13

14 15 16 17
GNU Emacs 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.
Gerd Moellmann's avatar
Gerd Moellmann committed
18

19 20
You should have received a copy of the GNU General Public License
along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
21

22 23

/* This version sorts the output by function name.  */
Jim Blandy's avatar
Jim Blandy committed
24

Pavel Janík's avatar
Pavel Janík committed
25 26 27 28
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

Jim Blandy's avatar
Jim Blandy committed
29 30
#include <stdio.h>
#include <ctype.h>
31 32 33 34
#ifdef DOS_NT
#include <fcntl.h>		/* for O_BINARY */
#include <io.h>			/* for setmode */
#endif
Dave Love's avatar
Dave Love committed
35
#ifndef HAVE_STDLIB_H		/* config.h includes stdlib.  */
36
#ifndef WINDOWSNT		/* src/s/ms-w32.h includes stdlib.h */
Jim Blandy's avatar
Jim Blandy committed
37
extern char *malloc ();
Dave Love's avatar
Dave Love committed
38
#endif
39
#endif
Jim Blandy's avatar
Jim Blandy committed
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

#define NUL	'\0'
#define MARKER '\037'

#define DEBUG 0

typedef struct line LINE;

struct line
{
  LINE *next;			/* ptr to next or NULL */
  char *line;			/* text of the line */
};

typedef struct docstr DOCSTR;

struct docstr			/* Allocated thing for an entry. */
{
  DOCSTR *next;			/* next in the chain */
  char *name;			/* name of the function or var */
  LINE *first;			/* first line of doc text. */
  char type;			/* 'F' for function, 'V' for variable */
};


/* Print error message.  `s1' is printf control string, `s2' is arg for it. */

67
void
68
error (char *s1, char *s2)
Jim Blandy's avatar
Jim Blandy committed
69 70 71 72 73 74
{
  fprintf (stderr, "sorted-doc: ");
  fprintf (stderr, s1, s2);
  fprintf (stderr, "\n");
}

75 76 77
/* Print error message and exit.  */

void
78
fatal (char *s1, char *s2)
79 80
{
  error (s1, s2);
81
  exit (EXIT_FAILURE);
82 83
}

Jim Blandy's avatar
Jim Blandy committed
84 85 86
/* Like malloc but get fatal error if memory is exhausted.  */

char *
87
xmalloc (int size)
Jim Blandy's avatar
Jim Blandy committed
88 89 90 91 92 93 94 95
{
  char *result = malloc ((unsigned)size);
  if (result == NULL)
    fatal ("%s", "virtual memory exhausted");
  return result;
}

char *
96
xstrdup (char *str)
Jim Blandy's avatar
Jim Blandy committed
97 98 99 100 101 102 103 104 105
{
  char *buf = xmalloc (strlen (str) + 1);
  (void) strcpy (buf, str);
  return (buf);
}

/* Comparison function for qsort to call.  */

int
Andreas Schwab's avatar
Andreas Schwab committed
106
cmpdoc (const void *va, const void *vb)
Jim Blandy's avatar
Jim Blandy committed
107
{
Andreas Schwab's avatar
Andreas Schwab committed
108 109
  DOCSTR *const *a = va;
  DOCSTR *const *b = vb;
Jim Blandy's avatar
Jim Blandy committed
110 111 112 113 114 115 116 117 118 119 120 121 122 123
  register int val = strcmp ((*a)->name, (*b)->name);
  if (val) return val;
  return (*a)->type - (*b)->type;
}

enum state
{
  WAITING, BEG_NAME, NAME_GET, BEG_DESC, DESC_GET
};

char *states[] =
{
  "WAITING", "BEG_NAME", "NAME_GET", "BEG_DESC", "DESC_GET"
};
Pavel Janík's avatar
Pavel Janík committed
124

125
int
126
main (void)
Jim Blandy's avatar
Jim Blandy committed
127 128 129 130 131 132 133
{
  register DOCSTR *dp = NULL;	/* allocated DOCSTR */
  register LINE *lp = NULL;	/* allocated line */
  register char *bp;		/* ptr inside line buffer */
  register enum state state = WAITING; /* state at start */
  int cnt = 0;			/* number of DOCSTRs read */

134
  DOCSTR *docs = NULL;          /* chain of allocated DOCSTRS */
Jim Blandy's avatar
Jim Blandy committed
135
  char buf[512];		/* line buffer */
Pavel Janík's avatar
Pavel Janík committed
136

137 138 139 140 141 142
#ifdef DOS_NT
  /* DOC is a binary file.  */
  if (!isatty (fileno (stdin)))
    setmode (fileno (stdin), O_BINARY);
#endif

143 144
  bp = buf;

Jim Blandy's avatar
Jim Blandy committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
  while (1)			/* process one char at a time */
    {
      /* this char from the DOCSTR file */
      register int ch = getchar ();

      /* Beginnings */

      if (state == WAITING)
	{
	  if (ch == MARKER)
	    state = BEG_NAME;
	}
      else if (state == BEG_NAME)
	{
	  cnt++;
	  if (dp == NULL)	/* first dp allocated */
	    {
	      docs = dp = (DOCSTR*) xmalloc (sizeof (DOCSTR));
	    }
	  else			/* all the rest */
	    {
	      dp->next = (DOCSTR*) xmalloc (sizeof (DOCSTR));
	      dp = dp->next;
	    }
	  lp = NULL;
	  dp->next = NULL;
	  bp = buf;
	  state = NAME_GET;
	  /* Record whether function or variable.  */
	  dp->type = ch;
	  ch = getchar ();
	}
      else if (state == BEG_DESC)
	{
	  if (lp == NULL)	/* first line for dp */
	    {
	      dp->first = lp = (LINE*)xmalloc (sizeof (LINE));
	    }
	  else			/* continuing lines */
	    {
	      lp->next = (LINE*)xmalloc (sizeof (LINE));
	      lp = lp->next;
	    }
	  lp->next = NULL;
	  bp = buf;
	  state = DESC_GET;
	}
Pavel Janík's avatar
Pavel Janík committed
192

Jim Blandy's avatar
Jim Blandy committed
193 194 195 196 197 198 199 200 201 202 203
      /* process gets */

      if (state == NAME_GET || state == DESC_GET)
	{
	  if (ch != MARKER && ch != '\n' && ch != EOF)
	    {
	      *bp++ = ch;
	    }
	  else			/* saving and changing state */
	    {
	      *bp = NUL;
204
	      bp = xstrdup (buf);
Jim Blandy's avatar
Jim Blandy committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230

	      if (state == NAME_GET)
		dp->name = bp;
	      else
		lp->line = bp;

	      bp = buf;
	      state =  (ch == MARKER) ? BEG_NAME : BEG_DESC;
	    }
	}			/* NAME_GET || DESC_GET */
      if (ch == EOF)
	break;
    }

  {
    DOCSTR **array;
    register int i;		/* counter */

    /* build array of ptrs to DOCSTRs */

    array = (DOCSTR**)xmalloc (cnt * sizeof (*array));
    for (dp = docs, i = 0; dp != NULL ; dp = dp->next)
      array[i++] = dp;

    /* sort the array by name; within each name, by type */

Andreas Schwab's avatar
Andreas Schwab committed
231
    qsort ((char*)array, cnt, sizeof (DOCSTR*), cmpdoc);
Jim Blandy's avatar
Jim Blandy committed
232 233 234 235 236 237

    /* write the output header */

    printf ("\\input texinfo  @c -*-texinfo-*-\n");
    printf ("@setfilename ../info/summary\n");
    printf ("@settitle Command Summary for GNU Emacs\n");
238
    printf ("@finalout\n");
Jim Blandy's avatar
Jim Blandy committed
239 240
    printf ("@unnumbered Command Summary for GNU Emacs\n");
    printf ("@table @asis\n");
Richard M. Stallman's avatar
Richard M. Stallman committed
241
    printf ("\n");
242 243
    printf ("@iftex\n");
    printf ("@global@let@ITEM@item\n");
Richard M. Stallman's avatar
Richard M. Stallman committed
244 245 246 247 248 249 250 251 252 253 254 255
    printf ("@def@item{@filbreak@vskip5pt@ITEM}\n");
    printf ("@font@tensy cmsy10 scaled @magstephalf\n");
    printf ("@font@teni cmmi10 scaled @magstephalf\n");
    printf ("@def\\{{@tensy@char110}}\n"); /* this backslash goes with cmr10 */
    printf ("@def|{{@tensy@char106}}\n");
    printf ("@def@{{{@tensy@char102}}\n");
    printf ("@def@}{{@tensy@char103}}\n");
    printf ("@def<{{@teni@char62}}\n");
    printf ("@def>{{@teni@char60}}\n");
    printf ("@chardef@@64\n");
    printf ("@catcode43=12\n");
    printf ("@tableindent-0.2in\n");
256
    printf ("@end iftex\n");
Jim Blandy's avatar
Jim Blandy committed
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279

    /* print each function from the array */

    for (i = 0; i < cnt; i++)
      {
	printf ("\n@item %s @code{%s}\n@display\n",
		array[i]->type == 'F' ? "Function" : "Variable",
		array[i]->name);

	for (lp = array[i]->first; lp != NULL ; lp = lp->next)
	  {
	    for (bp = lp->line; *bp; bp++)
	      {
		/* the characters "@{}" need special treatment */
		if (*bp == '@' || *bp == '{' || *bp == '}')
		  {
		    putchar('@');
		  }
		putchar(*bp);
	      }
	    putchar ('\n');
	  }
	printf("@end display\n");
280 281 282 283
	/* Try to avoid a save size overflow in the TeX output
           routine.  */
	if (i%100 == 0 && i > 0 && i != cnt)
	  printf("\n@end table\n@table @asis\n");
Jim Blandy's avatar
Jim Blandy committed
284 285 286 287 288 289
      }

    printf ("@end table\n");
    printf ("@bye\n");
  }

290
  return EXIT_SUCCESS;
Jim Blandy's avatar
Jim Blandy committed
291
}
Miles Bader's avatar
Miles Bader committed
292 293 294

/* arch-tag: ce28f204-1e70-4b34-8210-3d54a5662071
   (do not change this comment) */
295 296

/* sorted-doc.c ends here */