コード例 #1
0
ファイル: expand.cpp プロジェクト: A-G-F/coda-sass-plugin
 Statement* Expand::operator()(If* i)
 {
   if (*i->predicate()->perform(eval->with(env, backtrace))) {
     append_block(i->consequent());
   }
   else {
     Block* alt = i->alternative();
     if (alt) append_block(alt);
   }
   return 0;
 }
コード例 #2
0
ファイル: expand.cpp プロジェクト: A-G-F/coda-sass-plugin
 Statement* Expand::operator()(For* f)
 {
   string variable(f->variable());
   Expression* low = f->lower_bound()->perform(eval->with(env, backtrace));
   if (low->concrete_type() != Expression::NUMBER) {
     error("lower bound of `@for` directive must be numeric", low->path(), low->position(), backtrace);
   }
   Expression* high = f->upper_bound()->perform(eval->with(env, backtrace));
   if (high->concrete_type() != Expression::NUMBER) {
     error("upper bound of `@for` directive must be numeric", high->path(), high->position(), backtrace);
   }
   double lo = static_cast<Number*>(low)->value();
   double hi = static_cast<Number*>(high)->value();
   if (f->is_inclusive()) ++hi;
   Env new_env;
   new_env[variable] = new (ctx.mem) Number(low->path(), low->position(), lo);
   new_env.link(env);
   env = &new_env;
   Block* body = f->block();
   for (double i = lo;
        i < hi;
        (*env)[variable] = new (ctx.mem) Number(low->path(), low->position(), ++i)) {
     append_block(body);
   }
   env = new_env.parent();
   return 0;
 }
コード例 #3
0
ファイル: expand.cpp プロジェクト: A-G-F/coda-sass-plugin
 Statement* Expand::operator()(Mixin_Call* c)
 {
   string full_name(c->name() + "[m]");
   if (!env->has(full_name)) {
     error("no mixin named " + c->name(), c->path(), c->position(), backtrace);
   }
   Definition* def = static_cast<Definition*>((*env)[full_name]);
   Block* body = def->block();
   Parameters* params = def->parameters();
   Arguments* args = static_cast<Arguments*>(c->arguments()
                                              ->perform(eval->with(env, backtrace)));
   Backtrace here(backtrace, c->path(), c->position(), ", in mixin `" + c->name() + "`");
   backtrace = &here;
   Env new_env;
   new_env.link(def->environment());
   if (c->block()) {
     // represent mixin content blocks as thunks/closures
     Definition* thunk = new (ctx.mem) Definition(c->path(),
                                                  c->position(),
                                                  "@content",
                                                  new (ctx.mem) Parameters(c->path(), c->position()),
                                                  c->block(),
                                                  Definition::MIXIN);
     thunk->environment(env);
     new_env.current_frame()["@content[m]"] = thunk;
   }
   bind("mixin " + c->name(), params, args, ctx, &new_env, eval);
   Env* old_env = env;
   env = &new_env;
   append_block(body);
   env = old_env;
   backtrace = here.parent;
   return 0;
 }
コード例 #4
0
ファイル: dcache.c プロジェクト: AhmadTux/DragonFlyBSD
static void
invalidate_block (struct dcache_block *block, void *param)
{
  DCACHE *dcache = (DCACHE *) param;

  splay_tree_remove (dcache->tree, (splay_tree_key) block->addr);
  append_block (&dcache->freelist, block);
}
コード例 #5
0
ファイル: cssize.cpp プロジェクト: ezinaz/MobilePlayground
 Statement* Cssize::operator()(Block* b)
 {
   Block* bb = SASS_MEMORY_NEW(ctx.mem, Block, b->pstate(), b->length(), b->is_root());
   // bb->tabs(b->tabs());
   block_stack.push_back(bb);
   append_block(b);
   block_stack.pop_back();
   return bb;
 }
コード例 #6
0
ファイル: cssize.cpp プロジェクト: xzyfer/libsass
 Block_Ptr Cssize::operator()(Block_Ptr b)
 {
   Block_Obj bb = SASS_MEMORY_NEW(Block, b->pstate(), b->length(), b->is_root());
   // bb->tabs(b->tabs());
   block_stack.push_back(bb);
   append_block(b, bb);
   block_stack.pop_back();
   return bb.detach();
 }
