/*----------------------------------------------------------------------
* file_tool.c - display or modify (binary?) info in files
*
* This is a pretty generic file processing tool, originally designed
* to display and modify data at random places in files, and also to
* deal with GEMS 5.x image files (e.g. being able to replace subject
* names with 'x's).
*
* options:
*
* special options:
*
* -help display help
* -help_ge display help on GE info structures
* -hist display history
* -debug LEVEL show extra info (0, 1 or 2)
* -version show version information
*
* required 'options':
*
* -infiles file1 ... specify files to display/alter
*
* GE info options
*
* -ge_all display GE header and extras info
* -ge_header display GE header info
* -ge_extras display extra GE image info
* -ge_uv17 diplay the value of the uv17 variable
* -ge_run diplay the run number - same as uv17
* -ge_off diplay file offsets for various fields
*
* GEMS 4.x options
*
* -ge4_all display GEMS 4.x series and image headers
* -ge4_series display GEMS 4.x series header
* -ge4_image display GEMS 4.x image header
*
* script file options:
*
* -show_bad_backslash show any lines with only whitespace after '\'
* -show_file_type show whether UNIX, Mac or MS file type
*
* raw ascii options:
*
* -length LENGTH number of bytes to display/modify
* -mod_data DATA specify modification data
* -mod_type TYPE specify modification with a value or string
* -offset OFFSET display/modify from OFFSET bytes into files
* -quiet do not display header info with output
*
* numeric options:
*
* -disp_int2 display data as 2-byte integers
* -disp_int4 display data as 4-byte integers
* -disp_real4 display data as 4-byte floats
* -swap_bytes use byte swapping for numbers
*
* examples:
*
* file_tool -help
* file_tool -help_ge
* file_tool -ge_all -infiles I.100
* file_tool -ge_run -infiles I.?42
* file_tool -offset 100 -length 32 -infiles file1 file2
* file_tool -offset 100 -length 32 -quiet -infiles file1 file2
* file_tool -disp_int2 -swap -offset 1024 -length 16 -infiles file3
* file_tool -mod_data "hi there" -offset 2515 -length 8 -infiles I.*
* file_tool -debug 1 -mod_data x -mod_type char -offset 2515 \
* -length 21 -infiles I.*
*----------------------------------------------------------------------
*/
static char g_history[] =
"----------------------------------------------------------------------\n"
" file_tool history:\n"
"\n"
" 1.0 September 11, 2002\n"
" - initial release\n"
"\n"
" 1.1 February 26, 2003\n"
" - added -quiet option\n"
" - use dynamic allocation for data to read\n"
"\n"
" 1.2 May 06, 2003 (will go to 2.0 after more changes are made)\n"
" - added interface for reading GEMS 4.x formatted image files\n"
" - added corresponding options -ge4_all, -ge4_image, -ge4_series\n"
" - added options to display raw numeric data:\n"
" disp_int2, disp_int4, disp_real4\n"
" - changed local version of l_THD_filesize to THD_filesize, as\n"
" the ge4_ functions may get that from mrilib.\n"
"\n"
" 2.0 May 29, 2003\n"
" - added information for ge4 study header\n"
" - added option -ge4_study\n"
"\n"
" 2.1 June 02, 2003\n"
" - changed format of call to ge4_read_header()\n"
" - made swap_[24]() static\n"
"\n"
" 2.2 July 27, 2003\n"
" - wrap unknown printed strings in NULL check\n"
"\n"
" 3.0 March 17, 2004\n"
" - added binary editing (gee, that's why I wrote it 18 months ago...)\n"
" (see -mod_type s/uint1, s/uint2, s/uint4, float4, float8\n"
" - added '-ge_off' option, to display offsets for some GEMS fields\n"
" - added '-hist' option, to display this history\n"
"\n"
" 3.1 March 17, 2004 - only check length against data_len for string mods\n"
" 3.2 March 24, 2004\n"
" - only check max length when modifying data (thanks, PSFB)\n"
" 3.2a March 22, 2005 - removed all tabs\n"
" 3.3 June 8, 2007 - added -show_bad_backslash and -show_file_type\n"
" 3.4 June 8, 2007 - added examples for 3.3 update\n"
"----------------------------------------------------------------------\n";
#define VERSION "3.4 (Jun 13, 2007)"
/* ----------------------------------------------------------------------
* todo:
*
* - add option '-help_ge4'
* ----------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "file_tool.h"
#include "ge4_header.h"
char g_rep_output_data[MAX_STR_LEN]; /* in case user doesn't pass it in */
static int swap_2 ( void * ptr );
static int swap_4 ( void * ptr );
/*------------------------------------------------------------
* - check that the program is used correctly
* - fill the param_t struct, based on user inputs
* - process the files (display/modify data from/in each file)
*------------------------------------------------------------
*/
int main ( int argc, char * argv[] )
{
param_t P;
int rv;
if ( (rv = set_params( &P, argc, argv ) ) < 0 )
return rv;
else if ( rv > 0 )
return 0;
if ( (rv = attack_files( &P ) ) != 0 )
return rv;
return 0;
}
/*------------------------------------------------------------
* - foreach file
* - if we are displaying GE info, do so
* - else, display/modify pertinent data
*------------------------------------------------------------
*/
int
attack_files( param_t * p )
{
int fc, rv;
for ( fc = 0; fc < p->num_files; fc++ )
{
if ( p->ge_disp )
{
if ( (rv = process_ge( p->flist[fc], p )) != 0 )
return rv;
}
else if ( p->ge4_disp )
{
if ( (rv = process_ge4( p->flist[fc], p )) != 0 )
return rv;
}
else if ( p->script )
{
if ( (rv = process_script( p->flist[fc], p )) != 0 )
return rv;
}
else if ( ( rv = process_file( p->flist[fc], p) ) != 0 )
return rv;
}
return 0;
}
/*------------------------------------------------------------
* Do the processing for script files:
*------------------------------------------------------------
*/
int
process_script( char * filename, param_t * p )
{
int rv;
if ( p->script & SCR_SHOW_FILE ) rv = scr_show_file (filename, p);
if (!rv && p->script & SCR_SHOW_BAD_BS) rv = scr_show_bad_bs(filename, p);
return rv;
}
/*------------------------------------------------------------
* Scan file for: '\\' then whitespace then '\n'
*------------------------------------------------------------*/
int
scr_show_bad_bs( char * filename, param_t * p )
{
static char * fdata = NULL;
static int flen = 0;
char * line_start, *cp;
int count, cur, bcount = 0, bad = 0;
int lnum = 1;
if( read_file( filename, &fdata, &flen ) < 0 ) return -1;
if( p->debug ) fprintf(stderr,"--- file %s ---\n",filename);
line_start = fdata;
for( count = 0; count < flen; /* in loop */ )
{
/* note beginning of line (it's the next char) */
if( fdata[count] == '\n' ){ line_start = fdata+count+1; lnum++; }
if( fdata[count] != '\\' ){ count++; continue; }
/* found a '\\' char, count it and look beyond */
bcount++; count++;
/* skip any whitespace */
cur = count;
while( fdata[count] != '\n' && isspace(fdata[count]) ) count++;
if( count == cur || fdata[count] != '\n' ) /* we're okay */
continue;
bad++;
/* this line is bad, and we're looking at '\n' */
if( !p->quiet )
{
printf("bad line @ %4d: ", lnum);
for( cp = line_start; cp <= fdata+count; cp++)
putchar(*cp);
}
}
if(p->debug > 0) fprintf(stderr,"file %s: %d bad lines\n",filename,bad);
if(bad > 255) bad = 255; /* limit on exit status */
return bad;
}
/*------------------------------------------------------------
* Scan file for 0x0d characters ('\r').
* dos: \r\n
* mac: \r
* unix: else
*------------------------------------------------------------*/
int
scr_show_file( char * filename, param_t * p )
{
static char * fdata = NULL;
static int flen = 0;
char * cp;
int length, count, bin = 0;
if( p->debug ) fprintf(stderr,"--- file %s ---\n",filename);
if( (length = read_file( filename, &fdata, &flen )) < 0 ) return -1;
if( p->debug ) fprintf(stderr,"file length = %d\n", length);
for( cp = fdata, count = 0; count < length; count++ )
{
if( !isprint(cp[count]) && !isspace(cp[count]) )
{
if( bin == 0 )
{
bin = 1;
if( !p->quiet )
fprintf(stderr,"file '%s' has non-printable chars",
filename);
}
if( p->debug ) fprintf(stderr,": %d (0x%0x)",cp[count],cp[count]);
else fputc('\n',stderr);
}
if( cp[count] != '\r' ) continue;
if( count <= length && cp[count+1] == '\n' ) /* dos type */
{
if( p->debug )
fprintf(stderr,"found 0x0d0a char pair at offset %d\n",count);
printf("%s file type: DOS\n", filename);
return 0;
}
else /* mac type */
{
if( p->debug )
fprintf(stderr,"found 0x0d char at offset %d\n",count);
printf("%s file type: MAC\n", filename);
return 0;
}
}
printf("%s file type: UNIX\n", filename);
return 0;
}
/*------------------------------------------------------------
* Inhale the file. Update fdata and flen if need be.
* return the file size
*------------------------------------------------------------*/
int
read_file( char * filename, char ** fdata, int * flen )
{
FILE * fp;
int length, nbytes;
if( !filename || !fdata || !flen )
{
fprintf(stderr,"** read_file: bad Ptrs %p,%p,%p\n",filename,fdata,flen);
return -1;
}
length = THD_filesize(filename);
/* see if we need to update space */
if ( *flen < length )
{
*fdata = (char*) realloc( *fdata, length * sizeof(char) );
if ( *fdata == NULL )
{
fprintf( stderr, "failure: cannot allocate %d bytes for data\n",
length );
return -1;
}
*flen = length;
}
/* open, read, close */
if ( (fp = fopen( filename, "r" )) == NULL )
{
fprintf( stderr, "failure: cannot open <%s> for 'r'\n", filename );
return -1;
}
nbytes = fread( *fdata, 1, length, fp );
fclose( fp );
if ( nbytes != length )
{
fprintf( stderr, "failure: read only %d of %d bytes from file '%s'\n",
nbytes, length, filename );
return -1;
}
return length;
}
/*------------------------------------------------------------
* Run the relevant GEMS 4.x processing functions.
*------------------------------------------------------------
*/
int
process_ge4( char * filename, param_t * p )
{
ge4_header H;
int rv;
rv = ge4_read_header( &H, filename, 0 );
if ( rv != 0 )
{
if ( p->ge4_disp ) /* then display the bad result */
{
printf( "%s : GEMS 4.x header failure : %d\n", filename, rv );
return 0;
}
else /* else just return it */
return -1;
}
if ( (p->debug > 1) || (p->ge4_disp & GE4_DISP_STUDY) )
idisp_ge4_study_header( filename, &H.std_h );
if ( (p->debug > 1) || (p->ge4_disp & GE4_DISP_SERIES) )
idisp_ge4_series_header( filename, &H.ser_h );
if ( (p->debug > 1) || (p->ge4_disp & GE4_DISP_IMAGE) )
idisp_ge4_image_header( filename, &H.im_h );
return 0;
}
/*------------------------------------------------------------
* Run the relevant GE processing functions.
*------------------------------------------------------------
*/
int
process_ge( char * filename, param_t * p )
{
ge_header_info H;
ge_extras E;
ge_off off;
int rv;
rv = read_ge_header( filename, &H, &E, &off );
if ( rv != 0 )
{
if ( p->ge_disp ) /* if we are here to display - state results */
{
printf( "%s : GE header failure : %d\n", filename, rv );
return 0; /* don't fail out */
}
else
return -1; /* else, just return the results */
}
if ( (p->debug > 1) || (p->ge_disp & GE_HEADER) )
r_idisp_ge_header_info( filename, &H );
if ( (p->debug > 1) || (p->ge_disp & GE_EXTRAS ) )
r_idisp_ge_extras( filename, &E );
if ( p->ge_disp & GE_OFF )
disp_ge_offsets( filename, &off );
if ( p->ge_disp & GE_UV17 )
printf( "%s : run # %d\n", filename, H.uv17 );
return 0;
}
/*------------------------------------------------------------
* Do the processing for the given file:
*
* - open the file
* - go to the user-specified offset (may be 0)
* - read the relevant number of bytes
* - if display info, print out data
* - if modifying, go back to 'offset' and write data
* - close file
*------------------------------------------------------------
*/
int
process_file( char * filename, param_t * p )
{
FILE * fp;
static char * fdata = NULL;
static int flen = 0;
int nbytes;
int length; /* either p->length or file size */
/* if passed length was not given, init to filesize */
if ( p->length > 0 ) length = p->length;
else length = THD_filesize(filename);
if ( (fp = fopen( filename, "r+" )) == NULL )
{
fprintf( stderr, "failure: cannot open <%s> for 'rw'\n", filename );
return -1;
}
if ( flen < length )
{
fdata = (char*) realloc( fdata, length * sizeof(char) );
if ( fdata == NULL )
{
fprintf( stderr, "failure: cannot allocate %d bytes for data\n",
length );
return -1;
}
flen = length;
}
if ( fseek( fp, p->offset, SEEK_SET ) )
{
fprintf( stderr, "failure: cannot seek to <%ld> in file '%s'\n",
p->offset, filename );
fclose( fp );
return -1;
}
if ( (nbytes = fread( fdata, 1, length, fp )) != length )
{
fprintf( stderr, "failure: read only %d of %d bytes from file '%s'\n",
nbytes, length, filename );
fclose( fp );
return -1;
}
/* display file contents */
if ( !p->modify || p->debug )
{
if ( ! p->quiet && ! p->ndisp )
printf( "<%s> : '", filename );
/* handle the numeric display */
if ( p->ndisp )
{
if ( disp_numeric_data( fdata, p, stdout ) )
{
fclose( fp );
return -1;
}
}
else if ( (nbytes = fwrite(fdata, 1, length, stdout)) != length )
{
fprintf( stderr, "\nfailure: wrote only %d of %d bytes to '%s'\n",
nbytes, length, "stdout" );
fclose( fp );
return -1;
}
if ( ! p->quiet && ! p->ndisp )
puts( "'" ); /* single quote plus newline */
}
if ( p->modify ) /* if writing back to file */
{
if ( fseek( fp, p->offset, SEEK_SET ) )
{
fprintf( stderr, "failure: cannot re-seek to <%ld> in file '%s'\n",
p->offset, filename );
fclose( fp );
return -1;
}
if ( (nbytes = write_data_to_file( fp, filename, p, length ) ) < 0 )
{
fclose( fp );
return -1;
}
if ( p->debug > 0 )
{
printf( "wrote '%s' (%d bytes) to file '%s', position %ld\n",
p->mod_data, length, filename, p->offset );
}
}
fclose( fp );
return 0;
}
/*------------------------------------------------------------
* Actually write data into the file stream.
*
* return bytes written : on success
* -1 : on error
*------------------------------------------------------------
*/
int write_data_to_file( FILE * fp, char * filename, param_t * p, int length )
{
double dval;
char * outp, * inp, * endp;
int dsize, c, nbytes;
if ( (dsize = mtype_size( p->mod_type )) < 1 )
{
fprintf(stderr,"** bad size %d for mod_type %d\n", dsize, p->mod_type);
return -1;
}
if ( p->debug > 1 )
fprintf(stderr,"-- dsize = %d\n", dsize);
/* deal with characters separately */
if ( p->mod_type == MOD_STR || p->mod_type == MOD_CHAR )
{
int remaining = length - p->data_len; /* note remainder (if any) */
if ( (nbytes=fwrite(p->mod_data, 1, p->data_len, fp)) != p->data_len )
{
fprintf( stderr, "\nfailure: wrote only %d of %d bytes to '%s'\n",
nbytes, p->data_len, filename );
fclose( fp );
return -1;
}
/* and fill with 0 */
for ( c = 0; c < remaining; c++ )
fputc( '\0', fp );
return length;
}
if ( p->debug > 1 ) fprintf(stderr,"++ values: ");
/* now write numerical values into g_rep_output_data */
outp = g_rep_output_data;
inp = p->mod_data;
memset(outp, 0, length);
for ( c = 0; (c+dsize) <= length; c += dsize, outp += dsize )
{
dval = strtod( inp, &endp );
if ( endp && inp != endp ) /* then we read something in */
{
switch (p->mod_type)
{
default:
fprintf(stderr,"** wdtf: bad type %d\n", p->mod_type);
return -1;
case MOD_U1:
*(unsigned char *)outp = (unsigned char)dval;
break;
case MOD_S1:
*(char *)outp = (char)dval;
break;
case MOD_U2:
*(unsigned short *)outp = (unsigned short)dval;
break;
case MOD_S2:
*(short *)outp = (short)dval;
break;
case MOD_U4:
*(unsigned long *)outp = (unsigned long)dval;
break;
case MOD_S4:
*(long *)outp = (long)dval;
break;
case MOD_F4:
*(float *)outp = (float)dval;
break;
case MOD_F8:
*(double *)outp = dval;
break;
}
if ( p->swap )
{
if ( dsize == 2 )
swap_2( (void *)outp );
else if ( dsize == 4 )
swap_4( (void *)outp );
}
if ( p->debug > 1 ) fprintf(stderr," %f", dval);
}
else
break; /* done */
inp = endp; /* prepare to go after a new number */
}
if ( p->debug > 1 ) fputc('\n', stderr);
/* now just write the data out */
nbytes = fwrite(g_rep_output_data, 1, length, fp);
if ( nbytes != length )
{
fprintf(stderr,"** wrote only %d of %d bytes of binary data\n",
nbytes, length);
return nbytes;
}
return length;
}
int mtype_size( int type )
{
if ( type == MOD_STR ) return 1;
if ( type == MOD_CHAR ) return 1;
if ( type == MOD_U1 ) return 1;
if ( type == MOD_S1 ) return 1;
if ( type == MOD_U2 ) return 2;
if ( type == MOD_S2 ) return 2;
if ( type == MOD_U4 ) return 4;
if ( type == MOD_S4 ) return 4;
if ( type == MOD_F4 ) return 4;
if ( type == MOD_F8 ) return 8;
return -1;
}
/*------------------------------------------------------------
* Read user arguments, and fill param_t struct.
*
* - if modifying, verify arguments
*------------------------------------------------------------
*/
int
set_params( param_t * p, int argc, char * argv[] )
{
int ac;
if ( argc < 2 )
{
usage( argv[0], USE_SHORT );
return -1;
}
if ( !p || !argv )
{
fprintf( stderr, "failure: bad params to set_params: "
"p = <%p>, ac = <%d>, av = <%p>\n",
p, argc, argv );
return -1;
}
/* clear out param struct - this sets all default values */
memset( p, 0, sizeof(*p) );
for ( ac = 1; ac < argc; ac++ )
{
/* check for -help_ge before -help, to allow for only -h */
if ( ! strncmp(argv[ac], "-help_ge", 8 ) )
{
usage( argv[0], USE_GE );
return -1;
}
else if ( ! strncmp(argv[ac], "-help", 3 ) )
{
usage( argv[0], USE_LONG );
return -1;
}
else if ( ! strncmp(argv[ac], "-hist", 3 ) )
{
usage( argv[0], USE_HISTORY );
return -1;
}
else if ( ! strncmp(argv[ac], "-debug", 6 ) )
{
if ( (ac+1) >= argc )
{
fputs( "missing option parameter: LEVEL\n"
"option usage: -debug LEVEL\n"
" where LEVEL is the debug level (0,1 or 2)\n",
stderr );
return -1;
}
p->debug = atoi(argv[++ac]);
if ( (p->debug < 0) || (p->debug > 2) )
{
fprintf( stderr, "invalid debug level <%d>\n", p->debug );
return -1;
}
}
else if ( ! strncmp(argv[ac], "-disp_int2", 10 ) )
{
p->ndisp |= NDISP_INT2;
}
else if ( ! strncmp(argv[ac], "-disp_int4", 10 ) )
{
p->ndisp |= NDISP_INT4;
}
else if ( ! strncmp(argv[ac], "-disp_real4", 11 ) )
{
p->ndisp |= NDISP_REAL4;
}
else if ( ! strncmp(argv[ac], "-mod_data", 6 ) )
{
if ( (ac+1) >= argc )
{
fputs( "missing option parameter: DATA\n"
"option usage: -mod_data DATA\n"
" where DATA is the replacement string or numbers\n",
stderr );
return -1;
}
ac++;
p->mod_data = argv[ac];
}
else if ( ! strncmp(argv[ac], "-mod_type", 6 ) )
{
if ( (ac+1) >= argc )
{
fputs( "missing option parameter: TYPE\n"
"option usage: -mod_type TYPE\n"
" where TYPE is 'val' or 'str'\n",
stderr );
return -1;
}
ac++;
if ( (p->mod_type = check_mod_type(argv[ac])) == MOD_INVALID )
{
fputs( "option usage: -mod_type TYPE\n", stderr );
fputs( " where TYPE is 'str' or 'val'\n", stderr );
return -1;
}
}
else if ( ! strncmp(argv[ac], "-offset", 4 ) )
{
if ( (ac+1) >= argc )
{
fputs( "missing option parameter: OFFSET\n"
"option usage: -offset OFFSET\n"
" where OFFSET is the file offset\n",
stderr );
return -1;
}
p->offset = atoi(argv[++ac]);
if ( p->offset < 0 )
{
fprintf( stderr, "bad file OFFSET <%ld>\n", p->offset );
return -1;
}
}
else if ( ! strncmp(argv[ac], "-length", 4 ) )
{
if ( (ac+1) >= argc )
{
fputs( "missing option parameter: LENGTH\n"
"option usage: -length LENGTH\n"
" where LENGTH is the length to display or modify\n",
stderr );
return -1;
}
p->length = atoi(argv[++ac]);
if ( p->length < 0 )
{
fprintf( stderr, "bad LENGTH <%d>\n", p->length );
return -1;
}
}
else if ( ! strncmp(argv[ac], "-quiet", 2 ) )
{
p->quiet = 1;
}
else if ( ! strncmp(argv[ac], "-show_bad_backslash", 9 ) )
{
p->script |= SCR_SHOW_BAD_BS;
}
else if ( ! strncmp(argv[ac], "-show_file_type", 10 ) )
{
p->script |= SCR_SHOW_FILE;
}
else if ( ! strncmp(argv[ac], "-swap_bytes", 3 ) )
{
p->swap = 1;
}
else if ( ! strncmp(argv[ac], "-ver", 2 ) )
{
usage( argv[0], USE_VERSION );
return 1;
}
else if ( ! strncmp(argv[ac], "-infiles", 4 ) )
{
if ( (ac+1) >= argc )
{
fputs( "missing input files...\n"
"option usage: -infiles file1 file2 ...\n",
stderr );
return -1;
}
ac++;
p->num_files = argc - ac;
p->flist = argv + ac;
break; /* input files finish the argument list */
}
/* continue with GE info displays */
else if ( ! strncmp(argv[ac], "-ge_all", 7 ) )
{
p->ge_disp |= GE_ALL;
}
else if ( ! strncmp(argv[ac], "-ge_header", 7 ) )
{
p->ge_disp |= GE_HEADER;
}
else if ( ! strncmp(argv[ac], "-ge_extras", 7 ) )
{
p->ge_disp |= GE_EXTRAS;
}
else if ( ! strncmp(argv[ac], "-ge_off", 7 ) )
{
p->ge_disp |= GE_OFF;
}
/* allow both forms - uv17 means the run number */
else if ( ! strncmp(argv[ac], "-ge_uv17", 7 ) ||
! strncmp(argv[ac], "-ge_run", 7 ) )
{
p->ge_disp |= GE_UV17;
}
/* continue with GEMS 4.x info displays */
else if ( ! strncmp(argv[ac], "-ge4_all", 7 ) )
{
p->ge4_disp |= GE4_DISP_ALL;
}
else if ( ! strncmp(argv[ac], "-ge4_image", 7 ) )
{
p->ge4_disp |= GE4_DISP_IMAGE;
}
else if ( ! strncmp(argv[ac], "-ge4_series", 8 ) )
{
p->ge4_disp |= GE4_DISP_SERIES;
}
else if ( ! strncmp(argv[ac], "-ge4_study", 8 ) )
{
p->ge4_disp |= GE4_DISP_STUDY;
}
/* finish with bad option */
else
{
fprintf( stderr, "error: unknown option, <%s>\n", argv[ac] );
return -1;
}
}
if ( p->debug > 1 )
disp_param_data( p );
if ( p->num_files <= 0 )
{
fputs( "error: missing '-infiles' option\n", stderr );
return -1;
}
/* if script, do not allow many other options */
if ( p->script && ( p->ge_disp || p->ge4_disp || p->ndisp || p->mod_data ) )
{
fputs( "error: no other operations with script\n",stderr);
return -1;
}
/* if only displaying GE data, no further check are necessary */
if ( p->ge_disp || p->ge4_disp )
return 0;
/* now do all other tests for displaying/modifying generic file data */
if ( p->mod_data )
{
p->modify = 1; /* so we plan to modify the data */
p->data_len = strlen(p->mod_data); /* note data length */
}
else
p->modify = 0; /* be explicit */
if ( p->length <= 0 && p->debug > 0 )
fputs( "warning: missing '-length' option, using file len\n", stderr );
if ( p->modify )
{
if ( p->length > MAX_STR_LEN )
{
fprintf( stderr, "failure: length <%d> exceeds maximum %d\n",
p->length, MAX_STR_LEN );
return -1;
}
if ( p->mod_type == MOD_CHAR )
{
/* we are writing one char length times */
memset( g_rep_output_data, *p->mod_data, p->length );
p->mod_data = g_rep_output_data;
p->data_len = p->length;
}
else if ( p->mod_type == MOD_STR && p->length < p->data_len )
{
fprintf( stderr, "failure: data length <%d> exceeds length <%d>\n",
p->data_len, p->length );
return -1;
}
}
return 0;
}
/*------------------------------------------------------------
* return appropriate MOD_ value, if one exists
*------------------------------------------------------------
*/
int check_mod_type( char * name )
{
/* character mods */
if ( ! strncmp(name, "str", 3) )
return MOD_STR; /* this is default */
if ( ! strncmp(name, "val", 3) || ! strncmp(name, "char", 4) )
return MOD_CHAR;
/* integral mods */
if ( ! strncmp(name, "uint1", 5) )
return MOD_U1;
if ( ! strncmp(name, "sint1", 5) )
return MOD_S1;
if ( ! strncmp(name, "uint2", 5) )
return MOD_U2;
if ( ! strncmp(name, "sint2", 5) )
return MOD_S2;
if ( ! strncmp(name, "uint4", 5) )
return MOD_U4;
if ( ! strncmp(name, "sint4", 5) )
return MOD_S4;
/* real mods */
if ( ! strncmp(name, "float4", 6) )
return MOD_F4;
if ( ! strncmp(name, "float8", 6) )
return MOD_F8;
return MOD_INVALID;
}
/*------------------------------------------------------------
* Display usage information, depending on usage level:
*
* - USE_SHORT : most basic usage info
* - USE_VERSION : display the current version info
* - USE_GE : describe GE struct elements
* - USE_LONG : complete help on program and options
*------------------------------------------------------------
*/
int usage( char * prog, int level )
{
if ( level == USE_SHORT )
{
printf( "usage: %s -help\n"
"usage: %s [options] file1 file2 ...\n",
prog, prog);
return 0;
}
else if ( level == USE_VERSION )
{
printf( "%s, version %s, compiled: %s\n",
prog, VERSION, __DATE__ );
return 0;
}
else if ( level == USE_HISTORY )
{
fputs( g_history, stdout );
return 0;
}
else if ( level == USE_GE )
{
help_ge_structs( prog );
return 0;
}
else if ( level != USE_LONG )
{
fprintf( stderr, "failure: bad usage level <%d>\n", level );
return -1;
}
/* so we are in a USE_LONG case */
help_full( prog );
return 0;
}
/*------------------------------------------------------------
* Describe elements of each GE struct.
*------------------------------------------------------------
*/
int
help_ge_structs( char * prog )
{
printf( "------------------------------------------------------------\n"
"These are descriptions of the elements in the GE\n"
"data structures used by '%s'. Most elements\n"
"correspond to a field in the image file header.\n"
"\n"
"These fields are shown when running '%s'\n"
"with any of the options:\n"
" '-ge_header', '-ge_extras', or '-ge_all'.\n"
/* taken from Ifile.c */
"----------------------------------------\n"
"ge_header_info struct:\n"
"\n"
" good : is this a valid GE image file\n"
" nx,ny : dimensions of image in voxels\n"
" uv17 : run number (user variable 17)\n"
" dx,dy,dz : directional deltas - distances between voxels\n"
" zoff : location of image in z direction\n"
" tr,te : TR and TE timings\n"
" orients : orientation string for image\n"
"----------------------------------------\n"
/* taken from mri_read.c */
"ge_extras struct:\n"
"\n"
" bpp : bytes per pixel (file_size = nx * ny * bpp)\n"
" cflag : compression flag (here, 1 means NOT compressed)\n"
" hdroff : offset of image header (from beginning of file)\n"
" skip : offset of image data (from beginning of file)\n"
" swap : is byte swapping performed?\n"
" xyzX : coordinate box containing image\n"
"------------------------------------------------------------\n"
"\n", prog, prog
);
return 0;
}
/*------------------------------------------------------------
* Show detailed help.
*------------------------------------------------------------
*/
int
help_full( char * prog )
{
printf(
"\n"
"%s - display or modify sections of a file\n"
"\n"
" This program can be used to display or edit data in arbitrary\n"
" files. If no '-mod_data' option is provided (with DATA), it\n"
" is assumed the user wishes only to display the specified data\n"
" (using both '-offset' and '-length', or using '-ge_XXX').\n"
"\n"
" usage: %s [options] -infiles file1 file2 ...\n"
"\n"
" examples:\n"
"\n"
" ----- help examples -----\n"
"\n"
" 1. get detailed help:\n"
"\n"
" %s -help\n"
"\n"
" 2. get descriptions of GE struct elements:\n"
"\n"
" %s -help_ge\n"
"\n"
" ----- GEMS 4.x and 5.x display examples -----\n"
"\n"
" 1. display GE header and extras info for file I.100:\n"
"\n"
" %s -ge_all -infiles I.100\n"
"\n"
" 2. display GEMS 4.x series and image headers for file I.100:\n"
"\n"
" %s -ge4_all -infiles I.100\n"
"\n"
" 3. display run numbers for every 100th I-file in this directory\n"
"\n"
" %s -ge_uv17 -infiles I.?42\n"
" %s -ge_run -infiles I.?42\n"
"\n"
" ----- general value display examples -----\n"
"\n"
" 1. display the 32 characters located 100 bytes into each file:\n"
"\n"
" %s -offset 100 -length 32 -infiles file1 file2\n"
"\n"
" 2. display the 8 4-byte reals located 100 bytes into each file:\n"
"\n"
" %s -disp_real4 -offset 100 -length 32 -infiles file1 file2\n"
"\n"
" ----- script file checking examples -----\n"
"\n"
" 1. in each file, check whether it is a UNIX file type\n"
"\n"
" %s -show_file_type -infiles my_scripts_*.txt\n"
"\n"
" 2. in each file, look for spaces after trailing backslashes '\\'\n"
"\n"
" %s -show_bad_backslash -infiles my_scripts_*.txt\n"
"\n"
" ----- character modification examples -----\n"
"\n"
" 1. in each file, change the 8 characters at 2515 to 'hi there':\n"
"\n"
" %s -mod_data \"hi there\" -offset 2515 -length 8 -infiles I.*\n"
"\n"
" 2. in each file, change the 21 characters at 2515 to all 'x's\n"
" (and print out extra debug info)\n"
"\n"
" %s -debug 1 -mod_data x -mod_type val -offset 2515 \\\n"
" -length 21 -infiles I.*\n"
"\n"
" ----- raw number modification examples -----\n"
"\n"
" 1. in each file, change the 3 short integers starting at position\n"
" 2508 to '2 -419 17'\n"
"\n"
" %s -mod_data '2 -419 17' -mod_type sint2 -offset 2508 \\\n"
" -length 6 -infiles I.*\n"
"\n"
" 2. in each file, change the 3 binary floats starting at position\n"
" 2508 to '-83.4 2 17' (and set the next 8 bytes to zero by\n"
" setting the length to 20, instead of just 12).\n"
"\n"
" %s -mod_data '-83.4 2 17' -mod_type float4 -offset 2508 \\\n"
" -length 20 -infiles I.*\n"
"\n"
" 3. in each file, change the 3 binary floats starting at position\n"
" 2508 to '-83.4 2 17', and apply byte swapping\n"
"\n"
" %s -mod_data '-83.4 2 17' -mod_type float4 -offset 2508 \\\n"
" -length 12 -swap_bytes -infiles I.*\n"
"\n"
" notes:\n"
"\n"
" o Use of '-infiles' is required.\n"
" o Use of '-length' or a GE information option is required.\n"
" o As of this version, only modification with text is supported.\n"
" Editing binary data is coming soon to a workstation near you.\n"
"\n"
" special options:\n"
"\n"
" -help : show this help information\n"
" : e.g. -help\n"
"\n"
" -version : show version information\n"
" : e.g. -version\n"
"\n"
" -hist : show the program's modification history\n"
"\n"
" -debug LEVEL : print extra info along the way\n"
" : e.g. -debug 1\n"
" : default is 0, max is 2\n"
"\n"
" required 'options':\n"
"\n"
" -infiles f1 f2 ... : specify input files to print from or modify\n"
" : e.g. -infiles file1\n"
" : e.g. -infiles I.*\n"
"\n"
" Note that '-infiles' should be the final option. This is\n"
" to allow the user an arbitrary number of input files.\n"
"\n"
" GE info options:\n"
"\n"
" -ge_all : display GE header and extras info\n"
" -ge_header : display GE header info\n"
" -ge_extras : display extra GE image info\n"
" -ge_uv17 : display the value of uv17 (the run #)\n"
" -ge_run : (same as -ge_uv17)\n"
" -ge_off : display file offsets for various fields\n"
"\n"
" GEMS 4.x info options:\n"
"\n"
" -ge4_all : display GEMS 4.x series and image headers\n"
" -ge4_image : display GEMS 4.x image header\n"
" -ge4_series : display GEMS 4.x series header\n"
" -ge4_study : display GEMS 4.x study header\n"
"\n"
" script file options:\n"
"\n"
" -show_bad_backslash : show lines with whitespace after '\\'\n"
"\n"
" This is meant to find problems in script files where the\n"
" script programmer has spaces or tabs after a final '\\'\n"
" on the line. That would break the line continuation.\n"
"\n"
" -show_file_type : print file type of UNIX, Mac or DOS\n"
"\n"
" Shell scripts need to be UNIX type files. This option\n"
" will inform the programmer if there are end of line\n"
" characters that define an alternate file type.\n"
"\n"
" raw ascii options:\n"
"\n"
" -length LENGTH : specify the number of bytes to print/modify\n"
" : e.g. -length 17\n"
"\n"
" This includes numbers after the conversion to binary. So\n"
" if -mod_data is '2 -63 186', and -mod_type is 'sint2' (or\n"
" signed shorts), then 6 bytes will be written (2 bytes for\n"
" each of 3 short integers).\n"
"\n"
" ** Note that if the -length argument is MORE than what is\n"
" needed to write the numbers out, the remaind of the length\n"
" bytes will be written with zeros. If '17' is given for\n"
" the length, and 3 short integers are given as data, there \n"
" will be 11 bytes of 0 written after the 6 bytes of data.\n"
"\n"
" -mod_data DATA : specify a string to change the data to\n"
" : e.g. -mod_data hello\n"
" : e.g. -mod_data '2 -17.4 649'\n"
" : e.g. -mod_data \"change to this string\"\n"
"\n"
" This is the data that will be writting into the modified\n"
" file. If the -mod_type is 'str' or 'char', then the\n"
" output data will be those characters. If the -mod_type\n"
" is any other (i.e. a binary numerical format), then the\n"
" output will be the -mod_data, converted from numerical\n"
" text to binary.\n"
"\n"
" ** Note that a list of numbers must be contained in quotes,\n"
" so that it will be processed as a single parameter.\n"
"\n"
" -mod_type TYPE : specify the data type to write to the file\n"
" : e.g. -mod_type string\n"
" : e.g. -mod_type sint2\n"
" : e.g. -mod_type float4\n"
" : default is 'str'\n"
"\n"
" TYPE can be one of:\n"
"\n"
" str : perform a string substitution\n"
" char, val : perform a (repeated?) character substitution\n"
" uint1 : single byte unsigned int (binary write)\n"
" sint1 : single byte signed int (binary write)\n"
" uint2 : two byte unsigned int (binary write)\n"
" sint2 : two byte signed int (binary write)\n"
" uint4 : four byte unsigned int (binary write)\n"
" sint4 : four byte signed int (binary write)\n"
" float4 : four byte floating point (binary write)\n"
" float8 : eight byte floating point (binary write)\n"
"\n"
" If 'str' is used, which is the default action, the data is\n"
" replaced by the contents of the string DATA (from the\n"
" '-mod_data' option).\n"
"\n"
" If 'char' is used, then LENGTH bytes are replaced by the\n"
" first character of DATA, repeated LENGTH times.\n"
"\n"
" For any of the others, the list of numbers found in the\n"
" -mod_data option will be written in the supplied binary\n"
" format. LENGTH must be large enough to accomodate this\n"
" list. And if LENGTH is higher, the output will be padded\n"
" with zeros, to fill to the requesed length.\n"
"\n"
" -offset OFFSET : use this offset into each file\n"
" : e.g. -offset 100\n"
" : default is 0\n"
"\n"
" This is the offset into each file for the data to be\n"
" read or modified.\n"
"\n"
" -quiet : do not output header information\n"
"\n"
" numeric options:\n"
"\n"
" -disp_int2 : display 2-byte integers\n"
" : e.g. -disp_int2\n"
"\n"
" -disp_int4 : display 4-byte integers\n"
" : e.g. -disp_int4\n"
"\n"
" -disp_real4 : display 4-byte real numbers\n"
" : e.g. -disp_real4\n"
"\n"
" -swap_bytes : use byte-swapping on numbers\n"
" : e.g. -swap_bytes\n"
"\n"
" If this option is used, then byte swapping is done on any\n"
" multi-byte numbers read from or written to the file.\n"
"\n"
" - R Reynolds, version: %s, compiled: %s\n"
"\n",
prog, prog,
prog, prog, prog, prog, prog, prog, prog, prog, prog, prog, prog,
prog, prog, prog, prog,
VERSION, __DATE__
);
return 0;
}
/*------------------------------------------------------------
* Reverse the order of the 4 bytes at this address.
*------------------------------------------------------------
*/
static int
swap_4( void * ptr ) /* destructive */
{
unsigned char * addr = ptr;
addr[0] ^= addr[3]; addr[3] ^= addr[0]; addr[0] ^= addr[3];
addr[1] ^= addr[2]; addr[2] ^= addr[1]; addr[1] ^= addr[2];
return 0;
}
/*------------------------------------------------------------
* Reverse the order of the 2 bytes at this address.
*------------------------------------------------------------
*/
static int
swap_2( void * ptr ) /* destructive */
{
unsigned char * addr = ptr;
addr[0] ^= addr[1]; addr[1] ^= addr[0]; addr[0] ^= addr[1];
return 0;
}
/******************************************************************/
/*** Return info from a GEMS IMGF file into user-supplied struct **/
/* stolen from Ifile.c and modified ... */
int
read_ge_header( char *pathname , ge_header_info *hi, ge_extras *E, ge_off *off )
{
FILE *imfile ;
int length , skip , swap=0 ;
char orients[8] , str[8] ;
int nx , ny , bpp , cflag , hdroff ;
float uv17 = -1.0;
if( hi == NULL ) return -1; /* bad */
hi->good = 0 ; /* not good yet */
if( pathname == NULL ||
pathname[0] == '\0' ) return -1; /* bad */
length = THD_filesize( pathname ) ;
if( length < 1024 ) return -1; /* bad */
imfile = fopen( pathname , "r" ) ;
if( imfile == NULL ) return -1; /* bad */
strcpy(str,"JUNK") ; /* initialize string */
fread(str,1,4,imfile) ; /* check for "IMGF" at start of file */
if( str[0]!='I' || str[1]!='M' || str[2]!='G' || str[3]!='F' ){ /* bad */
fclose(imfile) ; return -2;
}
/*-- read next 5 ints (after the "IMGF" string) --*/
fread( &skip , 4,1, imfile ) ; /* offset into file of image data */
fread( &nx , 4,1, imfile ) ; /* x-size */
fread( &ny , 4,1, imfile ) ; /* y-size */
fread( &bpp , 4,1, imfile ) ; /* bits per pixel (should be 16) */
fread( &cflag, 4,1, imfile ) ; /* compression flag (1=uncompressed)*/
/*-- check if nx is funny --*/
if( nx < 0 || nx > 8192 ){ /* have to byte swap these 5 ints */
swap = 1 ; /* flag to swap data, too */
swap_4(&skip); swap_4(&nx); swap_4(&ny); swap_4(&bpp); swap_4(&cflag);
} else {
swap = 0 ; /* data is ordered for this CPU */
}
if( nx < 0 || nx > 8192 || ny < 0 || ny > 8192 ){ /* bad */
fclose(imfile) ; return -1;
}
hi->nx = nx ;
hi->ny = ny ;
off->nx = 8;
off->ny = 12;
if( skip+2*nx*ny > length || /* file is too short */
skip <= 0 || /* bizarre */
cflag != 1 || /* data is compressed */
bpp != 16 ){
fclose(imfile); return -1; /* data is not shorts */
}
/*-- try to read image header data as well --*/
fseek( imfile , 148L , SEEK_SET ) ; /* magic GEMS offset */
fread( &hdroff , 4,1 , imfile ) ; /* location of image header */
if( swap ) swap_4(&hdroff) ;
if( hdroff > 0 && hdroff+256 < length ){ /* can read from image header */
float dx,dy,dz, xyz[9], zz ; int itr, ii,jj,kk ;
/*-- get voxel grid sizes --*/
fseek( imfile , hdroff+26 , SEEK_SET ) ; /* dz */
fread( &dz , 4,1 , imfile ) ;
fseek( imfile , hdroff+50 , SEEK_SET ) ; /* dx and dy */
fread( &dx , 4,1 , imfile ) ;
fread( &dy , 4,1 , imfile ) ;
off->dx = hdroff+50;
off->dy = hdroff+54;
off->dz = hdroff+26;
if( swap ){ swap_4(&dx); swap_4(&dy); swap_4(&dz); }
hi->dx = dx ; hi->dy = dy ; hi->dz = dz ;
/* grid orientation: from 3 sets of LPI corner coordinates: */
/* xyz[0..2] = top left hand corner of image (TLHC) */
/* xyz[3..5] = top right hand corner of image (TRHC) */
/* xyz[6..8] = bottom right hand corner of image (BRHC) */
/* GEMS coordinate orientation here is LPI */
off->xyz = hdroff+154;
fseek( imfile , hdroff+154 , SEEK_SET ) ; /* another magic number */
fread( xyz , 4,9 , imfile ) ;
if( swap ){
swap_4(xyz+0); swap_4(xyz+1); swap_4(xyz+2);
swap_4(xyz+3); swap_4(xyz+4); swap_4(xyz+5);
swap_4(xyz+6); swap_4(xyz+7); swap_4(xyz+8);
}
/* x-axis orientation */
/* ii determines which spatial direction is x-axis */
/* and is the direction that has the biggest change */
/* between the TLHC and TRHC */
dx = fabs(xyz[3]-xyz[0]) ; ii = 1 ;
dy = fabs(xyz[4]-xyz[1]) ; if( dy > dx ){ ii=2; dx=dy; }
dz = fabs(xyz[5]-xyz[2]) ; if( dz > dx ){ ii=3; }
dx = xyz[ii+2]-xyz[ii-1] ; if( dx < 0. ){ ii = -ii; }
switch( ii ){
case 1: orients[0]= 'L'; orients[1]= 'R'; break;
case -1: orients[0]= 'R'; orients[1]= 'L'; break;
case 2: orients[0]= 'P'; orients[1]= 'A'; break;
case -2: orients[0]= 'A'; orients[1]= 'P'; break;
case 3: orients[0]= 'I'; orients[1]= 'S'; break;
case -3: orients[0]= 'S'; orients[1]= 'I'; break;
default: orients[0]='\0'; orients[1]='\0'; break;
}
/* y-axis orientation */
/* jj determines which spatial direction is y-axis */
/* and is the direction that has the biggest change */
/* between the BRHC and TRHC */
dx = fabs(xyz[6]-xyz[3]) ; jj = 1 ;
dy = fabs(xyz[7]-xyz[4]) ; if( dy > dx ){ jj=2; dx=dy; }
dz = fabs(xyz[8]-xyz[5]) ; if( dz > dx ){ jj=3; }
dx = xyz[jj+5]-xyz[jj+2] ; if( dx < 0. ){ jj = -jj; }
switch( jj ){
case 1: orients[2] = 'L'; orients[3] = 'R'; break;
case -1: orients[2] = 'R'; orients[3] = 'L'; break;
case 2: orients[2] = 'P'; orients[3] = 'A'; break;
case -2: orients[2] = 'A'; orients[3] = 'P'; break;
case 3: orients[2] = 'I'; orients[3] = 'S'; break;
case -3: orients[2] = 'S'; orients[3] = 'I'; break;
default: orients[2] ='\0'; orients[3] ='\0'; break;
}
orients[4] = '\0' ; /* terminate orientation string */
kk = 6 - abs(ii)-abs(jj) ; /* which spatial direction is z-axis */
/* where 1=LR, 2=PA, 3=IS */
/* (can't tell orientation from 1 slice) */
zz = xyz[kk-1] ; /* z-coordinate of this slice */
hi->zoff = zz ;
strcpy(hi->orients,orients) ;
/*-- get TR in seconds --*/
off->tr = hdroff+194;
fseek( imfile , hdroff+194 , SEEK_SET ) ;
fread( &itr , 4,1 , imfile ) ; /* note itr is an int */
if( swap ) swap_4(&itr) ;
hi->tr = 1.0e-6 * itr ; /* itr is in microsec */
/*-- get TE in milliseconds --*/
off->te = hdroff+202;
fseek( imfile , hdroff+202 , SEEK_SET ) ;
fread( &itr , 4,1 , imfile ) ; /* itr is an int, in microsec */
if( swap ) swap_4(&itr) ;
hi->te = 1.0e-6 * itr ;
/* zmodify: get User Variable 17, a likely indicator of a new scan,
* info by S. Marrett, location from S. Inati's matlab function
* GE_readHeaderImage.m
*/
off->uv17 = hdroff+272+202;
/* printf ("\nuv17 = \n"); */
fseek ( imfile , hdroff+272+202, SEEK_SET ) ;
fread( &uv17 , 4, 1 , imfile ) ;
if( swap ) swap_4(&uv17) ;
/* printf ("%d ", (int)uv17); */
hi->uv17 = (int)uv17;
/* printf ("\n"); */
hi->good = 1 ; /* this is a good file */
E->bpp = bpp; /* store the ge_extra info */
E->cflag = cflag;
E->hdroff = hdroff;
E->skip = skip;
E->swap = swap;
memcpy( E->xyz, xyz, sizeof(xyz) );
} /* end of actually reading image header */
fclose(imfile);
return 0;
}
/*------------------------------------------------------------
* Return the size of the file.
*------------------------------------------------------------
*/
unsigned long
THD_filesize ( char * pathname )
{
struct stat buf;
if ( pathname == NULL || *pathname == '\0' )
return -1;
if ( stat( pathname, &buf ) != 0 )
return -1;
return (unsigned long)buf.st_size;
}
/*------------------------------------------------------------
* Just output raw numbers from the starting location,
* swapping bytes (if requested).
*------------------------------------------------------------
*/
int
disp_numeric_data( char * data, param_t * p, FILE * fp )
{
int c;
if ( data == NULL || fp == NULL )
{
fprintf( stderr, "** error: bad params to DND '%p,%p'\n", data, fp );
return -1;
}
if ( p->length <= 0 || p->ndisp == 0 )
return 0;
/* print out shorts */
if ( p->ndisp & NDISP_INT2 )
{
short * sp = (short *)data;
fprintf( fp, "0x%4x : ", (unsigned int)p->offset );
for ( c = 0; c < p->length/2; c++, sp++ )
{
if ( p->swap )
swap_2( sp );
fprintf( fp, "%d ", *sp );
}
fputc( '\n', fp );
}
/* print out ints */
if ( p->ndisp & NDISP_INT4 )
{
int * ip = (int *)data;
fprintf( fp, "0x%4x : ", (unsigned int)p->offset );
for ( c = 0; c < p->length/4; c++, ip++ )
{
if ( p->swap )
swap_4( ip );
fprintf( fp, "%d ", *ip );
}
fputc( '\n', fp );
}
/* print out floats */
if ( p->ndisp & NDISP_REAL4 )
{
float * rp = (float *)data;
fprintf( fp, "0x%4x : ", (unsigned int)p->offset );
for ( c = 0; c < p->length/4; c++, rp++ )
{
if ( p->swap )
swap_4( rp );
fprintf( fp, "%f ", *rp );
}
fputc( '\n', fp );
}
return 0;
}
/*------------------------------------------------------------
* Display the contents of the param_t struct.
*------------------------------------------------------------
*/
int
disp_param_data( param_t * p )
{
if ( ! p )
return -1;
printf( "num_files, flist : %d, %p\n"
"debug, data_len : %d, %d\n"
"ge_disp, ge4_disp, ndisp : 0x%x, 0x%x, 0x%x\n"
"\n"
"swap, modify, mod_type : %d, %d, %d\n"
"offset, length, quiet : %ld, %d, %d\n"
"mod_data : %s\n"
"\n",
p->num_files, p->flist, p->debug, p->data_len,
p->ge_disp, p->ge4_disp, p->ndisp, p->swap, p->modify,
p->mod_type, p->offset, p->length, p->quiet,
CHECK_NULL_STR(p->mod_data)
);
if ( p->debug > 1 )
{
int c;
printf( "file list: " );
for ( c = 0; c < p->num_files; c ++ )
printf( "'%s' ", p->flist[c] );
printf( "\n" );
}
return 0;
}
/*------------------------------------------------------------
* Display the contents of the ge_extras struct.
*------------------------------------------------------------
*/
int
r_idisp_ge_extras( char * info, ge_extras * E )
{
if ( info )
fputs( info, stdout );
if ( E == NULL )
{
printf( "r_idisp_ge_extras: E == NULL" );
return -1;
}
printf( " ge_extras at %p :\n"
" bpp = %d\n"
" cflag = %d\n"
" hdroff = %d\n"
" skip = %d\n"
" swap = %d\n"
" (xyz0,xyz1,xyz2) = (%f,%f,%f)\n"
" (xyz3,xyz4,xyz5) = (%f,%f,%f)\n"
" (xyz6,xyz7,xyz8) = (%f,%f,%f)\n",
E, E->bpp, E->cflag, E->hdroff, E->skip, E->swap,
E->xyz[0], E->xyz[1], E->xyz[2],
E->xyz[3], E->xyz[4], E->xyz[5],
E->xyz[6], E->xyz[7], E->xyz[8]
);
return 0;
}
/*------------------------------------------------------------
* Display the contents of the ge_header_info struct.
*------------------------------------------------------------
*/
int
r_idisp_ge_header_info( char * info, ge_header_info * I )
{
if ( info )
fputs( info, stdout );
if ( I == NULL )
{
printf( "r_idisp_ge_header_info: I == NULL" );
return -1;
}
printf( " ge_header_info at %p :\n"
" good = %d\n"
" (nx,ny) = (%d,%d)\n"
" uv17 = %d\n"
" (dx,dy,dz) = (%f,%f,%f)\n"
" zoff = %f\n"
" (tr,te) = (%f,%f)\n"
" orients = %8s\n",
I, I->good, I->nx, I->ny, I->uv17,
I->dx, I->dy, I->dz, I->zoff, I->tr, I->te,
CHECK_NULL_STR(I->orients)
);
return 0;
}
/*------------------------------------------------------------
* Display the contents of the ge_header_info struct.
*------------------------------------------------------------
*/
int
disp_ge_offsets( char * info, ge_off * D )
{
if ( info )
fputs( info, stdout );
if ( D == NULL )
{
printf( "disp_ge_offsets: D == NULL" );
return -1;
}
printf( " ge_off at %p :\n"
" nx, ny, uv17 = %d, %d, %d\n"
" dx, dy, dz = %d, %d, %d\n"
" tr, te, xyz = %d, %d, %d\n",
D, D->nx, D->ny, D->uv17,
D->dx, D->dy, D->dz,
D->tr, D->te, D->xyz
);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1