2 // Small program to 'implode' the master document automagically from separate
3 // files in the include/ directory.
6 // (C) 2017 Underground Software
12 #include <sys/stat.h> // For mkdir()
13 #include <sys/types.h>
16 // Global variable (OMG YOU EVIL BASTARD!!)
17 char buffer[1024000], keyword[1024], token[1024];
18 char title[1024], shortTitle[1024], inclFile[1024], style[1024];
19 int level = 0, lastLevel = -1;
20 int lineCount = 0, startLine, sectionLineCount, fileCount = 0;
21 int part = 0, chapter = 0, subchapter = 0;
24 FILE * newFile = NULL;
25 char level1File[1024], level2File[1024], level3File[1024], temp[1024];
26 char partFN[1024], chapterFN[1024], scLink[4096];
29 void MakeFilename(char * fn)
33 for(int i=0; i<l; i++)
37 else if (fn[i] >= 'A' && fn[i] <= 'Z')
39 else if (fn[i] >= 'a' && fn[i] <= 'z')
41 else if (fn[i] >= '0' && fn[i] <= '9')
49 long SkipHeader(FILE * file)
55 // If we hit the EOF before finishing, something went horribly wrong
59 fgets(buffer, 1023999, file);
60 length += strlen(buffer) + 1;
62 // If we're seeing the end of header sentinel, return; we're done.
63 if (strncmp(buffer, "---", 3) == 0)
69 // If we hit the EOF before finishing, something went horribly wrong
73 fgets(buffer, 1023999, file);
74 length += strlen(buffer) + 1;
76 // If we're seeing the end of header sentinel, return; we're done.
77 if (strncmp(buffer, "---", 3) == 0)
85 void CopyFileToStream(char * from, FILE * toFile)
87 FILE * fromFile = fopen(from, "r");
91 printf("\n\nCould not open file '%s' for reading! Aborting!!\n", from);
95 fseek(fromFile, 0, SEEK_END);
96 long length = ftell(fromFile);
99 long skipped = ftell(fromFile);
101 for(long i=skipped; i<length; i++)
102 fputc(fgetc(fromFile), toFile);
108 bool ParseHeader(FILE * file)
112 // If we hit the EOF before finishing, something went horribly wrong
116 fgets(buffer, 1023999, file);
119 // If we're seeing the end of header sentinel, return; we're done.
120 if (strncmp(buffer, "---", 3) == 0)
123 sscanf(buffer, "%[^:]: %[^\n]", keyword, token);
125 if (strcmp(keyword, "title") == 0)
127 strcpy(title, token);
129 else if (strcmp(keyword, "part") == 0)
132 int len = strlen(token);
137 level = 1, chapter++, subchapter = 0;
139 level = 2, subchapter++;
141 level = -1; // Something went wrong
143 else if (strcmp(keyword, "include") == 0)
145 strcpy(inclFile, token);
147 else if (strcmp(keyword, "menu_title") == 0)
149 strcpy(shortTitle, token);
151 else if (strcmp(keyword, "style") == 0)
153 strcpy(style, token);
155 else if (strcmp(keyword, "exclude") == 0)
157 // Don't care about the token, just the keyword
161 printf("Unknown keyword '%s' (token: %s)\n", keyword, token);
164 // If we end up here, something went horribly wrong...
169 int main(int argc, char * argv[])
171 // First, check to see if this has been run here already.
172 FILE * fp = fopen("master-doc.txt", "r");
173 fgets(buffer, 1023999, fp);
176 if (strncmp(buffer, "<!-- imploded -->", 17) == 0)
178 printf("Master file has already been imploded.\n");
182 // First, rename the master document
183 rename("master-doc.txt", "master-doc.bak");
185 // Then open the .bak file
186 FILE * master = fopen("master-doc.bak", "r");
190 printf("Could not open master doc (master-doc.txt) file!\n");
194 // Create new master document
195 FILE * exp = fopen("master-doc.txt", "w");
199 printf("Could not open 'master-doc.txt' file!\n");
204 fprintf(exp, "<!-- imploded -->\n");
206 while (!feof(master))
208 fgets(buffer, 1023999, master);
211 // Look for start of file marker
212 if (strncmp(buffer, "---", 3) == 0)
214 // Reset the "short" title, include file & style
220 if (!ParseHeader(master))
222 printf("Something went horribly wrong with the header parsing! Aborting!\n");
226 // Close any previously opened files...
233 // We finished parsing our keyword block, now do something about
237 // Parts don't have any content...
239 // Set up the "part" level of TOC link
240 sprintf(partFN, "%s", temp);
242 // Set up content for the imploded part level
243 fprintf(exp, "\n---\n");
244 fprintf(exp, "title: %s\n", title);
246 if (strlen(shortTitle) > 0)
247 fprintf(exp, "menu_title: %s\n", shortTitle);
249 fprintf(exp, "part: part\n");
250 fprintf(exp, "---\n\n\n");
254 // Make a filename from the title (not short title!)
255 strcpy(chapterFN, title);
256 MakeFilename(chapterFN);
258 // Set up content for the imploded chapter level
259 fprintf(exp, "---\n");
260 fprintf(exp, "title: %s\n", title);
262 if (strlen(shortTitle) > 0)
263 fprintf(exp, "menu_title: %s\n", shortTitle);
265 // If it was already an include file, mark it to stay in include/
268 fprintf(exp, "include: %s\n", inclFile);
269 fprintf(exp, "exclude: yes\n");
272 fprintf(exp, "part: chapter\n");
273 fprintf(exp, "---\n");
275 // Make the file expected at this level (but only if not
280 sprintf(temp, "include/%s.html", chapterFN);
281 CopyFileToStream(temp, exp);
289 strcpy(scLink, title);
290 MakeFilename(scLink);
292 // Set up content for the exploded subchapter level
293 fprintf(exp, "---\n");
294 fprintf(exp, "title: %s\n", title);
296 if (strlen(shortTitle) > 0)
297 fprintf(exp, "menu_title: %s\n", shortTitle);
299 // If it was already an include file, mark it to stay in include/
302 fprintf(exp, "include: %s\n", inclFile);
303 fprintf(exp, "exclude: yes\n");
306 fprintf(exp, "part: subchapter\n");
307 fprintf(exp, "---\n");
312 sprintf(temp, "include/%s.html", scLink);
313 CopyFileToStream(temp, exp);
321 // Kill the buffer to prevent false positives...
325 printf("\nProcessed %i lines.\n", lineCount);
326 printf("Imploded master document from %i files.\n", fileCount);
334 // Finally, remove the .bak file:
335 remove("master-doc.bak");