]> Shamusworld >> Repos - ardour-manual-diverged/blob - explode.cpp
Sync with master branch.
[ardour-manual-diverged] / explode.cpp
1 //
2 // Small program to 'explode' the master document automagically into separate
3 // files in the include/ directory.
4 //
5 // by James Hammons
6 // (C) 2017 Underground Software
7 //
8
9 // still need a fix for titles with the same name...
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/stat.h>           // For mkdir()
15 #include <sys/types.h>
16
17
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;
24 bool first = true;
25 bool nomove = false;
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];
29
30
31 void MakeFilename(char * fn)
32 {
33         int l = strlen(fn);
34
35         for(int i=0; i<l; i++)
36         {
37                 if (fn[i] == ' ')
38                         fn[i] = '-';
39                 else if (fn[i] >= 'A' && fn[i] <= 'Z')
40                         fn[i] |= 0x20;
41                 else if (fn[i] >= 'a' && fn[i] <= 'z')
42                         ;
43                 else if (fn[i] >= '0' && fn[i] <= '9')
44                         ;
45                 else
46                         fn[i] = '_';
47         }
48 }
49
50
51 bool ParseHeader(FILE * file)
52 {
53         while (true)
54         {
55                 // If we hit the EOF before finishing, something went horribly wrong
56                 if (feof(file))
57                         break;
58
59                 fgets(buffer, 1023999, file);
60                 lineCount++;
61
62                 // If we're seeing the end of header sentinel, return; we're done.
63                 if (strncmp(buffer, "---", 3) == 0)
64                         return true;
65
66                 sscanf(buffer, "%[^:]: %[^\n]", keyword, token);
67
68                 if (strcmp(keyword, "title") == 0)
69                 {
70                         strcpy(title, token);
71                 }
72                 else if (strcmp(keyword, "part") == 0)
73                 {
74                         lastLevel = level;
75                         int len = strlen(token);
76
77                         if (len == 4)
78                                 level = 0, part++;
79                         else if (len == 7)
80                                 level = 1, chapter++, subchapter = 0;
81                         else if (len == 10)
82                                 level = 2, subchapter++;
83                         else
84                                 level = -1;  // Something went wrong
85                 }
86                 else if (strcmp(keyword, "include") == 0)
87                 {
88                         strcpy(inclFile, token);
89                 }
90                 else if (strcmp(keyword, "menu_title") == 0)
91                 {
92                         strcpy(shortTitle, token);
93                 }
94                 else if (strcmp(keyword, "style") == 0)
95                 {
96                         strcpy(style, token);
97                 }
98                 else if (strcmp(keyword, "exclude") == 0)
99                 {
100                         // Don't care about the token, just the keyword
101                         nomove = true;
102                 }
103                 else
104                         printf("Unknown keyword '%s' (token: %s)\n", keyword, token);
105         }
106
107         // If we end up here, something went horribly wrong...
108         return false;
109 }
110
111
112 //
113 // Restore the master document back to its pre-run state
114 //
115 void HandleFailure(void)
116 {
117         // Close open files...
118         fclose(master);
119         fclose(exp);
120
121         if (newFile)
122                 fclose(newFile);
123
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");
127 }
128
129
130 int main(int argc, char * argv[])
131 {
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);
135         fclose(fp);
136
137         if (strncmp(buffer, "<!-- exploded -->", 17) == 0)
138         {
139                 printf("Master file has already been exploded.\n");
140                 return 0;
141         }
142
143         // First, rename the master document
144         rename("master-doc.txt", "master-doc.bak");
145
146         // Then open the .bak file
147         master = fopen("master-doc.bak", "r");
148
149         if (master == NULL)
150         {
151                 printf("Could not open master doc (master-doc.txt) file!\n");
152                 return -1;
153         }
154
155         // Create new master document
156         exp = fopen("master-doc.txt", "w");
157
158         if (exp == NULL)
159         {
160                 printf("Could not open 'master-doc.txt' file!\n");
161                 fclose(master);
162                 return -1;
163         }
164
165         fprintf(exp, "<!-- exploded -->\n");
166
167         while (!feof(master))
168         {
169                 fgets(buffer, 1023999, master);
170                 lineCount++;
171
172                 // Look for start of file marker
173                 if (strncmp(buffer, "---", 3) == 0)
174                 {
175                         // Reset the "short" title, include file & sytle
176                         title[0] = 0;
177                         shortTitle[0] = 0;
178                         inclFile[0] = 0;
179                         style[0] = 0;
180                         nomove = false;
181
182                         if (!ParseHeader(master))
183                         {
184                                 printf("Something went horribly wrong with the header parsing! Aborting!\n");
185                                 HandleFailure();
186                                 return -1;
187                         }
188
189                         if (strlen(title) == 0)
190                         {
191                                 printf("Header is missing a 'title:' section, aborting!\n");
192                                 HandleFailure();
193                                 return -1;
194                         }
195
196                         // Close any previously opened files...
197                         if (newFile != NULL)
198                         {
199                                 fclose(newFile);
200                                 newFile = NULL;
201                         }
202
203                         // We finished parsing our keyword block, now do something about
204                         // it... :-P
205
206                         // temp, for explode only:
207                         if (strlen(inclFile) > 0)
208                                 nomove = true;
209
210                         if (level == 0)
211                         {
212                                 // Parts don't have any content...
213
214                                 // Set up the "part" level of TOC link
215                                 sprintf(partFN, "%s", temp);
216
217                                 // Set up content for the exploded part level
218                                 fprintf(exp, "\n---\n");
219                                 fprintf(exp, "title: %s\n", title);
220
221                                 if (strlen(shortTitle) > 0)
222                                         fprintf(exp, "menu_title: %s\n", shortTitle);
223
224                                 fprintf(exp, "part: part\n");
225                                 fprintf(exp, "---\n\n\n");
226                         }
227                         else if (level == 1)
228                         {
229                                 // Make a filename from the title (not short title!)
230                                 strcpy(chapterFN, title);
231                                 MakeFilename(chapterFN);
232
233                                 // Set up content for the exploded chapter level
234                                 fprintf(exp, "---\n");
235                                 fprintf(exp, "title: %s\n", title);
236
237                                 if (strlen(shortTitle) > 0)
238                                         fprintf(exp, "menu_title: %s\n", shortTitle);
239
240                                 if (strlen(inclFile) > 0)
241                                         fprintf(exp, "include: %s\n", inclFile);
242                                 else
243                                         fprintf(exp, "include: %s.html\n", chapterFN);
244
245                                 // If it was already an include file, mark it to stay in include/
246                                 if (nomove)
247                                         fprintf(exp, "exclude: yes\n");
248
249                                 fprintf(exp, "part: chapter\n");
250                                 fprintf(exp, "---\n\n");
251
252                                 // Make the file expected at this level (but only if not
253                                 // included)...
254                                 if (nomove == false)
255                                 {
256                                         fileCount++;
257                                         sprintf(temp, "include/%s.html", chapterFN);
258                                         newFile = fopen(temp, "w");
259                                         fprintf(newFile, "---\n");
260                                         fprintf(newFile, "title: %s\n", title);
261
262                                         if (strlen(shortTitle) > 0)
263                                                 fprintf(newFile, "menu_title: %s\n", shortTitle);
264
265                                         fprintf(newFile, "---\n");
266                                 }
267                         }
268                         else if (level == 2)
269                         {
270                                 strcpy(scLink, title);
271                                 MakeFilename(scLink);
272
273                                 // Set up content for the exploded subchapter level
274                                 fprintf(exp, "---\n");
275                                 fprintf(exp, "title: %s\n", title);
276
277                                 if (strlen(shortTitle) > 0)
278                                         fprintf(exp, "menu_title: %s\n", shortTitle);
279
280                                 if (strlen(inclFile) > 0)
281                                         fprintf(exp, "include: %s\n", inclFile);
282                                 else
283                                         fprintf(exp, "include: %s.html\n", scLink);
284
285                                 // If it was already an include file, mark it to stay in include/
286                                 if (nomove)
287                                         fprintf(exp, "exclude: yes\n");
288
289                                 fprintf(exp, "part: subchapter\n");
290                                 fprintf(exp, "---\n\n");
291
292                                 if (nomove == false)
293                                 {
294                                         fileCount++;
295                                         sprintf(temp, "include/%s.html", scLink);
296                                         newFile = fopen(temp, "w");
297                                         fprintf(newFile, "---\n");
298                                         fprintf(newFile, "title: %s\n", title);
299
300                                         if (strlen(shortTitle) > 0)
301                                                 fprintf(newFile, "menu_title: %s\n", shortTitle);
302
303                                         if (strlen(style) > 0)
304                                                 fprintf(newFile, "style: %s\n", style);
305
306                                         fprintf(newFile, "---\n");
307                                 }
308                         }
309                 }
310                 else
311                 {
312                         if (((level == 1) || (level == 2)) && (newFile != NULL))
313                                 fprintf(newFile, "%s", buffer);
314                 }
315
316                 // Kill the buffer to prevent false positives...
317                 buffer[0] = 0;
318         }
319
320         printf("\nProcessed %i lines.\n", lineCount);
321         printf("Exploded master document into %i files.\n", fileCount);
322
323         fclose(master);
324         fclose(exp);
325
326         if (newFile)
327                 fclose(newFile);
328
329         // Finally, remove the .bak file:
330         remove("master-doc.bak");
331
332         return 0;
333 }
334