]> 4ch.mooo.com Git - 16.git/blob - src/v2/source/UTIL/CHRMAK/CHRMAK.CC
wwww
[16.git] / src / v2 / source / UTIL / CHRMAK / CHRMAK.CC
1 /*\r
2 Copyright (C) 1998 BJ Eirich (aka vecna)\r
3 This program is free software; you can redistribute it and/or\r
4 modify it under the terms of the GNU General Public License\r
5 as published by the Free Software Foundation; either version 2\r
6 of the License, or (at your option) any later version.\r
7 This program is distributed in the hope that it will be useful,\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
10 See the GNU General Public Lic\r
11 See the GNU General Public License for more details.\r
12 You should have received a copy of the GNU General Public License\r
13 along with this program; if not, write to the Free Software\r
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
15 */\r
16 \r
17 // CHRMAK.CC\r
18 // V2 PCX to CHR converter w/ makefiles\r
19 //\r
20 // coded by aen\r
21 // aen@verge-rpg.com\r
22 \r
23 #include <stdio.h>\r
24 #include <stdlib.h>\r
25 #include <stdarg.h>\r
26 #include <ctype.h>\r
27 #include <string.h>\r
28 #include <sys/stat.h>\r
29 \r
30 #include <conio.h>\r
31 \r
32 ////////////////////////////////////////////////////////////////////////////\r
33 ////////////////////////////////////////////////////////////////////////////\r
34 \r
35 typedef unsigned char byte;\r
36 typedef unsigned short word;\r
37 typedef unsigned long quad;\r
38 \r
39 static void fputw(word w, FILE *fp) { fwrite(&w,1,2,fp); }\r
40 static void fputd(quad d, FILE *fp) { fwrite(&d,1,4,fp); }\r
41 static word fgetw(FILE *fp) { word w; fread(&w,1,2,fp); return w; }\r
42 quad fgetd(FILE *fp) { quad d; fread(&d,1,4,fp); return d; }\r
43 \r
44 // skips the number of bytes in the file; just seeks past them\r
45 static void fskip(int bytes, FILE *fp)\r
46   { fseek(fp,bytes,SEEK_CUR); }\r
47 \r
48 static void fputraw(char *raw, int bytes, FILE *fp)\r
49   { fwrite(raw, 1,bytes, fp); }\r
50 \r
51 // writes a null-terminated string to the file\r
52 void fputstrz(char *str, FILE *fp)\r
53   { fputraw(str, strlen(str)+1, fp); }\r
54 \r
55 // writes a string to the file (without the null-terminator), preceeded by\r
56 // a quad length marker\r
57 static void fputstrn(char *str, FILE *fp)\r
58   { int n=strlen(str)+1; fputd(n,fp); fputraw(str,n,fp); }\r
59 \r
60 ////////////////////////////////////////////////////////////////////////////\r
61 ////////////////////////////////////////////////////////////////////////////\r
62 \r
63 #define CHRMAK_VER_MAJ 0\r
64 #define CHRMAK_VER_MIN 1\r
65 #define CHRMAK_VER_STR "0.1b"\r
66 #define CHRMAK_AUTHORS "aen"\r
67 \r
68 // parsing vars\r
69 static char *mak_base=0;\r
70 static char *makp=0;\r
71 static int mak_bytes=0;\r
72 static char mak_tok_ident[256];\r
73 static char mak_tok_val[256];\r
74 static int mak_tok_valn=0;          // numeric val of mak_tok\r
75 static int mak_line=0;\r
76 \r
77 // makefile vars\r
78 static char chrmak_makefile[256];\r
79 \r
80 static char pcx_name[256];      static int got_pcx_name=0;\r
81 static char chr_name[256];      static int got_chr_name=0;\r
82 static int frame_w=0;           static int got_frame_w=0;\r
83 static int frame_h=0;           static int got_frame_h=0;\r
84 static int hot_x=0;             static int got_hot_x=0;\r
85 static int hot_y=0;             static int got_hot_y=0;\r
86 static int hot_w=0;             static int got_hot_w=0;\r
87 static int hot_h=0;             static int got_hot_h=0;\r
88 static int per_row=0;           static int got_per_row=0;\r
89 static int total_frames=0;      static int got_total_frames=0;\r
90 static int lidle=0;             static int got_lidle=0;\r
91 static int ridle=0;             static int got_ridle=0;\r
92 static int uidle=0;             static int got_uidle=0;\r
93 static int didle=0;             static int got_didle=0;\r
94 static char lscript[256];       static int got_lscript=0;\r
95 static char rscript[256];       static int got_rscript=0;\r
96 static char uscript[256];       static int got_uscript=0;\r
97 static char dscript[256];       static int got_dscript=0;\r
98 \r
99 void warning(char *message, ...)\r
100 {\r
101   static char buffer[256];\r
102   va_list args;\r
103 \r
104   va_start(args, message);\r
105   vsprintf(buffer, message, args);\r
106   va_end(args);\r
107 \r
108   printf("%s \n", buffer);\r
109 }\r
110 \r
111 static void fatal(char *message, ...)\r
112 {\r
113   static char buffer[256];\r
114   va_list args;\r
115 \r
116   va_start(args, message);\r
117   vsprintf(buffer, message, args);\r
118   va_end(args);\r
119 \r
120   printf("%s \n", buffer);\r
121 \r
122   exit(0);\r
123 }\r
124 \r
125 //#ifdef __DJGPP__\r
126 // Watcom has one of these\r
127 static int filelength(int handle)\r
128 {\r
129   struct stat fileinfo;\r
130   if (-1 == fstat(handle, &fileinfo))\r
131     fatal("error fstating");\r
132   return fileinfo.st_size;\r
133 }\r
134 //#endif\r
135 \r
136 static int streq(char *a, char *b)\r
137 {\r
138   while (*a)\r
139   {\r
140     if (*a++ != *b++)\r
141       return 0;\r
142   }\r
143   return !*b;\r
144 }\r
145 \r
146 static void usage()\r
147 {\r
148   printf("usage: chrmak <makefile> \n");\r
149   exit(0);\r
150 }\r
151 \r
152 static void banner()\r
153 {\r
154   printf("chrmak v%s \1e by %s \n", CHRMAK_VER_STR, CHRMAK_AUTHORS);\r
155 }\r
156 \r
157 static void parse_args(int argc, char *argv[])\r
158 {\r
159   if (argc != 2)\r
160     usage();\r
161 \r
162   strcpy(chrmak_makefile, argv[1]);\r
163 }\r
164 \r
165 static void skip_cpp_comment()\r
166 {\r
167   makp+=2;\r
168   while (*makp && '\n'!=*makp)\r
169     makp++;\r
170   if (*makp)\r
171     makp++;\r
172 }\r
173 \r
174 static void skip_c_comment()\r
175 {\r
176   makp+=2;\r
177   while (*makp && ('*'!=makp[0] || '/'!=makp[1]))\r
178   {\r
179     if ('\n'==*makp)\r
180       mak_line++;\r
181     if ('/'==makp[0] && '*'==makp[1])\r
182       skip_c_comment();\r
183     else makp++;\r
184   }\r
185   if (*makp)\r
186     makp+=2;\r
187 }\r
188 \r
189 static void parse_whitespace()\r
190 {\r
191   do {\r
192     if (!*makp)\r
193       return;\r
194     if (isspace(*makp))\r
195     {\r
196       while (*makp && isspace(*makp))\r
197       {\r
198         if ('\n'==*makp)\r
199           mak_line++;\r
200         makp++;\r
201       }\r
202       continue;\r
203     }\r
204     if ('/'==makp[0] && '/'==makp[1])\r
205       { skip_cpp_comment(); continue; }\r
206     if ('/'==makp[0] && '*'==makp[1])\r
207       { skip_c_comment(); continue; }\r
208     break;\r
209   } while (1);\r
210 }\r
211 \r
212 static void grab_ident()\r
213 {\r
214   char *t=mak_tok_ident;\r
215   while (isalnum(*makp) || '_'==*makp)\r
216     *t++=*makp++;\r
217   *t=0;\r
218   strlwr(mak_tok_ident);\r
219 }\r
220 \r
221 static void grab_val()\r
222 {\r
223   char *t=mak_tok_val;\r
224   while (isalnum(*makp) || '_'==*makp)\r
225     *t++=*makp++;\r
226   *t=0;\r
227   mak_tok_valn=atoi(mak_tok_val);\r
228 }\r
229 \r
230 static int ident_is(char *id) { return streq(mak_tok_ident,id); }\r
231 \r
232 static void do_assign()\r
233 {\r
234   if (ident_is("pcx_name"))\r
235     { strcpy(pcx_name, mak_tok_val); got_pcx_name=1;            return; }\r
236   else if (ident_is("chr_name"))\r
237     { strcpy(chr_name, mak_tok_val); got_chr_name=1;            return; }\r
238   else if (ident_is("frame_w"))\r
239     { frame_w=mak_tok_valn;          got_frame_w=1;             return; }\r
240   else if (ident_is("frame_h"))\r
241     { frame_h=mak_tok_valn;          got_frame_h=1;             return; }\r
242   else if (ident_is("hot_x"))\r
243     { hot_x=mak_tok_valn;            got_hot_x=1;               return; }\r
244   else if (ident_is("hot_y"))\r
245     { hot_y=mak_tok_valn;            got_hot_y=1;               return; }\r
246   else if (ident_is("hot_w"))\r
247     { hot_w=mak_tok_valn;            got_hot_w=1;               return; }\r
248   else if (ident_is("hot_h"))\r
249     { hot_h=mak_tok_valn;            got_hot_h=1;               return; }\r
250   else if (ident_is("per_row"))\r
251     { per_row=mak_tok_valn;          got_per_row=1;             return; }\r
252   else if (ident_is("total_frames"))\r
253     { total_frames=mak_tok_valn;     got_total_frames=1;        return; }\r
254   else if (ident_is("lidle"))\r
255     { lidle=mak_tok_valn;            got_lidle=1;               return; }\r
256   else if (ident_is("ridle"))\r
257     { ridle=mak_tok_valn;            got_ridle=1;               return; }\r
258   else if (ident_is("uidle"))\r
259     { uidle=mak_tok_valn;            got_uidle=1;               return; }\r
260   else if (ident_is("didle"))\r
261     { didle=mak_tok_valn;            got_didle=1;               return; }\r
262   else if (ident_is("lscript"))\r
263     { strcpy(lscript, mak_tok_val);  got_lscript=1;             return; }\r
264   else if (ident_is("rscript"))\r
265     { strcpy(rscript, mak_tok_val);  got_rscript=1;             return; }\r
266   else if (ident_is("uscript"))\r
267     { strcpy(uscript, mak_tok_val);  got_uscript=1;             return; }\r
268   else if (ident_is("dscript"))\r
269     { strcpy(dscript, mak_tok_val);  got_dscript=1;             return; }\r
270 \r
271   fatal("%s: unknown ident '%s' on line %i",\r
272     chrmak_makefile, mak_tok_ident, mak_line);\r
273 }\r
274 \r
275 static int parse_assign()\r
276 {\r
277   int last_line=0; // helper for error detection\r
278 \r
279   parse_whitespace();\r
280   if (!*makp)\r
281     return 1;\r
282   else if (isalpha(*makp))\r
283   {\r
284     grab_ident();      // get ident\r
285     last_line=mak_line;\r
286 \r
287     parse_whitespace(); // expect\r
288     if ('=' != *makp++)\r
289       fatal("%s: expected = on line %i", chrmak_makefile, last_line);\r
290 \r
291     parse_whitespace(); // get val\r
292     grab_val();\r
293     last_line=mak_line;\r
294 \r
295     do_assign();\r
296 \r
297     parse_whitespace(); // expect\r
298     if (';' != *makp++)\r
299       fatal("%s: expected ; on line %i", chrmak_makefile, last_line);\r
300     else while (';'==*makp) makp++;\r
301 \r
302     return 0;\r
303   }\r
304   fatal("%s: expected ident, got '%c' on line %i",\r
305     chrmak_makefile, *makp, mak_line);\r
306   return 1;\r
307 }\r
308 \r
309 static void check_needs()\r
310 {\r
311   if (!got_pcx_name)     fatal("%s: pcx_name missing", chrmak_makefile);\r
312   if (!got_chr_name)     fatal("%s: chr_name missing", chrmak_makefile);\r
313   if (!got_frame_w)      fatal("%s: frame_w missing", chrmak_makefile);\r
314   if (!got_frame_h)      fatal("%s: frame_h missing", chrmak_makefile);\r
315   if (!got_hot_x)        fatal("%s: hot_x missing", chrmak_makefile);\r
316   if (!got_hot_y)        fatal("%s: hot_y missing", chrmak_makefile);\r
317   if (!got_hot_w)        fatal("%s: hot_w missing", chrmak_makefile);\r
318   if (!got_hot_h)        fatal("%s: hot_h missing", chrmak_makefile);\r
319   if (!got_per_row)      fatal("%s: per_row missing", chrmak_makefile);\r
320   if (!got_total_frames) fatal("%s: total_frames missing", chrmak_makefile);\r
321   if (!got_lidle)        fatal("%s: lidle missing", chrmak_makefile);\r
322   if (!got_ridle)        fatal("%s: ridle missing", chrmak_makefile);\r
323   if (!got_uidle)        fatal("%s: uidle missing", chrmak_makefile);\r
324   if (!got_didle)        fatal("%s: didle missing", chrmak_makefile);\r
325   if (!got_lscript)      fatal("%s: lscript missing", chrmak_makefile);\r
326   if (!got_rscript)      fatal("%s: rscript missing", chrmak_makefile);\r
327   if (!got_uscript)      fatal("%s: uscript missing", chrmak_makefile);\r
328   if (!got_dscript)      fatal("%s: dscript missing", chrmak_makefile);\r
329 }\r
330 \r
331 static void parse_makefile()\r
332 {\r
333   FILE *fp=0;\r
334 \r
335   printf("ú parsing %s \r", chrmak_makefile);\r
336   fflush(stdout);\r
337 \r
338   fp=fopen(chrmak_makefile, "rb");\r
339   if (!fp) fatal("unable to open %s", chrmak_makefile);\r
340 \r
341   mak_bytes=filelength(fileno(fp));     // calc bytes\r
342   mak_base=new char [mak_bytes+1];      // alloc room\r
343   fread(mak_base,1,mak_bytes,fp);       // read bytes\r
344   mak_base[mak_bytes]=0;                // null-term\r
345   makp=mak_base;                        // setup cur byte ptr\r
346   mak_line=1;\r
347 \r
348   while (!parse_assign())\r
349     ;\r
350 \r
351   // got everything we need?\r
352   check_needs();\r
353 \r
354   delete[]mak_base; mak_base=0;\r
355   makp=0;\r
356 \r
357   fclose(fp);\r
358 \r
359   printf("û \n");\r
360   fflush(stdout);\r
361 }\r
362 \r
363 ////////////////////////////////////////////////////////////////////////////\r
364 // PCX & COMPRESS STUFF ////////////////////////////////////////////////////\r
365 ////////////////////////////////////////////////////////////////////////////\r
366 \r
367 static FILE *chrfp=0;\r
368 static FILE *pcxfp=0;\r
369 static byte *virscr=0;\r
370 \r
371 int manufacturer=0;                     // pcx header\r
372 int version=0;\r
373 int encoding=0;\r
374 int bpp=0;\r
375 int xmin=0,ymin=0;\r
376 int xmax=0,ymax=0;\r
377 int hres=0,vres=0;\r
378 char palette[48];\r
379 int reserved=0;\r
380 int color_planes=0;\r
381 int bpl=0;\r
382 int palette_type=0;\r
383 char filler[58];\r
384 byte pal[768];\r
385 \r
386 int image_width=0,image_depth=0;\r
387 quad vidoffset=0;\r
388 \r
389 void LoadPCXHeader()\r
390 {\r
391   manufacturer  = fgetc(pcxfp); // always 10\r
392   version       = fgetc(pcxfp); // should be 5?\r
393   encoding      = fgetc(pcxfp); // always 1\r
394   bpp           = fgetc(pcxfp); // bits per pixel\r
395 \r
396   xmin          = fgetw(pcxfp); // grab window\r
397   ymin          = fgetw(pcxfp);\r
398   xmax          = fgetw(pcxfp);\r
399   ymax          = fgetw(pcxfp);\r
400   image_width   = xmax-xmin+1;  // calc dims\r
401   image_depth   = ymax-ymin+1;\r
402 \r
403   hres          = fgetw(pcxfp);\r
404   vres          = fgetw(pcxfp);\r
405 \r
406   fread(palette,1,48,pcxfp);    // ega color map\r
407 \r
408   reserved      = fgetc(pcxfp);\r
409   color_planes  = fgetc(pcxfp); // should be 1\r
410 \r
411   bpl           = fgetw(pcxfp); // bytes per line\r
412   palette_type  = fgetw(pcxfp);\r
413 \r
414   fread(filler,1,58,pcxfp);     // nothing important here\r
415 }\r
416 \r
417 void ReadPCXLine(byte *dest)\r
418 {\r
419   int i=0,c=0,n=0,run=0;\r
420 \r
421   // decode a row\r
422   for (n=0; n<image_width; n+=run)\r
423   {\r
424     // assume single pixel\r
425     run=1;\r
426     c=fgetc(pcxfp);\r
427     // is this a run?\r
428     if ((c&192)==192)\r
429     {\r
430       // calc run and grab color\r
431       run=c&63;\r
432       c=fgetc(pcxfp);\r
433     }\r
434     // now replicate run bytes\r
435     for (i=0; i<run; i++)\r
436       dest[vidoffset+n+i]=(byte)c;\r
437   }\r
438   // skip row padding, if any\r
439   fskip(bpl-image_width,pcxfp);\r
440 }\r
441 \r
442 void LoadPCX(char *filename)\r
443 {\r
444   int i=0;\r
445 \r
446   // open file\r
447   if (pcxfp) fclose(pcxfp);\r
448   pcxfp=fopen(filename,"rb");\r
449   if (!pcxfp)\r
450   { printf("unable to open %s", filename);\r
451     exit(0);\r
452   }\r
453 \r
454   // get info\r
455   LoadPCXHeader();\r
456 \r
457   // allocate image data\r
458   if (virscr) { free(virscr); virscr=0; }\r
459   virscr=(byte *)malloc(image_width*image_depth);\r
460 \r
461   // decompress image data\r
462   for (i=0; i<image_depth; i++)\r
463   { vidoffset=i*image_width;\r
464     ReadPCXLine(virscr);\r
465   }\r
466 \r
467   // pal exists?\r
468   if (fgetc(pcxfp) == 12)\r
469     fread(pal,1,768,pcxfp);\r
470 \r
471   // done\r
472   fclose(pcxfp);\r
473 }\r
474 \r
475 static int bufsize=0;\r
476 static byte *csrc=0, *cb=0;\r
477 \r
478 static void emitc(byte b) { *csrc++=b, bufsize++; }\r
479 \r
480 static void Compress(byte *p, int len)\r
481 {\r
482   int i=0;\r
483   byte byt=0,samect=0;\r
484 \r
485   csrc=cb;\r
486   i=0; bufsize=0;\r
487   do\r
488   {\r
489     byt=p[i++];\r
490     samect=1;\r
491     while (samect<254 && i<len && byt==p[i])\r
492       { samect++; i++; }\r
493 \r
494     if (samect==2 && byt != 0xFF) { emitc(byt); }\r
495     if (samect==3 && byt != 0xFF) { emitc(byt); emitc(byt); }\r
496     if (samect>3 || byt == 0xFF)\r
497     {\r
498       emitc(0xFF);\r
499       emitc(samect);\r
500     }\r
501     emitc(byt);\r
502 \r
503   } while (i<len);\r
504 }\r
505 \r
506 static byte *raw=0,*r=0;\r
507 \r
508 static void dumpframe(int x, int y)\r
509 {\r
510   byte *src=&virscr[(y*image_width)+x];\r
511 \r
512   for (y=0; y<frame_h; y++)\r
513   {\r
514     for (x=0; x<frame_w; x++)\r
515       *r++=src[x];\r
516     src+=image_width;\r
517   }\r
518 }\r
519 \r
520 ////////////////////////////////////////////////////////////////////////////\r
521 ////////////////////////////////////////////////////////////////////////////\r
522 \r
523 static void WriteFrames(char *filename, FILE *dump)\r
524 {\r
525   int i=0,j=0;\r
526   int raw_bytes=0;\r
527 \r
528   printf("  ú reading image %s \r", pcx_name);\r
529   fflush(stdout);\r
530 \r
531   LoadPCX(filename);\r
532 \r
533   printf("  û \n");\r
534   fflush(stdout);\r
535 \r
536   printf("  ú collecting frames \r");\r
537   fflush(stdout);\r
538 \r
539   // setup bufs for raw data/compression\r
540   raw_bytes = total_frames * (frame_w*frame_h);\r
541   cb  = (byte *)malloc(raw_bytes);\r
542   raw = (byte *)malloc(raw_bytes); r=raw;\r
543 \r
544   // dump all frames in row major byte order into 'raw'\r
545   for (i=0; i<10; i++)\r
546     for (j=0; j<per_row; j++)\r
547     {\r
548       if ((i*per_row)+j<total_frames)\r
549         dumpframe(1+(j*(frame_w+1)), 1+(i*(frame_h+1)));\r
550     }\r
551 \r
552   printf("  û \n");\r
553   fflush(stdout);\r
554 \r
555   printf("  ú compressing \r");\r
556   fflush(stdout);\r
557 \r
558   // smush the sucker\r
559   Compress(raw, raw_bytes);\r
560 \r
561   fputd(bufsize,dump);           // compressed data bytes\r
562   fputraw((char *)cb,bufsize,dump);      // compressed data\r
563 \r
564   printf("  û \n");\r
565   fflush(stdout);\r
566 \r
567   // cleanup bufs\r
568   free(raw);\r
569   free(cb);\r
570 }\r
571 \r
572 static void WriteInfo(FILE *dump)\r
573 {\r
574   fputc(2,  dump);              // version\r
575   fputw((word)frame_w, dump);         // frame dims\r
576   fputw((word)frame_h, dump);\r
577   fputw((word)hot_x, dump);           // hotspot coords\r
578   fputw((word)hot_y, dump);\r
579   fputw((word)hot_w, dump);           // hotspot dims\r
580   fputw((word)hot_h, dump);\r
581   fputw((word)total_frames, dump);    // total frames\r
582 }\r
583 \r
584 static void WriteScripts(FILE *fp)\r
585 {\r
586   fputd(lidle,fp);\r
587   fputd(ridle,fp);\r
588   fputd(uidle,fp);\r
589   fputd(didle,fp);\r
590 \r
591   fputstrn(lscript,fp);\r
592   fputstrn(rscript,fp);\r
593   fputstrn(uscript,fp);\r
594   fputstrn(dscript,fp);\r
595 }\r
596 \r
597 static void write_chr()\r
598 {\r
599   strcat(pcx_name, ".pcx");\r
600   strcat(chr_name, ".chr");\r
601 \r
602   /*\r
603   // DEBUG\r
604   printf(" \n");\r
605   printf("pcx_name: %s \n", pcx_name);\r
606   printf("chr_name: %s \n", chr_name);\r
607   printf("frame_w: %i \n", frame_w);\r
608   printf("frame_h: %i \n", frame_h);\r
609   printf("hot_x: %i \n", hot_x);\r
610   printf("hot_y: %i \n", hot_y);\r
611   printf("hot_w: %i \n", hot_w);\r
612   printf("hot_h: %i \n", hot_h);\r
613   printf("per_row: %i \n", per_row);\r
614   printf("total_frames: %i \n", total_frames);\r
615   printf("lidle: %i \n", lidle);\r
616   printf("ridle: %i \n", ridle);\r
617   printf("uidle: %i \n", uidle);\r
618   printf("didle: %i \n", didle);\r
619   printf("lscript: %s \n", lscript);\r
620   printf("rscript: %s \n", rscript);\r
621   printf("uscript: %s \n", uscript);\r
622   printf("dscript: %s \n", dscript);\r
623   fflush(stdout);\r
624   getch();\r
625   */\r
626 \r
627   printf("> dumping %s \n", chr_name);\r
628   fflush(stdout);\r
629 \r
630   chrfp=fopen(chr_name, "wb");\r
631   if (!chrfp) fatal("unable to open %s", chr_name);\r
632 \r
633   WriteInfo(chrfp);\r
634   WriteFrames(pcx_name,chrfp);\r
635   WriteScripts(chrfp);\r
636 \r
637   fclose(chrfp);\r
638 \r
639   printf("complete! \n");\r
640   fflush(stdout);\r
641 }\r
642 \r
643 int main(int argc, char *argv[])\r
644 {\r
645   banner();\r
646 \r
647   parse_args(argc, argv);\r
648   parse_makefile();\r
649 \r
650   write_chr();\r
651 \r
652   return 0;\r
653 }\r