コード例 #7
0
ファイル: expand.cpp プロジェクト: A-G-F/coda-sass-plugin
 Statement* Expand::operator()(While* w)
 {
   Expression* pred = w->predicate();
   Block* body = w->block();
   while (*pred->perform(eval->with(env, backtrace))) {
     append_block(body);
   }
   return 0;
 }
コード例 #8
0
ファイル: bm3d.c プロジェクト: yxliang/BM3D
// --------------------------------------------------------------------------
// METHODS FOR INTERMEDIATE STEPS
// --------------------------------------------------------------------------
int get_chrom (png_img* img, list_t* source_list, list_t* target_list, unsigned int const channel) {
	group_node_t* tmp = *source_list;
	block_node_t* group;
	block_t* block;
	int x, y, bs;
	double d;
	group_t tmp_group = 0;				// group, which holds a set of similar blocks
	block_t tmp_block;

	// validate input list
	if (tmp == NULL) {
		generate_error ("Invalid reference list for extracting chrominance channels...");
		return 1;
	}

	// allocate block memory
	if (new_block_struct(tmp->group->block.block_size, &tmp_block) != 0) {
		return 1;
	}

	// go through all groups
	while (tmp != NULL) {
		group = tmp->group;

		// iterate over all blocks within the actual group
		while (group != NULL) {
			block = &group->block;
			x = block->x;
			y = block->y;
			bs = block->block_size;
			d = group->distance;

			// obtain block data for the u-channel
			if (get_block (img, channel, &tmp_block, x-(bs/2), y-(bs/2)) != 0) {
				return 1;
			}
				
			// append block data to the regarding group
			if (append_block (&tmp_group, &tmp_block, d) != 0) {
				return 1;
			}

			group = group->next;
		}

		// add extracted groups to regarding lists
		if (append_group (target_list, &tmp_group) != 0) {
			return 1;
		}

		tmp_group = 0; 
		tmp = tmp->next;
	}

	return 0;
}
コード例 #9
0
ファイル: mksfs.c プロジェクト: 151706061/ucore_lab
static void
add_entry(struct sfs_fs *sfs, struct cache_inode *current, struct cache_inode *file, const char *name) {
    static struct sfs_entry __entry, *entry = &__entry;
    assert(current->inode.type == SFS_TYPE_DIR && strlen(name) <= SFS_MAX_FNAME_LEN);
    entry->ino = file->ino, strcpy(entry->name, name);
    uint32_t entry_ino = sfs_alloc_ino(sfs);
    write_block(sfs, entry, sizeof(entry->name), entry_ino);
    append_block(sfs, current, sizeof(entry->name), entry_ino, name);
    file->inode.nlinks ++;
}
コード例 #10
0
ファイル: mksfs.c プロジェクト: 151706061/ucore_lab
void
open_link(struct sfs_fs *sfs, struct cache_inode *file, const char *filename) {
    static char buffer[SFS_BLKSIZE];
    uint32_t ino = sfs_alloc_ino(sfs);
    ssize_t ret = readlink(filename, buffer, sizeof(buffer));
    if (ret < 0 || ret == SFS_BLKSIZE) {
        open_bug(sfs, filename, "read link failed, %d", (int)ret);
    }
    write_block(sfs, buffer, ret, ino);
    append_block(sfs, file, ret, ino, filename);
}
コード例 #11
0
ファイル: expand.cpp プロジェクト: A-G-F/coda-sass-plugin
 Statement* Expand::operator()(Block* b)
 {
   Env new_env;
   new_env.link(*env);
   env = &new_env;
   Block* bb = new (ctx.mem) Block(b->path(), b->position(), b->length(), b->is_root());
   block_stack.push_back(bb);
   append_block(b);
   block_stack.pop_back();
   env = env->parent();
   return bb;
 }
コード例 #12
0
inline AObjReusePool<_ObjectType>::AObjReusePool(
  uint32_t initial_size,
  uint32_t expand_size
  ) :
  m_pool(nullptr, 0u, initial_size),
  m_block_p(nullptr),
  m_expand_size(expand_size)
  #ifdef AORPOOL_USAGE_COUNT
    , m_count_now(0u), m_count_max(0u), m_grow_f(nullptr)
  #endif
  {
  append_block(initial_size);
  }
