Example #1
0
/*! Increment the current visit count for a particular OBJECT. */
static inline gint
visit(OBJECT *obj)
{
  gpointer val = GINT_TO_POINTER(is_visited (obj) + 1);
  g_hash_table_replace (visit_table, obj, val);
  return GPOINTER_TO_INT (val);
}
Example #2
0
deferred * defer(uint16_t address, deferred * next)
{
    if (is_visited(address)) {
        return next;
    }
    //printf("deferring %X\n", address);
    deferred * d = malloc(sizeof(deferred));
    d->address = address;
    d->next = next;
    return d;
}
Example #3
0
struct raster *filter_rcu(struct raster *r, double d_max)
{
 int            x, y;		// for()
 int            dx, dy;		// dim_x, dim_y
 struct raster *r_out;		// obraz wyjsciowy
 char          *visited;	// tablica elementow juz odwiedzonych

 // wymiary obrazka:
 dx=raster_dim_x(r);
 dy=raster_dim_y(r);

 // przydzielanie pamieci:
 visited=(char*)malloc(dx*dy);	// tworzymy tablice odwiedzonych pixeli
 if(visited==NULL)
   return NULL;
 r_out=raster_clone(r);		// bedziemy pracowac na DOKLADNEJ kopii...
 if(r_out==NULL)
 {
   free(visited);
   return NULL;
 };

 // poki co nie odwiedzilismy zadnego pixela
 memset(visited, 0, dx*dy);

 // dalej bedziemy sie juz poslugiwac KWADRATAMI gradientu, zeby
 // nie pierwiastkowac za kazdym razem
 d_max*=d_max;

 //
 // przejscie po wszystkich pixelach
 //
 for(y=0; y<dy; y++)
   for(x=0; x<dx; x++)
   {
     if( is_visited(r, visited, x, y) )	// juz tu bylismy?
       continue;
     process_img(r_out, r, visited,
                 d_max, x, y, x, y,
                 raster_pix_get(r, x, y) );	// przetwazanie wlasc.
   }; // for(y;x)
 //
 // koniec przetwarzania
 //

 // sprzatamy po sobie!
 free(visited);

 return r_out;
}; // filter_rcu()
Example #4
0
        void bfs()
        {
            auto source = Node{ init, "" };
            for (q.push(source); !q.empty(); max_q_lenth = std::max(max_q_lenth, q.size()))
            {
                auto curr = q.front(); q.pop();
                if (curr.state == goal)
                {
                    final_path = curr.path; return;
                }

                for (auto c : curr.valid_children())
                    if (!is_visited(c.state)) visit(c.state), q.push(c);
            }
        }
