Пример #1
0
int harp_unit_converter_new(const char *from_unit, const char *to_unit, harp_unit_converter **new_unit_converter)
{
    harp_unit_converter *unit_converter;
    ut_unit *from_udunit;
    ut_unit *to_udunit;

    if (parse_unit(from_unit, &from_udunit) != 0)
    {
        return -1;
    }

    if (parse_unit(to_unit, &to_udunit) != 0)
    {
        ut_free(from_udunit);
        return -1;
    }

    if (!ut_are_convertible(from_udunit, to_udunit))
    {
        harp_set_error(HARP_ERROR_UNIT_CONVERSION, "unit '%s' cannot be converted to unit '%s'", from_unit, to_unit);
        ut_free(to_udunit);
        ut_free(from_udunit);
        return -1;
    }

    unit_converter = (harp_unit_converter *)malloc(sizeof(harp_unit_converter));
    if (unit_converter == NULL)
    {
        harp_set_error(HARP_ERROR_OUT_OF_MEMORY, "out of memory (could not allocate %lu bytes) (%s:%u)",
                       sizeof(harp_unit_converter), __FILE__, __LINE__);
        ut_free(to_udunit);
        ut_free(from_udunit);
        return -1;
    }

    unit_converter->converter = ut_get_converter(from_udunit, to_udunit);
    if (unit_converter->converter == NULL)
    {
        handle_udunits_error();
        harp_unit_converter_delete(unit_converter);
        ut_free(to_udunit);
        ut_free(from_udunit);
        return -1;
    }

    ut_free(to_udunit);
    ut_free(from_udunit);

    *new_unit_converter = unit_converter;
    return 0;
}
Пример #2
0
std::unique_ptr<UnitEmitter> single_unit(std::unique_ptr<UnitEmitter> input) {
  trace_time timer("single unit");

  php::Program program;
  program.units.push_back(parse_unit(*input));
  auto const u = borrow(program.units[0]);

  // Single-unit index.
  Index index{u};

  // Visit each method in the unit, except the pseudomain, which isn't
  // supported for anything yet.
  for (auto& c : u->classes) {
    for (auto& m : c->methods) {
      analyze_and_optimize_func(index, Context { u, borrow(m), borrow(c) });
    }
    assert(check(*c));
  }
  for (auto& f : u->funcs) {
    analyze_and_optimize_func(index, Context { u, borrow(f) });
    assert(check(*f));
  }

  assert(check(*u));
  return emit_unit(index, *u);
}
Пример #3
0
std::unique_ptr<php::Program> parse_program(const Container& units) {
  trace_time tracer("parse");
  auto ret = folly::make_unique<php::Program>();
  ret->units = parallel_map(
    units,
    [&] (const std::unique_ptr<UnitEmitter>& ue) {
      return parse_unit(*ue);
    }
  );
  return ret;
}
int main(int argc, char *argv[])
{
	combatant *def, *att[20];
	double hit_chance;
	unsigned damage;
	bool slows;
	unsigned int i;

	if (argc < 3)
		run(argv[1] ? atoi(argv[1]) : 0);

	if (argc < 9) {
		fprintf(stderr,"Usage: %s <damage> <attacks> <hp> <hitprob> [drain,slows,slowed,swarm,firststrike,berserk,maxhp=<num>] <damage> <attacks> <hp> <hitprob> [drain,slows,slowed,berserk,firststrike,swarm,maxhp=<num>] ...",
				argv[0]);
		exit(1);
	}

	def = parse_unit(&argv, &damage, &hit_chance, &slows);
	for (i = 0; argv[1]; ++i)
		att[i] = parse_unit(&argv);
	att[i] = NULL;

	for (i = 0; att[i]; ++i) {
		// In case defender has swarm, effectiveness changes.
		debug(("Fighting next attacker\n"));
		def->set_effectiveness(damage, hit_chance, slows);
		att[i]->fight(*def);
	}

	def->print("Defender", 0);
	for (i = 0; att[i]; ++i)
		att[i]->print("Attacker", 0);

	delete def;
	for (i = 0; att[i]; ++i)
		delete att[i];

	return 0;
}
Пример #5
0
int harp_unit_is_valid(const char *str)
{
    ut_unit *unit;

    if (parse_unit(str, &unit) != 0)
    {
        return 0;
    }

    ut_free(unit);

    return 1;
}
Пример #6
0
/**
 * Compare the two specified units. Units can compare equal even if their string representations are not, e.g. consider
 * "W" (Watt) and "J/s" (Joule per second).
 * \return
 *   \arg \c <0, \a unit_a is considered less than \a unit_b.
 *   \arg \c 0, \a unit_a and \a unit_b are considered equal.
 *   \arg \c >0, \a unit_a is considered greater than \a unit_b.
 */