コード例 #13
0
ファイル: dcache.c プロジェクト: AhmadTux/DragonFlyBSD
static void
dcache_invalidate_line (DCACHE *dcache, CORE_ADDR addr)
{
  struct dcache_block *db = dcache_hit (dcache, addr);

  if (db)
    {
      splay_tree_remove (dcache->tree, (splay_tree_key) db->addr);
      remove_block (&dcache->oldest, db);
      append_block (&dcache->freelist, db);
      --dcache->size;
    }
}
コード例 #14
0
    //
    // process_local_garbage
    //
    void ThreadLocalCollector::process_local_garbage(void (*garbage_list_handler)(ThreadLocalCollector *)) {
        // Gather the garbage blocks into _tlcBuffer, which currently holds marked blocks.
        usword_t garbage_count = _localBlocks.count() - _tlcBufferCount;
        if (garbage_count == 0) {
            // no garbage
            // TODO:  if we keep hitting this condition, we could use feedback to increase the thread local threshold.
            _localBlocks.clearFlags();    // clears flags only.
			GARBAGE_COLLECTION_COLLECTION_END((auto_zone_t*)_zone, 0ull, 0ull, _localBlocks.count(), (uint64_t)(-1));
            return;
        }

        _tlcBufferCount = 0;
        size_t scavenged_size = 0; 
        
        // use the mark bit in _localBlocks to generate a garbage list in _tlcBuffer/_tlcBufferCount
        for (uint32_t i = _localBlocks.firstOccupiedSlot(), last = _localBlocks.lastOccupiedSlot(); (i <= last) && (_tlcBufferCount != garbage_count); i++) {
            void *block = _localBlocks.unmarkedPointerAtIndex(i);
            if (block) {
                Subzone *subzone = Subzone::subzone(block);
                usword_t q = subzone->quantum_index_unchecked(block);
                if (subzone->is_thread_local(q)) {
						scavenged_size += subzone->size(q);
                    append_block(block);
                    _localBlocks.remove(i);
                } else {
                    auto_error(_zone, "not thread local garbage", (const void *)block);
                }
            }
        }
#ifdef MEASURE_TLC_STATS
        _zone->statistics().add_local_collected(_tlcBufferCount);
#endif
        
        // clear the marks & compact. must be done before evict_local_garbage(), which does more marking.
        // if the thread is not suspended then we can also possibly shrink the locals list size
        // if the thread IS suspended then we must not allocate
        if (_thread.suspended())
            _localBlocks.clearFlagsRehash();
        else
            _localBlocks.clearFlagsCompact();
        
        AUTO_PROBE(auto_probe_end_local_scan(_tlcBufferCount, &_tlcBuffer[0]));

        garbage_list_handler(this);

        // skip computing the locals size if the probe is not enabled
        if (GARBAGE_COLLECTION_COLLECTION_PHASE_END_ENABLED())
            GARBAGE_COLLECTION_COLLECTION_END((auto_zone_t*)_zone, garbage_count, (uint64_t)scavenged_size, _localBlocks.count(), (uint64_t)_localBlocks.localsSize());
    }
コード例 #15
0
ファイル: mksfs.c プロジェクト: 151706061/ucore_lab
void
open_file(struct sfs_fs *sfs, struct cache_inode *file, const char *filename, int fd) {
    static char buffer[SFS_BLKSIZE];
    ssize_t ret, last = SFS_BLKSIZE;
    while ((ret = read(fd, buffer, sizeof(buffer))) != 0) {
        assert(last == SFS_BLKSIZE);
        uint32_t ino = sfs_alloc_ino(sfs);
        write_block(sfs, buffer, ret, ino);
        append_block(sfs, file, ret, ino, filename);
        last = ret;
    }
    if (ret < 0) {
        open_bug(sfs, filename, "read file failed.\n");
    }
}
コード例 #16
0
ファイル: dcache.c プロジェクト: AhmadTux/DragonFlyBSD
static struct dcache_block *
dcache_alloc (DCACHE *dcache, CORE_ADDR addr)
{
  struct dcache_block *db;

  if (dcache->size >= dcache_size)
    {
      /* Evict the least recently allocated line.  */
      db = dcache->oldest;
      remove_block (&dcache->oldest, db);

      splay_tree_remove (dcache->tree, (splay_tree_key) db->addr);
    }
  else
    {
      db = dcache->freelist;
      if (db)
	remove_block (&dcache->freelist, db);
      else
	db = xmalloc (offsetof (struct dcache_block, data) +
		      dcache->line_size);

      dcache->size++;
    }

  db->addr = MASK (dcache, addr);
  db->refs = 0;

  /* Put DB at the end of the list, it's the newest.  */
  append_block (&dcache->oldest, db);

  splay_tree_insert (dcache->tree, (splay_tree_key) db->addr,
		     (splay_tree_value) db);

  return db;
}
コード例 #17
0
ファイル: expand.cpp プロジェクト: A-G-F/coda-sass-plugin
 Statement* Expand::operator()(Each* e)
 {
   string variable(e->variable());
   Expression* expr = e->list()->perform(eval->with(env, backtrace));
   List* list = 0;
   if (expr->concrete_type() != Expression::LIST) {
     list = new (ctx.mem) List(expr->path(), expr->position(), 1, List::COMMA);
     *list << expr;
   }
   else {
     list = static_cast<List*>(expr);
   }
   Env new_env;
   new_env[variable] = 0;
   new_env.link(env);
   env = &new_env;
   Block* body = e->block();
   for (size_t i = 0, L = list->length(); i < L; ++i) {
     (*env)[variable] = (*list)[i]->perform(eval->with(env, backtrace));
     append_block(body);
   }
   env = new_env.parent();
   return 0;
 }
