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