	}
	GF_SAFEALLOC(tr, DashTemplateRecord)
	tr->tpl = gf_strdup(tpl);
	gf_list_add(ctx->tpl_records, tr);
	return 0;
}

static void dasher_setup_sources(GF_Filter *filter, GF_DasherCtx *ctx, GF_MPD_AdaptationSet *set)
{
	char szDASHTemplate[GF_MAX_PATH];
	char szTemplate[GF_MAX_PATH];
	char szSegmentName[GF_MAX_PATH];
	char szInitSegmentTemplate[GF_MAX_PATH];
	char szInitSegmentFilename[GF_MAX_PATH];
	char szIndexSegmentName[GF_MAX_PATH];
	char szSetFileSuffix[200], szDASHSuffix[220];
	const char *template = NULL;
	u32 as_id = 0;
	Bool single_template = GF_TRUE;
	u32 i, j, count, nb_base, nb_streams;
	GF_List *multi_pids = NULL;
	u32 set_timescale = 0;
	Bool init_template_done=GF_FALSE;
	Bool use_inband = ((ctx->bs_switch==DASHER_BS_SWITCH_INBAND) || (ctx->bs_switch==DASHER_BS_SWITCH_INBAND_PPS)) ? GF_TRUE : GF_FALSE;
	Bool template_use_source = GF_FALSE;
	Bool split_rep_names = GF_FALSE;
	Bool split_set_names = GF_FALSE;
	u32 force_ds_id;
	GF_DashStream *ds;
	GF_MPD_Representation *rep = gf_list_get(set->representations, 0);
	if (!rep) {
		assert(0);
		return;
	}
	ds = rep->playback.udta;

	count = gf_list_count(set->representations);

	if (!ctx->sigfrag) {
		assert(ctx->template);
		template = ((GF_DashStream *)set->udta)->template;
	}

	for (i=0; i<count; i++) {
		rep = gf_list_get(set->representations, i);
		ds = rep->playback.udta;
		if (!ds->template && !template) {}
		else if (ds->template && template && !strcmp(ds->template, template) ) {
		} else {
			single_template = GF_FALSE;
		}
		if (ds->template) template_use_source = dasher_template_use_source_url(ds->template);

		if (template_use_source) {
			single_template = GF_FALSE;
		}

		if (ds->as_id && !as_id)
			as_id = ds->as_id;

		if (ds->fps.den && ( (ds->fps.num*set->max_framerate.den) >= (s32) (set->max_framerate.num*ds->fps.den) )) {
			set->max_framerate.num = ds->fps.num;
			set->max_framerate.den = ds->fps.den;
			gf_media_get_reduced_frame_rate(&set->max_framerate.num, &set->max_framerate.den);
		}
		if (ds->width && ds->height) {
			if (!set->par) {
				GF_SAFEALLOC(set->par, GF_MPD_Fractional);
			}
			if (set->par) {
				set->par->num = ds->width;
				set->par->den = ds->height;
				gf_media_reduce_aspect_ratio(&set->par->num, &set->par->den);
			}
		}
	}
	if (!template) template = ctx->template;

	if (as_id) {
		set->id = ds->as_id;
	}
	if (ctx->sseg) {
		set->segment_alignment = GF_TRUE;
		set->starts_with_sap = 1;
	}

	if (count==1)
		single_template = GF_TRUE;
	else if (single_template) {
		//for regular reps, if we depend on filename we cannot mutualize the template
		if (dasher_template_use_source_url(template) ) {
			single_template = GF_FALSE;
		}
		//and for scalable reps, if we don't have bandwidth /repID we cannot mutualize the template
		else if (gf_list_count(ds->complementary_streams) ) {
			if (strstr(template, "$Bandwidth$") != NULL) single_template = GF_FALSE;
			else if (strstr(template, "$RepresentationId$") != NULL) single_template = GF_FALSE;
		}
	}

	if (set->lang) gf_free(set->lang);
	set->lang = gf_strdup(ds->lang ? ds->lang : "und");

	//check all streams in active period not in this set
	force_ds_id = ds->id;
	nb_streams = gf_list_count(ctx->current_period->streams);
	for (i=0; i<nb_streams; i++) {
		char *frag_uri;
		u32 len1, len2;
		GF_DashStream *ads = gf_list_get(ctx->current_period->streams, i);

		if (force_ds_id && (ads != ds) && (ads->id == ds->id)) {
			force_ds_id = 0;
		}

		if (ads->set == set) continue;
		frag_uri = strrchr(ds->src_url, '#');
		if (frag_uri) len1 = (u32) (frag_uri-1 - ds->src_url);
		else len1 = (u32) strlen(ds->src_url);
		frag_uri = strrchr(ads->src_url, '#');
		if (frag_uri) len2 = (u32) (frag_uri-1 - ads->src_url);
		else len2 = (u32) strlen(ads->src_url);

		if ((len1==len2) && !strncmp(ds->src_url, ads->src_url, len1)) {
			split_set_names = GF_TRUE;
			break;
		}
	}

	if (ctx->timescale>0) {
		set_timescale = ctx->timescale;
	} else {
		u32 first_timescale;
		rep = gf_list_get(set->representations, 0);
		ds = rep->playback.udta;
		first_timescale = ds->timescale;
		for (i=1; i<count; i++) {
			rep = gf_list_get(set->representations, i);
			ds = rep->playback.udta;
			if (ds->timescale != first_timescale) {
				//we cannot use a single template if enforcing timescales which are not identical
				single_template = GF_FALSE;
				break;
			}
		}
	}

	for (i=0; i<count; i++) {
		if (ctx->sigfrag)
			break;

		rep = gf_list_get(set->representations, i);
		ds = rep->playback.udta;

		if (!dasher_template_use_source_url(template))
			continue;

		if (ds->muxed_base)
			continue;

		for (j=i+1; j<count; j++) {
			const GF_PropertyValue *p1, *p2;
			GF_DashStream *a_ds;
			rep = gf_list_get(set->representations, j);
			a_ds = rep->playback.udta;

			if (a_ds->muxed_base == ds)
				continue;

			p1 = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_FILEPATH);
			p2 = gf_filter_pid_get_property(a_ds->ipid, GF_PROP_PID_FILEPATH);
			if (p1 && p2 && gf_props_equal(p1, p2)) split_rep_names = GF_TRUE;
			else if (!p1 && !p2) split_rep_names = GF_TRUE;
			p1 = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_URL);
			p2 = gf_filter_pid_get_property(a_ds->ipid, GF_PROP_PID_URL);
			if (p1 && p2 && gf_props_equal(p1, p2)) split_rep_names = GF_TRUE;
			else if (!p1 && !p2) split_rep_names = GF_TRUE;

			if (split_rep_names) break;
		}
		if (split_rep_names) break;
	}

	if (split_set_names) {
		if (!force_ds_id) {
			if (split_rep_names || !ds->split_set_names)
				force_ds_id = ds->id;
			else
				force_ds_id = gf_list_find(ctx->pids, ds) + 1;
		}
		sprintf(szSetFileSuffix, "_track%d_", force_ds_id);
	}

	//assign PID IDs - we assume only one component of a given media type per adaptation set
	//and assign the same PID ID for each component of the same type
	//we could refine this using roles, but most HAS solutions don't use roles at the mulitplexed level
	for (i=0; i<count; i++) {
		Bool is_bs_switching;
		rep = gf_list_get(set->representations, i);
		ds = rep->playback.udta;
		if (ds->pid_id) continue;
		//in bitstream switching mode, ensure each track in the set has the same ID
		//except when tile merge is used
		is_bs_switching = ds->tile_dep_id_merged ? GF_FALSE : set->bitstream_switching;
		if (is_bs_switching) {
			ctx->next_pid_id_in_period++;
			//except for base tile track where we force using input PID ID
			//to avoid messing up sabt/tbas references
			if (ds->tile_base) {
				ds->pid_id = ds->id;
				if (ctx->next_pid_id_in_period <= ds->pid_id)
					ctx->next_pid_id_in_period = ds->pid_id;
			} else {
				ds->pid_id = ctx->next_pid_id_in_period;
			}

			for (j=i+1; j<count; j++) {
				GF_DashStream *a_ds;
				rep = gf_list_get(set->representations, j);
				a_ds = rep->playback.udta;
				if (a_ds->pid_id) continue;
				if (a_ds->dep_id) continue;
				if (a_ds->stream_type == ds->stream_type) a_ds->pid_id = ds->pid_id;
			}
		}
		//otherwise copy over the source PID
		else {
			ds->pid_id = ds->id;
		}
	}

	for (i=0; i<count; i++) {
		rep = gf_list_get(set->representations, i);
		ds = rep->playback.udta;
		if (!ds->dep_id) continue;

		for (j=i+1; j<count; j++) {
			GF_DashStream *a_ds;
			rep = gf_list_get(set->representations, j);
			a_ds = rep->playback.udta;
			if (ds->dep_id == a_ds->id) {
				ds->dep_pid_id = a_ds->pid_id;
				break;
			}
		}
	}

	//this is crude because we don't copy the properties, we just pass a list of pids to the destination muxer !!
	//we should cleanup one of these days
	if (set->bitstream_switching && (ctx->bs_switch==DASHER_BS_SWITCH_MULTI)) {
		multi_pids = gf_list_new();
		for (i=0; i<count; i++) {
			rep = gf_list_get(set->representations, i);
			ds = rep->playback.udta;
			if (ds->owns_set) ds->multi_pids = multi_pids;
			gf_list_add(multi_pids, ds->ipid);
		}
	}

	if (ctx->cp!=GF_DASH_CPMODE_REPRESENTATION) {
		gf_mpd_del_list(set->content_protection, gf_mpd_descriptor_free, 0);
		set->content_protection = dasher_get_content_protection_desc(ctx, NULL, set);
	}

	for (i=0; i<count; i++) {
		GF_Err e;
		char szRawExt[20];
		Bool use_dash_suffix = GF_FALSE;
		Bool is_source_template = GF_FALSE;
		const char *seg_ext, *init_ext, *idx_ext, *force_init_seg_tpl;
#if 0
		GF_MPD_URL *force_init_seg_sl;
#endif
		Bool skip_init = GF_FALSE;
		GF_DashStream *tile_base_ds = NULL;
		Bool is_bs_switch;
		u32 reused_template_idx;
		u32 init_template_mode = GF_DASH_TEMPLATE_INITIALIZATION_TEMPLATE;
		rep = gf_list_get(set->representations, i);
		ds = rep->playback.udta;

		//remove representations for streams muxed with others, but still open the output
		if (ds->muxed_base) {
			GF_DashStream *ds_set = set->udta;
			gf_list_rem(set->representations, i);
			i--;
			count--;
			assert(ds_set->nb_rep);
			ds_set->nb_rep--;
			assert(ctx->sigfrag || ds->muxed_base->dst_filter);
			gf_list_transfer(ds->muxed_base->rep->audio_channels, rep->audio_channels);
			gf_list_transfer(ds->muxed_base->rep->base_URLs, rep->base_URLs);
			gf_list_transfer(ds->muxed_base->rep->content_protection , rep->content_protection);
			gf_list_transfer(ds->muxed_base->rep->essential_properties , rep->essential_properties);
			gf_list_transfer(ds->muxed_base->rep->frame_packing , rep->frame_packing);
			if (rep->x_children) {
				if (!ds->muxed_base->rep->x_children) ds->muxed_base->rep->x_children = gf_list_new();
				gf_list_transfer(ds->muxed_base->rep->x_children, rep->x_children);
			}
			gf_list_transfer(ds->muxed_base->rep->supplemental_properties , rep->supplemental_properties);

			gf_mpd_representation_free(ds->rep);
			ds->rep = NULL;

			if (!gf_list_count(ds->set->content_component)) {
				dasher_set_content_components(ds->muxed_base);
			}
			dasher_set_content_components(ds);
			assert(!multi_pids);
			//open PID
			dasher_open_pid(filter, ctx, ds, NULL, GF_FALSE);
			continue;
		}
		if (ds->template) {
			strcpy(szTemplate, ds->template);
			if (ctx->sigfrag) {
				const GF_PropertyValue *p = gf_filter_pid_get_property_str(ds->ipid, "source_template");
				if (p && p->value.boolean)
					is_source_template = GF_TRUE;
			}
		} else {
			strcpy(szTemplate, ctx->template ? ctx->template : "");
		}

		if (use_inband) {
			ds->inband_params = 1;
			if ((ds->codec_id==GF_CODECID_VVC) && (ctx->bs_switch==DASHER_BS_SWITCH_INBAND_PPS))
				ds->inband_params = 2;
		}

		//if bitstream switching and templating, only set for the first one
		if (i && set->bitstream_switching && ds->stl && single_template) continue;

		if (!set_timescale) set_timescale = ds->timescale;

		if (ctx->timescale<0) ds->mpd_timescale = ds->timescale;
		else ds->mpd_timescale = set_timescale;

		if (ctx->sigfrag && gf_filter_pid_get_property_str(ds->ipid, "source_template")) {
			const GF_PropertyValue *p = gf_filter_pid_get_property_str(ds->ipid, "stl_timescale");
			if (p && p->value.uint) {
				ds->mpd_timescale = p->value.uint;
			}
		}

		if (ds->nb_repeat && !ctx->loop) {
			if (split_set_names) {
				sprintf(szDASHSuffix, "%sp%d_", szSetFileSuffix, ds->nb_repeat+1);
			} else {
				sprintf(szDASHSuffix, "p%d_", ds->nb_repeat);
			}
			use_dash_suffix = GF_TRUE;
		} else if (split_set_names) {
			strcpy(szDASHSuffix, szSetFileSuffix);
			use_dash_suffix = GF_TRUE;
		}
		//we need dash suffix in template, but the template may be user-provided without dash suffix. If so add it
		//we don't add suffic if we have $RepresentationID or $Path set, we assume the user knows what he's doing
		if (use_dash_suffix && !strstr(szTemplate, "$FS$") && !strstr(szTemplate, "$RepresentationID$") && !strstr(szTemplate, "$Path=")) {
			strcat(szTemplate, "$FS$");
		}

		//resolve segment template
		e = gf_filter_pid_resolve_file_template(ds->ipid, szTemplate, szDASHTemplate, 0, use_dash_suffix ? szDASHSuffix : NULL);
		if (e) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[Dasher] Cannot resolve template name %s, cannot derive output segment names, disabling rep %s\n", szTemplate, ds->src_url));
			gf_filter_pid_set_discard(ds->ipid, GF_TRUE);
			ds->done = 1;
			continue;
		}

		if (single_template && ds->split_set_names && !use_dash_suffix) {
			char szStrName[20];
			sprintf(szStrName, "_set%d", 1 + gf_list_find(ctx->current_period->period->adaptation_sets, set)  );
			strcat(szDASHTemplate, szStrName);
		}
		else if (split_rep_names) {
			char szStrName[20];
			sprintf(szStrName, "_rep%d", 1 + gf_list_find(set->representations, ds->rep)  );
			strcat(szDASHTemplate, szStrName);
		}

		ds->rawmux = GF_FALSE;
		idx_ext = NULL;

		const char *def_ext = NULL;
		seg_ext = init_ext = NULL;

		if (ctx->muxtype==DASHER_MUX_TS) {
			def_ext = seg_ext = init_ext = "ts";
			if (!ctx->do_m3u8 && (ctx->subs_sidx>=0) )
				idx_ext = "idx";
		}
		else if (ctx->muxtype==DASHER_MUX_MKV) def_ext = "mkv";
		else if (ctx->muxtype==DASHER_MUX_WEBM) def_ext = "webm";
		else if (ctx->muxtype==DASHER_MUX_OGG) def_ext = "ogg";
		else if (ctx->muxtype==DASHER_MUX_RAW) {
			char *ext = (char *) gf_codecid_file_ext(ds->codec_id);
			if (ds->codec_id==GF_CODECID_RAW) {
				const GF_PropertyValue *p;
				if (ds->stream_type==GF_STREAM_VISUAL) {
					p = gf_filter_pid_get_property(ds->ipid, GF_PROP_PIXFMT);
					if (p) ext = (char *) gf_pixel_fmt_sname(p->value.uint);
				}
				else if (ds->stream_type==GF_STREAM_AUDIO) {
					p = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_AUDIO_FORMAT);
					if (p) ext = (char *) gf_audio_fmt_sname(p->value.uint);
				}
			}
			strncpy(szRawExt, ext ? ext : "raw", 19);
			szRawExt[19] = 0;
			ext = strchr(szRawExt, '|');
			if (ext) ext[0] = 0;
			def_ext = szRawExt;
		}

		if (!ds->muxed_base && ctx->rawsub && (ds->stream_type==GF_STREAM_TEXT) ) {
			char *ext_sub = (char *) gf_codecid_file_ext(ds->codec_id);
			if (ext_sub) {
				if (!strcmp(ext_sub, "subx"))
					ext_sub = "ttml";

				strncpy(szRawExt, ext_sub, 19);
				szRawExt[19] = 0;
				ext_sub = strchr(szRawExt, '|');
				if (ext_sub) ext_sub[0] = 0;
				def_ext = szRawExt;
				skip_init = GF_TRUE;
				ds->rawmux = GF_TRUE;
			}
		}

		if (ctx->segext && !stricmp(ctx->segext, "null")) {
			seg_ext = NULL;
		} else {
			seg_ext = ctx->segext;
			if (!seg_ext) seg_ext = def_ext ? def_ext : "m4s";
		}
		if (ctx->initext && !stricmp(ctx->initext, "null")) {
			init_ext = NULL;
		} else {
			init_ext = ctx->initext;
			if (!init_ext) init_ext = def_ext ? def_ext : "mp4";
		}

		//source template is used, do not use any extensions, they are present in the template
		if (is_source_template) {
			def_ext = NULL;
			init_ext = NULL;
			seg_ext = NULL;
		}

		is_bs_switch = set->bitstream_switching;
		//only used to force _init in default templates
		if (ds->tile_base) is_bs_switch = GF_FALSE;

		//check we are not reusing an existing template from previous periods, if so append a suffix
		//we check the final init name
		if (!ds->skip_tpl_reuse) {
			//1- init will not work in tiling as the base track and the first rep could end up having the same
			//segment template since base uses "init" while tile tracks don't for the init template
			//2- because of that, all evaluated templates must be the segment ones, otherwise we may check the audio init template
			//against a tile segment template, which will not match even though they use the same base template...
			//ex: template: seg_ => seg_trackN_init.mp4 for non-tiled vs seg_trackN_$number$.m4s for tiled, resulting in same N
			//being used for 2 track
			//cf issue 1849
			//we however don't want to change templates if they are indeed reused but resolve to something different due to representationID
			//we therefore resolve the segment template with startNumber 0 time 0, use this resolved name as base check.

			gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_SEGMENT, is_bs_switch, szInitSegmentFilename, ds->rep_id, NULL, szDASHTemplate, is_source_template ? NULL : "mp4", 0, ds->bitrate, 0, ds->stl);

			reused_template_idx = dasher_check_template_reuse(ctx, szInitSegmentFilename);
			if (reused_template_idx) {
				char szExName[20];
				sprintf(szExName, "_r%d_", reused_template_idx);
				strcat(szDASHTemplate, szExName);
				//force template at representation level if more than one rep and templates have been reused
				if (gf_list_count(ds->set->representations)>1)
					single_template = GF_FALSE;
			}
		}

		//get final segment template with path resolution - output file name is NULL, we already have solved this
		gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_TEMPLATE_WITH_PATH, is_bs_switch, szSegmentName, ds->rep_id, NULL, szDASHTemplate, seg_ext, 0, 0, 0, ds->stl);
		ds->seg_template = gf_strdup(szSegmentName);

		//get final segment template - output file name is NULL, we already have solved this
		gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_TEMPLATE, is_bs_switch, szSegmentName, ds->rep_id, NULL, szDASHTemplate, seg_ext, 0, 0, 0, ds->stl);

		//get index templates
		if (idx_ext) {
			gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_REPINDEX_TEMPLATE_WITH_PATH, is_bs_switch, szIndexSegmentName, ds->rep_id, NULL, szDASHTemplate, idx_ext, 0, 0, 0, ds->stl);
			ds->idx_template = gf_strdup(szIndexSegmentName);

			gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_REPINDEX_TEMPLATE, is_bs_switch, szIndexSegmentName, ds->rep_id, NULL, szDASHTemplate, idx_ext, 0, 0, 0, ds->stl);
		}

		//get final init name - output file name is NULL, we already have solved this
		gf_media_mpd_format_segment_name(GF_DASH_TEMPLATE_INITIALIZATION, is_bs_switch, szInitSegmentFilename, ds->rep_id, NULL, szDASHTemplate, init_ext, 0, ds->bitrate, 0, ds->stl);

		//get final init template name - output file name is NULL, we already have solved this
		gf_media_mpd_format_segment_name(init_template_mode, is_bs_switch, szInitSegmentTemplate, ds->rep_id, NULL, szDASHTemplate, init_ext, 0, 0, 0, ds->stl);

		if (ctx->sigfrag) {
			if (ctx->template || ds->template) {
				 if (is_source_template) {
					const GF_PropertyValue *mpd_url = gf_filter_pid_get_property_str(ds->ipid, "manifest_url");
					strcpy(szInitSegmentFilename, gf_file_basename(ds->src_url));

					if (ctx->out_path && mpd_url) {
						char *url, *mpd_out;
						mpd_out = gf_file_basename(ctx->out_path);
						u32 len = (u32) (mpd_out - ctx->out_path);
						char *mpd_src = mpd_url->value.string;
						if (!strncmp(ctx->out_path, mpd_url->value.string, len))
							mpd_src += len;

						const GF_PropertyValue *init_url = gf_filter_pid_get_property_str(ds->ipid, "init_url");
						if (init_url) {
							url = gf_url_concatenate(mpd_src, init_url->value.string);
							strcpy(szInitSegmentFilename, url);
							strcpy(szInitSegmentTemplate, url);
							gf_free(url);
						} else {
							//no init segment URL
							strcpy(szInitSegmentFilename, "");
							strcpy(szInitSegmentTemplate, "");
						}

						url = gf_url_concatenate(mpd_src, ds->template);
						strcpy(szSegmentName, url);
						gf_free(url);
					}
				 }
			} else {
				strcpy(szInitSegmentFilename, gf_file_basename(ds->src_url));
				strcpy(szSegmentName, gf_file_basename(ds->src_url));
			}
		}

		if (ctx->store_seg_states) {
			assert(!ds->pending_segment_states);
			ds->pending_segment_states = gf_list_new();
		}
		/* baseURLs */
		nb_base = ds->p_base_url ? ds->p_base_url->value.string_list.nb_items : 0;
		for (j=0; j<nb_base; j++) {
			GF_MPD_BaseURL *base_url;
			char *url = ds->p_base_url->value.string_list.vals[j];
			GF_SAFEALLOC(base_url, GF_MPD_BaseURL);
			if (base_url) {
				base_url->URL = gf_strdup(url);
				gf_list_add(rep->base_URLs, base_url);
			}
		}

		force_init_seg_tpl = NULL;
