Add html production for convenience generating the website.
[open-adventure.git] / compile.c
1 #define LINESIZE 100
2 #define RTXSIZ 277
3 #define CLSMAX 12
4 #define LOCSIZ 185
5 #define LINSIZ 12600
6 #define TRNSIZ 5
7 #define TABSIZ 330
8 #define VRBSIZ 35
9 #define HNTSIZ 20
10 #define TRVSIZ 885
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stdbool.h>
15 #include <unistd.h>
16
17 const char advent_to_ascii[] = {0, 32, 33, 34, 39, 40, 41, 42, 43, 44, 45, 46, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 37, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 35, 36, 38, 47, 58, 59, 60, 61, 62, 63, 64, 91, 92, 93, 94, 95, 96, 123, 124, 125, 126, 0};
18 /* Rendered from the now-gone MPINIT() function */
19 const char ascii_to_advent[] = {0, 74, 75, 76, 77, 78, 79, 80, 81, 82, 0, 0, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 0, 1, 2, 106, 107, 63, 108, 3, 4, 5, 6, 7, 8, 9, 10, 109, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 110, 111, 112, 113, 114, 115, 116, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 117, 118, 119, 120, 121, 122, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 123, 124, 125, 126, 83};
20
21 // Global variables for use in functions below that can gradually disappear as code is cleaned up
22 long LNLENG;
23 long LNPOSN;
24 char INLINE[LINESIZE+1];
25 long NEWLOC;
26 long OLDLOC;
27
28 // Storage for what comes out of the database
29 long LINUSE;
30 long TRVS;
31 long CLSSES;
32 long TRNVLS;
33 long TABNDX;
34 long HNTMAX;
35 long PTEXT[101];
36 long RTEXT[RTXSIZ + 1];
37 long CTEXT[CLSMAX + 1];
38 long OBJSND[101];
39 long OBJTXT[101];
40 long STEXT[LOCSIZ + 1];
41 long LTEXT[LOCSIZ + 1];
42 long COND[LOCSIZ + 1];
43 long KEY[LOCSIZ + 1];
44 long LOCSND[LOCSIZ + 1];
45 long LINES[LINSIZ + 1];
46 long CVAL[CLSMAX + 1];
47 long TTEXT[TRNSIZ + 1];
48 long TRNVAL[TRNSIZ + 1];
49 long TRAVEL[TRVSIZ + 1];
50 long KTAB[TABSIZ + 1];
51 long ATAB[TABSIZ + 1];
52 long PLAC[101];
53 long FIXD[101];
54 long ACTSPK[VRBSIZ + 1];
55 long HINTS[HNTSIZ + 1][5];
56
57 bool is_set(long, long);
58 long GETTXT(long, long, long);
59 void BUG(long);
60 void MAPLIN(FILE*);
61 long GETNUM(FILE*);
62 int read_database(FILE*);
63 void read_messages(FILE*, long);
64 void read_section3_stuff(FILE*);
65 void read_vocabulary(FILE*);
66 void read_initial_locations(FILE*);
67 void read_action_verb_message_nr(FILE*);
68 void read_conditions(FILE*);
69 void read_hints(FILE*);
70 void read_sound_text(FILE*);
71 void write_0d(FILE*, FILE*, long, char*);
72 void write_1d(FILE*, FILE*, long[], long, char*);
73 void write_hints(FILE*, FILE*, long[][5], long, long, char*);
74 void write_files(FILE*, FILE*);
75
76 bool is_set(long var, long position)
77 {
78   long mask = 1l << position;
79   bool result = (var & mask) == mask;
80   return(result);
81 }
82
83 long GETTXT(long SKIP,long ONEWRD, long UPPER) {
84 /*  Take characters from an input line and pack them into 30-bit words.
85  *  Skip says to skip leading blanks.  ONEWRD says stop if we come to a
86  *  blank.  UPPER says to map all letters to uppercase.  If we reach the
87  *  end of the line, the word is filled up with blanks (which encode as 0's).
88  *  If we're already at end of line when GETTXT is called, we return -1. */
89
90   long TEXT;
91   static long SPLITTING = -1;
92
93   if(LNPOSN != SPLITTING)
94     SPLITTING = -1;
95   TEXT= -1;
96   while (true) {
97     if(LNPOSN > LNLENG)
98       return(TEXT);
99     if((!SKIP) || INLINE[LNPOSN] != 0)
100       break;
101     LNPOSN=LNPOSN+1;
102   }
103
104   TEXT=0;
105   for (int I=1; I<=5; I++) {
106     TEXT=TEXT*64;
107     if(LNPOSN > LNLENG || (ONEWRD && INLINE[LNPOSN] == 0))
108       continue;
109     char current=INLINE[LNPOSN];
110     if(current < 63) {
111       SPLITTING = -1;
112       if(UPPER && current >= 37)
113         current=current-26;
114       TEXT=TEXT+current;
115       LNPOSN=LNPOSN+1;
116       continue;
117     }
118     if(SPLITTING != LNPOSN) {
119       TEXT=TEXT+63;
120       SPLITTING = LNPOSN;
121       continue;
122     }
123
124     TEXT=TEXT+current-63;
125     SPLITTING = -1;
126     LNPOSN=LNPOSN+1;
127   }
128
129   return(TEXT);
130 }
131
132 void BUG(long NUM) {
133
134 /*  The following conditions are currently considered fatal bugs.  Numbers < 20
135  *  are detected while reading the database; the others occur at "run time".
136  *      0       Message line > 70 characters
137  *      1       Null line in message
138  *      2       Too many words of messages
139  *      3       Too many travel options
140  *      4       Too many vocabulary words
141  *      5       Required vocabulary word not found
142  *      6       Too many RTEXT messages
143  *      7       Too many hints
144  *      8       Location has cond bit being set twice
145  *      9       Invalid section number in database
146  *      10      Too many locations
147  *      11      Too many class or turn messages
148  *      20      Special travel (500>L>300) exceeds goto list
149  *      21      Ran off end of vocabulary table
150  *      22      Vocabulary type (N/1000) not between 0 and 3
151  *      23      Intransitive action verb exceeds goto list
152  *      24      Transitive action verb exceeds goto list
153  *      25      Conditional travel entry with no alternative
154  *      26      Location has no travel entries
155  *      27      Hint number exceeds goto list
156  *      28      Invalid month returned by date function
157  *      29      Too many parameters given to SETPRM */
158
159   fprintf(stderr, "Fatal error %ld.  See source code for interpretation.\n", NUM);
160   exit(EXIT_FAILURE);
161 }
162
163 void MAPLIN(FILE *OPENED) {
164 /*  Read a line of input, from the specified input source,
165  *  translate the chars to integers in the range 0-126 and store
166  *  them in the common array "INLINE".  Integer values are as follows:
167  *     0   = space [ASCII CODE 40 octal, 32 decimal]
168  *    1-2  = !" [ASCII 41-42 octal, 33-34 decimal]
169  *    3-10 = '()*+,-. [ASCII 47-56 octal, 39-46 decimal]
170  *   11-36 = upper-case letters
171  *   37-62 = lower-case letters
172  *    63   = percent (%) [ASCII 45 octal, 37 decimal]
173  *   64-73 = digits, 0 through 9
174  *  Remaining characters can be translated any way that is convenient;
175  *  The "TYPE" routine below is used to map them back to characters when
176  *  necessary.  The above mappings are required so that certain special
177  *  characters are known to fit in 6 bits and/or can be easily spotted.
178  *  Array elements beyond the end of the line should be filled with 0,
179  *  and LNLENG should be set to the index of the last character.
180  *
181  *  If the data file uses a character other than space (e.g., tab) to
182  *  separate numbers, that character should also translate to 0.
183  *
184  *  This procedure may use the map1,map2 arrays to maintain static data for
185  *  the mapping.  MAP2(1) is set to 0 when the program starts
186  *  and is not changed thereafter unless the routines on this page choose
187  *  to do so. */
188
189   do {
190     fgets(INLINE + 1, sizeof(INLINE) - 1, OPENED);
191   }
192   while (!feof(OPENED) && INLINE[1] == '#');
193
194   LNLENG = 0;
195   for (size_t i = 1; i <= sizeof(INLINE) && INLINE[i] != 0; ++i)
196     {
197       char val = INLINE[i] + 1;
198       INLINE[i] = ascii_to_advent[(unsigned)val];
199       if (INLINE[i] != 0)
200         LNLENG = i;
201     }
202   LNPOSN = 1;
203 }
204
205 long GETNUM(FILE *source) {
206 /*  Obtain the next integer from an input line.  If K>0, we first read a
207  *  new input line from a file; if K<0, we read a line from the keyboard;
208  *  if K=0 we use a line that has already been read (and perhaps partially
209  *  scanned).  If we're at the end of the line or encounter an illegal
210  *  character (not a digit, hyphen, or blank), we return 0. */
211
212   long DIGIT, GETNUM, SIGN;
213
214   if(source != NULL) MAPLIN(source);
215   GETNUM = 0;
216
217   while (INLINE[LNPOSN] == 0) {
218     if (LNPOSN > LNLENG) return(GETNUM);
219     ++LNPOSN;
220   }
221
222   if(INLINE[LNPOSN] != 9)
223     {
224       SIGN=1;
225     }
226   else
227     {
228       SIGN= -1;
229       LNPOSN=LNPOSN+1;
230     }
231   while (!(LNPOSN > LNLENG || INLINE[LNPOSN] == 0))
232     {
233       DIGIT=INLINE[LNPOSN]-64;
234       if(DIGIT < 0 || DIGIT > 9)
235         {
236           GETNUM=0;
237           break;
238         }
239       GETNUM=GETNUM*10+DIGIT;
240       LNPOSN=LNPOSN+1;
241     }
242
243   GETNUM=GETNUM*SIGN;
244   LNPOSN=LNPOSN+1;
245   return(GETNUM);
246 }
247
248 int read_database(FILE* database) {
249
250 /*  Clear out the various text-pointer arrays.  All text is stored in array
251  *  lines; each line is preceded by a word pointing to the next pointer (i.e.
252  *  the word following the end of the line).  The pointer is negative if this is
253  *  first line of a message.  The text-pointer arrays contain indices of
254  *  pointer-words in lines.  STEXT(N) is short description of location N.
255  *  LTEXT(N) is long description.  PTEXT(N) points to message for PROP(N)=0.
256  *  Successive prop messages are found by chasing pointers.  RTEXT contains
257  *  section 6's stuff.  CTEXT(N) points to a player-class message.  TTEXT is for
258  *  section 14.  We also clear COND (see description of section 9 for details). */
259
260   for (int I=1; I<=300; I++) {
261     if(I <= 100) PTEXT[I] = 0;
262     if(I <= RTXSIZ) RTEXT[I] = 0;
263     if(I <= CLSMAX) CTEXT[I] = 0;
264     if(I <= 100) OBJSND[I] = 0;
265     if(I <= 100) OBJTXT[I] = 0;
266     if(I > LOCSIZ) break;
267     STEXT[I] = 0;
268     LTEXT[I] = 0;
269     COND[I] = 0;
270     KEY[I] = 0;
271     LOCSND[I] = 0;
272   }
273
274   LINUSE = 1;
275   TRVS = 1;
276   CLSSES = 0;
277   TRNVLS = 0;
278
279 /*  Start new data section.  Sect is the section number. */
280
281   while(true)
282     {
283       long SECT=GETNUM(database);
284       OLDLOC= -1;
285       switch (SECT)
286         {
287           case 0: return(0);
288           case 1: read_messages(database, SECT); break;
289           case 2: read_messages(database, SECT); break;
290           case 3: read_section3_stuff(database); break;
291           case 4: read_vocabulary(database); break;
292           case 5: read_messages(database, SECT); break;
293           case 6: read_messages(database, SECT); break;
294           case 7: read_initial_locations(database); break;
295           case 8: read_action_verb_message_nr(database); break;
296           case 9: read_conditions(database); break;
297           case 10: read_messages(database, SECT); break;
298           case 11: read_hints(database); break;
299           case 12: break;
300           case 13: read_sound_text(database); break;
301           case 14: read_messages(database, SECT); break;
302           default: BUG(9);
303         }
304     }
305 }
306
307
308 /*  Sections 1, 2, 5, 6, 10, 14.  Read messages and set up pointers. */
309 void read_messages(FILE* database, long SECT)
310   {
311     long KK=LINUSE;
312     while(true)
313       {
314         long LOC;
315         LINUSE=KK;
316         LOC=GETNUM(database);
317         if(LNLENG >= LNPOSN+70)BUG(0);
318         if(LOC == -1) return;
319         if(LNLENG < LNPOSN)BUG(1);
320         do {
321             KK=KK+1;
322             if(KK >= LINSIZ)BUG(2);
323             LINES[KK]=GETTXT(false,false,false);
324           }
325         while(LINES[KK] != -1);
326         LINES[LINUSE]=KK;
327         if(LOC == OLDLOC) continue;
328         OLDLOC=LOC;
329         LINES[LINUSE]= -KK;
330         if(SECT == 14)
331           {
332             TRNVLS=TRNVLS+1;
333             if(TRNVLS > TRNSIZ)BUG(11);
334             TTEXT[TRNVLS]=LINUSE;
335             TRNVAL[TRNVLS]=LOC;
336             continue;
337           }
338         if(SECT == 10)
339           {
340             CLSSES=CLSSES+1;
341             if(CLSSES > CLSMAX)BUG(11);
342             CTEXT[CLSSES]=LINUSE;
343             CVAL[CLSSES]=LOC;
344             continue;
345           }
346         if(SECT == 6)
347           {
348             if(LOC > RTXSIZ)BUG(6);
349             RTEXT[LOC]=LINUSE;
350             continue;
351           }
352         if(SECT == 5)
353           {
354             if(LOC > 0 && LOC <= 100)PTEXT[LOC]=LINUSE;
355             continue;
356           }
357         if(LOC > LOCSIZ)BUG(10);
358         if(SECT == 1)
359           {
360             LTEXT[LOC]=LINUSE;
361             continue;
362           }
363
364         STEXT[LOC]=LINUSE;
365       }
366   }
367
368
369 /*  The stuff for section 3 is encoded here.  Each "from-location" gets a
370  *  contiguous section of the "TRAVEL" array.  Each entry in travel is
371  *  NEWLOC*1000 + KEYWORD (from section 4, motion verbs), and is negated if
372  *  this is the last entry for this location.  KEY(N) is the index in travel
373  *  of the first option at location N. */
374 void read_section3_stuff(FILE* database)
375   {
376     long LOC;
377     while((LOC=GETNUM(database)) != -1)
378       {
379         long NEWLOC=GETNUM(NULL);
380         long L;
381         if(KEY[LOC] == 0)
382           {
383             KEY[LOC]=TRVS;
384           }
385         else
386           {
387             TRAVEL[TRVS-1]= -TRAVEL[TRVS-1];
388           }
389         while((L=GETNUM(NULL)) != 0)
390           {
391             TRAVEL[TRVS]=NEWLOC*1000+L;
392             TRVS=TRVS+1;
393             if(TRVS == TRVSIZ)BUG(3);
394           }
395         TRAVEL[TRVS-1]= -TRAVEL[TRVS-1];
396       }
397   }
398
399
400 /*  Here we read in the vocabulary.  KTAB(N) is the word number, ATAB(N) is
401  *  the corresponding word.  The -1 at the end of section 4 is left in KTAB
402  *  as an end-marker. */
403 void read_vocabulary(FILE* database)
404   {
405     for (TABNDX=1; TABNDX<=TABSIZ; TABNDX++)
406       {
407         KTAB[TABNDX]=GETNUM(database);
408         if(KTAB[TABNDX] == -1) return;
409         ATAB[TABNDX]=GETTXT(true,true,true);
410       } /* end loop */
411     BUG(4);
412   }
413
414
415 /*  Read in the initial locations for each object.  Also the immovability info.
416  *  plac contains initial locations of objects.  FIXD is -1 for immovable
417  *  objects (including the snake), or = second loc for two-placed objects. */
418 void read_initial_locations(FILE* database)
419   {
420     long OBJ;
421     while((OBJ=GETNUM(database)) != -1)
422       {
423         PLAC[OBJ]=GETNUM(NULL);
424         FIXD[OBJ]=GETNUM(NULL);
425       }
426   }
427
428
429 /*  Read default message numbers for action verbs, store in ACTSPK. */
430 void read_action_verb_message_nr(FILE* database)
431   {
432     long VERB;
433     while((VERB=GETNUM(database)) != -1)
434       {
435         ACTSPK[VERB]=GETNUM(NULL);
436       }
437   }
438
439
440 /*  Read info about available liquids and other conditions, store in COND. */
441 void read_conditions(FILE* database)
442   {
443     long K;
444     while((K=GETNUM(database)) != -1)
445       {
446         long LOC;
447         while((LOC=GETNUM(NULL)) != 0)
448           {
449             if(is_set(COND[LOC],K)) BUG(8);
450             COND[LOC]=COND[LOC] + (1l << K);
451           }
452       }
453   }
454
455
456 /*  Read data for hints. */
457 void read_hints(FILE* database)
458   {
459     long K;
460     HNTMAX=0;
461     while((K=GETNUM(database)) != -1)
462       {
463         if(K <= 0 || K > HNTSIZ)BUG(7);
464         for (int I=1; I<=4; I++)
465           {
466             HINTS[K][I] =GETNUM(NULL);
467           } /* end loop */
468         HNTMAX=(HNTMAX>K ? HNTMAX : K);
469       }
470   }
471
472
473 /*  Read the sound/text info, store in OBJSND, OBJTXT, LOCSND. */
474 void read_sound_text(FILE* database)
475   {
476     long K;
477     while((K=GETNUM(database)) != -1)
478       {
479         long KK=GETNUM(NULL);
480         long I=GETNUM(NULL);
481         if(I != 0)
482           {
483             OBJSND[K]=(KK>0 ? KK : 0);
484             OBJTXT[K]=(I>0 ? I : 0);
485             continue;
486           }
487
488         LOCSND[K]=KK;
489       }
490   }
491
492 /*  Finish constructing internal data format */
493
494 /*  Having read in the database, certain things are now constructed.  PROPS are
495  *  set to zero.  We finish setting up COND by checking for forced-motion travel
496  *  entries.  The PLAC and FIXD arrays are used to set up ATLOC(N) as the first
497  *  object at location N, and LINK(OBJ) as the next object at the same location
498  *  as OBJ.  (OBJ>100 indicates that FIXED(OBJ-100)=LOC; LINK(OBJ) is still the
499  *  correct link to use.)  ABB is zeroed; it controls whether the abbreviated
500  *  description is printed.  Counts modulo 5 unless "LOOK" is used. */
501
502 void write_0d(FILE* c_file, FILE* header_file, long single, char* varname)
503 {
504   fprintf(c_file, "long %s = %ld;\n", varname, single);
505   fprintf(header_file, "extern long %s;\n", varname);
506 }
507
508 void write_1d(FILE* c_file, FILE* header_file, long array[], long dim, char* varname)
509 {
510   fprintf(c_file, "long %s[] = {\n", varname);
511   for (int i = 0; i < dim; ++i)
512     {
513       if (i % 10 == 0)
514         {
515           if (i > 0)
516             fprintf(c_file, "\n");
517           fprintf(c_file, "  ");
518         }
519       fprintf(c_file, "%ld, ", array[i]);
520     }
521   fprintf(c_file, "\n};\n");
522   fprintf(header_file, "extern long %s[%ld];\n", varname, dim);
523 }
524
525 void write_hints(FILE* c_file, FILE* header_file, long matrix[][5], long dim1, long dim2, char* varname)
526 {
527   fprintf(c_file, "long %s[][%ld] = {\n", varname, dim2);
528   for (int i = 0; i < dim1; ++i)
529     {
530       fprintf(c_file, "  {");
531       for (int j = 0; j < dim2; ++j)
532         {
533           fprintf(c_file, "%ld, ", matrix[i][j]);
534         }
535       fprintf(c_file, "},\n");
536     }
537   fprintf(c_file, "};\n");
538   fprintf(header_file, "extern long %s[%ld][%ld];\n", varname, dim1, dim2);
539 }
540
541 void write_files(FILE* c_file, FILE* header_file)
542 {
543   // preprocessor defines for the header
544   fprintf(header_file, "#define RTXSIZ 277\n");
545   fprintf(header_file, "#define CLSMAX 12\n");
546   fprintf(header_file, "#define LOCSIZ 185\n");
547   fprintf(header_file, "#define LINSIZ 12500\n");
548   fprintf(header_file, "#define TRNSIZ 5\n");
549   fprintf(header_file, "#define TABSIZ 330\n");
550   fprintf(header_file, "#define VRBSIZ 35\n");
551   fprintf(header_file, "#define HNTSIZ 20\n");
552   fprintf(header_file, "#define TRVSIZ 885\n");
553   fprintf(header_file, "\n");
554
555   // include the header in the C file
556   fprintf(c_file, "#include \"database.h\"\n");
557   fprintf(c_file, "\n");
558
559   // content variables
560   write_0d(c_file, header_file, LINUSE, "LINUSE");
561   write_0d(c_file, header_file, TRVS, "TRVS");
562   write_0d(c_file, header_file, CLSSES, "CLSSES");
563   write_0d(c_file, header_file, TRNVLS, "TRNVLS");
564   write_0d(c_file, header_file, TABNDX, "TABNDX");
565   write_0d(c_file, header_file, HNTMAX, "HNTMAX");
566   write_1d(c_file, header_file, PTEXT, 100 + 1, "PTEXT");
567   write_1d(c_file, header_file, RTEXT, RTXSIZ + 1, "RTEXT");
568   write_1d(c_file, header_file, CTEXT, CLSMAX + 1, "CTEXT");
569   write_1d(c_file, header_file, OBJSND, 100 + 1, "OBJSND");
570   write_1d(c_file, header_file, OBJTXT, 100 + 1, "OBJTXT");
571   write_1d(c_file, header_file, STEXT, LOCSIZ + 1, "STEXT");
572   write_1d(c_file, header_file, LTEXT, LOCSIZ + 1, "LTEXT");
573   write_1d(c_file, header_file, COND, LOCSIZ + 1, "COND");
574   write_1d(c_file, header_file, KEY, LOCSIZ + 1, "KEY");
575   write_1d(c_file, header_file, LOCSND, LOCSIZ + 1, "LOCSND");
576   write_1d(c_file, header_file, LINES, LINSIZ + 1, "LINES");
577   write_1d(c_file, header_file, CVAL, CLSMAX + 1, "CVAL");
578   write_1d(c_file, header_file, TTEXT, TRNSIZ + 1, "TTEXT");
579   write_1d(c_file, header_file, TRNVAL, TRNSIZ + 1, "TRNVAL");
580   write_1d(c_file, header_file, TRAVEL, TRVSIZ + 1, "TRAVEL");
581   write_1d(c_file, header_file, KTAB, TABSIZ + 1, "KTAB");
582   write_1d(c_file, header_file, ATAB, TABSIZ + 1, "ATAB");
583   write_1d(c_file, header_file, PLAC, 100 + 1, "PLAC");
584   write_1d(c_file, header_file, FIXD, 100 + 1, "FIXD");
585   write_1d(c_file, header_file, ACTSPK, VRBSIZ + 1, "ACTSPK");
586   write_hints(c_file, header_file, HINTS, HNTSIZ + 1, 5, "HINTS");
587 }
588
589 int main()
590 {
591   FILE* database = fopen("adventure.text", "r");
592   read_database(database);
593   fclose(database);
594
595   FILE* c_file = fopen("database.c", "w");
596   FILE* header_file = fopen("database.h", "w");
597   write_files(c_file, header_file);
598   fclose(c_file);
599   fclose(header_file);
600
601   return(EXIT_SUCCESS);
602 }