void grid_segment::grow(std::function<grid_segment::ptr(grid_cell_base::label)> segments_accessor)
{
    vector<grid_cell::ptr> tovisit;
    tovisit.push_back(*cells_.begin());
    set_visited(tovisit.front());

    grid_cell_base::label label = tovisit.front()->get_label();

    while(!tovisit.empty())
    {
        grid_cell::ptr c = tovisit.back();
        tovisit.pop_back();

        c->set_label(label);
        cells_.insert(c);

        for(size_t i=0; i<4; i++)
        {
            auto nc = grid_.get_neighbour_cell_4(c,i);
            if(nc)
            {
                if(nc->has_label())
                {
                    if(nc->get_label() != label && !nc->is_ignored())
                    {
                        add_edge(std::static_pointer_cast<graph_node>(segments_accessor(label)),
                                 std::static_pointer_cast<graph_node>(segments_accessor(nc->get_label())));
                    }
                    continue;
                }

                if(nc->is_target() && !nc->is_ignored() && nc->is_covered() && !is_visited(nc))
                {
                    set_visited(nc);
                    tovisit.push_back(nc);
                }
            }
        }
    }
}
Example #6
0
static void
add_group_to_closure (GtkSizeGroup    *group,
		      GtkSizeGroupMode mode,
		      GSList         **groups,
		      GSList         **widgets)
{
  GSList *tmp_widgets;
  
  *groups = g_slist_prepend (*groups, group);
  mark_visited (group);

  tmp_widgets = group->widgets;
  while (tmp_widgets)
    {
      GtkWidget *tmp_widget = tmp_widgets->data;
      
      if (!is_visited (tmp_widget))
	add_widget_to_closure (tmp_widget, mode, groups, widgets);
      
      tmp_widgets = tmp_widgets->next;
    }
}
Example #7
0
static void
add_widget_to_closure (GtkWidget       *widget,
		       GtkSizeGroupMode mode,
		       GSList         **groups,
		       GSList         **widgets)
{
  GSList *tmp_groups;

  *widgets = g_slist_prepend (*widgets, widget);
  mark_visited (widget);

  tmp_groups = get_size_groups (widget);
  while (tmp_groups)
    {
      GtkSizeGroup *tmp_group = tmp_groups->data;
      
      if ((tmp_group->mode == GTK_SIZE_GROUP_BOTH || tmp_group->mode == mode) &&
	  !is_visited (tmp_group))
	add_group_to_closure (tmp_group, mode, groups, widgets);

      tmp_groups = tmp_groups->next;
    }
}
Example #8
0
// A not-so-fast leak checking based on the concept what a heap block without any
// reference directly/indirectly from a global/local variable is a lost one
CA_BOOL display_heap_leak_candidates(void)
{
	CA_BOOL rc = CA_TRUE;
	unsigned long total_blocks = 0;
	struct inuse_block* blocks = NULL;
	struct inuse_block* blk;
	unsigned int* qv_bitmap = NULL;	// Bit flags of whether a block is queued/visited
	unsigned long cur_index;
	size_t total_leak_bytes;
	size_t total_bytes;
	unsigned long leak_count;

	// create and populate an array of all in-use blocks
	blocks = build_inuse_heap_blocks(&total_blocks);
	if (!blocks || total_blocks == 0)
	{
		CA_PRINT("Failed: no in-use heap block is found\n");
		return CA_FALSE;
	}

	// Prepare bitmap with the clean state
	// Each block uses two bits(queued/visited)
	qv_bitmap = (unsigned int*) calloc((total_blocks+15)*2/32, sizeof(unsigned int));
	if (!qv_bitmap)
	{
		CA_PRINT("Out of Memory\n");
		rc = CA_FALSE;
		goto leak_check_out;
	}

	// search global/local(module's .text/.data/.bss and thread stack) memory
	// for all references to these in-use blocks, mark them queued and visited
	if (!mark_blocks_referenced_by_globals_locals(blocks, total_blocks, qv_bitmap))
	{
		rc = CA_FALSE;
		goto leak_check_out;
	}

	// Within in-use blocks,
	// repeatedly use queued blocks to find unvisited ones through reference
	// mark newly found blocks queued and visited
	// until no queued blocks any more to work with
	cur_index = 0;
	do
	{
		cur_index = get_next_queued_index(qv_bitmap, total_blocks, cur_index);
		if (cur_index < total_blocks)
		{
			unsigned int* indexp;
			blk = blocks + cur_index;
			if (!blk->reachable.index_map)
			{
				if (!build_block_index_map(blk, blocks, total_blocks))
				{
					rc = CA_FALSE;
					goto leak_check_out;
				}
			}
			// We have index map to work with by now
			indexp = blk->reachable.index_map;
			while (*indexp != UINT_MAX)
			{
				unsigned int index = *indexp;
				if (!is_queued_or_visited(qv_bitmap, index))
				{
					set_queued_and_visited(qv_bitmap, index);
				}
				indexp++;
			}
			// done with this block
			reset_queued(qv_bitmap, cur_index);
		}
		else
			break;
	} while (1);

	// Display blocks that found no references to them directly or indirectly from global/local areas
	CA_PRINT("Potentially leaked heap memory blocks:\n");
	total_leak_bytes = 0;
	total_bytes = 0;
	leak_count = 0;
	for (cur_index = 0, blk = blocks; cur_index < total_blocks; cur_index++, blk++)
	{
		total_bytes += blk->size;
		if (!is_visited(qv_bitmap, cur_index))
		{
			leak_count++;
			CA_PRINT("[%ld] addr="PRINT_FORMAT_POINTER" size="PRINT_FORMAT_SIZE"\n",
					leak_count, blk->addr, blk->size);
			total_leak_bytes += blk->size;
		}
	}
	if (leak_count)
	{
		CA_PRINT("Total %ld (", leak_count);
		print_size(total_leak_bytes);
		CA_PRINT(") leak candidates out of %ld (", total_blocks);
		print_size(total_bytes);
		CA_PRINT(") in-use memory blocks\n");
	}
	else
		CA_PRINT("All %ld heap blocks are referenced, no leak candidate\n", total_blocks);

leak_check_out:
	if (blocks)
		free_inuse_heap_blocks(blocks, total_blocks);
	if (qv_bitmap)
		free (qv_bitmap);
	return rc;
}
Example #9
0
// ta procedura odpowiada za kolejne przejscia rekurencyjne, celem
// unifikacji kolorystyki obrazu
static int process_img(struct raster *r_out, struct raster *r,
                       char visited[], double d_max,
                       int x, int y, int x_prev, int y_prev,
                       struct rgb24 base)
{
 int          off_x, off_y;	// przesuniecia x,y
 int          cx, cy;		// CurrentX, CurrentY
 double       d_cur;		// bierzacy gradient!
 double       d[2];		// gradienty miedzy elementami
 double       tmp;		// pomocniczy
 struct rgb24 pix_out;		// pixel do wstawienia
 struct rgb24 pix[3];		// pixele:
				//   pix[2] - bierzacy
				//   pix[1] - poprzedni pix[2] w linii
				//   pix[0] - poprzedni pix[1] w linii