#if 0
		force_init_seg_sl = NULL;
#endif
		if (ds->codec_id==GF_CODECID_HEVC_TILES) {
			tile_base_ds = get_base_ds(ctx, ds);
			skip_init = GF_TRUE;
			if (tile_base_ds->rep->segment_template) force_init_seg_tpl = tile_base_ds->rep->segment_template->initialization;
			if (!force_init_seg_tpl && tile_base_ds->set->segment_template) force_init_seg_tpl = tile_base_ds->set->segment_template->initialization;

#if 0
			if (tile_base_ds->rep->segment_list) force_init_seg_sl = tile_base_ds->rep->segment_list->initialization_segment;
			if (!force_init_seg_sl && tile_base_ds->set->segment_list) force_init_seg_sl = tile_base_ds->set->segment_list->initialization_segment;
#endif
		}
		if (ctx->muxtype==DASHER_MUX_RAW) skip_init = GF_TRUE;
		else if (ctx->muxtype==DASHER_MUX_TS) skip_init = GF_TRUE;
		else if (ctx->muxtype==DASHER_MUX_OGG) skip_init = GF_TRUE;

		//forward mode, change segment names
		if (ctx->forward_mode) {
			u32 k, nb_pids = gf_list_count(ctx->pids);
			char *src = NULL;
			const GF_PropertyValue *p = gf_filter_pid_get_property(ds->ipid, GF_PROP_PCK_FILENAME);

			if (!p || !p->value.string) {
				GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[Dasher] Couldn't fetch source URL in forward mode, cannot forward\n"));
				ctx->in_error = GF_TRUE;
				return;
			}
			src = p->value.string;

			for (k=0; k<nb_pids; k++) {
				GF_DashStream *a_ds = gf_list_get(ctx->pids, k);
				if (ds == a_ds) continue;
				if (!a_ds->dst_filter) continue;

				p = gf_filter_pid_get_property(a_ds->ipid, GF_PROP_PCK_FILENAME);
				if (!p || !p->value.string) {
					GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[Dasher] Couldn't fetch source URL in forward mode, cannot forward\n"));
					ctx->in_error = GF_TRUE;
					return;
				}
				//same init segment used (bs switching)
				if (!strcmp(p->value.string, src))
					skip_init = GF_TRUE;
			}
			strcpy(szInitSegmentFilename, src);
			strcpy(szInitSegmentTemplate, src);

			if (ctx->tpl) {
				p = gf_filter_pid_get_property(ds->ipid, GF_PROP_PID_TEMPLATE);
				if (!p || !p->value.string) {
					GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[Dasher] Couldn't fetch source template in forward mode, cannot forward\n"));
					ctx->in_error = GF_TRUE;
					return;
				}
				strcpy(szSegmentName, p->value.string);
			}
		}

		ds->init_seg = gf_strdup(szInitSegmentFilename);

		//we use segment template
		if (ctx->tpl) {
			Bool use_single_init;
			GF_MPD_SegmentTemplate *seg_template;
			u32 start_number = ds->startNumber ? ds->startNumber : 1;
			u64 seg_duration = (u64)(ds->dash_dur.num) * ds->mpd_timescale / ds->dash_dur.den;

			if (ds->inband_params && (ctx->bs_switch==DASHER_BS_SWITCH_INBAND_PPS)) {
				use_single_init = GF_FALSE;
				single_template = GF_FALSE;
			} else {
				use_single_init = (set->bitstream_switching || single_template) ? GF_TRUE : GF_FALSE;
			}

			//first rep in set and bs switching or single template, create segment template at set level
			if (!i && use_single_init ) {
				init_template_done = GF_TRUE;
				seg_template = NULL;
				if (!skip_init || force_init_seg_tpl || single_template) {
					GF_SAFEALLOC(seg_template, GF_MPD_SegmentTemplate);
					if (seg_template) {
						if (skip_init) {
							seg_template->initialization = force_init_seg_tpl ? gf_strdup(force_init_seg_tpl) : NULL;
							seg_template->hls_init_name = force_init_seg_tpl ? tile_base_ds->init_seg : NULL;
						} else {
							seg_template->initialization = gf_strdup(szInitSegmentTemplate);
							seg_template->hls_init_name = ds->init_seg;
						}
					}
				}
				set->segment_template = seg_template;

				dasher_open_destination(filter, ctx, rep, szInitSegmentFilename, skip_init);

				if (single_template) {
					seg_template->media = gf_strdup(szSegmentName);
					if (ds->idx_template)
						seg_template->index = gf_strdup(szIndexSegmentName);

					seg_template->timescale = ds->mpd_timescale;
					seg_template->start_number = start_number;
					seg_template->duration = seg_duration;

					if (ctx->asto>0) {
						seg_template->availability_time_offset = ctx->asto;
					}
				} else if (seg_template) {
					seg_template->start_number = (u32)-1;
				}
			}
			//non-first rep in set and single template, only open destination
			if (i && single_template) {
				dasher_open_destination(filter, ctx, rep, szInitSegmentFilename, (set->bitstream_switching || skip_init) ? GF_TRUE : GF_FALSE);
			}
			//first rep in set and no bs switching or mutliple templates, create segment template at rep level
			else if (i || !single_template) {
				GF_SAFEALLOC(seg_template, GF_MPD_SegmentTemplate);
				if (seg_template) {
					rep->segment_template = seg_template;
					if (!init_template_done) {
						if (skip_init) {
							seg_template->initialization = force_init_seg_tpl ? gf_strdup(force_init_seg_tpl) : NULL;
							seg_template->hls_init_name = force_init_seg_tpl ? tile_base_ds->init_seg : NULL;
						} else {
							seg_template->initialization = gf_strdup(szInitSegmentTemplate);
							seg_template->hls_init_name = ds->init_seg;
						}
						dasher_open_destination(filter, ctx, rep, szInitSegmentFilename, skip_init);
					} else if (i) {
						dasher_open_destination(filter, ctx, rep, szInitSegmentFilename, (set->bitstream_switching || skip_init) ? GF_TRUE : GF_FALSE);
					}
					seg_template->media = gf_strdup(szSegmentName);
					if (ds->idx_template)
						seg_template->index = gf_strdup(szIndexSegmentName);
					seg_template->duration = seg_duration;
					seg_template->timescale = ds->mpd_timescale;
					seg_template->start_number = start_number;
					if (ctx->asto > 0) {
						seg_template->availability_time_offset = ctx->asto;
					}
				}
			}
		}
		/*we are using a single file or segment, use base url*/
		else if (ctx->sseg || ctx->sfile) {
			GF_MPD_BaseURL *baseURL;

			if (ds->init_seg) gf_free(ds->init_seg);
			ds->init_seg = gf_strdup(szInitSegmentFilename);

			GF_SAFEALLOC(baseURL, GF_MPD_BaseURL);
			if (!baseURL) continue;

			if (!rep->base_URLs) rep->base_URLs = gf_list_new();
			gf_list_add(rep->base_URLs, baseURL);

			if (ctx->sseg) {
				GF_MPD_SegmentBase *segment_base;
				baseURL->URL = gf_strdup(szInitSegmentFilename);
				GF_SAFEALLOC(segment_base, GF_MPD_SegmentBase);
				if (!segment_base) continue;
				rep->segment_base = segment_base;
				dasher_open_destination(filter, ctx, rep, szInitSegmentFilename, GF_FALSE);
			} else {
				GF_MPD_SegmentList *seg_list;
				GF_SAFEALLOC(seg_list, GF_MPD_SegmentList);
				if (!seg_list) continue;
				GF_SAFEALLOC(seg_list->initialization_segment, GF_MPD_URL);
				if (!seg_list->initialization_segment) continue;
				seg_list->start_number = (u32) -1;
				baseURL->URL = gf_strdup(szInitSegmentFilename);
				seg_list->dasher_segment_name = gf_strdup(szSegmentName);
				seg_list->timescale = ds->mpd_timescale;
				seg_list->duration = (u64) (ds->dash_dur.num) * ds->mpd_timescale / ds->dash_dur.den;
				seg_list->segment_URLs = gf_list_new();
				rep->segment_list = seg_list;
				ds->pending_segment_urls = gf_list_new();

				dasher_open_destination(filter, ctx, rep, szInitSegmentFilename, skip_init);
			}
		}
		//no template, no single file, we need a file list
		else {
			GF_MPD_SegmentList *seg_list;
			GF_SAFEALLOC(seg_list, GF_MPD_SegmentList);
			if (!seg_list) continue;

			if (!skip_init) {
				GF_SAFEALLOC(seg_list->initialization_segment, GF_MPD_URL);
				if (!seg_list->initialization_segment) continue;

				seg_list->initialization_segment->sourceURL = gf_strdup(szInitSegmentFilename);
			}
			seg_list->dasher_segment_name = gf_strdup(szSegmentName);
			seg_list->timescale = ds->mpd_timescale;
			seg_list->segment_URLs = gf_list_new();
			seg_list->start_number = (u32) -1;
			seg_list->duration = (u64) (ds->dash_dur.num) * ds->mpd_timescale / ds->dash_dur.den;
			rep->segment_list = seg_list;
			ds->pending_segment_urls = gf_list_new();


static void js_file_finalize(JSRuntime *rt, JSValue obj)
{
	FILE *f = JS_GetOpaque(obj, file_class_id);
	if (!f) return;
	gf_fclose(f);


GF_Err gf_sm_load_init_svg(GF_SceneLoader *load)
{
	load->process = load_svg_run;
	load->done = load_svg_done;
	load->parse_string = load_svg_parse_string;
	load->suspend = load_svg_suspend;

	return GF_OK;

}


typedef struct
{
	//this is not the template string, this is the resolved segment name for first segment, startNumber=0 and time=0
	char *tpl;
	u32 nb_reused;
} DashTemplateRecord;

static u32 dasher_check_template_reuse(GF_DasherCtx *ctx, const char *tpl)
{
	DashTemplateRecord *tr;
	u32 i, count = gf_list_count(ctx->tpl_records);
	for (i=0; i<count; i++) {
		tr = gf_list_get(ctx->tpl_records, i);
		if (!strcmp(tr->tpl, tpl)) {
			tr->nb_reused++;
			return tr->nb_reused;


RE_NODE* yr_re_node_create(
    int type,
    RE_NODE* left,
    RE_NODE* right)
{
  RE_NODE* result = (RE_NODE*) yr_malloc(sizeof(RE_NODE));

  if (result != NULL)
  {
    result->type = type;
    result->left = left;
    result->right = right;
    result->greedy = TRUE;
    result->forward_code = NULL;
    result->backward_code = NULL;
  }

  return result;
}


int yr_execute_code(
    YR_RULES* rules,
    YR_SCAN_CONTEXT* context,
    int timeout,
    time_t start_time)
{
  int64_t mem[MEM_SIZE];
  int32_t sp = 0;
  uint8_t* ip = rules->code_start;

  YR_VALUE args[MAX_FUNCTION_ARGS];
  YR_VALUE *stack;
  YR_VALUE r1;
  YR_VALUE r2;
  YR_VALUE r3;

  #ifdef PROFILING_ENABLED
  YR_RULE* current_rule = NULL;
  #endif

  YR_RULE* rule;
  YR_MATCH* match;
  YR_OBJECT_FUNCTION* function;

  char* identifier;
  char* args_fmt;

  int i;
  int found;
  int count;
  int result = ERROR_SUCCESS;
  int stop = FALSE;
  int cycle = 0;
  int tidx = context->tidx;
  int stack_size;

  #ifdef PROFILING_ENABLED
  clock_t start = clock();
  #endif

  yr_get_configuration(YR_CONFIG_STACK_SIZE, (void*) &stack_size);

  stack = (YR_VALUE*) yr_malloc(stack_size * sizeof(YR_VALUE));

  if (stack == NULL)
    return ERROR_INSUFFICIENT_MEMORY;

  while(!stop)
  {
    switch(*ip)
    {
      case OP_HALT:
        assert(sp == 0); // When HALT is reached the stack should be empty.
        stop = TRUE;
        break;

      case OP_PUSH:
        r1.i = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        push(r1);
        break;

      case OP_POP:
        pop(r1);
        break;

      case OP_CLEAR_M:
        r1.i = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        mem[r1.i] = 0;
        break;

      case OP_ADD_M:
        r1.i = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        pop(r2);
        if (!is_undef(r2))
          mem[r1.i] += r2.i;
        break;

      case OP_INCR_M:
        r1.i = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        mem[r1.i]++;
        break;

      case OP_PUSH_M:
        r1.i = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        r1.i = mem[r1.i];
        push(r1);
        break;

      case OP_POP_M:
        r1.i = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        pop(r2);
        mem[r1.i] = r2.i;
        break;

      case OP_SWAPUNDEF:
        r1.i = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        pop(r2);

        if (is_undef(r2))
        {
          r1.i = mem[r1.i];
          push(r1);
        }
        else
        {
          push(r2);
        }
        break;

      case OP_JNUNDEF:
        pop(r1);
        push(r1);

        ip = jmp_if(!is_undef(r1), ip);
        break;

      case OP_JLE:
        pop(r2);
        pop(r1);
        push(r1);
        push(r2);

        ip = jmp_if(r1.i <= r2.i, ip);
        break;

      case OP_JTRUE:
        pop(r1);
        push(r1);

        ip = jmp_if(!is_undef(r1) && r1.i, ip);
        break;

      case OP_JFALSE:
        pop(r1);
        push(r1);

        ip = jmp_if(is_undef(r1) || !r1.i, ip);
        break;

      case OP_AND:
        pop(r2);
        pop(r1);

        if (is_undef(r1) || is_undef(r2))
          r1.i = 0;
        else
          r1.i = r1.i && r2.i;

        push(r1);
        break;

      case OP_OR:
        pop(r2);
        pop(r1);

        if (is_undef(r1))
        {
          push(r2);
        }
        else if (is_undef(r2))
        {
          push(r1);
        }
        else
        {
          r1.i = r1.i || r2.i;
          push(r1);
        }
        break;

      case OP_NOT:
        pop(r1);

        if (is_undef(r1))
          r1.i = UNDEFINED;
        else
          r1.i= !r1.i;

        push(r1);
        break;

      case OP_MOD:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        if (r2.i != 0)
          r1.i = r1.i % r2.i;
        else
          r1.i = UNDEFINED;
        push(r1);
        break;

      case OP_SHR:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i >> r2.i;
        push(r1);
        break;

      case OP_SHL:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i << r2.i;
        push(r1);
        break;

      case OP_BITWISE_NOT:
        pop(r1);
        ensure_defined(r1);
        r1.i = ~r1.i;
        push(r1);
        break;

      case OP_BITWISE_AND:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i & r2.i;
        push(r1);
        break;

      case OP_BITWISE_OR:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i | r2.i;
        push(r1);
        break;

      case OP_BITWISE_XOR:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i ^ r2.i;
        push(r1);
        break;

      case OP_PUSH_RULE:
        rule = *(YR_RULE**)(ip + 1);
        ip += sizeof(uint64_t);
        r1.i = rule->t_flags[tidx] & RULE_TFLAGS_MATCH ? 1 : 0;
        push(r1);
        break;

      case OP_INIT_RULE:
        #ifdef PROFILING_ENABLED
        current_rule = *(YR_RULE**)(ip + 1);
        #endif
        ip += sizeof(uint64_t);
        break;

      case OP_MATCH_RULE:
        pop(r1);
        rule = *(YR_RULE**)(ip + 1);
        ip += sizeof(uint64_t);

        if (!is_undef(r1) && r1.i)
          rule->t_flags[tidx] |= RULE_TFLAGS_MATCH;
        else if (RULE_IS_GLOBAL(rule))
          rule->ns->t_flags[tidx] |= NAMESPACE_TFLAGS_UNSATISFIED_GLOBAL;

        #ifdef PROFILING_ENABLED
        rule->clock_ticks += clock() - start;
        start = clock();
        #endif
        break;

      case OP_OBJ_LOAD:
        identifier = *(char**)(ip + 1);
        ip += sizeof(uint64_t);

        r1.o = (YR_OBJECT*) yr_hash_table_lookup(
            context->objects_table,
            identifier,
            NULL);

        assert(r1.o != NULL);
        push(r1);
        break;

      case OP_OBJ_FIELD:
        identifier = *(char**)(ip + 1);
        ip += sizeof(uint64_t);

        pop(r1);
        ensure_defined(r1);

        r1.o = yr_object_lookup_field(r1.o, identifier);

        assert(r1.o != NULL);
        push(r1);
        break;

      case OP_OBJ_VALUE:
        pop(r1);
        ensure_defined(r1);

        switch(r1.o->type)
        {
          case OBJECT_TYPE_INTEGER:
            r1.i = ((YR_OBJECT_INTEGER*) r1.o)->value;
            break;

          case OBJECT_TYPE_FLOAT:
            if (isnan(((YR_OBJECT_DOUBLE*) r1.o)->value))
              r1.i = UNDEFINED;
            else
              r1.d = ((YR_OBJECT_DOUBLE*) r1.o)->value;
            break;

          case OBJECT_TYPE_STRING:
            if (((YR_OBJECT_STRING*) r1.o)->value == NULL)
              r1.i = UNDEFINED;
            else
              r1.p = ((YR_OBJECT_STRING*) r1.o)->value;
            break;

          default:
            assert(FALSE);
        }

        push(r1);
        break;

      case OP_INDEX_ARRAY:
        pop(r1);  // index
        pop(r2);  // array

        ensure_defined(r1);
        ensure_defined(r2);
        assert(r2.o->type == OBJECT_TYPE_ARRAY);

        r1.o = yr_object_array_get_item(r2.o, 0, (int) r1.i);

        if (r1.o == NULL)
          r1.i = UNDEFINED;

        push(r1);
        break;

      case OP_LOOKUP_DICT:
        pop(r1);  // key
        pop(r2);  // dictionary

        ensure_defined(r1);
        ensure_defined(r2);
        assert(r2.o->type == OBJECT_TYPE_DICTIONARY);

        r1.o = yr_object_dict_get_item(
            r2.o, 0, r1.ss->c_string);

        if (r1.o == NULL)
          r1.i = UNDEFINED;

        push(r1);
        break;

      case OP_CALL:
        args_fmt = *(char**)(ip + 1);
        ip += sizeof(uint64_t);

        i = (int) strlen(args_fmt);
        count = 0;

        // pop arguments from stack and copy them to args array

        while (i > 0)
        {
          pop(r1);

          if (is_undef(r1))  // count the number of undefined args
            count++;

          args[i - 1] = r1;
          i--;
        }

        pop(r2);
        ensure_defined(r2);

        if (count > 0)
        {
          // if there are undefined args, result for function call
          // is undefined as well.

          r1.i = UNDEFINED;
          push(r1);
          break;
        }

        function = (YR_OBJECT_FUNCTION*) r2.o;
        result = ERROR_INTERNAL_FATAL_ERROR;

        for (i = 0; i < MAX_OVERLOADED_FUNCTIONS; i++)
        {
          if (function->prototypes[i].arguments_fmt == NULL)
            break;

          if (strcmp(function->prototypes[i].arguments_fmt, args_fmt) == 0)
          {
            result = function->prototypes[i].code(args, context, function);
            break;
          }
        }

        assert(i < MAX_OVERLOADED_FUNCTIONS);

        if (result == ERROR_SUCCESS)
        {
          r1.o = function->return_obj;
          push(r1);
        }
        else
        {
          stop = TRUE;
        }

        break;

      case OP_FOUND:
        pop(r1);
        r1.i = r1.s->matches[tidx].tail != NULL ? 1 : 0;
        push(r1);
        break;

      case OP_FOUND_AT:
        pop(r2);
        pop(r1);

        if (is_undef(r1))
        {
          r1.i = 0;
          push(r1);
          break;
        }

        match = r2.s->matches[tidx].head;
        r3.i = FALSE;

        while (match != NULL)
        {
          if (r1.i == match->base + match->offset)
          {
            r3.i = TRUE;
            break;
          }

          if (r1.i < match->base + match->offset)
            break;

          match = match->next;
        }

        push(r3);
        break;

      case OP_FOUND_IN:
        pop(r3);
        pop(r2);
        pop(r1);

        ensure_defined(r1);
        ensure_defined(r2);

        match = r3.s->matches[tidx].head;
        r3.i = FALSE;

        while (match != NULL && !r3.i)
        {
          if (match->base + match->offset >= r1.i &&
              match->base + match->offset <= r2.i)
          {
            r3.i = TRUE;
          }

          if (match->base + match->offset > r2.i)
            break;

          match = match->next;
        }

        push(r3);
        break;

      case OP_COUNT:
        pop(r1);
        r1.i = r1.s->matches[tidx].count;
        push(r1);
        break;

      case OP_OFFSET:
        pop(r2);
        pop(r1);

        ensure_defined(r1);

        match = r2.s->matches[tidx].head;
        i = 1;
        r3.i = UNDEFINED;

        while (match != NULL && r3.i == UNDEFINED)
        {
          if (r1.i == i)
            r3.i = match->base + match->offset;

          i++;
          match = match->next;
        }

        push(r3);
        break;

      case OP_LENGTH:
        pop(r2);
        pop(r1);

        ensure_defined(r1);

        match = r2.s->matches[tidx].head;
        i = 1;
        r3.i = UNDEFINED;

        while (match != NULL && r3.i == UNDEFINED)
        {
          if (r1.i == i)
            r3.i = match->match_length;

          i++;
          match = match->next;
        }

        push(r3);
        break;

      case OP_OF:
        found = 0;
        count = 0;
        pop(r1);

        while (!is_undef(r1))
        {
          if (r1.s->matches[tidx].tail != NULL)
            found++;
          count++;
          pop(r1);
        }

        pop(r2);

        if (is_undef(r2))
          r1.i = found >= count ? 1 : 0;
        else
          r1.i = found >= r2.i ? 1 : 0;

        push(r1);
        break;

      case OP_FILESIZE:
        r1.i = context->file_size;
        push(r1);
        break;

      case OP_ENTRYPOINT:
        r1.i = context->entry_point;
        push(r1);
        break;

      case OP_INT8:
        pop(r1);
        r1.i = read_int8_t_little_endian(context->iterator, (size_t) r1.i);
        push(r1);
        break;

      case OP_INT16:
        pop(r1);
        r1.i = read_int16_t_little_endian(context->iterator, (size_t) r1.i);
        push(r1);
        break;

      case OP_INT32:
        pop(r1);
        r1.i = read_int32_t_little_endian(context->iterator, (size_t) r1.i);
        push(r1);
        break;

      case OP_UINT8:
        pop(r1);
        r1.i = read_uint8_t_little_endian(context->iterator, (size_t) r1.i);
        push(r1);
        break;

      case OP_UINT16:
        pop(r1);
        r1.i = read_uint16_t_little_endian(context->iterator, (size_t) r1.i);
        push(r1);
        break;

      case OP_UINT32:
        pop(r1);
        r1.i = read_uint32_t_little_endian(context->iterator, (size_t) r1.i);
        push(r1);
        break;

      case OP_INT8BE:
        pop(r1);
        r1.i = read_int8_t_big_endian(context->iterator, (size_t) r1.i);
        push(r1);
        break;

      case OP_INT16BE:
        pop(r1);
        r1.i = read_int16_t_big_endian(context->iterator, (size_t) r1.i);
        push(r1);
        break;

      case OP_INT32BE:
        pop(r1);
        r1.i = read_int32_t_big_endian(context->iterator, (size_t) r1.i);
        push(r1);
        break;

      case OP_UINT8BE:
        pop(r1);
        r1.i = read_uint8_t_big_endian(context->iterator, (size_t) r1.i);
        push(r1);
        break;

      case OP_UINT16BE:
        pop(r1);
        r1.i = read_uint16_t_big_endian(context->iterator, (size_t) r1.i);
        push(r1);
        break;

      case OP_UINT32BE:
        pop(r1);
        r1.i = read_uint32_t_big_endian(context->iterator, (size_t) r1.i);
        push(r1);
        break;

      case OP_CONTAINS:
        pop(r2);
        pop(r1);

        ensure_defined(r1);
        ensure_defined(r2);

        r1.i = memmem(r1.ss->c_string, r1.ss->length,
                      r2.ss->c_string, r2.ss->length) != NULL;
        push(r1);
        break;

      case OP_IMPORT:
        r1.i = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);

        result = yr_modules_load((char*) r1.p, context);

        if (result != ERROR_SUCCESS)
          stop = TRUE;

        break;

      case OP_MATCHES:

        pop(r2);
        pop(r1);

        ensure_defined(r2);
        ensure_defined(r1);

        if (r1.ss->length == 0)
        {
          r1.i = FALSE;
          push(r1);
          break;
        }

        r1.i = yr_re_exec(
          (uint8_t*) r2.re->code,
          (uint8_t*) r1.ss->c_string,
          r1.ss->length,
          0,
          r2.re->flags | RE_FLAGS_SCAN,
          NULL,
          NULL) >= 0;

        push(r1);
        break;

      case OP_INT_TO_DBL:
        r1.i = *(uint64_t*)(ip + 1);
        ip += sizeof(uint64_t);
        r2 = stack[sp - r1.i];
        if (is_undef(r2))
          stack[sp - r1.i].i = UNDEFINED;
        else
          stack[sp - r1.i].d = (double) r2.i;
        break;

      case OP_STR_TO_BOOL:
        pop(r1);
        ensure_defined(r1);
        r1.i = r1.ss->length > 0;
        push(r1);
        break;

      case OP_INT_EQ:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i == r2.i;
        push(r1);
        break;

      case OP_INT_NEQ:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i != r2.i;
        push(r1);
        break;

      case OP_INT_LT:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i < r2.i;
        push(r1);
        break;

      case OP_INT_GT:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i > r2.i;
        push(r1);
        break;

      case OP_INT_LE:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i <= r2.i;
        push(r1);
        break;

      case OP_INT_GE:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i >= r2.i;
        push(r1);
        break;

      case OP_INT_ADD:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i + r2.i;
        push(r1);
        break;

      case OP_INT_SUB:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i - r2.i;
        push(r1);
        break;

      case OP_INT_MUL:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.i * r2.i;
        push(r1);
        break;

      case OP_INT_DIV:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        if (r2.i != 0)
          r1.i = r1.i / r2.i;
        else
          r1.i = UNDEFINED;
        push(r1);
        break;

      case OP_INT_MINUS:
        pop(r1);
        ensure_defined(r1);
        r1.i = -r1.i;
        push(r1);
        break;

      case OP_DBL_LT:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.d < r2.d;
        push(r1);
        break;

      case OP_DBL_GT:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.d > r2.d;
        push(r1);
        break;

      case OP_DBL_LE:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.d <= r2.d;
        push(r1);
        break;

      case OP_DBL_GE:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.d >= r2.d;
        push(r1);
        break;

      case OP_DBL_EQ:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.d == r2.d;
        push(r1);
        break;

      case OP_DBL_NEQ:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.i = r1.d != r2.d;
        push(r1);
        break;

      case OP_DBL_ADD:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.d = r1.d + r2.d;
        push(r1);
        break;

      case OP_DBL_SUB:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.d = r1.d - r2.d;
        push(r1);
        break;

      case OP_DBL_MUL:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.d = r1.d * r2.d;
        push(r1);
        break;

      case OP_DBL_DIV:
        pop(r2);
        pop(r1);
        ensure_defined(r2);
        ensure_defined(r1);
        r1.d = r1.d / r2.d;
        push(r1);
        break;

      case OP_DBL_MINUS:
        pop(r1);
        ensure_defined(r1);
        r1.d = -r1.d;
        push(r1);
        break;

      case OP_STR_EQ:
      case OP_STR_NEQ:
      case OP_STR_LT:
      case OP_STR_LE:
      case OP_STR_GT:
      case OP_STR_GE:

        pop(r2);
        pop(r1);

        ensure_defined(r1);
        ensure_defined(r2);

        switch(*ip)
        {
          case OP_STR_EQ:
            r1.i = (sized_string_cmp(r1.ss, r2.ss) == 0);
            break;
          case OP_STR_NEQ:
            r1.i = (sized_string_cmp(r1.ss, r2.ss) != 0);
            break;
          case OP_STR_LT:
            r1.i = (sized_string_cmp(r1.ss, r2.ss) < 0);
            break;
          case OP_STR_LE:
            r1.i = (sized_string_cmp(r1.ss, r2.ss) <= 0);
            break;
          case OP_STR_GT:
            r1.i = (sized_string_cmp(r1.ss, r2.ss) > 0);
            break;
          case OP_STR_GE:
            r1.i = (sized_string_cmp(r1.ss, r2.ss) >= 0);
            break;
        }

        push(r1);
        break;

      default:
        // Unknown instruction, this shouldn't happen.
        assert(FALSE);
    }

    if (timeout > 0)  // timeout == 0 means no timeout
    {
      // Check for timeout every 10 instruction cycles.

      if (++cycle == 10)
      {
        if (difftime(time(NULL), start_time) > timeout)
        {
          #ifdef PROFILING_ENABLED
          assert(current_rule != NULL);
          current_rule->clock_ticks += clock() - start;
          #endif
          result = ERROR_SCAN_TIMEOUT;
          stop = TRUE;
        }

        cycle = 0;
      }
    }

    ip++;
  }

  yr_modules_unload_all(context);
  yr_free(stack);

  return result;


int _yr_emit_inst_arg_uint32(
    RE_EMIT_CONTEXT* emit_context,
    uint8_t opcode,
    uint32_t argument,
    uint8_t** instruction_addr,
    uint32_t** argument_addr,
    int* code_size)
{
  FAIL_ON_ERROR(yr_arena_write_data(
      emit_context->arena,
      &opcode,
      sizeof(uint8_t),
      (void**) instruction_addr));

  FAIL_ON_ERROR(yr_arena_write_data(
      emit_context->arena,
      &argument,
      sizeof(uint32_t),
      (void**) argument_addr));

  *code_size = sizeof(uint8_t) + sizeof(uint32_t);

  return ERROR_SUCCESS;
}


static int _6502_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {
	char addrbuf[64];
	const int buffsize = sizeof (addrbuf) - 1;

	memset (op, '\0', sizeof (RAnalOp));
	op->size = snes_op_get_size (1, 1, &snes_op[data[0]]);	//snes-arch is similiar to nes/6502
	op->addr = addr;
	op->type = R_ANAL_OP_TYPE_UNK;
	op->id = data[0];
	r_strbuf_init (&op->esil);
	switch (data[0]) {
	case 0x02:
	case 0x03:
	case 0x04:
	case 0x07:
	case 0x0b:
	case 0x0c:
	case 0x0f:
	case 0x12:
	case 0x13:
	case 0x14:
	case 0x17:
	case 0x1a:
	case 0x1b:
	case 0x1c:
	case 0x1f:
	case 0x22:
	case 0x23:
	case 0x27:
	case 0x2b:
	case 0x2f:
	case 0x32:
	case 0x33:
	case 0x34:
	case 0x37:
	case 0x3a:
	case 0x3b:
	case 0x3c:
	case 0x3f:
	case 0x42:
	case 0x43:
	case 0x44:
	case 0x47:
	case 0x4b:
	case 0x4f:
	case 0x52:
	case 0x53:
	case 0x54:
	case 0x57:
	case 0x5a:
	case 0x5b:
	case 0x5c:
	case 0x5f:
	case 0x62:
	case 0x63:
	case 0x64:
	case 0x67:
	case 0x6b:
	case 0x6f:
	case 0x72:
	case 0x73:
	case 0x74:
	case 0x77:
	case 0x7a:
	case 0x7b:
	case 0x7c:
	case 0x7f:
	case 0x80:
	case 0x82:
	case 0x83:
	case 0x87:
	case 0x89:
	case 0x8b:
	case 0x8f:
	case 0x92:
	case 0x93:
	case 0x97:
	case 0x9b:
	case 0x9c:
	case 0x9e:
	case 0x9f:
	case 0xa3:
	case 0xa7:
	case 0xab:
	case 0xaf:
	case 0xb2:
	case 0xb3:
	case 0xb7:
	case 0xbb:
	case 0xbf:
	case 0xc2:
	case 0xc3:
	case 0xc7:
	case 0xcb:
	case 0xcf:
	case 0xd2:
	case 0xd3:
	case 0xd4:
	case 0xd7:
	case 0xda:
	case 0xdb:
	case 0xdc:
	case 0xdf:
	case 0xe2:
	case 0xe3:
	case 0xe7:
	case 0xeb:
	case 0xef:
	case 0xf2:
	case 0xf3:
	case 0xf4:
	case 0xf7:
	case 0xfa:
	case 0xfb:
	case 0xfc:
	case 0xff:
		// undocumented or not-implemented opcodes for 6502.
		// some of them might be implemented in 65816
		op->size = 1;
		op->type = R_ANAL_OP_TYPE_ILL;
		break;

	// BRK
	case 0x00: // brk
		op->cycles = 7;
		op->type = R_ANAL_OP_TYPE_SWI;
		// override 65816 code which seems to be wrong: size is 1, but pc = pc + 2
		op->size = 1;
		// PC + 2 to Stack, P to Stack  B=1 D=0 I=1. "B" is not a flag. Only its bit is pushed on the stack
		// PC was already incremented by one at this point. Needs to incremented once more
		// New PC is Interrupt Vector: $fffe. (FIXME: Confirm this is valid for all 6502)
		r_strbuf_set (&op->esil, ",1,I,=,0,D,=,flags,0x10,|,0x100,sp,+,=[1],pc,1,+,0xfe,sp,+,=[2],3,sp,-=,0xfffe,[2],pc,=");
		break;

	// FLAGS
	case 0x78: // sei
	case 0x58: // cli
	case 0x38: // sec
	case 0x18: // clc
	case 0xf8: // sed
	case 0xd8: // cld
	case 0xb8: // clv
		op->cycles = 2;
		// FIXME: what opcode for this?
		op->type = R_ANAL_OP_TYPE_NOP;
		_6502_anal_esil_flags (op, data[0]);
		break;
	// BIT
	case 0x24: // bit $ff
	case 0x2c: // bit $ffff
		op->type = R_ANAL_OP_TYPE_MOV;
		_6502_anal_esil_get_addr_pattern3 (op, data, addrbuf, buffsize, 0);
		r_strbuf_setf (&op->esil, "a,%s,[1],&,0x80,&,!,!,N,=,a,%s,[1],&,0x40,&,!,!,V,=,a,%s,[1],&,0xff,&,!,Z,=",addrbuf, addrbuf, addrbuf);
		break;
	// ADC
	case 0x69: // adc #$ff
	case 0x65: // adc $ff
	case 0x75: // adc $ff,x
	case 0x6d: // adc $ffff
	case 0x7d: // adc $ffff,x
	case 0x79: // adc $ffff,y
	case 0x61: // adc ($ff,x)
	case 0x71: // adc ($ff,y)
		// FIXME: update V
		// FIXME: support BCD mode
		op->type = R_ANAL_OP_TYPE_ADD;
		_6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize);
		if (data[0] == 0x69) // immediate mode
			r_strbuf_setf (&op->esil, "%s,a,+=,C,NUM,$c7,C,=,a,+=,$c7,C,|=", addrbuf);
		else	r_strbuf_setf (&op->esil, "%s,[1],a,+=,C,NUM,$c7,C,=,a,+=,$c7,C,|=", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		// fix Z
		r_strbuf_append (&op->esil, ",a,a,=,$z,Z,=");
		break;
	// SBC
	case 0xe9: // sbc #$ff
	case 0xe5: // sbc $ff
	case 0xf5: // sbc $ff,x
	case 0xed: // sbc $ffff
	case 0xfd: // sbc $ffff,x
	case 0xf9: // sbc $ffff,y
	case 0xe1: // sbc ($ff,x)
	case 0xf1: // sbc ($ff,y)
		// FIXME: update V
		// FIXME: support BCD mode
		op->type = R_ANAL_OP_TYPE_SUB;
		_6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize);
		if (data[0] == 0xe9) // immediate mode
			r_strbuf_setf (&op->esil, "C,!,%s,+,a,-=", addrbuf);
		else	r_strbuf_setf (&op->esil, "C,!,%s,[1],+,a,-=", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_BNZ);
		// fix Z and revert C
		r_strbuf_append (&op->esil, ",a,a,=,$z,Z,=,C,!=");
		break;
	// ORA
	case 0x09: // ora #$ff
	case 0x05: // ora $ff
	case 0x15: // ora $ff,x
	case 0x0d: // ora $ffff
	case 0x1d: // ora $ffff,x
	case 0x19: // ora $ffff,y
	case 0x01: // ora ($ff,x)
	case 0x11: // ora ($ff),y
		op->type = R_ANAL_OP_TYPE_OR;
		_6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize);
		if (data[0] == 0x09) // immediate mode
			r_strbuf_setf (&op->esil, "%s,a,|=", addrbuf);
		else	r_strbuf_setf (&op->esil, "%s,[1],a,|=", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		break;
	// AND
	case 0x29: // and #$ff
	case 0x25: // and $ff
	case 0x35: // and $ff,x
	case 0x2d: // and $ffff
	case 0x3d: // and $ffff,x
	case 0x39: // and $ffff,y
	case 0x21: // and ($ff,x)
	case 0x31: // and ($ff),y
		op->type = R_ANAL_OP_TYPE_AND;
		_6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize);
		if (data[0] == 0x29) // immediate mode
			r_strbuf_setf (&op->esil, "%s,a,&=", addrbuf);
		else	r_strbuf_setf (&op->esil, "%s,[1],a,&=", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		break;
	// EOR
	case 0x49: // eor #$ff
	case 0x45: // eor $ff
	case 0x55: // eor $ff,x
	case 0x4d: // eor $ffff
	case 0x5d: // eor $ffff,x
	case 0x59: // eor $ffff,y
	case 0x41: // eor ($ff,x)
	case 0x51: // eor ($ff),y
		op->type = R_ANAL_OP_TYPE_XOR;
		_6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize);
		if (data[0] == 0x49) // immediate mode
			r_strbuf_setf (&op->esil, "%s,a,^=", addrbuf);
		else	r_strbuf_setf (&op->esil, "%s,[1],a,^=", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		break;
	// ASL
	case 0x0a: // asl a
	case 0x06: // asl $ff
	case 0x16: // asl $ff,x
	case 0x0e: // asl $ffff
	case 0x1e: // asl $ffff,x
		op->type = R_ANAL_OP_TYPE_SHL;
		if (data[0] == 0x0a) {
			r_strbuf_set (&op->esil, "1,a,<<=,$c7,C,=,a,a,=");
		} else  {
			_6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'x');
			r_strbuf_setf (&op->esil, "1,%s,[1],<<,%s,=[1],$c7,C,=", addrbuf, addrbuf);
		}
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		break;
	// LSR
	case 0x4a: // lsr a
	case 0x46: // lsr $ff
	case 0x56: // lsr $ff,x
	case 0x4e: // lsr $ffff
	case 0x5e: // lsr $ffff,x
		op->type = R_ANAL_OP_TYPE_SHR;
		if (data[0] == 0x4a) {
			r_strbuf_set (&op->esil, "1,a,&,C,=,1,a,>>=");
		} else {
			_6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'x');
			r_strbuf_setf (&op->esil, "1,%s,[1],&,C,=,1,%s,[1],>>,%s,=[1]", addrbuf, addrbuf, addrbuf);
		}
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		break;
	// ROL
	case 0x2a: // rol a
	case 0x26: // rol $ff
	case 0x36: // rol $ff,x
	case 0x2e: // rol $ffff
	case 0x3e: // rol $ffff,x
		op->type = R_ANAL_OP_TYPE_ROL;
		if (data[0] == 0x2a) {
			r_strbuf_set (&op->esil, "1,a,<<,C,|,a,=,$c7,C,=,a,a,=");
		} else {
			_6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'x');
			r_strbuf_setf (&op->esil, "1,%s,[1],<<,C,|,%s,=[1],$c7,C,=", addrbuf, addrbuf);
		}
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		break;
	// ROR
	case 0x6a: // ror a
	case 0x66: // ror $ff
	case 0x76: // ror $ff,x
	case 0x6e: // ror $ffff
	case 0x7e: // ror $ffff,x
		// uses N as temporary to hold C value. but in fact,
		// it is not temporary since in all ROR ops, N will have the value of C
		op->type = R_ANAL_OP_TYPE_ROR;
		if (data[0] == 0x6a) {
			r_strbuf_set (&op->esil, "C,N,=,1,a,&,C,=,1,a,>>,7,N,<<,|,a,=");
		} else {
			_6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'x');
			r_strbuf_setf (&op->esil, "C,N,=,1,%s,[1],&,C,=,1,%s,[1],>>,7,N,<<,|,%s,=[1]", addrbuf, addrbuf, addrbuf);
		}
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		break;
	// INC
	case 0xe6: // inc $ff
	case 0xf6: // inc $ff,x
	case 0xee: // inc $ffff
	case 0xfe: // inc $ffff,x
		op->type = R_ANAL_OP_TYPE_STORE;
		_6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'x');
		r_strbuf_setf (&op->esil, "%s,++=[1]", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		break;
	// DEC
	case 0xc6: // dec $ff
	case 0xd6: // dec $ff,x
	case 0xce: // dec $ffff
	case 0xde: // dec $ffff,x
		op->type = R_ANAL_OP_TYPE_STORE;
		_6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'x');
		r_strbuf_setf (&op->esil, "%s,--=[1]", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		break;
	// INX, INY
	case 0xe8: // inx
	case 0xc8: // iny
		op->cycles = 2;
		op->type = R_ANAL_OP_TYPE_STORE;
		_6502_anal_esil_inc_reg (op, data[0], "+");
		break;
	// DEX, DEY
	case 0xca: // dex
	case 0x88: // dey
		op->cycles = 2;
		op->type = R_ANAL_OP_TYPE_STORE;
		_6502_anal_esil_inc_reg (op, data[0], "-");
		break;
	// CMP
	case 0xc9: // cmp #$ff
	case 0xc5: // cmp $ff
	case 0xd5: // cmp $ff,x
	case 0xcd: // cmp $ffff
	case 0xdd: // cmp $ffff,x
	case 0xd9: // cmp $ffff,y
	case 0xc1: // cmp ($ff,x)
	case 0xd1: // cmp ($ff),y
		op->type = R_ANAL_OP_TYPE_CMP;
		_6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize);
		if (data[0] == 0xc9) // immediate mode
			r_strbuf_setf (&op->esil, "%s,a,==", addrbuf);
		else	r_strbuf_setf (&op->esil, "%s,[1],a,==", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_BNZ);
		// invert C, since C=1 when A-M >= 0
		r_strbuf_append (&op->esil, ",C,!,C,=");
		break;
	// CPX
	case 0xe0: // cpx #$ff
	case 0xe4: // cpx $ff
	case 0xec: // cpx $ffff
		op->type = R_ANAL_OP_TYPE_CMP;
		_6502_anal_esil_get_addr_pattern3 (op, data, addrbuf, buffsize, 0);
		if (data[0] == 0xe0) // immediate mode
			r_strbuf_setf (&op->esil, "%s,x,==", addrbuf);
		else	r_strbuf_setf (&op->esil, "%s,[1],x,==", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_BNZ);
		// invert C, since C=1 when A-M >= 0
		r_strbuf_append (&op->esil, ",C,!,C,=");
		break;
	// CPY
	case 0xc0: // cpy #$ff
	case 0xc4: // cpy $ff
	case 0xcc: // cpy $ffff
		op->type = R_ANAL_OP_TYPE_CMP;
		_6502_anal_esil_get_addr_pattern3 (op, data, addrbuf, buffsize, 0);
		if (data[0] == 0xc0) // immediate mode
			r_strbuf_setf (&op->esil, "%s,y,==", addrbuf);
		else	r_strbuf_setf (&op->esil, "%s,[1],y,==", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_BNZ);
		// invert C, since C=1 when A-M >= 0
		r_strbuf_append (&op->esil, ",C,!,C,=");
		break;
	// BRANCHES
	case 0x10: // bpl $ffff
	case 0x30: // bmi $ffff
	case 0x50: // bvc $ffff
	case 0x70: // bvs $ffff
	case 0x90: // bcc $ffff
	case 0xb0: // bcs $ffff
	case 0xd0: // bne $ffff
	case 0xf0: // beq $ffff
		// FIXME: Add 1 if branch occurs to same page.
		// FIXME: Add 2 if branch occurs to different page
		op->cycles = 2;
		op->failcycles = 3;
		op->type = R_ANAL_OP_TYPE_CJMP;
		if (len > 1) {
			if (data[1] <= 127) {
				op->jump = addr + data[1] + op->size;
			} else {
				op->jump = addr - (256 - data[1]) + op->size;
			}
		} else {
			op->jump = addr;
		}
		op->fail = addr + op->size;
		// FIXME: add a type of conditional
		// op->cond = R_ANAL_COND_LE;
		_6502_anal_esil_ccall (op, data[0]);
		break;
	// JSR
	case 0x20: // jsr $ffff
		op->cycles = 6;
		op->type = R_ANAL_OP_TYPE_CALL;
		op->jump = data[1] | data[2] << 8;
		op->stackop = R_ANAL_STACK_INC;
		op->stackptr = 2;
		// JSR pushes the address-1 of the next operation on to the stack before transferring program
		// control to the following address
		// stack is on page one and sp is an 8-bit reg: operations must be done like: sp + 0x100
		r_strbuf_setf (&op->esil, "1,pc,-,0xff,sp,+,=[2],0x%04x,pc,=,2,sp,-=", op->jump);
		break;
	// JMP
	case 0x4c: // jmp $ffff
		op->cycles = 3;
		op->type = R_ANAL_OP_TYPE_JMP;
		op->jump = data[1] | data[2] << 8;
		r_strbuf_setf (&op->esil, "0x%04x,pc,=", op->jump);
		break;
	case 0x6c: // jmp ($ffff)
		op->cycles = 5;
		op->type = R_ANAL_OP_TYPE_UJMP;
		// FIXME: how to read memory?
		// op->jump = data[1] | data[2] << 8;
		r_strbuf_setf (&op->esil, "0x%04x,[2],pc,=", data[1] | data[2] << 8);
		break;
	// RTS
	case 0x60: // rts
		op->eob = true;
		op->type = R_ANAL_OP_TYPE_RET;
		op->cycles = 6;
		op->stackop = R_ANAL_STACK_INC;
		op->stackptr = -2;
		// Operation:  PC from Stack, PC + 1 -> PC
		// stack is on page one and sp is an 8-bit reg: operations must be done like: sp + 0x100
		r_strbuf_set (&op->esil, "0x101,sp,+,[2],pc,=,pc,++=,2,sp,+=");
		break;
	// RTI
	case 0x40: // rti
		op->eob = true;
		op->type = R_ANAL_OP_TYPE_RET;
		op->cycles = 6;
		op->stackop = R_ANAL_STACK_INC;
		op->stackptr = -3;
		// Operation: P from Stack, PC from Stack
		// stack is on page one and sp is an 8-bit reg: operations must be done like: sp + 0x100
		r_strbuf_set (&op->esil, "0x101,sp,+,[1],flags,=,0x102,sp,+,[2],pc,=,3,sp,+=");
		break;
	// NOP
	case 0xea: // nop
		op->type = R_ANAL_OP_TYPE_NOP;
		op->cycles = 2;
		break;
	// LDA
	case 0xa9: // lda #$ff
	case 0xa5: // lda $ff
	case 0xb5: // lda $ff,x
	case 0xad: // lda $ffff
	case 0xbd: // lda $ffff,x
	case 0xb9: // lda $ffff,y
	case 0xa1: // lda ($ff,x)
	case 0xb1: // lda ($ff),y
		op->type = R_ANAL_OP_TYPE_LOAD;
		_6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize);
		if (data[0] == 0xa9) // immediate mode
			r_strbuf_setf (&op->esil, "%s,a,=", addrbuf);
		else	r_strbuf_setf (&op->esil, "%s,[1],a,=", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		break;
	// LDX
	case 0xa2: // ldx #$ff
	case 0xa6: // ldx $ff
	case 0xb6: // ldx $ff,y
	case 0xae: // ldx $ffff
	case 0xbe: // ldx $ffff,y
		op->type = R_ANAL_OP_TYPE_LOAD;
		_6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'y');
		if (data[0] == 0xa2) // immediate mode
			r_strbuf_setf (&op->esil, "%s,x,=", addrbuf);
		else	r_strbuf_setf (&op->esil, "%s,[1],x,=", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		break;
	// LDY
	case 0xa0: // ldy #$ff
	case 0xa4: // ldy $ff
	case 0xb4: // ldy $ff,x
	case 0xac: // ldy $ffff
	case 0xbc: // ldy $ffff,x
		op->type = R_ANAL_OP_TYPE_LOAD;
		_6502_anal_esil_get_addr_pattern3 (op, data, addrbuf, buffsize, 'x');
		if (data[0] == 0xa0) // immediate mode
			r_strbuf_setf (&op->esil, "%s,y,=", addrbuf);
		else	r_strbuf_setf (&op->esil, "%s,[1],y,=", addrbuf);
		_6502_anal_update_flags (op, _6502_FLAGS_NZ);
		break;
	// STA
	case 0x85: // sta $ff
	case 0x95: // sta $ff,x
	case 0x8d: // sta $ffff
	case 0x9d: // sta $ffff,x
	case 0x99: // sta $ffff,y
	case 0x81: // sta ($ff,x)
	case 0x91: // sta ($ff),y
		op->type = R_ANAL_OP_TYPE_STORE;
		_6502_anal_esil_get_addr_pattern1 (op, data, addrbuf, buffsize);
		r_strbuf_setf (&op->esil, "a,%s,=[1]", addrbuf);
		break;
	// STX
	case 0x86: // stx $ff
	case 0x96: // stx $ff,y
	case 0x8e: // stx $ffff
		op->type = R_ANAL_OP_TYPE_STORE;
		_6502_anal_esil_get_addr_pattern2 (op, data, addrbuf, buffsize, 'y');
		r_strbuf_setf (&op->esil, "x,%s,=[1]", addrbuf);
		break;
	// STY
	case 0x84: // sty $ff
	case 0x94: // sty $ff,x
	case 0x8c: // sty $ffff
		op->type = R_ANAL_OP_TYPE_STORE;
		_6502_anal_esil_get_addr_pattern3 (op, data, addrbuf, buffsize, 'x');
		r_strbuf_setf (&op->esil, "y,%s,=[1]", addrbuf);
		break;
	// PHP/PHA
	case 0x08: // php
	case 0x48: // pha
		op->type = R_ANAL_OP_TYPE_PUSH;
		op->cycles = 3;
		op->stackop = R_ANAL_STACK_INC;
		op->stackptr = 1;
		_6502_anal_esil_push (op, data[0]);
		break;
	// PLP,PLA
	case 0x28: // plp
	case 0x68: // plp
		op->type = R_ANAL_OP_TYPE_POP;
		op->cycles = 4;
		op->stackop = R_ANAL_STACK_INC;
		op->stackptr = -1;
		_6502_anal_esil_pop (op, data[0]);
		break;
	// TAX,TYA,...
	case 0xaa: // tax
	case 0x8a: // txa
	case 0xa8: // tay
	case 0x98: // tya
		op->type = R_ANAL_OP_TYPE_MOV;
		op->cycles = 2;
		_6502_anal_esil_mov (op, data[0]);
		break;
	case 0x9a: // txs
		op->type = R_ANAL_OP_TYPE_MOV;
		op->cycles = 2;
		op->stackop = R_ANAL_STACK_SET;
		// FIXME: should I get register X a place it here?
		// op->stackptr = get_register_x();
		_6502_anal_esil_mov (op, data[0]);
		break;
	case 0xba: // tsx
		op->type = R_ANAL_OP_TYPE_MOV;
		op->cycles = 2;
		op->stackop = R_ANAL_STACK_GET;
		_6502_anal_esil_mov (op, data[0]);
		break;
	}
	return op->size;
}


