/********************************************************************** ce-conv.c Code copyright 1991 by Ken Cox. Distributed as Freeware. Updated 2007 by David Madison version 1.0, May 1991 version 1.1, Aug 1991 version 1.2, Sep 2007 This program reads text descriptions of Cosmic Encounter powers and their associated Flares from standard input and generates three files, POWERS.OUT, FLARES.OUT, and FLARES.ONE, containing PostScript. When the PostScript is combined with the header files powers.ps and cards.ps (distributed separately), the result can be used to print power cards and Flares. To compile under UNIX: cc -o ce-conv ce-conv.c To use under UNIX: ce-conv < file or ce-conv file [file ...] You might need to change the line #include to #include , depending on your system; under UNIX, look in /usr/include to see what the string header file is named. In addition, you might need to change "strchr" into "index". **********************************************************************/ #include #include #include #ifndef VERBOSE #define VERBOSE 0 #endif #define POWER_OUT_FILE "POWERS.OUT" #define FLARE_OUT_FILE "FLARES.OUT" #define FLARE_ONE_FILE "FLARES.ONE" static FILE *file_in, *power_out, *flare_out, *one_out, *curr_out; static char line[8192]; static char name_buf[8192]; static char origin_buf[8192]; static char power_buf[8192]; static char rest_buf[8192]; static char *filename; static int lineno, outstate, power_type; /* TO ADD MORE WORDS THAT WILL BE RECOGNIZED IN "You have the power...", * add more entries to the pw_str array. Each entry uses two strings: * the string to look for after the "You have the power", and a string * to be emitted in the Flare description. The second string must be * defined in the PostScript header cards.ps; in that file we now have * /PO (Power of) def /PT (Power to) def * /PV (Power over) def /PW (Power) def * which define the four strings currently in this array. * For example, if you wanted to permit "You have the power in X.", where * X is anything, you would do two things: * 1) Add the entry { "in", "PN" } to the array BEFORE the last entry * currently in the array (the { "", "PW" } entry). * 2) Add the definition /PN (Power in) def to cards.ps. */ static struct { char *search_string; char *print_string; int len; } pw_str[] = { { "of", "PO" }, { "to", "PT" }, { "over", "PV" }, { "", "PW" }, }; #define NPOWER_STRINGS (sizeof(pw_str)/sizeof(pw_str[0])) main(argc,argv) int argc; char **argv; { int i; power_out = fopen(POWER_OUT_FILE,"w"); flare_out = fopen(FLARE_OUT_FILE,"w"); one_out = fopen(FLARE_ONE_FILE,"w"); if (power_out == (FILE *)NULL || flare_out == (FILE *)NULL || one_out == NULL) { fprintf(stderr,"Can't open output file(s)\n"); exit(1); } for (i = 0; i < NPOWER_STRINGS; i++) pw_str[i].len = strlen(pw_str[i].search_string); fprintf(power_out,"\nSetup\n"); fprintf(flare_out,"\n/OneShotFlares false def\nSetup\n"); fprintf(one_out,"\n/OneShotFlares true def\nSetup\n"); if (argc > 1) { while (argc > 1) { argc--; argv++; filename = *argv; if ((file_in = fopen(filename,"r")) != NULL) { #if VERBOSE > 2 fprintf(stderr,"opening %s\n",filename); #endif lineno = 0; outstate = 0; read_file(); fclose(file_in); } else { fprintf(stderr,"warning: can't open %s\n",filename); } } } else { file_in = stdin; filename = "stdin"; #if VERBOSE > 2 fprintf(stderr,"opening %s\n",filename); #endif lineno = 0; outstate = 0; read_file(); } fprintf(power_out,"\nFinished\n"); fclose(power_out); fprintf(flare_out,"\nFinished\n"); fclose(flare_out); fprintf(one_out,"\nFinished\n"); fclose(one_out); exit(0); } read_file() { int found_flare; line[0] = '\0'; curr_out = power_out; get_header(); for (;;) { curr_out = power_out; if (!get_power_line()) return; get_power_text(); get_paragraph("History: ",1); get_paragraph("Restriction: ",1); fprintf(curr_out,"(%s) {} Power\n",rest_buf); do { found_flare = 0; while (line[0] == '\0') if (!getline()) return; if (!strncmp(line,"Wild: ",6)) { get_flare(flare_out,"Wild: ","Super: "); found_flare = 1; } else if (!strncmp(line,"Wild1: ",7)) { get_flare(one_out,"Wild1: ","Super1: "); found_flare = 1; } } while (found_flare); } } int getline() { lineno++; if (fgets(line,8190,file_in) == NULL) return(0); #if VERBOSE > 8 fprintf(stderr,"%s\n",line); #endif if (line[0] == '\t' || line[0] == ' ' || line[0] == ';' || line[0] == '\n') line[0] = '\0'; return(1); } outline(s) char *s; { while (*s) { if (*s < ' ') { if (*s == '\t') fprintf(curr_out,"\\t"); else if (*s != '\n') fputc(' ',curr_out); } else switch (*s) { case '(': fprintf(curr_out,"\\("); break; case ')': fprintf(curr_out,"\\)"); break; case '%': fprintf(curr_out,"\\%%"); break; case '"': fprintf(curr_out,outstate?"\\272":"\\252"); outstate = !outstate; break; case '-': if (*(s+1) == '-') { fprintf(curr_out,"\\261"); s++; } else fputc('-',curr_out); break; case '.': if (*(s+1) == '.' && *(s+2) == '.') { fprintf(curr_out,"\\274"); s += 2; } else fputc('.',curr_out); break; case '\\': s++; if (*s >= '0' && *s <= '7' && *(s+1) >= '0' && *(s+1) <= '7' && *(s+2) >= '0' && *(s+2) <= '7') { fprintf(curr_out,"\\%c%c%c",*s,*(s+1),*(s+2)); s += 2; } else switch(*s) { case '\0': return; case '\\': fprintf(curr_out,"\\\\"); break; case 'r': fprintf(curr_out,"\\r"); break; case 'n': case ' ': fputc(' ',curr_out); break; case 't': fprintf(curr_out,"\\t"); break; case 'l': fprintf(curr_out,"\\243"); break; case '*': case 'b': fprintf(curr_out,"\\267"); break; case '-': fprintf(curr_out,"\\320"); break; default: fprintf(curr_out,"\\\\%c",*s); break; } break; default: fputc(*s,curr_out); }; s++; } } capitalize(s) char *s; { int firstofword; for (firstofword = 1; *s; s++) { if (firstofword && *s >= 'a' && *s <= 'z') { if (strncmp(s,"and ",4) && strncmp(s,"or ",3) && strncmp(s,"the ",4) && strncmp(s,"a ",2)) *s += 'A'-'a'; firstofword = 0; } else if (*s >= 'A' && *s <= 'Z') firstofword = 0; else if (*s == ' ' || *s == '-') firstofword = 1; } } leave(s) char *s; { fprintf(power_out,"\nFinished\n"); fclose(power_out); fprintf(flare_out,"\nFinished\n"); fclose(flare_out); fprintf(one_out,"\nFinished\n"); fclose(one_out); fprintf(stderr,"\n%s line %d: %s\n",filename,lineno,s); exit(1); } get_substring(s,d,term) char **s, *d, term; { while (**s == ' ') (*s)++; while (**s != term) { if (!**s) leave("Missing substring terminator (' ' or '.')\n"); *d = *(*s)++; d++; } *d = '\0'; } get_header() { char *s; fprintf(power_out,"\nStringsDict begin\n"); for (;;) { outstate = 0; while (line[0] == '\0') if (!getline()) break; if (line[0] != '#') break; s = &line[1]; while (*s && *s != ' ' && *s != '\t') s++; *s++ = '\0'; fprintf(power_out,"/Set%s (",&line[1]); while (*s == ' ' || *s == '\t') s++; outline(s); fprintf(power_out,") def\n"); line[0] = '\0'; } fprintf(power_out,"end\n"); } get_power_line() { char *s; int i; outstate = 0; while (line[0] == '\0') if (!getline()) return 0; s = line; get_substring(&s,name_buf,'\t'); fprintf(curr_out,"(%s)",name_buf); #if VERBOSE > 0 fprintf(stderr,"%s\n",name_buf); #endif while (*s && *s != '[') s++; if (*s++ != '[') leave("expected ["); if (*s == 'M') fprintf(curr_out," Mandatory "); else if (*s == 'O') fprintf(curr_out," Optional "); else if (*s == 'B') fprintf(curr_out," Both "); else leave("expected M, O, or B"); if (*++s != ':') leave("expected :"); for (i = 0, s++; *s && *s != ':' && *s != ']'; origin_buf[i++] = *s++) if (*s <= ' ' || *s > '~' || strchr("()<>[]{}/%",*s) != NULL) leave("illegal character in origin string"); if (!*s) leave("expected : or ] after origin string"); origin_buf[i] = '\0'; fprintf(curr_out,"Set%s ",origin_buf); if (*s == ':') { for (s++, i = 0; *s && *s != ']'; s++,i++) rest_buf[i] = *s; rest_buf[i] = '\0'; } else rest_buf[0] = '\0'; if (*s != ']') leave("expected ]"); s++; while (*s == ' ' || *s == '\t') s++; if (!*s) leave("expected brief description"); putc('(',curr_out); outline(s); putc(')',curr_out); line[0] = '\0'; return 1; } get_power_text() { char *s; int i; #if VERBOSE > 8 fprintf(stderr,"Of/To/Two/Etc.:\n"); #endif outstate = 0; while (line[0] == '\0') if (!getline()) leave("no power text"); if (strncmp(line,"You have the power ",19)) leave("no \"You have the power\""); s = line+19; while (*s && *s == ' ') s++; for (power_type = -1, i = 0; i < NPOWER_STRINGS; i++) { if (!strncmp(s,pw_str[i].search_string,pw_str[i].len)) { power_type = i; fprintf(curr_out," (power %s",pw_str[i].search_string); if (pw_str[i].len != 0) fprintf(curr_out," "); s += pw_str[i].len; break; } } if (power_type == -1) leave("no power to/of/over/etc."); get_substring(&s,power_buf,'.'); #ifdef CAPITALIZE capitalize(power_buf); #endif outline(power_buf); #if VERBOSE > 8 fprintf(stderr,"Text:\n"); #endif while (*s == '.' || *s == ' ') s++; fprintf(curr_out,")\n("); outline(s); while (getline()) { if (line[0] == '\0') { fprintf(curr_out,")\n"); return; } fprintf(curr_out," \\\n"); outline(line); } } get_paragraph(hdr,optional) char *hdr; int optional; { char *s; int hdrlen; static char errbuf[64]; #if VERBOSE > 8 fprintf(stderr,"%s\n",hdr); #endif outstate = 0; while (line[0] == '\0') if (!getline()) { sprintf(errbuf,"missing %s paragraph",hdr); leave(errbuf); } hdrlen = strlen(hdr); if (strncmp(line,hdr,hdrlen)) { if (optional) { fprintf(curr_out,"() "); return; } sprintf(errbuf,"no %s",hdr); leave(errbuf); } s = line+hdrlen; while (*s == ':' || *s == ' ') s++; fprintf(curr_out,"("); outline(s); while (getline()) { if (line[0] == '\0') break; fprintf(curr_out," \\\n"); outline(line); } line[0] = '\0'; fprintf(curr_out,")\n"); } get_flare(fp,s1,s2) FILE *fp; char *s1, *s2; { curr_out = fp; capitalize(power_buf); fprintf(curr_out,"(%s) [ %s (%s) ] (%s)\n",name_buf, pw_str[power_type].print_string, power_buf, rest_buf); get_paragraph(s1,0); get_paragraph(s2,0); fprintf(curr_out,"{} Flare\n"); }