/* ARIADNE V.1.3 Copyright Richard Mott 2000 Wellcome Trust Centre For Human Genetics Univeristy of Oxford Roosevelt Drive Oxford OX3 7AD UK The software package ARIADNE is distributed in the hope that it will be useful, but in order that the University as a charitable foundation protects its assets for the benefit of its educational and research purposes, the University makes clear that no condition is made or to be implied, nor is any warranty given or to be implied, as to the accuracy of ARIADNE, or that it will be suitable for any particular purpose or for use under any specific conditions, or that the content or use of ARIADNE will not constitute or result in infringement of third-party rights. Furthermore, the University disclaims all responsibility for the use which is made of ARIADNE. */ #include #include #include #include #include #include #include"cl.h" #ifdef ALPHA extern void exit(int); #endif extern int skip_comments( FILE *file, char *string ); /*command line option to suppress all comments*/ int comment = 1; FILE * OpenFile( char *filename, char *mode ) /* attempts to open filename, using mode to determine function (read/write/append), and stops the program on failure */ { FILE *fp; char *MakeLegal(); if ( ( fp = fopen( MakeLegal(filename), mode ) ) == NULL ) { fprintf( stderr, "\n ERROR: file %s will not open for function %s\n\n", filename, mode ); exit(1); } else return fp; } int GetFloat( char *format, float *variable, int argc, char **argv ) /* gets a float from command line */ /* format can be a string like "-a=%f", or "-a". In the former case is looks for entries line -a=10.3 AND -a 10.3, in the latter just for -a 10.3 */ { float t; char *s; char Format[256]; sprintf(Format,"%g",*variable); AppendUsage( format, "float", Format, 0 ); if ( (s = NextArg( format, argc, argv ) ) && sscanf( s, "%f", &t ) == 1 ) { *variable = t; return 1; } s = format; while(*s && *s != '=') s++; if ( *s == '=' ) sprintf(Format,"%s", format); else sprintf(Format,"%s%s", format, "=%f"); while ( --argc > 0 ) { if ( sscanf( argv[argc], Format, &t ) == 1 ) { *variable = t; return 1; } } return 0; } char * NextArg( char *format, int argc, char **argv ) /* scan the command lines for argument matching stub, and return the NEXT arg eg if format == "-max=%d", then argv == "-max 10" returns "10" */ { char *s = ClStub( format ); argc--; while( --argc > 0 ) { if ( ! strcmp( s, argv[argc] ) ) return argv[argc+1]; } return NULL; } char * ClStub( char *format ) /* extract stub from format, eg "-files=%s" -> "-files" */ { static char stub[256]; char *s=stub; while ( *format && *format != '=' ) *s++ = *format++; *s = 0; return stub; } int GetInt( char *format, int *variable, int argc, char **argv ) /* gets an int from the command line */ { int t; char *s; char Format[256]; sprintf(Format,"%d",*variable); AppendUsage( format, "integer", Format, 0 ); if ( (s = NextArg( format, argc, argv ) ) && sscanf( s, "%d", &t ) == 1 ) { *variable = t; return 1; } s = format; while(*s && *s != '=') s++; if ( *s == '=' ) sprintf(Format,"%s", format); else sprintf(Format,"%s%s", format, "=%d"); while ( --argc > 0 ) { if ( sscanf( argv[argc], Format, &t ) == 1 ) { *variable = t; return 1; } } return 0; } int ClCheck( char *format, int argc, char **argv ) /* checks if a string is on the command line*/ { AppendUsage( format, "switch", "", 0 ); while ( --argc > 0 ) { if ( strcmp( format, argv[argc] ) == 0 ) return 1; } return 0; } int GetBool( char *format, int *bool, int argc, char **argv ) /* checks for boolean switch, eg -gap=yes -gap=y -gap=1 -gap=true -gap=t -gap TRUE -gap=no -gap=n -gap=0 -gap=false -gap=f FALSE format should be the string "-gap" */ { /* int arg;*/ if ( *bool ) AppendUsage( format, "switch", "true", 0 ); else AppendUsage( format, "switch", "false", 0 ); if ( GetInt( format, bool, argc, argv) ) return 1; else { char reply[256]; memset((void *)reply,0,256); if ( GetArg( format, reply, argc, argv ) ) { if ( ! strcasecmp( reply, "yes" ) || ! strcasecmp( reply, "y" ) || ! strcasecmp( reply, "true" ) || ! strcasecmp( reply, "t" ) ) { *bool = 1; return 1; } else if ( ! strcasecmp( reply, "no" ) || ! strcasecmp( reply, "n" ) || ! strcasecmp( reply, "false" ) || ! strcasecmp( reply, "f" ) ) { *bool = 0; return 1; } } } if ( ClCheck( format, argc, argv ) ) return 1; else return 0; } int GetBoolean( char *format, int *bool, int argc, char **argv ) /* similar to GetBool(), except that function returns 1 and sets *bool = 1 if ClCheck is true also . Therefore the switch -switch is equivalent to -switch=y -noswitch is equivalent to -switch=n */ { char noformat[256]; int Argc = argc; /*int n;*/ if ( *bool ) AppendUsage( format, "switch", "true", 1 ); else AppendUsage( format, "switch", "false", 1 ); if ( *format == '-' ) sprintf(noformat,"-no%s", &format[1] ); else sprintf(noformat,"-no%s", format ); while ( --Argc > 0 ) { if ( ! strcmp( format, argv[Argc] ) ) { *bool = 1; return 1; } else if ( ! strcmp( noformat,argv[Argc]) ) { *bool = 0; return 1; } } /* NB there is a slight bug here in that a command line of the form program -notest -test=y will yield FALSE because it searches for -notest before -test=y THerefore you should stick to one convention within a command-line */ return GetBool( format, bool, argc, argv ); } int GetArg( char *format, char *arg, int argc, char ** argv ) /* gets a string argument*/ { char *s; char Format[256]; AppendUsage( format, "text", arg, 0 ); s = format; while(*s && *s != '=') s++; if ( *s == '=' ) sprintf(Format,"%s", format); else sprintf(Format,"%s%s", format, "=%s"); if ( (s = NextArg( format, argc, argv )) ) { strcpy( arg, s ); return 1; } while ( --argc > 0 ) { if ( sscanf( argv[argc], Format, arg ) > 0 ) return 1; } return 0; } FILE * NextFile( char *filename, int argc, char **argv ) /* searches the command line for arguments not beginning with "-", and tries to open the first one it finds for reading. The corresponding argument in the command-line list is then blanked out so that on the next call a different file is opened. The name of the file opened is returned in filename. On failure the function returns NULL */ { FILE *fp; int i; *filename = 0; while ( --argc > 0 ) { if ( argv[argc][0] != 0 && argv[argc][0] != '-' ) { if ( (fp = fopen( filename, "r" )) ) { strcpy( filename, argv[argc] ); for(i=0;i<=strlen(argv[argc]);i++) argv[argc][i] = 0; return fp; } } } return NULL; } char * Extension ( char *filename, char *ext) /* changes the Extension of filename to ext. e.g. Extension( "file.dat", "out" ); produces file.out Extension( "file", "out"); produces file.out Extension( "file", ".out"); produces file.out Extension( "file.out", ""); produces file Note: filename MUST be long enough to cope ! Returns the modified string */ { int n; if ( ! ext ) return filename; if ( ext[0] == '.' ) ext++; n = strlen(filename); while ( filename[n] != '.' && n > 0 ) n--; if ( filename[n] != '.' ) { n = strlen(filename); filename[n] = '.'; } n++; strcpy( &filename[n], ext ); if ( filename[n=strlen(filename)-1] == '.' ) filename[n] = 0; return filename; } char * BaseName (char *filename) /* strips any Directory from filename e.g. BaseName("/gea/users/rmott/.cshrc"); produces .cshrc BaseName("/usr"); produces usr */ { int n, m; n = strlen(filename); while( filename[n] != '/' && n > 0 ) n--; if ( filename[n] == '/' ) n++; m = 0; while ( filename[m] ) filename[m++] = filename[n++]; return filename; } char * DirName( char *pathname ) /* strips off the filename from the path, leaving the Directory */ { char *s = &pathname[strlen(pathname)-1]; while( *s && s > pathname && *s != '/' ) s--; if ( s == pathname && *s != '/' ) strcpy(pathname, "./"); else if ( s == pathname && *s == '/' ) strcpy(pathname,"/"); else *s = 0; return pathname; } char * Directory( char *filename, char *dir ) /* changes the Directory part of filename to dir. e.g. Directory( "/home/gea/fred/file.dat", "/usr/local/" ); produces /usr/local/file.dat Directory("/usr/lib", "var"); produces var/lib, i.e. a Directory slash is inserted if necessary. */ { char name[512]; BaseName( filename ); if ( dir && *dir ) { if ( dir[strlen(dir)-1] != '/' ) sprintf( name, "%s/%s", dir, filename ); else sprintf( name, "%s%s", dir, filename ); strcpy( filename, name ); } return filename; } char * RootName( char *filename ) /* trims off the Directory and the Extension from filename */ { return Extension(BaseName(filename),""); } /* use compiler switch -DVAX to use the form of MakeLegal which converts . to _ */ #ifdef VAX char * MakeLegal( char *filename ) /* converts files like file.in.out to file_in.out */ { char *s = filename, *t; int n=0; while( *s ) { if ( *s == '.' ) { n++; t = s; } s++; } if ( n > 1 ) { t--; while ( t != filename ) { if ( *t == '.' ) *t = '_'; t--; } } return filename; } #else char * MakeLegal( char *filename ) { return filename; } #endif FILE * ArgFile( char *format, char *mode, int argc, char **argv, char *filename ) /* parses the command-line using format, attempts to get a filename and open it. If format does not match any argument then NULL is returned. If format matchs an argument but the file will not open then an error message is printed to stderr */ { FILE *fp=NULL; *filename = 0; if ( GetArg( format, filename, argc, argv ) ) { if ( ( fp = fopen( filename, mode ) ) == NULL ) fprintf( stderr, "\n ERROR: file %s will not open for function %s\n\n", filename, mode ); } if ( !strcmp( mode, "w" ) ) AppendUsage( format, "Writeable File", "", 1 ); else if ( !strcmp( mode, "r" ) ) AppendUsage( format, "Readable File", "", 1 ); else AppendUsage( format, "File", "", 1 ); return fp; } FILE * ArgFileForce( char *format, char *mode, int argc, char **argv, char *filename ) /* parses the command-line using format, attempts to get a filename and open it. If format does not match any argument or if format matchs an argument but the file will not open then the program stops*/ { FILE *fp; if ( GetArg( format, filename, argc, argv ) ) { if ( ( fp = fopen( filename, mode ) ) == NULL ) { fprintf( stderr, "\n ERROR: file %s will not open for function %s\n\n", filename, mode ); exit(1); } else return fp; } else { fprintf( stderr, "\n ERROR: argument %s not on command line\n\n", format ); exit(1); } } #include #include #include int FileTime( char *filename ) /* returns the time that filename was last modified, or 0 if filename cannot be opened for reading or if the call to stat fails */ { FILE *fp; struct stat buf; if ( ! (fp = fopen(filename,"r")) ) return 0; else { fclose(fp); if ( ! stat( filename, &buf ) ) return (int)buf.st_mtime; else return 0; } } char * FileDate( char *filename ) /* similar to FileTime() execpt that a pointer to the date (in English) */ { FILE *fp; struct stat buf; char date[256], *t; strcpy( date, "?"); if ( (fp = fopen(filename,"r")) ) { fclose(fp); if ( ! stat( filename, &buf ) ) { sprintf( date, "%s", ctime(&buf.st_mtime) ); t = date; while ( *t ) { if ( *t == '\n') *t = 0; t++; } } } t = date; return t; } typedef struct use_list { char *format; char *text; char *def; struct use_list *next; } USE_LIST; static USE_LIST *use_begin=NULL, *use_end=NULL; static char *help_text=NULL; void AppendUsage( char *format, char *text, char *def, int overide ) { USE_LIST *use; if ( ! use_begin ) use_begin = use_end = (USE_LIST *)calloc( 1, sizeof(USE_LIST) ); else { use = use_begin; while( use ) { if ( ! strcmp( use->format, format ) ) { if ( overide ) break; else return; } use = use->next; } if ( ! use ) use_end = use_end->next = (USE_LIST *)calloc( 1, sizeof(USE_LIST) ); else use_end = use; } /* printf("append %s %s %s\n", format, text, def ); */ use_end->format = (char*)strdup( format ); use_end->text = (char*)strdup( text ); use_end->def = (char*)strdup( def ); } int CheckUsage( FILE *fp, int argc, char **argv ) { USE_LIST *u; int errors=0; char *arg, *noarg; while( --argc > 0 ) { arg = argv[argc]; if ( *arg == '-' ) { if ( strlen(arg) > 3 && (arg[1] == 'n') && (arg[2] == 'o') ) noarg = &arg[3]; else noarg = NULL; u = use_begin; while( u && strncmp( argv[argc], u->format, strlen(argv[argc]) ) && ( noarg == NULL || strncmp( noarg, &u->format[1], strlen(noarg) ) ) ) u = u->next; if ( ! u && ! isdigit((int)arg[1]) ) { if ( fp ) fprintf(fp, "WARNING: unknown argument %s\n", argv[argc] ); errors++; } } } return errors; } void AddHelp( char *string ) { if ( string ) help_text = strdup(string); } void GetHelp( int argc, char **argv ) { int want_help = ClCheck("-help", argc, argv ); int errors = CheckUsage( stderr, argc, argv ); if ( want_help || errors ) PrintUsage( argc, argv, 1 ); } void PrintUsage( int argc, char **argv, int stop ) { USE_LIST *u; char name[256]; strcpy(name, argv[0]); BaseName(name); u = use_begin; if ( help_text ) fprintf(stderr, "\n%s\n", help_text ); fprintf( stderr, "\nusage: %s\n", name ); while( u ) { fprintf( stderr, " %-15s %-20s [ %s ]\n", u->format, u->text, u->def ); u = u->next; } fprintf(stderr, "\n\n"); if ( stop ) exit(1); } #define COM "-comfile=" #define MAX_COM_DEPTH 10 static int com_depth=0; int AddCommandsFromFile( int argc, char **argv, int *nargc, char ***nargv ) /* looks for a command file argument and parses the command file, adding at to the command line */ { FILE *fp; char comfile[256], line[256], *s, **targv = argv; int n = argc, targc=argc; *nargc = targc = argc; *nargv = targv = argv; if ( ++com_depth < MAX_COM_DEPTH && (fp = ArgFile( "-comfile=%s", "r", argc, argv, comfile ) )) { /* printf( "! %2d reading commands from file %s\n", com_depth, comfile );*/ while( skip_comments( fp, line ) != EOF ) targc++; rewind(fp); targv = (char**)calloc( targc, sizeof(char*) ); while( n-- ) { if ( argv[n] && strncmp( COM, argv[n] , strlen(COM) ) ) targv[n] = argv[n]; else targv[n] = (char*)strdup(" "); } targc = argc; while( skip_comments( fp, s=line ) != EOF ) { while( isspace((int) *s) ) s++; /* was *s++ rtm 7.xii.99 */ targv[targc++] = (char*)strdup(s); } AddCommandsFromFile( targc, targv, nargc, nargv ); com_depth--; return 1; } else { com_depth--; return 0; } } int LegalString( char *string, char **strings, int size, int *value ) /* checks if string is a member os strings, and sets value to the index in the array strings returns 1 on success and 0 on failure */ { int i; if ( string ) for(i=0;i n ) return 0; else { /*char *t, *s;*/ while( m >= 0 ) { if ( text[n] != suffix[m] ) return 0; n--; m--; } } return 1; } int GetSeed( int *seed, int argc, char **argv ) { time_t time(), *tloc; int s; tloc = NULL; s = *seed = ((int)time(tloc))% 100000; GetInt( "-seed", &s, argc, argv ); *seed = s; /* fprintf(stderr,"! seed = %d\n", *seed); */ return *seed; } int GetRestrictedArg( char *format, char *arg, int argc, char ** argv, int stringc, char **strings, int *value ) { *value = -1; GetArg( format, arg, argc, argv ); return LegalString( arg, strings, stringc, value ); }