This commit was manufactured by cvs2svn to create tag
[kbuild-mirror.git] / doc / docdesign.c
blob4d92124c4fd33a6ddd049b8b7363ce6d3c356282
1 /* $Id$
3 * Documentation generator.
5 * Copyright (c) 2002 knut st. osmundsen <bird@anduin.net>
8 * This file is part of kBuild.
10 * kBuild is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published
12 * by the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * kBuild is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with kBuild; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 /*******************************************************************************
28 * Header Files *
29 *******************************************************************************/
30 #include <string.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <errno.h>
36 /*******************************************************************************
37 * Structures and Typedefs *
38 *******************************************************************************/
39 typedef struct _Section
41 struct _Section *pNext; /* Next Section. */
42 int iLevel; /* 0 is @design, 1 is @subsection and so on. */
43 char *pszHeader;
44 char *pszText; /* Content of the section. */
45 int cchText;
46 } SECTION, *PSECTION;
49 /*******************************************************************************
50 * Global Variables *
51 *******************************************************************************/
52 PSECTION pSections = NULL;
53 PSECTION pSectionsTail = NULL;
56 /**
57 * Reads the file parsing out the @design and @sub[..]section
58 * parts putting them into the pSections list.
60 int ParseFile(const char *pszFilename)
62 int rc = 0;
63 FILE * phFile;
66 * Open the file.
68 phFile = fopen(pszFilename, "r");
69 if (phFile)
71 static char szLine[0x10000];
72 enum {enmUnknown, enmSection, enmSectionClosing}
73 enmState = enmUnknown;
74 PSECTION pCurSection = NULL;
77 * Read the file line by line. looking for @design and @sub[..]section.
79 while (fgets(szLine, sizeof(szLine), phFile))
81 int fNew = 0;
82 int iLevel = 0;
83 char *psz = szLine;
84 char *pszEnd = &szLine[strlen(szLine) - 1];
86 * Strip off any ' ', '\t', '\n', '\r', '\*\/' and '*' from end
87 * Strip off any ' ', '\t', '\/\*', '*' and '//' from start.
88 * Need to check for closing comment too.
90 while ( pszEnd >= psz
91 && ( *pszEnd == '*'
92 || *pszEnd == ' '
93 || *pszEnd == '\t'
94 || *pszEnd == '\r'
95 || *pszEnd == '\n'
99 *pszEnd-- = '\0';
101 if (pszEnd > psz && !strcmp(&pszEnd[-1], "*/") && enmState == enmSection)
102 enmState = enmSectionClosing;
103 while ( pszEnd >= psz
104 && ( *pszEnd == '*'
105 || *pszEnd == ' '
106 || *pszEnd == '\t'
107 || *pszEnd == '\n'
108 || *pszEnd == '\r'
109 || (*pszEnd == '/' && pszEnd > psz && pszEnd[-1] == '*')
113 if (*pszEnd == '/')
114 *pszEnd-- = '\0';
115 *pszEnd-- = '\0';
118 while ( *psz == '*'
119 || *psz == ' '
120 || *psz == '\t'
121 || (*psz == '/' && (psz[1] == '*' || psz[1] == '/')))
123 if (*psz++ == '/')
124 psz++;
129 * Look for tag.
131 if (!strncmp(psz, "@design", 7))
133 fNew = 1;
134 iLevel = 0;
136 else if (!strncmp(psz, "@sub", 4))
138 char *psz2 = psz + 4;
139 fNew = 1;
140 iLevel = 1;
141 while (!strncmp(psz2, "sub", 3))
143 psz2 += 3;
144 iLevel++;
149 * Action
151 if (fNew)
153 char *psz2;
155 * New Section.
156 * Change state.
157 * Allocate new section struct, init it and link it into the list.
158 * Get section header.
160 if (enmState != enmSectionClosing)
161 enmState = enmSection;
163 pCurSection = malloc(sizeof(*pCurSection));
164 memset(pCurSection, 0, sizeof(*pCurSection));
165 pCurSection->iLevel = iLevel;
166 if (pSectionsTail)
167 pSectionsTail = pSectionsTail->pNext = pCurSection;
168 else
169 pSections = pSectionsTail = pCurSection;
171 psz2 = strpbrk(psz, " \t");
172 if (psz2)
174 while (*psz2 == ' ' || *psz == '\t')
175 psz2++;
176 if (*psz)
177 pCurSection->pszHeader = strdup(psz2);
180 else if (enmState == enmSection || enmState == enmSectionClosing)
183 * Add text to current section
185 int cch = strlen(psz);
186 if (!cch && pCurSection->cchText)
188 psz = "<p>";
189 cch = strlen(psz);
192 if (cch)
194 pCurSection->pszText = realloc(pCurSection->pszText, pCurSection->cchText + cch + 2);
195 pCurSection->pszText[pCurSection->cchText++] = '\n';
196 strcpy(&pCurSection->pszText[pCurSection->cchText], psz);
197 pCurSection->cchText += cch;
202 * State transition.
204 if (enmState == enmSectionClosing)
205 enmState = enmUnknown;
207 } /* while fgets */
209 fclose(phFile);
211 else
213 fprintf(stderr, "error: failed to open %s. errno=%d\n", pszFilename, errno);
214 rc = errno;
217 return rc;
222 * Checks if psz is point to a tag we pass thru.
223 * @returns length of tag if pass thru tag.
224 * @returns 0 if not.
225 * @param psz Pointer to text string.
227 int isTag(const char *psz)
229 int i;
230 static char * apszTags[] =
232 "<b>", "</b>",
233 "<i>", "</i>",
234 "<ul>", "</ul>",
235 "<ol>", "</ol>",
236 "<pre>", "</pre>",
237 "<h1>", "</h1>",
238 "<h2>", "</h2>",
239 "<h3>", "</h3>",
240 "<h4>", "</h4>",
241 "<h5>", "</h5>",
242 "<h6>", "</h6>",
243 "<li>",
244 "<p>",
245 "<br>"
248 if (*psz == '<')
250 for (i = 0; i < sizeof(apszTags) / sizeof(apszTags[0]); i++)
252 int cch = strlen(apszTags[i]);
253 if (!strnicmp(apszTags[i], psz, cch))
254 return cch;
258 return 0;
263 * HTMLify text and print it.
264 * @param pszText Text in question.
266 void PutHtmlText(const char *pszText)
268 while (*pszText)
270 char ch = *pszText;
271 char sz[256];
272 sz[0] = '\0';
273 switch (ch)
275 case '<':
277 int cch = isTag(pszText);
278 if (cch)
280 strncat(sz, pszText, cch);
281 pszText += cch - 1;
283 else
284 strcpy(sz, "&lt;");
285 break;
288 case '>':
289 strcpy(sz, "&gt;");
290 break;
292 case '&':
293 strcpy(sz, "&amp;");
294 break;
296 default:
297 sz[0] = ch;
298 sz[1] = '\0';
300 printf("%s", sz);
301 pszText++;
307 * Keep track and formats section level.
309 void SectionNumber(int iLevel, int *paiSections, char *pszSection)
311 int i;
313 paiSections[iLevel]++;
314 for (i = iLevel + 1; i < 100; i++)
315 paiSections[i] = 0;
317 sprintf(pszSection, "%d", paiSections[0]);
318 if (iLevel == 0)
319 strcat(pszSection, ".0");
320 else
322 for (i = 1; i <= iLevel; i++)
323 sprintf(&pszSection[strlen(pszSection)], ".%d", paiSections[i]);
329 * Outputs the section stuff to stdout as HTML.
331 int MakeHTML(void)
333 int aiSections[100];
334 char szSection[1024];
335 PSECTION pCurSection;
337 #if 0
338 /* debug */
339 for (pCurSection = pSections; pCurSection; pCurSection = pCurSection->pNext)
340 fprintf(stderr, "debug: level=%d cchText=%-4d header=%s \n",
341 pCurSection->iLevel, pCurSection->cchText, pCurSection->pszHeader);
342 #endif
345 * Header
347 printf("<!-- Generate by docdesign -->\n"
348 "<head>\n"
349 "<title>Design Document</title>\n"
350 "\n"
351 "<body>\n"
355 * Content
357 printf("<a name=content><h2>Content</h2></a>\n"
358 "<ul>\n"
360 memset(&aiSections[0], 0, sizeof(aiSections));
361 for (pCurSection = pSections; pCurSection; pCurSection = pCurSection->pNext)
363 SectionNumber(pCurSection->iLevel, &aiSections[0], szSection);
364 printf(" <li><a href=\"#%s\">%s %s</a>\n",
365 szSection, szSection, pCurSection->pszHeader);
367 printf("</ul>\n"
368 "\n");
371 * Sections.
373 memset(&aiSections[0], 0, sizeof(aiSections));
374 for (pCurSection = pSections; pCurSection; pCurSection = pCurSection->pNext)
376 int iHNumber = min(pCurSection->iLevel + 1, 5);
377 SectionNumber(pCurSection->iLevel, &aiSections[0], szSection);
378 printf("<p><br><p>\n"
379 "<a href=#content><a name=%s><h%d>%s %s</h%d></a></a>\n"
380 "\n",
381 szSection, iHNumber, szSection, pCurSection->pszHeader, iHNumber);
382 if (pCurSection->pszText)
383 PutHtmlText(pCurSection->pszText);
385 printf("</ul>\n"
386 "\n");
389 /* footer */
390 printf("</body>\n"
391 "</head>\n");
393 return -1;
397 int main(int argc, char **argv)
399 int rc;
400 int argi;
403 * Parse arguments.
405 for (argi = 1, rc = 0; !rc && argi < argc; argi++)
407 if (argv[argi][0] == '@')
409 FILE *phFile = fopen(&argv[argi][1], "r");
410 if (phFile)
412 char szFilename[1024];
413 while (!rc && fgets(szFilename, sizeof(szFilename), phFile))
415 char *psz = szFilename;
416 char *pszEnd = &psz[strlen(psz)] - 1;
417 while (*psz == '\t' || *psz == ' ') psz++;
418 while (pszEnd >= psz && (*pszEnd == '\t' || *pszEnd == ' ' || *pszEnd == '\n' || *pszEnd == '\r'))
419 *pszEnd-- = '\0';
420 rc = ParseFile(psz);
424 else
425 rc = ParseFile(argv[argi]);
428 if (!rc)
429 rc = MakeHTML();
431 return rc;