2 // Small program to 'explode' the master document automagically into separate
3 // files in the include/ directory.
6 // (C) 2017 Underground Software
9 // still need a fix for titles with the same name...
14 #include <sys/stat.h> // For mkdir()
15 #include <sys/types.h>
18 // Global variable (OMG YOU EVIL BASTARD!!)
19 char buffer[1024000], keyword[1024], token[1024];
20 char title[1024], shortTitle[1024], inclFile[1024], style[1024];
21 int level = 0, lastLevel = -1;
22 int lineCount = 0, startLine, sectionLineCount, fileCount = 0;
23 int part = 0, chapter = 0, subchapter = 0;
26 FILE * newFile = NULL, * master = NULL, * exp = NULL;
27 char level1File[1024], level2File[1024], level3File[1024], temp[1024];
28 char partFN[1024], chapterFN[1024], scLink[4096];
31 void MakeFilename(char * fn)
35 for(int i=0; i<l; i++)
39 else if (fn[i] >= 'A' && fn[i] <= 'Z')
41 else if (fn[i] >= 'a' && fn[i] <= 'z')
43 else if (fn[i] >= '0' && fn[i] <= '9')
51 bool ParseHeader(FILE * file)
55 // If we hit the EOF before finishing, something went horribly wrong
59 fgets(buffer, 1023999, file);
62 // If we're seeing the end of header sentinel, return; we're done.
63 if (strncmp(buffer, "---", 3) == 0)
66 sscanf(buffer, "%[^:]: %[^\n]", keyword, token);
68 if (strcmp(keyword, "title") == 0)
72 else if (strcmp(keyword, "part") == 0)
75 int len = strlen(token);
80 level = 1, chapter++, subchapter = 0;
82 level = 2, subchapter++;
84 level = -1; // Something went wrong
86 else if (strcmp(keyword, "include") == 0)
88 strcpy(inclFile, token);
90 else if (strcmp(keyword, "menu_title") == 0)
92 strcpy(shortTitle, token);
94 else if (strcmp(keyword, "style") == 0)
98 else if (strcmp(keyword, "exclude") == 0)
100 // Don't care about the token, just the keyword
104 printf("Unknown keyword '%s' (token: %s)\n", keyword, token);
107 // If we end up here, something went horribly wrong...
113 // Restore the master document back to its pre-run state
115 void HandleFailure(void)
117 // Close open files...
124 // Remove our work, and restore the backup of the master document
125 remove("master-doc.txt");
126 rename("master-doc.bak", "master-doc.txt");
130 int main(int argc, char * argv[])
132 // First, check to see if this has been run here already.
133 FILE * fp = fopen("master-doc.txt", "r");
134 fgets(buffer, 1023999, fp);
137 if (strncmp(buffer, "<!-- exploded -->", 17) == 0)
139 printf("Master file has already been exploded.\n");
143 // First, rename the master document
144 rename("master-doc.txt", "master-doc.bak");
146 // Then open the .bak file
147 master = fopen("master-doc.bak", "r");
151 printf("Could not open master doc (master-doc.txt) file!\n");
155 // Create new master document
156 exp = fopen("master-doc.txt", "w");
160 printf("Could not open 'master-doc.txt' file!\n");
165 fprintf(exp, "<!-- exploded -->\n");
167 while (!feof(master))
169 fgets(buffer, 1023999, master);
172 // Look for start of file marker
173 if (strncmp(buffer, "---", 3) == 0)
175 // Reset the "short" title, include file & sytle
182 if (!ParseHeader(master))
184 printf("Something went horribly wrong with the header parsing! Aborting!\n");
189 if (strlen(title) == 0)
191 printf("Header is missing a 'title:' section, aborting!\n");
196 // Close any previously opened files...
203 // We finished parsing our keyword block, now do something about
206 // temp, for explode only:
207 if (strlen(inclFile) > 0)
212 // Parts don't have any content...
214 // Set up the "part" level of TOC link
215 sprintf(partFN, "%s", temp);
217 // Set up content for the exploded part level
218 fprintf(exp, "\n---\n");
219 fprintf(exp, "title: %s\n", title);
221 if (strlen(shortTitle) > 0)
222 fprintf(exp, "menu_title: %s\n", shortTitle);
224 fprintf(exp, "part: part\n");
225 fprintf(exp, "---\n\n\n");
229 // Make a filename from the title (not short title!)
230 strcpy(chapterFN, title);
231 MakeFilename(chapterFN);
233 // Set up content for the exploded chapter level
234 fprintf(exp, "---\n");
235 fprintf(exp, "title: %s\n", title);
237 if (strlen(shortTitle) > 0)
238 fprintf(exp, "menu_title: %s\n", shortTitle);
240 if (strlen(inclFile) > 0)
241 fprintf(exp, "include: %s\n", inclFile);
243 fprintf(exp, "include: %s.html\n", chapterFN);
245 // If it was already an include file, mark it to stay in include/
247 fprintf(exp, "exclude: yes\n");
249 fprintf(exp, "part: chapter\n");
250 fprintf(exp, "---\n\n");
252 // Make the file expected at this level (but only if not
257 sprintf(temp, "include/%s.html", chapterFN);
258 newFile = fopen(temp, "w");
259 fprintf(newFile, "---\n");
260 fprintf(newFile, "title: %s\n", title);
262 if (strlen(shortTitle) > 0)
263 fprintf(newFile, "menu_title: %s\n", shortTitle);
265 fprintf(newFile, "---\n");
270 strcpy(scLink, title);
271 MakeFilename(scLink);
273 // Set up content for the exploded subchapter level
274 fprintf(exp, "---\n");
275 fprintf(exp, "title: %s\n", title);
277 if (strlen(shortTitle) > 0)
278 fprintf(exp, "menu_title: %s\n", shortTitle);
280 if (strlen(inclFile) > 0)
281 fprintf(exp, "include: %s\n", inclFile);
283 fprintf(exp, "include: %s.html\n", scLink);
285 // If it was already an include file, mark it to stay in include/
287 fprintf(exp, "exclude: yes\n");
289 fprintf(exp, "part: subchapter\n");
290 fprintf(exp, "---\n\n");
295 sprintf(temp, "include/%s.html", scLink);
296 newFile = fopen(temp, "w");
297 fprintf(newFile, "---\n");
298 fprintf(newFile, "title: %s\n", title);
300 if (strlen(shortTitle) > 0)
301 fprintf(newFile, "menu_title: %s\n", shortTitle);
303 if (strlen(style) > 0)
304 fprintf(newFile, "style: %s\n", style);
306 fprintf(newFile, "---\n");
312 if (((level == 1) || (level == 2)) && (newFile != NULL))
313 fprintf(newFile, "%s", buffer);
316 // Kill the buffer to prevent false positives...
320 printf("\nProcessed %i lines.\n", lineCount);
321 printf("Exploded master document into %i files.\n", fileCount);
329 // Finally, remove the .bak file:
330 remove("master-doc.bak");