/* formatb.c Version 1.8 of May 2002 doerry@aol.com */ /* Copyright (C) 1989-2002 Norbert H. Doerry 5 April 1989 This program formats a file for inclusion into a thesis. It is 12 pitch, a left margin of 1.25 inches, and 1 inch elsewhere centered at the bottom and .5 inches up, the page number will be printed. formatb [-page ##] [-h] [-f fontname] [input_file] [output_file] --------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --------------------------------------------------------------- **** Version 1.1: Modified 8 April 1989 ***** Added wrap, nopage, and simple options and multiple names for options -w ## or -wrap ## ## is the maximum number of characters per line if ## is omitted, use default of 62 characters -n or -nopage turns printing page number off -s or -simple only prints the line numbers, no dashes on either side. **** Version 1.2: Modified 11 April 1989 **** Fixed bug that wiped out last character in a line if it wasn't a new line. **** Version 1.3: Modified 21 April 1989 **** Added ability to vary point size of characters -P ## or -Pitch ## **** Version 1.4: Modified 25 Sept 1989 **** Eliminated output_file and allow for multiple input files changed -P option to -F changed -Pitch to -Fontheight added -oOutputfile option Added ability to print date in the upper right corner -t or -time Changed other options so arguments immediately follow command like most other unix commands. print error messages to stderr instead of stdout **** Version 1.5 of August 1992 Modified to remove warnings when compiling for MS-DOS systems **** Version 1.6 of August 1992 Added the ability to vary the number of lines per inch -l## or -lines## Broke the main() routine into a number of subroutines **** Version 1.7 of March 1993 Added the ability to print only certain pages of a file -[## :: Do not print pages before ## -]## :: Do not print pages after ## *** Version 1.7a of April 1993 Modified the treatment of tabs, tab stops are located every 8 characters instead of blindly substituting tabs with 8 characters *** Version 1.7b of December 1993 Updated Help Option *** Version 1.8 of June 2002 Combined all the source code into one file. Summary of options: -f##### or -font##### :: ##### is PostScript fontname -F## or -Fontheight## :: ## is font pitch in points (normally 12) -h or -header :: print input filename in upper left corner -l## or -lines## :: ## is number of lines per inch -n or -nopage :: suppress printing of page numbers -p## or -page## :: ## is starting page number -o##### :: ##### is output file -s or -simple :: Use simple format for printing line numbers -t or -time :: Print time in upper right corner -w## or -wrap## :: Wrap line after ## characters -[## :: Do not print all pages previous to ## -]## :: Do not print all pages after ## -help or -? :: Print out help ********* */ #include #include #include #include #include #define DEBUG 0 #define SYS 1 /* where SYS is set equal to one of the following constants or 0 for a generic case */ #define TTY 0 /* generic TTY terminal */ #define DOS 1 /* microsoft DOS */ #define XWIN 2 /* Unix X windows */ #define UNIX 3 /* Unix with TTY */ /* define __STDC__ if not already defined */ #if !defined __STDC__ #define __STDC__ 0 #endif /* define PTR to be of type void if standard C and char otherwise */ #if __STDC__ == 1 || SYS == DOS #define PTR void #define SIZ size_t #else #define PTR char #define SIZ unsigned #endif #if !defined __DATE__ #define __DATE__ "June 2002" #endif #define VERSION "1.8" #define LEFT 90.0 #define RIGHT 540.0 #define UP 720.0 #define DOWN 72.0 #define CENTER 306.0 #define PAGE_Y 36.0 #define DX 6.0 #define DY 12.0 #define XMIN 0.0 #define XMAX 612.0 #define YMIN 0.0 #define YMAX 792.0 static float x_min,x_max,y_min,y_max; static float xo , yo; static float font_height; static float scale; /* width is the x coordinate in inches, length is the y coordinate in inch */ /* scale is the default PS number of units per inch */ #define WIDTH 8.5 #define LENGTH 11.0 #define SCALE 72.0 #define LINE_THICKNESS 0.005 #if SYS == DOS #define NULL_FILE "NUL" #else #define NULL_FILE "null" #endif typedef struct Infile { char name[81]; struct Infile *next; } INFILE; struct Options { int page; int nopage; int wrap_mode; int header_page; int wrap; int simple; int time_mode; int start_page; int end_page; char fontname[81]; float pitch; float lines; char *time; char outfile[81]; FILE *outf; /* stream for writing to a file */ FILE *outn; /* stream for writing to a NULL device */ FILE *out; /* current stream writing too */ struct Infile *infile; } opt; #if SYS == DOS || __STDC__ == 1 void print_newpage(char *); void help(void); void write_line(char *,char *,float *,float *); void initialize(void); void read_commands(int ,char **); void write_file(FILE *,char *); void ps_window(float,float,float,float); void ps_init(FILE *,char *,float); void ps_move(float,float,FILE *); void ps_puts(char *,float,float,FILE *); #else void print_newpage(); void help(); void write_line(); void initialize(); void read_commands(); void write_file(); void ps_window(); void ps_init(); void ps_move(); void ps_puts(); #endif #if __STDC__ != 1 && SYS != DOS char Stofa(),Stoda(); #else char Stofa(char *,float * ,int *,int); char Stoda(char *,double *,int *,int); #endif #if SYS == DOS || __STDC__ == 1 int main(int argc,char **argv) #else int main(argc,argv) int argc; char **argv; #endif { FILE *in; INFILE *fil; in = (FILE *) NULL; /* force next line to be interpreted as a command, not a declaration */ initialize(); /* initialize all the parameters */ read_commands(argc,argv); /* update the parameters from the command line */ /* process the output file */ if (opt.outfile[0] == (char) NULL) /* if no output file, use stdout */ { opt.outf = stdout; strcpy(opt.outfile,"stdout"); } else opt.outf = fopen(opt.outfile,"w"); if (opt.outf == (FILE *) NULL) { fprintf(stderr," *** ERROR : unable to open file %s\n",opt.outfile); exit(EXIT_FAILURE); } /* open the Null File */ opt.outn = fopen(NULL_FILE,"w"); if (opt.outn == (FILE *) NULL && opt.start_page > 0 && opt.end_page > 0) { fprintf(stderr," *** ERROR : unable to open file %s\n",NULL_FILE); exit(EXIT_FAILURE); } /* initialize the output stream */ opt.out = (opt.start_page <= 1) ? opt.outf : opt.outn; /* if no input files were specified, use stdin */ if (opt.infile == (INFILE *) NULL) { opt.infile = (INFILE *) calloc((SIZ) 1, sizeof(INFILE)); if (opt.infile == (INFILE *) NULL) { fprintf(stderr,"\n *** ERROR: Out of Memory in main()\n"); exit(-1); } opt.infile->name[0] = (char) NULL; opt.infile->next = (INFILE *) NULL; } /* set up the postscript output file */ ps_window((float)XMIN,(float)XMAX,(float)YMIN,(float)YMAX); ps_init(opt.outf,"formatb",(float).01); /* set up the font correctly */ fprintf(opt.outf,"/%s findfont %g scalefont setfont\n", opt.fontname,opt.pitch); /* loop through all the files */ for (fil = opt.infile; fil != (INFILE *) NULL; fil = fil->next) { /* open input file for reading */ in = (fil->name[0] == (char) NULL) ? stdin : fopen(fil->name,"r"); write_file(in,fil->name); /* close the file */ if (in != stdin) fclose(in); } if (opt.outf != stdout) fclose(opt.outf); if (opt.outn != stdout) fclose(opt.outn); return(EXIT_SUCCESS); } #if SYS == DOS || __STDC__ == 1 void print_newpage(char *infile) #else void print_newpage(infile) char *infile #endif { char line[81]; if (opt.nopage) { /* print the line number */ if (opt.simple == 0) sprintf(line,"- %d -",opt.page); else sprintf(line,"%d",opt.page); ps_move((float)(CENTER - strlen(line)/2.0),(float)PAGE_Y,opt.out); ps_puts(line,(float)0.0,(float)12.0,opt.out); } if (opt.header_page) { /* print the filename */ ps_move((float) LEFT,(float)(UP + 30),opt.out); if (infile != (char *) NULL) ps_puts(infile,(float) 0.0,(float)12.0,opt.out); else ps_puts("stdin",(float)0.0,(float)12.0,opt.out); } if (opt.time_mode) { /* print the time */ ps_move((float)(RIGHT - 144.0) , (float)(UP + 30.0), opt.out); ps_puts(opt.time,(float)0.0,(float)12.0,opt.out); } /* print the showpage */ fprintf(opt.out,"s\n"); fprintf(opt.out,"showpage\n"); fprintf(opt.out,"n\n"); } #if SYS == DOS || __STDC__ == 1 void help(void) #else void help() #endif { /* this is the help function */ printf("\n\n Formatb\n\n Copyright (C) 1989-2002 Norbert H. Doerry\n\n"); printf(" Version %s <> Dated %s\n\n",VERSION,__DATE__); printf(" formatb [-options] [infile] [infile] \n\n"); printf(" Available options\n"); printf(" -fFontname :: specify PostScript font to use\n"); printf(" -F## :: font size in points (normally 12)\n"); printf(" -h :: print input filename in upper left corner\n"); printf(" -l## :: Number of lines per inch\n"); printf(" -p## :: start page number with ## \n"); printf(" -n :: suppress printing of page numbers\n"); printf(" -s :: use simple format for printing page numbers\n"); printf(" -t :: print time in upper right corner\n"); printf(" -w## :: wrap line after ## characters\n"); printf(" -oFilename :: Specify Output filename to use\n"); printf(" -help :: print out help information\n"); printf(" -[## :: start printing with this page\n"); printf(" -]## :: stop printing after this page\n"); printf("\n"); exit(0); } #if SYS == DOS || __STDC__ == 1 void write_line(char *outline,char *infile,float *x,float *y) #else void write_line(outline,infile,x,y) char *outline; char *infile; float *x,*y; #endif { char line[512]; int i,j,k; if (opt.wrap_mode == 0) /* no wrap */ { ps_move(*x,*y,opt.out); ps_puts(outline,(float) 0.0,(float) 12.0,opt.out); *y -= 72.0 / opt.lines; if (*y < (float) DOWN) { print_newpage(infile); *x = (float) LEFT; *y = (float) (UP - 72.0 / opt.lines); opt.page++; opt.out = ((opt.page >= opt.start_page) && (opt.end_page == 0 || opt.page <= opt.end_page)) ? opt.outf : opt.outn; } } else { /* write outline to line with at most 'wrap' characters at a time */ k = strlen(outline); j = 0; while (j < k) { for (i = 0 ; i < opt.wrap && j < k ; i++ , j++) line[i] = outline[j]; line[i] = (char) NULL; if (i == opt.wrap) { /* find first space working backwards */ for (i--; line[i] != ' ' && line[i] != '\t' && line[i] != '\n' && i != 0 ; i-- , j--); if (i != 0) line[++i] = (char) NULL; else j += opt.wrap - 1; } ps_move(*x,*y,opt.out); ps_puts(line,(float) 0.0,(float)12.0,opt.out); *y -= 72.0 / opt.lines; if (*y < (float) DOWN) { print_newpage(infile); *x = (float) LEFT; *y = (float) (UP - 72.0 / opt.lines); opt.page++; opt.out = ((opt.page >= opt.start_page) && (opt.end_page == 0 || opt.page <= opt.end_page)) ? opt.outf : opt.outn; } } } } #if SYS == DOS || __STDC__ == 1 void initialize(void) #else void initialize() #endif { time_t clock; opt.page = 1; /* starting page number */ opt.nopage = 1; /* default is with page numbers */ opt.wrap_mode = 0; /* do not wrap columns */ opt.header_page = 0; /* do not print filename as a header */ opt.wrap = 62; /* default for 10 cpi Courier */ opt.simple = 0; /* default is not simple */ opt.time_mode = 0; /* do not print time */ strcpy(opt.fontname,"Courier"); /* set the font type */ opt.pitch = (float) 12.0; /* default is 12 Point */ opt.lines = (float) (72.0 / DY); /* default number of lines per inch */ opt.start_page = 0; /* default to start with first page */ opt.end_page = 0; /* default to print to the end of the file */ /* set the date */ clock = time((time_t) NULL); opt.time = ctime(&clock); /* set the output filename to NULL */ opt.outfile[0] = (char) NULL; /* set the input file structure to NULL */ opt.infile = (INFILE *) NULL; } #if SYS == DOS || __STDC__ == 1 void read_commands(int argc,char **argv) #else void read_commands(argc,argv) int argc; char **argv; #endif { INFILE *inf,*lif; int argv_index; int k; float val = (float) 0.0; int ncnt; /* initialize */ argv_index = 0; /* pointer to entry in argv */ lif = (INFILE *) NULL; /* pointer to the last INFILE structure */ while (argc > ++argv_index) { /* see if start page option */ if (strncmp(argv[argv_index],"-p",2) == 0) { k = (strncmp(argv[argv_index],"-page",5) == 0) ? 5 : 2; Stofa(argv[argv_index] + k , &val, &ncnt, 1); if (ncnt == 1) opt.page = (int) floor ((double)(val + .5)); } else if (strncmp(argv[argv_index],"-F",2) == 0) { k = (strncmp(argv[argv_index],"-Fontheight",11) == 0) ? 11 : 2; Stofa(argv[argv_index] + k,&val,&ncnt,1); if (ncnt == 1 && val > (float) 0.0) opt.pitch = val; } else if (strncmp(argv[argv_index],"-l",2) == 0) { k = (strncmp(argv[argv_index],"-lines",6) == 0) ? 6 : 2; Stofa(argv[argv_index] + k,&val,&ncnt,1); if (ncnt == 1 && val > (float) 0.0) opt.lines= val; } else if (strcmp(argv[argv_index],"-nopage") == 0 || strcmp(argv[argv_index],"-n") == 0) { opt.nopage = 0; } else if (strcmp(argv[argv_index],"-header") == 0 || strcmp(argv[argv_index],"-h") == 0) { opt.header_page = 1; } else if (strncmp(argv[argv_index],"-w",2) == 0) { opt.wrap_mode = 1; k = (strncmp(argv[argv_index],"-wrap",5) == 0) ? 5: 2; Stofa(argv[argv_index] + k,&val,&ncnt,1); if (ncnt == 1 && val > (float) 0.5) opt.wrap = (int) floor((double)(val + .5)); } else if (strncmp(argv[argv_index],"-f",2) == 0) { k = (strncmp(argv[argv_index],"-font",5) == 0) ? 5: 2; if (*(argv[argv_index] + k) != (char) NULL) strcpy(opt.fontname,argv[argv_index]+k); } else if (strncmp(argv[argv_index],"-o",2) == 0) { k = 2; if (*(argv[argv_index] + k) != (char) NULL) strcpy(opt.outfile,argv[argv_index]+k); } else if (strcmp(argv[argv_index],"-simple") == 0 || strcmp(argv[argv_index],"-s") == 0) { opt.simple = 1; } else if (strcmp(argv[argv_index],"-time") == 0 || strcmp(argv[argv_index],"-t") == 0) { opt.time_mode = 1; } else if (strcmp(argv[argv_index],"-help") == 0 || strcmp(argv[argv_index],"-?") == 0) { help(); exit(0); } else if (strncmp(argv[argv_index],"-[",2) == 0) { Stofa(argv[argv_index] + 2,&val,&ncnt,1); if (ncnt == 1 && val > (float) 0.0) opt.start_page = (int)floor((double)(val+.5)); } else if (strncmp(argv[argv_index],"-]",2) == 0) { Stofa(argv[argv_index] + 2,&val,&ncnt,1); if (ncnt == 1 && val > (float) 0.0) opt.end_page = (int)floor((double)(val+.5)); } else if (argv[argv_index][0] == '-') { printf(" *** ERROR : illegal option %s\n",argv[argv_index]); exit(-1); } else /* its an input filename */ { inf = (INFILE *) calloc((SIZ)1, sizeof(INFILE)); if (inf == (INFILE *) NULL) { fprintf(stderr,"\n *** ERROR: Out of Memory in read_commands()\n"); exit(-1); } strcpy(inf->name,argv[argv_index]); inf->next = (INFILE *) NULL; /* terminate the linked list */ if (lif == (INFILE *) NULL) /* add entry to the linked list */ opt.infile = inf; else lif->next = inf; lif = inf; } } } #if SYS == DOS || __STDC__ == 1 void write_file(FILE *in,char *infile) #else void writ_file(in,infile) FILE *in; char *infile; #endif { float y,x; int i,j,k; char rdline[512],outline[512]; /* initialize 'cursor' */ y = (float) (UP - 72.0 / opt.lines); x = (float) LEFT; /* loop until input file is completely read in */ while(fgets(rdline,512,in) != NULL) { k = strlen(rdline) - 1; /* get rid of newline character */ if (rdline[k] == '\n') rdline[k] = (char) NULL; if (k == 0) { rdline[0] = ' '; rdline[1] = (char) NULL; } for (i = j = 0; rdline[i] != (char) NULL ; i++) { if (rdline[i] == '\t') { /* replace every tab with up to eight spaces */ for (k = j ; j < k + 8 && (j == k || j % 8 != 0) ; j++) outline[j] = ' '; } else if (rdline[i] == '\f') { /* got a form feed */ outline[j] = (char) NULL; write_line(outline,infile,&x,&y); print_newpage(infile); x = (float) LEFT; y = (float)(UP - DY); opt.page++; opt.out = ((opt.page >= opt.start_page) && (opt.end_page == 0 || opt.page <= opt.end_page)) ? opt.outf : opt.outn; j = 0; /* start over */ } else outline[j++] = rdline[i]; } outline[j] = (char) NULL; write_line(outline,infile,&x,&y); } /* print out a formfeed unless we're at the top of the page */ if (y != (float)(UP - 72.0 / opt.lines)) print_newpage(infile); } /* ps_init */ /* ps_init writes out the header information in the file */ #if SYS == DOS || __STDC__ == 1 void ps_init(FILE *out,char *string,float thickness) #else void ps_init(out,string,thickness) FILE *out; char *string; /* this is name to be printed in a comment section */ float thickness; /* this is the thickness of the lines in inches */ #endif { float x_range,y_range, x_scale, y_scale, xx_range,yy_range,thick; extern float xo,yo,x_min,y_min,x_max,y_max; extern float font_height; extern float scale; fprintf(out,"%%!PS-Adobe-1.0\n"); fprintf(out,"%% File produced by %s\n",string); fprintf(out,"/m {moveto} def\n"); fprintf(out,"/l {lineto} def\n"); fprintf(out,"/s {stroke} def\n"); fprintf(out,"/n {newpath} def\n"); fprintf(out,"2 setlinejoin\n"); /* sets the joint type to Bezel */ /* calculate scale parameters */ x_range = x_max - x_min; if (x_range <= (float) 0.0) x_range = (float) 1.0; y_range = y_max - y_min; if (y_range <= (float) 0.0) y_range = (float) 1.0; x_scale = (float) ((SCALE * WIDTH) / x_range); y_scale = (float) ((SCALE * LENGTH) / y_range); scale = (x_scale > y_scale) ? y_scale : x_scale; if (DEBUG != 0) { printf(" xmin = %g xmax = %g ymin = %g ymax = %g\n",x_min,x_max, y_min,y_max); printf(" xrange = %g yrange = %g\n",x_range,y_range); printf(" xscale = %g yscale = %g scale = %g\n",x_scale,y_scale,scale); } fprintf(out,"%g %g scale\n", scale , scale); /* calculate translation of origin */ /* these are the adjusted ranges */ xx_range = (float)(WIDTH * SCALE / scale); yy_range = (float)(LENGTH * SCALE / scale); /* this is the location of the origin */ xo = xx_range / 2.0 - x_range / 2.0 - x_min; yo = yy_range / 2.0 - y_range / 2.0 - y_min; fprintf(out,"%g %g translate\n",xo,yo); if (DEBUG != 0) { printf(" xx_range = %g yy_range = %g\n",xx_range,yy_range); printf(" xo = %g yo = %g\n",xo,yo); } /* set the line width */ thick = (thickness <= (float) 0.0) ? (float) (LINE_THICKNESS * SCALE / scale) : (float) (thickness * SCALE / scale); fprintf(out,"%g setlinewidth\n",thick); /* set the font height */ font_height = (float)(12.0 / scale); fprintf(out,"/Helvetica findfont %g scalefont setfont\n",font_height); /* start the new path */ fprintf(out,"n\n"); } /* ps_window sets the user coordinate system, this routine should be executed before ps_init is executed */ #if SYS == DOS || __STDC__ == 1 void ps_window(float xmin, float xmax,float ymin,float ymax) #else void ps_window(xmin,xmax,ymin,ymax) float xmin,xmax,ymin,ymax; #endif { extern float x_min,x_max,y_min,y_max; x_min = (xmin < xmax) ? xmin : xmax; x_max = (xmin > xmax) ? xmin : xmax; if (x_min == x_max) x_max += 1.0; y_min = (ymin < ymax) ? ymin : ymax; y_max = (ymin > ymax) ? ymin : ymax; if (y_min == y_max) y_max += 1.0; } /* ps_get_window returns the present coordinate system */ #if SYS == DOS || __STDC__ == 1 void ps_get_window(float *xmin,float *xmax,float *ymin,float *ymax) #else ps_get_window(xmin,xmax,ymin,ymax) float *xmin,*xmax,*ymin,*ymax; #endif { extern float x_min,x_max,y_min,y_max; *xmin = x_min; *xmax = x_max; *ymin = y_min; *ymax = y_max; } /* ps_move */ /* This routine moves the cursor to the argument passed to it */ #if SYS == DOS || __STDC__ == 1 void ps_move(float x,float y,FILE *out) #else void ps_move(x,y,out) float x,y; FILE *out; #endif { fprintf(out,"%g %g m\n",x,y); } /* ps_puts */ /* ps_puts will eventually allow one to print character strings in any orientation */ #if SYS == DOS || __STDC__ == 1 void ps_puts(char *string,float angle,float height,FILE *out) #else void ps_puts(string,angle,height,out) char *string; float angle; /* rotation angle in degrees */ float height; /* height in user coordinates */ FILE *out; #endif { extern float font_height; char line[131]; int i,j; /* copy the string and insert proper control characters */ for (i = j = 0 ; string[i] != (char) NULL && j < 130; i++,j++) { if (string[i] == '\\' || string[i] == '(' || string[i] == ')' || string[i] == '\n' || string[i] == '\r' || string[i] == '\b' || string[i] == '\t' || string[i] == '\f') { line[j++] = '\\'; if (string[i] == '\\') line[j] = '\\'; else if (string[i] == '(' || string[i] == ')') line[j] = string[i]; else if (string[i] == '\n') line[j] = 'n'; else if (string[i] == '\r') line[j] = 'r'; else if (string[i] == '\b') line[j] = 'b'; else if (string[i] == '\t') line[j] = 't'; else if (string[i] == '\f') line[j] = 'f'; } else line[j] = string[i]; } line[j] = (char) NULL; if (angle != 0) fprintf(out,"%g rotate\n",angle); if (font_height != height) { font_height = height; fprintf(out,"/Helvetica findfont "); fprintf(out,"%g scalefont setfont\n",height); } fprintf(out,"(%s) show\n",line); if (angle != 0) fprintf(out,"%g rotate\n",-angle); } #define MAX_EXP 38 /* maximum sized exponent for system */ /* Stofa */ /* NHD Stofa is like Stoda except that fltaptr is of type (float *) */ #if __STDC__ != 1 && SYS != DOS char Stofa(rdline,fltaptr,nbrptr,maxnum) char *rdline; /* input string */ float *fltaptr; /* output array of numbers */ int *nbrptr; /* output number of elements in fltaptr */ int maxnum; /* input maximum number of elements in fltaptr */ #else char Stofa(char *rdline, float *fltaptr, int *nbrptr, int maxnum) #endif { double *dptr; char ch; int i; /* error checking */ if (maxnum <= 0) return (char) NULL; /* initialize */ fltaptr[0] = (float) 0.0; /* allocate an array of double precision numbers */ dptr = (double *) calloc((SIZ)maxnum, sizeof(double)); if (dptr == (double *) NULL) return (char) NULL; /* call Stoda */ ch = Stoda(rdline,dptr,nbrptr,maxnum); /* copy dptr to fltaptr */ for (i = 0 ; i < *nbrptr ; i++) fltaptr[i] = (float) dptr[i]; /* free dptr */ free((PTR *) dptr); return ch; } /* Stoda converts a string to an array of floating point numbers passes back the array and the number of numbers successfully converted. The returned value is a zero if read successfullly to end of line, otherwise, returns the character that reading failed at. The fourth argument passed to the function is the maximum number of elements in the array */ #if __STDC__ != 1 && SYS != DOS char Stoda(string,fltaptr,nbrptr,maxlen) char *string; /* input: string */ double *fltaptr; /* output: array of floating point numbers */ int *nbrptr; /* output: number of elements converted */ int maxlen; /* input: maximum nbr of elements in fltaptr */ #else char Stoda(char *string, double *fltaptr, int *nbrptr, int maxlen) #endif { int sign; /* sign of the number */ int index = 0; double power; int i; char ch; double inch; /* used when ft-inch entries used */ int exponent,exp_sign; /* error checking */ if (maxlen <= 0) return (char) NULL; /* initialize the first reurn number to zero */ *nbrptr = 0; /* strip off leading blanks and tabs */ while ((ch=string[index++]) == ' ' || ch == '\t'); /* convert the numbers */ while ((ch >= '0' && ch <= '9') || ch == '.' || ch == '+' || ch == '-' || ch == ',' || ch == ';' || ch == ':' || ch == 'e' || ch == 'E') { sign = 1; /* default is positive */ power = 10.0; /* used for dividing after hitting decimal point */ exponent = 0; /* existing level of the exponent */ exp_sign = 1; /* exponent is assumed positive */ /* check for the sign */ if ( ch == '-' || ch == '+') { sign = (ch == '-') ? -1 : 1; ch = string[index++]; } fltaptr[*nbrptr] = 0.0; /* initialize value */ while (ch >= '0' && ch <= '9') { fltaptr[*nbrptr] *= 10.0; fltaptr[*nbrptr] += (double) (ch - '0'); ch = string[index++]; } if (ch == '.') /* check for decimal point */ { while ((ch = string[index++]) >= '0' && ch <= '9') { fltaptr[*nbrptr] += (double) (ch - '0') / power; power *= 10.0; } } else if (ch == '-') /* check for ft-in entry */ { if ((ch = string[index++]) >= '0' && ch <= '9') { inch = (double) (ch - '0'); /* see if 10 or 11 inches */ if (inch == 1.0) { if ((ch = string[index++]) == '0' || ch == '1') { inch *= 10.0; inch += (double)(ch - '0'); } else index--; } power = 10.0; if ((ch = string[index++]) == '.') /* ft-decimal inch */ { while ((ch = string[index++]) >= '0' && ch <= '9') { inch += (double) (ch - '0') / power; power *= 10.0; } } else if (ch == '-') /* ft-inch-eighth */ { if ((ch = string[index++]) >= '0' && ch <= '7') { inch += (double)(ch - '0') / 8.0; if ((ch = string[index++]) == '.') { while ((ch = string[index++]) >= '0' && ch <= '9') { inch += (double) (ch - '0') / (8.0 * power); power *= 10.0; } } } } fltaptr[*nbrptr] += inch / 12.0; } } /* check for exponent */ if (ch == 'e' || ch == 'E') { /* if the mantissa is not specified but an exponent was specified set the mantissa to 1.0 */ if (fltaptr[*nbrptr] == 0 && string[index - 2] != '0' && string[index - 2] != '.') fltaptr[*nbrptr] = 1.0; /* get the next character */ ch = string[index++]; exp_sign = 1; power = 10.0; /* get the sign of the exponent */ if ( ch == '-' || ch == '+') { exp_sign = (ch == '-') ? -1 : 1; ch = string[index++]; } /* get the actual exponent value */ exponent = 0; /* initialize value */ while (ch >= '0' && ch <= '9') { exponent *= 10; exponent += (int) (ch - '0'); ch = string[index++]; } } /* ensure exponent is not too large */ /* MAX_EXP is the max size of an exponent (1e+MAX_EXP is legal)*/ exponent *= exp_sign; /* give the exponent its proper sign */ /* normalize the expression so the mantissa is between 0 and 1 and the exponent adjusted accordingly */ while(fltaptr[*nbrptr] > 1.0) { fltaptr[*nbrptr] /= 10.0; exponent++; } while(fltaptr[*nbrptr] < 0.0) { fltaptr[*nbrptr] *= 10.0; exponent--; } /* determine the exponent sign again */ exp_sign = (exponent < 0) ? -1 : 1; /* determine the exponent magnitude */ exponent = (exponent < 0) ? -exponent : exponent; /* see if the exponent exceeds the maximum */ if (exponent > MAX_EXP) { exponent = MAX_EXP; fltaptr[*nbrptr] = (exp_sign == -1) ? 0.0 : 1.0; } /* multiply number by its exponent */ power = (exp_sign == -1) ? 0.1 : 10.0; for (i = 0 ; i < exponent ; i++) fltaptr[*nbrptr] *= power; /* multiply number by its sign */ fltaptr[*nbrptr] *= (double) sign; (*nbrptr)++; /* stop if converted maximum number of elements */ if (*nbrptr == maxlen) break; /* see if illegal character following a legal number */ if (ch == '-' || ch == '+' || ch == '8' || ch == '9' || ch == '.') break; /* ignore delimiting spaces */ while (ch == ' ' || ch == '\t') ch = string[index++]; /* ignore delimiting : ; , */ if ( ch == ':' || ch == ';' || ch ==',' ) while ((ch = string[index++]) == ' ' || ch == '\t'); /* interpret successive : : , as zero entries in the array */ while ( ch == ':' || ch == ';' || ch ==',' ) { if (*nbrptr < maxlen) { fltaptr[*nbrptr] = 0.0; (*nbrptr)++; } else break; while((ch = string[index++]) == ' ' || ch == '\t'); } } return (char) ch; }