Example #1
0
static void rTokInto(struct pfCompile *pfc, char *baseDir, char *modName,
    boolean lookForPfh)
/* Tokenize module, and recursively any thing it goes into. */
{
char *pfPath = findSourcePath(baseDir, pfc->paraLibPath, modName, ".pf");
char *pfhPath = replaceSuffix(pfPath, ".pf", ".pfh");
char *oPath = replaceSuffix(pfPath, ".pf", ".o");
char *cPath = replaceSuffix(pfPath, ".pf", ".c");
char *fileName = NULL;
struct pfModule *module;
boolean isPfh = FALSE;
struct pfToken *tok;


/* Look too see if can use just module header.
 * We can if it exists and is newer than module. */
if (lookForPfh)
    {
    if (fileExists(pfhPath) && fileExists(cPath) && fileExists(oPath))
	{
	unsigned long pfTime = fileModTime(pfPath);
	unsigned long pfhTime = fileModTime(pfhPath);
	unsigned long cTime = fileModTime(cPath);
	unsigned long oTime = fileModTime(oPath);
	if (pfTime < pfhTime && pfhTime <= cTime && cTime <= oTime)
	    {
	    fileName = pfhPath;
	    isPfh = TRUE;
	    }
	}
    }
if (fileName == NULL)
    fileName = pfPath;

/* Tokenize file and add module to hash. */
module = tokenizeFile(pfc->tkz, fileName, modName);
module->isPfh = isPfh;
hashAdd(pfc->moduleHash, modName, module);

/* Look and see if there are any 'include' or 'import' to follow. */
for (tok = module->tokList; tok != NULL; tok = tok->next)
    {
    if (tok->type == pftInclude || tok->type == pftImport)
        {
	struct pfToken *modTok = tok->next;
	if (modTok->type != pftString)
	   expectingGot("module name in single quotes", modTok); 
	if (sameString(modTok->val.s, modName))
	    errAt(modTok, "A module can't include/import itself.");
	if (!hashLookup(pfc->moduleHash, modTok->val.s))
	    rTokInto(pfc, baseDir, modTok->val.s, TRUE);
	}
    }

/* Add module to list */
slAddHead(&pfc->moduleList, module);

/* Clean up and go home. */
freeMem(pfPath);
freeMem(pfhPath);
freeMem(oPath);
freeMem(cPath);
}
Example #2
0
File: main.c Project: bowhan/kent
void paraFlow(char *fileName, int pfArgc, char **pfArgv)
/* parse and dump. */
{
struct pfCompile *pfc;
struct pfParse *program, *module;
char baseDir[256], baseName[128], baseSuffix[64];
char defFile[PATH_LEN];
char *parseFile = "out.parse";
char *typeFile = "out.typed";
char *boundFile = "out.bound";
char *scopeFile = "out.scope";
char *foldedFile = "out.folded";
char *cFile = "out.c";
FILE *parseF = mustOpen(parseFile, "w");
FILE *typeF = mustOpen(typeFile, "w");
FILE *scopeF = mustOpen(scopeFile, "w");
FILE *boundF = mustOpen(boundFile, "w");
FILE *foldedF = mustOpen(foldedFile, "w");

if (endPhase < 0)
    return;
verbose(2, "Phase 0 - initialization\n");
pfc = pfCompileNew();
getPaths(pfc);
splitPath(fileName, baseDir, baseName, baseSuffix);
pfc->baseDir = cloneString(baseDir);
safef(defFile, sizeof(defFile), "%s%s.pfh", baseDir, baseName);

if (endPhase < 1)
   return ;
verbose(2, "Phase 1 - tokenizing\n");
pfTokenizeInto(pfc, baseDir, baseName);

if (endPhase < 2)
    return;
verbose(2, "Phase 2 - parsing\n");
program = pfParseInto(pfc);
dumpParseTree(pfc, program, parseF);
carefulClose(&parseF);

if (endPhase < 3)
    return;
verbose(2, "Phase 3 - binding names\n");
pfBindVars(pfc, program);
dumpParseTree(pfc, program, boundF);
carefulClose(&boundF);

if (endPhase < 4)
    return;
verbose(2, "Phase 4 - type checking\n");
pfTypeCheck(pfc, &program);
dumpParseTree(pfc, program, typeF);
carefulClose(&typeF);

if (endPhase < 5)
    return;
verbose(2, "Phase 5 - polymorphic, para, and flow checks\n");
checkPolymorphic(pfc, pfc->scopeRefList);
checkParaFlow(pfc, program);
printScopeInfo(scopeF, 0, program);
carefulClose(&scopeF);

if (endPhase < 6)
    return;
verbose(2, "Phase 6 - constant folding\n");
pfConstFold(pfc, program);
dumpParseTree(pfc, program, foldedF);

if (optionExists("asm"))
    {
    struct dyString *gccFiles;

    if (endPhase < 7)
	return;
    verbose(2, "Phase 7 - nothing\n");

    if (endPhase < 8)
	return;
    verbose(2, "Phase 8 - Code generation\n");

    pfc->backEnd = backEndFind("mac-pentium");
    gccFiles = asmCoder(pfc, program, baseDir, baseName);

    if (endPhase < 9)
        return;
    verbose(2, "Phase 9 - Assembling pentium code\n");
        {
	char *libName = hashMustFindVal(pfc->cfgHash,"runAsmLib");
	struct dyString *dy = dyStringNew(0);
	int err;
	dyStringPrintf(dy, "gcc ");
	dyStringPrintf(dy, "-I %s ", pfc->cIncludeDir);
	dyStringPrintf(dy, "-o %s%s ", baseDir, baseName);
	dyStringAppend(dy, gccFiles->string);
	dyStringPrintf(dy, "%s ", libName);
	dyStringPrintf(dy, " %s ", pfc->runtimeLib);
	dyStringPrintf(dy, "%s ", pfc->jkwebLib);
	verbose(2, "%s\n", dy->string);
	err = system(dy->string);
	if (err != 0)
	    errAbort("Couldn't assemble: %s", dy->string);
	dyStringFree(&dy);
	}
    dyStringFree(&gccFiles);
    }
else
    {
    verbose(2, "Phase 7 - nothing\n");
    if (endPhase < 8)
	return;
    verbose(2, "Phase 8 - C code generation\n");
    pfCodeC(pfc, program, baseDir, cFile);
    verbose(2, "%d modules, %d tokens, %d parseNodes\n",
	pfc->moduleHash->elCount, pfc->tkz->tokenCount, pfParseCount(program));

    if (endPhase < 9)
	return;
    verbose(2, "Phase 9 - compiling C code\n");
    /* Now run gcc on it. */
	{
	struct dyString *dy = dyStringNew(0);
	int err;
	for (module = program->children; module != NULL; module = module->next)
	    {
	    if (module->name[0] != '<' && module->type != pptModuleRef)
		{
		struct pfModule *mod = hashMustFindVal(pfc->moduleHash, module->name);
		char *cName = replaceSuffix(mod->fileName, ".pf", ".c");
		char *oName = replaceSuffix(mod->fileName, ".pf", ".o");
		dyStringClear(dy);
		dyStringAppend(dy, "gcc ");
		dyStringAppend(dy, "-O ");
		dyStringPrintf(dy, "-I %s ", pfc->cIncludeDir);
		dyStringAppend(dy, "-c ");
		dyStringAppend(dy, "-o ");
		dyStringPrintf(dy, "%s ", oName);
		dyStringPrintf(dy, "%s ", cName);
		verbose(2, "%s\n", dy->string);
		err = system(dy->string);
		if (err != 0)
		    errAbort("Couldn't compile %s.c", module->name);
		freeMem(oName);
		freeMem(cName);
		}
	    }
	dyStringClear(dy);
	dyStringAppend(dy, "gcc ");
	dyStringAppend(dy, "-O ");
	dyStringPrintf(dy, "-I %s ", pfc->cIncludeDir);
	dyStringPrintf(dy, "-o %s%s ", baseDir, baseName);
	dyStringPrintf(dy, "%s ", cFile);
	for (module = program->children; module != NULL; module = module->next)
	    {
	    if (module->name[0] != '<')
		{
		struct pfModule *mod = hashMustFindVal(pfc->moduleHash, module->name);
		char *suffix = (module->type == pptModuleRef ? ".pfh" : ".pf");
		char *oName = replaceSuffix(mod->fileName, suffix, ".o");
		dyStringPrintf(dy, "%s ", oName);
		freeMem(oName);
		}
	    }
	dyStringPrintf(dy, " %s ", pfc->runtimeLib);
	dyStringPrintf(dy, "%s ", pfc->jkwebLib);
	dyStringAppend(dy, "-lpthread -lm");
	verbose(2, "%s\n", dy->string);
	err = system(dy->string);
	if (err != 0)
	    errnoAbort("problem compiling:\n", dy->string);
	dyStringFree(&dy);
	}

    }
if (endPhase < 10)
    return;

verbose(2, "Phase 10 - execution\n");
/* Now go run program itself. */
    {
    struct dyString *dy = dyStringNew(0);
    int err;
    int i;
    if (baseDir[0] == 0)
	dyStringPrintf(dy, "./%s", baseName);
    else
	dyStringPrintf(dy, "%s%s", baseDir, baseName);
    for (i=0; i<pfArgc; ++i)
	{
	dyStringAppendC(dy, ' ');
	dyStringAppend(dy, pfArgv[i]);
	}
    err = system(dy->string);
    if (err != 0)
	errAbort("problem running %s", baseName);
    dyStringFree(&dy);
    }
}
Example #3
0
int main(int argc, char **argv) {

    int         optndx;

    static struct option myopts[] = {
        /* {char *name, int has_arg, int *flag, int val} */
        {"blocksize", required_argument, 0, 'b'},
        {"help", no_argument, 0, 'h'},
        {"interval", required_argument, 0, 'i'},
        {"nbins", required_argument, 0, 'n'},
        {"bootreps", required_argument, 0, 'r'},
        {"threads", required_argument, 0, 't'},
        {"verbose", no_argument, 0, 'v'},
        {"window", required_argument, 0, 'w'},
        {NULL, 0, NULL, 0}
    };

    double      windowsize_cm = 0.3;
    double      confidence = 0.95;
    int         nthreads = 0;   /* number of threads to launch */
    long        sampling_interval = 1;
    long        bootreps = 0;
    long        blocksize = 300;
    int         nbins = 25;
    int         verbose = 0;
    int         ploidy = 1;     /* default is haploid. */
    const int   folded = true;
    unsigned    nGtype, twoNsmp;

    FILE       *ifp = NULL;
    time_t      currtime = time(NULL);
    gsl_rng    *rng;
    char       *ifname = NULL;
    int         i, tndx;
    int         chromosome = -99;
    long        nSNPs = 0;
    Tabulation **tab;
    Spectab   **spectab;
    Boot      **boot = NULL;
    BootConf   *bc = NULL;
    char        bootfilename[FILENAMESIZE] = { '\0' };
    char        simcmd[1000] = { '\0' };
    unsigned    jobid;
    {
        char s[200];
        snprintf(s, sizeof(s), "%u %s", getpid(), ctime(&currtime));
        jobid = hash(s);
    }

    printf("#################################\n");
    printf("# eld: estimate LD and spectrum #\n");
    printf("#################################\n");

    putchar('\n');
#ifdef __TIMESTAMP__
    printf("# Program was compiled: %s\n", __TIMESTAMP__);
#else
    printf("# Program was compiled: %s, %s\n", __TIME__, __DATE__);
#endif
    printf("# Program was run     : %s\n", ctime(&currtime));

    printf("# cmd:");
    for(i = 0; i < argc; ++i)
        printf(" %s", argv[i]);
    putchar('\n');

    /* import definitions from initialization file */
    Ini        *ini = Ini_new(INIFILE);

    if(ini) {
        Ini_setLong(ini, "blocksize", &blocksize, !MANDATORY);
        Ini_setLong(ini, "samplingInterval", &sampling_interval, !MANDATORY);
        Ini_setInt(ini, "nbins", &nbins, !MANDATORY);
        Ini_setDbl(ini, "confidence", &confidence, !MANDATORY);
        Ini_setInt(ini, "nthreads", &nthreads, !MANDATORY);
        Ini_setDbl(ini, "windowCm", &windowsize_cm, !MANDATORY);
        Ini_free(ini);
        ini = NULL;
    }

    /* command line arguments */
    for(;;) {
        i = getopt_long(argc, argv, "b:f:hi:n:R:r:t:vw:W:", myopts, &optndx);
        if(i == -1)
            break;
        switch (i) {
        case ':':
        case '?':
            usage();
            break;
        case 'b':
            blocksize = strtod(optarg, NULL);
			if(blocksize <= 0) {
				fprintf(stderr,
						"%s:%d: bad argument to -b or --blocksize: \"%s\"\n",
						__FILE__,__LINE__,optarg);
				usage();
			}
            break;
        case 'h':
            usage();
            break;
        case 'i':
            sampling_interval = strtol(optarg, NULL, 10);
            break;
        case 'n':
            nbins = strtod(optarg, NULL);
            break;
        case 'r':
            bootreps = strtol(optarg, NULL, 10);
            break;
        case 't':
            nthreads = strtol(optarg, NULL, 10);
            break;
        case 'v':
            verbose = 1;
            break;
        case 'w':
            windowsize_cm = strtod(optarg, NULL);
            break;
        default:
            usage();
        }
    }

    /* remaining option gives file name */
    switch (argc - optind) {
    case 0:
        fprintf(stderr, "Command line must specify input file\n");
        usage();
        break;
    case 1:
        ifname = strdup(argv[optind]);
        ifp = fopen(ifname, "r");
        if(ifp == NULL)
            eprintf("ERR@%s:%d: couldn't open file \"%s\"\n",
                    __FILE__, __LINE__, ifname);
        break;
    default:
        fprintf(stderr, "Only one input file is allowed\n");
        usage();
    }
    myassert(ifname != NULL);
    myassert(ifp != NULL);

    if(bootreps > 0) {
        // Generate bootstrap output file name from input file name.
        // Strip suffix; add -jobid.boot
        char *basename = strrchr(ifname, '/'); // linux only!!!
        if(basename == NULL)
            basename = ifname;
        else
            basename += 1;    // skip '/' character
        snprintf(bootfilename, sizeof(bootfilename), "%s", basename);
        char suffix[30];
        snprintf(suffix, sizeof(suffix), "-%x.boot", jobid);
        replaceSuffix(bootfilename, sizeof(bootfilename), suffix,
                      strlen(suffix));
    }

    /* Read assignments from header of gtp file */
    Assignment *asmt = Gtp_readHdr(ifp);

    Assignment_setInt(asmt, "chromosome", &chromosome, !MANDATORY);
    Assignment_setString(asmt, "sim cmd", simcmd, sizeof(simcmd), !MANDATORY);
    Assignment_setInt(asmt, "ploidy", &ploidy, !MANDATORY);
    Assignment_free(asmt);
    asmt = NULL;

    // 1st pass through file: count SNPs and figure out which will be
    // read by each thread.
    fprintf(stderr, "Indexing file \"%s\"...\n", ifname);
    FileIndex  *fndx = FileIndex_readFile(ifp);

    // Number of SNPs and number genotypes per SNP
    nSNPs = FileIndex_nSNPs(fndx);
    nGtype = FileIndex_nGtype(fndx);
    if(nSNPs == 0 || nGtype == 0) {
        FileIndex_printSummary(fndx, stderr);
        eprintf("ERR@%s:%d: Input file has no data\n", __FILE__, __LINE__);
    }
    assert(ploidy == FileIndex_ploidy(fndx));
    twoNsmp = nGtype * ploidy; // haploid sample size

    /* Number of threads */
    if(nthreads == 0)
        nthreads = lround(getNumCores());

    double      min_cm = FileIndex_getMapPos(fndx, 0);
    double      max_cm = FileIndex_getMapPos(fndx,
                                             FileIndex_nSNPs(fndx) - 1);
    double      maxRange = max_cm - min_cm;

    /* If necessary, reduce window to size of chromosome */
    if(windowsize_cm > maxRange) {
        windowsize_cm = maxRange;

        printf("# Warning: Reducing windowsize to sequence length\n");
        printf("#   windowsize_cm: %lg\n", windowsize_cm);
    }

    ThreadBounds *tb = ThreadBounds_new(nthreads,
                                        windowsize_cm,
                                        fndx);

    FileIndex_free(fndx);
    fndx = NULL;
    fclose(ifp);

    if(verbose)
        ThreadBounds_print(tb, nthreads, stdout);

    rng = gsl_rng_alloc(gsl_rng_taus);
    gsl_rng_set(rng, (unsigned) currtime);

    // allocate arrays
    DblArray *sigdsq = DblArray_new((unsigned long) nbins);
    checkmem(sigdsq, __FILE__, __LINE__);

    DblArray *rsq = DblArray_new((unsigned long) nbins);
    checkmem(rsq, __FILE__, __LINE__);


    DblArray *separation = DblArray_new((unsigned long) nbins);
    checkmem(separation, __FILE__, __LINE__);

    ULIntArray *nobs = ULIntArray_new((unsigned long) nbins);
    checkmem(nobs, __FILE__, __LINE__);
    
    unsigned spdim = specdim(twoNsmp, folded); 
    ULIntArray *spectrum = ULIntArray_new((unsigned long) spdim);
    checkmem(spectrum, __FILE__, __LINE__);

    tab = (Tabulation **) malloc(nthreads * sizeof(tab[0]));
    checkmem(tab, __FILE__, __LINE__);

    spectab = (Spectab **) malloc(nthreads * sizeof(spectab[0]));
    checkmem(spectab, __FILE__, __LINE__);

    for(i = 0; i < nthreads; ++i) {
        tab[i] = Tabulation_new(windowsize_cm, nbins);
        spectab[i] = Spectab_new(twoNsmp, folded);
    }

    // Initially, all boot pointers are set to NULL. If they remain
    // NULL, then each thread will know not do a
    // bootstrap. Bootstrap is done only if boot[i] is not NULL.
    boot = malloc(nthreads * sizeof(*boot));
    checkmem(boot, __FILE__, __LINE__);
    memset(boot, 0, nthreads * sizeof(*boot));

    myassert(boot != NULL);

    for(i = 0; i < nthreads; ++i)
        myassert(boot[i] == NULL);

    if(bootreps > 0) {

		printf("%s:%d: blocksize=%ld\n",
			   __FILE__,__LINE__,blocksize);fflush(stdout);
        boot[0] = Boot_new(nSNPs, bootreps, twoNsmp, folded, blocksize,
                           windowsize_cm,
                           nbins, rng);
        myassert(boot[0] != NULL);

        for(i = 1; i < nthreads; ++i)
            boot[i] = Boot_dup(boot[0]);
    }

    // targ[i] = ptr to i'th ThreadArg object.
    ThreadArg  *targ = malloc(nthreads * sizeof(targ[0]));

    checkmem(targ, __FILE__, __LINE__);
    for(tndx = 0; tndx < nthreads; ++tndx) {
        targ[tndx].thisThread = tndx;
        targ[tndx].ifname = ifname;
        targ[tndx].ploidy = ploidy;
        targ[tndx].nGtype = 0;
        targ[tndx].sampling_interval = sampling_interval;
        targ[tndx].nbins = nbins;
        targ[tndx].window_cm = windowsize_cm;
        targ[tndx].tab = tab[tndx];
        targ[tndx].spectab = spectab[tndx];
        targ[tndx].boot = boot[tndx];
        targ[tndx].tb = &tb[tndx];
        targ[tndx].overflow = 0;
    }

    // echo parameters
    if(strlen(simcmd) > 0)
        printf("# %s = %s\n", "sim cmd", simcmd);
    if(chromosome >= 0)
        printf("# %-35s = %d\n", "chromosome", chromosome);
    printf("# %-35s = %x\n", "JobId", jobid);
    printf("# %-35s = %lg\n", "Window size (cM)", windowsize_cm);
    printf("# %-35s = %s\n", "Input file", ifname);
    printf("# %-35s = %ld\n", "nSNPs", nSNPs);
    printf("# %-35s = %d\n", "nbins", nbins);
    printf("# %-35s = %ld\n", "sampling interval", sampling_interval);
    printf("# %-35s = %d\n", "nthreads", nthreads);
    printf("# %-35s = %ld\n", "bootstrap replicates", bootreps);
    if(bootfilename[0])
        printf("# %-35s = %s\n", "bootstrap output file", bootfilename);
    else
        printf("# %-35s = %s\n", "bootstrap output file", "none");
    printf("# %-35s = %u\n", "Number of genotypes", nGtype);
    printf("# %-35s = %d\n", "Ploidy", ploidy);
    printf("# %-35s = %d\n", "Haploid sample size", nGtype * ploidy);

    fflush(stdout);

    pthread_t  *thread;

    thread = malloc(nthreads * sizeof(pthread_t));
    checkmem(thread, __FILE__, __LINE__);

    fflush(stdout);
    fprintf(stderr, "Launching %d threads...\n", nthreads);
    for(tndx = 0; tndx < nthreads; ++tndx) {
        i = pthread_create(&thread[tndx], NULL, threadfun, &targ[tndx]);
        if(i)
            eprintf("ERR@%s:%d: pthread_create returned %d\n",
                    __FILE__, __LINE__, i);
    }

    fflush(stdout);
    /* wait for threads to finish */
    for(tndx = 0; tndx < nthreads; ++tndx) {
        void       *status;

        i = pthread_join(thread[tndx], &status);
        if(i)
            eprintf("ERR@%s:%d: pthread_join returned %d\n",
                    __FILE__, __LINE__, i);
        fprintf(stderr, " %2d threads have finished\n", tndx + 1);
    }

    fprintf(stderr, "Back from threads\n");

    assert(nGtype == targ[nthreads - 1].nGtype);

    /* aggregate tabulations from threads */
    for(tndx = 1; tndx < nthreads; ++tndx) {
        Tabulation_plus_equals(tab[0], tab[tndx]);
        Spectab_plus_equals(spectab[0], spectab[tndx]);
    }

    if(Tabulation_report(tab[0], separation, nobs, sigdsq, rsq)) {
        fprintf(stderr, "sigdsq data are invalid because"
                " Tabulation overflowed.\n");
        fprintf(stderr, "   Each bin can hold %lu comparisons.\n", ULONG_MAX);
        fprintf(stderr, "   Use fewer SNPs or increase --nbins.\n");
    }else{
        if(bootreps > 0) {
            /* aggregate boot structures from threads */
            for(tndx = 1; tndx < nthreads; ++tndx)
                Boot_plus_equals(boot[0], boot[tndx]);
            bc = BootConf_new(boot[0], confidence);
            myassert(bc);

            if(bootfilename[0]) {
                FILE       *bootfile = fopen(bootfilename, "w");
                if(bootfile==NULL) {
                    fprintf(stderr,"%s:%s:%d: Can't open file %s for output\n",
                            __FILE__, __func__, __LINE__, bootfilename);
                    exit(EXIT_FAILURE);
                }

                Boot_dump(boot[0], bootfile);
                fclose(bootfile);
            }
        }

        putchar('\n');
        printf("# Estimates of sigdsq\n");
        printf("#%12s: mean centimorgans separating pairs of SNPs\n", "cM");
        printf("#%12s: number of observations\n", "nobs");
        if(bootreps > 0)
            BootConf_printHdr(bc, stdout);
        printf("#%10s %11s %10s", "cM", "sigdsq", "nobs");
        if(bootreps > 0)
            printf(" %10s %10s", "loLD", "hiLD");
        printf(" %11s", "rsq");
        putchar('\n');
        for(i = 0; i < nbins; ++i) {
            // "separation" is is distance in cm.
            printf("%11.8lf %11.8lf %10lu",
                   DblArray_get(separation, i),
                   DblArray_get(sigdsq,i),
                   ULIntArray_get(nobs, i));
            if(bootreps > 0)
                printf(" %10.8lf %10.8lf",
                       BootConf_lowBound(bc, i), BootConf_highBound(bc, i));
            printf(" %11.8lf", DblArray_get(rsq,i));
            putchar('\n');
        }

        long unsigned nSpec = Spectab_report(spectab[0], spectrum);
        assert(nSpec == nSNPs);
        
        putchar('\n');
        printf("# %s site frequency spectrum",
               (folded ? "Folded" : "Unfolded"));
        if(bootreps > 0)
            printf(" with %0.1lf%% confidence bounds", 100*confidence);
        putchar('\n');
        printf("# %lu segregating sites\n", nSpec);
        printf("#%10s %11s", "count", "spectrum");
        if(bootreps > 0)
            printf(" %10s %10s", "loSpec", "hiSpec");
        putchar('\n');
        for(i=0; i < spdim; ++i)  {
            printf("%11d %11lu", i+1, ULIntArray_get(spectrum,i));
            if(bootreps > 0)
                printf(" %10.2lf %10.2lf",
                       BootConf_loSpecBound(bc, i),
                       BootConf_hiSpecBound(bc, i));
            putchar('\n');
        }
    }

    if(bootreps > 0) {
        for(i = 0; i < nthreads; ++i)
            Boot_free(boot[i]);
    }
    if(bc)
        BootConf_free(bc);
    free(boot);
    DblArray_free(sigdsq);
    DblArray_free(rsq);
    DblArray_free(separation);
    ULIntArray_free(nobs);
    ULIntArray_free(spectrum);
    for(i = 0; i < nthreads; ++i) {
        Tabulation_free(tab[i]);
    }
    free(thread);
    free(tab);
    free(targ);
    ThreadBounds_free(tb);
    free(ifname);
    gsl_rng_free(rng);

#ifdef __APPLE__
    putchar(' ');               /* prevents hang on exit under osx */
#endif
    return 0;
}
    bool BrazilianStemmer::step1()
    {
        if (CT.empty())
            return false;
        
        // suffix length = 7
        if (checkSuffix(CT, L"uciones") && checkSuffix(R2, L"uciones"))
        {
            CT = replaceSuffix(CT, L"uciones", L"u");
            return true;
        }

        // suffix length = 6
        if (CT.length() >= 6)
        {
            if (checkSuffix(CT, L"imentos") && checkSuffix(R2, L"imentos"))
            {
                CT = removeSuffix(CT, L"imentos");
                return true;
            }
            if (checkSuffix(CT, L"amentos") && checkSuffix(R2, L"amentos"))
            {
                CT = removeSuffix(CT, L"amentos");
                return true;
            }
            if (checkSuffix(CT, L"adores") && checkSuffix(R2, L"adores"))
            {
                CT = removeSuffix(CT, L"adores");
                return true;
            }
            if (checkSuffix(CT, L"adoras") && checkSuffix(R2, L"adoras"))
            {
                CT = removeSuffix(CT, L"adoras");
                return true;
            }
            if (checkSuffix(CT, L"logias") && checkSuffix(R2, L"logias")) 
            {
                replaceSuffix(CT, L"logias", L"log");
                return true;
            }
            if (checkSuffix(CT, L"encias") && checkSuffix(R2, L"encias"))
            {
                CT = replaceSuffix(CT, L"encias", L"ente");
                return true;
            }
            if (checkSuffix(CT, L"amente") && checkSuffix(R1, L"amente"))
            {
                CT = removeSuffix(CT, L"amente");
                return true;
            }
            if (checkSuffix(CT, L"idades") && checkSuffix(R2, L"idades"))
            {
                CT = removeSuffix(CT, L"idades");
                return true;
            }
        }

        // suffix length = 5
        if (CT.length() >= 5)
        {
            if (checkSuffix(CT, L"acoes") && checkSuffix(R2, L"acoes"))
            {
                CT = removeSuffix(CT, L"acoes");
                return true;
            }
            if (checkSuffix(CT, L"imento") && checkSuffix(R2, L"imento"))
            {
                CT = removeSuffix(CT, L"imento");
                return true;
            }
            if (checkSuffix(CT, L"amento") && checkSuffix(R2, L"amento"))
            {
                CT = removeSuffix(CT, L"amento");
                return true;
            }
            if (checkSuffix(CT, L"adora") && checkSuffix(R2, L"adora"))
            {
                CT = removeSuffix(CT, L"adora");
                return true;
            }
            if (checkSuffix(CT, L"ismos") && checkSuffix(R2, L"ismos"))
            {
                CT = removeSuffix(CT, L"ismos");
                return true;
            }
            if (checkSuffix(CT, L"istas") && checkSuffix(R2, L"istas"))
            {
                CT = removeSuffix(CT, L"istas");
                return true;
            }
            if (checkSuffix(CT, L"logia") && checkSuffix(R2, L"logia"))
            {
                CT = replaceSuffix(CT, L"logia", L"log");
                return true;
            }
            if (checkSuffix(CT, L"ucion") && checkSuffix(R2, L"ucion"))
            {
                CT = replaceSuffix(CT, L"ucion", L"u");
                return true;
            }
            if (checkSuffix(CT, L"encia") && checkSuffix(R2, L"encia"))
            {
                CT = replaceSuffix(CT, L"encia", L"ente");
                return true;
            }
            if (checkSuffix(CT, L"mente") && checkSuffix(R2, L"mente"))
            {
                CT = removeSuffix(CT, L"mente");
                return true;
            }
            if (checkSuffix(CT, L"idade") && checkSuffix(R2, L"idade"))
            {
                CT = removeSuffix(CT, L"idade");
                return true;
            }
        }

        // suffix length = 4
        if (CT.length() >= 4)
        {
            if (checkSuffix(CT, L"acao") && checkSuffix(R2, L"acao"))
            {
                CT = removeSuffix(CT, L"acao");
                return true;
            }
            if (checkSuffix(CT, L"ezas") && checkSuffix(R2, L"ezas"))
            {
                CT = removeSuffix(CT, L"ezas");
                return true;
            }
            if (checkSuffix(CT, L"icos") && checkSuffix(R2, L"icos"))
            {
                CT = removeSuffix(CT, L"icos");
                return true;
            }
            if (checkSuffix(CT, L"icas") && checkSuffix(R2, L"icas"))
            {
                CT = removeSuffix(CT, L"icas");
                return true;
            }
            if (checkSuffix(CT, L"ismo") && checkSuffix(R2, L"ismo"))
            {
                CT = removeSuffix(CT, L"ismo");
                return true;
            }
            if (checkSuffix(CT, L"avel") && checkSuffix(R2, L"avel"))
            {
                CT = removeSuffix(CT, L"avel");
                return true;
            }
            if (checkSuffix(CT, L"ivel") && checkSuffix(R2, L"ivel"))
            {
                CT = removeSuffix(CT, L"ivel");
                return true;
            }
            if (checkSuffix(CT, L"ista") && checkSuffix(R2, L"ista"))
            {
                CT = removeSuffix(CT, L"ista");
                return true;
            }
            if (checkSuffix(CT, L"osos") && checkSuffix(R2, L"osos"))
            {
                CT = removeSuffix(CT, L"osos");
                return true;
            }
            if (checkSuffix(CT, L"osas") && checkSuffix(R2, L"osas"))
            {
                CT = removeSuffix(CT, L"osas");
                return true;
            }
            if (checkSuffix(CT, L"ador") && checkSuffix(R2, L"ador"))
            {
                CT = removeSuffix(CT, L"ador");
                return true;
            }
            if (checkSuffix(CT, L"ivas") && checkSuffix(R2, L"ivas"))
            {
                CT = removeSuffix(CT, L"ivas");
                return true;
            }
            if (checkSuffix(CT, L"ivos") && checkSuffix(R2, L"ivos"))
            {
                CT = removeSuffix(CT, L"ivos");
                return true;
            }
            if (checkSuffix(CT, L"iras") && checkSuffix(RV, L"iras") && suffixPreceded(CT, L"iras", L"e"))
            {
                CT = replaceSuffix(CT, L"iras", L"ir");
                return true;
            }
        }

        // suffix length = 3
        if (CT.length() >= 3)
        {
            if (checkSuffix(CT, L"eza") && checkSuffix(R2, L"eza"))
            {
                CT = removeSuffix(CT, L"eza");
                return true;
            }
            if (checkSuffix(CT, L"ico") && checkSuffix(R2, L"ico"))
            {
                CT = removeSuffix(CT, L"ico");
                return true;
            }
            if (checkSuffix(CT, L"ica") && checkSuffix(R2, L"ica"))
            {
                CT = removeSuffix(CT, L"ica");
                return true;
            }
            if (checkSuffix(CT, L"oso") && checkSuffix(R2, L"oso"))
            {
                CT = removeSuffix(CT, L"oso");
                return true;
            }
            if (checkSuffix(CT, L"osa") && checkSuffix(R2, L"osa"))
            {
                CT = removeSuffix(CT, L"osa");
                return true;
            }
            if (checkSuffix(CT, L"iva") && checkSuffix(R2, L"iva"))
            {
                CT = removeSuffix(CT, L"iva");
                return true;
            }
            if (checkSuffix(CT, L"ivo") && checkSuffix(R2, L"ivo"))
            {
                CT = removeSuffix(CT, L"ivo");
                return true;
            }
            if (checkSuffix(CT, L"ira") && checkSuffix(RV, L"ira") && suffixPreceded(CT, L"ira", L"e"))
            {
                CT = replaceSuffix(CT, L"ira", L"ir");
                return true;
            }
        }

        // no ending was removed by step1
        return false;
    }