Ejemplo n.º 1
0
int main (int argc, char *argv []) {
	init_graph();

	context = zmq_init (1); 
	
	send_hashes = zmq_socket (context, ZMQ_PUSH);

    zmq_connect (send_hashes, "tcp://localhost:5557");

    recv_hashes = zmq_socket (context, ZMQ_SUB);
    zmq_connect (recv_hashes, "tcp://localhost:5556");

	recv_work = zmq_socket (context, ZMQ_REP);
	int wport = zsocket_bind(recv_work, "tcp://*:*");
	
	printf("Waiting for work on port %i\n",wport);

	recv_ctrl = zmq_socket (context, ZMQ_PULL);
	int cport = zsocket_bind(recv_ctrl, "tcp://*:*");
	
	printf("Waiting for controlmessages on port %i\n",cport);

	char *filter = "";
	zmq_setsockopt (recv_hashes, ZMQ_SUBSCRIBE, filter, strlen (filter));

    pthread_t worker;
    pthread_create (&worker, NULL, update_hashes, (void*) &context);

    pthread_t stats;
    pthread_create (&stats, NULL, print_stats, NULL);

    
	printf("starting\n");
	



//	enqueue(root,digest);
// 
   
	while (1) {
	   work_hard();
		count++;
    }
	running = 0;
	printf("%d  %d\n",count,count_elements());
	printf("Hit: %d Cache: %d\n",hit,cache);
	
	
    zmq_close (send_hashes);
    zmq_close (recv_hashes);
    zmq_term (context);

    return 0;
}
Ejemplo n.º 2
0
vector<pair<size_t, size_t> > make_pattern_counts(const context_t & ctx,
        const vector<size_t> & word_indices, const size_t & c_index) {

    // pattern_ids = map(f, word_indices)
    //      where f = lambda x : ctx.vec_letter_word_to_pattern[c_index][x]
    vector<size_t> pattern_ids;
    pattern_ids.reserve(word_indices.size());
    vector<size_t>::const_iterator j;
    for (j = word_indices.begin(); j != word_indices.end(); ++j) {
        pattern_ids.push_back(ctx.vec_letter_word_to_pattern[c_index][*j]);
    }
    return count_elements(pattern_ids);
}
Ejemplo n.º 3
0
void do_summary_calc( AS_INF near *info, BITS mode )
{
 if ( mode & ASTEROID )
	 maxplan = CHIRON;
 else if ( mode & VERT_EAST )
	 maxplan = EAST_POINT;
 else 
	 maxplan = IM_COELI;
 count_genders( info, &genders );
 count_elements( info, &elements );
 count_qualities( info, &qualities );
 count_signs( info, sign_count );
 if ( mode & HOUSES ) {
    count_hemispheres( info, &hemispheres );
    count_modals( info, &modals );
    count_functional( info, &functionals );
    scout_planet = find_scout_planet( info );
    count_houses( info, house_count );
 }
 if ( mode & ASPECTS )
    count_aspects( info, aspect_count );
}
double read_only_numerical_quick_median_internal(Iterator begin,
                                                 Iterator end,
                                                 PivotCalculator &pivot_calculator,
                                                 PerformanceStats &performance_stats)
{
    if (begin == end)
    {
        throw std::runtime_error("Cannot calculate the median of an empty set.");
    }

    /*
     * The algorithm is an optimized version of the brute force algorithm, taking its
     * cues from quickselect, which in turn is based on quicksort.
     *
     * Quicksort works by selecting a pivot, putting it into its final position in
     * the sort order, then recursively applying itself to the two subsequences on
     * either side of the pivot. Quickselect proceeds in the same way, except that
     * it does not have to apply itself to both subsequences: it is obvious which
     * subsequence contains the n-th element. (This optimization is what causes
     * quickselect to have average complexity O(N) rather than O(N logN).) One way
     * of looking at that is to say when quickselect deals with a pivot, it may not
     * have found the n-th element, but it has found an upper or lower bound, as the
     * case may be, for the n-th element. Obviously, a read-only version of quickselect
     * can do the same thing. The difference is that it cannot pass to geometrically
     * shrinking subsequences, because it cannot do any sorting. Instead, it has to
     * keep track of the current upper and lower bounds. It then makes use of that
     * information by skipping all elements that are not within these bounds when it
     * comes to selecting a pivot.
     *
     * The description above is identical to the one that we gave for the non-numerical
     * case. What's different here (that is, in the numerical case), is this:
     * instead of selecting a pivot from the available elements between the current
     * lower and upper bound, we *calculate* a pivot, namely, as some function of the
     * current lower and upper bound. This reflects the assumption that the median won't
     * be too far from the mean. The actual pivot strategy, that is, the function that
     * is used to calculate the pivot, is a policy of this algorithm. That way, the
     * pivot strategy can be chosen on the basis of assumptions regarding the distribution
     * of the data.
     */

    // If the number of elements is even, the median is an interval of
    // which both ends must be found.
    //
    bool median_interval_left_endpoint_found = false;
    double median_interval_left_endpoint = 0.;
    bool median_interval_right_endpoint_found = false;
    double median_interval_right_endpoint = 0.;

    // As a minor optimization, we trim the sequence at the beginning and
    // the end, discarding elements that are not candidates for a pivot.
    //
    int total_length_of_sequence = 0;
    Iterator active_sequence_begin = begin;
    Iterator active_sequence_end = end;
    int num_discarded_elements_less_than_median_lower_bound = 0;
    int num_discarded_elements_greater_than_median_upper_bound = 0;

    pivot_calculator.initialize(begin, end, performance_stats);
    total_length_of_sequence = pivot_calculator.get_total_sequence_length();
    double median_lower_bound = pivot_calculator.get_total_sequence_min();
    double median_upper_bound = pivot_calculator.get_total_sequence_max();
    performance_stats.set_sequence_length(total_length_of_sequence);

    // To determine the numerical pivot, we need the number of elements below and above
    // the current median lower bound and upper bound, respectively. By keeping that count
    // across loop iterations, we can update it efficiently, that is, without additional
    // comparisons.
    //
    int num_elements_less_than_median_lower_bound = 0;
    int num_elements_greater_than_median_upper_bound = 0;

    // Main loop for selecting and processing pivots.
    //
    double median = 0.0;
    while (true)
    {
        /*
         * Trim the sequence on both sides. This is a minor optimization with
         * little effect on the running time, but it is too obvious to not do it.
         * Trimming at the end can only be done for bidirectional iterators or
         * better, hence the two separate function calls.
         */

        // Trim the sequence at the beginning.
        //
        std::tuple<Iterator, int, int> trim_left_result =
            trim_sequence_left(active_sequence_begin, median_lower_bound, median_upper_bound, performance_stats);
        //
        // Trim the sequence at the end.
        //
        std::tuple<Iterator, int, int> trim_right_result =
            trim_sequence_right(active_sequence_end,
                                median_lower_bound,
                                median_upper_bound,
                                performance_stats,
                                typename std::iterator_traits<Iterator>::iterator_category());
        //
        active_sequence_begin = std::get<0>(trim_left_result);
        active_sequence_end = std::get<0>(trim_right_result);
        num_discarded_elements_less_than_median_lower_bound +=
            (std::get<1>(trim_left_result) + std::get<1>(trim_right_result));
        num_discarded_elements_greater_than_median_upper_bound +=
            (std::get<2>(trim_left_result) + std::get<2>(trim_right_result));

        /*
         * Calculate the pivot and count the number of elements less than, equal to, and greater
         * than the pivot in the subsequence [run, end).
         */

        double pivot = pivot_calculator(median_lower_bound,
                                        median_upper_bound,
                                        num_elements_less_than_median_lower_bound,
                                        num_elements_greater_than_median_upper_bound);

        std::tuple<int, int, int, double, double> element_counts =
            count_elements(active_sequence_begin, active_sequence_end, pivot, performance_stats);

        int num_elements_less_than_pivot =
            std::get<0>(element_counts) + num_discarded_elements_less_than_median_lower_bound;
        int num_elements_equal_to_pivot = std::get<1>(element_counts);
        int num_elements_greater_than_pivot =
            std::get<2>(element_counts) + num_discarded_elements_greater_than_median_upper_bound;
        double max_of_less_than_pivot = std::get<3>(element_counts);
        double min_of_greater_than_pivot = std::get<4>(element_counts);

        /*
         * Check what we found: new lower bound, new upper bound, median position, left or right endpoint of median
         * interval.
         */

        // Too many elements above pivot: new lower bound found.
        //
        if (num_elements_greater_than_pivot > (total_length_of_sequence / 2) + 1)
        {
            median_lower_bound = min_of_greater_than_pivot;
            num_elements_less_than_median_lower_bound = num_elements_less_than_pivot + num_elements_equal_to_pivot;
        }
        //
        // Too many elements below pivot: new upper bound found.
        //
        else if (num_elements_less_than_pivot > (total_length_of_sequence / 2) + 1)
        {
            median_upper_bound = max_of_less_than_pivot;
            num_elements_greater_than_median_upper_bound =
                num_elements_greater_than_pivot + num_elements_equal_to_pivot;
        }
        //
        // Median position or median interval endpoint(s) found. Here, the cases of even and odd number of
        // elements diverge.
        //
        else
        {
            // Sequence length is an odd number: median found.
            //
            if (total_length_of_sequence % 2 == 1)
            {
                if (num_elements_greater_than_pivot == (total_length_of_sequence / 2) + 1)
                {
                    median = min_of_greater_than_pivot;
                }
                else if (num_elements_less_than_pivot == (total_length_of_sequence / 2) + 1)
                {
                    median = max_of_less_than_pivot;
                }
                else
                {
                    median = pivot;
                }
                break;
            }
            //
            // Sequence length is an even number: one or both median interval endpoints found.
            //
            // In the case distinctions below, p stands for the pivot, and e_n stands for the
            // element at 1-based position n. So e_{n/2} is the left endpoint of the median
            // interval.
            //
            else
            {
                // e_{n/2 - 1} != e_{n/2} and p in [e_{n/2 - 1}, e_{n/2})
                //
                if (num_elements_greater_than_pivot == (total_length_of_sequence / 2) + 1)
                {
                    median_interval_left_endpoint_found = true;
                    median_interval_left_endpoint = min_of_greater_than_pivot;

                    // We may have to continue in search of the other median interval endpoint, so also record this
                    // as a lower bound.
                    median_lower_bound = median_interval_left_endpoint;
                    num_elements_less_than_median_lower_bound =
                        num_elements_less_than_pivot + num_elements_equal_to_pivot;
                }
                //
                // e_{n/2} != e_{n/2 + 1} and p == e_{n/2}
                //
                else if (num_elements_greater_than_pivot == total_length_of_sequence / 2 &&
                         num_elements_equal_to_pivot > 0)
                {
                    median_interval_left_endpoint_found = true;
                    median_interval_left_endpoint = pivot;

                    median_interval_right_endpoint_found = true;
                    median_interval_right_endpoint = min_of_greater_than_pivot;
                }
                //
                // e_{n/2} != e_{n/2 + 1} and p in (e_{n/2}, e_{n/2 + 1})
                //
                else if (num_elements_greater_than_pivot == total_length_of_sequence / 2)
                {
                    median_interval_left_endpoint_found = true;
                    median_interval_left_endpoint = max_of_less_than_pivot;

                    median_interval_right_endpoint_found = true;
                    median_interval_right_endpoint = min_of_greater_than_pivot;
                }
                //
                // e_{n/2} != e_{n/2 + 1} and p == e_{n/2 + 1}
                //
                else if (num_elements_less_than_pivot == total_length_of_sequence / 2 &&
                         num_elements_equal_to_pivot > 0)
                {
                    median_interval_left_endpoint_found = true;
                    median_interval_left_endpoint = max_of_less_than_pivot;

                    median_interval_right_endpoint_found = true;
                    median_interval_right_endpoint = pivot;
                }
                //
                // e_{n/2 + 1} != e_{n/2 + 2} and p in (e_{n/2 + 1}, e_{n/2 + 2}]
                //
                else if (num_elements_less_than_pivot == (total_length_of_sequence / 2) + 1)
                {
                    median_interval_right_endpoint_found = true;
                    median_interval_right_endpoint = max_of_less_than_pivot;

                    // We may have to continue in search of the other median interval endpoint, so also record this
                    // as an upper bound.
                    median_upper_bound = median_interval_right_endpoint;
                    num_elements_greater_than_median_upper_bound =
                        num_elements_greater_than_pivot + num_elements_equal_to_pivot;
                }
                //
                // Left and right endpoint of median interval must have been the same, and that was the pivot.
                //
                else
                {
                    assert(num_elements_equal_to_pivot > 0);
                    median = pivot;
                    break;
                }

                if (median_interval_left_endpoint_found && median_interval_right_endpoint_found)
                {
                    median = mean(median_interval_left_endpoint, median_interval_right_endpoint);
                    break;
                }
            }
        }
    }

    performance_stats.update_averages();
    return median;
}
Ejemplo n.º 5
0
int main (int argc, char *argv[])
{
    int i, n, ib, nb, nz, nv, celldim, phydim;
    int nn, type, *elems = 0, idata[5];
    cgsize_t ne;
    char *p, basename[33], title[65];
    float value, *var;
    SOLUTION *sol;
    FILE *fp;

    if (argc < 2)
        print_usage (usgmsg, NULL);

    ib = 0;
    basename[0] = 0;
    while ((n = getargs (argc, argv, options)) > 0) {
        switch (n) {
            case 'a':
                ascii = 1;
                break;
            case 'b':
                ib = atoi (argarg);
                break;
            case 'B':
                strncpy (basename, argarg, 32);
                basename[32] = 0;
                break;
            case 'w':
                weighting = 1;
                break;
            case 'S':
                usesol = atoi (argarg);
                break;
        }
    }

    if (argind > argc - 2)
        print_usage (usgmsg, "CGNSfile and/or Tecplotfile not given");
    if (!file_exists (argv[argind]))
        FATAL (NULL, "CGNSfile does not exist or is not a file");

    /* open CGNS file */

    printf ("reading CGNS file from %s\n", argv[argind]);
    nb = open_cgns (argv[argind], 1);
    if (!nb)
        FATAL (NULL, "no bases found in CGNS file");
    if (*basename && 0 == (ib = find_base (basename)))
        FATAL (NULL, "specified base not found");
    if (ib > nb) FATAL (NULL, "base index out of range");
    cgnsbase = ib ? ib : 1;
    if (cg_base_read (cgnsfn, cgnsbase, basename, &celldim, &phydim))
        FATAL (NULL, NULL);
    if (celldim != 3 || phydim != 3)
        FATAL (NULL, "cell and physical dimension must be 3");
    printf ("  using base %d - %s\n", cgnsbase, basename);

    if (NULL == (p = strrchr (argv[argind], '/')) &&
        NULL == (p = strrchr (argv[argind], '\\')))
        strncpy (title, argv[argind], sizeof(title));
    else
        strncpy (title, ++p, sizeof(title));
    title[sizeof(title)-1] = 0;
    if ((p = strrchr (title, '.')) != NULL)
        *p = 0;

    read_zones ();
    if (!nZones)
        FATAL (NULL, "no zones in the CGNS file");
    
    /* verify dimensions fit in an integer */

    for (nz = 0; nz < nZones; nz++) {
        if (Zones[nz].nverts > CG_MAX_INT32)
	    FATAL(NULL, "zone size too large to write with integers");
	if (Zones[nz].type == CGNS_ENUMV(Unstructured)) {
            count_elements (nz, &ne, &type);
            if (ne > CG_MAX_INT32)
	        FATAL(NULL, "too many elements to write with integers");
        }
     }

    nv = 3 + check_solution ();

    /* open Tecplot file */

    printf ("writing %s Tecplot data to <%s>\n",
        ascii ? "ASCII" : "binary", argv[++argind]);
    if (NULL == (fp = fopen (argv[argind], ascii ? "w+" : "w+b")))
        FATAL (NULL, "couldn't open Tecplot output file");

    /* write file header */

    if (ascii)
        fprintf (fp, "TITLE = \"%s\"\n", title);
    else {
        fwrite ("#!TDV75 ", 1, 8, fp);
        i = 1;
        write_ints (fp, 1, &i);
        write_string (fp, title);
    }

    /* write variables */

    if (ascii) {
        fprintf (fp, "VARIABLES = \"X\", \"Y\", \"Z\"");
        if (usesol) {
            sol = Zones->sols;
            for (n = 0; n < sol->nflds; n++)
                fprintf (fp, ",\n\"%s\"", sol->flds[n].name);
        }
    }
    else {
        write_ints (fp, 1, &nv);
        write_string (fp, "X");
        write_string (fp, "Y");
        write_string (fp, "Z");
        if (usesol) {
            sol = Zones->sols;
            for (n = 0; n < sol->nflds; n++)
                write_string (fp, sol->flds[n].name);
        }
    }

    /* write zones */

    if (!ascii) {
        for (nz = 0; nz < nZones; nz++) {
            if (Zones[nz].type == CGNS_ENUMV(Structured)) {
                idata[0] = 0;          /* BLOCK */
                idata[1] = -1;         /* color not specified */
                idata[2] = (int)Zones[nz].dim[0];
                idata[3] = (int)Zones[nz].dim[1];
                idata[4] = (int)Zones[nz].dim[2];
            }
            else {
                count_elements (nz, &ne, &type);
                idata[0] = 2;          /* FEBLOCK */
                idata[1] = -1;         /* color not specified */
                idata[2] = (int)Zones[nz].dim[0];
                idata[3] = (int)ne;
                idata[4] = type;
            }
            value = 299.0;
            write_floats (fp, 1, &value);
            write_string (fp, Zones[nz].name);
            write_ints (fp, 5, idata);
        }
        value = 357.0;
        write_floats (fp, 1, &value);
    }

    for (nz = 0; nz < nZones; nz++) {
        printf ("  zone %d...", nz+1);
        fflush (stdout);
        read_zone_grid (nz+1);
        ne = 0;
        type = 2;
        nn = (int)Zones[nz].nverts;
        var = (float *) malloc (nn * sizeof(float));
        if (NULL == var)
            FATAL (NULL, "malloc failed for temp float array");
        if (Zones[nz].type == CGNS_ENUMV(Unstructured))
            elems = volume_elements (nz, &ne, &type);

        if (ascii) {
            if (Zones[nz].type == CGNS_ENUMV(Structured))
                fprintf (fp, "\nZONE T=\"%s\", I=%d, J=%d, K=%d, F=BLOCK\n",
                    Zones[nz].name, (int)Zones[nz].dim[0],
                    (int)Zones[nz].dim[1], (int)Zones[nz].dim[2]);
            else
                fprintf (fp, "\nZONE T=\"%s\", N=%d, E=%d, F=FEBLOCK, ET=%s\n",
                    Zones[nz].name, nn, (int)ne, type == 2 ? "TETRAHEDRON" : "BRICK");
        }
        else {
            value = 299.0;
            write_floats (fp, 1, &value);
            i = 0;
            write_ints (fp, 1, &i);
            i = 1;
            for (n = 0; n < nv; n++)
                write_ints (fp, 1, &i);
        }

        for (n = 0; n < nn; n++)
            var[n] = (float)Zones[nz].verts[n].x;
        write_floats (fp, nn, var);
        for (n = 0; n < nn; n++)
            var[n] = (float)Zones[nz].verts[n].y;
        write_floats (fp, nn, var);
        for (n = 0; n < nn; n++)
            var[n] = (float)Zones[nz].verts[n].z;
        write_floats (fp, nn, var);

        if (usesol) {
            read_solution_field (nz+1, usesol, 0);
            sol = &Zones[nz].sols[usesol-1];
            if (sol->location != CGNS_ENUMV(Vertex))
                cell_vertex_solution (nz+1, usesol, weighting);
            for (nv = 0; nv < sol->nflds; nv++) {
                for (n = 0; n < nn; n++)
                    var[n] = (float)sol->flds[nv].data[n];
                write_floats (fp, nn, var);
            }
        }

        free (var);

        if (Zones[nz].type == CGNS_ENUMV(Unstructured)) {
            if (!ascii) {
                i = 0;
                write_ints (fp, 1, &i);
            }
            nn = 1 << type;
            for (i = 0, n = 0; n < ne; n++, i += nn)
                write_ints (fp, nn, &elems[i]);
            free (elems);
        }
        puts ("done");
    }

    fclose (fp);
    cg_close (cgnsfn);
    return 0;
}
Ejemplo n.º 6
0
static int *volume_elements (int nz, cgsize_t *nelems, int *elemtype)
{
    int i, np, ns, nt, et;
    int *elems;
    cgsize_t n, nn, ne;
    ZONE *z = &Zones[nz];

    count_elements (nz, &ne, &nt);
    *nelems = ne;
    *elemtype = nt;

    elems = (int *) malloc ((size_t)ne * (1 << nt) * sizeof(int));
    if (NULL == elems)
        FATAL (NULL, "malloc failed for elements");

    for (np = 0, ns = 0; ns < z->nesets; ns++) {
        ne = z->esets[ns].end - z->esets[ns].start + 1;
        et = z->esets[ns].type;
        if (et < CGNS_ENUMV(TETRA_4) || et > CGNS_ENUMV(MIXED)) continue;
        for (n = 0, nn = 0; nn < ne; nn++) {
            if (z->esets[ns].type == CGNS_ENUMV(MIXED))
                et = (int)z->esets[ns].conn[n++];
            switch (et) {
                case CGNS_ENUMV(TETRA_4):
                case CGNS_ENUMV(TETRA_10):
                    if (nt == 2) {
                        for (i = 0; i < 4; i++)
                            elems[np++] = (int)z->esets[ns].conn[n+i];
                    }
                    else {
                        for (i = 0; i < 3; i++)
                            elems[np++] = (int)z->esets[ns].conn[n+i];
                        elems[np++] = (int)z->esets[ns].conn[n+2];
                        for (i = 0; i < 4; i++)
                            elems[np++] = (int)z->esets[ns].conn[n+3];
                    }
                    break;
                case CGNS_ENUMV(PYRA_5):
                case CGNS_ENUMV(PYRA_14):
                    for (i = 0; i < 4; i++)
                        elems[np++] = (int)z->esets[ns].conn[n+i];
                    for (i = 0; i < 4; i++)
                        elems[np++] = (int)z->esets[ns].conn[n+4];
                    break;
                case CGNS_ENUMV(PENTA_6):
                case CGNS_ENUMV(PENTA_15):
                case CGNS_ENUMV(PENTA_18):
                    for (i = 0; i < 3; i++)
                        elems[np++] = (int)z->esets[ns].conn[n+i];
                    elems[np++] = (int)z->esets[ns].conn[n+2];
                    for (i = 3; i < 6; i++)
                        elems[np++] = (int)z->esets[ns].conn[n+i];
                    elems[np++] = (int)z->esets[ns].conn[n+5];
                    break;
                case CGNS_ENUMV(HEXA_8):
                case CGNS_ENUMV(HEXA_20):
                case CGNS_ENUMV(HEXA_27):
                    for (i = 0; i < 8; i++)
                        elems[np++] = (int)z->esets[ns].conn[n+i];
                    break;
            }
            n += element_node_counts[et];
        }
    }

    return elems;
}
Ejemplo n.º 7
0
void
cmd_cnew(const char *e_line, command *commands)
{
	xmlNodePtr	db_node = NULL;
	xmlChar		*name = NULL, *description = NULL;

	char			*created = NULL;
	char			*line = NULL;
	unsigned long int	idx = 0;
#ifndef _READLINE
	int		e_count = 0;
#endif


	/* this is unused in this function */
	commands = NULL;

	if ((idx = count_elements(keychain->parent->children)) >= ITEMS_MAX - 1) {
		dprintf(STDERR_FILENO, "ERROR: Can not create the keychain: maximum number of keychains reached, %lu.\n", ITEMS_MAX - 1);

		return;
	}


	line = strdup(e_line); malloc_check(line);

	strtok(line, " ");		/* remove the command from the line */
	name = BAD_CAST strtok(NULL, " ");	/* assign the command's first parameter (name) */
	if (name) {
		name = xmlStrdup(name);
	} else {	/* if we didn't get a name as a parameter */
		strlcpy(prompt_context, "NEW keychain name", sizeof(prompt_context));

#ifndef _READLINE
		/* disable history temporarily */
		if (el_set(e, EL_HIST, history, NULL) != 0) {
			perror("ERROR: el_set(EL_HIST)");
		}

		e_line = el_gets(e, &e_count);

		/* re-enable history */
		if (el_set(e, EL_HIST, history, eh) != 0) {
			perror("ERROR: el_set(EL_HIST)");
		}
#else
		e_line = readline(prompt_str());
#endif
		if (e_line) {
			name = xmlStrdup(BAD_CAST e_line); malloc_check(name);
#ifndef _READLINE
			name[xmlStrlen(name) - 1] = '\0'; /* remove the newline */
#else
			free((char *)e_line); e_line = NULL;
#endif
		} else {
#ifndef _READLINE
			el_reset(e);
#endif
			strlcpy(prompt_context, "", sizeof(prompt_context));

			return;
		}
	}

	free(line); line = NULL;

	strlcpy(prompt_context, "NEW keychain description", sizeof(prompt_context));

#ifndef _READLINE
	/* disable history temporarily */
	if (el_set(e, EL_HIST, history, NULL) != 0) {
		perror("ERROR: el_set(EL_HIST)");
	}

	e_line = el_gets(e, &e_count);

	/* re-enable history */
	if (el_set(e, EL_HIST, history, eh) != 0) {
		perror("ERROR: el_set(EL_HIST)");
	}
#else
	e_line = readline(prompt_str());
#endif
	if (e_line) {
		description = xmlStrdup(BAD_CAST e_line); malloc_check(description);
#ifndef _READLINE
		description[xmlStrlen(description) - 1] = '\0'; /* remove the newline */
#else
		free((char *)e_line); e_line = NULL;
#endif
	} else {
#ifndef _READLINE
		el_reset(e);
#endif
		strlcpy(prompt_context, "", sizeof(prompt_context));

		return;
	}

	strlcpy(prompt_context, "", sizeof(prompt_context));


	db_node = find_keychain(name, 1);
	if (!db_node) {
		created = malloc(TIME_MAXLEN); malloc_check(created);
		snprintf(created, TIME_MAXLEN, "%d", (int)time(NULL));

		/* XXX reloading a saved document inserts a 'text' element between each visible node (why?)
		 * so we must reproduce this */
		xmlAddChild(keychain->parent, xmlNewText(BAD_CAST "\t"));

		db_node = xmlNewChild(keychain->parent, NULL, BAD_CAST "keychain", NULL);

		xmlNewProp(db_node, BAD_CAST "name", name);
		xmlNewProp(db_node, BAD_CAST "created", BAD_CAST created);
		xmlNewProp(db_node, BAD_CAST "modified", BAD_CAST created);
		xmlNewProp(db_node, BAD_CAST "description", description);

		/* make the XML document prettttyyy */
		xmlAddChild(db_node, xmlNewText(BAD_CAST "\n\t"));

		printf("Created keychain: %lu. %s\n", idx, name);

		/* XXX reloading a saved document inserts a 'text' element between each visible node (why?)
		 * so we must reproduce this */
		xmlAddChild(keychain->parent, xmlNewText(BAD_CAST "\n"));

		db_params.dirty = 1;
	} else {
		printf("Keychain '%s' already exists!\n", name);
	}

	xmlFree(name); name = NULL;
	xmlFree(description); description = NULL;
	free(created); created = NULL;
} /* cmd_cnew() */