Пример #1
0
void repo_destroy(repo* rep) {
	if (rep->mountpt)
		gen_free(rep->mountpt);
	if (rep->repo)
		gen_free(rep->repo);
	rwlock_destroy(&rep->fslock);
	mutex_destroy(&rep->idlock);
}
Пример #2
0
int repo_commit(repo* rep, const char* branchpath) {
	int err = 0;
	char* srcpath = gen_malloc(MAX_PATH_LEN);
	if (!srcpath) {
		err = -ENOMEM;
		goto exit;
	}
	char* dstpath = gen_malloc(MAX_PATH_LEN);
	if (!dstpath) {
		err = -ENOMEM;
		goto exit;
	}

	// Quiesce all FS activity and wait for outstanding meta-data updates
	// to the underlying FS to flush.
	rwlock_wrlock(&rep->fslock);
	sync();

	// All objects in stage are now frozen, they can be moved into
	// the globally shared object stores.
	gen_sprintf(srcpath, "%s/stage/objs", branchpath);
	gen_sprintf(dstpath, "%s/objs", rep->repo);
	err = moveobjects(dstpath, srcpath);
	if (err)
		goto exit_unlock;

	// Now move the staged root into the set of old roots
	uint64_t id = repo_newid(rep);
	gen_sprintf(srcpath, "%s/stage/root", branchpath);
	gen_sprintf(dstpath, "%s/oldroots/i%lu", branchpath, id);
	err = gen_rename(srcpath, dstpath);

exit_unlock:
	rwlock_wrunlock(&rep->fslock);
exit:
	if (srcpath)
		gen_free(srcpath);
	if (dstpath)
		gen_free(dstpath);
	return err;
}
Пример #3
0
static int	put_fits
(
    pfi		char_out,
    int		a[],
    int		nx,
    int		ny 
)
{
    void	pr_foramt_message();

    int		n;
    short	*sa;
    int		status;
 

    /*
     * write data with swapping
     */

    PR_CHECK( put_raw( char_out, a, nx, ny, TRUE) );


    /*
     * add zeroes to get up to multiple of 2880 bytes
     * number of padding short ints to write is between 0 and 1439
     */

    n = 1439 - ( ( nx * ny - 1 ) % 1440 );
    status = PR_SUCCESS;
    if ( n > 0 )
    {
	/*
	 * allocate a block of zeros
	 */

	PR_CHECK_NULL( sa = (short *) calloc( n , sizeof( short ) ) );
	status = char_out( sa, n * sizeof( short ) );
	gen_free( sa );
    }
    return( status );
}
Пример #4
0
static int	put_raw
(
    pfi		char_out,
    int		a[],
    int		nx,
    int		ny,
    boolean	swap 
)
{
    void	h_swap_bytes();
    boolean	test_swap();

    int		i;
    int		j;
    int		k;
    short	*sa;		/* Working array for swaped data.	*/
    boolean	tswap;		/* is byte swaping required?		*/
    int		v;


    /*
     * see if byte-swapping will be needed
     */

    if (swap) 
    {
	tswap = test_swap();
    } 
    else 
    {
	tswap = 0;
    }


    /*
     * write a row at a time to minimize page faulting problems
     */

    PR_CHECK_NULL( sa = short_alloc( ny ) );

    for ( i = 0; i < nx ; i++ ) 
    {
	k = i * ny;

	for ( j = 0; j < ny; j++) 
	{
	    /*
	     * force value into 16-bit integer range
	     */

	    v = a[k++];
	    if (v < -32768) 
	    {
		sa[j] = -32768;
	    } 
	    else if (v > 32767) 
	    {
		sa[j] = 32767;
	    } 
	    else 
	    {
		sa[j] = v;
	    }
	}

	if ( tswap ) 
	{
	    h_swap_bytes( sa, ny * sizeof( short ) );
	}
	PR_CHECK( char_out( sa, ny * sizeof( short ) ) );
    }
    gen_free(sa);

    return( PR_SUCCESS );
}
Пример #5
0
void* 
resolve_thread( void *data )
{
	method_list_t 		*m_list;
	mc_t 				*mc;
	cs_t				*cs;
	method_prototype 	method;
	char				*cs_dboid;
	resolve_function 	res_func;
	ev_queue_t			*res_queue;
	png_t 				*conf;
	gen_t 				*g;
	obj_t 				*obj;
	
	conf = (png_t*) data;
	res_queue = &conf->res_queue;
	m_list = conf->m_list;
	
	/* Set default resolve function */
	res_func = &resolve;
	
	printf( "[Resolve Thread] Started.\n" );
	
	while( 1 )
	{
		/* locks the signal variable and wait */
		/*
		pthread_mutex_lock( conf->resolve_sig_lock );
		pthread_cond_wait( conf->resolve_sig, conf->resolve_sig_lock  );
		pthread_mutex_unlock( conf->resolve_sig_lock );
		*/
		
		ev_queue_listen( res_queue );
		
		/* Get what conflict set that send the signal */
		cs_dboid = ev_queue_pop( res_queue );
		
		cs = cs_list_find( &((png_t*)data)->cs_list, cs_dboid );
		
		/* Fetch a generation that needs to be resolved */
		g = cs_pop( cs );
		if( g != NULL )
		{
			/* Fetch the object from the storage */
			imdb_fetch( &conf->stable_db, "obj", (void*)&obj );
			
			/* Perform some conflict resolution */
			mc = res_func( g );
			
			/* Fetch the function pointer */
			method = method_list_find( m_list, mc->method_name );
			
			/* Perform the method on the object */
			method( obj, mc->params, mc->num_param );
			
			/* Put the object back */
			imdb_store( &conf->stable_db, "obj", obj, sizeof( obj_t ) );
			
			printf( "Conflict resolved generation %d\n", g->num );
			
			gen_free( g );

			free( obj );
		}		
	}
	
	return NULL;
}
Пример #6
0
int
main(int argc, char *argv[])
{
    FILE *fp;
    char *input_filename = argv[1];
    char *output_filename = _PATH_PARSER;
    char *conf_filename = _PATH_SQUID_CONF;
    int linenum = 0;
    Entry *entries = NULL;
    Entry *curr = NULL;
    enum State state;
    int rc = 0;
    char *ptr = NULL;
#ifdef _SQUID_OS2_
    const char *rmode = "rt";
#else
    const char *rmode = "r";
#endif

    /*-------------------------------------------------------------------*
     * Parse input file
     *-------------------------------------------------------------------*/

    /* Open input file */
    if ((fp = fopen(input_filename, rmode)) == NULL) {
	perror(input_filename);
	exit(1);
    }
    state = sSTART;
    while (feof(fp) == 0 && state != sEXIT) {
	char buff[MAX_LINE];
	char *t;
	if (NULL == fgets(buff, MAX_LINE, fp))
	    break;
	linenum++;
	if ((t = strchr(buff, '\n')))
	    *t = '\0';
	switch (state) {
	case sSTART:
	    if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) {
		/* ignore empty and comment lines */
		(void) 0;
	    } else if (!strncmp(buff, "NAME:", 5)) {
		char *name;
		if ((name = strtok(buff + 5, WS)) == NULL) {
		    printf("Error in input file\n");
		    exit(1);
		}
		curr = calloc(1, sizeof(Entry));
		curr->name = xstrdup(name);
		state = s1;
	    } else if (!strcmp(buff, "EOF")) {
		state = sEXIT;
	    } else if (!strcmp(buff, "COMMENT_START")) {
		curr = calloc(1, sizeof(Entry));
		curr->name = xstrdup("comment");
		curr->loc = xstrdup("none");
		state = sDOC;
	    } else {
		printf("Error on line %d\n", linenum);
		printf("--> %s\n", buff);
		exit(1);
	    }
	    break;

	case s1:
	    if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) {
		/* ignore empty and comment lines */
		(void) 0;
	    } else if (!strncmp(buff, "COMMENT:", 8)) {
		ptr = buff + 8;
		while (xisspace(*ptr))
		    ptr++;
		curr->comment = xstrdup(ptr);
	    } else if (!strncmp(buff, "DEFAULT:", 8)) {
		ptr = buff + 8;
		while (xisspace(*ptr))
		    ptr++;
		curr->default_value = xstrdup(ptr);
	    } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) {
		ptr = buff + 16;
		while (xisspace(*ptr))
		    ptr++;
		curr->default_if_none = xstrdup(ptr);
	    } else if (!strncmp(buff, "LOC:", 4)) {
		if ((ptr = strtok(buff + 4, WS)) == NULL) {
		    printf("Error on line %d\n", linenum);
		    exit(1);
		}
		curr->loc = xstrdup(ptr);
	    } else if (!strncmp(buff, "TYPE:", 5)) {
		if ((ptr = strtok(buff + 5, WS)) == NULL) {
		    printf("Error on line %d\n", linenum);
		    exit(1);
		}
		curr->type = xstrdup(ptr);
	    } else if (!strncmp(buff, "IFDEF:", 6)) {
		if ((ptr = strtok(buff + 6, WS)) == NULL) {
		    printf("Error on line %d\n", linenum);
		    exit(1);
		}
		curr->ifdef = xstrdup(ptr);
	    } else if (!strcmp(buff, "DOC_START")) {
		state = sDOC;
	    } else if (!strcmp(buff, "DOC_NONE")) {
		/* add to list of entries */
		curr->next = entries;
		entries = curr;
		state = sSTART;
	    } else {
		printf("Error on line %d\n", linenum);
		exit(1);
	    }
	    break;

	case sDOC:
	    if (!strcmp(buff, "DOC_END") || !strcmp(buff, "COMMENT_END")) {
		Line *head = NULL;
		Line *line = curr->doc;
		/* reverse order of doc lines */
		while (line != NULL) {
		    Line *tmp;
		    tmp = line->next;
		    line->next = head;
		    head = line;
		    line = tmp;
		}
		curr->doc = head;
		/* add to list of entries */
		curr->next = entries;
		entries = curr;
		state = sSTART;
	    } else if (!strcmp(buff, "NOCOMMENT_START")) {
		state = sNOCOMMENT;
	    } else {
		Line *line = calloc(1, sizeof(Line));
		line->data = xstrdup(buff);
		line->next = curr->doc;
		curr->doc = line;
	    }
	    break;

	case sNOCOMMENT:
	    if (!strcmp(buff, "NOCOMMENT_END")) {
		Line *head = NULL;
		Line *line = curr->nocomment;
		/* reverse order of lines */
		while (line != NULL) {
		    Line *tmp;
		    tmp = line->next;
		    line->next = head;
		    head = line;
		    line = tmp;
		}
		curr->nocomment = head;
		state = sDOC;
	    } else {
		Line *line = calloc(1, sizeof(Line));
		line->data = xstrdup(buff);
		line->next = curr->nocomment;
		curr->nocomment = line;
	    }
	    break;

	case sEXIT:
	    assert(0);		/* should never get here */
	    break;
	}
    }
    if (state != sEXIT) {
	printf("Error unexpected EOF\n");
	exit(1);
    } else {
	/* reverse order of entries */
	Entry *head = NULL;

	while (entries != NULL) {
	    Entry *tmp;

	    tmp = entries->next;
	    entries->next = head;
	    head = entries;
	    entries = tmp;
	}
	entries = head;
    }
    fclose(fp);

    /*-------------------------------------------------------------------*
     * Generate default_all()
     * Generate parse_line()
     * Generate dump_config()
     * Generate free_all()
     * Generate example squid.conf file
     *-------------------------------------------------------------------*/

    /* Open output x.c file */
    if ((fp = fopen(output_filename, "w")) == NULL) {
	perror(output_filename);
	exit(1);
    }
    fprintf(fp,
	"/*\n"
	" * Generated automatically from %s by %s\n"
	" *\n"
	" * Abstract: This file contains routines used to configure the\n"
	" *           variables in the squid server.\n"
	" */\n"
	"\n",
	input_filename, argv[0]
	);
    rc = gen_default(entries, fp);
    gen_default_if_none(entries, fp);
    gen_parse(entries, fp);
    gen_dump(entries, fp);
    gen_free(entries, fp);
    fclose(fp);

    /* Open output x.conf file */
    if ((fp = fopen(conf_filename, "w")) == NULL) {
	perror(conf_filename);
	exit(1);
    }
    gen_conf(entries, fp);
    fclose(fp);

    return (rc);
}
Пример #7
0
int
main(int argc, char *argv[])
{
    FILE *fp;
    char *input_filename = argv[1];
    const char *output_filename = _PATH_PARSER;
    const char *conf_filename = _PATH_SQUID_CONF;
    const char *conf_filename_short = _PATH_SQUID_CONF_SHORT;
    const char *type_depend = argv[2];
    int linenum = 0;
    Entry *entries = NULL;
    Entry *curr = NULL;
    Type *types = NULL;
    enum State state;
    int rc = 0;
    char *ptr = NULL;
#ifdef _SQUID_OS2_
    const char *rmode = "rt";
#else
    const char *rmode = "r";
#endif
    char buff[MAX_LINE];

    if (argc != 3)
	usage(argv[0]);

    input_filename = argv[1];
    type_depend = argv[2];

    /*-------------------------------------------------------------------*
     * Parse type dependencies
     *-------------------------------------------------------------------*/
    if ((fp = fopen(type_depend, rmode)) == NULL) {
	perror(input_filename);
	exit(1);
    }
    while ((NULL != fgets(buff, MAX_LINE, fp))) {
	const char *type = strtok(buff, WS);
	const char *dep;
	Type *t;
	if (!type || type[0] == '#')
	    continue;
	t = (Type *) xcalloc(1, sizeof(*t));
	t->name = xstrdup(type);
	while ((dep = strtok(NULL, WS)) != NULL) {
	    TypeDep *d = (TypeDep *) xcalloc(1, sizeof(*d));
	    d->name = xstrdup(dep);
	    d->next = t->depend;
	    t->depend = d;
	}
	t->next = types;
	types = t;
    }
    fclose(fp);

    /*-------------------------------------------------------------------*
     * Parse input file
     *-------------------------------------------------------------------*/

    /* Open input file */
    if ((fp = fopen(input_filename, rmode)) == NULL) {
	perror(input_filename);
	exit(1);
    }
#ifdef _SQUID_WIN32_
    setmode(fileno(fp), O_TEXT);
#endif
    state = sSTART;
    while (feof(fp) == 0 && state != sEXIT) {
	char *t;
	if (NULL == fgets(buff, MAX_LINE, fp))
	    break;
	linenum++;
	if ((t = strchr(buff, '\n')))
	    *t = '\0';
	switch (state) {
	case sSTART:
	    if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) {
		/* ignore empty and comment lines */
		(void) 0;
	    } else if (!strncmp(buff, "NAME:", 5)) {
		char *name, *aliasname;
		if ((name = strtok(buff + 5, WS)) == NULL) {
		    printf("Error in input file\n");
		    exit(1);
		}
		curr = xcalloc(1, sizeof(Entry));
		curr->name = xstrdup(name);
		while ((aliasname = strtok(NULL, WS)) != NULL) {
		    EntryAlias *alias = xcalloc(1, sizeof(EntryAlias));
		    alias->next = curr->alias;
		    alias->name = xstrdup(aliasname);
		    curr->alias = alias;
		}
		state = s1;
	    } else if (!strcmp(buff, "EOF")) {
		state = sEXIT;
	    } else if (!strcmp(buff, "COMMENT_START")) {
		curr = xcalloc(1, sizeof(Entry));
		curr->name = xstrdup("comment");
		curr->loc = xstrdup("none");
		state = sDOC;
	    } else {
		printf("Error on line %d\n", linenum);
		printf("--> %s\n", buff);
		exit(1);
	    }
	    break;

	case s1:
	    if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) {
		/* ignore empty and comment lines */
		(void) 0;
	    } else if (!strncmp(buff, "COMMENT:", 8)) {
		ptr = buff + 8;
		while (xisspace(*ptr))
		    ptr++;
		curr->comment = xstrdup(ptr);
	    } else if (!strncmp(buff, "DEFAULT:", 8)) {
		ptr = buff + 8;
		while (xisspace(*ptr))
		    ptr++;
		curr->default_value = xstrdup(ptr);
	    } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) {
		ptr = buff + 16;
		while (xisspace(*ptr))
		    ptr++;
		lineAdd(&curr->default_if_none, ptr);
	    } else if (!strncmp(buff, "LOC:", 4)) {
		if ((ptr = strtok(buff + 4, WS)) == NULL) {
		    printf("Error on line %d\n", linenum);
		    exit(1);
		}
		curr->loc = xstrdup(ptr);
	    } else if (!strncmp(buff, "TYPE:", 5)) {
		if ((ptr = strtok(buff + 5, WS)) == NULL) {
		    printf("Error on line %d\n", linenum);
		    exit(1);
		}
		/* hack to support arrays, rather than pointers */
		if (0 == strcmp(ptr + strlen(ptr) - 2, "[]")) {
		    curr->array_flag = 1;
		    *(ptr + strlen(ptr) - 2) = '\0';
		}
		checkDepend(curr->name, ptr, types, entries);
		curr->type = xstrdup(ptr);
	    } else if (!strncmp(buff, "IFDEF:", 6)) {
		if ((ptr = strtok(buff + 6, WS)) == NULL) {
		    printf("Error on line %d\n", linenum);
		    exit(1);
		}
		curr->ifdef = xstrdup(ptr);
	    } else if (!strcmp(buff, "DOC_START")) {
		state = sDOC;
	    } else if (!strcmp(buff, "DOC_NONE")) {
		/* add to list of entries */
		curr->next = entries;
		entries = curr;
		state = sSTART;
	    } else {
		printf("Error on line %d\n", linenum);
		exit(1);
	    }
	    break;

	case sDOC:
	    if (!strcmp(buff, "DOC_END") || !strcmp(buff, "COMMENT_END")) {
		Line *head = NULL;
		Line *line = curr->doc;
		/* reverse order of doc lines */
		while (line != NULL) {
		    Line *tmp;
		    tmp = line->next;
		    line->next = head;
		    head = line;
		    line = tmp;
		}
		curr->doc = head;
		/* add to list of entries */
		curr->next = entries;
		entries = curr;
		state = sSTART;
	    } else if (!strcmp(buff, "NOCOMMENT_START")) {
		state = sNOCOMMENT;
	    } else {
		Line *line = xcalloc(1, sizeof(Line));
		line->data = xstrdup(buff);
		line->next = curr->doc;
		curr->doc = line;
	    }
	    break;

	case sNOCOMMENT:
	    if (!strcmp(buff, "NOCOMMENT_END")) {
		Line *head = NULL;
		Line *line = curr->nocomment;
		/* reverse order of lines */
		while (line != NULL) {
		    Line *tmp;
		    tmp = line->next;
		    line->next = head;
		    head = line;
		    line = tmp;
		}
		curr->nocomment = head;
		state = sDOC;
	    } else {
		Line *line = xcalloc(1, sizeof(Line));
		line->data = xstrdup(buff);
		line->next = curr->nocomment;
		curr->nocomment = line;
	    }
	    break;

	case sEXIT:
	    assert(0);		/* should never get here */
	    break;
	}
    }
    if (state != sEXIT) {
	printf("Error unexpected EOF\n");
	exit(1);
    } else {
	/* reverse order of entries */
	Entry *head = NULL;

	while (entries != NULL) {
	    Entry *tmp;

	    tmp = entries->next;
	    entries->next = head;
	    head = entries;
	    entries = tmp;
	}
	entries = head;
    }
    fclose(fp);

    /*-------------------------------------------------------------------*
     * Generate default_all()
     * Generate parse_line()
     * Generate dump_config()
     * Generate free_all()
     * Generate example squid.conf.default file
     *-------------------------------------------------------------------*/

    /* Open output x.c file */
    if ((fp = fopen(output_filename, "w")) == NULL) {
	perror(output_filename);
	exit(1);
    }