コード例 #18
0
inline _ObjectType * AObjReusePool<_ObjectType>::pop()
  {
  #ifdef AORPOOL_USAGE_COUNT
    m_count_now++;

    if (m_count_now > m_count_max)
      {
      m_count_max = m_count_now;
      }
  #endif

  if (m_pool.get_length() == 0u)
    {
    if (m_exp_pool.get_length() == 0u)
      {
      // No free objects, so make more
      append_block(m_expand_size);
      }

    return m_exp_pool.pop_last();
    }

  return m_pool.pop_last();
  }
コード例 #19
0
ファイル: expand.cpp プロジェクト: smikes/libsass
  Statement* Expand::operator()(Each* e)
  {
    vector<string> variables(e->variables());
    Expression* expr = e->list()->perform(eval->with(env, backtrace));
    List* list = 0;
    Map* map = 0;
    if (expr->concrete_type() == Expression::MAP) {
      map = static_cast<Map*>(expr);
    }
    else if (expr->concrete_type() != Expression::LIST) {
      list = new (ctx.mem) List(expr->path(), expr->position(), 1, List::COMMA);
      *list << expr;
    }
    else {
      list = static_cast<List*>(expr);
    }
    Env new_env;
    for (size_t i = 0, L = variables.size(); i < L; ++i) new_env[variables[i]] = 0;
    new_env.link(env);
    env = &new_env;
    Block* body = e->block();

    if (map) {
      for (auto key : map->keys()) {
        Expression* k = key->perform(eval->with(env, backtrace));
        Expression* v = map->at(key)->perform(eval->with(env, backtrace));

        if (variables.size() == 1) {
          List* variable = new (ctx.mem) List(map->path(), map->position(), 2, List::SPACE);
          *variable << k;
          *variable << v;
          (*env)[variables[0]] = variable;
        } else {
          (*env)[variables[0]] = k;
          (*env)[variables[1]] = v;
        }
        append_block(body);
      }
    }
    else {
      for (size_t i = 0, L = list->length(); i < L; ++i) {
        List* variable = 0;
        if ((*list)[i]->concrete_type() != Expression::LIST  || variables.size() == 1) {
          variable = new (ctx.mem) List((*list)[i]->path(), (*list)[i]->position(), 1, List::COMMA);
          *variable << (*list)[i];
        }
        else {
          variable = static_cast<List*>((*list)[i]);
        }
        for (size_t j = 0, K = variables.size(); j < K; ++j) {
          if (j < variable->length()) {
            (*env)[variables[j]] = (*variable)[j]->perform(eval->with(env, backtrace));
          }
          else {
            (*env)[variables[j]] = new (ctx.mem) Null(expr->path(), expr->position());
          }
        }
        append_block(body);
      }
    }
    env = new_env.parent();
    return 0;
  }
