Esempio n. 1
0
int main(const int argc, char* argv[]) {
	FILE *image;
	enum exe_type et;

	if (argc < 2) {
		fprintf(stderr, "Synopsis: %s file.exe [...]\n", argv[0]);
		return 0;
	}

#ifdef ENABLE_DEBUG
	if (!strcmp(argv[1], "--pretend") && argc >= 3) {
		pretending = 1;
		argv[1] = argv[2]; /* we won't be using argv[2+] anyway */
	}
#endif

	image = fopen(argv[1], "r");
	et = detect_format(image); /* image can be NULL here */

	if (et == EXE_ERROR)
		perror("I/O error while reading executable");
	if (image)
		fclose(image);

	if (et < EXE_ERROR) {
		char* const handler = read_conf(et);
		if (handler)
			doexec(handler, argv);
	}

	return 127;
}
Esempio n. 2
0
int main(int argc, char **argv) {
    scram_fd **in, *out;
    int n_input, i;
    bam_seq_t **s;
    char imode[10], *in_f = "", omode[10], *out_f = "";
    int level = '\0'; // nul terminate string => auto level
    int c, verbose = 0;
    int s_opt = 0, S_opt = 0, embed_ref = 0;
    char *ref_fn = NULL;
    int start, end;
    char ref_name[1024] = {0};
    refs_t *refs = NULL;

    /* Parse command line arguments */
    while ((c = getopt(argc, argv, "u0123456789hvs:S:V:r:XI:O:R:")) != -1) {
	switch (c) {
	case '0': case '1': case '2': case '3': case '4':
	case '5': case '6': case '7': case '8': case '9':
	    level = c;
	    break;
	    
	case 'u':
	    level = '0';
	    break;

	case 'h':
	    usage(stdout);
	    return 0;

	case 'v':
	    verbose++;
	    break;

	case 's':
	    s_opt = atoi(optarg);
	    break;

	case 'S':
	    S_opt = atoi(optarg);
	    break;

	case 'V':
	    cram_set_option(NULL, CRAM_OPT_VERSION, optarg);
	    break;

	case 'r':
	    ref_fn = optarg;
	    break;

	case 'X':
	    embed_ref = 1;
	    break;

	case 'I':
	    in_f = parse_format(optarg);
	    break;

	case 'O':
	    out_f = parse_format(optarg);
	    break;

	case 'R': {
	    char *cp = strchr(optarg, ':');
	    if (cp) {
		*cp = 0;
		switch (sscanf(cp+1, "%d-%d", &start, &end)) {
		case 1:
		    end = start;
		    break;
		case 2:
		    break;
		default:
		    fprintf(stderr, "Malformed range format\n");
		    return 1;
		}
	    } else {
		start = INT_MIN;
		end   = INT_MAX;
	    }
	    strncpy(ref_name, optarg, 1023);
	    break;
	}

	case '?':
	    fprintf(stderr, "Unrecognised option: -%c\n", optopt);
	    usage(stderr);
	    return 1;
	}
    }    

    /* Open output file */
    sprintf(omode, "w%s%c", out_f, level);
    if (!(out = scram_open("-", omode))) {
	fprintf(stderr, "Failed to open bam file %s\n", argv[optind+1]);
	return 1;
    }

    /* Open multiple input files */
    sprintf(imode, "r%s%c", in_f, level);
    n_input = argc - optind;
    if (!n_input) {
	fprintf(stderr, "No input files specified.\n");
	return 1;
    }
    if (!(in = malloc(n_input * sizeof(*in))))
	return 1;
    if (!(s = malloc(n_input * sizeof(*s))))
	return 1;
    for (i = 0; i < n_input; i++, optind++) {
	s[i] = NULL;
	if (*in_f == 0)
	    sprintf(imode, "r%s%c", detect_format(argv[optind]), level);
	if (!(in[i] = scram_open(argv[optind], imode))) {
	    fprintf(stderr, "Failed to open bam file %s\n", argv[optind]);
	    return 1;
	}
	if (i && !hdr_compare(scram_get_header(in[0]),
			      scram_get_header(in[i]))) {
	    fprintf(stderr, "Incompatible reference sequence list.\n");
	    fprintf(stderr, "Currently the @SQ lines need to be identical"
		    " in all files.\n");
	    return 1;
	}

	if (!refs && scram_get_refs(in[i]))
	    refs = scram_get_refs(in[i]);

	if (refs && scram_set_option(in[i], CRAM_OPT_SHARED_REF, refs))
	    return 1;
    }

    /* Set any format specific options */
    if (refs)
	scram_set_option(out, CRAM_OPT_SHARED_REF, refs);

    if (scram_set_option(out, CRAM_OPT_VERBOSITY, verbose))
	return 1;
    if (s_opt)
	if (scram_set_option(out, CRAM_OPT_SEQS_PER_SLICE, s_opt))
	    return 1;

    if (S_opt)
	if (scram_set_option(out, CRAM_OPT_SLICES_PER_CONTAINER, S_opt))
	    return 1;

    if (embed_ref)
	if (scram_set_option(out, CRAM_OPT_EMBED_REF, embed_ref))
	    return 1;
    
    /* Copy header and refs from in to out, for writing purposes */
    // FIXME: do proper merging of @PG lines
    // FIXME: track mapping of old PG aux name to new PG aux name per seq
    scram_set_header(out, sam_hdr_dup(scram_get_header(in[0])));

    // Needs doing after loading the header.
    if (ref_fn)
	if (scram_set_option(out, CRAM_OPT_REFERENCE, ref_fn))
	    return 1;

    if (scram_get_header(in[0])) {
	if (scram_write_header(out))
	    return 1;
    }


    /* Do the actual file format conversion */
    fprintf(stderr, "Opening and loading initial seqs\n");
    for (i = 0; i < n_input; i++) {
	if (scram_get_seq(in[i], &s[i]) < 0) {
	    if (scram_close(in[i]))
		return 1;
	    in[i] = NULL;
	    free(s[i]);
	    continue;
	}
    }

    fprintf(stderr, "Merging...\n");
    for (;;) {
	int64_t best_val = INT64_MAX;
	int best_j = 0, j;

	for (j = 0; j < n_input; j++) {
	    bam_seq_t *b = s[j];
	    uint64_t x;
	    if (!in[j])
		continue;

	    x = (((uint64_t)bam_ref(b))<<33)
		| (bam_pos(b)<<2)
		| (bam_strand(b)<<1)
		| !(bam_flag(b) & BAM_FREAD1);
	    if (best_val > x) {
		best_val = x;
		best_j = j;
	    }
	}
	
	if (best_val == INT64_MAX) { // all closed
	    break;
	}

	if (-1 == scram_put_seq(out, s[best_j]))
	    return 1;
	
	if (scram_get_seq(in[best_j], &s[best_j]) < 0) {
	    if (scram_close(in[best_j]))
		return 1;
	    in[best_j] = NULL;
	    free(s[best_j]);
	}
    }

    for (i = 0; i < n_input; i++) {
	if (!in[i])
	    continue;
	scram_close(in[i]);
	if (s[i])
	    free(s[i]);
    }

    /* Finally tidy up and close files */
    if (scram_close(out))
	return 1;
    free(in);
    free(s);

    return 0;
}
void setArguments(){
    /*
     * Verification os file in
     */
    if (fileIn == NULL){
        fprintf(stderr, "There is no input file.\n");
        exit(-1);
    }

    /*
     * Verification o number of bits.
     * Number default: 1.
     */
    if (nbBits == -1){
        nbBits = 1;
    }
    else{
        if(nbBits>8 || nbBits <1){
            fprintf(stderr, "Not possible to pattern a message with this number of bits\n");
            exit(-1);
        }
    }

    /*
     * Verification of pattern
     * Default pattern: Direct.
     */
    if(pattern == NULL){
        pattern = "DIRECT";
        patternInt = 1;
    }
    else{
        flag = validatePattern();
        switch (flag){
            case -1:
                fprintf(stderr, "Not a valid pattern\n");
                exit(-1);
            case 1:
                patternInt = flag; //Direct Pattern
                break;
            case 2:
                patternInt = flag; //Inverse
                break;
            case 3:
                fprintf(stderr, "External spiral pattern not implemented\n");
                exit(-3);
            case 4:
                fprintf(stderr, "Internal spiral pattern not implemented\n");
                exit(-4);
        }
    }

    /**
     * Setting and validation os Channels
     * Default: Red,Green,Blue
     */
    if (channels == NULL){
        firstChannel = 2;
        secondChannel = 1;
        thirdChannel = 0;
    }else{
        setChannels();
    }

    /**
     * Validation of Magic Number
     * Default: 48454C50
     */
    if(magicHexa == NULL){
        magicHexa = "48454C50";
        magic = hex_to_str(magicHexa); // magic = "HELP"
    }else{
        magic = hex_to_str(magicHexa);
    }

    /**
     * Validation of Output
     * Default: Standart (Console)
     */
    if(fileOut != NULL){
        isStandard = false;
    }
    else {
        isStandard = true;
        fileOut = "output.txt";
    }

    /**
     * Validation of the format of input
     * If there is no format, the program will detect.
     * If the format of the image its different of the argument or it is not a format accepted,
     * the program ends/error.
     */

    img = cvLoadImage(fileIn, 1); // Second parameter == 1 (RGB) || == 0 (GREY)
    if (img){ //Try to load the image by OpenCv
        if(formatIn == NULL){
            int format = detect_format(fileIn);
            if (format == -1){
                fprintf(stderr, "Not possible to detect format\n");
                exit(-1);
            }
        }
        else {
            flag = validateFormat();
            switch (flag) {
                case 0: //Accepted
                    break;
                case -1:
                    fprintf(stderr, "%s is not a format accepted\n", formatIn);
                    exit(-1);
                case -2:
                    fprintf(stderr, "This format is not the format of the image\n");
                    exit(-2);
                case -3:
                    fprintf(stderr, "Not a format valid\n");
                    exit(-2);
            }
        }
    }else{
        fprintf(stderr, "Could not open the file\n");
        exit(-3);
    }
}
Esempio n. 4
0
int main(int argc, char **argv) {
    scram_fd *in, *out;
    bam_seq_t *s;
    char imode[10], *in_f = "", omode[10], *out_f = "";
    int level = '\0'; // nul terminate string => auto level
    int c, verbose = 0;
    int s_opt = 0, S_opt = 0, embed_ref = 0, ignore_md5 = 0, decode_md = 0;
    char *ref_fn = NULL;
    int start, end, multi_seq = -1, no_ref = 0;
    int use_bz2 = 0, use_arith = 0, use_lzma = 0;
    char ref_name[1024] = {0};
    refs_t *refs;
    int nthreads = 1;
    t_pool *p = NULL;
    int max_reads = -1;
    enum quality_binning binning = BINNING_NONE;

    /* Parse command line arguments */
    while ((c = getopt(argc, argv, "u0123456789hvs:S:V:r:xXeI:O:R:!MmjJZt:BN:")) != -1) {
	switch (c) {
	case '0': case '1': case '2': case '3': case '4':
	case '5': case '6': case '7': case '8': case '9':
	    level = c;
	    break;
	    
	case 'u':
	    level = '0';
	    break;

	case 'h':
	    usage(stdout);
	    return 0;

	case 'v':
	    verbose++;
	    break;

	case 's':
	    s_opt = atoi(optarg);
	    break;

	case 'S':
	    S_opt = atoi(optarg);
	    break;

	case 'm':
	    decode_md = 1;
	    break;

	case 'V':
	    if (cram_set_option(NULL, CRAM_OPT_VERSION, optarg))
		return 1;
	    break;

	case 'r':
	    ref_fn = optarg;
	    break;

	case 'X':
	    fprintf(stderr, "-X is deprecated in favour of -e.\n");
	case 'e':
	    embed_ref = 1;
	    break;

	case 'x':
	    no_ref = 1;
	    break;

	case 'I':
	    in_f = parse_format(optarg);
	    break;

	case 'O':
	    out_f = parse_format(optarg);
	    break;

	case 'R': {
	    char *cp = strchr(optarg, ':');
	    if (cp) {
		*cp = 0;
		switch (sscanf(cp+1, "%d-%d", &start, &end)) {
		case 1:
		    end = start;
		    break;
		case 2:
		    break;
		default:
		    fprintf(stderr, "Malformed range format\n");
		    return 1;
		}
	    } else {
		start = INT_MIN;
		end   = INT_MAX;
	    }
	    strncpy(ref_name, optarg, 1023);
	    break;
	}

	case '!':
	    ignore_md5 = 1;
	    break;

	case 'M':
	    multi_seq = 1;
	    break;

	case 'j':
#ifdef HAVE_LIBBZ2
	    use_bz2 = 1;
#else
	    fprintf(stderr, "Warning: bzip2 support is not compiled into this"
		    " version.\nPlease recompile.\n");
#endif
	    break;

	case 'J':
	    use_arith = 1;
	    break;

	case 'Z':
#ifdef HAVE_LIBLZMA
	    use_lzma = 1;
#else
	    fprintf(stderr, "Warning: lzma support is not compiled into this"
		    " version.\nPlease recompile.\n");
#endif
	    break;

	case 't':
	    nthreads = atoi(optarg);
	    if (nthreads < 1) {
		fprintf(stderr, "Number of threads needs to be >= 1\n");
		return 1;
	    }
	    break;

	case 'B':
	    binning = BINNING_ILLUMINA;
	    break;

	case 'N': // For debugging
	    max_reads = atoi(optarg);
	    break;

	case '?':
	    fprintf(stderr, "Unrecognised option: -%c\n", optopt);
	    usage(stderr);
	    return 1;
	}
    }    

    if (argc - optind > 2) {
	fprintf(stderr, "Usage: scramble [input_file [output_file]]\n");
	return 1;
    }
    

    /* Open up input and output files */
    sprintf(imode, "r%s%c", in_f, level);
    if (argc - optind > 0) {
	if (*in_f == 0)
	    sprintf(imode, "r%s%c", detect_format(argv[optind]), level);
	if (!(in = scram_open(argv[optind], imode))) {
	    fprintf(stderr, "Failed to open file %s\n", argv[optind]);
	    return 1;
	}
    } else {
	if (!(in = scram_open("-", imode))) {
	    fprintf(stderr, "Failed to open file %s\n", argv[optind]);
	    return 1;
	}
    }
    if (!in->is_bam && ref_fn) {
	cram_load_reference(in->c, ref_fn);
	if (!in->c->refs && !embed_ref) {
	    fprintf(stderr, "Unable to find an appropriate reference.\n"
		    "Please specify a valid reference with "
		    "-r ref.fa option.\n");
	    return 1;
	}
    }

    sprintf(omode, "w%s%c", out_f, level);
    if (argc - optind > 1) {
	if (*out_f == 0)
	    sprintf(omode, "w%s%c", detect_format(argv[optind+1]), level);
	if (!(out = scram_open(argv[optind+1], omode))) {
	    fprintf(stderr, "Failed to open file %s\n", argv[optind+1]);
	    return 1;
	}
    } else {
	if (!(out = scram_open("-", omode))) {
	    fprintf(stderr, "Failed to open file %s\n", argv[optind+1]);
	    return 1;
	}
    }


    /* Set any format specific options */
    scram_set_refs(out, refs = scram_get_refs(in));

    scram_set_option(out, CRAM_OPT_VERBOSITY, verbose);
    if (s_opt)
	if (scram_set_option(out, CRAM_OPT_SEQS_PER_SLICE, s_opt))
	    return 1;

    if (S_opt)
	if (scram_set_option(out, CRAM_OPT_SLICES_PER_CONTAINER, S_opt))
	    return 1;

    if (embed_ref)
	if (scram_set_option(out, CRAM_OPT_EMBED_REF, embed_ref))
	    return 1;

    if (use_bz2)
	if (scram_set_option(out, CRAM_OPT_USE_BZIP2, use_bz2))
	    return 1;

    if (use_arith)
	if (scram_set_option(out, CRAM_OPT_USE_ARITH, use_arith))
	    return 1;

    if (use_lzma)
	if (scram_set_option(out, CRAM_OPT_USE_LZMA, use_lzma))
	    return 1;

    if (binning != BINNING_NONE)
	if (scram_set_option(out, CRAM_OPT_BINNING, binning))
	    return 1;

    if (no_ref)
	if (scram_set_option(out, CRAM_OPT_NO_REF, no_ref))
	    return 1;

    if (multi_seq)
	if (scram_set_option(out, CRAM_OPT_MULTI_SEQ_PER_SLICE, multi_seq))
	    return 1;

    if (decode_md) {
	if (no_ref) {
	    fprintf(stderr, "Cannot use -m in conjunction with -x.\n");
	    return 1;
	}
	if (scram_set_option(in, CRAM_OPT_DECODE_MD, decode_md))
	    return 1;
    }

    if (nthreads > 1) {
	if (NULL == (p = t_pool_init(nthreads*2, nthreads)))
	    return 1;

	if (scram_set_option(in,  CRAM_OPT_THREAD_POOL, p))
	    return 1;
	if (scram_set_option(out, CRAM_OPT_THREAD_POOL, p))
	    return 1;
    }

    if (ignore_md5)
	if (scram_set_option(in, CRAM_OPT_IGNORE_MD5, ignore_md5))
	    return 1;
    

    /* Copy header and refs from in to out, for writing purposes */
    scram_set_header(out, scram_get_header(in));

    // Needs doing after loading the header.
    if (ref_fn) {
	if (scram_set_option(out, CRAM_OPT_REFERENCE, ref_fn))
	    return 1;
    } else {
	// Attempt to fill out a cram->refs[] array from @SQ headers
	scram_set_option(out, CRAM_OPT_REFERENCE, NULL);
    }

    if (scram_get_header(out)) {
	char *arg_list = stringify_argv(argc, argv);

	if (!arg_list)
	    return 1;

	if (sam_hdr_add_PG(scram_get_header(out), "scramble",
			   "VN", PACKAGE_VERSION,
			   "CL", arg_list, NULL))
	    return 1;

	if (scram_write_header(out))
	    return 1;

	free(arg_list);

    }


    /* Support for sub-range queries, currently implemented for CRAM only */
    if (*ref_name != 0) {
	cram_range r;
	int refid;

	if (in->is_bam) {
	    fprintf(stderr, "Currently the -R option is only implemented for CRAM indices\n");
	    return 1;
	}
	    
	cram_index_load(in->c, argv[optind]);

	refid = sam_hdr_name2ref(in->c->header, ref_name);

	if (refid == -1 && *ref_name != '*') {
	    fprintf(stderr, "Unknown reference name '%s'\n", ref_name);
	    return 1;
	}
	r.refid = refid;
	r.start = start;
	r.end = end;
	if (scram_set_option(in, CRAM_OPT_RANGE, &r))
	    return 1;
    }

    /* Do the actual file format conversion */
    s = NULL;

    while (scram_get_seq(in, &s) >= 0) {
	if (-1 == scram_put_seq(out, s)) {
	    fprintf(stderr, "Failed to encode sequence\n");
	    return 1;
	}
	if (max_reads >= 0)
	    if (--max_reads == 0)
		break;
    }

    if (max_reads == -1) {
	switch(scram_eof(in)) {
	case 0:
	    fprintf(stderr, "Failed to decode sequence\n");
	    return 1;
	case 2:
	    fprintf(stderr, "Warning: no end-of-file block identified. "
		    "File may be truncated.\n");
	    break;
	case 1: default:
	    // expected case
	    break;
	}
    }

    /* Finally tidy up and close files */
    if (scram_close(in))
	return 1;
    if (scram_close(out))
	return 1;

    if (p)
	t_pool_destroy(p, 0);

    if (s)
	free(s);

    return 0;
}
Esempio n. 5
0
int main(int argc, char **argv) {
    scram_fd *in;
    bam_seq_t *s;
    char imode[10], *in_f = "";
    int level = '\0'; // nul terminate string => auto level
    int c;
    char *ref_fn = NULL;
    int start, end, ignore_md5 = 0;
    char ref_name[1024] = {0};
    bam_flagstat_t st;
    int nthreads = 1;

    memset(&st, 0, sizeof(st));

    /* Parse command line arguments */
    while ((c = getopt(argc, argv, "hI:R:r:!t:")) != -1) {
	switch (c) {
	case 'h':
	    usage(stdout);
	    return 0;

	case 'r':
	    ref_fn = optarg;
	    break;

	case 'I':
	    in_f = parse_format(optarg);
	    break;

	case 'R': {
	    char *cp = strchr(optarg, ':');
	    if (cp) {
		*cp = 0;
		switch (sscanf(cp+1, "%d-%d", &start, &end)) {
		case 1:
		    end = start;
		    break;
		case 2:
		    break;
		default:
		    fprintf(stderr, "Malformed range format\n");
		    return 1;
		}
	    } else {
		start = INT_MIN;
		end   = INT_MAX;
	    }
	    strncpy(ref_name, optarg, 1023);
	    break;
	}

	case '!':
	    ignore_md5 = 1;
	    break;

	case 't':
	    nthreads = atoi(optarg);
	    if (nthreads < 1) {
		fprintf(stderr, "Number of threads needs to be >= 1\n");
		return 1;
	    }
	    break;

	case '?':
	    fprintf(stderr, "Unrecognised option: -%c\n", optopt);
	    usage(stderr);
	    return 1;
	}
    }    

    if (argc - optind > 2) {
	fprintf(stderr, "Usage: scramble [input_file [output_file]]\n");
	return 1;
    }
    

    /* Open up input and output files */
    sprintf(imode, "r%s%c", in_f, level);
    if (argc - optind > 0) {
	if (*in_f == 0)
	    sprintf(imode, "r%s%c", detect_format(argv[optind]), level);
	if (!(in = scram_open(argv[optind], imode))) {
	    fprintf(stderr, "Failed to open file %s\n", argv[optind]);
	    return 1;
	}
    } else {
	if (!(in = scram_open("-", imode))) {
	    fprintf(stderr, "Failed to open file %s\n", argv[optind]);
	    return 1;
	}
    }
    if (!in->is_bam && ref_fn)
	cram_load_reference(in->c, ref_fn);

    if (nthreads > 1) 
	if (scram_set_option(in,  CRAM_OPT_NTHREADS, nthreads))
	    return 1;

    if (ignore_md5)
	if (scram_set_option(in, CRAM_OPT_IGNORE_MD5, ignore_md5))
	    return 1;
    

    /* Support for sub-range queries, currently implemented for CRAM only */
    if (*ref_name != 0) {
	cram_range r;
	int refid;

	if (in->is_bam) {
	    fprintf(stderr, "Currently the -R option is only implemented for CRAM indices\n");
	    return 1;
	}
	    
	cram_index_load(in->c, argv[optind]);

	refid = sam_hdr_name2ref(in->c->header, ref_name);

	if (refid == -1 && *ref_name != '*') {
	    fprintf(stderr, "Unknown reference name '%s'\n", ref_name);
	    return 1;
	}
	r.refid = refid;
	r.start = start;
	r.end = end;
	if (scram_set_option(in, CRAM_OPT_RANGE, &r))
	    return 1;
    }

    /* Do the actual file format conversion */
    s = NULL;
    while (scram_get_seq(in, &s) >= 0) {
	int w = s->flag & BAM_FQCFAIL ? 1 : 0;
	++st.n_reads[w];

	if (s->flag & BAM_FPAIRED) {
	    ++st.n_pair_all[w];
	    if (s->flag & BAM_FPROPER_PAIR)
		++st.n_pair_good[w];

	    if (s->flag & BAM_FREAD1)
		++st.n_read1[w];

	    if (s->flag & BAM_FREAD2)
		++st.n_read2[w];

	    if ((s->flag & BAM_FMUNMAP) && !(s->flag & BAM_FUNMAP))
		++st.n_sgltn[w]; 

	    if (!(s->flag & BAM_FUNMAP) && !(s->flag & BAM_FMUNMAP)) {
		++st.n_pair_map[w];

		if (s->mate_ref != s->ref) {
		    ++st.n_diffchr[w];
		    if (s->map_qual >= 5)
			++st.n_diffhigh[w];
		}
	    }
	}

	if (!(s->flag & BAM_FUNMAP))
	    ++st.n_mapped[w];

	if (s->flag & BAM_FDUP)
	    ++st.n_dup[w];
    }

    if (s)
	free(s);

    if (!scram_eof(in))
	return 1;

    if (scram_close(in))
	return 1;

    printf("%lld + %lld in total (QC-passed reads + QC-failed reads)\n", st.n_reads[0], st.n_reads[1]);
    printf("%lld + %lld duplicates\n", st.n_dup[0], st.n_dup[1]);
    printf("%lld + %lld mapped (%.2f%%:%.2f%%)\n", st.n_mapped[0], st.n_mapped[1], (float)st.n_mapped[0] / st.n_reads[0] * 100.0, (float)st.n_mapped[1] / st.n_reads[1] * 100.0);
    printf("%lld + %lld paired in sequencing\n", st.n_pair_all[0], st.n_pair_all[1]);
    printf("%lld + %lld read1\n", st.n_read1[0], st.n_read1[1]);
    printf("%lld + %lld read2\n", st.n_read2[0], st.n_read2[1]);
    printf("%lld + %lld properly paired (%.2f%%:%.2f%%)\n", st.n_pair_good[0], st.n_pair_good[1], (float)st.n_pair_good[0] / st.n_pair_all[0] * 100.0, (float)st.n_pair_good[1] / st.n_pair_all[1] * 100.0);
    printf("%lld + %lld with itself and mate mapped\n", st.n_pair_map[0], st.n_pair_map[1]);
    printf("%lld + %lld singletons (%.2f%%:%.2f%%)\n", st.n_sgltn[0], st.n_sgltn[1], (float)st.n_sgltn[0] / st.n_pair_all[0] * 100.0, (float)st.n_sgltn[1] / st.n_pair_all[1] * 100.0);
    printf("%lld + %lld with mate mapped to a different chr\n", st.n_diffchr[0], st.n_diffchr[1]);
    printf("%lld + %lld with mate mapped to a different chr (mapQ>=5)\n", st.n_diffhigh[0], st.n_diffhigh[1]);

    return 0;
}
static int
read_spec(struct mtree_reader *r, char *s)
{
	struct mtree_entry	*entry;
	char			 name[MAXPATHLEN];
	char			*slash, *file, *word, *next;
	int			 ret;
	int			 skip = 0;

	/* Try to detect the format if it isn't known yet. */
	if (r->path_last == -1 && detect_format(r, s) == -1)
		return (-1);
	if (r->path_last != 1) {
		/*
		 * Path is surely in the first field, either because we know
		 * the format or there is just one single field.
		 */
		read_word(s, &file, &next);
		assert(file != NULL);

		if (IS_DOTDOT(file)) {
			/* Only change the parent, keywords are ignored. */
			if (r->parent == NULL) {
				mtree_reader_set_error(r, EINVAL,
				    "`..' not allowed, no parent directory");
				return (-1);
			}
			r->parent = r->parent->parent;
			return (0);
		}
	}
	entry = mtree_entry_create_empty();
	if (entry == NULL) {
		mtree_reader_set_error(r, errno, NULL);
		return (-1);
	}

	if (r->path_last != 1) {
		if (next != NULL) {
			/* Read keyword that follow the path. */
			ret = read_keywords(r, next, &entry->data, 1);
			if (ret == -1) {
				mtree_entry_free(entry);
				return (-1);
			}
		}
	} else {
		/* Path is at the end, read the keywords first. */
		for (file = NULL; file == NULL;) {
			read_word(s, &word, &next);
			assert(word != NULL);

			if (next != NULL) {
				ret = read_keyword(r, word, &entry->data, 1);
				if (ret == -1) {
					mtree_entry_free(entry);
					return (-1);
				}
				s = next;
			} else
				file = word;
		}
		assert(file != NULL);

		if (IS_DOTDOT(file)) {
			mtree_reader_set_error(r, EINVAL, "`..' not allowed in "
			    "this format");
			mtree_entry_free(entry);
			return (-1);
		}
	}
	/* Copy /set values to the entry. */
	mtree_entry_data_copy_keywords(&entry->data, &r->defaults,
	    r->defaults.keywords, 0);

	/*
	 * See if we should skip this file.
	 */
	if (SKIP_TYPE(r->options, entry->data.type)) {
		/*
		 * With directories in version 1.0 format, we'll have to worry
		 * about potentially setting the directory as the current
		 * parent, other types can be skipped immediately.
		 */
		if (entry->data.type != MTREE_ENTRY_DIR || r->path_last == 1)
			goto skip;
		else
			skip = 1;
	}

	/* Save the file path and name. */
	if (strnunvis(name, sizeof(name), file) == -1) {
		mtree_reader_set_error(r, ENAMETOOLONG, "File name too long: `%s'",
		    file);
		mtree_entry_free(entry);
		return (-1);
	}
	if ((slash = strchr(name, '/')) != NULL) {
		/*
		 * If the name contains a slash, it is a relative path.
		 * These do not change the working directory.
		 */
		if (skip)
			goto skip;
		ret = mtree_cleanup_path(name, &entry->path, &entry->name);
		if (ret == -1) {
			mtree_reader_set_error(r, errno, NULL);
			mtree_entry_free(entry);
			return (-1);
		}
	} else {
		entry->name = strdup(name);
		if (entry->name == NULL) {
			mtree_reader_set_error(r, errno, NULL);
			mtree_entry_free(entry);
			return (-1);
		}
		entry->parent = r->parent;
		entry->path = create_v1_path(entry);
		if (entry->path == NULL) {
			mtree_reader_set_error(r, errno, NULL);
			mtree_entry_free(entry);
			return (-1);
		}
	}

	/*
	 * We may want to skip this entry if a filter told us to skip
	 * children of a directory, which is a parent of this entry.
	 *
	 * There is also no need to worry about changing the parent if
	 * this happens.
	 */
	if (!skip && r->skip_trie != NULL) {
		char *tok;
		char *endptr;

		for (tok = strtok_r(name, "/", &endptr); tok != NULL;
		     tok = strtok_r(NULL, "/", &endptr)) {
			if (mtree_trie_find(r->skip_trie, tok) != NULL) {
				mtree_entry_free(entry);
				return (0);
			}
		}
	}

	/*
	 * Mark the current entry as the current directory. This only applies
	 * to classic (1.0) entries and must be done after keywords are read.
	 */
	if (slash == NULL && entry->data.type == MTREE_ENTRY_DIR)
		r->parent = entry;
	if (skip)
		goto skip;

	if (r->filter != NULL) {
		int result;

		/* Apply filter. */
		result = r->filter(entry, r->filter_data);
		if (result & MTREE_ENTRY_SKIP_CHILDREN) {
			if (entry->data.type == MTREE_ENTRY_DIR) {
				struct mtree_entry *found, *start;

				if (r->skip_trie == NULL) {
					r->skip_trie = mtree_trie_create(NULL);
					if (r->skip_trie == NULL) {
						mtree_reader_set_error(r, errno,
						    NULL);
						return (-1);
					}
				}
				if (mtree_trie_insert(r->skip_trie, entry->path,
				    TRIE_ITEM) == -1) {
					mtree_reader_set_error(r, errno,
					    NULL);
					return (-1);
				}

				strcpy(name, entry->path);
				strcat(name, "/");
				/*
				 * Remove children that are already in the
				 * list.
				 */
				start = r->entries;
				for (;;) {
					found = mtree_entry_find_prefix(start,
					    name);
					if (found == NULL)
						break;

					start = found->next;
					r->entries = mtree_entry_unlink(
					    r->entries, found);
					mtree_entry_free(found);
				}
			}
		}
		if (result & MTREE_ENTRY_SKIP)
			goto skip;
	}

	r->entries = mtree_entry_prepend(r->entries, entry);
	return (0);
skip:
	/*
	 * Skipping directory which is the current parent would make its files
	 * end up in a wrong directory.
	 *
	 * Keep such entries in a list of `loose' entries instead, these will
	 * be deleted when all the work is done.
	 */
	if (entry == r->parent)
		r->loose = mtree_entry_prepend(r->loose, entry);
	else
		mtree_entry_free(entry);
	return (0);
}