kvm_pfn_t gfn_to_pfn_atomic(struct kvm *kvm, gfn_t gfn)
{
	return gfn_to_pfn_memslot_atomic(gfn_to_memslot(kvm, gfn), gfn);
}


int kvm_get_dirty_log_protect(struct kvm *kvm,
			struct kvm_dirty_log *log, bool *flush)
{
	struct kvm_memslots *slots;
	struct kvm_memory_slot *memslot;
	int i, as_id, id;
	unsigned long n;
	unsigned long *dirty_bitmap;
	unsigned long *dirty_bitmap_buffer;

	as_id = log->slot >> 16;
	id = (u16)log->slot;
	if (as_id >= KVM_ADDRESS_SPACE_NUM || id >= KVM_USER_MEM_SLOTS)
		return -EINVAL;

	slots = __kvm_memslots(kvm, as_id);
	memslot = id_to_memslot(slots, id);

	dirty_bitmap = memslot->dirty_bitmap;
	if (!dirty_bitmap)
		return -ENOENT;

	n = kvm_dirty_bitmap_bytes(memslot);
	*flush = false;
	if (kvm->manual_dirty_log_protect) {
		/*
		 * Unlike kvm_get_dirty_log, we always return false in *flush,
		 * because no flush is needed until KVM_CLEAR_DIRTY_LOG.  There
		 * is some code duplication between this function and
		 * kvm_get_dirty_log, but hopefully all architecture
		 * transition to kvm_get_dirty_log_protect and kvm_get_dirty_log
		 * can be eliminated.
		 */
		dirty_bitmap_buffer = dirty_bitmap;
	} else {
		dirty_bitmap_buffer = kvm_second_dirty_bitmap(memslot);
		memset(dirty_bitmap_buffer, 0, n);

		spin_lock(&kvm->mmu_lock);
		for (i = 0; i < n / sizeof(long); i++) {
			unsigned long mask;
			gfn_t offset;

			if (!dirty_bitmap[i])
				continue;

			*flush = true;
			mask = xchg(&dirty_bitmap[i], 0);
			dirty_bitmap_buffer[i] = mask;

			if (mask) {
				offset = i * BITS_PER_LONG;
				kvm_arch_mmu_enable_log_dirty_pt_masked(kvm, memslot,
									offset, mask);
			}
		}
		spin_unlock(&kvm->mmu_lock);
	}

