428
+ − 1 /* Give this program DOCSTR.mm.nn as standard input
+ − 2 and it outputs to standard output
+ − 3 a file of texinfo input containing the doc strings.
+ − 4
+ − 5 This version sorts the output by function name.
+ − 6 */
+ − 7
+ − 8 /* Synched up with: FSF 19.28. */
+ − 9
438
+ − 10 #include <config.h>
428
+ − 11
+ − 12 #include <stdio.h>
+ − 13 #include <ctype.h>
440
+ − 14 #include <stdlib.h> /* for qsort() and malloc() */
+ − 15 #include <string.h>
+ − 16 static void *xmalloc (size_t);
428
+ − 17
+ − 18 #define NUL '\0'
+ − 19 #define MARKER '\037'
+ − 20
+ − 21 #define DEBUG 0
+ − 22
440
+ − 23 typedef struct LINE LINE;
428
+ − 24
440
+ − 25 struct LINE
428
+ − 26 {
+ − 27 LINE *next; /* ptr to next or NULL */
+ − 28 char *line; /* text of the line */
+ − 29 };
+ − 30
+ − 31 typedef struct docstr DOCSTR;
+ − 32
+ − 33 struct docstr /* Allocated thing for an entry. */
+ − 34 {
+ − 35 DOCSTR *next; /* next in the chain */
+ − 36 char *name; /* name of the function or var */
+ − 37 LINE *first; /* first line of doc text. */
+ − 38 char type; /* 'F' for function, 'V' for variable */
+ − 39 };
+ − 40
+ − 41
+ − 42 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
+ − 43
+ − 44 static void
+ − 45 error (char *s1, char *s2)
+ − 46 {
+ − 47 fprintf (stderr, "sorted-doc: ");
+ − 48 fprintf (stderr, s1, s2);
+ − 49 fprintf (stderr, "\n");
+ − 50 }
+ − 51
+ − 52 /* Print error message and exit. */
+ − 53
+ − 54 static void
+ − 55 fatal (char *s1, char *s2)
+ − 56 {
+ − 57 error (s1, s2);
+ − 58 exit (1);
+ − 59 }
+ − 60
+ − 61 /* Like malloc but get fatal error if memory is exhausted. */
+ − 62
+ − 63 static void *
440
+ − 64 xmalloc (size_t size)
428
+ − 65 {
440
+ − 66 void *result = malloc (size);
428
+ − 67 if (result == NULL)
+ − 68 fatal ("%s", "virtual memory exhausted");
+ − 69 return result;
+ − 70 }
+ − 71
+ − 72 static char *
+ − 73 strsav (char *str)
+ − 74 {
440
+ − 75 char *buf = (char *) xmalloc (strlen (str) + 1);
+ − 76 strcpy (buf, str);
+ − 77 return buf;
428
+ − 78 }
+ − 79
+ − 80 /* Comparison function for qsort to call. */
+ − 81
+ − 82 static int
+ − 83 cmpdoc (DOCSTR **a, DOCSTR **b)
+ − 84 {
+ − 85 register int val = strcmp ((*a)->name, (*b)->name);
+ − 86 if (val) return val;
+ − 87 return (*a)->type - (*b)->type;
+ − 88 }
+ − 89
+ − 90
+ − 91 enum state
+ − 92 {
+ − 93 WAITING, BEG_NAME, NAME_GET, BEG_DESC, DESC_GET
+ − 94 };
+ − 95
442
+ − 96 const char *states[] =
428
+ − 97 {
+ − 98 "WAITING", "BEG_NAME", "NAME_GET", "BEG_DESC", "DESC_GET"
+ − 99 };
+ − 100
+ − 101 int
2367
+ − 102 main (int argc, char **argv)
428
+ − 103 {
+ − 104 register DOCSTR *dp = NULL; /* allocated DOCSTR */
+ − 105 register LINE *lp = NULL; /* allocated line */
+ − 106 register char *bp = 0; /* ptr inside line buffer */
+ − 107 /* int notfirst = 0; / * set after read something */
+ − 108 register enum state state = WAITING; /* state at start */
+ − 109 int cnt = 0; /* number of DOCSTRs read */
+ − 110
+ − 111 DOCSTR *docs = 0; /* chain of allocated DOCSTRS */
+ − 112 char buf[512]; /* line buffer */
+ − 113
+ − 114 while (1) /* process one char at a time */
+ − 115 {
+ − 116 /* this char from the DOCSTR file */
+ − 117 register int ch = getchar ();
+ − 118
+ − 119 /* Beginnings */
+ − 120
+ − 121 if (state == WAITING)
+ − 122 {
+ − 123 if (ch == MARKER)
+ − 124 state = BEG_NAME;
+ − 125 }
+ − 126 else if (state == BEG_NAME)
+ − 127 {
+ − 128 cnt++;
+ − 129 if (dp == NULL) /* first dp allocated */
+ − 130 {
+ − 131 docs = dp = (DOCSTR*) xmalloc (sizeof (DOCSTR));
+ − 132 }
+ − 133 else /* all the rest */
+ − 134 {
+ − 135 dp->next = (DOCSTR*) xmalloc (sizeof (DOCSTR));
+ − 136 dp = dp->next;
+ − 137 }
+ − 138 lp = NULL;
+ − 139 dp->next = NULL;
+ − 140 bp = buf;
+ − 141 state = NAME_GET;
+ − 142 /* Record whether function or variable. */
+ − 143 dp->type = ch;
+ − 144 ch = getchar ();
+ − 145 }
+ − 146 else if (state == BEG_DESC)
+ − 147 {
+ − 148 if (lp == NULL) /* first line for dp */
+ − 149 {
+ − 150 dp->first = lp = (LINE*)xmalloc (sizeof (LINE));
+ − 151 }
+ − 152 else /* continuing lines */
+ − 153 {
+ − 154 lp->next = (LINE*)xmalloc (sizeof (LINE));
+ − 155 lp = lp->next;
+ − 156 }
+ − 157 lp->next = NULL;
+ − 158 bp = buf;
+ − 159 state = DESC_GET;
+ − 160 }
+ − 161
+ − 162 /* process gets */
+ − 163
+ − 164 if (state == NAME_GET || state == DESC_GET)
+ − 165 {
+ − 166 if (ch != MARKER && ch != '\n' && ch != EOF)
+ − 167 {
+ − 168 *bp++ = ch;
+ − 169 }
+ − 170 else /* saving and changing state */
+ − 171 {
+ − 172 *bp = NUL;
+ − 173 bp = strsav (buf);
+ − 174
+ − 175 if (state == NAME_GET)
+ − 176 dp->name = bp;
+ − 177 else
+ − 178 lp->line = bp;
+ − 179
+ − 180 bp = buf;
+ − 181 state = (ch == MARKER) ? BEG_NAME : BEG_DESC;
+ − 182 }
+ − 183 } /* NAME_GET || DESC_GET */
+ − 184 if (ch == EOF)
+ − 185 break;
+ − 186 }
+ − 187
+ − 188 {
+ − 189 DOCSTR **array;
+ − 190 register int i; /* counter */
+ − 191
+ − 192 /* build array of ptrs to DOCSTRs */
+ − 193
+ − 194 array = (DOCSTR**)xmalloc (cnt * sizeof (*array));
+ − 195 for (dp = docs, i = 0; dp != NULL ; dp = dp->next)
+ − 196 array[i++] = dp;
+ − 197
+ − 198 /* sort the array by name; within each name, by type */
+ − 199
+ − 200 qsort ((char*)array, cnt, sizeof (DOCSTR*),
442
+ − 201 (int (*)(const void *, const void *)) cmpdoc);
428
+ − 202
+ − 203 /* write the output header */
+ − 204
+ − 205 printf ("\\input texinfo @c -*-texinfo-*-\n");
+ − 206 printf ("@setfilename ../info/summary\n");
613
+ − 207 printf ("@settitle Command Summary for XEmacs\n");
+ − 208 printf ("@unnumbered Command Summary for XEmacs\n");
428
+ − 209 printf ("@table @asis\n");
+ − 210 printf ("\n");
+ − 211 printf ("@iftex\n");
+ − 212 printf ("@global@let@ITEM=@item\n");
+ − 213 printf ("@def@item{@filbreak@vskip5pt@ITEM}\n");
+ − 214 printf ("@font@tensy cmsy10 scaled @magstephalf\n");
+ − 215 printf ("@font@teni cmmi10 scaled @magstephalf\n");
+ − 216 printf ("@def\\{{@tensy@char110}}\n"); /* this backslash goes with cmr10 */
+ − 217 printf ("@def|{{@tensy@char106}}\n");
+ − 218 printf ("@def@{{{@tensy@char102}}\n");
+ − 219 printf ("@def@}{{@tensy@char103}}\n");
+ − 220 printf ("@def<{{@teni@char62}}\n");
+ − 221 printf ("@def>{{@teni@char60}}\n");
+ − 222 printf ("@chardef@@64\n");
+ − 223 printf ("@catcode43=12\n");
+ − 224 printf ("@tableindent-0.2in\n");
+ − 225 printf ("@end iftex\n");
+ − 226
+ − 227 /* print each function from the array */
+ − 228
+ − 229 for (i = 0; i < cnt; i++)
+ − 230 {
+ − 231 printf ("\n@item %s @code{%s}\n@display\n",
+ − 232 array[i]->type == 'F' ? "Function" : "Variable",
+ − 233 array[i]->name);
+ − 234
+ − 235 for (lp = array[i]->first; lp != NULL ; lp = lp->next)
+ − 236 {
+ − 237 for (bp = lp->line; *bp; bp++)
+ − 238 {
+ − 239 /* the characters "@{}" need special treatment */
+ − 240 if (*bp == '@' || *bp == '{' || *bp == '}')
+ − 241 {
+ − 242 putchar('@');
+ − 243 }
+ − 244 putchar(*bp);
+ − 245 }
+ − 246 putchar ('\n');
+ − 247 }
+ − 248 printf("@end display\n");
+ − 249 if ( i%200 == 0 && i != 0 ) printf("@end table\n\n@table @asis\n");
+ − 250 }
+ − 251
+ − 252 printf ("@end table\n");
+ − 253 printf ("@bye\n");
+ − 254 }
+ − 255
+ − 256 return 0;
+ − 257 }