int main(int argc, char *argv[]) { /* Setup the input data structures handlers */ int format_output = 0; int strict_tags = 0; int echo_settings = 0; int dump_args = 0 ; /* set to 1 if dumping arguments to choose_primers */ int io_version = 4; /* Some space for file names */ char p3_all_file[FILE_NAME_SIZE]; char p3_settings_file[FILE_NAME_SIZE]; p3_global_settings *global_pa; seq_args *sarg; read_boulder_record_results read_boulder_record_res = {0,0}; pr_append_str fatal_parse_err; pr_append_str nonfatal_parse_err; pr_append_str warnings; /* Some variables needed by getopt */ int opt, option_index = 0; struct option long_options[] = { {"about", no_argument, 0, 'a'}, {"format_output", no_argument, &format_output, 1}, {"strict_tags", no_argument, &strict_tags, 1}, {"p3_settings_file", required_argument, 0, 'p'}, {"echo_settings_file", no_argument, &echo_settings, 1}, {"io_version", required_argument, 0, 'i'}, {"2x_compat", no_argument, 0, '2'}, {"output", required_argument, 0, 'o'}, {"error", required_argument, 0, 'e'}, {0, 0, 0, 0} }; int about = 0, output = 0, error = 0, compat = 0, invalid_flag = 0; char output_file[FILE_NAME_SIZE], error_file[FILE_NAME_SIZE]; /* Retval will point to the return value from choose_primers(). */ p3retval *retval = NULL; int input_found=0; p3_all_file[0] = '\0'; p3_settings_file[0] = '\0'; init_pr_append_str(&fatal_parse_err); init_pr_append_str(&nonfatal_parse_err); init_pr_append_str(&warnings); /* Get the program name for correct error messages */ pr_release = libprimer3_release(); pr_program_name = argv[0]; p3_set_program_name(pr_program_name); /* We set up some signal handlers in case someone starts up the program * from the command line, wonders why nothing is happening, and then kills * the program. */ signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); /* Allocate the space for global settings and fill in default parameters */ global_pa = p3_create_global_settings(); if (!global_pa) { exit(-2); /* Out of memory. */ } if (dump_args) global_pa->dump = 1 ; /* Read in the flags provided with the program call */ opterr = 0; while ((opt = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) { switch (opt) { case 'a': about = 1; break; case 'p': strncpy(p3_settings_file, optarg, FILE_NAME_SIZE - 1); break; case 'i': if (!strcmp(optarg, "3")) io_version = 3; else if (!strcmp(optarg, "4")) io_version = 4; else io_version = -1; break; case '2': compat = 1; break; case 'o': output = 1; strncpy(output_file, optarg, FILE_NAME_SIZE - 1); break; case 'e': error = 1; strncpy(error_file, optarg, FILE_NAME_SIZE - 1); break; case '?': invalid_flag = 1; break; } } /* Open the output and error files specified */ if (error == 1) { /* reassign stderr */ if (freopen(error_file, "w", stderr) == NULL) { fprintf(stderr, "Error creating file %s\n", error_file); exit(-1); } } if (output == 1) { /* reassign stdout */ if (freopen(output_file, "w", stdout) == NULL) { fprintf(stderr, "Error creating file %s\n", output_file); exit(-1); } } /* We do any printing after redirecting stdout and stderr */ if (about == 1) { printf("%s\n", pr_release); exit(0); } if ((io_version == -1) || (invalid_flag == 1)) { print_usage(); exit(-1); } if (compat == 1) { printf("PRIMER_ERROR=flag -2x_compat is no longer supported\n=\n"); exit(-1); } /* Check if an input file has been specified */ if (optind < argc) { if (optind + 1 != argc) { print_usage(); exit(-1); } if (freopen(argv[optind], "r", stdin) == NULL) { fprintf(stderr, "Error opening file %s\n", argv[optind]); exit(-1); } } /* Settings files have to be read in just below, and the functions need a temporary sarg */ if (!(sarg = create_seq_arg())) { exit(-2); } /* Read data from the settings file until a "=" line occurs. Assign parameter * values for primer picking to pa and sa. */ if (p3_settings_file[0] != '\0') { read_p3_file(p3_settings_file, settings, echo_settings && !format_output, global_pa, sarg, &fatal_parse_err, &nonfatal_parse_err, &warnings, &read_boulder_record_res); /* Check if the thermodynamical alignment flag was given */ if (global_pa->thermodynamic_alignment == 1) read_thermodynamic_parameters(); } /* We also need to print out errors here because the loop erases all * errors at start */ /* If there are fatal errors, write the proper message and exit */ if (fatal_parse_err.data != NULL) { if (format_output) { format_error(stdout, sarg->sequence_name, fatal_parse_err.data); } else { print_boulder_error(fatal_parse_err.data); } fprintf(stderr, "%s: %s\n", pr_program_name, fatal_parse_err.data); destroy_seq_args(sarg); exit(-4); } /* If there are nonfatal errors, write the proper message * and skip to the end of the loop */ if (!pr_is_empty(&nonfatal_parse_err)) { if (format_output) { format_error(stdout, sarg->sequence_name, nonfatal_parse_err.data); } else { print_boulder_error(nonfatal_parse_err.data); } } /* The temporary sarg is not needed any more */ destroy_seq_args(sarg); sarg = NULL; /* Read the data from input stream record by record and process it if * there are no errors. This is where the work is done. */ while (1) { /* Create and initialize a seq_args data structure. sa (seq_args *) is * initialized here because Values are _not_ retained across different * input records. */ if (!(sarg = create_seq_arg())) { exit(-2); } /* Reset all errors handlers and the return structure */ pr_set_empty(&fatal_parse_err); pr_set_empty(&nonfatal_parse_err); pr_set_empty(&warnings); retval = NULL; /* See read_boulder.h for documentation on read_boulder_record().*/ if (!read_boulder_record(stdin, &strict_tags, &io_version, !format_output, all_parameters, global_pa, sarg, &fatal_parse_err, &nonfatal_parse_err, &warnings, &read_boulder_record_res)) { break; /* There were no more boulder records */ } /* Check if the thermodynamical alignment flag was given and the path to the parameter files changed - we need to reread them */ if ((global_pa->thermodynamic_alignment == 1) && (thermodynamic_path_changed == 1)) read_thermodynamic_parameters(); input_found = 1; if ((global_pa->primer_task == pick_detection_primers) && (global_pa->pick_internal_oligo == 1)){ PR_ASSERT(global_pa->pick_internal_oligo); } /* If there are fatal errors, write the proper message and exit */ if (fatal_parse_err.data != NULL) { if (format_output) { format_error(stdout, sarg->sequence_name, fatal_parse_err.data); } else { print_boulder_error(fatal_parse_err.data); } fprintf(stderr, "%s: %s\n", pr_program_name, fatal_parse_err.data); destroy_p3retval(retval); destroy_seq_args(sarg); exit(-4); } /* If there are nonfatal errors, write the proper message * and skip to the end of the loop */ if (!pr_is_empty(&nonfatal_parse_err)) { if (format_output) { format_error(stdout, sarg->sequence_name, nonfatal_parse_err.data); } else { print_boulder_error(nonfatal_parse_err.data); } goto loop_wrap_up; } /* Print any warnings and continue processing */ if (!pr_is_empty(&warnings)) { if (format_output) { format_warning(stdout, sarg->sequence_name, warnings.data); } else { print_boulder_warning(warnings.data); } } if (read_boulder_record_res.file_flag && sarg->sequence_name == NULL) { /* We will not have a base name for the files */ if (format_output) { format_error(stdout, NULL, "Need PRIMER_SEQUENCE_ID if PRIMER_FILE_FLAG is not 0"); } else { print_boulder_error("Need PRIMER_SEQUENCE_ID if PRIMER_FILE_FLAG is not 0"); } goto loop_wrap_up; } /* Pick the primers - the central function */ p3_set_gs_primer_file_flag(global_pa, read_boulder_record_res.file_flag); retval = choose_primers(global_pa, sarg); if (NULL == retval) exit(-2); /* Out of memory. */ /* This is old code to make it compatible with version 3 input. In future versions it can be deleted! If it was necessary to use a left_input, right_input, or internal_oligo_input primer that was unacceptable, then add warnings. */ if (global_pa->pick_anyway && (io_version == 3 || format_output)) { if (sarg->left_input) { add_must_use_warnings(&retval->warnings, "Left primer", &retval->fwd.expl); } if (sarg->right_input) { add_must_use_warnings(&retval->warnings, "Right primer", &retval->rev.expl); } if (sarg->internal_input) { add_must_use_warnings(&retval->warnings, "Hybridization probe", &retval->intl.expl); } } /* End of the old code for compartibility. */ if (pr_is_empty(&retval->glob_err) && pr_is_empty(&retval->per_sequence_err)) { /* We need to test for errors before we call p3_print_oligo_lists. This function only works on retval as returned when there were no errors. */ if (read_boulder_record_res.file_flag) { /* Create files with left, right, and internal oligos. */ p3_print_oligo_lists(retval, sarg, global_pa, &retval->per_sequence_err, sarg->sequence_name); } } if (format_output) { print_format_output(stdout, &io_version, global_pa, sarg, retval, pr_release, read_boulder_record_res.explain_flag); } else { /* Use boulder output */ print_boulder(/* & */io_version, global_pa, sarg, retval, read_boulder_record_res.explain_flag); } loop_wrap_up: /* Here the failed loops join in again */ if (NULL != retval) { /* Check for errors and print them */ if (NULL != retval->glob_err.data) { fprintf(stderr, "%s: %s\n", pr_program_name, retval->glob_err.data); destroy_p3retval(retval); destroy_seq_args(sarg); exit(-4); } } destroy_p3retval(retval); /* This works even if retval is NULL */ retval = NULL; destroy_seq_args(sarg); sarg = NULL; } /* while (1) (processing boulder io records) ... End of the primary working loop */ /* To avoid being distracted when looking for leaks: */ if (global_pa->thermodynamic_alignment == 1) destroy_thal_structures(); p3_destroy_global_settings(global_pa); global_pa = NULL; destroy_seq_args(sarg); destroy_pr_append_str_data(&nonfatal_parse_err); destroy_pr_append_str_data(&fatal_parse_err); destroy_pr_append_str_data(&warnings); destroy_dpal_thal_arg_holder(); if (thermodynamic_params_path) free(thermodynamic_params_path); /* If it could not read input complain and die */ if (0 == input_found) { print_usage(); exit(-3); } return 0; }
int main (int argc, const char *argv[]) { unsigned int idx; char *end; int debug = 0; /* sequence file name specified by the user, otherwise STDIN will be used */ const char *sequence_file_name = NULL; const char *lists_file_name = NULL; /* data structure for all k-mer lists used for masking */ unsigned int nlists = 0; unsigned int nlist_parameters = 0; unsigned int npos = 0; unsigned int list_pos[MAX_VARIABLES], list_components[MAX_VARIABLES]; masker_parameters mp = {}; parameters_builder pbuilder = {}; input_sequence *input_seq = NULL; pr_append_str parse_err; pr_append_str warnings; init_pr_append_str (&parse_err); init_pr_append_str (&warnings); /* fill mp with default parameters */ mp.mdir = DEFAULT_MASKING_DIRECTION; mp.failure_rate = DEFAULT_FAILURE_RATE; mp.abs_cutoff = DEFAULT_ABS_CUTOFF; mp.nucl_masked_in_5p_direction = DEFAULT_M5P; mp.nucl_masked_in_3p_direction = DEFAULT_M3P; mp.print_sequence = PRINT_SEQUENCE; mp.do_soft_masking = HARD_MASKING; mp.masking_char = DEFAULT_MASK_CHAR; mp.list_prefix = DEFAULT_LIST_FILE_PREFIX; /* parsing and checking the commandline arguments */ for (idx = 1; (int)idx < argc; idx++) { if (!strcmp (argv[idx], "-h") || !strcmp (argv[idx], "--help") || !strcmp (argv[idx], "-?")) { print_help (0); } else if ((int)idx == argc - 1 && argv[idx][0] != '-') { sequence_file_name = argv[idx]; } else if (!strcmp (argv[idx], "-lf") || !strcmp (argv[idx], "--lists_file")) { /* lists specified from the file */ if (!argv[idx + 1] || argv[idx + 1][0] == '-') { pr_append_new_chunk_external (&warnings, "No lists file specified."); idx += 1; continue; } lists_file_name = argv[idx + 1]; idx += 1; } else if (!strcmp (argv[idx], "-l") || !strcmp (argv[idx], "--list")) { /* lists specified from the commandline */ if (nlist_parameters == MAX_VARIABLES) { pr_append_new_chunk_external (&parse_err, "Maximum number of list variables reached."); break; } if (!argv[idx + 1]) { pr_append_new_chunk_external (&warnings, "No list name specified with -l parameter!."); continue; } /* get the positions of list files */ list_pos[nlist_parameters] = idx; while (argv[idx + 1]) { if (argv[idx + 1][0] == '-') { if (!argv[idx + 1][1]) break; strtod (argv[idx + 1] + 1, &end); if (*end != 0) break; } else if (idx + 1 != list_pos[nlist_parameters] + 1 && idx + 1 != list_pos[nlist_parameters] + 4) { strtod (argv[idx + 1], &end); if (*end != 0) break; } else if (idx + 1 == list_pos[nlist_parameters] + 4 && strcmp (argv[idx + 1], "sq")) { break; } idx += 1; } list_components[nlist_parameters] = idx - list_pos[nlist_parameters]; nlist_parameters += 1; npos += 1; } else if (!strcmp (argv[idx], "-lp") || !strcmp (argv[idx], "--list_prefix")) { /* lists specified by the prefix */ if (!argv[idx + 1] || argv[idx + 1][0] == '-') { pr_append_new_chunk_external (&warnings, "No list prefix specified! Using the default value."); idx += 1; continue; } mp.list_prefix = (char *)argv[idx + 1]; idx += 1; } else if (!strcmp (argv[idx], "-p") || !strcmp (argv[idx], "--probability_cutoff")) { if (!argv[idx + 1]) { pr_append_new_chunk_external (&warnings, "No cutoff value specified! Using the default value."); idx += 1; continue; } mp.failure_rate = strtod (argv[idx + 1], &end); mp.abs_cutoff = 0; if (*end != 0 || mp.failure_rate < 0 || mp.failure_rate > 1) { pr_append_new_chunk_external (&parse_err, "Invalid cutoff value: "); pr_append_external (&parse_err, argv[idx + 1]); break; } idx += 1; } else if (!strcmp (argv[idx], "-a") || !strcmp (argv[idx], "--absolute_value_cutoff")) { if (!argv[idx + 1]) { pr_append_new_chunk_external (&warnings, "No absolute cutoff value specified! Using the default value."); idx += 1; continue; } mp.abs_cutoff = strtod (argv[idx + 1], &end); mp.failure_rate = 0.0; if (*end != 0 || mp.abs_cutoff < 0) { pr_append_new_chunk_external (&parse_err, "Invalid absolute cutoff value: "); pr_append_external (&parse_err, argv[idx + 1]); break; } idx += 1; } else if (!strcmp (argv[idx], "-m5") || !strcmp (argv[idx], "--mask_5p")) { if (!argv[idx + 1]) { pr_append_new_chunk_external (&warnings, "Number of nucleotides masked in 5' direction not specified! Using the default value."); idx += 1; continue; } mp.nucl_masked_in_5p_direction = strtod (argv[idx + 1], &end); if (*end != 0) { pr_append_new_chunk_external (&parse_err, "Invalid number of nucleotides masked in 5' direction: "); pr_append_external (&parse_err, argv[idx + 1]); break; } idx += 1; } else if (!strcmp (argv[idx], "-m3") || !strcmp (argv[idx], "--mask_3p")) { if (!argv[idx + 1]) { pr_append_new_chunk_external (&warnings, "Number of nucleotides masked in 3' direction not specified! Using the default value."); idx += 1; continue; } mp.nucl_masked_in_3p_direction = strtod (argv[idx + 1], &end); if (*end != 0) { pr_append_new_chunk_external (&parse_err, "Invalid number of nucleotides masked in 3' direction: "); pr_append_external (&parse_err, argv[idx + 1]); break; } idx += 1; } else if (!strcmp (argv[idx], "-c") || !strcmp (argv[idx], "--masking_char")) { if (!argv[idx + 1 || argv[idx + 1][0] == '-']) { pr_append_new_chunk_external (&warnings, "Character for masking not specified! Using the default value."); idx += 1; continue; } mp.masking_char = argv[idx + 1][0]; if (strlen(argv[idx + 1]) > 1 || mp.masking_char < 33 || mp.masking_char > 126) { pr_append_new_chunk_external (&parse_err, "Invalid character for masking: "); pr_append_external (&parse_err, argv[idx + 1]); break; } idx += 1; } else if (!strcmp (argv[idx], "-d") || !strcmp (argv[idx], "--masking_direction")) { if (!argv[idx + 1] || argv[idx + 1][0] == '-') { pr_append_new_chunk_external (&warnings, "Masking direction not specified! Masking both strands by default."); } else if (!strcmp (argv[idx + 1], "both")) { mp.mdir = both_on_same; } else if (!strcmp (argv[idx + 1], "fwd")) { mp.mdir = fwd; } else if (!strcmp (argv[idx + 1], "rev")) { mp.mdir = rev; } else { pr_append_new_chunk_external (&warnings, "Unknown masking direction: "); pr_append_external (&warnings, argv[idx + 1]); pr_append_external (&warnings, ". Masking both strands by default."); } idx += 1; } else if (!strcmp (argv[idx], "-s") || !strcmp (argv[idx], "--soft_mask")) { mp.do_soft_masking = SOFT_MASKING; } else if (!strcmp (argv[idx], "-D")) { debug += 1; } else { pr_append_new_chunk_external (&parse_err, "Unknown parameter: "); pr_append_external (&parse_err, argv[idx]); break; } } input_seq = create_input_sequence_from_file_name (sequence_file_name, &parse_err); if (parse_err.data != NULL) { fprintf(stderr, "%s -> parsing commandline: ERROR: %s\n", pr_programme_name, parse_err.data); exit(-1); } if (warnings.data != NULL) { fprintf(stderr, "%s -> parsing commandline: WARNING: %s\n", pr_programme_name, warnings.data); } if (lists_file_name) { /* if lists are given in a text file */ mp.fp = read_formula_parameters_from_file (lists_file_name, &nlist_parameters, &pbuilder, &mp.formula_intercept, &parse_err); nlists = pbuilder.nfp; } if (npos != 0) { /* if lists are given by commandline arguments (can be added to the ones given in a file) */ pbuilder.fp_array = mp.fp; for (idx = 0; idx < npos; idx++) { unsigned int pos = list_pos[idx] + 1; char *values[4]; unsigned int nvalues = list_components[idx]; char *end; memcpy (&values, &argv[pos], nvalues * sizeof(*argv)); if (nvalues == 1) { double ic; double neg = 1.0; if (values[0][0] == '-') { values[0] += 1; neg = -1.0; } ic = strtod (values[0], &end); if (*end == 0) { mp.formula_intercept = ic * neg; continue; } } add_variable_to_formula_parameters (values, nvalues, &pbuilder, &parse_err); } nlists = pbuilder.nfp; mp.fp = pbuilder.fp_array; } else if (nlists == 0 && !lists_file_name) { /* if there are no lists specified use the default formula */ mp.fp = create_default_formula_parameters (mp.list_prefix, &parse_err); mp.formula_intercept = DEFAULT_INTERCEPT; nlists = DEFAULT_NLISTS; nlist_parameters = DEFAULT_NLIST_PARAMETERS; } mp.nlists = nlists; if (mp.abs_cutoff > 0 && nlist_parameters != 1) { fprintf (stderr, "Error: Absolute value cutoff works with one list and one k-mer frequency parameter only. Currently you are using %u lists and %u parameters.\n", nlists, nlist_parameters); print_help(1); } if (parse_err.data != NULL) { fprintf(stderr, "%s -> building formula: ERROR: %s\n", pr_programme_name, parse_err.data); delete_input_sequence (input_seq); exit(-1); } if (debug > 0) print_parameters (&mp); read_and_mask_sequence (input_seq, NULL, &mp, &parse_err, debug); if (parse_err.data != NULL) { fprintf(stderr, "%s -> masking sequence: ERROR: %s\n", pr_programme_name, parse_err.data); delete_input_sequence (input_seq); delete_formula_parameters (mp.fp, nlists); exit(-1); } destroy_pr_append_str_data (&warnings); destroy_pr_append_str_data (&parse_err); delete_input_sequence (input_seq); delete_formula_parameters (mp.fp, nlists); if (debug > 0) fprintf (stderr, "Done!\n"); return 0; }
int main(int argc, char *argv[]) { /* Setup the input data structures handlers */ int format_output = 0; int strict_tags = 0; int dump_args = 0 ; /* set to 1 if dumping arguments to choose_primers */ int io_version = 4; /* Some space for file names */ char *tmp_file_name = NULL; char p3_all_file[FILE_NAME_SIZE]; char p3_settings_file[FILE_NAME_SIZE]; p3_global_settings *global_pa; seq_args *sarg; read_boulder_record_results read_boulder_record_res = {0,0}; pr_append_str fatal_parse_err; pr_append_str nonfatal_parse_err; /* Retval will point to the return value from choose_primers(). */ p3retval *retval = NULL; int input_found=0; p3_all_file[0] = '\0'; p3_settings_file[0] = '\0'; init_pr_append_str(&fatal_parse_err); init_pr_append_str(&nonfatal_parse_err); /* Get the program name for correct error messages */ pr_program_name = argv[0]; p3_set_program_name(pr_program_name); /* We set up some signal handlers in case someone starts up the program * from the command line, wonders why nothing is happening, and then kills * the program. */ signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); /* Allocate the space for global settings and fill in default parameters */ global_pa = p3_create_global_settings(); if (!global_pa) { exit(-2); /* Out of memory. */ } if (dump_args) global_pa->dump = 1 ; /* Read in the flags provided with the program call */ while (--argc > 0) { argv++; if (!strcmp(*argv, "-format_output")) { format_output = 1; } else if (!strcmp(*argv, "-about")) { printf( "%s\n", pr_release); exit (0); } else if (!strcmp(*argv, "-2x_compat")) { printf( "PRIMER_ERROR=flag -2x_compat is no longer supported\n=\n"); exit (-1); } else if (!strcmp(*argv, "-io_version=3")) { io_version = 3; } else if (!strcmp(*argv, "-io_version=4")) { io_version = 4; } else if (!strncmp(*argv, "-p3_settings_file=", 18)) { tmp_file_name = strchr(*argv,'=') + 1; strncpy (p3_settings_file,tmp_file_name,FILE_NAME_SIZE-1); } else if (!strcmp(*argv, "-strict_tags")) { strict_tags = 1; } else { print_usage(); exit(-1); } } /* Settings files have to be read in just below, and the functions need a temporary sarg */ if (!(sarg = create_seq_arg())) { exit(-2); } /* Read data from the settings file until a "=" line occurs. Assign parameter * values for primer picking to pa and sa. */ if (p3_settings_file[0] != '\0') { read_p3_file(p3_settings_file, settings, global_pa, sarg, &fatal_parse_err, &nonfatal_parse_err, &read_boulder_record_res); } /* We also need to print out errors here because the loop erases all * errors at start */ /* If there are fatal errors, write the proper message and exit */ if (fatal_parse_err.data != NULL) { if (format_output) { format_error(stdout, sarg->sequence_name, fatal_parse_err.data); } else { print_boulder_error(fatal_parse_err.data); } fprintf(stderr, "%s: %s\n", pr_program_name, fatal_parse_err.data); destroy_seq_args(sarg); exit(-4); } /* If there are nonfatal errors, write the proper message * and skip to the end of the loop */ if (!pr_is_empty(&nonfatal_parse_err)) { if (format_output) { format_error(stdout, sarg->sequence_name, nonfatal_parse_err.data); } else { print_boulder_error(nonfatal_parse_err.data); } } /* The temporary sarg is not needed any more */ destroy_seq_args(sarg); sarg = NULL; /* Read the data from input stream record by record and process it if * there are no errors. This is where the work is done. */ while (1) { /* Create and initialize a seq_args data structure. sa (seq_args *) is * initialized here because Values are _not_ retained across different * input records. */ if (!(sarg = create_seq_arg())) { exit(-2); } /* Reset all errors handlers and the return structure */ pr_set_empty(&fatal_parse_err); pr_set_empty(&nonfatal_parse_err); retval = NULL; /* See read_boulder.h for documentation on read_boulder_record().*/ if (!read_boulder_record(stdin, &strict_tags, &io_version, !format_output, all_parameters, global_pa, sarg, &fatal_parse_err, &nonfatal_parse_err, &read_boulder_record_res)) { break; /* There were no more boulder records */ } input_found = 1; if ((global_pa->primer_task == pick_detection_primers) && (global_pa->pick_internal_oligo == 1)){ PR_ASSERT(global_pa->pick_internal_oligo); } /* If there are fatal errors, write the proper message and exit */ if (fatal_parse_err.data != NULL) { if (format_output) { format_error(stdout, sarg->sequence_name, fatal_parse_err.data); } else { print_boulder_error(fatal_parse_err.data); } fprintf(stderr, "%s: %s\n", pr_program_name, fatal_parse_err.data); destroy_p3retval(retval); destroy_seq_args(sarg); exit(-4); } /* If there are nonfatal errors, write the proper message * and skip to the end of the loop */ if (!pr_is_empty(&nonfatal_parse_err)) { if (format_output) { format_error(stdout, sarg->sequence_name, nonfatal_parse_err.data); } else { print_boulder_error(nonfatal_parse_err.data); } goto loop_wrap_up; } if (read_boulder_record_res.file_flag && sarg->sequence_name == NULL) { /* We will not have a base name for the files */ if (format_output) { format_error(stdout, NULL, "Need PRIMER_SEQUENCE_ID if PRIMER_FILE_FLAG is not 0"); } else { print_boulder_error("Need PRIMER_SEQUENCE_ID if PRIMER_FILE_FLAG is not 0"); } goto loop_wrap_up; } /* Pick the primers - the central function */ p3_set_gs_primer_file_flag(global_pa, read_boulder_record_res.file_flag); retval = choose_primers(global_pa, sarg); if (NULL == retval) exit(-2); /* Out of memory. */ /* This is old code to make it compatible with version 3 input. In future versions it can be deleted! If it was necessary to use a left_input, right_input, or internal_oligo_input primer that was unacceptable, then add warnings. */ if (global_pa->pick_anyway && (io_version == 3 || format_output)) { if (sarg->left_input) { add_must_use_warnings(&retval->warnings, "Left primer", &retval->fwd.expl); } if (sarg->right_input) { add_must_use_warnings(&retval->warnings, "Right primer", &retval->rev.expl); } if (sarg->internal_input) { add_must_use_warnings(&retval->warnings, "Hybridization probe", &retval->intl.expl); } } /* End of the old code for compartibility. */ if (pr_is_empty(&retval->glob_err) && pr_is_empty(&retval->per_sequence_err)) { /* We need to test for errors before we call p3_print_oligo_lists. This function only works on retval as returned when there were no errors. */ if (read_boulder_record_res.file_flag) { /* Create files with left, right, and internal oligos. */ p3_print_oligo_lists(retval, sarg, global_pa, &retval->per_sequence_err, sarg->sequence_name); } } if (format_output) { print_format_output(stdout, &io_version, global_pa, sarg, retval, pr_release, read_boulder_record_res.explain_flag); } else { /* Use boulder output */ print_boulder(/* & */io_version, global_pa, sarg, retval, read_boulder_record_res.explain_flag); } loop_wrap_up: /* Here the failed loops join in again */ if (NULL != retval) { /* Check for errors and print them */ if (NULL != retval->glob_err.data) { fprintf(stderr, "%s: %s\n", pr_program_name, retval->glob_err.data); destroy_p3retval(retval); destroy_seq_args(sarg); exit(-4); } } destroy_p3retval(retval); /* This works even if retval is NULL */ retval = NULL; destroy_seq_args(sarg); sarg = NULL; } /* while (1) (processing boulder io records) ... End of the primary working loop */ /* To avoid being distracted when looking for leaks: */ p3_destroy_global_settings(global_pa); global_pa = NULL; destroy_seq_args(sarg); destroy_pr_append_str_data(&nonfatal_parse_err); destroy_pr_append_str_data(&fatal_parse_err); destroy_dpal_thal_arg_holder(); /* If it could not read input complain and die */ if (0 == input_found) { print_usage(); exit(-3); } return 0; }