	if (copy_to_user(log->dirty_bitmap, dirty_bitmap_buffer, n))
		return -EFAULT;
	return 0;
}


static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot)
{
	unsigned long dirty_bytes = 2 * kvm_dirty_bitmap_bytes(memslot);

	memslot->dirty_bitmap = kvzalloc(dirty_bytes, GFP_KERNEL);
	if (!memslot->dirty_bitmap)
		return -ENOMEM;

	return 0;
}


static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)
{
	char dir_name[ITOA_MAX_LEN * 2];
	struct kvm_stat_data *stat_data;
	struct kvm_stats_debugfs_item *p;

	if (!debugfs_initialized())
		return 0;

	snprintf(dir_name, sizeof(dir_name), "%d-%d", task_pid_nr(current), fd);
	kvm->debugfs_dentry = debugfs_create_dir(dir_name, kvm_debugfs_dir);

	kvm->debugfs_stat_data = kcalloc(kvm_debugfs_num_entries,
					 sizeof(*kvm->debugfs_stat_data),
					 GFP_KERNEL);
	if (!kvm->debugfs_stat_data)
		return -ENOMEM;

	for (p = debugfs_entries; p->name; p++) {
		stat_data = kzalloc(sizeof(*stat_data), GFP_KERNEL);
		if (!stat_data)
			return -ENOMEM;

		stat_data->kvm = kvm;
		stat_data->offset = p->offset;
		kvm->debugfs_stat_data[p - debugfs_entries] = stat_data;
		debugfs_create_file(p->name, 0644, kvm->debugfs_dentry,
				    stat_data, stat_fops_per_vm[p->kind]);
	}
	return 0;
}


