1/* Give this program DOC-mm.nn.oo as standard input and it outputs to
2   standard output a file of texinfo input containing the doc strings.
3
4   Copyright (C) 1989, 1992, 1994, 1996, 1999, 2000, 2001, 2002, 2003,
5                 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
6
7   This file is part of GNU Emacs.
8
9   GNU Emacs is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2, or (at your option)
12   any later version.
13
14   GNU Emacs is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with GNU Emacs; see the file COPYING.  If not, write to the
21   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22   Boston, MA 02110-1301, USA.
23
24   This version sorts the output by function name.  */
25
26#ifdef HAVE_CONFIG_H
27#include <config.h>
28#endif
29
30#include <stdio.h>
31#include <ctype.h>
32#ifdef DOS_NT
33#include <fcntl.h>		/* for O_BINARY */
34#include <io.h>			/* for setmode */
35#endif
36#ifndef HAVE_STDLIB_H		/* config.h includes stdlib.  */
37#ifndef WINDOWSNT		/* src/s/ms-w32.h includes stdlib.h */
38extern char *malloc ();
39#endif
40#endif
41
42#define NUL	'\0'
43#define MARKER '\037'
44
45#define DEBUG 0
46
47typedef struct line LINE;
48
49struct line
50{
51  LINE *next;			/* ptr to next or NULL */
52  char *line;			/* text of the line */
53};
54
55typedef struct docstr DOCSTR;
56
57struct docstr			/* Allocated thing for an entry. */
58{
59  DOCSTR *next;			/* next in the chain */
60  char *name;			/* name of the function or var */
61  LINE *first;			/* first line of doc text. */
62  char type;			/* 'F' for function, 'V' for variable */
63};
64
65
66/* Print error message.  `s1' is printf control string, `s2' is arg for it. */
67
68void
69error (s1, s2)
70     char *s1, *s2;
71{
72  fprintf (stderr, "sorted-doc: ");
73  fprintf (stderr, s1, s2);
74  fprintf (stderr, "\n");
75}
76
77/* Print error message and exit.  */
78
79void
80fatal (s1, s2)
81     char *s1, *s2;
82{
83  error (s1, s2);
84  exit (EXIT_FAILURE);
85}
86
87/* Like malloc but get fatal error if memory is exhausted.  */
88
89char *
90xmalloc (size)
91     int size;
92{
93  char *result = malloc ((unsigned)size);
94  if (result == NULL)
95    fatal ("%s", "virtual memory exhausted");
96  return result;
97}
98
99char *
100xstrdup (str)
101     char * str;
102{
103  char *buf = xmalloc (strlen (str) + 1);
104  (void) strcpy (buf, str);
105  return (buf);
106}
107
108/* Comparison function for qsort to call.  */
109
110int
111cmpdoc (a, b)
112     DOCSTR **a;
113     DOCSTR **b;
114{
115  register int val = strcmp ((*a)->name, (*b)->name);
116  if (val) return val;
117  return (*a)->type - (*b)->type;
118}
119
120
121enum state
122{
123  WAITING, BEG_NAME, NAME_GET, BEG_DESC, DESC_GET
124};
125
126char *states[] =
127{
128  "WAITING", "BEG_NAME", "NAME_GET", "BEG_DESC", "DESC_GET"
129};
130
131int
132main ()
133{
134  register DOCSTR *dp = NULL;	/* allocated DOCSTR */
135  register LINE *lp = NULL;	/* allocated line */
136  register char *bp;		/* ptr inside line buffer */
137  register enum state state = WAITING; /* state at start */
138  int cnt = 0;			/* number of DOCSTRs read */
139
140  DOCSTR *docs = NULL;          /* chain of allocated DOCSTRS */
141  char buf[512];		/* line buffer */
142
143#ifdef DOS_NT
144  /* DOC is a binary file.  */
145  if (!isatty (fileno (stdin)))
146    setmode (fileno (stdin), O_BINARY);
147#endif
148
149  bp = buf;
150
151  while (1)			/* process one char at a time */
152    {
153      /* this char from the DOCSTR file */
154      register int ch = getchar ();
155
156      /* Beginnings */
157
158      if (state == WAITING)
159	{
160	  if (ch == MARKER)
161	    state = BEG_NAME;
162	}
163      else if (state == BEG_NAME)
164	{
165	  cnt++;
166	  if (dp == NULL)	/* first dp allocated */
167	    {
168	      docs = dp = (DOCSTR*) xmalloc (sizeof (DOCSTR));
169	    }
170	  else			/* all the rest */
171	    {
172	      dp->next = (DOCSTR*) xmalloc (sizeof (DOCSTR));
173	      dp = dp->next;
174	    }
175	  lp = NULL;
176	  dp->next = NULL;
177	  bp = buf;
178	  state = NAME_GET;
179	  /* Record whether function or variable.  */
180	  dp->type = ch;
181	  ch = getchar ();
182	}
183      else if (state == BEG_DESC)
184	{
185	  if (lp == NULL)	/* first line for dp */
186	    {
187	      dp->first = lp = (LINE*)xmalloc (sizeof (LINE));
188	    }
189	  else			/* continuing lines */
190	    {
191	      lp->next = (LINE*)xmalloc (sizeof (LINE));
192	      lp = lp->next;
193	    }
194	  lp->next = NULL;
195	  bp = buf;
196	  state = DESC_GET;
197	}
198
199      /* process gets */
200
201      if (state == NAME_GET || state == DESC_GET)
202	{
203	  if (ch != MARKER && ch != '\n' && ch != EOF)
204	    {
205	      *bp++ = ch;
206	    }
207	  else			/* saving and changing state */
208	    {
209	      *bp = NUL;
210	      bp = xstrdup (buf);
211
212	      if (state == NAME_GET)
213		dp->name = bp;
214	      else
215		lp->line = bp;
216
217	      bp = buf;
218	      state =  (ch == MARKER) ? BEG_NAME : BEG_DESC;
219	    }
220	}			/* NAME_GET || DESC_GET */
221      if (ch == EOF)
222	break;
223    }
224
225  {
226    DOCSTR **array;
227    register int i;		/* counter */
228
229    /* build array of ptrs to DOCSTRs */
230
231    array = (DOCSTR**)xmalloc (cnt * sizeof (*array));
232    for (dp = docs, i = 0; dp != NULL ; dp = dp->next)
233      array[i++] = dp;
234
235    /* sort the array by name; within each name, by type */
236
237    qsort ((char*)array, cnt, sizeof (DOCSTR*), cmpdoc);
238
239    /* write the output header */
240
241    printf ("\\input texinfo  @c -*-texinfo-*-\n");
242    printf ("@setfilename ../info/summary\n");
243    printf ("@settitle Command Summary for GNU Emacs\n");
244    printf ("@finalout\n");
245    printf ("@unnumbered Command Summary for GNU Emacs\n");
246    printf ("@table @asis\n");
247    printf ("\n");
248    printf ("@iftex\n");
249    printf ("@global@let@ITEM@item\n");
250    printf ("@def@item{@filbreak@vskip5pt@ITEM}\n");
251    printf ("@font@tensy cmsy10 scaled @magstephalf\n");
252    printf ("@font@teni cmmi10 scaled @magstephalf\n");
253    printf ("@def\\{{@tensy@char110}}\n"); /* this backslash goes with cmr10 */
254    printf ("@def|{{@tensy@char106}}\n");
255    printf ("@def@{{{@tensy@char102}}\n");
256    printf ("@def@}{{@tensy@char103}}\n");
257    printf ("@def<{{@teni@char62}}\n");
258    printf ("@def>{{@teni@char60}}\n");
259    printf ("@chardef@@64\n");
260    printf ("@catcode43=12\n");
261    printf ("@tableindent-0.2in\n");
262    printf ("@end iftex\n");
263
264    /* print each function from the array */
265
266    for (i = 0; i < cnt; i++)
267      {
268	printf ("\n@item %s @code{%s}\n@display\n",
269		array[i]->type == 'F' ? "Function" : "Variable",
270		array[i]->name);
271
272	for (lp = array[i]->first; lp != NULL ; lp = lp->next)
273	  {
274	    for (bp = lp->line; *bp; bp++)
275	      {
276		/* the characters "@{}" need special treatment */
277		if (*bp == '@' || *bp == '{' || *bp == '}')
278		  {
279		    putchar('@');
280		  }
281		putchar(*bp);
282	      }
283	    putchar ('\n');
284	  }
285	printf("@end display\n");
286	/* Try to avoid a save size overflow in the TeX output
287           routine.  */
288	if (i%100 == 0 && i > 0 && i != cnt)
289	  printf("\n@end table\n@table @asis\n");
290      }
291
292    printf ("@end table\n");
293    printf ("@bye\n");
294  }
295
296  return EXIT_SUCCESS;
297}
298
299/* arch-tag: ce28f204-1e70-4b34-8210-3d54a5662071
300   (do not change this comment) */
301
302/* sorted-doc.c ends here */
303