/* parser.c Version 1.7 COPYRIGHT (C) 1996-2002 Norbert H. Doerry PARSER SYNTAX: PARSER Infile [-oOutfile] [-pProfile] [-tTestField] [-?] Infile Name of the input filename Outfile Name of the output filename (stdout if omitted) Profile Name of the Profile File name (uses parser.ini if omitted) TestField Name of a single field to print to screen to test the record_length and field position. PARSER is used to extract information from a database file consisting of fixed length records. The Profile file describes the field layout of the input file and describes how those fields should be presented in the output file. The format of the Profile file is [parser] print_column_names 0 ! 1 for yes, 0 for no ! field_delimiter 22 ! ascii code(s) in hex for the field delimiter ! for the output file (max 31 codes) ! record_delimiter 0A 0D ! ascii code(s) in hex for the record delimiter ! for the output file (max 31 codes) ! start_of_text_char 34 ! ascii code(s) in hex to mark the start of text ! for the output file (max 31 codes) ! end_of_text_char 34 ! ascii code(s) in hex to mark the end of text ! for the output file (max 31 codes) record_length 275 ! number of characters in a record of the ! input file field [name] [start position] [length] [TEXT or NUMBER] [print order] field [name] [start position] [legnth] [TEXT or NUMBER] [print order] [eof] ! end of file: all data following is ignored Revision History Version 1.0: April 1996 Norbert Doerry Intitial Release Version 1.0a: April 15, 1996 Norbert Doerry Fixed printing of header row Version 1.1: April 18, 1996 Norbert Doerry Added following commands to parser.ini: strip [field_name] ! eliminates leading and trailing white spaces reorder [field_name] 5 6 $c $D 3 4 ! reorders the bytes, in this case ! print the 5th byte first, then ! the 6th, then prints the character ! 'c' then the character 'D' then the ! 3rd byte, and finally the 4th byte delete_char [field_name] [char] ! deletes the character specified ! from the named field, to delete ! whitespaces or other non printing ! characters, use the normal \ commands ! To delete spaces, use \ followed by ! a space. Note, the commands are executed in the following order: - reorder - strip - delete_char Version 1.1a: April 22, 1996 Norbert Doerry Fixed a few bugs: Inability to set NULL string for end of text char Writing last line twice, 2nd time with errors Version 1.1b: December 1996 Norbert Doerry Fixed error with delete_char: would not delete repeated characters Version 1.2: December 27, 1996 Norbert Doerry Added more commands to parser.ini delete_alpha [field_name] ! deletes all alphabetic characters delete_nonalpha [field_name] ! deletes all non-alphabetic characters delete_numeric [field_name] ! deletes all number characters delete_nonnumeric [field_name] ! deletes all non-numeric characters delete_left [field_name] [nbr] ! deletes the 1st nbr characters delete_right [field_name] [nbr] ! deletes the last nbr characters keep_left [field_name] [nbr] ! keeps the left nbr characters keep_right [field_name] [nbr] ! keeps the right nbr characters insert_left [field_name] [string] ! insert the string before the field insert_right [field_name] [string] ! insert the string after the field replace_char [field_name] [old_char] [new_char] ! replace old_char with new_char The order that the functions are performed on the field is now the same as the order listed in the parser.ini file. The format for all characters is one of the following Hexadecimal: 0A ! two digit with out a prefix ASCII: $A ! the Ascii character A Control $\n ! Special character (New line in this case Created a new structure: Field_Function Eliminated the structure: Field Modified the structure: Field_Description Modified the structure: Parser added the -t option to enable testing the file to make sure the record length and field positions are accurate. Version 1.3: December 31, 1996 Combined the functions of parserf.exe added the following commands record_per_file 1 ! = 0 (default) ! then filename_field is ignored ! and all records are written to ! the command line parameter OUTFILE ! = 1 ! then OUTFILE command line ! parameter is ignored. The ! record_delimiter command is also ! ignored. ! Each record is written to a file whose ! base filename is set to the field ! specified by filename_field. ! It the file already exists, then ! the contents of the file are ! overwritten. filename_field [field_name] ! name of field to base filename on. Version 1.4: January 1997 added following commands: field_text [name] [string] [print_order] field_counter [name] [print_order] field_filename_field [name] [print_order] field_lookup [name] [look_up_field] [filename] [column] [print_order] field_date [name] [print_order] field_time [name] [print_order] Version 1.5: February 1997 added support for field delimited input files, creating HTML output files, and converting text to upper or lower case specifically added following commands: delimited_field [field_delimiter] [text_delimiter] fixed_field output_text output_html to_upper_case [name] to_lower_case [name] replace_text [field] [original_tex] [replacement_text] Also added the printing of dots to indicate progress Version 1.6: August 1997 allowed a record_length of 0 to indicate that records are delimited by newline characters. Use DEFAULTRECORDLENGTH as the maximum length of a line. Version 1.6a: August 1998 Fixed minor bug when record_length = 0 and reading the last line of a file. Version 1.7: June 2002 Added GNU GPL and recompiled on 32 bit compiler --------------------------------------------------------------- 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. --------------------------------------------------------------- If you discover any bugs, or have any questions concerning these programs, please send me an email (doerry@aol.com) */ #define REVISION "1.7" #include #include #include #include #include #include #define DEFAULTRECORDLENGTH 1023 /* values for FIELD_DESCRIPTION field_type element */ #define FIELD_UNDEFINED 0 #define FIELD_NORMAL 1 #define FIELD_TEXT 2 #define FIELD_COUNTER 3 #define FIELD_FILENAME_FIELD 4 #define FIELD_LOOKUP 5 #define FIELD_DATE 6 #define FIELD_TIME 7 #define CALCULATE_UNDEFINED 0 #define CALCULATE_NO 1 #define CALCULATE_WORKING 2 #define CALCULATE_YES 3 typedef struct Field_Description { char *name; int calculate_flag; /* */ int field_type; int start_position; int length; int type; /* TEXT or NUMBER or STRING */ int print_order; char *data; /* array for holding the data */ char *arg1; /* arrays for holding arguments */ struct Field_Description *field_lookup; /* field description for field_lookup */ FILE *fluf; /* input stream for field_lookup */ int data_length; /* length of the array */ struct Field_Function *ff; /* linked list of functions to perform on field */ struct Field_Description *next; /* next link in the linked list */ } FIELD_DESCRIPTION; #define FUNCTION_UNDEFINED 0 #define FUNCTION_STRIP 1 #define FUNCTION_REORDER 2 #define FUNCTION_DELETE_CHAR 3 #define FUNCTION_DELETE_LEFT 4 #define FUNCTION_DELETE_RIGHT 5 #define FUNCTION_DELETE_ALPHA 6 #define FUNCTION_DELETE_NONALPHA 7 #define FUNCTION_DELETE_NUMERIC 8 #define FUNCTION_DELETE_NONNUMERIC 9 #define FUNCTION_KEEP_LEFT 10 #define FUNCTION_KEEP_RIGHT 11 #define FUNCTION_INSERT_LEFT 12 #define FUNCTION_INSERT_RIGHT 13 #define FUNCTION_REPLACE_CHAR 14 #define FUNCTION_PAD_LEFT 15 #define FUNCTION_PAD_RIGHT 16 #define FUNCTION_TO_UPPER_CASE 17 #define FUNCTION_TO_LOWER_CASE 18 #define FUNCTION_REPLACE_TEXT 19 typedef struct Field_Function { int type; /* code for the function */ int arg; /* argument for the function or the number of element in array */ int *array; /* argument string */ struct Field_Function *next; } FIELD_FUNCTION; #define FILE_FIXED 0 #define FILE_DELIMITED 1 #define OUTPUT_TEXT 0 #define OUTPUT_HTML 1 typedef struct Parser { char infile[81]; char outfile[81]; char profile[81]; FILE *in; FILE *out; FILE *pro; char test_field[81]; /* used for -t option */ struct Field_Description *test_fd; char filename_field[81]; /* added in Version 1.3 */ int input_file_type; /* FILE_FIXED or FILE_DELIMITED: new for 1.5 */ char input_field_delimiter; /* new for version 1.5 */ char input_text_delimiter; /* new for version 1.5 */ int output_format; /* OUTPUT_TEXT or OUTPUT_HTML: new for 1.5 */ struct Field_Description *filename_fd; int record_per_file; int record_cnt; /* counter for records */ char *record; /* the current record being read in */ int nbr_field; /* for delimited files, the number of fields to read in */ char **ptr_field; /* an array of pointers to record elements to indicate the start of a field for delimited files */ int print_column_names; char field_delimiter[32]; char record_delimiter[32]; char start_of_text_char[32]; char end_of_text_char[32]; int record_length; struct Field_Description *fd; /* linked list of field descriptions */ char string_date[11]; /* format: mm/dd/yyyy */ char string_time[9]; /* format: hh:mm:ss */ int debug; } PARSER; #define TEXT 0 #define NUMBER 1 #define STRING 2 /* declare functions */ void initialize_data(PARSER *); void process_cmd_line(PARSER *,char *); void post_process(PARSER *); void read_profile(PARSER *); int read_profile_reorder(PARSER *,char *,int); FIELD_FUNCTION *read_profile_field_function(PARSER *,char *,int); FIELD_DESCRIPTION *read_profile_field(PARSER *,char *,int); void read_write(PARSER *); void read_delimited_record(PARSER *); void read_record(PARSER *); void process_record(PARSER *); void process_field(PARSER *,FIELD_DESCRIPTION *); void process_field_lookup(PARSER *, FIELD_DESCRIPTION *); void process_field_function(PARSER *,FIELD_DESCRIPTION *,FIELD_FUNCTION *); void write_record(PARSER *); void write_record_file(PARSER *); void clean_up(PARSER *); void print_help(void); void print_debug(PARSER *); FIELD_DESCRIPTION *alloc_Field_Description(void); FIELD_DESCRIPTION *find_field_description(FIELD_DESCRIPTION *,char *); char astoc(char *,char **); void strstrip(char *); char stoc(char *,char **); int chtoi(char); void print_field_function(FIELD_FUNCTION *,FIELD_DESCRIPTION *,FILE *); void print_array(int *,int,FILE *); void print_arg(int,FILE *); void convert_escape_string(char *); void extract_filename_base(char *, char *) ; /* start of the program */ int main(int argc, char **argv) { PARSER p; int i; /* intialize the PARSER structure */ initialize_data(&p); /* process the command line arguments */ for (i=1 ; i < argc ; i++) process_cmd_line(&p,argv[i]); /* post process the command line arguments, set everything up */ post_process(&p); /* do the actual work */ read_write(&p); /* close the files and finish everything */ clean_up(&p); return EXIT_SUCCESS; } void initialize_data(PARSER *p) { struct tm *tptr; time_t t; p->infile[0] = (char) NULL; p->outfile[0] = (char) NULL; strcpy(p->profile,"parser.ini"); p->in = (FILE *) NULL; p->out = stdout; p->pro = (FILE *) NULL; p->test_field[0] = (char) NULL; p->test_fd = (FIELD_DESCRIPTION *) NULL; p->output_format = OUTPUT_TEXT; p->input_file_type = FILE_FIXED; p->input_field_delimiter = ','; p->input_text_delimiter = '"'; p->filename_field[0] = (char) NULL; p->filename_fd = (FIELD_DESCRIPTION *) NULL; p->record_per_file = 0; p->record_cnt = 0; p->record = (char *) NULL; /* the current record being read in */ p->nbr_field = 0; p->ptr_field = (char **) NULL; p->print_column_names = 0; strcpy(p->field_delimiter,","); strcpy(p->record_delimiter,"\n"); strcpy(p->start_of_text_char,"\""); strcpy(p->end_of_text_char,"\""); p->record_length = 0; p->fd = (FIELD_DESCRIPTION *) NULL; /* linked list of field descriptions */ t = time((time_t *) NULL); tptr = localtime(&t); strftime(p->string_date,11,"%m/%d/%Y",tptr); strftime(p->string_time,9,"%X",tptr); p->debug = 0; } void process_cmd_line(PARSER *p,char *cmd) { if (p->debug) printf("%s\n",cmd); if (cmd[0] == '-' || cmd[0] == '/') { if (cmd[1] == 'o' || cmd[1] == 'O') { strcpy(p->outfile,cmd+2); } else if (cmd[1] == 'p' || cmd[1] == 'P') { strcpy(p->profile,cmd+2); } else if (cmd[1] == '?' || cmd[1] == 'h' || cmd[1] == 'H') { print_help(); exit(EXIT_SUCCESS); } else if (cmd[1] == 'd' || cmd[1] == 'D') { p->debug = 1; } else if (cmd[1] == 't' || cmd[1] == 'T') { strcpy(p->test_field,cmd+2); } else { fprintf(stderr,"\n *** ERROR : Syntax Error\n"); print_help(); exit(EXIT_FAILURE); } } else if (p->infile[0] == (char) NULL) { /* input file specified */ strcpy(p->infile,cmd); /* copy the filename */ p->in = fopen(cmd,"rt"); /* try to open the file */ if (p->in == (FILE *) NULL) /* if can't, print an error and exit */ { fprintf(stderr,"\n *** ERROR: Can not open file (%s)\n",cmd); exit(EXIT_FAILURE); } } else { /* error, multiple input files listed */ fprintf(stderr,"\n *** ERROR: SYNTAX ERROR, ARGUMENT (%s)\n",cmd); exit(EXIT_FAILURE); } } void post_process(PARSER *p) { FIELD_DESCRIPTION *fd; int ival; int record_length; int recalculate_flag; if (p->debug) printf("Enter post_process()\n"); /* try to open the profile */ p->pro = fopen(p->profile,"rt"); if (p->pro == (FILE *) NULL) { fprintf(stderr,"\n *** ERROR : Unable to open Profile file (%s)\n", p->profile); exit(EXIT_FAILURE); } /* read the profile */ if (p->debug) printf("Enter read_profile()\n"); read_profile(p); if (p->debug) printf("Complete read_profile()\n"); /* close the profile file */ if (p->pro != stdin) fclose(p->pro); /* make sure the input file exists */ if (p->in == (FILE *) NULL) { fprintf(stderr," *** ERROR: Input file not specified\n"); exit(EXIT_FAILURE); } /* try to open the output file */ if (p->record_per_file == 0) { if (p->debug) printf("Opening Output File\n"); if (p->outfile[0] != (char) NULL && p->test_field[0] == (char) NULL) { p->out = fopen(p->outfile,"wt"); if (p->out == (FILE *) NULL) { fprintf(stderr,"\n *** ERROR : Unable to open Output file (%s)\n", p->outfile); exit(EXIT_FAILURE); } } else { p->out = stdout; strcpy(p->outfile,""); } if (p->debug) printf("Completed Opening Output File\n"); } /* otherwise printing a record per file, see if a field is specified */ else if (p->filename_field[0] != (char) NULL) { /* look for the record_per_file */ p->filename_fd = find_field_description(p->fd,p->filename_field); if (p->filename_fd == (FIELD_DESCRIPTION *) NULL) { fprintf(stderr," *** ERROR: filename_field %s not defined\n", p->filename_field); exit(EXIT_FAILURE); } } /* check for a test field */ if (p->test_field[0] != (char) NULL) { if (p->debug) printf("Looking for Test Field\n"); fd = find_field_description(p->fd,p->test_field); if (fd == (FIELD_DESCRIPTION *) NULL) { fprintf(stderr," *** ERROR: Command Line Test Field %s not defined\n", p->test_field); exit(EXIT_FAILURE); } p->test_fd = p->fd; p->fd = (FIELD_DESCRIPTION *) calloc((size_t) 1, sizeof(FIELD_DESCRIPTION)); if (p->fd == (FIELD_DESCRIPTION *) NULL) { fprintf(stderr," *** ERROR: Out of Memory in post_process\n"); exit(EXIT_FAILURE); } p->fd->name = fd->name; p->fd->start_position = fd->start_position; p->fd->length = fd->length; p->fd->type = fd->type; p->fd->print_order = 1; p->fd->data = (char *) NULL; p->fd->data_length = fd->data_length; p->fd->ff = fd->ff; p->fd->next = (FIELD_DESCRIPTION *) NULL; if (p->debug) printf("Found Test Field\n"); p->record_per_file = 0; /* don't create a record for each file */ } /* allocate data arrays for the field_descriptions */ for (fd = p->fd ; fd != (FIELD_DESCRIPTION *) NULL ; fd = fd->next) { /* the data field is the longer of the source or destination field */ ival = (fd->length > fd->data_length) ? fd->length : fd->data_length; fd->data = (char *) calloc((size_t)(ival + 1), sizeof(char)); if (fd->data == (char *) NULL) { fprintf(stderr,"\n *** ERROR : Out of memory\n"); exit(EXIT_FAILURE); } } /* allocate the data record variable */ record_length = (p->record_length > 0) ? p->record_length : DEFAULTRECORDLENGTH; p->record = (char *)calloc((size_t)(record_length+1),sizeof(char)); if (p->record == (char *) NULL) { fprintf(stderr,"\n *** ERROR : Out of Memory\n"); exit(EXIT_FAILURE); } /* allocate the array of pointers for the delimited fields */ if (p->input_file_type == FILE_DELIMITED) { p->ptr_field = (char **) calloc((size_t)p->nbr_field+1,sizeof(char *)); if (p->ptr_field == (char **) NULL) { fprintf(stderr,"\n *** ERROR : Out of memory\n"); exit(EXIT_FAILURE); } } if (p->debug) print_debug(p); } void read_profile(PARSER *p) { char rdline[256]; char c; char *rd,*nrd; /* pointers for processing the line */ int start_flag = 0; /* flag that says we started the [parser] section */ int error_flag = 0; /* flag that indicates an error was encountered */ int lcnt = 0; /* counter for the line number in the profile file */ int i; /* local counter */ FIELD_DESCRIPTION *bfd,*fd; while (fgets(rdline,255,p->pro)) { rd = rdline; /* initialize the line pointer */ lcnt++; /* increment the line counter */ /* ignore leading whitespace characters */ strstrip(rd); /* see if blank line */ if (*rd == (char) NULL) continue; /* see if a comment */ if (*rd == '!' || *rd == '#') continue; /* if we haven't done so, look for the start of the [parser] section */ if (start_flag == 0) { if (strncmp(rd,"[parser]",8) == 0) start_flag = 1; continue; } /* see if we are at the end of the file */ if (*rd == '[') break; /* print the line if debug is set */ if (p->debug) printf("[%s]\n",lcnt,rd); /* otherwise its a command in the [parser] block */ if (strncmp(rd,"print_column_names",18) == 0) { rd += 18; /* start looking at the arguments */ while (isspace(*rd)) rd++; /* skip white spaces */ if (*rd == '0' || *rd == (char) NULL || *rd == '!') p->print_column_names = 0; else p->print_column_names = 1; } else if (strncmp(rd,"output_text",11) == 0) { p->output_format = OUTPUT_TEXT; } else if (strncmp(rd,"output_html",11) == 0) { p->output_format = OUTPUT_HTML; } else if (strncmp(rd,"fixed_field",11) == 0) { p->input_file_type = FILE_FIXED; } else if (strncmp(rd,"delimited_field",15) == 0) { p->input_file_type = FILE_DELIMITED; rd += 15; while (isspace(*rd)) rd++; /* skip white spaces */ if (*rd == (char) NULL || *rd == '!') continue; /* use previous values if field delimiter not specified */ p->input_field_delimiter = stoc(rd,&rd); while (isspace(*rd)) rd++; /* skip white spaces */ if (*rd == (char) NULL || *rd == '!') continue; /* use previous values if text delimiter not specified */ p->input_text_delimiter = stoc(rd,&rd); } else if (strncmp(rd,"record_per_file",15) == 0) { rd += 15; while (isspace((int) *rd)) rd++; /* skip white spaces */ if (*rd == '0' || *rd == (char) NULL || *rd == '!') p->record_per_file = 0; else p->record_per_file = 1; } else if (strncmp(rd,"filename_field",14) == 0) { rd += 14; while(isspace((int) *rd)) rd++; /* skip white spaces */ /* copy the first argument */ for (i=0 ; rd[i] != (char) NULL && isspace((int)rd[i]) == 0 && i < 80 ; i++) p->filename_field[i] = rd[i]; p->filename_field[i] = (char) NULL; } else if (strncmp(rd,"field_delimiter",15) == 0) { rd += 15; /* start looking at the arguments */ i=0; /* counter & index for the arguments */ p->field_delimiter[0] = (char) NULL; /* reset string */ while (*rd != (char) NULL) { if (*rd == '!') break; /* ignore comments */ p->field_delimiter[i] = stoc(rd,&rd); if (p->field_delimiter[i] == (char) NULL) break; p->field_delimiter[++i] = (char) NULL; if (i >= 31) /* don't use more than 31 codes */ break; } } else if (strncmp(rd,"record_delimiter",16) == 0) { rd += 16; /* start looking at the arguments */ i=0; /* counter & index for the arguments */ p->record_delimiter[0] = (char) NULL; /* reset string */ while (*rd != (char) NULL) { if (*rd == '!') break; /* ignore comments */ p->record_delimiter[i] = stoc(rd,&rd); if (p->record_delimiter[i] == (char) NULL) break; p->record_delimiter[++i] = (char) NULL; if (i >= 31) /* don't use more than 31 codes */ break; } } else if (strncmp(rd,"start_of_text_char",18) == 0) { rd += 18; /* start looking at the arguments */ i=0; /* counter & index for the arguments */ p->start_of_text_char[0] = (char) NULL; /* reset string */ while (*rd != (char) NULL) { if (*rd == '!') break; /* ignore comments */ p->start_of_text_char[i] = stoc(rd,&rd); if (p->start_of_text_char[i] == (char) NULL) break; p->start_of_text_char[++i] = (char) NULL; if (i >= 31) /* don't use more than 31 codes */ break; } } else if (strncmp(rd,"end_of_text_char",16) == 0) { rd += 16; /* start looking at the arguments */ i = 0; p->end_of_text_char[0] = (char) NULL; /* reset string */ while (*rd != (char) NULL) { if (*rd == '!') break; /* ignore comments */ p->end_of_text_char[i] = stoc(rd,&rd); if (p->end_of_text_char[i] == (char) NULL) break; p->end_of_text_char[++i] = (char) NULL; if (i >= 31) /* don't use more than 31 codes */ break; } } else if (strncmp(rd,"record_length",13) == 0) { rd += 13; /* start looking at the arguments */ while (isspace(*rd)) rd++; /* skip white spaces */ if (*rd == (char) NULL) { p->record_length = 0; } else { p->record_length = atoi(rd); } if (p->record_length < 0) { fprintf(stderr," *** ERROR : Negative record_length File %s line %d\n", p->profile,lcnt); error_flag = 1; } } else if (strncmp(rd,"field",5) == 0) { /* get and initialize the field_description structure */ fd = read_profile_field(p,rd,lcnt); if (fd == (FIELD_DESCRIPTION *) NULL) { error_flag = 1; continue; } /* attach to the linked list */ /* print debug stuff */ if (p->debug) printf("Read Field_Description, Attaching to Link List\n"); /* update the number of fields */ if (fd->start_position > p->nbr_field) p->nbr_field = fd->start_position; /* ensure link list is terminated */ fd->next = (FIELD_DESCRIPTION *) NULL; /* Insert the field_description into the proper place, sorting on the print_order */ /* see if the first link */ if (p->fd == (FIELD_DESCRIPTION *) NULL) { p->fd = fd; if (p->debug) printf(" First Link\n"); } /* not the first link, but should it be at the beginning */ else if (p->fd->print_order > fd->print_order) { fd->next = p->fd; p->fd = fd; if (p->debug) printf(" Inserted as the First Link\n"); } /* put it in the right spot */ else { for (bfd = p->fd ; bfd->next != (FIELD_DESCRIPTION *) NULL; bfd = bfd->next) { /* see if need to insert in the middle somewhere */ if (bfd->next->print_order > fd->print_order) { fd->next = bfd->next; bfd->next = fd; if (p->debug) printf(" Inserted in the middle of the chain\n"); break; } } /* see if need to insert at the end */ if (bfd->next == (FIELD_DESCRIPTION *) NULL) { bfd->next = fd; if (p->debug) printf(" Inserted as the Last Link\n"); } } if (p->debug) printf("Field_Description Attached to Link List\n"); } else { /* see if a field function */ if (read_profile_field_function(p,rd,lcnt) == (FIELD_FUNCTION *) NULL) { /* its an error */ fprintf(stderr,"\n *** ERROR : syntax error -- line %d of file %s\n", lcnt,p->profile); fprintf(stderr," %s",rdline); error_flag = 1; } } } if (error_flag) { exit(EXIT_FAILURE); } } FIELD_DESCRIPTION *read_profile_field(PARSER *p,char *rd,int lcnt) { FIELD_DESCRIPTION *fd; int slen; char *brd; brd = rd; fd = alloc_Field_Description(); /* determine the type of field description */ if (strncmp(rd,"field_",6) == 0) { if (strncmp(rd,"field_text",10) == 0) { fd->field_type = FIELD_TEXT; rd += 10; } else if (strncmp(rd,"field_counter",13) == 0) { fd->field_type = FIELD_COUNTER; rd += 13; } else if (strncmp(rd,"field_filename_field",20) == 0) { fd->field_type = FIELD_FILENAME_FIELD; rd += 20; } else if (strncmp(rd,"field_lookup",12) == 0) { fd->field_type = FIELD_LOOKUP; rd += 12; } else if (strncmp(rd,"field_date",10) == 0) { fd->field_type = FIELD_DATE; rd += 10; } else if (strncmp(rd,"field_time",10) == 0) { fd->field_type = FIELD_TIME; rd += 10; } else { /* error */ fprintf(stderr," *** ERROR: Profile %s line %d: illegal field command\n%s\n", p->profile,lcnt,brd); return (FIELD_DESCRIPTION *) NULL; } } else if (strncmp(rd,"field",5) == 0) { fd->field_type = FIELD_NORMAL; rd += 5; } else { /* error */ fprintf(stderr," *** ERROR: Profile %s line %d: illegal field command\n%s\n", p->profile,lcnt,brd); return (FIELD_DESCRIPTION *) NULL; } /* should have at least one 'space' following the command */ if (isspace((int)*rd) == 0) { /* error if not a white space */ fprintf(stderr," *** ERROR: Profile %s line %d: illegal field command\n%s\n", p->profile,lcnt,brd); return (FIELD_DESCRIPTION *) NULL; } /* skip the spaces */ while (isspace((int) *rd)) rd++; /* find the length of the name */ for (slen = 0;isspace(rd[slen]) == 0 && rd[slen] != (char) NULL; slen++); if (slen == 0) { fprintf(stderr," *** ERROR: Profile %s line %d: Syntax Error (%s)\n", p->profile,lcnt,brd); return (FIELD_DESCRIPTION *) NULL; } /* allocate the string */ fd->name = (char *) calloc((size_t)(slen+1),sizeof(char)); if (fd->name == (char *) NULL) { fprintf(stderr,"\n *** ERROR : Out of memory in alloc_Field_Description\n"); exit(EXIT_FAILURE); } strncpy(fd->name,rd,slen); /* copy the name */ fd->name[slen] = (char) NULL; /* NULL terminate the string */ rd += slen; /* update the pointer */ if (fd->field_type == FIELD_NORMAL) { /* get the start_position */ while (isspace(*rd)) rd++; /* skip white spaces */ fd->start_position = atoi(rd); /* do the conversions */ /* skip the non-white spaces */ while (isspace(*rd) == 0 && *rd != (char) NULL) rd++; /* get the length */ while (isspace(*rd)) rd++; /* skip white spaces */ fd->length = atoi(rd); /* do the conversions */ fd->data_length = fd->length; /* initialize */ /* skip the non-white spaces */ while (isspace(*rd) == 0 && *rd != (char) NULL) rd++; /* get the TEXT or NUMBER */ while (isspace(*rd)) rd++; /* skip white spaces */ if (strncmp(rd,"TEXT",4) == 0) fd->type = TEXT; else if (strncmp(rd,"NUMBER",5) == 0) fd->type = NUMBER; else fd->type = TEXT; /* default type */ /* skip the non-white spaces */ while (isspace(*rd) == 0 && *rd != (char) NULL) rd++; } else if (fd->field_type == FIELD_TEXT) { /* do the conversion of embedded control characters */ convert_escape_string(rd); /* find the end of the text -- first skip trailing spaces */ for (slen = (int) strlen(rd) - 1; isspace((int)rd[slen]) && slen >=0 ; slen--); /* skip the print order */ while (slen >= 0 && isdigit((int) rd[slen])) slen--; /* skip the spaces between text and print order */ while (slen >= 0 && isspace((int) rd[slen])) slen--; /* allocate the data array */ fd->arg1 = (char *) calloc((size_t)slen+2,sizeof(char)); if (fd->arg1 == (char *) NULL) { fprintf(stderr,"\n *** ERROR : Out of memory in alloc_Field_Description\n"); exit(EXIT_FAILURE); } /* copy the text */ strncpy(fd->arg1,rd,slen+1); fd->arg1[slen+1] = (char) NULL; /* update the pointer */ rd += slen + 1; fd->length = strlen(fd->arg1); fd->data_length = fd->length; fd->type = TEXT; } else if (fd->field_type == FIELD_COUNTER) { fd->type = NUMBER; fd->length = 6; /* assume less than 1 million records */ fd->data_length = fd->length; } else if (fd->field_type == FIELD_FILENAME_FIELD) { fd->length = 12; /* limited to DOS style filenames */ fd->data_length = fd->length; fd->type = TEXT; } else if (fd->field_type == FIELD_LOOKUP) { fd->length = 255; /* lines in lookup files limited to 255 chars */ fd->data_length = fd->length; fd->type = TEXT; /* skip leading spaces */ while(isspace((int) *rd)) rd++; /* get the field name to use for the lookup and store in data element */ /* get the length of the name of the field to use for the lookup */ for (slen = 0 ; isspace((int) rd[slen]) == 0 && rd[slen] != (char) NULL ; slen++); if (slen == 0) { fprintf(stderr," *** ERROR: Profile %s line %d: Syntax Error (%s)\n", p->profile,lcnt,brd); return (FIELD_DESCRIPTION *) NULL; } /* allocate the array and do the copying */ fd->data = (char *) calloc((size_t) slen+1,sizeof(char)); if (fd->data == (char *) NULL) { fprintf(stderr,"\n *** ERROR : Out of memory in alloc_Field_Description\n"); exit(EXIT_FAILURE); } strncpy(fd->data,rd,slen); fd->data[slen] = (char) NULL; rd += slen; /* find the field */ fd->field_lookup = find_field_description(p->fd,fd->data); if (fd->field_lookup == (FIELD_DESCRIPTION *) NULL) { fprintf(stderr," *** ERROR: Profile %s Line %d: Lookup field %s for field %s not defined\n", p->profile,lcnt,fd->data,fd->name); exit(EXIT_FAILURE); } /* free up the data array */ free((void *)fd->data); fd->data = (char *) NULL; /* skip leading spaces */ while(isspace((int) *rd)) rd++; /* get the filename of the file containing the data table for looking up the specified field in column 1 and returning the value in hte specified column */ /* get the length of the filename */ for (slen = 0 ; isspace((int) rd[slen]) == 0 && rd[slen] != (char) NULL ; slen++); if (slen == 0) { fprintf(stderr," *** ERROR: Profile %s line %d: Syntax Error (%s)\n", p->profile,lcnt,brd); return (FIELD_DESCRIPTION *) NULL; } /* store the filename in element arg1 */ fd->arg1 = (char *) calloc((size_t) slen+1,sizeof(char)); if (fd->arg1 == (char *) NULL) { fprintf(stderr,"\n *** ERROR : Out of memory in alloc_Field_Description\n"); exit(EXIT_FAILURE); } strncpy(fd->arg1,rd,slen); fd->arg1[slen] = (char) NULL; /* try to open the file */ fd->fluf = fopen(fd->arg1,"rt"); if (fd->fluf == (FILE*) NULL) { fprintf(stderr," *** ERROR: Profile %s Line %d: Unable to open lookup file %s for field %s\n", p->profile,lcnt,fd->arg1,fd->name); return (FIELD_DESCRIPTION *) NULL; } rd += slen; /* skip leading spaces */ while(isspace((int) *rd)) rd++; /* get the column to use in the filename specified and store it in the start_position element */ fd->start_position = atoi(rd); /* do the conversions */ if (fd->start_position < 1) { fprintf(stderr," *** ERROR: Profile %s Line %d: Illegal Column Number (%s)\n", p->profile,lcnt,brd); return (FIELD_DESCRIPTION *) NULL; } /* skip the non-white spaces */ while (isspace(*rd) == 0 && *rd != (char) NULL) rd++; } else if (fd->field_type == FIELD_DATE) { fd->length = 10; fd->data_length = fd->length; fd->type = TEXT; } else if (fd->field_type == FIELD_TIME) { fd->length = 8; fd->data_length = fd->length; fd->type = TEXT; } /* get the print_order */ while (isspace(*rd)) rd++; /* skip white spaces */ fd->print_order = atoi(rd); /* initalize the other stuff */ fd->ff = (FIELD_FUNCTION *) NULL; /* all done */ return fd; } FIELD_FUNCTION *read_profile_field_function(PARSER *p,char *rd,int lcnt) { char *command,*end_command,end_ch1; char *field_name, *end_field_name,end_ch2; FIELD_DESCRIPTION *fd; FIELD_FUNCTION *ff; FIELD_FUNCTION *bff; char *arg1; char *arg2; char ch; int i; /* find the pointers for each element */ for (command = rd; isspace((int)*command) ; command++); for (end_command = command ; isgraph((int) *end_command) ; end_command++); end_ch1 = *end_command; /* save the delimiter */ *end_command = (char) NULL; /* NULL terminate the command */ /* check for an error */ if (end_ch1 == (char) NULL) return (FIELD_FUNCTION *) NULL; /* no field name specified */ /* extract the field name */ for (field_name=end_command + 1;isspace((int)*field_name);field_name++); for (end_field_name = field_name ; isgraph((int) *end_field_name) ; end_field_name++); end_ch2 = *end_field_name; /* save the delimiter */ *end_field_name = (char) NULL; /* find the start of the arguments */ for (arg1 = end_field_name + 1 ; isspace((int)*arg1) && end_ch2 != (char) NULL ; arg1++); /* find the field description */ fd = find_field_description(p->fd,field_name); if (fd == (FIELD_DESCRIPTION *) NULL) { fprintf(stderr," *** ERROR: field %s undefined: Line %d, File %s\n", field_name,lcnt,p->profile); return (FIELD_FUNCTION *) NULL; /* couldn't find the field */ } /* allocate the FIELD_FUNCTION */ ff = (FIELD_FUNCTION *) calloc((size_t) 1 , sizeof(FIELD_FUNCTION)); if (ff == (FIELD_FUNCTION *) NULL) { fprintf(stderr," ***ERROR: Out of Memory in read_profile_field_function()\n"); exit(EXIT_FAILURE); } /* initialize elements */ ff->type = FUNCTION_UNDEFINED; ff->arg = 0; ff->array = (int *) NULL; /* search for the type */ if (strcmp(command,"reorder") == 0) { ff->type = FUNCTION_REORDER; /* need work here */ /* allocate the array initially to the size of the remaining string */ ff->array = (int*)calloc((size_t)strlen(arg1)+1,sizeof(int)); if (ff->array == (int *) NULL) { fprintf(stderr," *** ERROR: Out of memory in read_profile_field_function()\n"); exit(EXIT_FAILURE); } arg2 = arg1; while (isspace((int)*arg2))arg2++; for (ff->arg = 0 ; *arg2 != (char) NULL ; ff->arg++) { if (p->debug) { printf("%c",*arg2); fflush(stdout); } /* see if character */ if (*arg2 == '$') { arg2++; ff->array[ff->arg] = (int) astoc(arg2,&arg2); while (isspace((int)*arg2))arg2++; if (p->debug) { printf("<%c>",(char)ff->array[ff->arg]); fflush(stdout); } continue; } if (isdigit((int) *arg2) == 0) { if (p->debug) printf("<<--NON_DIGIT DETECTED HERE\n"); *end_command = end_ch1; *end_field_name = end_ch2; return (FIELD_FUNCTION *) NULL; } /* try to do the conversion of a number, the 256 offset is to differentiate an index with an ASCII character */ ff->array[ff->arg] = (int) strtol(arg2,&arg2,10) + 256; while (isspace((int)*arg2))arg2++; } ff->array = (int *)realloc((void *) ff->array,(size_t)(ff->arg+1)*sizeof(int)); if (ff->array == (int *) NULL) { fprintf(stderr," *** ERROR: Out of memory in read_profile_field_function()\n"); exit(EXIT_FAILURE); } fd->data_length += ff->arg; } else if (strcmp(command,"strip") == 0) { ff->type = FUNCTION_STRIP; } else if (strcmp(command,"delete_char") == 0) { ff->type = FUNCTION_DELETE_CHAR; ff->arg = (int) stoc(arg1,(char **) NULL); } else if (strcmp(command,"delete_alpha") == 0) { ff->type = FUNCTION_DELETE_ALPHA; } else if (strcmp(command,"delete_nonalpha") == 0) { ff->type = FUNCTION_DELETE_NONALPHA; } else if (strcmp(command,"delete_numeric") == 0) { ff->type = FUNCTION_DELETE_NUMERIC; } else if (strcmp(command,"delete_nonnumeric") == 0) { ff->type = FUNCTION_DELETE_NONNUMERIC; } else if (strcmp(command,"delete_left") == 0) { ff->type = FUNCTION_DELETE_LEFT; ff->arg = atoi(arg1); } else if (strcmp(command,"delete_right") == 0) { ff->type = FUNCTION_DELETE_RIGHT; ff->arg = atoi(arg1); } else if (strcmp(command,"keep_left") == 0) { ff->type = FUNCTION_KEEP_LEFT; ff->arg = atoi(arg1); } else if (strcmp(command,"keep_right") == 0) { ff->type = FUNCTION_KEEP_RIGHT; ff->arg = atoi(arg1); } else if (strcmp(command,"insert_left") == 0) { ff->type = FUNCTION_INSERT_LEFT; strstrip(arg1); convert_escape_string(arg1); ff->arg = (int) strlen(arg1); ff->array = (int *) calloc((size_t)ff->arg+1,sizeof(int)); if (ff->array == (int *) NULL) { fprintf(stderr," ***ERROR: Out of Memory in read_profile_field_function()\n"); exit(EXIT_FAILURE); } for (i = 0 ; i < ff->arg ; i++) ff->array[i] = (int) arg1[i]; ff->array[ff->arg] = (int) NULL; fd->data_length += ff->arg; } else if (strcmp(command,"insert_right") == 0) { ff->type = FUNCTION_INSERT_RIGHT; strstrip(arg1); convert_escape_string(arg1); ff->arg = (int) strlen(arg1); ff->array = (int *) calloc((size_t)ff->arg+1,sizeof(int)); if (ff->array == (int *) NULL) { fprintf(stderr," ***ERROR: Out of Memory in read_profile_field_function()\n"); exit(EXIT_FAILURE); } for (i = 0 ; i < ff->arg ; i++) ff->array[i] = (int) arg1[i]; ff->array[ff->arg] = (int) NULL; fd->data_length += ff->arg; } else if (strcmp(command,"replace_char") == 0) { ff->type = FUNCTION_REPLACE_CHAR; ff->array = (int *) calloc((size_t) 2 , sizeof(int)); if (ff->array == (int *) NULL) { fprintf(stderr," *** ERROR: Out of Memory in read_profile_field_function\n"); exit(EXIT_FAILURE); } ff->arg = 2; ff->array[0] = (int) stoc(arg1,&arg2); /* old char */ ff->array[1] = (int) stoc(arg2,(char **) NULL); /* new char to replace old char */ } else if (strcmp(command,"replace_text") == 0) { int j; ff->type = FUNCTION_REPLACE_TEXT; strstrip(arg1); ff->array = (int *) calloc((size_t)strlen(arg1)+1,sizeof(int)); if (ff->array == (int *) NULL) { fprintf(stderr," ***ERROR: Out of Memory in read_profile_field_function()\n"); exit(EXIT_FAILURE); } /* identify the two arguments. once the following is completed arg1 will be the address of the original text arg1 + ff->arg will be the address of the replacement text */ ff->arg = 0; for (i = 0 ; arg1[i] != (char) NULL ; i++) { /* check for escape sequences */ if (arg1[i] == '\\' && arg1[i+1] != (char) NULL) { i++; } else if (arg1[i] != '\\') { /* see if the end of the first argument (original string) */ if (ff->arg == 0 && isspace(arg1[i])) { /* NULL Terminate the original string */ arg1[i] = (char) NULL; i++; /* skip leading spacess of replacement string */ while (isspace((int)arg1[i])) i++; ff->arg = i; /* arg is the start of the replacement string */ i--; } /* see if at the end of the scond argument (replacement string) */ else if (isspace((int)arg1[i])) { arg1[i] = (char) NULL; break; } } } /* see if no text was found */ if (ff->arg < 2) return (FIELD_FUNCTION *) NULL; /* convert the escape sequences */ convert_escape_string(arg1); convert_escape_string(arg1 + ff->arg); /* copy the data */ for (i=0 ; arg1[i] != (char) NULL ; i++) ff->array[i] = arg1[i]; ff->array[i] = (char) NULL; for (i++,j=0 ; arg1[ff->arg + j] != (char) NULL ; j++) ff->array[i+j] = arg1[ff->arg + j]; ff->array[i+j] = (char) NULL; ff->arg = i; /* error check some more */ if (ff->array[0] == (int) NULL || i < 2) return (FIELD_FUNCTION *) NULL; /* adjust data length if the replacement is longer */ if (j > i - 1) /* j is length of the replacement text i - 1 is length of the original text */ fd->data_length = (int) floor((double) (fd->data_length * j) / (double) (i - 1)); } else if (strcmp(command,"pad_left") == 0) { ff->type = FUNCTION_PAD_LEFT; ff->arg = atoi(arg1); if (ff->arg > fd->data_length) fd->data_length = ff->arg; } else if (strcmp(command,"pad_right") == 0) { ff->type = FUNCTION_PAD_RIGHT; ff->arg = atoi(arg1); if (ff->arg > fd->data_length) fd->data_length = ff->arg; } else if (strcmp(command,"to_upper_case") == 0) { ff->type = FUNCTION_TO_UPPER_CASE; } else if (strcmp(command,"to_lower_case") == 0) { ff->type = FUNCTION_TO_LOWER_CASE; } else { *end_command = end_ch1; *end_field_name = end_ch2; return (FIELD_FUNCTION *) NULL; /* couldn't find the field */ } if (p->debug) printf("Attaching the Field_Function to the linked list\n"); /* attach to the linked list */ if (fd->ff == (FIELD_FUNCTION *) NULL) { fd->ff = ff; ff->next = (FIELD_FUNCTION *) NULL; if (p->debug) printf("Attached to the beginning of the linked list\n"); return ff; } for (bff = fd->ff ; bff->next != (FIELD_FUNCTION *) NULL ; bff = bff->next); bff->next = ff; ff->next = (FIELD_FUNCTION *) NULL; if (p->debug) printf("Attached to the End of the linked list\n"); return ff; } void read_write(PARSER *p) { FIELD_DESCRIPTION *fd; char filename[81]; int i; /* if we aren't using p-out, set it to NULL */ if (p->record_per_file != 0) p->out = (FILE *) NULL; /* print the HTML header if necessary */ if (p->output_format == OUTPUT_HTML && p->record_per_file == 0) { extract_filename_base(p->outfile, filename); fprintf(p->out,"%s\n",filename); fprintf(p->out,"

