예제 #1
0
void config_free(config_t *config)
{
    config->flag = 0;
    if(config->joina != NULL){
        free(config->joina);
    }
    if(config->joinr != NULL){
        free(config->joinr);
    }
    pl_free(&config->message);
    pl_free(&config->maccmd);
}
예제 #2
0
int play2048_noply(Game g) {
    int size;
    while(!is2048(g->board)) {
        //print_board(g->board);
        Move* moves = effectual_moves(g->board, &size);
        // Test end conditions
        if (moves == NULL)
            break;
        if (size == 0) {
            free(moves);
            break;
        }
        int i;
        Move bestMove = moves[0];
        double bestHeur = 0;
        for (i = 0; i < size; i++) {
            Game test = test_move_norand(g, moves[i]);
            PointList pl = open_spaces(test->board);
            if (pl->N == 0) {//This should never happen
                game_free(test);
                pl_free(pl);
                continue;
            }
            listNode *node = pl->points.head;
            double maxheur = 0;
            while (node != NULL) {
                Board cpy = board_cpy(test->board);
                Board cpy2 = board_cpy(test->board);
                Point p = (Point)node->data;
                place(cpy,p->r, p->c, 2);
                double twoheur = (*(test->h))(cpy);
                place(cpy2, p->r, p->c, 4);
                double fourheur = (*(test->h))(cpy2);
                double heur = twoheur > fourheur ? twoheur : fourheur;
                maxheur = maxheur > heur ? maxheur : heur;
                node = node->next;
                free_board(cpy);
                free_board(cpy2);
            }
            if (maxheur > bestHeur) {
                bestHeur = maxheur;
                bestMove = moves[i];
            }
            game_free(test);
            pl_free(pl);
        }
        make_move(g, bestMove);
        free(moves);
    }
    //printf("oneboard:\n");
    //print_board(g->board);
    return g->score;
}
예제 #3
0
static void pl_filter_test(void) {
	printsln((Any)__func__);
	List l, ac, ex;

	l = sl_of_string("Kürbis, Brombeere, Heidelbeere, Himbeere, Apfel");
	ac = pl_filter(l, f_ends_with, "beere");
	ex = sl_of_string("Brombeere, Heidelbeere, Himbeere");
	sl_check_expect(ac, ex);
	pl_free(l);
	l_free(ac);
	pl_free(ex);
}
예제 #4
0
void test_random(int *score, int *maxtile) {
    printf("Playing random...\n");
    Game g = init_game(squaresum_heuristic);
    PointList pl = open_spaces(g->board);
    while (!pl_empty(pl)) {
        pl_free(pl);
        make_move(g, (Move)randint(4));
        pl = open_spaces(g->board);
    }
    pl_free(pl);
    *score = g->score;
    *maxtile = max_tile(g->board);
    game_free(g);
}
예제 #5
0
void plot_index_free(plot_args_t* plotargs, void* baton) {
	plotindex_t* args = (plotindex_t*)baton;
	int i;
	for (i=0; i<pl_size(args->indexes); i++) {
		index_t* index = pl_get(args->indexes, i);
		index_free(index);
	}
	pl_free(args->indexes);
	for (i=0; i<pl_size(args->qidxes); i++) {
		qidxfile* qidx = pl_get(args->qidxes, i);
		qidxfile_close(qidx);
	}
	pl_free(args->qidxes);
	free(args);
}
예제 #6
0
static void pl_forall_test(void) {
	printsln((Any)__func__);
	List l = sl_of_string("1, 2, 3, 4, 5, 6");
	check_expect_b(pl_forall(l, pl_element_eq, "3"), false);
	check_expect_b(pl_forall(l, pl_element_ne, "9"), true);
	pl_free(l);
}
예제 #7
0
파일: pcache.c 프로젝트: ctelfer/catlib
void pc_free(void *item)
{
	struct pcache *pc;
	struct pc_pool *pcp;
	struct pool *pp;

	abort_unless(item);

	item = (char *)item - sizeof(cat_pcpad_t);
	pcp = *(struct pc_pool **)item;
	pp = &pcp->pool;
	if ( pp->fill == 0 ) {
		l_rem(&pcp->entry);
		l_ins(pcp->cache->avail.prev, &pcp->entry);
	}

	pl_free(pp, item);

	if ( pp->fill == pp->max ) {
		pc = pcp->cache;

		l_rem(&pcp->entry);
		if ( pc->mm && (pc->hiwat > 0) && (pc->npools > pc->hiwat) ) {
			mem_free(pc->mm, pcp);
			pc->npools -= 1;
		} else {
			l_ins(&pc->full, &pcp->entry);
		}
	}
}
예제 #8
0
static void pl_foldl_test(void) {
	printsln((Any)__func__);
	List l;
	Any s;
	
	l = sl_of_string("a, b, c");	
	s = pl_foldl(l, fold_concat_free, s_copy("init"));
	check_expect_s(s, "initabc");
	s_free(s);
	pl_free(l);

	l = sl_of_string("");	
	s = pl_foldl(l, fold_concat_free, s_copy("init"));
	check_expect_s(s, "init");
	s_free(s);
	pl_free(l);
}
예제 #9
0
static void pl_foldr_test(void) {
	printsln((Any)__func__);
	
	List l;
	Any s;
	
	l = sl_of_string("a, b, c");	
	s = pl_foldr(l, pl_concat_r, s_copy("X"));
	check_expect_s(s, "abcX");
	s_free(s);
	pl_free(l);

	l = sl_of_string("");	
	s = pl_foldr(l, pl_concat_r, s_copy("X"));
	check_expect_s(s, "X");
	s_free(s);
	pl_free(l);
}
예제 #10
0
파일: kb.c 프로젝트: 4auka/cmusphinx
/* RAH 4.15.01 Lots of memory is allocated, but never freed, this function will clean up.
 * First pass will get the low hanging fruit.*/
