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 /*******************************************************************************
29 *******************************************************************************/
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. */
44 char *pszText
; /* Content of the section. */
49 /*******************************************************************************
51 *******************************************************************************/
52 PSECTION pSections
= NULL
;
53 PSECTION pSectionsTail
= NULL
;
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
)
68 phFile
= fopen(pszFilename
, "r");
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
))
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.
101 if (pszEnd
> psz
&& !strcmp(&pszEnd
[-1], "*/") && enmState
== enmSection
)
102 enmState
= enmSectionClosing
;
103 while ( pszEnd
>= psz
109 || (*pszEnd
== '/' && pszEnd
> psz
&& pszEnd
[-1] == '*')
121 || (*psz
== '/' && (psz
[1] == '*' || psz
[1] == '/')))
131 if (!strncmp(psz
, "@design", 7))
136 else if (!strncmp(psz
, "@sub", 4))
138 char *psz2
= psz
+ 4;
141 while (!strncmp(psz2
, "sub", 3))
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
;
167 pSectionsTail
= pSectionsTail
->pNext
= pCurSection
;
169 pSections
= pSectionsTail
= pCurSection
;
171 psz2
= strpbrk(psz
, " \t");
174 while (*psz2
== ' ' || *psz
== '\t')
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
)
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
;
204 if (enmState
== enmSectionClosing
)
205 enmState
= enmUnknown
;
213 fprintf(stderr
, "error: failed to open %s. errno=%d\n", pszFilename
, errno
);
222 * Checks if psz is point to a tag we pass thru.
223 * @returns length of tag if pass thru tag.
225 * @param psz Pointer to text string.
227 int isTag(const char *psz
)
230 static char * apszTags
[] =
250 for (i
= 0; i
< sizeof(apszTags
) / sizeof(apszTags
[0]); i
++)
252 int cch
= strlen(apszTags
[i
]);
253 if (!strnicmp(apszTags
[i
], psz
, cch
))
263 * HTMLify text and print it.
264 * @param pszText Text in question.
266 void PutHtmlText(const char *pszText
)
277 int cch
= isTag(pszText
);
280 strncat(sz
, pszText
, cch
);
307 * Keep track and formats section level.
309 void SectionNumber(int iLevel
, int *paiSections
, char *pszSection
)
313 paiSections
[iLevel
]++;
314 for (i
= iLevel
+ 1; i
< 100; i
++)
317 sprintf(pszSection
, "%d", paiSections
[0]);
319 strcat(pszSection
, ".0");
322 for (i
= 1; i
<= iLevel
; i
++)
323 sprintf(&pszSection
[strlen(pszSection
)], ".%d", paiSections
[i
]);
329 * Outputs the section stuff to stdout as HTML.
334 char szSection
[1024];
335 PSECTION pCurSection
;
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
);
347 printf("<!-- Generate by docdesign -->\n"
349 "<title>Design Document</title>\n"
357 printf("<a name=content><h2>Content</h2></a>\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
);
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"
381 szSection
, iHNumber
, szSection
, pCurSection
->pszHeader
, iHNumber
);
382 if (pCurSection
->pszText
)
383 PutHtmlText(pCurSection
->pszText
);
397 int main(int argc
, char **argv
)
405 for (argi
= 1, rc
= 0; !rc
&& argi
< argc
; argi
++)
407 if (argv
[argi
][0] == '@')
409 FILE *phFile
= fopen(&argv
[argi
][1], "r");
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'))
425 rc
= ParseFile(argv
[argi
]);