%s

\n",filename); fprintf(p->out,"
\n");
  }

 /* print the header row if necessary */

 if (p->print_column_names && p->record_per_file == 0)
  {
   for (fd = p->fd ; fd != (FIELD_DESCRIPTION *) NULL ; fd = fd->next)
    {
     if (fd->print_order <= 0)
      continue;
     fputs(p->start_of_text_char,p->out);
     fputs(fd->name,p->out);
     fputs(p->end_of_text_char,p->out);
     if (fd->next != (FIELD_DESCRIPTION *) NULL)
      fputs(p->field_delimiter,p->out);
     else
      fputs(p->record_delimiter,p->out);
    }

  }

 /* read the input file until we run out of file */

 while(feof(p->in) == 0)
  {

   if (p->input_file_type == FILE_FIXED)
    {
     read_record(p);
    }
   else
    {
     read_delimited_record(p);
    }

   /* check for EOF */

   if (p->record[0] == (char) NULL)
    break;

   /* perform any necessary operations on the fields */

   process_record(p);

   /* print the fields to the output file */


   if (p->record_per_file == 0)
    write_record(p);
   else
    write_record_file(p);

   if (p->out != stdout && p->record_cnt % 100  == 0)
    {
     printf(".");
     fflush(stdout);
    }

  }

 if (p->out != stdout)
  printf("\n");


 /* print the HTML footer if necessary */

 if (p->output_format == OUTPUT_HTML && p->record_per_file == 0)
  {
   fprintf(p->out,"

File Created %s %s
\n",p->string_time,p->string_date); fprintf(p->out,"Source File: %s
\n",p->infile); fprintf(p->out,"Created by PARSER version %s (%s)
\n", REVISION,p->profile); } } void read_delimited_record(PARSER *p) { int i; int length; char *rd,*rdd,*rdd1; int text_flag; FIELD_DESCRIPTION *fd; int record_length; /* read in the record from the input file */ record_length = (p->record_length > 0) ? p->record_length : DEFAULTRECORDLENGTH; if (fgets(p->record,record_length,p->in) == (char *) NULL) { p->record[0] = (char) NULL; return; } /* delete the trailing white space characters */ for (i=strlen(p->record)-1 ; i >= 0 && isspace((int) p->record[i]) ; i--) p->record[i] = (char) NULL; /* debug info */ if (p->debug) printf("(%d)<%s>\n",p->record_cnt + 1, p->record); /* initialize the ptr_field to NULL pointers */ for (i=0 ; i < p->nbr_field ; i++) p->ptr_field[i] = (char *) NULL; /* find all of the fields */ for (i=0,rd = p->record ; *rd != (char ) NULL && i < p->nbr_field ; i++) { for (; isspace((int)*rd) ; rd++); /* skip leading spaces */ /* see if a text or numeric field */ if (*rd == p->input_text_delimiter) { text_flag = 1; rd++; } else { text_flag = 0; } p->ptr_field[i] = rd; /* skip the field */ while (*rd != (char) NULL) { /* if this is not a text field, then the first instance of the field delimiter should indicate the end of the field */ if (*rd == p->input_field_delimiter && text_flag == 0) { *rd = (char) NULL; /* NULL terminate the string */ rd++; break; } else if (*rd == p->input_text_delimiter && text_flag == 1) { /* if the next character is also a text delimiter, then it is a valid character */ if (*(rd+1) == p->input_text_delimiter) { rd += 2; } /* otherwise it should be the end of the field */ else { *rd = (char) NULL; /* terminate the string */ rd++; /* progress to the next field delimiter */ while (*rd != p->input_field_delimiter && *rd != (char) NULL) rd++; if (*rd == (p->input_field_delimiter)) { rd++; break; } } } else rd++; } if (p->debug) printf("<%s>",p->ptr_field[i]); /* combine repeated text delimiters */ if (text_flag == 1) { for (rdd1 = p->ptr_field[i], rdd = p->ptr_field[i] ; *rdd1 != (char) NULL ; rdd1++,rdd++) { if (*rdd1 == p->input_text_delimiter) rdd1++; *rdd = *rdd1; } *rdd = (char) NULL; } /* debug info */ if (p->debug) printf("<%s>",p->ptr_field[i]); } if (p->debug) printf("\n"); /* make sure that prematurely terminated lines have the fields set properly */ for ( ; i < p->nbr_field ; i++) p->ptr_field[i] = rd; /* *rd should be NULL */ p->record_cnt++; /* count the number of records read in */ /* extract all of the fields */ for (fd = p->fd ; fd != (FIELD_DESCRIPTION *) NULL ; fd=fd->next) { if (fd->field_type == FIELD_NORMAL) { strncpy(fd->data,p->ptr_field[fd->start_position - 1],fd->length); fd->data[fd->length] = (char) NULL; } else if (fd->field_type == FIELD_TEXT) { if (p->record_cnt == 1) strcpy(fd->data,fd->arg1); } else if (fd->field_type == FIELD_COUNTER) { sprintf(fd->data,"%06d",p->record_cnt); } else if (fd->field_type == FIELD_FILENAME_FIELD) { if (p->output_format != OUTPUT_HTML) sprintf(fd->data,"PF%06d.txt",p->record_cnt); else sprintf(fd->data,"PF%06d.htm",p->record_cnt); } else if (fd->field_type == FIELD_LOOKUP) { /* do nothing for now */ } else if (fd->field_type == FIELD_DATE) { if (p->record_cnt == 1) strcpy(fd->data,p->string_date); } else if (fd->field_type == FIELD_TIME) { if (p->record_cnt == 1) strcpy(fd->data,p->string_time); } else { /* unknown field type */ } } } void read_record(PARSER *p) { int i; FIELD_DESCRIPTION *fd; int record_length; record_length = (p->record_length > 0) ? p->record_length : DEFAULTRECORDLENGTH; /* read in the record from the input file */ for (i=0 ; i < record_length ; i++) { p->record[i] = (char) fgetc(p->in); /* ignore last line if only partial */ if (p->record[i] == EOF) { for (i=0 ; i < record_length ; i++) p->record[i] = (char) NULL; return; } /* if the record_length is not specified, read to a newline character */ if (p->record[i] == '\n' && p->record_length <= 0) { for ( ; i < record_length - 1 ; i++) p->record[i] = (char) NULL; } } p->record[i] = (char) NULL; /* NULL Terminate the string */ p->record_cnt++; /* count the number of records read in */ /* extract all of the fields */ for (fd = p->fd ; fd != (FIELD_DESCRIPTION *) NULL ; fd=fd->next) { if (fd->field_type == FIELD_NORMAL) { for (i=0 ; i < fd->length ; i++) { fd->data[i] = p->record[fd->start_position - 1 + i]; } fd->data[i] = (char) NULL; /* NULL terminate */ } else if (fd->field_type == FIELD_TEXT) { if (p->record_cnt == 1) strcpy(fd->data,fd->arg1); } else if (fd->field_type == FIELD_COUNTER) { sprintf(fd->data,"%06d",p->record_cnt); } else if (fd->field_type == FIELD_FILENAME_FIELD) { if (p->output_format != OUTPUT_HTML) sprintf(fd->data,"PF%06d.txt",p->record_cnt); else sprintf(fd->data,"PF%06d.htm",p->record_cnt); } else if (fd->field_type == FIELD_LOOKUP) { /* do nothing for now */ } else if (fd->field_type == FIELD_DATE) { if (p->record_cnt == 1) strcpy(fd->data,p->string_date); } else if (fd->field_type == FIELD_TIME) { if (p->record_cnt == 1) strcpy(fd->data,p->string_time); } else { /* unknown field type */ } } } void process_record(PARSER *p) { FIELD_DESCRIPTION *fd; for (fd = p->fd ; fd != (FIELD_DESCRIPTION *) NULL ; fd = fd->next) { /* skip the fields that aren't printed ... If the field is needed for a field_lookup, it will be calculated later */ if (fd->print_order <= 0) continue; if (p->debug) printf("Processing Field: %s <%d>\n",fd->name,fd->print_order); process_field(p,fd); } } void process_field(PARSER *p,FIELD_DESCRIPTION *fd) { FIELD_FUNCTION *ff; /* return if already calculated */ if (fd->calculate_flag == CALCULATE_YES) return; /* error if the calculation is in progress */ if (fd->calculate_flag == CALCULATE_WORKING) { /* error: circular reference */ fprintf(stderr," *** ERROR: Circular References for field_lookup %s\n", fd->name); exit(EXIT_FAILURE); } if (fd->field_type == FIELD_LOOKUP) { if (fd->field_lookup->calculate_flag == CALCULATE_NO) { fd->calculate_flag = CALCULATE_WORKING; process_field(p,fd->field_lookup); } process_field_lookup(p,fd); } /* see if a field that only needs to be calculated once */ else if (fd->field_type == FIELD_TEXT || fd->field_type == FIELD_DATE || fd->field_type == FIELD_TIME) { if (p->record_cnt > 1) { fd->calculate_flag = CALCULATE_YES; return; } } for (ff = fd->ff ; ff != (FIELD_FUNCTION *) NULL ; ff = ff->next) { if (p->debug) { print_field_function(ff,fd,stdout); } process_field_function(p,fd,ff); } fd->calculate_flag = CALCULATE_YES; } void process_field_lookup(PARSER *p, FIELD_DESCRIPTION *fd) { char rdline[256], *rd; int slen; int i, column_cnt; /* initialize to zero length */ fd->data[0] = (char) NULL; /* search the file */ while(fgets(rdline,255,fd->fluf)) { rd = rdline; /* skip spaces before the field */ while (isspace((int) *rd)) rd++; /* skip blank lines */ if (*rd == (char) NULL) continue; /* see if a match for the lookup */ slen = strlen(fd->field_lookup->data); if (strncmp(rd,fd->field_lookup->data,slen)==0) { /* got a match, find the column */ for (column_cnt = 1 ; column_cnt < fd->start_position ; column_cnt++) { /* skip spaces before the field */ while (isspace((int) *rd)) rd++; while (isspace((int) *rd) == 0 && *rd != (char) NULL) rd++; } while (isspace((int) *rd)) rd++; /* rd should now be at the beginning of the column or pointing to the NULL character if at the end of the line */ /* copy the field */ for (i=0 ; rd[i] != (char) NULL && isspace((int)rd[i]) == 0 ; i++) fd->data[i] = rd[i]; fd->data[i] = (char) NULL; } } /* rewind the file for the next record */ rewind(fd->fluf); } void process_field_function(PARSER *p,FIELD_DESCRIPTION *fd,FIELD_FUNCTION *ff) { int i,j; char *s; if (ff->type == FUNCTION_STRIP) { strstrip(fd->data); } else if (ff->type == FUNCTION_REORDER) { s = (char *) calloc((size_t)fd->data_length+1,sizeof(char)); if (s == (char *) NULL) { fprintf(stderr," ***ERROR: Out of memory in process_field_function()\n"); exit(EXIT_FAILURE); } strcpy(s,fd->data); for (i=0 ; i < ff->arg ; i++) { if (ff->array[i] > 256) { j = ff->array[i] - 256 - 1; if (j >= (int) strlen(s)) { fd->data[i] = ' '; } else { fd->data[i] = s[j]; } } else { fd->data[i] = (char) ff->array[i]; } } fd->data[i] = (char) NULL; free((void *) s); } else if (ff->type == FUNCTION_DELETE_CHAR) { for (i=0,j=0; fd->data[i] != (char) NULL ; i++) { if (fd->data[i] != (char) ff->arg) { fd->data[j] = fd->data[i]; j++; } } fd->data[j] = (char) NULL; } else if (ff->type == FUNCTION_DELETE_LEFT) { if ((int) strlen(fd->data) <= ff->arg) fd->data[0] = (char) NULL; else if (ff->arg > 0) { for (i=ff->arg,j=0; fd->data[i] != (char) NULL ; i++,j++) fd->data[j] = fd->data[i]; fd->data[j] = (char) NULL; } } else if (ff->type == FUNCTION_DELETE_RIGHT) { if ((int)strlen(fd->data) <= ff->arg) fd->data[0] = (char) NULL; else if (ff->arg > 0) { fd->data[strlen(fd->data) - ff->arg] = (char) NULL; } } else if (ff->type == FUNCTION_DELETE_ALPHA) { for (i=0,j=0; fd->data[i] != (char) NULL ; i++) { if (isalpha((int)fd->data[i])==0) { fd->data[j] = fd->data[i]; j++; } } fd->data[j] = (char) NULL; } else if (ff->type == FUNCTION_DELETE_NONALPHA) { for (i=0,j=0; fd->data[i] != (char) NULL ; i++) { if (isalpha((int)fd->data[i])) { fd->data[j] = fd->data[i]; j++; } } fd->data[j] = (char) NULL; } else if (ff->type == FUNCTION_DELETE_NUMERIC) { for (i=0,j=0; fd->data[i] != (char) NULL ; i++) { if (isdigit((int)fd->data[i])==0) { fd->data[j] = fd->data[i]; j++; } } fd->data[j] = (char) NULL; } else if (ff->type == FUNCTION_DELETE_NONNUMERIC) { for (i=0,j=0; fd->data[i] != (char) NULL ; i++) { if (isdigit((int)fd->data[i])) { fd->data[j] = fd->data[i]; j++; } } fd->data[j] = (char) NULL; } else if (ff->type == FUNCTION_KEEP_LEFT) { if (ff->arg < (int) strlen(fd->data)) fd->data[ff->arg] = (char) NULL; } else if (ff->type == FUNCTION_KEEP_RIGHT) { if (ff->arg < (int) strlen(fd->data)) { for (j=0,i=strlen(fd->data) - ff->arg ; fd->data[i] != (char) NULL; i++,j++) fd->data[j] = fd->data[i]; fd->data[j] = (char) NULL; } } else if (ff->type == FUNCTION_INSERT_LEFT) { /* move data right by the number of characters to insert */ for (i=(int)strlen(fd->data) ; i >= 0 && ff->arg > 0 ; i--) fd->data[i+ff->arg] = fd->data[i]; /* insert the characters */ for (i=0 ; i < ff->arg ; i++) fd->data[i] = (char) ff->array[i]; } else if (ff->type == FUNCTION_INSERT_RIGHT) { for (i=0,j=strlen(fd->data); i < ff->arg ; i++,j++) fd->data[j] = (char) ff->array[i]; fd->data[j] = (char) NULL; } else if (ff->type == FUNCTION_REPLACE_CHAR) { for (i=0; fd->data[i] != (char) NULL ; i++) { if (fd->data[i] == (char) ff->array[0]) fd->data[i] = (char) ff->array[1]; } } else if (ff->type == FUNCTION_REPLACE_TEXT) { int l2,i1,shift; /* get the length of the replacement string */ for (l2 = 0 ; ff->array[l2+ff->arg] != (int) NULL ; l2++); /* search the data string for the original string */ for (i = 0 , j= 0; fd->data[i] != (char) NULL ; i ++) { /* see if this character matches the corresponding character in the original text string */ if (fd->data[i] != (char) ff->array[j]) j = 0; /* if not a match, then start over */ else j++; /* if a match, look at next element */ /* see if have matched the entire original string, if so, then insert the new text */ if (ff->array[j] == (int) NULL) { /* calculate the number of characters need to shift */ shift = l2 - j; /* debug stuff */ if (p->debug) { print_array(ff->array,j,stdout); printf(" fd->data = <%s> i = %d j = %d shift = %d l2 = %d\n", fd->data, i,j,shift,l2); } /* see if need to shift the data string right or left */ if ( shift < 0) /* shift left, shift negative */ { for (i1 = i + shift; fd->data[i1-shift] != (char) NULL ; i1++) fd->data[i1] = fd->data[i1-shift]; fd->data[i1] = (char) NULL; } else if (shift > 0) /* shift right */ { for (i1 = i ; fd->data[i1] != (char) NULL ; i1++); for ( ; i1 > i ; i1--) fd->data[i1 + shift] = fd->data[i1]; } /* insert the new string */ for (i1 = 0 ; i1 < l2 ; i1++) { fd->data[i-j+i1+1] = (char) ff->array[ff->arg+i1]; } if (p->debug) { printf("fd->data = <%s> fd->array[ff->arg] = ",fd->data); print_array(ff->array+ff->arg,l2,stdout); printf("\n"); } } } } else if (ff->type == FUNCTION_PAD_LEFT) { if (ff->arg > (int) strlen(fd->data)) { /* right justify the data */ for (i=ff->arg,j=(int)strlen(fd->data) ; j >= 0 ; i--,j--) fd->data[i] = fd->data[j]; /* insert the appropriate number of spaces */ for ( ; i >= 0 ; i--) fd->data[i] = ' '; } } else if (ff->type == FUNCTION_PAD_RIGHT) { if (ff->arg > (int) strlen(fd->data)) { for (i = (int) strlen(fd->data) ; i < ff->arg ; i++) { fd->data[i] = ' '; } fd->data[i] = (char) NULL; } } else if (ff->type == FUNCTION_TO_UPPER_CASE) { for (i = 0 ; fd->data[i] != (char) NULL ; i++) fd->data[i] = (char) toupper((int)fd->data[i]); } else if (ff->type == FUNCTION_TO_LOWER_CASE) { for (i = 0 ; fd->data[i] != (char) NULL ; i++) fd->data[i] = (char) tolower((int)fd->data[i]); } else { /* unknown function code */ } } void write_record(PARSER *p) { FIELD_DESCRIPTION *fd; for (fd = p->fd ; fd != (FIELD_DESCRIPTION *) NULL ; fd = fd->next) { fd->calculate_flag = CALCULATE_NO; /* initialize for the next pass */ /* don't print the fields with a print order less than or equal to 0 */ if (fd->print_order <= 0) continue; /* print the start_of_text_char if necessary */ if (fd->type == TEXT) fputs(p->start_of_text_char,p->out); /* print the actual field */ fputs(fd->data,p->out); /* print the end_of_text_char if necessary */ if (fd->type == TEXT) fputs(p->end_of_text_char,p->out); /* print the field delimiter if not the last record otherwise print the record delimiter */ if (fd->next != (FIELD_DESCRIPTION *) NULL) fputs(p->field_delimiter,p->out); else fputs(p->record_delimiter,p->out); } } void write_record_file(PARSER *p) { FIELD_DESCRIPTION *fd; char filename[255],filebase[255]; FILE *out; /* open the file */ if (p->output_format != OUTPUT_HTML || p->filename_fd->data[0] == (char) NULL) sprintf(filename,"PF%06d.txt",p->record_cnt); else sprintf(filename,"PF%06d.htm",p->record_cnt); if (p->filename_fd != (FIELD_DESCRIPTION *) NULL) { if (p->output_format != OUTPUT_HTML) sprintf(filename,"%s.txt",p->filename_fd->data); else sprintf(filename,"%s.htm",p->filename_fd->data); } out = fopen(filename,"w"); if (out == (FILE *) NULL) { fprintf(stderr," *** ERROR: Unable to write to file %s\n",filename); return; } /* print the HTML header if necessary */ if (p->output_format == OUTPUT_HTML) { extract_filename_base(filename,filebase); fprintf(out,"%s\n",filebase); fprintf(out,"

%s

\n",filebase); fprintf(out,"
\n");
  }


 for (fd = p->fd ; fd != (FIELD_DESCRIPTION *) NULL ; fd = fd->next)
  {

   fd->calculate_flag = CALCULATE_NO;  /* initialize for the next pass */

   /* don't print the fields with a print order less than or equal to 0 */

   if (fd->print_order <= 0)
    continue;

   /* print the column name if needed */

   if (p->print_column_names)
    {
     fprintf(out,"@%s ",fd->name);
    }

   /* print the start_of_text_char if necessary */

   if (fd->type == TEXT)
    fputs(p->start_of_text_char,out);

   /* print the actual field */

   fputs(fd->data,out);

   /* print the end_of_text_char if necessary */

   if (fd->type == TEXT)
    fputs(p->end_of_text_char,out);

   /* print the field delimiter if not the last record
      otherwise print the record delimiter */

   if (fd->next != (FIELD_DESCRIPTION *) NULL)

   /* print the field delimiter */

    fputs(p->field_delimiter,out);

   else

   /* print the record delimiter */

    fputs(p->record_delimiter,out);

  }

 /* print the HTML footer if necessary */

 if (p->output_format == OUTPUT_HTML)
  {
   fprintf(out,"

File Created %s %s
\n",p->string_time,p->string_date); fprintf(out,"Source File: %s
\n",p->infile); fprintf(out,"Created by PARSER version %s (%s)
\n", REVISION,p->profile); } /* close the file */ fclose(out); } void clean_up(PARSER *p) { if (p->out != stdout && p->out != (FILE *) NULL) fclose(p->out); if (p->in != stdin && p->in != (FILE *) NULL) fclose(p->in); } void print_help() { printf("\n PARSER Version %s (%s)\n",REVISION,__DATE__); printf("\n COPYRIGHT (C) 1996-2002 Norbert H. Doerry\n"); printf("\n SYNTAX: PARSER INFILE -oOUTFILE -pPROFILE \n\n"); printf(" INFILE Input File Name\n"); printf(" OUTFILE Output File Name (stdout if omitted)\n"); printf(" PROFILE Profile File Name (parser.ini if omitted)\n"); printf(" PARSER converts a file consisting of data fields &\n"); printf(" records into a file consisting of comma or other delimitted\n"); printf(" fields and records. The file conversion is specified by the\n"); printf(" PROFILE file.\n"); } void print_debug(PARSER *p) { FIELD_DESCRIPTION *fd; FIELD_FUNCTION *ff; char rdline[81]; printf("\n Debug information for Parser\n"); printf(" infile = (%s)\n",p->infile); printf(" outfile = (%s)\n",p->outfile); printf(" profile = (%s)\n",p->profile); printf(" print_column_names = %d\n",p->print_column_names); printf(" output_format = %d\n",p->output_format); printf(" record_per_file = %d\n",p->record_per_file); printf(" filename_field = (%s)\n",p->filename_field); printf(" input_file_type = %d\n",p->input_file_type); printf(" input_field_delimiter = (%c)\n",p->input_field_delimiter); printf(" input_text_delimiter = (%c)\n",p->input_text_delimiter); printf(" record_cnt = %d\n",p->record_cnt); printf(" field_delimiter = (%s)\n",p->field_delimiter); printf(" record_delimiter = (%s)\n",p->record_delimiter); printf(" start_of_text_char = (%s)\n",p->start_of_text_char); printf(" end_of_text_char = (%s)\n",p->end_of_text_char); printf(" record_length = %d\n",p->record_length); printf(" string_date = (%s)\n",p->string_date); printf(" string_time = (%s)\n",p->string_time); printf(" nbr_field = %d\n",p->nbr_field); printf(" Field Descriptions\n"); printf(" %-30s %3s %3s %1s %3s\n","name","s-p", "len","t","prn"); for (fd = p->fd ; fd != (FIELD_DESCRIPTION *) NULL ; fd = fd->next) { if (fd->field_type == FIELD_NORMAL) { printf("N %30s %3d %3d %1d %3d\n",fd->name,fd->start_position, fd->length,fd->type,fd->print_order); } else if (fd->field_type == FIELD_TEXT) { printf("T %30s %3s %3s %1s %3d (%s)\n",fd->name," "," "," ", fd->print_order,fd->data); } else if (fd->field_type == FIELD_COUNTER) { printf("C %30s %3s %3s %1s %3d\n",fd->name," "," "," ",fd->print_order); } else if (fd->field_type == FIELD_FILENAME_FIELD) { printf("F %30s %3s %3s %1s %3d\n",fd->name," "," "," ",fd->print_order); } else if (fd->field_type == FIELD_LOOKUP) { printf("L %30s %3s %3s %1s %3d (%s %s %d)\n",fd->name," "," "," ", fd->print_order,fd->arg1,fd->field_lookup->name,fd->start_position); } else if (fd->field_type == FIELD_DATE) { printf("D %30s %3s %3s %1s %3d (%s)\n",fd->name," "," "," ", fd->print_order,fd->data); } else if (fd->field_type == FIELD_TIME) { printf("T %30s %3s %3s %1s %3d (%s)\n",fd->name," "," "," ", fd->print_order,fd->data); } for (ff = fd->ff ; ff != (FIELD_FUNCTION *) NULL ; ff = ff->next) print_field_function(ff,fd,stdout); } } FIELD_DESCRIPTION *alloc_Field_Description(void) { FIELD_DESCRIPTION *fd; fd = (FIELD_DESCRIPTION *) calloc((size_t)1,sizeof(FIELD_DESCRIPTION)); if (fd == (FIELD_DESCRIPTION *) NULL) { fprintf(stderr,"\n *** ERROR : Out of memory in alloc_Field_Description\n"); exit(EXIT_FAILURE); } fd->name = (char *) NULL; fd->calculate_flag = CALCULATE_NO; fd->field_type = FIELD_UNDEFINED; fd->start_position = 0; fd->length = 0; fd->type = TEXT; /* TEXT or NUMBER or STRING */ fd->print_order = 0; fd->data = (char *) NULL; /* array for holding the data */ fd->arg1 = (char *) NULL; /* arrays for holding arguments */ fd->field_lookup = (FIELD_DESCRIPTION *) NULL; /* field description for field_lookup */ fd->fluf = (FILE *) NULL; /* input stream for field_lookup */ fd->data_length = 0; /* length of the array */ fd->ff = (FIELD_FUNCTION *) NULL; /* linked list of functions to perform on field */ fd->next = (FIELD_DESCRIPTION *) NULL; /* next link in the linked list */ return fd; } FIELD_DESCRIPTION *find_field_description(FIELD_DESCRIPTION *bfd,char *field_name) { FIELD_DESCRIPTION *fd; for (fd = bfd ; fd != (FIELD_DESCRIPTION *) NULL ; fd = fd->next) { if (strcmp(field_name,fd->name) == 0) break; } return fd; } void strstrip(char *s) { char *ps,*ns; /* find the first non space character */ for (ps = s ; isspace(*ps) != 0 ; ps++); /* copy the bytes */ for (ns = s ; *ps != (char) NULL ; ps++,ns++) *ns = *ps; *ns = (char) NULL; /* NULL terminate */ if (ns == s) /* blank line, thus we are done */ return; ns--; /* go back one space */ while (isspace(*ns)) /* work backwards from the end to eliminate spaces */ { *ns = (char) NULL; if (ns == s) break; ns--; } } /* astoc returns the first character of rd if it is not \, otherwise it returns the applicable escape code or the character following the \ if an escape code is not defined, nrd is the pointer to the first character in rd that is not converted */ char astoc(char *rd,char **nrd) { char c; /* get the character */ if (*rd == '\\') { if (*(rd+1) == 'a') c = '\a'; else if (*(rd+1) == 'b') c = '\b'; else if (*(rd+1) == 'f') c = '\f'; else if (*(rd+1) == 'n') c = '\n'; else if (*(rd+1) == 'r') c = '\r'; else if (*(rd+1) == 't') c = '\t'; else if (*(rd+1) == 'v') c = '\v'; else if (*(rd+1) == (char) NULL) /* if line ends, then use a space */ c = ' '; else c = *(rd+1); if (nrd != (char **) NULL) *nrd = rd + 2; } else { c = *rd; if (nrd != (char **) NULL) *nrd = rd + 1; } return c; } /* stoc() reads the first character of rdline that is a non whitespace. if the first character is $, then it is skipped and the next character is used unless that next character is \ in which case the next two characters are used to define a control character. If the first character is a number or the letters a-f, then the first two bytes are assumed to be a hex representation of the character. Otherwise the routine returns NULL */ char stoc(char *rdline,char **ptr) { char *sptr; int hi_nyble; int lo_nyble; char c; /* skip leading spaces */ for (sptr = rdline ; isspace((int) *sptr) ; sptr++); /* check for a character */ if (*sptr == '$') { sptr++; return astoc(sptr,ptr); } hi_nyble = chtoi(*sptr); lo_nyble = chtoi(*(sptr+1)); if (hi_nyble < 0) { if (ptr != (char **) NULL) *ptr = sptr; return (char) NULL; } c = (char) hi_nyble; sptr++; if (lo_nyble < 0) { if (ptr != (char **) NULL) *ptr = sptr; return c; } sptr++; c = (char)(hi_nyble * 16 + lo_nyble); if (ptr != (char **) NULL) *ptr = sptr; return c; } int chtoi(char c) { char hex[17] = "0123456789ABCDEF"; char ch; int i; ch = (char) toupper((int) c); for (i=0 ; hex[i] != ch && i < 16 ; i++); if (i == 16) return -1; return i; } /* FUNCTION_UNDEFINED 0 FUNCTION_STRIP 1 FUNCTION_REORDER 2 FUNCTION_DELETE_CHAR 3 FUNCTION_DELETE_LEFT 4 FUNCTION_DELETE_RIGHT 5 FUNCTION_DELETE_ALPHA 6 FUNCTION_DELETE_NONALPHA 7 FUNCTION_DELETE_NUMERIC 8 FUNCTION_DELETE_NONNUMERIC 9 FUNCTION_KEEP_LEFT 10 FUNCTION_KEEP_RIGHT 11 FUNCTION_INSERT_LEFT 12 FUNCTION_INSERT_RIGHT 13 FUNCTION_REPLACE_CHAR 14 */ void print_field_function(FIELD_FUNCTION *ff,FIELD_DESCRIPTION *fd,FILE *out) { int i; if (ff->type == FUNCTION_STRIP) fprintf(out,"strip %s\n",fd->name); else if (ff->type == FUNCTION_REORDER) { fprintf(out,"reorder %s",fd->name); for (i = 0 ; i < ff->arg ; i++) { fprintf(out," "); if (ff->array[i] < 256) { fprintf(out,"$"); print_arg(ff->array[i],out); } else fprintf(out,"%d",ff->array[i]-256); } fprintf(out,"\n"); } else if (ff->type == FUNCTION_DELETE_CHAR) { fprintf(out,"delete_char %s ",fd->name); fprintf(out,"$"); print_arg(ff->arg,out); fprintf(out,"\n"); } else if (ff->type == FUNCTION_DELETE_LEFT) fprintf(out,"delete_left %s %d\n",fd->name,ff->arg); else if (ff->type == FUNCTION_DELETE_RIGHT) fprintf(out,"delete_right %s %d\n",fd->name,ff->arg); else if (ff->type == FUNCTION_DELETE_ALPHA) fprintf(out,"delete_alpha %s\n",fd->name); else if (ff->type == FUNCTION_DELETE_NONALPHA) fprintf(out,"delete_nonalpha %s\n",fd->name); else if (ff->type == FUNCTION_DELETE_NUMERIC) fprintf(out,"delete_numeric %s\n",fd->name); else if (ff->type == FUNCTION_DELETE_NONNUMERIC) fprintf(out,"delete_nonnumeric %s\n",fd->name); else if (ff->type == FUNCTION_KEEP_LEFT) fprintf(out,"keep_left %s %d\n",fd->name,ff->arg); else if (ff->type == FUNCTION_KEEP_RIGHT) fprintf(out,"keep_right %s %d\n",fd->name,ff->arg); else if (ff->type == FUNCTION_INSERT_LEFT) { fprintf(out,"insert_left %s ",fd->name); print_array(ff->array,ff->arg,out); fprintf(out,"\n"); } else if (ff->type == FUNCTION_INSERT_RIGHT) { fprintf(out,"insert_right %s ",fd->name); print_array(ff->array,ff->arg,out); fprintf(out,"\n"); } else if (ff->type == FUNCTION_REPLACE_CHAR) { fprintf(out,"replace_char %s ",fd->name); fprintf(out,"$"); print_arg(ff->array[0],out); fprintf(out," "); fprintf(out,"$"); print_arg(ff->array[1],out); fprintf(out,"\n"); } else if (ff->type == FUNCTION_REPLACE_TEXT) { int l2; fprintf(out,"replace_text %s ",fd->name); print_array(ff->array,ff->arg-1,out); fprintf(out," "); for (l2 = 0 ; ff->array[l2+ff->arg] != (int) NULL ; l2++); print_array(ff->array+ff->arg,l2,out); fprintf(out,"\n"); } else if (ff->type == FUNCTION_PAD_RIGHT) fprintf(out,"pad_right %s %d\n",fd->name,ff->arg); else if (ff->type == FUNCTION_PAD_LEFT) fprintf(out,"pad_left %s %d\n",fd->name,ff->arg); else if (ff->type == FUNCTION_TO_UPPER_CASE) fprintf(out,"to_upper_case %s\n",fd->name); else if (ff->type == FUNCTION_TO_LOWER_CASE) fprintf(out,"to_lower_case %s\n",fd->name); else fprintf(out,"<> %s\n",fd->name); } void print_array(int *array,int arg,FILE *out) { int i; for (i=0 ; i < arg ; i++) print_arg(array[i],out); } void print_arg(int arg,FILE *out) { if ((char) arg == '\a') fprintf(out,"\\a"); else if ((char) arg == '\b') fprintf(out,"\\b"); else if ((char) arg == '\f') fprintf(out,"\\f"); else if ((char) arg == '\n') fprintf(out,"\\n"); else if ((char) arg == '\r') fprintf(out,"\\r"); else if ((char) arg == '\t') fprintf(out,"\\t"); else if ((char) arg == '\v') fprintf(out,"\\v"); else if ((char) arg == '\\') fprintf(out,"\\\\"); else fprintf(out,"%c",(char)arg); } void convert_escape_string(char *s) { int i,j; for (i = 0 ; s[i] != (char) NULL ; i++) { if (s[i] == '\\') { if (s[i+1] == (char) NULL) { s[i] = ' '; break; } /* move all the characters left one */ for (j = i ; s[j] != (char) NULL ; j++) s[j] = s[j+1]; /* do the conversions */ if (s[i] == (int) 'a') s[i] = '\a'; else if (s[i] == (int) 'b') s[i] = '\b'; else if (s[i] == (int) 'f') s[i] = '\f'; else if (s[i] == (int) 'n') s[i] = '\n'; else if (s[i] == (int) 'r') s[i] = '\r'; else if (s[i] == (int) 't') s[i] = '\t'; else if (s[i] == (int) 'v') s[i] = '\v'; } } } void extract_filename_base(char *filename, char *filebase) { int i; if (filename == (char *) NULL || filebase == (char *) NULL) return; /* find the start of the filename */ for (i = strlen(filename) ; i >= 0 ; i--) { if (filename[i] == '/' || filename[i] == '\\') break; } /* i is one less than the start of the filename */ i++; /* copy the output filename */ strcpy(filebase,filename + i); /* find the . delimiter and truncate the filename there */ for (i = strlen(filebase) ; i > 0 ; i--) { if (filebase[i] == '.') { filebase[i] = (char) NULL; break; } } }