static int vm_stat_get(void *_offset, u64 *val)
{
	unsigned offset = (long)_offset;
	struct kvm *kvm;
	struct kvm_stat_data stat_tmp = {.offset = offset};
	u64 tmp_val;

	*val = 0;
	spin_lock(&kvm_lock);
	list_for_each_entry(kvm, &vm_list, vm_list) {
		stat_tmp.kvm = kvm;
		vm_stat_get_per_vm((void *)&stat_tmp, &tmp_val);
		*val += tmp_val;
	}
	spin_unlock(&kvm_lock);
	return 0;
}


void vcpu_load(struct kvm_vcpu *vcpu)
{
	int cpu = get_cpu();
	preempt_notifier_register(&vcpu->preempt_notifier);
	kvm_arch_vcpu_load(vcpu, cpu);
	put_cpu();
}


static void iucv_callback_txdone(struct iucv_path *path,
				 struct iucv_message *msg)
{
	struct sock *sk = path->private;
	struct sk_buff *this = NULL;
	struct sk_buff_head *list = &iucv_sk(sk)->send_skb_q;
	struct sk_buff *list_skb = list->next;
	unsigned long flags;

	bh_lock_sock(sk);
	if (!skb_queue_empty(list)) {
		spin_lock_irqsave(&list->lock, flags);

		while (list_skb != (struct sk_buff *)list) {
			if (!memcmp(&msg->tag, CB_TAG(list_skb), CB_TAG_LEN)) {
				this = list_skb;
				break;
			}
			list_skb = list_skb->next;
		}
		if (this)
			__skb_unlink(this, list);

		spin_unlock_irqrestore(&list->lock, flags);

		if (this) {
			kfree_skb(this);
			/* wake up any process waiting for sending */
			iucv_sock_wake_msglim(sk);
		}
	}

