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