|
|
1.1 ! root 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: #include <stdio.h> ! 9: #include <ctype.h> ! 10: ! 11: extern char *malloc (); ! 12: char *xmalloc (); ! 13: ! 14: #define NUL '\0' ! 15: #define MARKER '\037' ! 16: ! 17: #define DEBUG 0 ! 18: ! 19: typedef struct line LINE; ! 20: ! 21: struct line ! 22: { ! 23: LINE *next; /* ptr to next or NULL */ ! 24: char *line; /* text of the line */ ! 25: }; ! 26: ! 27: typedef struct docstr DOCSTR; ! 28: ! 29: struct docstr /* Allocated thing for an entry. */ ! 30: { ! 31: DOCSTR *next; /* next in the chain */ ! 32: char *name; /* name of the function or var */ ! 33: LINE *first; /* first line of doc text. */ ! 34: char type; /* 'F' for function, 'V' for variable */ ! 35: }; ! 36: ! 37: ! 38: /* Print error message and exit. */ ! 39: ! 40: fatal (s1, s2) ! 41: char *s1, *s2; ! 42: { ! 43: error (s1, s2); ! 44: exit (1); ! 45: } ! 46: ! 47: /* Print error message. `s1' is printf control string, `s2' is arg for it. */ ! 48: ! 49: error (s1, s2) ! 50: char *s1, *s2; ! 51: { ! 52: fprintf (stderr, "sorted-doc: "); ! 53: fprintf (stderr, s1, s2); ! 54: fprintf (stderr, "\n"); ! 55: } ! 56: ! 57: /* Like malloc but get fatal error if memory is exhausted. */ ! 58: ! 59: char * ! 60: xmalloc (size) ! 61: int size; ! 62: { ! 63: char *result = malloc ((unsigned)size); ! 64: if (result == NULL) ! 65: fatal ("%s", "virtual memory exhausted"); ! 66: return result; ! 67: } ! 68: ! 69: char * ! 70: strsav (str) ! 71: char * str; ! 72: { ! 73: char *buf = xmalloc (strlen (str) + 1); ! 74: (void) strcpy (buf, str); ! 75: return (buf); ! 76: } ! 77: ! 78: /* Comparison function for qsort to call. */ ! 79: ! 80: int ! 81: cmpdoc (a, b) ! 82: DOCSTR **a; ! 83: 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: ! 96: char *states[] = ! 97: { ! 98: "WAITING", "BEG_NAME", "NAME_GET", "BEG_DESC", "DESC_GET" ! 99: }; ! 100: ! 101: main () ! 102: { ! 103: register DOCSTR *dp = NULL; /* allocated DOCSTR */ ! 104: register LINE *lp = NULL; /* allocated line */ ! 105: register char *bp; /* ptr inside line buffer */ ! 106: int notfirst = 0; /* set after read something */ ! 107: register enum state state = WAITING; /* state at start */ ! 108: int cnt = 0; /* number of DOCSTRs read */ ! 109: ! 110: DOCSTR *docs; /* chain of allocated DOCSTRS */ ! 111: char buf[512]; /* line buffer */ ! 112: ! 113: while (1) /* process one char at a time */ ! 114: { ! 115: /* this char from the DOCSTR file */ ! 116: register int ch = getchar (); ! 117: ! 118: /* Beginnings */ ! 119: ! 120: if (state == WAITING) ! 121: { ! 122: if (ch == MARKER) ! 123: state = BEG_NAME; ! 124: } ! 125: else if (state == BEG_NAME) ! 126: { ! 127: cnt++; ! 128: if (dp == NULL) /* first dp allocated */ ! 129: { ! 130: docs = dp = (DOCSTR*) xmalloc (sizeof (DOCSTR)); ! 131: } ! 132: else /* all the rest */ ! 133: { ! 134: dp->next = (DOCSTR*) xmalloc (sizeof (DOCSTR)); ! 135: dp = dp->next; ! 136: } ! 137: lp = NULL; ! 138: dp->next = NULL; ! 139: bp = buf; ! 140: state = NAME_GET; ! 141: /* Record whether function or variable. */ ! 142: dp->type = ch; ! 143: ch = getchar (); ! 144: } ! 145: else if (state == BEG_DESC) ! 146: { ! 147: if (lp == NULL) /* first line for dp */ ! 148: { ! 149: dp->first = lp = (LINE*)xmalloc (sizeof (LINE)); ! 150: } ! 151: else /* continuing lines */ ! 152: { ! 153: lp->next = (LINE*)xmalloc (sizeof (LINE)); ! 154: lp = lp->next; ! 155: } ! 156: lp->next = NULL; ! 157: bp = buf; ! 158: state = DESC_GET; ! 159: } ! 160: ! 161: /* process gets */ ! 162: ! 163: if (state == NAME_GET || state == DESC_GET) ! 164: { ! 165: if (ch != MARKER && ch != '\n' && ch != EOF) ! 166: { ! 167: *bp++ = ch; ! 168: } ! 169: else /* saving and changing state */ ! 170: { ! 171: *bp = NUL; ! 172: bp = strsav (buf); ! 173: ! 174: if (state == NAME_GET) ! 175: dp->name = bp; ! 176: else ! 177: lp->line = bp; ! 178: ! 179: bp = buf; ! 180: state = (ch == MARKER) ? BEG_NAME : BEG_DESC; ! 181: } ! 182: } /* NAME_GET || DESC_GET */ ! 183: if (ch == EOF) ! 184: break; ! 185: } ! 186: ! 187: { ! 188: DOCSTR **array; ! 189: register int i; /* counter */ ! 190: ! 191: /* build array of ptrs to DOCSTRs */ ! 192: ! 193: array = (DOCSTR**)xmalloc (cnt * sizeof (*array)); ! 194: for (dp = docs, i = 0; dp != NULL ; dp = dp->next) ! 195: array[i++] = dp; ! 196: ! 197: /* sort the array by name; within each name, by type */ ! 198: ! 199: qsort ((char*)array, cnt, sizeof (DOCSTR*), cmpdoc); ! 200: ! 201: /* write the output header */ ! 202: ! 203: printf ("\\input texinfo @c -*-texinfo-*-\n"); ! 204: printf ("@setfilename ../info/summary\n"); ! 205: printf ("@settitle Command Summary for GNU Emacs\n"); ! 206: printf ("@unnumbered Command Summary for GNU Emacs\n"); ! 207: printf ("@table @asis\n"); ! 208: ! 209: /* print each function from the array */ ! 210: ! 211: for (i = 0; i < cnt; i++) ! 212: { ! 213: printf ("\n@item %s @code{%s}\n@display\n", ! 214: array[i]->type == 'F' ? "Function" : "Variable", ! 215: array[i]->name); ! 216: ! 217: for (lp = array[i]->first; lp != NULL ; lp = lp->next) ! 218: { ! 219: for (bp = lp->line; *bp; bp++) ! 220: { ! 221: /* the characters "@{}" need special treatment */ ! 222: if (*bp == '@' || *bp == '{' || *bp == '}') ! 223: { ! 224: putchar('@'); ! 225: } ! 226: putchar(*bp); ! 227: } ! 228: putchar ('\n'); ! 229: } ! 230: printf("@end display\n"); ! 231: } ! 232: ! 233: printf ("@end table\n"); ! 234: printf ("@bye\n"); ! 235: } ! 236: ! 237: return 0; ! 238: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.