	if (sk->sk_state == IUCV_CLOSING) {
		if (skb_queue_empty(&iucv_sk(sk)->send_skb_q)) {
			sk->sk_state = IUCV_CLOSED;
			sk->sk_state_change(sk);
		}
	}
	bh_unlock_sock(sk);

}


  ::tensorflow::Status WriteSplits(
      const std::vector<std::vector<SPLITS_TYPE>>& out_splits,
      OpKernelContext* context) {
    OpOutputList splits_out;
    TF_RETURN_IF_ERROR(
        context->output_list("output_nested_splits", &splits_out));
    for (int i = 0; i < out_splits.size(); ++i) {
      Tensor* splits;
      SPLITS_TYPE num_splits = out_splits[i].size();
      TF_RETURN_IF_ERROR(
          splits_out.allocate(i, TensorShape({num_splits}), &splits));
      auto splits_flat = splits->flat<SPLITS_TYPE>();
      std::copy_n(out_splits[i].data(), out_splits[i].size(),
                  splits_flat.data());
    }
    return ::tensorflow::Status::OK();
  }


h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
{
	struct req *req;
	h2_error h2e;
	const uint8_t *p;
	size_t l;

	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
	ASSERT_RXTHR(h2);

	if (r2 == NULL) {
		if (h2->rxf_stream <= h2->highest_stream)
			return (H2CE_PROTOCOL_ERROR);	// rfc7540,l,1153,1158
		/* NB: we don't need to guard the read of h2->open_streams
		 * because headers are handled sequentially so it cannot
		 * increase under our feet.
		 */
		if (h2->open_streams >=
		    h2->local_settings.max_concurrent_streams) {
			VSLb(h2->vsl, SLT_Debug,
			     "H2: stream %u: Hit maximum number of "
			     "concurrent streams", h2->rxf_stream);
			return (H2SE_REFUSED_STREAM);	// rfc7540,l,1200,1205
		}
		h2->highest_stream = h2->rxf_stream;
		r2 = h2_new_req(wrk, h2, h2->rxf_stream, NULL);
	}
	CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);

	if (r2->state != H2_S_IDLE)
		return (H2CE_PROTOCOL_ERROR);	// XXX spec ?
	r2->state = H2_S_OPEN;

	req = r2->req;
	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);

	req->vsl->wid = VXID_Get(wrk, VSL_CLIENTMARKER);
	VSLb(req->vsl, SLT_Begin, "req %u rxreq", VXID(req->sp->vxid));
	VSL(SLT_Link, req->sp->vxid, "req %u rxreq", VXID(req->vsl->wid));

	h2->new_req = req;
	req->sp = h2->sess;
	req->transport = &H2_transport;

	req->t_first = VTIM_real();
	req->t_req = VTIM_real();
	req->t_prev = req->t_first;
	VSLb_ts_req(req, "Start", req->t_first);
	VCL_Refresh(&wrk->vcl);
	req->vcl = wrk->vcl;
	wrk->vcl = NULL;
	req->acct.req_hdrbytes += h2->rxf_len;

	HTTP_Setup(req->http, req->ws, req->vsl, SLT_ReqMethod);
	http_SetH(req->http, HTTP_HDR_PROTO, "HTTP/2.0");

	h2h_decode_init(h2);

	p = h2->rxf_data;
	l = h2->rxf_len;
	if (h2->rxf_flags & H2FF_HEADERS_PADDED) {
		if (*p + 1 > l)
			return (H2CE_PROTOCOL_ERROR);	// rfc7540,l,1884,1887
		l -= 1 + *p;
		p += 1;
	}
	if (h2->rxf_flags & H2FF_HEADERS_PRIORITY) {
		if (l < 5)
			return (H2CE_PROTOCOL_ERROR);
		l -= 5;
		p += 5;
	}
	h2e = h2h_decode_bytes(h2, p, l);
	if (h2e != NULL) {
		Lck_Lock(&h2->sess->mtx);
		VSLb(h2->vsl, SLT_Debug, "HPACK(hdr) %s", h2e->name);
		Lck_Unlock(&h2->sess->mtx);
		(void)h2h_decode_fini(h2);
		AZ(r2->req->ws->r);
		h2_del_req(wrk, r2);
		return (h2e);
	}

	if (h2->rxf_flags & H2FF_HEADERS_END_STREAM)
		req->req_body_status = REQ_BODY_NONE;

	if (h2->rxf_flags & H2FF_HEADERS_END_HEADERS)
		return (h2_end_headers(wrk, h2, req, r2));
	return (0);
}


  explicit SparseSparseBinaryOpShared(OpKernelConstruction *ctx)
      : OpKernel(ctx) {}


static inline void get_strl(AVIOContext *pb, char *buf, int buf_size, int len)
{
    int i;
    char *q, r;

    q = buf;
    for(i=0;i<len;i++) {
        r = avio_r8(pb);
        if (i < buf_size - 1)
            *q++ = r;
    }
    if (buf_size > 0) *q = '\0';
}