int harp_unit_compare(const char *unit_a, const char *unit_b)
{
    ut_unit *udunit_a;
    ut_unit *udunit_b;
    int result;

    if (parse_unit(unit_a, &udunit_a) != 0)
    {
        return -1;
    }

    if (parse_unit(unit_b, &udunit_b) != 0)
    {
        ut_free(udunit_a);
        return -1;
    }

    result = ut_compare(udunit_a, udunit_b);

    ut_free(udunit_b);
    ut_free(udunit_a);
    return result;
}
Пример #7
0
void Parameter::file_results    ()
{
    SuperString tmp;
    int    junk;
    size_t size = m_matches.size();
    for (int x=1; x<size; x++)
    {
        tmp = m_matches[x].str();
        SuperString exp = get_numeral_regexpression( m_type );
        int matches = tmp.regex_find( exp );
        if (matches)
            parse_value( tmp, junk );
        else
            parse_unit( tmp );
        matches = tmp.regex_find( m_name );
        if (matches)
            m_name_found = tmp;
    }
}
Пример #8
0
/** main() */
int main(int argc, char *argv[])
{
  const char * fname[2] =
    { NULL, NULL };

  FILE * fp[2] =
    { NULL, NULL };

  compression_t compression[2] =
    { compression_unknown, compression_unknown };

  int rc[2] =
    { -1, -1 };

  int dc[2] =
    { -1, -1 };

  int ru[2] =
    { radians, radians };

  int du[2] =
    { radians, radians };

  ccarray_t * list[2] =
    { NULL, NULL };

  size_t capacity[2] =
    { 15000000, 15000000 };

  char head[2][MAX_HEADER_LENGTH];

  int beverbose = 0;
  int invert_match = 0;

  double r = -1;

  int i;
  size_t size1, size2, pos1, pos2;
  const obj_t * obj1, * obj2;
  //double rcd;

  /* parse command line */

  for ( i = 1; i < argc; ++i )
  {
    if ( strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-help") == 0 ) {
      show_usage(stdout, argc, argv);
      return 0;
    }

    if ( strncmp(argv[i], "rc1=", 4) == 0 )
    {
      if ( sscanf(argv[i] + 4, "%d", &rc[0]) != 1 || rc[0] < 1 ) {
        fprintf(stderr,"Invalid value of %s\n", argv[i]);
        return -1;
      }
    }
    else if ( strncmp(argv[i], "rc2=", 4) == 0 )
    {
      if ( sscanf(argv[i] + 4, "%d", &rc[1]) != 1 || rc[1] < 1 ) {
        fprintf(stderr,"Invalid value of %s\n", argv[i]);
        return -1;
      }
    }
    else if ( strncmp(argv[i], "dc1=", 4) == 0 )
    {
      if ( sscanf(argv[i] + 4, "%d", &dc[0]) != 1 || dc[0] < 1 ) {
        fprintf(stderr,"Invalid value of %s\n", argv[i]);
        return -1;
      }
    }
    else if ( strncmp(argv[i], "dc2=", 4) == 0 )
    {
      if ( sscanf(argv[i] + 4, "%d", &dc[1]) != 1 || dc[1] < 1 ) {
        fprintf(stderr,"Invalid value of %s\n", argv[i]);
        return -1;
      }
    }
    else if ( strncmp(argv[i], "ru1=", 4) == 0 )
    {
      if ( (ru[0] = parse_unit(argv[i] + 4)) == -1 ) {
        fprintf(stderr,"Invalid value of %s\n", argv[i]);
        return -1;
      }
    }
    else if ( strncmp(argv[i], "ru2=", 4) == 0 )
    {
      if ( (ru[1] = parse_unit(argv[i] + 4)) == -1 ) {
        fprintf(stderr,"Invalid value of %s\n", argv[i]);
        return -1;
      }
    }
    else if ( strncmp(argv[i], "du1=", 4) == 0 )
    {
      if ( (du[0] = parse_unit(argv[i] + 4)) == -1 ) {
        fprintf(stderr,"Invalid value of %s\n", argv[i]);
        return -1;
      }
    }
    else if ( strncmp(argv[i], "du2=", 4) == 0 )
    {
      if ( (du[1] = parse_unit(argv[i] + 4)) == -1 ) {
        fprintf(stderr,"Invalid value of %s\n", argv[i]);
        return -1;
      }
    }
    else if ( strncmp(argv[i], "r=", 2) == 0 )
    {
      if ( sscanf(argv[i] + 2, "%lf", &r) != 1 || r <= 0 ) {
        fprintf(stderr,"Invalid value of %s\n", argv[i]);
        return -1;
      }
    }
    else if ( strcmp(argv[i], "-i") == 0 ) {
      invert_match = 1;
    }
    else if ( strcmp(argv[i], "-v") == 0 ) {
      beverbose = 1;
    }
    else if ( !fname[0] ) {
      fname[0] = argv[i];
    }
    else if ( !fname[1] ) {
      fname[1] = argv[i];
    }
    else {
      fprintf(stderr, "Invalid argument '%s'. Note that only 2 input files are allowed\n", argv[i]);
      return -1;
    }
  }



  /* check command line inputs */

  if ( !fname[0] || !fname[1] ) {
    fprintf(stderr,"Two input file names expected\n");
    show_usage(stderr, argc, argv);
    return -1;
  }

  if ( rc[0] < 1 ) {
    fprintf(stderr,"rc1 argument is mandatory\n");
    show_usage(stderr, argc, argv);
    return -1;
  }

  if ( rc[1] < 1 ) {
    fprintf(stderr,"rc2 argument is mandatory\n");
    show_usage(stderr, argc, argv);
    return -1;
  }

  if ( dc[0] < 1 ) {
    fprintf(stderr,"dc1 argument is mandatory\n");
    show_usage(stderr, argc, argv);
    return -1;
  }

  if ( dc[1] < 1 ) {
    fprintf(stderr,"dc2 argument is mandatory\n");
    show_usage(stderr, argc, argv);
    return -1;
  }

  if ( (r *= (PI / (180 * 3600))) <= 0 ) {
    fprintf(stderr,"r argument is mandatory\n");
    show_usage(stderr, argc, argv);
    return -1;
  }




  /* check if input files are readable */
  for ( i = 0; i < 2; ++i )
  {
    if ( access(fname[i], R_OK) != 0 ) {
      fprintf(stderr, "Can't read %s: %s\n", fname[i], strerror(errno));
      return -1;
    }
  }


  /* allocate memory storage */
  for ( i = 0; i < 2; ++i )
  {
    if ( !(list[i] = ccarray_create(capacity[i], sizeof(obj_t))) ) {
      fprintf(stderr, "ccarray_create(capacity=%zu) fails: %s\n", capacity[i], strerror(errno));
      return -1;
    }
  }


  /* load input files */
  for ( i = 0; i < 2; ++i )
  {
    if ( beverbose ) {
      fprintf(stderr,"loading %s....\n", fname[i]);
    }

    if ( !(fp[i] = open_file(fname[i], &compression[i])) ) {
      fprintf(stderr, "Can't read '%s': %s\n", fname[i], strerror(errno));
      return -1;
    }
    if ( load_objects(fp[i], rc[i], dc[i], ru[i], du[i], head[i], list[i]) != 0 ) {
      fprintf(stderr, "Can't load %s\n", fname[i]);
      return -1;
    }
    close_file( fp[i], compression[i] );

    if ( beverbose ) {
      fprintf(stderr,"%s: %zu objects\n", fname[i], ccarray_size(list[i]));
    }

    if ( ccarray_size(list[i]) == capacity[i] && !feof(fp[i]) ) {
      fprintf(stderr, "load_objects() fails for %s: Too many objects. Try increase capacity1 (currently %zu)\n",
          fname[i], capacity[i]);
      return -1;
    }
  }


  /* sort lists */
  for ( i = 0; i < 2; ++i )
  {
    if ( beverbose ) {
      fprintf(stderr, "sort %s....\n", fname[i]);
    }
    //ccarray_sort(list[i], 0, ccarray_size(list[i]), cmpradec);
    ccarray_sort(list[i], 0, ccarray_size(list[i]), cmpdecra);
  }


  /* search pairs */
  if ( beverbose ) {
    fprintf(stderr,"search pairs...\n");
  }

  printf("%s\t%s\tdra\tddec\n", head[0], head[1]);

  size1 = ccarray_size(list[0]);
  size2 = ccarray_size(list[1]);


  double dra_closest=0;
  double ddec_closest=0;

  size_t imin=0;
  size_t imax=size2;

  for ( pos1 = 0; pos1 < size1; ++pos1 )
  {
	char line_closest [MAX_INPUT_LINE_LENGTH];
	line_closest[MAX_INPUT_LINE_LENGTH-1]=0;

    double decmin, decmax, dra, ddec;
    int objcount = 0;

    obj1 = ccarray_peek(list[0], pos1);

    decmin = obj1->dec - r;
    decmax = obj1->dec + r;

    get_index(list[1],&imin,&imax,size2,decmin,decmax);

    double rmin=r;
    double dr;

    for ( pos2=imin; pos2 < imax; ++pos2 )
    {
      obj2 = ccarray_peek(list[1], pos2);

      dra = (obj2->ra - obj1->ra) * cos((obj1->dec + obj2->dec) / 2);
      ddec = (obj2->dec - obj1->dec);

      dr=hypot(dra, ddec);
      if (  dr< rmin )
      {
    	  rmin=dr;

    	  dra_closest=dra;
    	  ddec_closest=ddec;

    	  strcpy(line_closest,obj2->line);

    	  if ( line_closest[MAX_INPUT_LINE_LENGTH - 1] != 0 ) {
    	  	        fprintf(stderr,"too long input line in this file\n");
    	  	        return -1;
    	  	      }

    	  ++objcount;
      }
    }
    if ( !invert_match && objcount>0) {
                printf("%s\t%s\t%+9.3f\t%+9.3f\n", obj1->line, line_closest, dra_closest * 180 * 3600 / PI, ddec_closest * 180 * 3600 / PI);
       }

    if ( invert_match && objcount == 0 ) {
      printf("%s\n", obj1->line);
    }
  }


  return 0;
}
Пример #9
0
int main (int argc, char * argv[])
{
    int c;
    extern char * optarg;
    extern int optind;
    svccfg_mode mode;
    if (argc < 2)
    {
        fprintf (stderr, "svccfg: expected option\n");
        exit (1);
    }

    if (!strcasecmp (argv[1], "import"))
        mode = IMPORT;
    else
        goto mode_unknown;

    clnt = s16db_context_create ();
    optind++;

    switch (mode)
    {
    case IMPORT:
    {
        int is_systemd = 0;
        const char * manifest = 0;
        svc_t * newSvc;

        while ((c = getopt (argc, argv, "m:s")) != -1)
        {
            switch (c)
            {
            case 'm':
                manifest = optarg;
                break;
            case 's':
                is_systemd = 1;
                break;

            case '?':
                exit (1);
                break;
            }
        }

        if (!manifest)
            eerror ("import manifest mode, but no manifest specified\n");

        newSvc = parse_unit (is_systemd, manifest);
        if (!newSvc)
            exit (1);

        int ret = s16db_svc_install (clnt, newSvc);
        printf ("installed manifest for service <%s> %d\n", newSvc->name, ret);

        // return 0;

        break;
    }
    }

    svc_list box = s16db_svc_retrieve_all (clnt);
    for (svc_list_iterator it = svc_list_begin (box); it != NULL;
         svc_list_iterator_next (&it))
    {
        printf ("Service: %s\n", it->val->name);
        printf ("  ID: %d\n", it->val->id);
        printf ("  PList:\n");
        for (prop_list_iterator itp = prop_list_begin (it->val->properties);
             itp != NULL; prop_list_iterator_next (&itp))
        {
            printf ("    %s: %s\n", itp->val->name, itp->val->value.pval_u.s);
        }
    }

    s16db_context_destroy (clnt);
    return 0;

mode_unknown:
    fprintf (stderr, "svccfg: unknown operation: %s\n", argv[1]);
}
Пример #10
0
void config::load(const std::string& path) {
    cybozu::config_parser cp(path);

    if( cp.exists(VIRTUAL_IP) )
        m_vip.parse(cp.get(VIRTUAL_IP));

    if( cp.exists(PORT) ) {
        int n = cp.get_as_int(PORT);
        if( n < 1 || n > 65535 )
            throw bad_config("Bad port: " + cp.get(PORT));
        m_port = static_cast<std::uint16_t>(n);
    }

    if( cp.exists(REPL_PORT) ) {
        int n = cp.get_as_int(REPL_PORT);
        if( n < 1 || n > 65535 )
            throw bad_config("Bad repl port: " + cp.get(REPL_PORT));
        m_repl_port = static_cast<std::uint16_t>(n);
    }

    if( cp.exists(BIND_IP) ) {
        for( auto& s: cybozu::tokenize(cp.get(BIND_IP), ' ') ) {
            m_bind_ip.emplace_back(s);
        }
    }

    if( cp.exists(MAX_CONNECTIONS) ) {
        int conns = cp.get_as_int(MAX_CONNECTIONS);
        if( conns < 0 )
            throw bad_config("max_connections must be >= 0");
        m_max_connections = conns;
    }

    if( cp.exists(TEMP_DIR) ) {
        m_tempdir = cp.get(TEMP_DIR);
        if( ! cybozu::is_dir(m_tempdir) )
            throw bad_config("Not a directory: " + m_tempdir);
        if( ! cybozu::is_writable(m_tempdir) )
            throw bad_config("Directory not writable: " + m_tempdir);
    }

    if( cp.exists(USER) ) {
        m_user = cp.get(USER);
    }

    if( cp.exists(GROUP) ) {
        m_group = cp.get(GROUP);
    }

    if( cp.exists(LOG_THRESHOLD) ) {
        auto it = THRESHOLDS.find(cp.get(LOG_THRESHOLD));
        if( it == THRESHOLDS.end() )
            throw bad_config("Invalid threshold: " + cp.get(LOG_THRESHOLD));
        m_threshold = it->second;
    }

    if( cp.exists(LOG_FILE) ) {
        m_logfile = cp.get(LOG_FILE);
        if( m_logfile.size() == 0 || m_logfile[0] != '/' )
            throw bad_config("Invalid log file: " + m_logfile);
    }

    if( cp.exists(BUCKETS) ) {
        int buckets = cp.get_as_int(BUCKETS);
        if( buckets < 1 )
            throw bad_config("buckets must be > 0");
        if( buckets < 10000 )
            cybozu::logger::warning() << "Too small bucket count!";
        m_buckets = buckets;
    }

    if( cp.exists(MAX_DATA_SIZE) ) {
        std::string t = cp.get(MAX_DATA_SIZE);
        if( t.empty() )
            throw bad_config("max_data_size must not be empty");
        m_max_data_size = parse_unit(t, MAX_DATA_SIZE);
    }

    if( cp.exists(HEAP_DATA_LIMIT) ) {
        std::string t = cp.get(HEAP_DATA_LIMIT);
        if( t.empty() )
            throw bad_config("heap_data_limit must not be empty");
        m_heap_data_limit = parse_unit(t, HEAP_DATA_LIMIT);
        if( m_heap_data_limit < 4096 )
            throw bad_config("too small heap_data_limit");
    }

    if( cp.exists(MEMORY_LIMIT) ) {
        std::string t = cp.get(MEMORY_LIMIT);
        if( t.empty() )
            throw bad_config("memory_limit must not be empty");
        m_memory_limit = parse_unit(t, MEMORY_LIMIT);
    }

    if( cp.exists(REPL_BUFSIZE) ) {
        int bufs = cp.get_as_int(REPL_BUFSIZE);
        if( bufs < 1 )
            throw bad_config("repl_buffer_size must be > 0");
        m_repl_bufsize = bufs;
    }

    if( cp.exists(SECURE_ERASE) ) {
        m_secure_erase = cp.get_as_bool(SECURE_ERASE);
    }

    if( cp.exists(LOCK_MEMORY) ) {
        m_lock_memory = cp.get_as_bool(LOCK_MEMORY);
    }

    if( cp.exists(WORKERS) ) {
        int n = cp.get_as_int(WORKERS);
        if( n < 1 )
            throw bad_config("workers must be > 0");
        if( n > MAX_WORKERS )
            throw bad_config("workers must be <= " +
                             std::to_string(MAX_WORKERS));
        m_workers = n;
    }

    if( cp.exists(GC_INTERVAL) ) {
        int n = cp.get_as_int(GC_INTERVAL);
        if( n < 1 )
            throw bad_config("gc_interval must be > 0");
        m_gc_interval = n;
    }

    if( cp.exists(SLAVE_TIMEOUT) ) {
        int n = cp.get_as_int(SLAVE_TIMEOUT);
        if( n < 1 )
            throw bad_config("slave_timeout must be > 0");
        m_slave_timeout = n;
    }

    m_counter_config.load(cp);
}
Пример #11
0
int
frec_proc_heur(heur_t *h, const wchar_t *regex, size_t len, int cflags)
{
	int errcode;
	parser_state state;

	errcode = init_state(&state, regex, len, cflags);
	if (errcode != REG_OK)
		goto err;

	DEBUG_PRINT("enter");

	/*
	 * Process the pattern char-by-char.
	 *
	 * state.procidx: position in regex
	 * state.heur: buffer for the fragment being extracted
	 * state.heurpos: buffer position
	 */
	for (state.procidx = 0; state.procidx < state.len; state.procidx++) {
		switch (state.regex[state.procidx]) {

		/*
		 * BRE/ERE: Bracketed expression ends the segment or the
		 * brackets are treated as normal if at least the opening
		 * bracket is escaped.
		 */
		case L'[':
			if (state.escaped) {
				store_char(&state);
				continue;
			} else {
				if (parse_set(&state) == REG_BADPAT)
					return REG_BADPAT;
				state.tlen = (state.tlen == -1) ? -1 : state.tlen + 1;
				errcode = end_segment(&state, false);
				if (errcode != REG_OK)
					goto err;
			}
			continue;

		/*
		 * If a repetition marker, erases the repeting character
		 * and terminates the segment, otherwise treated as a normal
		 * character.
		 * BRE: repetition marker if ESCAPED.
		 * ERE: repetition marker if NOT ESCAPED.
		 */
		case L'{':
			/* Be more permissive at the beginning of the pattern */
			if (state.escaped && (state.procidx == 1)) {
				store_char(&state);
				continue;
			} else if (state.procidx == 0) {
				store_char(&state);
				continue;
			}

			if (state.escaped ^ state.ere) {
				drop_last_char(&state);
				parse_unit(&state, L'{', L'}');
				errcode = end_segment(&state, true);
				if (errcode != REG_OK)
					goto err;
			} else {
				store_char(&state);
				continue;
			}
			continue;

		/*
		 * Terminates the current segment if used for a subexpression,
		 * otherwise treated as a normal character.
		 * BRE: subexpression if ESCAPED.
		 * ERE: subexpression if NOT ESCAPED.
		 */
		case L'(':
			if (state.escaped ^ state.ere) {
				parse_unit(&state, L'(', L')');
				errcode = end_segment(&state, true);
				if (errcode != REG_OK)
					goto err;
			} else {
				store_char(&state);
				continue;
			}
			continue;

		/*
		 * Sets escaped flag.
		 * Escaped escape is treated as a normal character.
		 * (This is also the GNU behaviour.)
		 */
		case L'\\':
			if (state.escaped) {
				store_char(&state);
				continue;
			} else
				state.escaped = true;
			continue;

		/*
		 * BRE: If not the first character and not escaped, erases the
		 * last character and terminates the segment.
		 * Otherwise treated as a normal character.
		 * ERE: Skipped if first character (GNU), rest is like in BRE.
		 */
		case L'*':
			/* Be more permissive at the beginning of the pattern */
			if (state.escaped || (!state.ere && (state.procidx == 0))) {
				store_char(&state);
				continue;
			} else {
				drop_last_char(&state);
				errcode = end_segment(&state, true);
				if (errcode != REG_OK)
					goto err;
			}
			continue;

		/*
		 * BRE: it is a normal character, behavior is undefined
		 * when escaped.
		 * ERE: it is special unless escaped. Terminate segment
		 * when not escaped. Last character is not removed because it
		 * must occur at least once. It is skipped when first
		 * character (GNU).
		 */
		case L'+':
			/* Be more permissive at the beginning of the pattern */
			if (state.ere && (state.procidx == 0))
				continue;
			else if (state.ere ^ state.escaped) {
				errcode = end_segment(&state, true);
				if (errcode != REG_OK)
					goto err;
			} else {
				store_char(&state);
				continue;
			}
			continue;

		/*
		 * BRE: it is a normal character, behavior is undefined
		 * when escaped.
		 * ERE: it is special unless escaped. Terminate segment
		 * when not escaped. Last character is removed. Skipped when
		 * first character (GNU).
		 */
		case L'?':
			/* Be more permissive at the beginning of the pattern */
			if (state.ere && (state.procidx == 0))
				continue;
			if (state.ere ^ state.escaped) {
				drop_last_char(&state);
				errcode = end_segment(&state, true);
				if (errcode != REG_OK)
					goto err;
			} else {
				store_char(&state);
				continue;
			}
			continue;

		/*
		 * BRE: it is a normal character, behavior is undefined
		 * when escaped.
		 * ERE: alternation marker; unsupported.
		 */
		case L'|':
			if (state.ere ^ state.escaped) {
				errcode = REG_BADPAT;
				goto err;
			} else {
				store_char(&state);
				continue;
			}
			continue;

		/*
		 * BRE/ERE: matches any single character; normal character
		 * if escaped.
		 */
		case L'.':
			if (state.escaped) {
				store_char(&state);
				continue;
			} else {
				state.has_dot = true;
				state.tlen = (state.tlen == -1) ? -1 : state.tlen + 1;
				errcode = end_segment(&state, false);
				if (errcode != REG_OK)
					goto err;
			}
			continue;

		case L'\n':
			state.has_lf = true;
			store_char(&state);
			continue;

		/*
		 * If escaped, terminates segment.
		 * Otherwise adds current character to the current segment
		 * by copying it to the temporary space.
		 */
		default:
			if (state.escaped) {
				if (state.regex[state.procidx] == L'n') {
					state.has_lf = true;
					store(&state, L'\n');
					continue;
				}
				errcode = end_segment(&state, true);
				if (errcode != REG_OK)
					goto err;
			} else {
				store_char(&state);
				continue;
			}
			continue;
		}
	}

	if (state.heurpos > 0) {
		errcode = end_segment(&state, false);
		if (errcode != REG_OK)
			goto err;
	}

	h->heur = malloc(sizeof(fastmatch_t));
	if (!h->heur) {
		errcode = REG_ESPACE;
		goto err;
	}

	errcode = fill_heuristics(&state, h);
	if (errcode != REG_OK)
		goto err;

	errcode = REG_OK;

err:
	if ((errcode != REG_OK) && (h->heur != NULL))
		frec_free_fast(h->heur);

	free_state(&state);
	return (errcode);
}