コード例 #20
0
ファイル: bm3d.c プロジェクト: yxliang/BM3D
// method, which performs the block-matching for a given channel
int block_matching (png_img* img,
						  png_img* tmp,
						  unsigned int const b_size,
						  unsigned int const b_step,
						  unsigned int const sigma,
						  unsigned int const h_search,
						  unsigned int const v_search,
						  double const th_2d,
						  double const tau_match,
						  unsigned int const channel,
						  unsigned int block_marking,
						  list_t* list) {
	int i, j, k, l;
	block_t ref_block;
	block_t cmp_block;
	double d;							// block distance
	group_t group = 0;				// group, which holds a set of similar blocks
	int count = 0;						// variable to add increasing numbers to the file names

	// allocate block memory
	if (new_block_struct(b_size, &ref_block) != 0) {
		return 1;
	}
	
	if (new_block_struct(b_size, &cmp_block) != 0) {
		return 1;
	}

	// compare blocks according to the sliding-window manner
	for (j=0; j<img->height; j=j+b_step) {
		for (i=0; i<img->width; i=i+b_step) {

			// obtain refernce block
			if (!exceeds_image_dimensions(img->width, img->height, b_size, i, j)) { 

				if (get_block (img, channel, &ref_block, i-(b_size/2), j-(b_size/2)) != 0) {
					return 1;
				}
				
				if (append_block (&group, &ref_block, 0.0) != 0) {
					return 1;
				}
				
				if (block_marking) {
					png_copy_values (tmp, img);
					mark_search_window (tmp, &ref_block, h_search, v_search);
					mark_ref_block (tmp, &ref_block);
				}

				for (l=0; l<img->height; l=l+b_step) {
					for (k=0; k<img->width; k=k+b_step) {

						// obtain block to compare to reference block
						if (!(exceeds_image_dimensions(img->width, img->height, b_size, k, l)) && 								
							 !(exceeds_search_window(img->width, img->height, b_size, h_search, v_search, i, j, k, l)) &&
							 !((i==k) && (j==l))) {			// must be different from reference block

							if (get_block (img, channel, &cmp_block, k-(b_size/2), l-(b_size/2)) != 0) {
								return 1;
							}

							// compare blocks for similarity
							d = get_block_distance (&ref_block, &cmp_block, sigma, th_2d);
							
							// decide whether block similarity is sufficient
							if (d < tau_match*255) {
								if (append_block (&group, &cmp_block, d) != 0) {
									return 1;
								}

								if (block_marking) {
									mark_cmp_block (tmp, &cmp_block);
								}
							}
						}
					}
				}


				// add group of similar blocks to list
				if (append_group (list, &group) != 0) {
					return 1;
				}

				// write output image with marked group in it
				if (block_marking) {
					yuv2rgb(tmp);
					if (png_write(tmp, "img/rgb/grp/", "group", ++count) != 0) {
						return 1;
					}
				}

				group = 0; 
			}
		}
	}

	return 0;
}
コード例 #21
0
ファイル: expand.cpp プロジェクト: A-G-F/coda-sass-plugin
 Statement* Expand::operator()(Import_Stub* i)
 {
   append_block(ctx.style_sheets[i->file_name()]);
   return 0;
 }