static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    RMDemuxContext *rm = s->priv_data;
    AVStream *st = NULL; // init to silence compiler warning
    int i, len, res, seq = 1;
    int64_t timestamp, pos;
    int flags;

    for (;;) {
        if (rm->audio_pkt_cnt) {
            // If there are queued audio packet return them first
            st = s->streams[rm->audio_stream_num];
            res = ff_rm_retrieve_cache(s, s->pb, st, st->priv_data, pkt);
            if(res < 0)
                return res;
            flags = 0;
        } else {
            if (rm->old_format) {
                RMStream *ast;

                st = s->streams[0];
                ast = st->priv_data;
                timestamp = AV_NOPTS_VALUE;
                len = !ast->audio_framesize ? RAW_PACKET_SIZE :
                    ast->coded_framesize * ast->sub_packet_h / 2;
                flags = (seq++ == 1) ? 2 : 0;
                pos = avio_tell(s->pb);
            } else {
                len = rm_sync(s, &timestamp, &flags, &i, &pos);
                if (len > 0)
                    st = s->streams[i];
            }

            if (avio_feof(s->pb))
                return AVERROR_EOF;
            if (len <= 0)
                return AVERROR(EIO);

            res = ff_rm_parse_packet (s, s->pb, st, st->priv_data, len, pkt,
                                      &seq, flags, timestamp);
            if (res < -1)
                return res;
            if((flags&2) && (seq&0x7F) == 1)
                av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME);
            if (res)
                continue;
        }

        if(  (st->discard >= AVDISCARD_NONKEY && !(flags&2))
           || st->discard >= AVDISCARD_ALL){
            av_packet_unref(pkt);
        } else
            break;
    }

    return 0;
}


static bool ok_jpg_decode_scan(ok_jpg_decoder *decoder) {
    decoder->next_restart = 0;
    ok_jpg_decode_restart(decoder);
    if (decoder->restart_intervals_remaining > 0) {
        // Increment because the restart is checked before each data unit instead of after.
        decoder->restart_intervals_remaining++;
    }
    if (decoder->progressive) {
        void (*decode_function)(ok_jpg_decoder *decoder, ok_jpg_component *c, int16_t *block);
        if (decoder->scan_prev_scale > 0) {
            decode_function = ok_jpg_decode_block_subsequent_scan;
        } else {
            decode_function = ok_jpg_decode_block_progressive;
        }
        if (decoder->num_scan_components == 1) {
            ok_jpg_component *c = decoder->components + decoder->scan_components[0];
            c->next_block = 0;
            for (int data_unit_y = 0; data_unit_y < c->blocks_v; data_unit_y++) {
                int16_t *block = c->blocks + (c->next_block * 64);
                for (int data_unit_x = 0; data_unit_x < c->blocks_h; data_unit_x++) {
                    if (!ok_jpg_decode_restart_if_needed(decoder)) {
                        return false;
                    }
                    decode_function(decoder, c, block);
                    block += 64;
                }
                if (decoder->eof_found || decoder->huffman_error) {
                    return false;
                }
                c->next_block += (size_t)(c->H * decoder->data_units_x);
            }
        } else {
            for (int i = 0; i < decoder->num_scan_components; i++) {
                ok_jpg_component *c = decoder->components + decoder->scan_components[i];
                c->next_block = 0;
            }
            for (int data_unit_y = 0; data_unit_y < decoder->data_units_y; data_unit_y++) {
                for (int data_unit_x = 0; data_unit_x < decoder->data_units_x; data_unit_x++) {
                    if (!ok_jpg_decode_restart_if_needed(decoder)) {
                        return false;
                    }
                    for (int i = 0; i < decoder->num_scan_components; i++) {
                        ok_jpg_component *c = decoder->components + decoder->scan_components[i];
                        size_t block_index = c->next_block;
                        for (int y = 0; y < c->V; y++) {
                            for (int x = 0; x < c->H; x++) {
                                decode_function(decoder, c, c->blocks + (block_index * 64));
                                block_index++;
                            }
                            block_index += (size_t)(c->H * (decoder->data_units_x - 1));
                        }
                        c->next_block += c->H;
                    }
                }
                if (decoder->eof_found || decoder->huffman_error) {
                    return false;
                }
                for (int i = 0; i < decoder->num_scan_components; i++) {
                    ok_jpg_component *c = decoder->components + decoder->scan_components[i];
                    c->next_block += (size_t)((c->V - 1) * c->H * decoder->data_units_x);
                }
            }
        }
    } else {
        int16_t block[64];
        for (int data_unit_y = 0; data_unit_y < decoder->data_units_y; data_unit_y++) {
            for (int data_unit_x = 0; data_unit_x < decoder->data_units_x; data_unit_x++) {
                if (!ok_jpg_decode_restart_if_needed(decoder)) {
                    return false;
                }
                for (int i = 0; i < decoder->num_scan_components; i++) {
                    ok_jpg_component *c = decoder->components + decoder->scan_components[i];
                    int offset_y = 0;
                    for (int y = 0; y < c->V; y++) {
                        int offset_x = 0;
                        for (int x = 0; x < c->H; x++) {
                            ok_jpg_decode_block(decoder, c, block);
                            c->idct(block, c->output + offset_x + offset_y);
                            offset_x += 8;
                        }
                        offset_y += C_WIDTH * 8;
                    }
                }
                if (decoder->huffman_error) {
                    return false;
                }
                ok_jpg_convert_data_unit(decoder, data_unit_x, data_unit_y);
            }
            if (decoder->eof_found) {
                return false;
            }
        }
    }

    ok_jpg_dump_bits(decoder);

    for (int i = 0; i < decoder->num_scan_components; i++) {
        ok_jpg_component *c = decoder->components + decoder->scan_components[i];
        if (!c->complete) {
            c->complete = decoder->scan_end == 63 && decoder->scan_scale == 0;
        }
    }

    return true;
}


R_API int r_flag_move(RFlag *f, ut64 at, ut64 to) {
	RFlagItem *item = r_flag_get_i (f, at);
	if (item) {
		r_flag_set (f, item->name, to, item->size);
		return true;
	}
	return false;
}


R_API int r_flag_relocate(RFlag *f, ut64 off, ut64 off_mask, ut64 to) {
	ut64 neg_mask = ~(off_mask);
	RFlagItem *item;
	RListIter *iter;
	int n = 0;

	r_list_foreach (f->flags, iter, item) {
		ut64 fn = item->offset & neg_mask;
		ut64 on = off & neg_mask;
		if (fn == on) {
			ut64 fm = item->offset & off_mask;
			ut64 om = to & off_mask;
			item->offset = (to&neg_mask) + fm + om;
			n++;
		}
	}
	return n;
}


R_API RFlagItem *r_flag_get_at(RFlag *f, ut64 off, bool closest) {
	RFlagItem *item, *nice = NULL;
	RListIter *iter;
	const RFlagsAtOffset *flags_at = r_flag_get_nearest_list (f, off, -1);
	if (!flags_at) {
		return NULL;
	}
	if (flags_at->off == off) {
		r_list_foreach (flags_at->flags, iter, item) {
			if (f->space_idx != -1 && item->space != f->space_idx) {
				continue;
			}
			if (nice) {
				if (isFunctionFlag (nice->name)) {
					nice = item;
				}
			} else {
				nice = item;
			}
		}
		return nice;
	}

	if (!closest) {
		return NULL;
	}
	while (!nice && flags_at) {
		r_list_foreach (flags_at->flags, iter, item) {
			if (f->space_strict && IS_IN_SPACE (f, item)) {
				continue;
			}
			if (item->offset == off) {
				eprintf ("XXX Should never happend\n");
				return evalFlag (f, item);
			}
			nice = item;
			break;
		}
		if (flags_at->off) {
			flags_at = r_flag_get_nearest_list (f, flags_at->off - 1, -1);
		} else {
			flags_at = NULL;
		}
	}
	return evalFlag (f, nice);
}


R_API RFlagItem *r_flag_set(RFlag *f, const char *name, ut64 off, ut32 size) {
	RFlagItem *item = NULL;
	RList *list;

	/* contract fail */
	if (!name || !*name) {
		return NULL;
	}

	item = r_flag_get (f, name);
	if (item) {
		if (item->offset == off) {
			item->size = size;
			return item;
		}
		remove_offsetmap (f, item);
	} else {
		item = R_NEW0 (RFlagItem);
		if (!item) {
			return NULL;
		}
		if (!set_name (item, name)) {
			eprintf ("Invalid flag name '%s'.\n", name);
			r_flag_item_free (item);
			return NULL;
		}
		//item share ownership prone to uaf, that is why only
		//f->flags has set up free pointer
		ht_insert (f->ht_name, item->name, item);
		r_list_append (f->flags, item);
	}

	item->space = f->space_idx;
	item->offset = off + f->base;
	item->size = size;

	list = (RList *)r_flag_get_list (f, off);
	if (!list) {
		RFlagsAtOffset *flagsAtOffset = R_NEW (RFlagsAtOffset);
		list = r_list_new ();
		flagsAtOffset->flags = list;
		flagsAtOffset->off = off;
		// CID 1378268:  Resource leaks  (RESOURCE_LEAK)
		// Ignoring storage allocated by "r_skiplist_insert(f->by_off, flagsAtOffset)" leaks it.
		r_skiplist_insert (f->by_off, flagsAtOffset);
	}
	r_list_append (list, item);
	return item;
}


R_API int r_flag_bind(RFlag *f, RFlagBind *fb) {
	fb->f = f;
	fb->exist_at = r_flag_exist_at;
	fb->get = r_flag_get;
	fb->get_at = r_flag_get_at;
	fb->set = r_flag_set;
	fb->set_fs = r_flag_space_set;
	return 0;
}


static void remove_offsetmap(RFlag *f, RFlagItem *item) {
	RFlagsAtOffset *flags = r_flag_get_nearest_list (f, item->offset, 0);
	if (flags) {
		r_list_delete_data (flags->flags, item);
		if (r_list_empty (flags->flags)) {
			r_skiplist_delete (f->by_off, flags);
		}
	}
}


R_API char *r_flag_get_liststr(RFlag *f, ut64 off) {
	RFlagItem *fi;
	RListIter *iter;
	const RList *list = r_flag_get_list (f, off);
	char *p = NULL;
	r_list_foreach (list, iter, fi) {
		p = r_str_appendf (p, "%s%s",
			fi->realname, iter->n ? "," : ":");
	}
	return p;
}


static void flag_skiplist_free(void *data) {
	RFlagsAtOffset *item = (RFlagsAtOffset *)data;
	r_list_free (item->flags);
	free (data);
}


R_API RFlagItem *r_flag_get_i(RFlag *f, ut64 off) {
	const RList *list;
	if (!f) {
		return NULL;
	}
	list = r_flag_get_list (f, off);
	return list ? evalFlag (f, r_list_get_top (list)) : NULL;
}


MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
                   size_t max_len, hwaddr addr, const char *fw_file_name,
                   FWCfgCallback fw_callback, void *callback_opaque,
                   AddressSpace *as, bool read_only)
{
    MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
    Rom *rom;
    MemoryRegion *mr = NULL;

    rom           = g_malloc0(sizeof(*rom));
    rom->name     = g_strdup(name);
    rom->as       = as;
    rom->addr     = addr;
    rom->romsize  = max_len ? max_len : len;
    rom->datasize = len;
    rom->data     = g_malloc0(rom->datasize);
    memcpy(rom->data, blob, len);
    rom_insert(rom);
    if (fw_file_name && fw_cfg) {
        char devpath[100];
        void *data;

        if (read_only) {
            snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
        } else {
            snprintf(devpath, sizeof(devpath), "/ram@%s", fw_file_name);
        }

        if (mc->rom_file_has_mr) {
            data = rom_set_mr(rom, OBJECT(fw_cfg), devpath, read_only);
            mr = rom->mr;
        } else {
            data = rom->data;
        }

        fw_cfg_add_file_callback(fw_cfg, fw_file_name,
                                 fw_callback, NULL, callback_opaque,
                                 data, rom->datasize, read_only);
    }
    return mr;
}


print_unix_command_map ()
{
  Keymap save, cmd_xmap;

  save = rl_get_keymap ();
  cmd_xmap = get_cmd_xmap_from_keymap (save);
  rl_set_keymap (cmd_xmap);
  rl_macro_dumper (1);
  rl_set_keymap (save);
  return 0;
}


main (argc, argv)
     int argc;
     char **argv;
{
  unsigned int i;

  for (i = 1; i < argc; ++i)
    {
      char **value = glob_filename (argv[i], 0);
      if (value == NULL)
	puts ("Out of memory.");
      else if (value == &glob_error_return)
	perror (argv[i]);
      else
	for (i = 0; value[i] != NULL; i++)
	  puts (value[i]);
    }

  exit (0);
}


_cygwin32_check_tmp ()
{
  struct stat sb;

  if (stat ("/tmp", &sb) < 0)
    internal_warning (_("could not find /tmp, please create!"));
  else
    {
      if (S_ISDIR (sb.st_mode) == 0)
	internal_warning (_("/tmp must be a valid directory name"));
    }
}