 set_visited(r, visited, x, y);	// zaznaczamy, ze tu juz bylismy!

 //
 // etap 1: przetwazanie lokalne
 //
 pix[2]=raster_pix_get(r,x,     y     );// pobieramy bierzacy pixel
 pix[1]=raster_pix_get(r,x_prev,y_prev);// oraz poprzedni
 cx=x_prev-(x-x_prev);			// wyliczamy jeszcze wczesniejsza poz.
 cy=y_prev-(y-y_prev);
 if( raster_xy_rng(r, cx, cy) )		// nalezy ona jeszcze do obrazka?
   pix[0]=raster_pix_get(r,cx,cy);	// pobieramy wiec wartosc!
 else
   pix[0]=pix[1];			// domyslnie wstawiamy poprzednia

 // analiza i ustalanie gradientu:
 d[0] =grad_v(pix[0], pix[1]);
 d[1] =grad_v(pix[1], pix[2]);
 d_cur=fabs( (1*d[0]-2*d[1])/3 );

 if(d_cur>d_max)		// koniec zejsc??
   return 0;
 // ustawiamy pixel na zadany!

 //pix_out=base;			// jakis ustalony kolorek...

 //pix_out=pix[1];		// poprzedni

/*
 tmp      =d_max-d_cur;		// wspl proporc
 pix_out.r=(int)( ((1-tmp)*base.r + tmp*pix[2].r) );
 pix_out.g=(int)( ((1-tmp)*base.g + tmp*pix[2].g) );
 pix_out.b=(int)( ((1-tmp)*base.b + tmp*pix[2].b) );
*/

/*
 pix_out.r=(1*base.r + 3*pix[2].r)/4;
 pix_out.g=(1*base.g + 3*pix[2].g)/4;
 pix_out.b=(1*base.b + 3*pix[2].b)/4;
*/

 double a,b,c,e, sum;
 c  =1;	// base
 e  =0;	// pix[0]
 a  =1;	// pix[1]
 b  =1;	// pix[2]
 sum=a+b+c+e;
 pix_out.r=(e*pix[0].r + a*pix[1].r + b*pix[2].r + c*base.r)/sum;
 pix_out.g=(e*pix[0].g + a*pix[1].g + b*pix[2].g + c*base.g)/sum;
 pix_out.b=(e*pix[0].b + a*pix[1].b + b*pix[2].b + c*base.b)/sum;
 //tmp      =fabs(c*base.r-b*pix[2].r)/sum;
 tmp      =fabs(base.r-pix[2].r);
 tmp      =1 + tmp/255.0;
 pix_out.r=MIN(255, (int)(tmp*pix_out.r) );
 pix_out.g=MIN(255, (int)(tmp*pix_out.g) );
 pix_out.b=MIN(255, (int)(tmp*pix_out.b) );
 //pix_out.r=MIN(255, pix_out.r+MAX(base.r, pix[0].r)-(base.r+pix[0].r)/2 );
 //pix_out.g=MIN(255, pix_out.g+MAX(base.g, pix[0].g)-(base.g+pix[0].g)/2 );
 //pix_out.b=MIN(255, pix_out.b+MAX(base.b, pix[0].b)-(base.b+pix[0].b)/2 );

