VirtualBox

source: kBuild/trunk/doc/docdesign.c@ 287

Last change on this file since 287 was 16, checked in by bird, 22 years ago

More fun.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.8 KB
Line 
1/* $Id: docdesign.c 16 2002-10-16 23:21:04Z bird $
2 *
3 * Documentation generator.
4 *
5 * Copyright (c) 2002 knut st. osmundsen <[email protected]>
6 *
7 *
8 * This file is part of kBuild.
9 *
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.
14 *
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.
19 *
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
23 *
24 */
25
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#include <string.h>
31#include <stdlib.h>
32#include <stdio.h>
33#include <errno.h>
34
35
36/*******************************************************************************
37* Structures and Typedefs *
38*******************************************************************************/
39typedef struct _Section
40{
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;
47
48
49/*******************************************************************************
50* Global Variables *
51*******************************************************************************/
52PSECTION pSections = NULL;
53PSECTION pSectionsTail = NULL;
54
55
56/**
57 * Reads the file parsing out the @design and @sub[..]section
58 * parts putting them into the pSections list.
59 */
60int ParseFile(const char *pszFilename)
61{
62 int rc = 0;
63 FILE * phFile;
64
65 /*
66 * Open the file.
67 */
68 phFile = fopen(pszFilename, "r");
69 if (phFile)
70 {
71 static char szLine[0x10000];
72 enum {enmUnknown, enmSection, enmSectionClosing}
73 enmState = enmUnknown;
74 PSECTION pCurSection = NULL;
75
76 /*
77 * Read the file line by line. looking for @design and @sub[..]section.
78 */
79 while (fgets(szLine, sizeof(szLine), phFile))
80 {
81 int fNew = 0;
82 int iLevel = 0;
83 char *psz = szLine;
84 char *pszEnd = &szLine[strlen(szLine) - 1];
85 /*
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.
89 */
90 while ( pszEnd >= psz
91 && ( *pszEnd == '*'
92 || *pszEnd == ' '
93 || *pszEnd == '\t'
94 || *pszEnd == '\r'
95 || *pszEnd == '\n'
96 )
97 )
98 {
99 *pszEnd-- = '\0';
100 }
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] == '*')
110 )
111 )
112 {
113 if (*pszEnd == '/')
114 *pszEnd-- = '\0';
115 *pszEnd-- = '\0';
116 }
117
118 while ( *psz == '*'
119 || *psz == ' '
120 || *psz == '\t'
121 || (*psz == '/' && (psz[1] == '*' || psz[1] == '/')))
122 {
123 if (*psz++ == '/')
124 psz++;
125 }
126
127
128 /*
129 * Look for tag.
130 */
131 if (!strncmp(psz, "@design", 7))
132 {
133 fNew = 1;
134 iLevel = 0;
135 }
136 else if (!strncmp(psz, "@sub", 4))
137 {
138 char *psz2 = psz + 4;
139 fNew = 1;
140 iLevel = 1;
141 while (!strncmp(psz2, "sub", 3))
142 {
143 psz2 += 3;
144 iLevel++;
145 }
146 }
147
148 /*
149 * Action
150 */
151 if (fNew)
152 {
153 char *psz2;
154 /*
155 * New Section.
156 * Change state.
157 * Allocate new section struct, init it and link it into the list.
158 * Get section header.
159 */
160 if (enmState != enmSectionClosing)
161 enmState = enmSection;
162
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;
170
171 psz2 = strpbrk(psz, " \t");
172 if (psz2)
173 {
174 while (*psz2 == ' ' || *psz == '\t')
175 psz2++;
176 if (*psz)
177 pCurSection->pszHeader = strdup(psz2);
178 }
179 }
180 else if (enmState == enmSection || enmState == enmSectionClosing)
181 {
182 /*
183 * Add text to current section
184 */
185 int cch = strlen(psz);
186 if (!cch && pCurSection->cchText)
187 {
188 psz = "<p>";
189 cch = strlen(psz);
190 }
191
192 if (cch)
193 {
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;
198 }
199 }
200
201 /*
202 * State transition.
203 */
204 if (enmState == enmSectionClosing)
205 enmState = enmUnknown;
206
207 } /* while fgets */
208
209 fclose(phFile);
210 }
211 else
212 {
213 fprintf(stderr, "error: failed to open %s. errno=%d\n", pszFilename, errno);
214 rc = errno;
215 }
216
217 return rc;
218}
219
220
221/**
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.
226 */
227int isTag(const char *psz)
228{
229 int i;
230 static char * apszTags[] =
231 {
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>"
246 };
247
248 if (*psz == '<')
249 {
250 for (i = 0; i < sizeof(apszTags) / sizeof(apszTags[0]); i++)
251 {
252 int cch = strlen(apszTags[i]);
253 if (!strnicmp(apszTags[i], psz, cch))
254 return cch;
255 }
256 }
257
258 return 0;
259}
260
261
262/**
263 * HTMLify text and print it.
264 * @param pszText Text in question.
265 */
266void PutHtmlText(const char *pszText)
267{
268 while (*pszText)
269 {
270 char ch = *pszText;
271 char sz[256];
272 sz[0] = '\0';
273 switch (ch)
274 {
275 case '<':
276 {
277 int cch = isTag(pszText);
278 if (cch)
279 {
280 strncat(sz, pszText, cch);
281 pszText += cch - 1;
282 }
283 else
284 strcpy(sz, "&lt;");
285 break;
286 }
287
288 case '>':
289 strcpy(sz, "&gt;");
290 break;
291
292 case '&':
293 strcpy(sz, "&amp;");
294 break;
295
296 default:
297 sz[0] = ch;
298 sz[1] = '\0';
299 }
300 printf("%s", sz);
301 pszText++;
302 }
303}
304
305
306/**
307 * Keep track and formats section level.
308 */
309void SectionNumber(int iLevel, int *paiSections, char *pszSection)
310{
311 int i;
312
313 paiSections[iLevel]++;
314 for (i = iLevel + 1; i < 100; i++)
315 paiSections[i] = 0;
316
317 sprintf(pszSection, "%d", paiSections[0]);
318 if (iLevel == 0)
319 strcat(pszSection, ".0");
320 else
321 {
322 for (i = 1; i <= iLevel; i++)
323 sprintf(&pszSection[strlen(pszSection)], ".%d", paiSections[i]);
324 }
325}
326
327
328/**
329 * Outputs the section stuff to stdout as HTML.
330 */
331int MakeHTML(void)
332{
333 int aiSections[100];
334 char szSection[1024];
335 PSECTION pCurSection;
336
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
343
344 /*
345 * Header
346 */
347 printf("<!-- Generate by docdesign -->\n"
348 "<head>\n"
349 "<title>Design Document</title>\n"
350 "\n"
351 "<body>\n"
352 );
353
354 /*
355 * Content
356 */
357 printf("<a name=content><h2>Content</h2></a>\n"
358 "<ul>\n"
359 );
360 memset(&aiSections[0], 0, sizeof(aiSections));
361 for (pCurSection = pSections; pCurSection; pCurSection = pCurSection->pNext)
362 {
363 SectionNumber(pCurSection->iLevel, &aiSections[0], szSection);
364 printf(" <li><a href=\"#%s\">%s %s</a>\n",
365 szSection, szSection, pCurSection->pszHeader);
366 }
367 printf("</ul>\n"
368 "\n");
369
370 /*
371 * Sections.
372 */
373 memset(&aiSections[0], 0, sizeof(aiSections));
374 for (pCurSection = pSections; pCurSection; pCurSection = pCurSection->pNext)
375 {
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);
384 }
385 printf("</ul>\n"
386 "\n");
387
388
389 /* footer */
390 printf("</body>\n"
391 "</head>\n");
392
393 return -1;
394}
395
396
397int main(int argc, char **argv)
398{
399 int rc;
400 int argi;
401
402 /*
403 * Parse arguments.
404 */
405 for (argi = 1, rc = 0; !rc && argi < argc; argi++)
406 {
407 if (argv[argi][0] == '@')
408 {
409 FILE *phFile = fopen(&argv[argi][1], "r");
410 if (phFile)
411 {
412 char szFilename[1024];
413 while (!rc && fgets(szFilename, sizeof(szFilename), phFile))
414 {
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);
421 }
422 }
423 }
424 else
425 rc = ParseFile(argv[argi]);
426 }
427
428 if (!rc)
429 rc = MakeHTML();
430
431 return rc;
432}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette