// Includes #include #include #include #include #include "..\x_str.h" // Global Variables char* gps_output_write = "wb"; int gpb_output_append = false; int gpi_match_text = 0; int gpi_match_field = 0; int gpi_project_field = 0; // Type Defintions // DBF Header Format typedef struct struct_DBF_HEADER { char i_ver; char i_year; char i_mon; char i_day; int i_rec_count; short i_header_size; short i_rec_length; } type_DBF_HEADER; // DBF Field Defintion Formation typedef struct struct_DBF_FIELDS { char s_name[11]; char s_type; unsigned int i_fda; unsigned char i_field_len; unsigned char i_field_decimal; char s_discard[14]; } type_DBF_FIELDS; //---------------------------------------------------------------------------- // Functions // long ifn_file_slurp( char* ps_file_name, char** ps_buffer ) { FILE* fp = fopen( ps_file_name, "rb" ); long i_file_len = 0; if (fp != NULL) { if (fseek(fp, 0L, SEEK_END) == 0) { long i_bufsize = ftell(fp); if (i_bufsize == -1) { fprintf( stderr, "Error reading file - i_bufsize !" ); } if ( *ps_buffer != NULL ) { free(*ps_buffer); } *ps_buffer = malloc(sizeof(char) * (i_bufsize + 1)); if (fseek(fp, 0L, SEEK_SET) != 0) { fputs("Error reading file - SEEK_SET !", stderr ); } i_file_len = fread(*ps_buffer, sizeof(char), i_bufsize, fp); if (i_file_len == 0) { fprintf( stderr, "Error reading file - i_file_len !" ); } else { (*ps_buffer)[++i_file_len] = '\0'; } } fclose(fp); } else { fprintf( stderr, "Error finding file - Input file doesn't exist !\n"); } return (i_file_len); } // //---------------------------------------------------------------------------- // void fn_help() { // --------- printf("\nUsage: ci_dbf input_file.DBF output_file.TXT []\n\n"); printf("Options:\n"); printf("\t/m {value}\tOutputs records containing {value}.\n"); printf("\t/f {field}\tLimit match to {field}.\n"); printf("\t/app\t\tAppend to output file. Does not print field names.\n"); printf("\t/prj {project}\tAdds a PROJECT field. Each record has {project} include in the output.\n"); printf("\t/fmt\t\tFormat numeric fields - right align ..\n"); printf("\t/?\t\tThis help text.\n"); return; } // //---------------------------------------------------------------------------- // int main(int pi, char **ps ) { printf("\nCI_DBF.EXE - v2025.08.09a : Convert DBF to TabTXT\n"); // Input Checks int pi_field_match = -1; // Options int i = 1; while( i < pi ) { if (( strncmp("/?" , ps[i], 2) == 0)) { fn_help(); return(0); } if (( strncmp("/app", ps[i], 4) == 0)) { gps_output_write = "ab"; gpb_output_append = true; } if (( strncmp("/m" , ps[i], 2) == 0)) { gpi_match_text = i + 1; } if (( strncmp("/f" , ps[i], 2) == 0)) { gpi_match_field = i + 1; } if (( strncmp("/prj", ps[i], 4) == 0)) { gpi_project_field = i + 1; } i++; } if ( gpi_match_text > 0 ) { if ( ps[gpi_match_text] ) { x_fn_str_upper( ps[gpi_match_text] ); }} if ( gpi_match_field > 0) { if ( ps[gpi_match_field] ) { pi_field_match = atoi( ps[gpi_match_field] ); }} // Main arguments if ( !ps[1] ) { fprintf( stderr, "No input file !\n" ); return( -1 ); } if ( !ps[2] ) { fprintf( stderr, "No output file !\n" ); return( -1 ); } // Header printf( "\nReading .. %s\n", ps[1] ); char* s_file = NULL; long i_file_size_bytes = ifn_file_slurp( ps[1], &s_file ); if ( i_file_size_bytes < 1 ) { return( -1 ); } type_DBF_HEADER* xo_dbf_header = (type_DBF_HEADER*) &s_file[0]; //xo_dbf_header = (type_DBF_HEADER*) &s_file[0]; printf( "\nVer: %d" , xo_dbf_header->i_ver ); printf( "\nLast Mod: %d-%02d-%02d" , (xo_dbf_header->i_year + 1900), xo_dbf_header->i_mon, xo_dbf_header->i_day ); printf( "\nNumber of Records: %ld" , xo_dbf_header->i_rec_count ); printf( "\nHeader Size: %d" , xo_dbf_header->i_header_size ); printf( "\nRecord Length: %d" , xo_dbf_header->i_rec_length ); printf( "\nDBF Size Length: %d" , xo_dbf_header->i_header_size + ( xo_dbf_header->i_rec_count * xo_dbf_header->i_rec_length ) ); // Columns -- Fields printf( "\n\nWriting ..%s\n", ps[2] ); char s_EOL = 13; FILE* fp = fopen( ps[2], gps_output_write ); type_DBF_FIELDS* xo_dbf_fields[128]; int i_field = 0; long i_file_index = 32; long i_buf = 0; long i_fda_calc = 1; char* s_buf; s_buf = malloc( xo_dbf_header->i_rec_length + 50 ); if ( gpi_project_field == 0 ) { i_buf = snprintf ( s_buf, 10, "#\tDEL\t" ); } else { i_buf = snprintf ( s_buf, 60, "#\tPROJECT\tDEL\t" ); } if ( !gpb_output_append ) { fwrite( s_buf, i_buf, 1, fp ); } while ( s_file[i_file_index] != 0x0d ) { xo_dbf_fields[i_field] = (type_DBF_FIELDS*) &s_file[i_file_index]; xo_dbf_fields[i_field]->i_fda = i_fda_calc; printf ( "\n%d\t%10s\t%c\t%d\t%d\t%d" , i_field , xo_dbf_fields[i_field]->s_name , xo_dbf_fields[i_field]->s_type , xo_dbf_fields[i_field]->i_fda , xo_dbf_fields[i_field]->i_field_len , xo_dbf_fields[i_field]->i_field_decimal ); i_fda_calc += xo_dbf_fields[i_field]->i_field_len; i_buf = snprintf ( s_buf, 50, "%s (%c,%d)\t" , xo_dbf_fields[i_field]->s_name , xo_dbf_fields[i_field]->s_type , xo_dbf_fields[i_field]->i_field_len ); if ( !gpb_output_append ) { fwrite( s_buf, i_buf, 1, fp ); } i_field++; i_file_index += 32; } if ( !gpb_output_append ) { fwrite( &s_EOL, 1, 1, fp ); } int i_field_count = i_field; printf( "\n\n%d fields.", i_field_count ); // Rows -- Records char* s_rec; char* s_rec_upper; long i_rec = 0; long i_match = 0; char* s_match; char s_field[300]; // Each field can be a max of 254 characters char* s_field_upper; char* s_match_field; int i_match_field; int i_space; s_rec = malloc( xo_dbf_header->i_rec_length + 1 ); while ( i_rec < xo_dbf_header->i_rec_count ) { memcpy( s_rec, &s_file[xo_dbf_header->i_header_size + ( i_rec * xo_dbf_header->i_rec_length ) ], xo_dbf_header->i_rec_length ); s_rec[xo_dbf_header->i_rec_length] = '\0'; s_match = s_rec; if ( gpi_match_text > 0 ) { s_rec_upper = x_sfn_str_upper( s_rec ); s_match = strstr( s_rec_upper, ps[gpi_match_text] ); free( s_rec_upper ); } if ( s_match ) { if ( gpi_project_field == 0 ) { i_buf = snprintf ( s_buf, 10, "%d\t%c\t", (i_rec + 1), s_rec[0] ); } else { i_buf = snprintf ( s_buf, 60, "%d\t%s\t%c\t", (i_rec + 1), ps[gpi_project_field], s_rec[0] ); } i_field = 0; i_match_field = 0; while ( i_field < i_field_count ) { memcpy( s_field, &s_rec[xo_dbf_fields[i_field]->i_fda], xo_dbf_fields[i_field]->i_field_len ); // Trim trailing whitespace i_space = xo_dbf_fields[i_field]->i_field_len; s_field[i_space] = 0x020; while (( s_field[i_space] == 0x020 ) && ( i_space >= 0 )) { i_space--; } s_field[i_space + 1] = '\0'; // Check for matching field s_match_field = s_field; if ( pi_field_match == i_field ) { s_field_upper = x_sfn_str_upper( s_field ); s_match_field = strstr( s_field_upper, ps[gpi_match_text] ); free( s_field_upper ); } if ( s_match_field ) { i_match_field++; } // Add field data to output buffer i_buf += snprintf ( &s_buf[i_buf], xo_dbf_header->i_rec_length - i_buf, "%s\t" , s_field ); i_field++; } if ( i_match_field == i_field_count ) { i_match++; fwrite( s_buf, i_buf - 1, 1, fp ); fwrite( &s_EOL, 1, 1, fp ); } } i_rec++; } printf( "\n%d matched records.", i_match ); printf( "\n" ); // Program End fclose( fp ); free( s_rec ); free( s_buf ); free( s_file ); return( 0 ); } // //----------------------------------------------------------------------------