void
kb_free(kb_t * kb)
{
    if (kb->srch) {
        srch_uninit(kb->srch);
    /** Add search free code */
    }

    if (kb->stat) {
        stat_free((void *) kb->stat);
    }

    if (kb->ascr)
        ascr_free((void *) kb->ascr);

    if (kb->fastgmm)
        fast_gmm_free((void *) kb->fastgmm);

    if (kb->beam)
        beam_free((void *) kb->beam);


    if (kb->pl)
        pl_free((void *) kb->pl);

    if (kb->kbcore != NULL)
        kbcore_free(kb->kbcore);

    /* This is awkward, currently, there are two routines to control MLLRs and I don't have time 
       to unify them yet. TBD */
    if (kb->adapt_am->regA && kb->adapt_am->regB && kb->adapt_am->regH)
        mllr_free_regmat(kb->adapt_am->regA, kb->adapt_am->regB, kb->adapt_am->regH);
    if (kb->adapt_am)
        adapt_am_free(kb->adapt_am);

    if (kb->feat) {
        ckd_free((void *) kb->feat[0][0]);
        ckd_free_2d((void **) kb->feat);
    }


    if (kb->uttid) {
        ckd_free(kb->uttid);
    }

    if (kb->uttfile) {
        ckd_free(kb->uttfile);
    }


#if 0                           /* valgrind reports this one. */
    if (kb->matchsegfp)
        fclose(kb->matchsegfp);
    if (kb->matchfp)
        fclose(kb->matchfp);
#endif
}
예제 #11
0
static void pl_index_from_test(void) {
	printsln((Any)__func__);
	List a = sl_of_string("10, 20, 30, 40, 50");
	check_expect_i(pl_index_from(a, "20", 0), 1);
	check_expect_i(pl_index_from(a, "20", 1), 1);
	check_expect_i(pl_index_from(a, "20", 2), -1);
	check_expect_i(pl_index_from(a, "30", -1), 2);
	check_expect_i(pl_index_from(a, "60", 0), -1);
	pl_free(a);
}
예제 #12
0
void place_rand(Board b) {
    PointList pl = open_spaces(b);
    Point p = pl_rand(pl);
    if (p == NULL) {
        fprintf(stderr, "Number not placed, board is full.\n");
        return;
    }
    place(b, p->r, p->c, two_or_four());
    pl_free(pl);
}
예제 #13
0
void multiindex_close(multiindex_t* mi) {
	if (!mi)
		return;
	if (mi->starkd) {
		startree_close(mi->starkd);
		mi->starkd = NULL;
	}
	if (mi->inds) {
		int i;
		for (i=0; i<pl_size(mi->inds); i++) {
			index_t* ind = pl_get(mi->inds, i);
			ind->starkd = NULL;
			index_free(ind);
		}
		pl_free(mi->inds);
		mi->inds = NULL;
	}
    if (mi->fits) {
        anqfits_close(mi->fits);
        mi->fits = NULL;
    }
}
예제 #14
0
파일: bl.c 프로젝트: blackball/an-test6
void bl_reverse(bl* list) {
	// reverse each block, and reverse the order of the blocks.
	pl* blocks;
	bl_node* node;
	bl_node* lastnode;
	int i;

	// reverse each block
	blocks = pl_new(256);
	for (node=list->head; node; node=node->next) {
		for (i=0; i<(node->N/2); i++) {
			memswap(NODE_CHARDATA(node) + i * list->datasize,
					NODE_CHARDATA(node) + (node->N - 1 - i) * list->datasize,
					list->datasize);
		}
		pl_append(blocks, node);
	}

	// reverse the blocks
	lastnode = NULL;
	for (i=pl_size(blocks)-1; i>=0; i--) {
		node = pl_get(blocks, i);
		if (lastnode)
			lastnode->next = node;
		lastnode = node;
	}
	if (lastnode)
		lastnode->next = NULL;
	pl_free(blocks);

	// swap head and tail
	node = list->head;
	list->head = list->tail;
	list->tail = node;

	list->last_access = NULL;
	list->last_access_n = 0;
}
예제 #15
0
static void pl_map_test(void) {
	printsln((Any)__func__);
	List l, ac, ex;
	
	l = sl_of_string("a, b, c, d");
	ac = pl_map(l, append_each, "...!");
	ex = sl_of_string("a...!, b...!, c...!, d...!");
	sl_check_expect(ac, ex);
	pl_free(l);
	pl_free(ac);
	pl_free(ex);
	
	l = sl_of_string("a, b, c, d");
	ac = pl_map(l, append_each, "");
	ex = sl_of_string("a, b, c, d");
	sl_check_expect(ac, ex);
	pl_free(l);
	pl_free(ac);
	pl_free(ex);
}
예제 #16
0
int main(int argc, char **argv) {
    int argchar;
	startree_t* starkd;
	double ra=0.0, dec=0.0, radius=0.0;
	sl* tag = sl_new(4);
	anbool tagall = FALSE;
	char* starfn = NULL;
	int loglvl = LOG_MSG;
	char** myargs;
	int nmyargs;
	anbool getinds = FALSE;
	double* radec;
	int* inds;
	int N;
	int i;
	char* rdfn = NULL;
	pl* tagdata = pl_new(16);
	il* tagsizes = il_new(16);
	fitstable_t* tagalong = NULL;

    while ((argchar = getopt (argc, argv, OPTIONS)) != -1)
        switch (argchar) {
		case 'o':
			rdfn = optarg;
			break;
		case 'I':
			getinds = TRUE;
			break;
		case 'r':
			ra = atof(optarg);
			break;
		case 'd':
			dec = atof(optarg);
			break;
		case 'R':
			radius = atof(optarg);
			break;
		case 't':
			sl_append(tag, optarg);
			break;
		case 'T':
			tagall = TRUE;
			break;
		case 'v':
			loglvl++;
			break;
        case '?':
            fprintf(stderr, "Unknown option `-%c'.\n", optopt);
		case 'h':
			printHelp(argv[0]);
			break;
		default:
			return -1;
		}

	nmyargs = argc - optind;
	myargs = argv + optind;

	if (nmyargs != 1) {
		ERROR("Got %i arguments; expected 1.\n", nmyargs);
		printHelp(argv[0]);
		exit(-1);
	}
	starfn = myargs[0];

	log_init(loglvl);

	starkd = startree_open(starfn);
	if (!starkd) {
		ERROR("Failed to open star kdtree");
		exit(-1);
	}

	logmsg("Searching kdtree %s at RA,Dec = (%g,%g), radius %g deg.\n",
		   starfn, ra, dec, radius);

	startree_search_for_radec(starkd, ra, dec, radius,
							  NULL, &radec, &inds, &N);

	logmsg("Got %i results.\n", N);

	if (!N)
		goto done;

	if (tagall) {
		int j, M;
		M = startree_get_tagalong_N_columns(starkd); 
		for (j=0; j<M; j++)
			sl_append(tag, startree_get_tagalong_column_name(starkd, j));
	}

	if (sl_size(tag)) {
		tagalong = startree_get_tagalong(starkd);
		if (!tagalong) {
			ERROR("Failed to find tag-along table in index");
			exit(-1);
		}
	}

	if (rdfn) {
		rdlist_t* rd = rdlist_open_for_writing(rdfn);
		il* colnums = il_new(16);

		if (!rd) {
			ERROR("Failed to open output file %s", rdfn);
			exit(-1);
		}
		if (rdlist_write_primary_header(rd)) {
			ERROR("Failed to write header to output file %s", rdfn);
			exit(-1);
		}

		for (i=0; i<sl_size(tag); i++) {
			const char* col = sl_get(tag, i);
			char* units;
			tfits_type type;
			int arraysize;
			void* data;
			int colnum;
			int itemsize;

			if (fitstable_find_fits_column(tagalong, col, &units, &type, &arraysize)) {
				ERROR("Failed to find column \"%s\" in index", col);
				exit(-1);
			}
			itemsize = fits_get_atom_size(type) * arraysize;
			data = fitstable_read_column_array_inds(tagalong, col, type, inds, N, NULL);
			if (!data) {
				ERROR("Failed to read data for column \"%s\" in index", col);
				exit(-1);
			}
			colnum = rdlist_add_tagalong_column(rd, type, arraysize, type, col, NULL);

			il_append(colnums, colnum);
			il_append(tagsizes, itemsize);
			pl_append(tagdata, data);
		}
		if (rdlist_write_header(rd)) {
			ERROR("Failed to write header to output file %s", rdfn);
			exit(-1);
		}

		for (i=0; i<N; i++) {
			if (rdlist_write_one_radec(rd, radec[i*2+0], radec[i*2+1])) {
				ERROR("Failed to write RA,Dec to output file %s", rdfn);
				exit(-1);
			}
		}
		for (i=0; i<sl_size(tag); i++) {
			int col = il_get(colnums, i);
			void* data = pl_get(tagdata, i);
			int itemsize = il_get(tagsizes, i);

			if (rdlist_write_tagalong_column(rd, col, 0, N, data, itemsize)) {
				ERROR("Failed to write tag-along data column %s", sl_get(tag, i));
				exit(-1);
			}
		}
		if (rdlist_fix_header(rd) ||
			rdlist_fix_primary_header(rd) ||
			rdlist_close(rd)) {
			ERROR("Failed to close output file %s", rdfn);
			exit(-1);
		}
		il_free(colnums);

	} else {
		// Header
		printf("# RA, Dec");
		if (getinds)
			printf(", index");
		for (i=0; i<sl_size(tag); i++)
			printf(", %s", sl_get(tag, i));
		printf("\n");

		for (i=0; i<sl_size(tag); i++) {
			const char* col = sl_get(tag, i);
			char* units;
			tfits_type type;
			int arraysize;
			void* data;
			int itemsize;

			if (fitstable_find_fits_column(tagalong, col, &units, &type, &arraysize)) {
				ERROR("Failed to find column \"%s\" in index", col);
				exit(-1);
			}
			itemsize = fits_get_atom_size(type) * arraysize;
			data = fitstable_read_column_array_inds(tagalong, col, type, inds, N, NULL);
			if (!data) {
				ERROR("Failed to read data for column \"%s\" in index", col);
				exit(-1);
			}
			il_append(tagsizes, itemsize);
			pl_append(tagdata, data);
		}

		for (i=0; i<N; i++) {
			//int j;
			printf("%g, %g", radec[i*2+0], radec[i*2+1]);
			if (getinds)
				printf(", %i", inds[i]);

			//// FIXME -- print tag-along data of generic type.
			/*
			 for (j=0; j<pl_size(tagdata); j++) {
			 double* data = pl_get(tagdata, j);
			 printf(", %g", data[i]);
			 }
			 */

			printf("\n");
		}
	}

 done:
	free(radec);
	free(inds);
	for (i=0; i<pl_size(tagdata); i++)
		free(pl_get(tagdata, i));
	pl_free(tagdata);
	il_free(tagsizes);

	return 0;
}
예제 #17
0
int main(int argc, char *argv[]) {
    int argchar;

	char* infn = NULL;
	char* outfn = NULL;
	FILE* fin = NULL;
	FILE* fout = NULL;
	pl* cols;
	char* progname = argv[0];
	int nextens;
	int ext;
	int NC;
	int start, size;
    anqfits_t* anq = NULL;

	qfits_table* outtable;
	unsigned char* buffer;

	cols = pl_new(16);

    while ((argchar = getopt (argc, argv, OPTIONS)) != -1)
        switch (argchar) {
        case 'c':
			pl_append(cols, optarg);
            break;
        case 'i':
			infn = optarg;
			break;
        case 'o':
			outfn = optarg;
			break;
        case '?':
        case 'h':
			printHelp(progname);
            return 0;
        default:
            return -1;
        }

	if (!infn || !outfn || !pl_size(cols)) {
		printHelp(progname);
		exit(-1);
	}

    fin = fopen(infn, "rb");
    if (!fin) {
        ERROR("Failed to open input file %s: %s\n", infn, strerror(errno));
        exit(-1);
    }

    fout = fopen(outfn, "wb");
    if (!fout) {
        ERROR("Failed to open output file %s: %s\n", outfn, strerror(errno));
        exit(-1);
    }

	// copy the main header exactly.
    anq = anqfits_open(infn);
    if (!anq) {
        ERROR("Failed to read \"%s\"", infn);
        exit(-1);
    }
    start = anqfits_header_start(anq, 0);
    size  = anqfits_header_size (anq, 0);
    if (pipe_file_offset(fin, start, size, fout)) {
        ERROR("Failed to copy primary header.\n");
        exit(-1);
    }

	NC = pl_size(cols);
	nextens = anqfits_n_ext(anq);
	printf("Translating %i extensions.\n", nextens);
	buffer = NULL;
	for (ext=1; ext<nextens; ext++) {
		int c2, c;
		int columns[NC];
		int sizes[NC];
		int offsets[NC];
		int offset = 0;
		int off, n;
		int totalsize = 0;
		const int BLOCK=1000;
		qfits_table* table;
		qfits_header* header;
		qfits_header* tablehdr;

		if (ext%100 == 0) {
			printf("Extension %i.\n", ext);
			fflush(stdout);
		}

		if (!anqfits_is_table(anq, ext)) {
			ERROR("extention %i isn't a table.\n", ext);
			// HACK - just copy it.
			return -1;
		}
		table = anqfits_get_table(anq, ext);
		if (!table) {
			ERROR("failed to open table: file %s, extension %i.\n", infn, ext);
			return -1;
		}
        header = anqfits_get_header(anq, ext);
		if (!header) {
			ERROR("failed to read header: extension %i\n", ext);
			exit(-1);
		}

		outtable = qfits_table_new(outfn, QFITS_BINTABLE, 0, NC, table->nr);
		outtable->tab_w = 0;
		
		for (c=0; c<pl_size(cols); c++) {
			columns[c] = -1;
		}
		for (c=0; c<pl_size(cols); c++) {
			char* colname = pl_get(cols, c);
			qfits_col* col;
			c2 = fits_find_column(table, colname);
			if (c2 == -1) {
				ERROR("Extension %i: failed to find column named %s\n",
						ext, colname);
				exit(-1);
			}
			col = table->col + c2;
			columns[c] = c2;
			sizes[c] = col->atom_nb * col->atom_size;
			offsets[c] = offset;
			offset += sizes[c];

			qfits_col_fill(outtable->col + c,
						   col->atom_nb, col->atom_dec_nb,
						   col->atom_size, col->atom_type,
						   col->tlabel, col->tunit,
						   col->nullval, col->tdisp,
						   col->zero_present,
						   col->zero,
						   col->scale_present,
						   col->scale,
						   outtable->tab_w);
			outtable->tab_w += sizes[c];
		}
		totalsize = offset;

		tablehdr = qfits_table_ext_header_default(outtable);
		// add any headers from the original table that aren't part of the BINTABLE extension.
        fits_copy_non_table_headers(tablehdr, header);
		qfits_header_dump(tablehdr, fout);
		qfits_header_destroy(tablehdr);
		
		buffer = realloc(buffer, totalsize * BLOCK);

		for (off=0; off<table->nr; off+=n) {
			if (off + BLOCK > table->nr)
				n = table->nr - off;
			else
				n = BLOCK;
			for (c=0; c<pl_size(cols); c++)
				qfits_query_column_seq_to_array_no_endian_swap
					(table, columns[c], off, n, buffer + offsets[c], totalsize);
			if (fwrite(buffer, totalsize, n, fout) != n) {
				ERROR("Error writing a block of data: ext %i: %s\n", ext, strerror(errno));
				exit(-1);
			}
		}

		qfits_table_close(outtable);
		fits_pad_file(fout);
		qfits_header_destroy(header);
		qfits_table_close(table);
	}
	free(buffer);

	if (fclose(fout)) {
		ERROR("Error closing output file: %s\n", strerror(errno));
	}
	fclose(fin);

    anqfits_close(anq);

	pl_free(cols);
	return 0;
}
예제 #18
0
int main(int argc, char** args) {
    int c;
    char* wcsfn = NULL;
    char* outfn = NULL;
    char* infn = NULL;
    sip_t sip;
    double scale = 1.0;
    anbool pngformat = TRUE;

    char* hdpath = NULL;
    anbool HD = FALSE;

    cairos_t thecairos;
    cairos_t* cairos = &thecairos;

    cairo_surface_t* target = NULL;
    cairo_t* cairot = NULL;

    cairo_surface_t* surfbg = NULL;
    cairo_t* cairobg = NULL;

    cairo_surface_t* surfshapes = NULL;
    cairo_t* cairoshapes = NULL;

    cairo_surface_t* surfshapesmask = NULL;
    cairo_t* cairoshapesmask = NULL;

    cairo_surface_t* surffg = NULL;
    cairo_t* cairo = NULL;

    double lw = 2.0;
    // circle linewidth.
    double cw = 2.0;

    double ngc_fraction = 0.02;

    // NGC linewidth
    double nw = 2.0;

    // leave a gap short of connecting the points.
    double endgap = 5.0;
    // circle radius.
    double crad = endgap;

    double fontsize = 14.0;

    double label_offset = 15.0;

    int W = 0, H = 0;
    unsigned char* img = NULL;

    anbool NGC = FALSE, constell = FALSE;
    anbool bright = FALSE;
    anbool common_only = FALSE;
    anbool print_common_only = FALSE;
    int Nbright = 0;
    double ra, dec, px, py;
    int i, N;
    anbool justlist = FALSE;
    anbool only_messier = FALSE;

    anbool grid = FALSE;
    double gridspacing = 0.0;
    double gridcolor[3] = { 0.2, 0.2, 0.2 };

    int loglvl = LOG_MSG;

	char halign = 'L';
	char valign = 'C';
    sl* json = NULL;

    anbool whitetext = FALSE;

    while ((c = getopt(argc, args, OPTIONS)) != -1) {
        switch (c) {
		case 'V':
			valign = optarg[0];
			break;
		case 'O':
			halign = optarg[0];
			break;
        case 'F':
            ngc_fraction = atof(optarg);
            break;
        case 'h':
            print_help(args[0]);
            exit(0);
        case 'J':
            json = sl_new(4);
            break;
        case 'G':
            gridspacing = atof(optarg);
            break;
        case 'g':
            {
            char *tail = NULL;
            gridcolor[0] = strtod(optarg,&tail);
            if (*tail) { tail++; gridcolor[1] = strtod(tail,&tail); }
            if (*tail) { tail++; gridcolor[2] = strtod(tail,&tail); }
            }
            break;
        case 'D':
            HD = TRUE;
            break;
        case 'd':
            hdpath = optarg;
            break;
        case 'M':
            only_messier = TRUE;
            break;
        case 'n':
            nw = atof(optarg);
            break;
        case 'f':
            fontsize = atof(optarg);
            break;
        case 'L':
            justlist = TRUE;
            outfn = NULL;
            break;
        case 'x':
        	whitetext = TRUE;
        	break;
        case 'v':
            loglvl++;
            break;
            break;
        case 'j':
            print_common_only = TRUE;
            break;
        case 'c':
            common_only = TRUE;
            break;
        case 'b':
            Nbright = atoi(optarg);
            break;
        case 'B':
            bright = TRUE;
            break;
        case 'N':
            NGC = TRUE;
            break;
        case 'C':
            constell = TRUE;
            break;
        case 'p':
            pngformat = FALSE;
            break;
        case 's':
            scale = atof(optarg);
            break;
        case 'o':
            outfn = optarg;
            break;
        case 'i':
            infn = optarg;
            break;
        case 'w':
            wcsfn = optarg;
            break;
        case 'W':
            W = atoi(optarg);
            break;
        case 'H':
            H = atoi(optarg);
            break;
        }
    }

    log_init(loglvl);
    log_to(stderr);
    fits_use_error_system();

    if (optind != argc) {
        print_help(args[0]);
        exit(-1);
    }

    if (!(outfn || justlist) || !wcsfn) {
        logerr("Need (-o or -L) and -w args.\n");
        print_help(args[0]);
        exit(-1);
    }

    // read WCS.
    logverb("Trying to parse SIP/TAN header from %s...\n", wcsfn);
    if (!file_exists(wcsfn)) {
        ERROR("No such file: \"%s\"", wcsfn);
        exit(-1);
    }
    if (sip_read_header_file(wcsfn, &sip)) {
        logverb("Got SIP header.\n");
    } else {
        ERROR("Failed to parse SIP/TAN header from %s", wcsfn);
        exit(-1);
    }

    if (!(NGC || constell || bright || HD || grid)) {
        logerr("Neither constellations, bright stars, HD nor NGC/IC overlays selected!\n");
        print_help(args[0]);
        exit(-1);
    }

    if (gridspacing > 0.0)
        grid = TRUE;

    // adjust for scaling...
    lw /= scale;
    cw /= scale;
    nw /= scale;
    crad /= scale;
    endgap /= scale;
    fontsize /= scale;
    label_offset /= scale;

    if (!W || !H) {
        W = sip.wcstan.imagew;
        H = sip.wcstan.imageh;
    }
    if (!(infn || (W && H))) {
        logerr("Image width/height unspecified, and no input image given.\n");
        exit(-1);
    }


    if (infn) {
		cairoutils_fake_ppm_init();
        img = cairoutils_read_ppm(infn, &W, &H);
        if (!img) {
            ERROR("Failed to read input image %s", infn);
            exit(-1);
        }
        cairoutils_rgba_to_argb32(img, W, H);
    } else if (!justlist) {
        // Allocate a black image.
        img = calloc(4 * W * H, 1);
        if (!img) {
            SYSERROR("Failed to allocate a blank image on which to plot!");
            exit(-1);
        }
    }

    if (HD && !hdpath) {
        logerr("If you specify -D (plot Henry Draper objs), you also have to give -d (path to Henry Draper catalog)\n");
        exit(-1);
    }

    if (!justlist) {
        /*
         Cairo layers:

         -background: surfbg / cairobg
         --> gets drawn first, in black, masked by surfshapesmask

         -shapes: surfshapes / cairoshapes
         --> gets drawn second, masked by surfshapesmask

         -foreground/text: surffg / cairo
         --> gets drawn last.
         */
        surffg = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, W, H);
        cairo = cairo_create(surffg);
        cairo_set_line_join(cairo, CAIRO_LINE_JOIN_BEVEL);
        cairo_set_antialias(cairo, CAIRO_ANTIALIAS_GRAY);
        cairo_set_source_rgba(cairo, 1.0, 1.0, 1.0, 1.0);
        cairo_scale(cairo, scale, scale);
        //cairo_select_font_face(cairo, "helvetica", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        cairo_select_font_face(cairo, "DejaVu Sans Mono Book", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        cairo_set_font_size(cairo, fontsize);

        surfshapes = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, W, H);
        cairoshapes = cairo_create(surfshapes);
        cairo_set_line_join(cairoshapes, CAIRO_LINE_JOIN_BEVEL);
        cairo_set_antialias(cairoshapes, CAIRO_ANTIALIAS_GRAY);
        cairo_set_source_rgba(cairoshapes, 1.0, 1.0, 1.0, 1.0);
        cairo_scale(cairoshapes, scale, scale);
        cairo_select_font_face(cairoshapes, "DejaVu Sans Mono Book", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        cairo_set_font_size(cairoshapes, fontsize);

        surfshapesmask = cairo_image_surface_create(CAIRO_FORMAT_A8, W, H);
        cairoshapesmask = cairo_create(surfshapesmask);
        cairo_set_line_join(cairoshapesmask, CAIRO_LINE_JOIN_BEVEL);
        cairo_set_antialias(cairoshapesmask, CAIRO_ANTIALIAS_GRAY);
        cairo_set_source_rgba(cairoshapesmask, 1.0, 1.0, 1.0, 1.0);
        cairo_scale(cairoshapesmask, scale, scale);
        cairo_select_font_face(cairoshapesmask, "DejaVu Sans Mono Book", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        cairo_set_font_size(cairoshapesmask, fontsize);
        cairo_paint(cairoshapesmask);
        cairo_stroke(cairoshapesmask);

        surfbg = cairo_image_surface_create(CAIRO_FORMAT_A8, W, H);
        cairobg = cairo_create(surfbg);
        cairo_set_line_join(cairobg, CAIRO_LINE_JOIN_BEVEL);
        cairo_set_antialias(cairobg, CAIRO_ANTIALIAS_GRAY);
        cairo_set_source_rgba(cairobg, 0, 0, 0, 1);
        cairo_scale(cairobg, scale, scale);
        cairo_select_font_face(cairobg, "DejaVu Sans Mono Book", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
        cairo_set_font_size(cairobg, fontsize);

        cairos->bg = cairobg;
        cairos->fg = cairo;
        cairos->shapes = cairoshapes;
        cairos->shapesmask = cairoshapesmask;
        cairos->imgW = (float)W/scale;
        cairos->imgH = (float)H/scale;
//    }

    if (grid) {
        double ramin, ramax, decmin, decmax;
        double ra, dec;
        double rastep = gridspacing / 60.0;
        double decstep = gridspacing / 60.0;
        // how many line segments
        int N = 10;
        double px, py;
        int i;

        cairo_set_source_rgba(cairo, gridcolor[0], gridcolor[1], gridcolor[2], 1.0);

        sip_get_radec_bounds(&sip, 100, &ramin, &ramax, &decmin, &decmax);
		logverb("Plotting grid lines from RA=%g to %g in steps of %g; Dec=%g to %g in steps of %g\n",
				ramin, ramax, rastep, decmin, decmax, decstep);
        for (dec = decstep * floor(decmin / decstep); dec<=decmax; dec+=decstep) {
			logverb("  dec=%g\n", dec);
            for (i=0; i<=N; i++) {
                ra = ramin + ((double)i / (double)N) * (ramax - ramin);
                if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py))
                    continue;
                // first time, move_to; else line_to
                ((ra == ramin) ? cairo_move_to : cairo_line_to)(cairo, px, py);
            }
            cairo_stroke(cairo);
        }
        for (ra = rastep * floor(ramin / rastep); ra <= ramax; ra += rastep) {
            //for (dec=decmin; dec<=decmax; dec += (decmax - decmin)/(double)N) {
			logverb("  ra=%g\n", ra);
            for (i=0; i<=N; i++) {
                dec = decmin + ((double)i / (double)N) * (decmax - decmin);
                if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py))
                    continue;
                // first time, move_to; else line_to
                ((dec == decmin) ? cairo_move_to : cairo_line_to)(cairo, px, py);
            }
            cairo_stroke(cairo);
        }

        cairo_set_source_rgba(cairo, 1.0, 1.0, 1.0, 1.0);
    }
  }

    if (constell) {
        N = constellations_n();

        logverb("Checking %i constellations.\n", N);
        for (c=0; c<N; c++) {
            const char* shortname = NULL;
            const char* longname;
            il* lines;
            il* uniqstars;
            il* inboundstars;
            float r,g,b;
            int Ninbounds;
            int Nunique;
            cairo_text_extents_t textents;
            double cmass[3];

            uniqstars = constellations_get_unique_stars(c);
            inboundstars = il_new(16);

            Nunique = il_size(uniqstars);
            debug("%s: %zu unique stars.\n", shortname, il_size(uniqstars));

            // Count the number of unique stars belonging to this contellation
            // that are within the image bounds
            Ninbounds = 0;
            for (i=0; i<il_size(uniqstars); i++) {
                int star;
                star = il_get(uniqstars, i);
                constellations_get_star_radec(star, &ra, &dec);
                debug("star %i: ra,dec (%g,%g)\n", il_get(uniqstars, i), ra, dec);
                if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py))
                    continue;
                if (px < 0 || py < 0 || px*scale > W || py*scale > H)
                    continue;
                Ninbounds++;
                il_append(inboundstars, star);
            }
            il_free(uniqstars);
            debug("%i are in-bounds.\n", Ninbounds);
            // Only draw this constellation if at least 2 of its stars
            // are within the image bounds.
            if (Ninbounds < 2) {
                il_free(inboundstars);
                continue;
            }

            // Set the color based on the location of the first in-bounds star.
            // This is a hack -- we have two different constellation
            // definitions with different numbering schemes!
            if (!justlist && (il_size(inboundstars) > 0)) {
                // This is helpful for videos: ensuring that the same
                // color is chosen for a constellation in each frame.
                int star = il_get(inboundstars, 0);
                constellations_get_star_radec(star, &ra, &dec);
                if (whitetext) {
                	r = g = b = 1;
                } else {
                	color_for_radec(ra, dec, &r, &g, &b);
                }
                cairo_set_source_rgba(cairoshapes, r,g,b,0.8);
                cairo_set_line_width(cairoshapes, cw);
                cairo_set_source_rgba(cairo, r,g,b,0.8);
                cairo_set_line_width(cairo, cw);
            }

            // Draw circles around each star.
            // Find center of mass (of the in-bounds stars)
            cmass[0] = cmass[1] = cmass[2] = 0.0;
            for (i=0; i<il_size(inboundstars); i++) {
                double xyz[3];
                int star = il_get(inboundstars, i);
                constellations_get_star_radec(star, &ra, &dec);
                if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py))
                    continue;
                if (px < 0 || py < 0 || px*scale > W || py*scale > H)
                    continue;
                if (!justlist) {
                    cairo_arc(cairobg, px, py, crad+1.0, 0.0, 2.0*M_PI);
                    cairo_stroke(cairobg);
                    cairo_arc(cairoshapes, px, py, crad, 0.0, 2.0*M_PI);
                    cairo_stroke(cairoshapes);
                }
                radecdeg2xyzarr(ra, dec, xyz);
                cmass[0] += xyz[0];
                cmass[1] += xyz[1];
                cmass[2] += xyz[2];
            }
            cmass[0] /= il_size(inboundstars);
            cmass[1] /= il_size(inboundstars);
            cmass[2] /= il_size(inboundstars);
            xyzarr2radecdeg(cmass, &ra, &dec);

            il_free(inboundstars);

            if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py))
                continue;

            shortname = constellations_get_shortname(c);
            longname = constellations_get_longname(c);
            assert(shortname && longname);

            logverb("%s at (%g, %g)\n", longname, px, py);

            if (Ninbounds == Nunique) {
                printf("The constellation %s (%s)\n", longname, shortname);
            } else {
                printf("Part of the constellation %s (%s)\n", longname, shortname);
            }

            if (justlist)
                continue;

            // If the label will be off-screen, move it back on.
            cairo_text_extents(cairo, shortname, &textents);
			
            if (px < 0)
                px = 0;
            if (py < textents.height)
                py = textents.height;
            if ((px + textents.width)*scale > W)
                px = W/scale - textents.width;
            if ((py+textents.height)*scale > H)
                py = H/scale - textents.height;
            logverb("%s at (%g, %g)\n", shortname, px, py);

            add_text(cairos, longname, px, py, halign, valign);

            // Draw the lines.
            cairo_set_line_width(cairo, lw);
            lines = constellations_get_lines(c);
            for (i=0; i<il_size(lines)/2; i++) {
                int star1, star2;
                double ra1, dec1, ra2, dec2;
                double px1, px2, py1, py2;
                double dx, dy;
                double dist;
                double gapfrac;
                star1 = il_get(lines, i*2+0);
                star2 = il_get(lines, i*2+1);
                constellations_get_star_radec(star1, &ra1, &dec1);
                constellations_get_star_radec(star2, &ra2, &dec2);
                if (!sip_radec2pixelxy(&sip, ra1, dec1, &px1, &py1) ||
                    !sip_radec2pixelxy(&sip, ra2, dec2, &px2, &py2))
                    continue;
                dx = px2 - px1;
                dy = py2 - py1;
                dist = hypot(dx, dy);
                gapfrac = endgap / dist;
                cairo_move_to(cairoshapes, px1 + dx*gapfrac, py1 + dy*gapfrac);
                cairo_line_to(cairoshapes, px1 + dx*(1.0-gapfrac), py1 + dy*(1.0-gapfrac));
                cairo_stroke(cairoshapes);
            }
            il_free(lines);
        }
        logverb("done constellations.\n");
    }

    if (bright) {
        double dy = 0;
        cairo_font_extents_t extents;
        pl* brightstars = pl_new(16);

        if (!justlist) {
            cairo_set_source_rgba(cairoshapes, 0.75, 0.75, 0.75, 0.8);
            cairo_font_extents(cairo, &extents);
            dy = extents.ascent * 0.5;
            cairo_set_line_width(cairoshapes, cw);
        }

        N = bright_stars_n();
        logverb("Checking %i bright stars.\n", N);

        for (i=0; i<N; i++) {
            const brightstar_t* bs = bright_stars_get(i);

            if (!sip_radec2pixelxy(&sip, bs->ra, bs->dec, &px, &py))
                continue;
            if (px < 0 || py < 0 || px*scale > W || py*scale > H)
                continue;
            if (!(bs->name && strlen(bs->name)))
                continue;
            if (common_only && !(bs->common_name && strlen(bs->common_name)))
                continue;

            if (strcmp(bs->common_name, "Maia") == 0)
                continue;

            pl_append(brightstars, bs);
        }

        // keep only the Nbright brightest?
        if (Nbright && (pl_size(brightstars) > Nbright)) {
            pl_sort(brightstars, sort_by_mag);
            pl_remove_index_range(brightstars, Nbright, pl_size(brightstars)-Nbright);
        }

        for (i=0; i<pl_size(brightstars); i++) {
            char* text;
            const brightstar_t* bs = pl_get(brightstars, i);

            if (!sip_radec2pixelxy(&sip, bs->ra, bs->dec, &px, &py))
                continue;
            if (bs->common_name && strlen(bs->common_name))
                if (print_common_only || common_only)
                    text = strdup(bs->common_name);
                else
                    asprintf_safe(&text, "%s (%s)", bs->common_name, bs->name);
            else
                text = strdup(bs->name);

            logverb("%s at (%g, %g)\n", text, px, py);

            if (json) {
                sl* names = sl_new(4);
                char* namearr;
                if (bs->common_name && strlen(bs->common_name))
                    sl_append(names, bs->common_name);
                if (bs->name)
					sl_append(names, bs->name);
				
                namearr = sl_join(names, "\", \"");

                sl_appendf(json,
                           "{ \"type\"  : \"star\", "
                           "  \"pixelx\": %g,       "
                           "  \"pixely\": %g,       "
                           "  \"name\"  : \"%s\",   "
                           "  \"names\" : [ \"%s\" ] } "
                           , px, py,
                           (bs->common_name && strlen(bs->common_name)) ? bs->common_name : bs->name,
                           namearr);
                free(namearr);
                sl_free2(names);
            }

            if (bs->common_name && strlen(bs->common_name))
                printf("The star %s (%s)\n", bs->common_name, bs->name);
            else
                printf("The star %s\n", bs->name);

            if (!justlist) {
                float r,g,b;
                // set color based on RA,Dec to match constellations above.
                if (whitetext) {
                	r = g = b = 1;
                } else {
                	color_for_radec(bs->ra, bs->dec, &r, &g, &b);
                }
                cairo_set_source_rgba(cairoshapes, r,g,b,0.8);
                cairo_set_source_rgba(cairo, r,g,b, 0.8);
            }

            if (!justlist)
                add_text(cairos, text, px + label_offset, py + dy,
						 halign, valign);

            free(text);

            if (!justlist) {
                // plot a black circle behind the light circle...
                cairo_arc(cairobg, px, py, crad+1.0, 0.0, 2.0*M_PI);
                cairo_stroke(cairobg);

                cairo_arc(cairoshapes, px, py, crad, 0.0, 2.0*M_PI);
                cairo_stroke(cairoshapes);
            }
        }
        pl_free(brightstars);
    }

    if (NGC) {
        double imscale;
        double imsize;
        double dy = 0;
        cairo_font_extents_t extents;

        if (!justlist) {
            cairo_set_source_rgb(cairoshapes, 1.0, 1.0, 1.0);
            cairo_set_source_rgb(cairo, 1.0, 1.0, 1.0);
            cairo_set_line_width(cairo, nw);
            cairo_font_extents(cairo, &extents);
            dy = extents.ascent * 0.5;
        }

        // arcsec/pixel
        imscale = sip_pixel_scale(&sip);
        // arcmin
        imsize = imscale * (imin(W, H) / scale) / 60.0;
        N = ngc_num_entries();

        logverb("Checking %i NGC/IC objects.\n", N);

        for (i=0; i<N; i++) {
            ngc_entry* ngc = ngc_get_entry(i);
            sl* str;
            sl* names;
            double pixsize;
            float ara, adec;
            char* text;

            if (!ngc)
                break;
            if (ngc->size < imsize * ngc_fraction)
                continue;

            if (ngcic_accurate_get_radec(ngc->is_ngc, ngc->id, &ara, &adec) == 0) {
                ngc->ra = ara;
                ngc->dec = adec;
            }

            if (!sip_radec2pixelxy(&sip, ngc->ra, ngc->dec, &px, &py))
                continue;
            if (px < 0 || py < 0 || px*scale > W || py*scale > H)
                continue;

            str = sl_new(4);
            //sl_appendf(str, "%s %i", (ngc->is_ngc ? "NGC" : "IC"), ngc->id);
            names = ngc_get_names(ngc, NULL);
            if (names) {
                int n;
                for (n=0; n<sl_size(names); n++) {
                    if (only_messier && strncmp(sl_get(names, n), "M ", 2))
                        continue;
                    sl_append(str, sl_get(names, n));
                }
            }
            sl_free2(names);

            text = sl_implode(str, " / ");

            printf("%s\n", text);

            pixsize = ngc->size * 60.0 / imscale;

            if (!justlist) {
                // black circle behind the white one...
                cairo_arc(cairobg, px, py, pixsize/2.0+1.0, 0.0, 2.0*M_PI);
                cairo_stroke(cairobg);

                cairo_move_to(cairoshapes, px + pixsize/2.0, py);
                cairo_arc(cairoshapes, px, py, pixsize/2.0, 0.0, 2.0*M_PI);
                debug("size: %f arcsec, pixsize: %f pixels\n", ngc->size, pixsize);
                cairo_stroke(cairoshapes);

                add_text(cairos, text, px + label_offset, py + dy,
						 halign, valign);
            }

            if (json) {
                char* namelist = sl_implode(str, "\", \"");
                sl_appendf(json,
                           "{ \"type\"   : \"ngc\", "
                           "  \"names\"  : [ \"%s\" ], "
                           "  \"pixelx\" : %g, "
                           "  \"pixely\" : %g, "
                           "  \"radius\" : %g }"
                           , namelist, px, py, pixsize/2.0);
                free(namelist);
            }

            free(text);
            sl_free2(str);
        }
    }

    if (HD) {
        double rac, decc, ra2, dec2;
        double arcsec;
        hd_catalog_t* hdcat;
        bl* hdlist;
        int i;

        if (!justlist)
            cairo_set_source_rgb(cairo, 1.0, 1.0, 1.0);

		logverb("Reading HD catalog: %s\n", hdpath);
        hdcat = henry_draper_open(hdpath);
        if (!hdcat) {
            ERROR("Failed to open HD catalog");
            exit(-1);
        }
		logverb("Got %i HD stars\n", henry_draper_n(hdcat));

        sip_pixelxy2radec(&sip, W/(2.0*scale), H/(2.0*scale), &rac, &decc);
        sip_pixelxy2radec(&sip, 0.0, 0.0, &ra2, &dec2);
        arcsec = arcsec_between_radecdeg(rac, decc, ra2, dec2);
        // Fudge
        arcsec *= 1.1;
        hdlist = henry_draper_get(hdcat, rac, decc, arcsec);
		logverb("Found %zu HD stars within range (%g arcsec of RA,Dec %g,%g)\n", bl_size(hdlist), arcsec, rac, decc);

        for (i=0; i<bl_size(hdlist); i++) {
            double px, py;
            char* txt;
            hd_entry_t* hd = bl_access(hdlist, i);
            if (!sip_radec2pixelxy(&sip, hd->ra, hd->dec, &px, &py)) {
                continue;
			}
            if (px < 0 || py < 0 || px*scale > W || py*scale > H) {
				logverb("  HD %i at RA,Dec (%g, %g) -> pixel (%.1f, %.1f) is out of bounds\n",
						hd->hd, hd->ra, hd->dec, px, py);
                continue;
			}
            asprintf_safe(&txt, "HD %i", hd->hd);
            if (!justlist) {
                cairo_text_extents_t textents;
                cairo_text_extents(cairo, txt, &textents);
                cairo_arc(cairobg, px, py, crad+1.0, 0.0, 2.0*M_PI);
                cairo_stroke(cairobg);
                cairo_arc(cairoshapes, px, py, crad, 0.0, 2.0*M_PI);
                cairo_stroke(cairoshapes);

                px -= (textents.width * 0.5);
                py -= (crad + 4.0);

                add_text(cairos, txt, px, py, halign, valign);
            }

            if (json)
                sl_appendf(json,
                           "{ \"type\"  : \"hd\","
                           "  \"pixelx\": %g, "
                           "  \"pixely\": %g, "
                           "  \"name\"  : \"HD %i\" }"
                           , px, py, hd->hd);

            printf("%s\n", txt);
            free(txt);
        }
        bl_free(hdlist);
        henry_draper_close(hdcat);
    }

    if (json) {
        FILE* fout = stderr;
        char* annstr = sl_implode(json, ",\n");
        fprintf(fout, "{ \n");
        fprintf(fout, "  \"status\": \"solved\",\n");
        fprintf(fout, "  \"git-revision\": %s,\n", AN_GIT_REVISION);
        fprintf(fout, "  \"git-date\": \"%s\",\n", AN_GIT_DATE);
        fprintf(fout, "  \"annotations\": [\n%s\n]\n", annstr);
        fprintf(fout, "}\n");
        free(annstr);
    }
    sl_free2(json);
    json = NULL;

    if (justlist)
        return 0;

    target = cairo_image_surface_create_for_data(img, CAIRO_FORMAT_ARGB32, W, H, W*4);
    cairot = cairo_create(target);
    cairo_set_source_rgba(cairot, 0, 0, 0, 1);

    // Here's where you set the background surface's properties...
    cairo_set_source_surface(cairot, surfbg, 0, 0);
    cairo_mask_surface(cairot, surfshapesmask, 0, 0);
    cairo_stroke(cairot);

    // Add on the shapes.
    cairo_set_source_surface(cairot, surfshapes, 0, 0);
    //cairo_mask_surface(cairot, surfshapes, 0, 0);
    cairo_mask_surface(cairot, surfshapesmask, 0, 0);
    cairo_stroke(cairot);

    // Add on the foreground.
    cairo_set_source_surface(cairot, surffg, 0, 0);
    cairo_mask_surface(cairot, surffg, 0, 0);
    cairo_stroke(cairot);

    // Convert image for output...
    cairoutils_argb32_to_rgba(img, W, H);

    if (pngformat) {
        if (cairoutils_write_png(outfn, img, W, H)) {
            ERROR("Failed to write PNG");
            exit(-1);
        }
    } else {
        if (cairoutils_write_ppm(outfn, img, W, H)) {
            ERROR("Failed to write PPM");
            exit(-1);
        }
    }

    cairo_surface_destroy(target);
    cairo_surface_destroy(surfshapesmask);
    cairo_surface_destroy(surffg);
    cairo_surface_destroy(surfbg);
    cairo_surface_destroy(surfshapes);
    cairo_destroy(cairo);
    cairo_destroy(cairot);
    cairo_destroy(cairobg);
    cairo_destroy(cairoshapes);
    cairo_destroy(cairoshapesmask);
    free(img);

    return 0;
}
예제 #19
0
//Applies NUM_PLY number of plys
double ply(list B, int d, Heuristic H) {
    if (d == 0) {
        listNode* node = B.head;
        double totalHeur = 0;
        if (B.logicalLength == 0)
            return 0;
        while (node != NULL) {
            //if (p)
            //    print_board(
            struct board_data b;
            b.data = node->data;
            totalHeur = totalHeur + (*H)(&b);
            node = node->next;
        }
        return (totalHeur / B.logicalLength);
        
    }
    list B2;
    list_new(&B2, BOARDSIZE * BOARDSIZE * sizeof(int), free);
    listNode* node = B.head;
    //printf("in ply\n");
    while (node != NULL) {
        int *bdata = (int *)(node->data);
        struct board_data b;
        b.data = bdata;
        //print_board(&b);
        PointList pl = open_spaces(&b);
        if (pl->N == 0) {
            pl_free(pl);
            node = node->next;
            continue;
        }
        listNode* n = pl->points.head;
        while (n != NULL) {
            Board b2 = board_cpy(&b);
            //Board b4 = board_cpy(&b);
            Point p = (Point)n->data;
            //printf("point (%d, %d)\n", p->r, p->c);
            place(b2, p->r, p->c, 2);
            //print_board(b2);
            //place(b4, p->r, p->c, 4);
            if (d == 1) {
                //printf("possible move of depth %i\n", NUM_PLY);
                //print_board(b2);
                list_prepend(&B2, (void*)b2->data);
                //list_prepend(&B2, (void*)b4->data);
                free_board(b2);
                //free_board(b4);
            }
            else {
                int size,i;
                //printf("possible moves of depth %i\n", NUM_PLY-d+1);
                Move* moves2 = effectual_moves(b2, &size);
                for (i=0; i < size; i++) {
                    Board cpy = board_cpy(b2);
                    shift(cpy, moves2[i]);
                    list_prepend(&B2, (void*)cpy->data);
                    //print_board(cpy);
                    free_board(cpy);
                }
                //Move* moves4 = effectual_moves(b4, &size);
                //for (i=0; i < size; i++) {
                //    Board cpy = board_cpy(b4);
                //    shift(cpy, moves4[i]);
                //    list_prepend(&B2, (void*)cpy->data);
                //    free_board(cpy);
                //}
                free_board(b2);
                //free_board(b4);
            }
            n = n->next;
        }
        pl_free(pl);
        node = node->next;
    }
    double retval = ply(B2, d-1, H);
    while (d > 1 && retval == 0) {
        d = d-1;
        retval = ply(B2, d-1, H);
    }
    list_destroy(&B2);
    return retval;
}
예제 #20
0
void human_game() {
    printf("Welcome to 2048!\n");
    print_commands();


    //char buf[MAXLINE];
    Game g = init_game(squaresum_heuristic);
    print_game(g);

    char in;
    int playing = 1;
    while (playing) {
        in = getc(stdin);
        if (in == '\033') {
            getc(stdin);
            switch (getc(stdin)) {
                case 'A':
                    in = 'u';
                    break;
                case 'B':
                    in = 'd';
                    break;
                case 'C':
                    in = 'r';
                    break;
                case 'D':
                    in = 'l';
                    break;
                default:
                    break;
            }
        }
        switch (in) {
            case 'q':
                playing = 0;
                break;
            case 'u':
                make_move(g, Up);
                print_game(g);
                break;
            case 'd':
                make_move(g, Down);
                print_game(g);
                break;
            case 'l':
                make_move(g, Left);
                print_game(g);
                break;
            case 'r':
                make_move(g, Right);
                print_game(g);
                break;
            case 'h':
                print_commands();
                break;
            default:
                break;
        }
        PointList pl = open_spaces(g->board);
        if (pl_empty(pl)) {
            playing = 0;
        }
        pl_free(pl);
    }
    print_game(g);
    printf("Game Over! Final Score: %d\n", g->score);
}
예제 #21
0
static void pl_insert_test(void) {
	printsln((Any)__func__);
	List ac, ex;

	ac = sl_of_string("1, 2, 3, 4, 5");
	pl_insert(ac, 0, s_create("9"));
	ex = sl_of_string("9, 1, 2, 3, 4, 5");
	sl_check_expect(ac, ex);
	pl_free(ac);
	pl_free(ex);
	
	ac = sl_of_string("1, 2, 3, 4, 5");
	pl_insert(ac, 5, s_create("9"));
	ex = sl_of_string("1, 2, 3, 4, 5, 9");
	sl_check_expect(ac, ex);
	pl_free(ac);
	pl_free(ex);
	
	ac = sl_of_string("1, 2, 3, 4, 5");
	pl_insert(ac, 3, s_create("9"));
	ex = sl_of_string("1, 2, 3, 9, 4, 5");
	sl_check_expect(ac, ex);
	pl_free(ac);
	pl_free(ex);
	
	ac = sl_of_string("1");
	pl_insert(ac, -1, "9");
	ex = sl_of_string("1");
	sl_check_expect(ac, ex);
	pl_free(ac);
	pl_free(ex);

	ac = sl_of_string("1");
	pl_insert(ac, 1, s_create("9"));
	ex = sl_of_string("1, 9");
	sl_check_expect(ac, ex);
	pl_free(ac);
	pl_free(ex);

	ac = pl_create();
	pl_insert(ac, 0, s_create("9"));
	ex = sl_of_string("9");
	sl_check_expect(ac, ex);
	pl_free(ac);
	pl_free(ex);
}
예제 #22
0
static void pl_remove_test(void) {
	printsln((Any)__func__);
	List ac, ex;
	Any s;

	ac = sl_of_string("1, 2, 3, 4, 5, 6");
	s = pl_get(ac, 0);
	s_free(s);
	pl_remove(ac, 0);
	ex = sl_of_string("2, 3, 4, 5, 6");
	sl_check_expect(ac, ex);
	pl_free(ac);
	pl_free(ex);
	
	ac = sl_of_string("1, 2, 3, 4, 5, 6");
	s = pl_get(ac, 5);
	s_free(s);
	pl_remove(ac, 5);
	ex = sl_of_string("1, 2, 3, 4, 5");
	sl_check_expect(ac, ex);
	pl_free(ac);
	pl_free(ex);
	
	ac = sl_of_string("1, 2, 3, 4, 5, 6");
	s = pl_get(ac, 3);
	s_free(s);
	pl_remove(ac, 3);
	ex = sl_of_string("1, 2, 3, 5, 6");
	sl_check_expect(ac, ex);
	pl_free(ac);
	pl_free(ex);
	
	ac = sl_of_string("1");
	pl_remove(ac, -1);
	ex = sl_of_string("1");
	sl_check_expect(ac, ex);
	pl_free(ac);
	pl_free(ex);
	
	ac = sl_of_string("1");
	pl_remove(ac, 1);
	ex = sl_of_string("1");
	sl_check_expect(ac, ex);
	pl_free(ac);
	pl_free(ex);
	
	ac = sl_of_string("1");
	s = pl_get(ac, 0);
	s_free(s);
	pl_remove(ac, 0);
	ex = pl_create();
	sl_check_expect(ac, ex);
	pl_free(ac);
	l_free(ex);
	
	ac = sl_of_string("");
	s = pl_get(ac, 0);
	s_free(s);
	pl_remove(ac, 0);
	ex = pl_create();
	sl_check_expect(ac, ex);
	l_free(ac);
	l_free(ex);
}
예제 #23
0
파일: main.c 프로젝트: Gardenya/deadbeef
int
main (int argc, char *argv[]) {
    int portable = 0;
#if STATICLINK
    int staticlink = 1;
#else
    int staticlink = 0;
#endif
#if PORTABLE
    portable = 1;
    if (!realpath (argv[0], dbinstalldir)) {
        strcpy (dbinstalldir, argv[0]);
    }
    char *e = strrchr (dbinstalldir, '/');
    if (e) {
        *e = 0;
    }
    else {
        fprintf (stderr, "couldn't determine install folder from path %s\n", argv[0]);
        exit (-1);
    }
#else
    if (!realpath (argv[0], dbinstalldir)) {
        strcpy (dbinstalldir, argv[0]);
    }
    char *e = strrchr (dbinstalldir, '/');
    if (e) {
        *e = 0;
        struct stat st;
        char checkpath[PATH_MAX];
        snprintf (checkpath, sizeof (checkpath), "%s/.ddb_portable", dbinstalldir);
        if (!stat (checkpath, &st)) {
            if (S_ISREG (st.st_mode)) {
                portable = 1;
            }
        }
    }
    if (!portable) {
        strcpy (dbinstalldir, PREFIX);
    }
#endif

#ifdef __GLIBC__
    signal (SIGSEGV, sigsegv_handler);
#endif
    setlocale (LC_ALL, "");
    setlocale (LC_NUMERIC, "C");
#ifdef ENABLE_NLS
//    fprintf (stderr, "enabling gettext support: package=" PACKAGE ", dir=" LOCALEDIR "...\n");
    if (portable) {
        char localedir[PATH_MAX];
        snprintf (localedir, sizeof (localedir), "%s/locale", dbinstalldir);
        bindtextdomain (PACKAGE, localedir);
    }
    else {
        bindtextdomain (PACKAGE, LOCALEDIR);
    }
	bind_textdomain_codeset (PACKAGE, "UTF-8");
	textdomain (PACKAGE);
#endif

    fprintf (stderr, "starting deadbeef " VERSION "%s%s\n", staticlink ? " [static]" : "", portable ? " [portable]" : "");
    srand (time (NULL));
#ifdef __linux__
    prctl (PR_SET_NAME, "deadbeef-main", 0, 0, 0, 0);
#endif

#if PORTABLE_FULL
    if (snprintf (confdir, sizeof (confdir), "%s/config", dbinstalldir) > sizeof (confdir)) {
        fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
        return -1;
    }

    strcpy (dbconfdir, confdir);
#else
    char *homedir = getenv ("HOME");
    if (!homedir) {
        fprintf (stderr, "unable to find home directory. stopping.\n");
        return -1;
    }

    char *xdg_conf_dir = getenv ("XDG_CONFIG_HOME");
    if (xdg_conf_dir) {
        if (snprintf (confdir, sizeof (confdir), "%s", xdg_conf_dir) > sizeof (confdir)) {
            fprintf (stderr, "fatal: XDG_CONFIG_HOME value is too long: %s\n", xdg_conf_dir);
            return -1;
        }
    }
    else {
        if (snprintf (confdir, sizeof (confdir), "%s/.config", homedir) > sizeof (confdir)) {
            fprintf (stderr, "fatal: HOME value is too long: %s\n", homedir);
            return -1;
        }
    }
    if (snprintf (dbconfdir, sizeof (dbconfdir), "%s/deadbeef", confdir) > sizeof (dbconfdir)) {
        fprintf (stderr, "fatal: out of memory while configuring\n");
        return -1;
    }
    mkdir (confdir, 0755);
#endif


    if (portable) {
        if (snprintf (dbdocdir, sizeof (dbdocdir), "%s/doc", dbinstalldir) > sizeof (dbdocdir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
#ifdef HAVE_COCOAUI
        char respath[PATH_MAX];
        cocoautil_get_resources_path (respath, sizeof (respath));
        if (snprintf (dbplugindir, sizeof (dbplugindir), "%s", respath) > sizeof (dbplugindir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
#else
        if (snprintf (dbplugindir, sizeof (dbplugindir), "%s/plugins", dbinstalldir) > sizeof (dbplugindir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
#endif
        if (snprintf (dbpixmapdir, sizeof (dbpixmapdir), "%s/pixmaps", dbinstalldir) > sizeof (dbpixmapdir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
        mkdir (dbplugindir, 0755);
    }
    else {
        if (snprintf (dbdocdir, sizeof (dbdocdir), "%s", DOCDIR) > sizeof (dbdocdir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
        if (snprintf (dbplugindir, sizeof (dbplugindir), "%s/deadbeef", LIBDIR) > sizeof (dbplugindir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
        if (snprintf (dbpixmapdir, sizeof (dbpixmapdir), "%s/share/deadbeef/pixmaps", PREFIX) > sizeof (dbpixmapdir)) {
            fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
            return -1;
        }
    }

    for (int i = 1; i < argc; i++) {
        // help, version and nowplaying are executed with any filter
        if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "-h")) {
            print_help ();
            return 0;
        }
        else if (!strcmp (argv[i], "--version")) {
            fprintf (stderr, "DeaDBeeF " VERSION " Copyright © 2009-2013 Alexey Yakovenko\n");
            return 0;
        }
        else if (!strcmp (argv[i], "--gui")) {
            if (i == argc-1) {
                break;
            }
            i++;
            strncpy (use_gui_plugin, argv[i], sizeof(use_gui_plugin) - 1);
            use_gui_plugin[sizeof(use_gui_plugin) - 1] = 0;
        }
    }

    trace ("installdir: %s\n", dbinstalldir);
    trace ("confdir: %s\n", confdir);
    trace ("docdir: %s\n", dbdocdir);
    trace ("plugindir: %s\n", dbplugindir);
    trace ("pixmapdir: %s\n", dbpixmapdir);

    mkdir (dbconfdir, 0755);

    int size = 0;
    char *cmdline = prepare_command_line (argc, argv, &size);

    // try to connect to remote player
    int s, len;
    struct sockaddr_un remote;

    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    memset (&remote, 0, sizeof (remote));
    remote.sun_family = AF_UNIX;
#if USE_ABSTRACT_SOCKET_NAME
    memcpy (remote.sun_path, server_id, sizeof (server_id));
    len = offsetof(struct sockaddr_un, sun_path) + sizeof (server_id)-1;
#else
    char *socketdirenv = getenv ("DDB_SOCKET_DIR");
    snprintf (remote.sun_path, sizeof (remote.sun_path), "%s/socket", socketdirenv ? socketdirenv : dbconfdir);
    len = offsetof(struct sockaddr_un, sun_path) + strlen (remote.sun_path);
#endif
    if (connect(s, (struct sockaddr *)&remote, len) == 0) {
        // pass args to remote and exit
        if (send(s, cmdline, size, 0) == -1) {
            perror ("send");
            exit (-1);
        }
        // end of message
        shutdown(s, SHUT_WR);

        int sz = -1;
        char *out = read_entire_message(s, &sz);
        if (sz == -1) {
            fprintf (stderr, "failed to pass args to remote!\n");
            exit (-1);
        }
        else {
            // check if that's nowplaying response
            const char np[] = "nowplaying ";
            const char err[] = "error ";
            if (!strncmp (out, np, sizeof (np)-1)) {
                const char *prn = &out[sizeof (np)-1];
                fwrite (prn, 1, strlen (prn), stdout);
            }
            else if (!strncmp (out, err, sizeof (err)-1)) {
                const char *prn = &out[sizeof (err)-1];
                fwrite (prn, 1, strlen (prn), stderr);
            }
            else if (sz > 0 && out[0]) {
                fprintf (stderr, "%s\n", out);
            }
        }
        if (out) {
            free (out);
        }
        close (s);
        exit (0);
    }
//    else {
//        perror ("INFO: failed to connect to existing session:");
//    }
    close(s);

    // become a server
    if (server_start () < 0) {
        exit (-1);
    }

    // hack: report nowplaying
    if (!strcmp (cmdline, "--nowplaying")) {
        char nothing[] = "nothing";
        fwrite (nothing, 1, sizeof (nothing)-1, stdout);
        return 0;
    }

    pl_init ();
    conf_init ();
    conf_load (); // required by some plugins at startup

    if (use_gui_plugin[0]) {
        conf_set_str ("gui_plugin", use_gui_plugin);
    }

    conf_set_str ("deadbeef_version", VERSION);

    volume_set_db (conf_get_float ("playback.volume", 0)); // volume need to be initialized before plugins start

    messagepump_init (); // required to push messages while handling commandline
    if (plug_load_all ()) { // required to add files to playlist from commandline
        exit (-1);
    }
    pl_load_all ();
    plt_set_curr_idx (conf_get_int ("playlist.current", 0));

    // execute server commands in local context
    int noloadpl = 0;
    if (argc > 1) {
        int res = server_exec_command_line (cmdline, size, NULL, 0);
        // some of the server commands ran on 1st instance should terminate it
        if (res == 2) {
            noloadpl = 1;
        }
        else if (res > 0) {
            exit (0);
        }
        else if (res < 0) {
            exit (-1);
        }
    }

    free (cmdline);

#if 0
    signal (SIGTERM, sigterm_handler);
    atexit (atexit_handler); // helps to save in simple cases
#endif

    streamer_init ();

    plug_connect_all ();
    messagepump_push (DB_EV_PLUGINSLOADED, 0, 0, 0);

    if (!noloadpl) {
        restore_resume_state ();
    }

    server_tid = thread_start (server_loop, NULL);

    mainloop_tid = thread_start (mainloop_thread, NULL);

    DB_plugin_t *gui = plug_get_gui ();
    if (gui) {
        gui->start ();
    }

    fprintf (stderr, "gui plugin has quit; waiting for mainloop thread to finish\n");
    thread_join (mainloop_tid);

    // terminate server and wait for completion
    if (server_tid) {
        server_terminate = 1;
        thread_join (server_tid);
        server_tid = 0;
    }

    // save config
    pl_save_all ();
    conf_save ();

    // delete legacy session file
    {
        char sessfile[1024]; // $HOME/.config/deadbeef/session
        if (snprintf (sessfile, sizeof (sessfile), "%s/deadbeef/session", confdir) < sizeof (sessfile)) {
            unlink (sessfile);
        }
    }

    // stop receiving messages from outside
    server_close ();

    // plugins might still hold references to playitems,
    // and query configuration in background
    // so unload everything 1st before final cleanup
    plug_disconnect_all ();
    plug_unload_all ();

    // at this point we can simply do exit(0), but let's clean up for debugging
    pl_free (); // may access conf_*
    conf_free ();

    fprintf (stderr, "messagepump_free\n");
    messagepump_free ();
    fprintf (stderr, "plug_cleanup\n");
    plug_cleanup ();

    fprintf (stderr, "hej-hej!\n");

    return 0;
}