 raster_pix_set(r_out, x, y, &pix_out);


 //
 // etap 2: przetwazanie reqrencyjne, po najblizszych sasiadach
 //
 for(off_y=-1; off_y<=1; off_y++)
   for(off_x=-1; off_x<=1; off_x++)
   {
     cx=x+off_x;
     cy=y+off_y;
     if(off_x==0 && off_y==0)		// dla siebie samego NIE wywolujemy
       continue;
     if( !raster_xy_rng(r, cx, cy) )	// indexy poza zasiegiem?
       continue;
     if( is_visited(r, visited, cx, cy) )	// pomijamy juz odwiedzione
       continue;
     process_img(r_out, r, visited,
                 d_max, cx, cy, x, y,
                 base);			// idziemy glebiej!
   }; // for(x+off,y+off)

  return 0;
};
Example #10
0
 // Check for being post-visited.
 // Should be previsited already (checked with assert(is_visited(n))).
 int is_postvisited( Node *n ) const { assert( is_visited(n), "" ); return _preorders[n->_idx]&1; }
Example #11
0
 // Return pre-order number.
 int get_preorder( Node *n ) const { assert( is_visited(n), "" ); return _preorders[n->_idx]>>1; }
Example #12
0
 // Pre-order numbers are written to the Nodes array as low-bit-set values.
 void set_preorder_visited( Node *n, int pre_order ) {
   assert( !is_visited( n ), "already set" );
   _preorders[n->_idx] = (pre_order<<1);
 };