コード例 #22
0
    TEST_FIXTURE(container_test_base, container_list_blobs)
    {
        m_container.create(azure::storage::blob_container_public_access_type::off, azure::storage::blob_request_options(), m_context);
        check_container_no_stale_property(m_container);
        std::map<utility::string_t, azure::storage::cloud_blob> blobs;

        for (int i = 0; i < 4; i++)
        {
            auto index = utility::conversions::print_string(i);
            auto blob = m_container.get_block_blob_reference(_XPLATSTR("blockblob") + index);
            blob.metadata()[_XPLATSTR("index")] = index;
            
            std::vector<uint8_t> buffer;
            buffer.resize(i * 16 * 1024);
            auto stream = concurrency::streams::container_stream<std::vector<uint8_t>>::open_istream(buffer);
            blob.upload_from_stream(stream, azure::storage::access_condition(), azure::storage::blob_request_options(), m_context);
            blobs[blob.name()] = blob;
        }

        for (int i = 0; i < 3; i++)
        {
            auto index = utility::conversions::print_string(i);
            auto blob = m_container.get_page_blob_reference(_XPLATSTR("pageblob") + index);
            blob.metadata()[_XPLATSTR("index")] = index;
            
            blob.create(i * 512, 0, azure::storage::access_condition(), azure::storage::blob_request_options(), m_context);
            check_container_no_stale_property(m_container);
            blobs[blob.name()] = blob;
        }

        for (int i = 0; i < 3; i++)
        {
            auto index = utility::conversions::print_string(i);
            auto blob = m_container.get_append_blob_reference(_XPLATSTR("appendblob") + index);
            blob.metadata()[_XPLATSTR("index")] = index;

            blob.create_or_replace(azure::storage::access_condition(), azure::storage::blob_request_options(), m_context);
            check_container_no_stale_property(m_container);

            std::vector<uint8_t> buffer;
            buffer.resize((i + 1) * 8 * 1024);
            fill_buffer_and_get_md5(buffer);
            auto stream = concurrency::streams::container_stream<std::vector<uint8_t>>::open_istream(buffer);
            blob.append_block(stream, utility::string_t(), azure::storage::access_condition(), azure::storage::blob_request_options(), m_context);
            blobs[blob.name()] = blob;
        }

        auto listing1 = list_all_blobs(utility::string_t(), azure::storage::blob_listing_details::all, 0, azure::storage::blob_request_options());
        for (auto iter = listing1.begin(); iter != listing1.end(); ++iter)
        {
            auto blob = blobs.find(iter->name());
            CHECK(blob != blobs.end());

            CHECK_UTF8_EQUAL(blob->second.uri().primary_uri().to_string(), iter->uri().primary_uri().to_string());
            CHECK_UTF8_EQUAL(blob->second.uri().secondary_uri().to_string(), iter->uri().secondary_uri().to_string());

            auto index_str = blob->second.metadata().find(_XPLATSTR("index"));
            CHECK(index_str != blob->second.metadata().end());
            auto index = utility::conversions::scan_string<int>(index_str->second);

            switch (iter->type())
            {
            case azure::storage::blob_type::block_blob:
                CHECK_EQUAL(index * 16 * 1024, iter->properties().size());
                break;

            case azure::storage::blob_type::page_blob:
                CHECK_EQUAL(index * 512, iter->properties().size());
                break;

            case azure::storage::blob_type::append_blob:
                CHECK_EQUAL((index + 1) * 8 * 1024, iter->properties().size());
                break;

            default:
                CHECK(false);
                break;
            }

            blobs.erase(blob);
        }

        CHECK_EQUAL(0U, blobs.size());

        auto listing2 = list_all_blobs(_XPLATSTR("block"), azure::storage::blob_listing_details::none, 10, azure::storage::blob_request_options());
        CHECK_EQUAL(4U, listing2.size());
        for (auto iter = listing2.begin(); iter != listing2.end(); ++iter)
        {
            CHECK(iter->metadata().empty());
        }
    }
コード例 #23
0
ファイル: ptftp.c プロジェクト: Soerboe/ptftp
int get(int sockfd, char *remote_file, char *local_file) {
    int len,
        pkt_num = 1;
    char request[512];
    struct file_info fi;
    uint8_t successful = FALSE;

    /* Create local file */
    strcpy(fi.filename, local_file);
    strcpy(fi.mode, MODE_OCTET); //TODO
    fi.readonly = FALSE;

    if (file_init(&fi) == ERRNO_FOPEN) {
        error_num(6);
        return -1;
    }

    struct pkt_request req;
    req.opcode = PKT_RRQ;
    strcpy(req.filename, remote_file);
    strcpy(req.mode, MODE_OCTET); // TODO
    len = serialize_request(&req, request);

    dccp_send(sockfd, request, len);

    while (TRUE) {
        int bytes;
        char buf[BUF_SIZE];

        if ((bytes = recv(sockfd, buf, BUF_SIZE, 0)) <= 0) {
            /* Client shut down */
            if (bytes == 0) {
                //TODO client shut down
                error_num(4);
                break;
            } else  {
                //TODO error
            }
        }

        printf("PKT %d\n", pkt_num++);

        uint16_t opcode = ntohs(*(uint16_t *) buf);

        /* Handle incoming packet */
        if (opcode == PKT_DATA) {
            uint32_t block = ntohs(*(uint32_t *) (buf + B2));
            char *data = buf + B2 + B4;

            printf("block: %d\n", block);

            /* Ignore data with wrong block number */
            if (block == fi.cur_block + 1) {
                append_block(&fi, data, bytes - B2 - B4);
            } else if (block <= fi.cur_block) { // resend ack for lost packet
                send_ack(sockfd, block);
                continue;
            } else {
                continue;
            }

            printf("last_bytes: %d\n", fi.last_numbytes);

            /* Send ACK */
    if (pkt_num != 2 && pkt_num != 3 && pkt_num != 4) // DEBUG REMOVE
            send_ack(sockfd, block); 

            if (fi.last_numbytes < BLOCKSIZE) {
                // transfer finished
                successful = TRUE;
                break; // TODO not break, wait for timeout
            }

        } else if (opcode == PKT_ACK) {

        } else if (opcode == PKT_ERROR) {

        } else {

        }
    }

    file_close(&fi);
    if (!successful)
        remove(fi.filename);
    return 0;
}