unquoted_glob_pattern_p (string)
     register char *string;
{
  register int c;
  char *send;
  int open, bsquote;

  DECLARE_MBSTATE;

  open = bsquote = 0;
  send = string + strlen (string);

  while (c = *string++)
    {
      switch (c)
	{
	case '?':
	case '*':
	  return (1);

	case '[':
	  open++;
	  continue;

	case ']':
	  if (open)		/* XXX - if --open == 0? */
	    return (1);
	  continue;

	case '/':
	  if (open)
	    open = 0;

	case '+':
	case '@':
	case '!':
	  if (*string == '(')	/*)*/
	    return (1);
	  continue;

	/* A pattern can't end with a backslash, but a backslash in the pattern
	   can be removed by the matching engine, so we have to run it through
	   globbing. */
	case '\\':
	  if (*string != '\0' && *string != '/')
	    {
	      bsquote = 1;
	      string++;
	      continue;
	    }
	  else if (open && *string == '/')
	    {
	      string++;		/* quoted slashes in bracket expressions are ok */
	      continue;
	    }
	  else if (*string == 0)
	    return (0);

	case CTLESC:
	  if (*string++ == '\0')
	    return (0);
	}

      /* Advance one fewer byte than an entire multibyte character to
	 account for the auto-increment in the loop above. */
#ifdef HANDLE_MULTIBYTE
      string--;
      ADVANCE_CHAR_P (string, send - string);
      string++;
#else
      ADVANCE_CHAR_P (string, send - string);
#endif
    }

  return ((bsquote && posix_glob_backslash) ? 2 : 0);
}


    Status CmdAuthenticate::_authenticateX509(const UserName& user, const BSONObj& cmdObj) {
        if (!getSSLManager()) {
            return Status(ErrorCodes::ProtocolError,
                          "SSL support is required for the MONGODB-X509 mechanism.");
        }
        if(user.getDB() != "$external") {
            return Status(ErrorCodes::ProtocolError,
                          "X.509 authentication must always use the $external database.");
        }

        ClientBasic *client = ClientBasic::getCurrent();
        AuthorizationSession* authorizationSession = client->getAuthorizationSession();
        std::string subjectName = client->port()->getX509SubjectName();

        if (user.getUser() != subjectName) {
            return Status(ErrorCodes::AuthenticationFailed,
                          "There is no x.509 client certificate matching the user.");
        }
        else {
            std::string srvSubjectName = getSSLManager()->getServerSubjectName();

            size_t srvClusterIdPos = srvSubjectName.find(",OU=");
            size_t peerClusterIdPos = subjectName.find(",OU=");

            std::string srvClusterId = srvClusterIdPos != std::string::npos ?
                srvSubjectName.substr(srvClusterIdPos) : "";
            std::string peerClusterId = peerClusterIdPos != std::string::npos ?
                subjectName.substr(peerClusterIdPos) : "";

            // Handle internal cluster member auth, only applies to server-server connections
            int clusterAuthMode = serverGlobalParams.clusterAuthMode.load();
            if (srvClusterId == peerClusterId && !srvClusterId.empty()) {
                if (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_undefined ||
                    clusterAuthMode == ServerGlobalParams::ClusterAuthMode_keyFile) {
                    return Status(ErrorCodes::AuthenticationFailed, "The provided certificate "
                                  "can only be used for cluster authentication, not client "
                                  "authentication. The current configuration does not allow "
                                  "x.509 cluster authentication, check the --clusterAuthMode flag");
                }
                authorizationSession->grantInternalAuthorization();
            }
            // Handle normal client authentication, only applies to client-server connections
            else {
                if (_isX509AuthDisabled) {
                    return Status(ErrorCodes::BadValue,
                                  _x509AuthenticationDisabledMessage);
                }
                Status status = authorizationSession->addAndAuthorizeUser(user);
                if (!status.isOK()) {
                    return status;
                }
            }
            return Status::OK();
        }
    }


static int khugepaged_scan_pmd(struct mm_struct *mm,
			       struct vm_area_struct *vma,
			       unsigned long address,
			       struct page **hpage)
{
	pgd_t *pgd;
	pud_t *pud;
	pmd_t *pmd;
	pte_t *pte, *_pte;
	int ret = 0, referenced = 0, none = 0;
	struct page *page;
	unsigned long _address;
	spinlock_t *ptl;
	int node = -1;

	VM_BUG_ON(address & ~HPAGE_PMD_MASK);

	pgd = pgd_offset(mm, address);
	if (!pgd_present(*pgd))
		goto out;

	pud = pud_offset(pgd, address);
	if (!pud_present(*pud))
		goto out;

	pmd = pmd_offset(pud, address);
	if (!pmd_present(*pmd) || pmd_trans_huge(*pmd))
		goto out;

	pte = pte_offset_map_lock(mm, pmd, address, &ptl);
	for (_address = address, _pte = pte; _pte < pte+HPAGE_PMD_NR;
	     _pte++, _address += PAGE_SIZE) {
		pte_t pteval = *_pte;
		if (pte_none(pteval)) {
			if (++none <= khugepaged_max_ptes_none)
				continue;
			else
				goto out_unmap;
		}
		if (!pte_present(pteval) || !pte_write(pteval))
			goto out_unmap;
		page = vm_normal_page(vma, _address, pteval);
		if (unlikely(!page))
			goto out_unmap;
		/*
		 * Chose the node of the first page. This could
		 * be more sophisticated and look at more pages,
		 * but isn't for now.
		 */
		if (node == -1)
			node = page_to_nid(page);
		VM_BUG_ON(PageCompound(page));
		if (!PageLRU(page) || PageLocked(page) || !PageAnon(page))
			goto out_unmap;
		/* cannot use mapcount: can't collapse if there's a gup pin */
		if (page_count(page) != 1)
			goto out_unmap;
		if (pte_young(pteval) || PageReferenced(page) ||
		    mmu_notifier_test_young(vma->vm_mm, address))
			referenced = 1;
	}
	if (referenced)
		ret = 1;
out_unmap:
	pte_unmap_unlock(pte, ptl);
	if (ret)
		/* collapse_huge_page will return with the mmap_sem released */
		collapse_huge_page(mm, address, hpage, vma, node);
out:
	return ret;
}


static int __split_huge_page_splitting(struct page *page,
				       struct vm_area_struct *vma,
				       unsigned long address)
{
	struct mm_struct *mm = vma->vm_mm;
	pmd_t *pmd;
	int ret = 0;

	spin_lock(&mm->page_table_lock);
	pmd = page_check_address_pmd(page, mm, address,
				     PAGE_CHECK_ADDRESS_PMD_NOTSPLITTING_FLAG);
	if (pmd) {
		/*
		 * We can't temporarily set the pmd to null in order
		 * to split it, the pmd must remain marked huge at all
		 * times or the VM won't take the pmd_trans_huge paths
		 * and it won't wait on the anon_vma->root->lock to
		 * serialize against split_huge_page*.
		 */
		pmdp_splitting_flush_notify(vma, address, pmd);
		ret = 1;
	}
	spin_unlock(&mm->page_table_lock);

	return ret;
}


static void __init khugepaged_slab_free(void)
{
	kmem_cache_destroy(mm_slot_cache);
	mm_slot_cache = NULL;
}


static void __split_huge_page(struct page *page,
			      struct anon_vma *anon_vma)
{
	int mapcount, mapcount2;
	struct anon_vma_chain *avc;

	BUG_ON(!PageHead(page));
	BUG_ON(PageTail(page));

	mapcount = 0;
	list_for_each_entry(avc, &anon_vma->head, same_anon_vma) {
		struct vm_area_struct *vma = avc->vma;
		unsigned long addr = vma_address(page, vma);
		BUG_ON(is_vma_temporary_stack(vma));
		if (addr == -EFAULT)
			continue;
		mapcount += __split_huge_page_splitting(page, vma, addr);
	}
	/*
	 * It is critical that new vmas are added to the tail of the
	 * anon_vma list. This guarantes that if copy_huge_pmd() runs
	 * and establishes a child pmd before
	 * __split_huge_page_splitting() freezes the parent pmd (so if
	 * we fail to prevent copy_huge_pmd() from running until the
	 * whole __split_huge_page() is complete), we will still see
	 * the newly established pmd of the child later during the
	 * walk, to be able to set it as pmd_trans_splitting too.
	 */
	if (mapcount != page_mapcount(page))
		printk(KERN_ERR "mapcount %d page_mapcount %d\n",
		       mapcount, page_mapcount(page));
	BUG_ON(mapcount != page_mapcount(page));

	__split_huge_page_refcount(page);

	mapcount2 = 0;
	list_for_each_entry(avc, &anon_vma->head, same_anon_vma) {
		struct vm_area_struct *vma = avc->vma;
		unsigned long addr = vma_address(page, vma);
		BUG_ON(is_vma_temporary_stack(vma));
		if (addr == -EFAULT)
			continue;
		mapcount2 += __split_huge_page_map(page, vma, addr);
	}
	if (mapcount != mapcount2)
		printk(KERN_ERR "mapcount %d mapcount2 %d page_mapcount %d\n",
		       mapcount, mapcount2, page_mapcount(page));
	BUG_ON(mapcount != mapcount2);
}


static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm,
					struct vm_area_struct *vma,
					unsigned long address,
					pmd_t *pmd, pmd_t orig_pmd,
					struct page *page,
					unsigned long haddr)
{
	pgtable_t pgtable;
	pmd_t _pmd;
	int ret = 0, i;
	struct page **pages;

	pages = kmalloc(sizeof(struct page *) * HPAGE_PMD_NR,
			GFP_KERNEL);
	if (unlikely(!pages)) {
		ret |= VM_FAULT_OOM;
		goto out;
	}

	for (i = 0; i < HPAGE_PMD_NR; i++) {
		pages[i] = alloc_page_vma_node(GFP_HIGHUSER_MOVABLE |
					       __GFP_OTHER_NODE,
					       vma, address, page_to_nid(page));
		if (unlikely(!pages[i] ||
			     mem_cgroup_newpage_charge(pages[i], mm,
						       GFP_KERNEL))) {
			if (pages[i])
				put_page(pages[i]);
			mem_cgroup_uncharge_start();
			while (--i >= 0) {
				mem_cgroup_uncharge_page(pages[i]);
				put_page(pages[i]);
			}
			mem_cgroup_uncharge_end();
			kfree(pages);
			ret |= VM_FAULT_OOM;
			goto out;
		}
	}

	for (i = 0; i < HPAGE_PMD_NR; i++) {
		copy_user_highpage(pages[i], page + i,
				   haddr + PAGE_SHIFT*i, vma);
		__SetPageUptodate(pages[i]);
		cond_resched();
	}

	spin_lock(&mm->page_table_lock);
	if (unlikely(!pmd_same(*pmd, orig_pmd)))
		goto out_free_pages;
	VM_BUG_ON(!PageHead(page));

	pmdp_clear_flush_notify(vma, haddr, pmd);
	/* leave pmd empty until pte is filled */

	pgtable = get_pmd_huge_pte(mm);
	pmd_populate(mm, &_pmd, pgtable);

	for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
		pte_t *pte, entry;
		entry = mk_pte(pages[i], vma->vm_page_prot);
		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
		page_add_new_anon_rmap(pages[i], vma, haddr);
		pte = pte_offset_map(&_pmd, haddr);
		VM_BUG_ON(!pte_none(*pte));
		set_pte_at(mm, haddr, pte, entry);
		pte_unmap(pte);
	}
	kfree(pages);

	mm->nr_ptes++;
	smp_wmb(); /* make pte visible before pmd */
	pmd_populate(mm, pmd, pgtable);
	page_remove_rmap(page);
	spin_unlock(&mm->page_table_lock);

	ret |= VM_FAULT_WRITE;
	put_page(page);

out:
	return ret;

out_free_pages:
	spin_unlock(&mm->page_table_lock);
	mem_cgroup_uncharge_start();
	for (i = 0; i < HPAGE_PMD_NR; i++) {
		mem_cgroup_uncharge_page(pages[i]);
		put_page(pages[i]);
	}
	mem_cgroup_uncharge_end();
	kfree(pages);
	goto out;
}


void mb2_cache_entry_delete_block(struct mb2_cache *cache, u32 key,
				  sector_t block)
{
	struct hlist_bl_node *node;
	struct hlist_bl_head *head;
	struct mb2_cache_entry *entry;

	head = &cache->c_hash[hash_32(key, cache->c_bucket_bits)];
	hlist_bl_lock(head);
	hlist_bl_for_each_entry(entry, node, head, e_hash_list) {
		if (entry->e_key == key && entry->e_block == block) {
			/* We keep hash list reference to keep entry alive */
			hlist_bl_del_init(&entry->e_hash_list);
			hlist_bl_unlock(head);
			spin_lock(&cache->c_lru_list_lock);
			if (!list_empty(&entry->e_lru_list)) {
				list_del_init(&entry->e_lru_list);
				cache->c_entry_count--;
				atomic_dec(&entry->e_refcnt);
			}
			spin_unlock(&cache->c_lru_list_lock);
			mb2_cache_entry_put(cache, entry);
			return;
		}
	}
	hlist_bl_unlock(head);
}


static int __init mb2cache_init(void)
{
	mb2_entry_cache = kmem_cache_create("mbcache",
				sizeof(struct mb2_cache_entry), 0,
				SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
	BUG_ON(!mb2_entry_cache);
	return 0;
}


static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
{
    DNXHDEncContext *ctx = avctx->priv_data;
    int mb_y = jobnr, mb_x;
    int qscale = ctx->qscale;
    LOCAL_ALIGNED_16(int16_t, block, [64]);
    ctx = ctx->thread[threadnr];

    ctx->m.last_dc[0] =
    ctx->m.last_dc[1] =
    ctx->m.last_dc[2] = 1 << (ctx->cid_table->bit_depth + 2);

    for (mb_x = 0; mb_x < ctx->m.mb_width; mb_x++) {
        unsigned mb = mb_y * ctx->m.mb_width + mb_x;
        int ssd     = 0;
        int ac_bits = 0;
        int dc_bits = 0;
        int i;

        dnxhd_get_blocks(ctx, mb_x, mb_y);

        for (i = 0; i < 8; i++) {
            int16_t *src_block = ctx->blocks[i];
            int overflow, nbits, diff, last_index;
            int n = dnxhd_switch_matrix(ctx, i);

            memcpy(block, src_block, 64*sizeof(*block));
            last_index = ctx->m.dct_quantize(&ctx->m, block, 4&(2*i), qscale, &overflow);
            ac_bits += dnxhd_calc_ac_bits(ctx, block, last_index);

            diff = block[0] - ctx->m.last_dc[n];
            if (diff < 0) nbits = av_log2_16bit(-2*diff);
            else          nbits = av_log2_16bit( 2*diff);

            av_assert1(nbits < ctx->cid_table->bit_depth + 4);
            dc_bits += ctx->cid_table->dc_bits[nbits] + nbits;

            ctx->m.last_dc[n] = block[0];

            if (avctx->mb_decision == FF_MB_DECISION_RD || !RC_VARIANCE) {
                dnxhd_unquantize_c(ctx, block, i, qscale, last_index);
                ctx->m.dsp.idct(block);
                ssd += dnxhd_ssd_block(block, src_block);
            }
        }
        ctx->mb_rc[qscale][mb].ssd = ssd;
        ctx->mb_rc[qscale][mb].bits = ac_bits+dc_bits+12+8*ctx->vlc_bits[0];
    }
    return 0;
}