#ifdef _SQUID_WIN32_
    setmode(fileno(fp), O_TEXT);
#endif
    fprintf(fp,
	"/*\n"
	" * Generated automatically from %s by %s\n"
	" *\n"
	" * Abstract: This file contains routines used to configure the\n"
	" *           variables in the squid server.\n"
	" */\n"
	"\n",
	input_filename, argv[0]
	);
    rc = gen_default(entries, fp);
    gen_default_if_none(entries, fp);
    gen_parse(entries, fp);
    gen_dump(entries, fp);
    gen_free(entries, fp);
    fclose(fp);

    /* Open output x.conf file */
    if ((fp = fopen(conf_filename, "w")) == NULL) {
	perror(conf_filename);
	exit(1);
    }
#ifdef _SQUID_WIN32_
    setmode(fileno(fp), O_TEXT);
#endif
    gen_conf(entries, fp, 1);
    fclose(fp);

    if ((fp = fopen(conf_filename_short, "w")) == NULL) {
	perror(conf_filename);
	exit(1);
    }
#ifdef _SQUID_WIN32_
    setmode(fileno(fp), O_TEXT);
#endif
    gen_conf(entries, fp, 0);
    fclose(fp);
    return (rc);
}
Пример #8
0
int repo_new(repo* rep, const char* newname) {
	int err = 0;
	// New branches track empty directories. The branch has no old roots.
	// It is staging and the current root being staged points to the only
	// object already staged: an empty directory.

	// Create a string buffer for making paths
	char* path = gen_malloc(MAX_PATH_LEN);
	if (!path) {
		err = -ENOMEM;
		goto exit;
	}
	gen_sprintf(path, "%s/br/%s", rep->repo, newname);

	// mkdir <rep->repo>/br/<newname>
	err = gen_mkdir(path, (mode_t)0700);
	if (err)
		goto exit;

	// mkdir <rep->repo>/br/<newname>/oldroots
	strcat(path, "/oldroots");
	err = gen_mkdir(path, (mode_t)0700);
	if (err)
		goto exit;

	// mkdir <rep->repo>/br/<newname>/stage
	gen_sprintf(path, "%s/br/%s/stage", rep->repo, newname);
	err = gen_mkdir(path, (mode_t)0700);
	if (err)
		goto exit;

	// mkdir <rep->repo>/br/<newname>/stage/objs
	strcat(path, "/objs");
	err = gen_mkdir(path, (mode_t)0700);
	if (err)
		goto exit;

	// mkdir <rep->repo>/br/<newname>/stage/objs/<nextid>
	uint64_t nextid = repo_newid(rep);
	gen_sprintf(path, "%s/br/%s/%lu", rep->repo, newname, nextid);
	err = gen_mkdir(path, (mode_t)0700);
	if (err)
		goto exit;

	// echo `repo_newid` > <rep->repo>/br/<newname>/stage/root
	gen_sprintf(path, "%s/br/%s/root", rep->repo, newname);
	int fd = gen_open(path, O_CREAT|O_RDWR, (mode_t)0700);
	if (fd < 0) {
		err = fd;
		goto exit;
	}
	gen_sprintf(path, "%lu\n", nextid);
	int nbytes;
	err = gen_write(fd, path, strlen(path), &nbytes);
	if (err)
		goto exit;
	gen_close(fd);
	sync();
exit:
	gen_free(path);
	return err;
}
Пример #9
0
int
main(int argc, char *argv[])
{
  gen_workspace *gen_workspace_p;
  lapack_workspace *lapack_workspace_p;
  size_t N;
  int c;
  int lower;
  int upper;
  int incremental;
  size_t nmat;
  gsl_matrix *A, *B;
  gsl_rng *r;
  int s;
  int compute_schur;
  size_t i;

  gsl_ieee_env_setup();
  gsl_rng_env_setup();

  N = 30;
  lower = -10;
  upper = 10;
  incremental = 0;
  nmat = 0;
  compute_schur = 0;

  while ((c = getopt(argc, argv, "ic:n:l:u:z")) != (-1))
    {
      switch (c)
        {
          case 'i':
            incremental = 1;
            break;

          case 'n':
            N = strtol(optarg, NULL, 0);
            break;

          case 'l':
            lower = strtol(optarg, NULL, 0);
            break;

          case 'u':
            upper = strtol(optarg, NULL, 0);
            break;

          case 'c':
            nmat = strtoul(optarg, NULL, 0);
            break;

          case 'z':
            compute_schur = 1;
            break;

          case '?':
          default:
            printf("usage: %s [-i] [-z] [-n size] [-l lower-bound] [-u upper-bound] [-c num]\n", argv[0]);
            exit(1);
            break;
        } /* switch (c) */
    }

  A = gsl_matrix_alloc(N, N);
  B = gsl_matrix_alloc(N, N);
  gen_workspace_p = gen_alloc(N, compute_schur);
  lapack_workspace_p = lapack_alloc(N);

  r = gsl_rng_alloc(gsl_rng_default);

  if (incremental)
    {
      make_start_matrix(A, lower);

      /* we need B to be non-singular */
      make_random_integer_matrix(B, r, lower, upper);
    }

  fprintf(stderr, "testing N = %d", N);
  if (incremental)
    fprintf(stderr, " incrementally");
  else
    fprintf(stderr, " randomly");

  fprintf(stderr, " on element range [%d, %d]", lower, upper);

  if (compute_schur)
    fprintf(stderr, ", with Schur vectors");

  fprintf(stderr, "\n");

  while (1)
    {
      if (nmat && (count >= nmat))
        break;

      ++count;

      if (!incremental)
        {
          make_random_matrix(A, r, lower, upper);
          make_random_matrix(B, r, lower, upper);
        }
      else
        {
          s = inc_matrix(A, lower, upper);
          if (s)
            break; /* all done */

          make_random_integer_matrix(B, r, lower, upper);
        }

      /*if (count != 89120)
        continue;*/

      /* make copies of matrices */
      gsl_matrix_memcpy(gen_workspace_p->A, A);
      gsl_matrix_memcpy(gen_workspace_p->B, B);
      gsl_matrix_transpose_memcpy(lapack_workspace_p->A, A);
      gsl_matrix_transpose_memcpy(lapack_workspace_p->B, B);

      /* compute eigenvalues with LAPACK */
      s = lapack_proc(lapack_workspace_p);

      if (s != GSL_SUCCESS)
        {
          printf("LAPACK failed, case %lu\n", count);
          exit(1);
        }

#if 0
      print_matrix(A, "A");
      print_matrix(B, "B");
      gsl_matrix_transpose(lapack_workspace_p->A);
      gsl_matrix_transpose(lapack_workspace_p->B);
      print_matrix(lapack_workspace_p->A, "S_lapack");
      print_matrix(lapack_workspace_p->B, "T_lapack");
#endif

      /* compute eigenvalues with GSL */
      s = gen_proc(gen_workspace_p);

      if (s != GSL_SUCCESS)
        {
          printf("=========== CASE %lu ============\n", count);
          printf("Failed to converge: found %u eigenvalues\n",
                 gen_workspace_p->n_evals);
          print_matrix(A, "A");
          print_matrix(B, "B");
          print_matrix(gen_workspace_p->A, "Af");
          print_matrix(gen_workspace_p->B, "Bf");
          print_matrix(lapack_workspace_p->A, "Ae");
          print_matrix(lapack_workspace_p->B, "Be");
          exit(1);
        }

#if 0
      print_matrix(gen_workspace_p->A, "S_gsl");
      print_matrix(gen_workspace_p->B, "T_gsl");
#endif

      /* compute alpha / beta vectors */
      for (i = 0; i < N; ++i)
        {
          double beta;
          gsl_complex alpha, z;

          beta = gsl_vector_get(gen_workspace_p->beta, i);
          if (beta == 0.0)
            GSL_SET_COMPLEX(&z, GSL_POSINF, GSL_POSINF);
          else
            {
              alpha = gsl_vector_complex_get(gen_workspace_p->alpha, i);
              z = gsl_complex_div_real(alpha, beta);
            }

          gsl_vector_complex_set(gen_workspace_p->evals, i, z);

          beta = gsl_vector_get(lapack_workspace_p->beta, i);
          GSL_SET_COMPLEX(&alpha,
                          lapack_workspace_p->alphar[i],
                          lapack_workspace_p->alphai[i]);

          if (beta == 0.0)
            GSL_SET_COMPLEX(&z, GSL_POSINF, GSL_POSINF);
          else
            z = gsl_complex_div_real(alpha, beta);

          gsl_vector_complex_set(lapack_workspace_p->evals, i, z);
          gsl_vector_complex_set(lapack_workspace_p->alpha, i, alpha);
        }

#if 0
      gsl_sort_vector(gen_workspace_p->beta);
      gsl_sort_vector(lapack_workspace_p->beta);
      sort_complex_vector(gen_workspace_p->alpha);
      sort_complex_vector(lapack_workspace_p->alpha);

      s = test_alpha(gen_workspace_p->alpha,
                     lapack_workspace_p->alpha,
                     A,
                     B,
                     "gen",
                     "lapack");
      s = test_beta(gen_workspace_p->beta,
                    lapack_workspace_p->beta,
                    A,
                    B,
                    "gen",
                    "lapack");
#endif
#if 1
      sort_complex_vector(gen_workspace_p->evals);
      sort_complex_vector(lapack_workspace_p->evals);

      s = test_evals(gen_workspace_p->evals,
                     lapack_workspace_p->evals,
                     A,
                     B,
                     "gen",
                     "lapack");
#endif

      if (compute_schur)
        {
          test_schur(A,
                     gen_workspace_p->A,
                     gen_workspace_p->Q,
                     gen_workspace_p->Z);
          test_schur(B,
                     gen_workspace_p->B,
                     gen_workspace_p->Q,
                     gen_workspace_p->Z);
        }
    }

  gsl_matrix_free(A);
  gsl_matrix_free(B);
  gen_free(gen_workspace_p);
  lapack_free(lapack_workspace_p);

  if (r)
    gsl_rng_free(r);

  return 0;
} /* main() */