Example #13
0
/* {{{ flt_lf_evaluate */
flt_lf_result_t *flt_lf_evaluate(flt_lf_node_t *n,message_t *msg,u_int64_t tid) {
  mod_api_t is_visited = cf_get_mod_api_ent("is_visited");
  flt_lf_result_t *result = cf_alloc(NULL,1,sizeof(*result),CF_ALLOC_CALLOC);
  flt_lf_result_t *l = NULL,*r = NULL,*tmp;
  struct tm tm,tm1;

  if(!n) return NULL;

  switch(n->type) {
    case TOK_CONTAINS:
      /* {{{ contains */
      l = flt_lf_evaluate(n->left,msg,tid);
      r = flt_lf_evaluate(n->right,msg,tid);

      flt_lf_to_string(l);
      flt_lf_to_string(r);

      result->type = T_BOOL;

      if(flt_lf_case_strstr(l->val,r->val)) result->val  = (void *)1;
      else result->val  = (void *)0;

      if(l->type == T_STRING) free(l->val);
      if(r->type == T_STRING) free(r->val);
      free(r);
      free(l);

      return result;
      /* }}} */

    case TOK_CONTAINS_NOT:
      /* {{{ contains not */
      l = flt_lf_evaluate(n->left,msg,tid);
      r = flt_lf_evaluate(n->right,msg,tid);

      flt_lf_to_string(l);
      flt_lf_to_string(r);

      result->type = T_BOOL;

      if(flt_lf_case_strstr(l->val,r->val)) result->val = (void *)0;
      else result->val = (void *)1;

      if(l->type == T_STRING) free(l->val);
      if(r->type == T_STRING) free(r->val);
      free(r);
      free(l);

      return result;
      /* }}} */

    case TOK_EQ:
      /* {{{ equal */
      l = flt_lf_evaluate(n->left,msg,tid);
      r = flt_lf_evaluate(n->right,msg,tid);

      flt_lf_r2l(l,r);
      result->type = T_BOOL;

      if(l->type == T_STRING) {
        if(cf_strcasecmp(l->val,r->val) == 0) result->val = (void *)1; /* true: strings are equal */
        else result->val = (void *)0;
      }
      else {
        if(l->type == T_DATE) {
          memset(&tm,0,sizeof(tm));
          memset(&tm1,0,sizeof(tm1));

          localtime_r((const time_t *)&l->val,&tm);
          gmtime_r((const time_t *)&r->val,&tm1);

          //if(tm1.tm_isdst) tm1.tm_hour -= 1;

          if(tm.tm_year == tm1.tm_year && tm.tm_mon == tm1.tm_mon && tm.tm_mday == tm1.tm_mday) {
            if(r->flags & FLT_LF_FLAG_HOUR) {
              if(tm.tm_hour == tm1.tm_hour) {
                if(r->flags & FLT_LF_FLAG_MIN) {
                  if(tm.tm_min == tm1.tm_min) {
                    if(r->flags & FLT_LF_FLAG_SEC) {
                      if(tm.tm_sec == tm1.tm_sec) result->val = (void *)1;
                      else result->val = (void *)0;
                    }
                    else result->val = (void *)1;
                  }
                  else result->val = (void *)0;
                }
                else result->val = (void *)1;
              }
              else result->val = (void *)0;
            }
            else result->val = (void *)1;
          }
          else result->val = (void *)0;
        }
        else {
          if(l->val == r->val) result->val = (void *)1;
          else result->val = (void *)0;
        }
      }

      if(l->type == T_STRING) free(l->val);
      if(r->type == T_STRING) free(r->val);
      free(r);
      free(l);

      return result;
      /* }}} */

    case TOK_NE:
      /* {{{ not equal */
      l = flt_lf_evaluate(n->left,msg,tid);
      r = flt_lf_evaluate(n->right,msg,tid);

      if(l->type == T_STRING) {
        if(cf_strcasecmp(l->val,r->val) == 0) result->val = (void *)0; /* false: strings are equal */
        else result->val = (void *)1;
      }
      else {
        if(l->val == r->val) result->val = (void *)0;
        else result->val = (void *)1;
      }

      flt_lf_r2l(l,r);
      result->type = T_BOOL;

      if(l->type == T_STRING) free(l->val);
      if(r->type == T_STRING) free(r->val);
      free(r);
      free(l);

      return result;
      /* }}} */

    case TOK_OR:
      /* {{{ or */
      result->type = T_BOOL;
      l = flt_lf_evaluate(n->left,msg,tid);
      if(flt_lf_is_true(l)) result->val = (void *)1;

      if(!result->val) {
        r = flt_lf_evaluate(n->right,msg,tid);
        if(flt_lf_is_true(r)) result->val = (void *)1;
      }

      if(l->type == T_STRING) free(l->val);
      if(r && r->type == T_STRING) free(r->val);
      free(r);
      free(l);

      return result;
      /* }}} */

    case TOK_AND:
      /* {{{ and */
      l = flt_lf_evaluate(n->left,msg,tid);
      r = flt_lf_evaluate(n->right,msg,tid);

      flt_lf_to_bool(l);
      flt_lf_to_bool(r);

      result->type = T_BOOL;

      if(!l->val || !r->val) result->val = (void *)0;
      else result->val = (void *)1;

      free(l);
      free(r);

      return result;
      /* }}} */

    case TOK_ID:
      /* {{{ id */
      if(n->content > (u_char *)1) {
        switch(*n->content) {
          case 'a':
            result->type = T_STRING;
            result->val  = strdup(msg->author.content);
            return result;
          case 's':
            result->type = T_STRING;
            result->val  = strdup(msg->subject.content);
            return result;
          case 'c':
            result->type = T_STRING;
            result->val  = msg->category.len ? strdup(msg->category.content) : strdup("");
            return result;
          case 'd':
            result->type = T_DATE;
            result->val  = (void *)msg->date;
            return result;
          case 'l':
            result->type = T_INT;
            result->val = (void *)msg->level;
            return result;
          case 'v':
            result->type = T_BOOL;
            if(cf_strcasecmp(n->content,"visited") == 0) {
              if(is_visited) result->val = (void *)(is_visited(&(msg->mid)) == NULL ? 0 : 1);
              else result->val = (void *)0;
            }
            else result->val = (void *)(msg->may_show == 0 ? 0 : 1);
            return result;
          case 't':
            result->type = T_INT;
            result->val = (void *)tid;
            return result;
        }
      }
      else {
        result->type = T_BOOL;
        result->val  = (void *)(n->content == (u_char *)1 ? 1 : 0);
        return result;
      }
      /* }}} */

    case TOK_STR:
      /* {{{ string */
      result->type = T_STRING;
      result->val  = strdup(n->content);
      return result;
      /* }}} */

    case TOK_LPAREN:
      result->type = T_BOOL;
      if(n->argument) {
        tmp = flt_lf_evaluate(n->argument,msg,tid);
        flt_lf_to_bool(tmp);
        result->val = tmp->val;
        free(tmp);
      }
      else result->val = (void *)0;
      return result;
  }

  return NULL;
}
Example #14
0
NET *s_traverse_net (TOPLEVEL *pr_current, NET *nets, int starting,
                     OBJECT *object, char *hierarchy_tag, int type)
{
  NET *new_net;
  CONN *c_current;
  GList *cl_current;
  char *temp = NULL;
  const gchar *netattrib_pinnum = NULL;

  visit (object);

  if (connection_type (object) != type)
    return nets;

  new_net = nets = s_net_add(nets);
  new_net->nid = object->sid;

  /* pins are not allowed to have the netname attribute attached to them */
  if (object->type != OBJ_PIN) {
    /* Ignore netname attributes on buses */
    if (object->type == OBJ_NET)
      temp = o_attrib_search_object_attribs_by_name (object, "netname", 0);

    if (temp) {
      new_net->net_name =
        s_hierarchy_create_netname(pr_current, temp,
                                   hierarchy_tag);
      g_free(temp);
    } else if (object->type == OBJ_NET) {
      /* search for the old label= attribute on nets */
      temp = o_attrib_search_object_attribs_by_name (object, "label", 0);
      if (temp) {
        printf(_("WARNING: Found label=%s. label= is deprecated, please use netname=\n"), temp);
        new_net->net_name =
          s_hierarchy_create_netname(pr_current, temp,
                                     hierarchy_tag);
        g_free(temp);
      }
    }
  }
#if DEBUG
  printf("inside traverse: %s\n", object->name);
#endif

  if (object->type == OBJ_PIN) {

    verbose_print (starting ? "p" : "P");

    new_net->connected_to =
      s_net_return_connected_string (pr_current, object, hierarchy_tag);

    temp = o_attrib_search_object_attribs_by_name (object, "pinlabel", 0);

    if (temp) {
      new_net->pin_label = temp;
    }

    /* net= new */
    netattrib_pinnum = s_netattrib_connected_string_get_pinnum (nets->connected_to);
    if (netattrib_pinnum != NULL && type == PIN_TYPE_NET) {

#if DEBUG
      printf("going to find netname %s \n", nets->connected_to);
#endif
      nets->net_name =
        s_netattrib_return_netname (pr_current, object,
                                    nets->connected_to,
                                    hierarchy_tag);
      nets->net_name_has_priority = TRUE;
      g_free(nets->connected_to);
      nets->connected_to = NULL;
    }
#if DEBUG
    printf("traverse connected_to: %s\n", new_net->connected_to);
#endif

    /* Terminate if we hit a pin which isn't the one we started with */
    if (!starting)
      return nets;
  }

  /*printf("Found net %s\n", object->name); */
  verbose_print("n");

  /* this is not perfect yet and won't detect a loop... */
  if (is_visited(object) > 100) {
    fprintf(stderr, _("Found a possible net/pin infinite connection\n"));
    exit(-1);
  }

  cl_current = object->conn_list;
  while (cl_current != NULL) {

    c_current = (CONN *) cl_current->data;

    if (c_current->other_object != NULL) {

      if (!is_visited(c_current->other_object) &&
          c_current->other_object != object) {
        nets = s_traverse_net (pr_current, nets, FALSE,
                               c_current->other_object, hierarchy_tag, type);
      }

    }
    cl_current = g_list_next(cl_current);
  }

  return (nets);
}
Example #15
0
int main(int argc, char ** argv)
{
    long filesize;
    uint8_t *filebuf;
    char disbuf[1024];
    z80inst instbuf;
    uint8_t * cur;
    FILE * f = fopen(argv[1], "rb");
    fseek(f, 0, SEEK_END);
    filesize = ftell(f);
    fseek(f, 0, SEEK_SET);
    filebuf = malloc(filesize);
    fread(filebuf, 1, filesize, f);
    fclose(f);
    deferred *def = NULL, *tmpd;
    uint16_t offset = 0;
    for(uint8_t opt = 2; opt < argc; ++opt) {
        if (argv[opt][0] == '-') {
            FILE * address_log;
            switch (argv[opt][1])
            {
            case 'l':
                labels = 1;
                break;
            case 'a':
                addr = 1;
                break;
            case 'o':
                only = 1;
                break;
            case 'f':
                opt++;
                if (opt >= argc) {
                    fputs("-f must be followed by a filename\n", stderr);
                    exit(1);
                }
                address_log = fopen(argv[opt], "r");
                if (!address_log) {
                    fprintf(stderr, "Failed to open %s for reading\n", argv[opt]);
                    exit(1);
                }
                while (fgets(disbuf, sizeof(disbuf), address_log)) {
                    if (disbuf[0]) {
                        uint16_t address = strtol(disbuf, NULL, 16);
                        if (address) {
                            def = defer(address, def);
                            reference(address);
                        }
                    }
                }
                break;
            case 's':
                opt++;
                if (opt >= argc) {
                    fputs("-s must be followed by a start offset in hex\n", stderr);
                    exit(1);
                }
                offset = strtol(argv[opt], NULL, 16);
                break;
            }
        } else {
            uint16_t address = strtol(argv[opt], NULL, 16);
            def = defer(address, def);
            reference(address);
        }
    }
    uint16_t start = offset;
    uint8_t *encoded, *next;
    uint32_t size;
    if (!def || !only) {
        def = defer(start, def);
    }
    uint16_t address;
    while(def) {
        do {
            encoded = NULL;
            address = def->address;
            if (!is_visited(address)) {
                encoded = filebuf + address - offset;
            }
            tmpd = def;
            def = def->next;
            free(tmpd);
        } while(def && encoded == NULL);
        if (!encoded) {
            break;
        }
        for(;;) {
            if ((address - offset) > filesize || is_visited(address) || address < offset) {
                break;
            }
            visit(address);
            next = z80_decode(encoded, &instbuf);
            address += (next-encoded);
            encoded = next;

            //z80_disasm(&instbuf, disbuf);
            //printf("%X: %s\n", address, disbuf);
            switch (instbuf.op)
            {
            case Z80_JR:
                address += instbuf.immed;
                encoded = filebuf + address - offset;
                break;
            case Z80_JRCC:
                reference(address + instbuf.immed);
                def = defer(address + instbuf.immed, def);
                break;
            case Z80_JP:
                address = instbuf.immed;
                encoded = filebuf + address - offset;
                break;
            case Z80_JPCC:
            case Z80_CALL:
            case Z80_CALLCC:
            case Z80_RST:
                reference(instbuf.immed);
                def = defer(instbuf.immed, def);
                break;
            default:
                if (z80_is_terminal(&instbuf)) {
                    address = filesize + 1;
                }
            }
        }
    }
    if (labels) {
        for (address = filesize; address < (64*1024); address++) {
            if (is_label(address)) {
                printf("ADR_%X equ $%X\n", address, address);
            }
        }
        puts("");
    }
    for (address = offset; address < filesize + offset; address++) {
        if (is_visited(address)) {
            encoded = filebuf + address - offset;
            z80_decode(encoded, &instbuf);
            if (labels) {
                /*m68k_disasm_labels(&instbuf, disbuf);
                if (is_label(instbuf.address)) {
                	printf("ADR_%X:\n", instbuf.address);
                }
                if (addr) {
                	printf("\t%s\t;%X\n", disbuf, instbuf.address);
                } else {
                	printf("\t%s\n", disbuf);
                }*/
            } else {
                z80_disasm(&instbuf, disbuf, address);
                printf("%X: %s\n", address, disbuf);
            }
        }
    }
    return 0;
}