/* * Last edited on 2009-02-10 09:06:27 by stolfi * * LISTSERV-Punch C conversion program, version number 02 * * Written by Eric Thomas * * * This public domain program has been tested on a VM system with the * huge BITEARN NODES file as input (over 23,000 LISTSERV-Punch format * records), as well as several other smaller files. No problem has * been encountered in the testing phase. * * The working version of the program has been electronically copied * into the document you are reading, untouched. There can therefore * be no keying error, or then it was in the original program too and * was not detected during the testing period. * * * Synopsis: * * The input file from LISTSERV is assumed to be the standard input. * * Output is directed to the standard output, but the program is * structured in such a way that this can be easily changed. * * * Problems: * * Send problem or bug reports to . * Philosophical lectures about the grandiose organization of C and * how it has been violated in this program should be directly * forwarded to /dev/null for a prompt answer. * */ #include #include void Substr(char *outstring, char *instring, int start, int length); /* This function does not have to be tailored */ void Getcard(char *string); /* This function must read one 80-chars line (one "card") from input and return it as result. A premature EOF is an error and must cause termination of the program. The result must be EXACTLY 80 characters in length */ void Dec2bin(int *result, char *string); /* This function does not have to be tailored */ void Openout(char *fn, char *ft); /* This procedure must open the output file under whatever file-id you may choose. */ void Closeout(void); /* This procedure must close the output file. Errors should be detected since they can mean a disk-full condition while writing the last buffer, or suchlike */ void Gobbleword(char *inpstring, char *outstring); /* This function should be left "as is" */ void Writeout(char *string, int *lenptr); /* This function does not have to be tailored */ int main(int argc, char **argv); /* Main program -- nothing needs to be changed */ char card[81], /* Input record image */ filename[9], filetype[9], number[6], /* Scratch string to hold a number */ recfm; int i,ncards,lrecl,xlrecl; FILE *outfile; void Substr(char *outstring, char *instring, int start, int length) { register int rd=0,wr=0; register char c; --start; while(rd < start) { if (instring[rd++]=='\0') { outstring=""; return; } } while(length-- > 0) { if ((c=instring[rd++]) != '\0') outstring[wr++]=c; else break; } outstring[wr]='\0'; return; } void Getcard(char *string) { register int i=0,c; while(i < 80) { if (((c=getchar()) != EOF) && (c != '\n')) string[i++]=c; else break; } if (c == EOF) { fprintf(stderr,"Premature EOF on input.\n"); exit(100); } if (i==80) { if (getchar() != '\n') { fprintf(stderr,"Input file contains records larger than 80.\n"); exit(100); } } while (i < 80) { string[i++]=' '; } string[i]='\0'; return; } void Dec2bin(int *result, char *string) { if (sscanf(string,"%d",result) != 0) return; fprintf(stderr,"Invalid decimal argument -- '%s'.\n",string); exit(100); } void Openout(char *fn, char *ft) { /* Our implementation uses standard output as file pointer */ outfile=stdout; /* The following instruction must be uncommented for use under most VM C's if the output file is to have a lrecl > 80 */ /* outfile=fopen("LPUNCH OUTPUT A (recfm v lrecl 65535","w"); */ return; } void Closeout(void) { /* The chosen implementation does nothing and relies on the operating system to close the standard output file. This is not good programming practice but at least it's transportable. */ return; } void Gobbleword(char *inpstring, char *outstring) { register int rd=0,wr=0; while (inpstring[rd] != '/') { outstring[wr++]=inpstring[rd++]; } outstring[wr]='\0'; for(wr=0;inpstring[++rd] != '\0';) { inpstring[wr++]=inpstring[rd]; } inpstring[wr]='\0'; return; } void Writeout(char *string, int *lenptr) { int i=0; while((string[i] != '\0') && ( *lenptr > 0)) { putc(string[i++],outfile); --( *lenptr); } } int main(int argc, char **argv) { do { /* Read up to and including 'ID/' card */ Getcard(card); } while ((card[0]!='I') || (card[1]!='D') || (card[2]!='/')); Substr(filename,card,4,8); Substr(filetype,card,13,8); recfm=card[21]; Substr(number,card,24,5); Dec2bin(&lrecl,number); Openout(filename,filetype); for (;;) { Getcard(card); if ((card[0]=='E') && (card[1]=='N') && (card[2]=='D') && (card[3]=='/')) break; if (recfm=='V') { Gobbleword(card,number); Dec2bin(&xlrecl,number); } else xlrecl=lrecl; Gobbleword(card,number); Dec2bin(&ncards,number); do { Writeout(card,&xlrecl); if (--ncards != 0) Getcard(card); } while(ncards!=0); for(i=1;i <= xlrecl;i++) { putc(' ',outfile); } putc('\n',outfile); } Closeout(); return 0; }