void macro_append(const char *text) { struct membuf *mb; LOG(LOG_DEBUG, ("appending >>%s<< to macro\n", text)); mb = get_named_buffer(s->named_buffer, s->macro_name); membuf_append(mb, text, strlen(text)); }
static void WriteToBufferCallback(const char *text, int length, void *user_data) { struct membuf *buf = ((struct ParserData *)user_data)->buf; if (length < 0) length = strlen(text); membuf_append(buf, text, length); }
// Allowed only for membufs, and unmanaged output files. // For unmanaged output files, must be used with care, and should not be // mixed with dbuf_write(). void dbuf_write_at(dbuf *f, i64 pos, const u8 *m, i64 len) { if(len<1 || pos<0) return; if(pos + len > f->max_len_hard) { do_on_dbuf_size_exceeded(f); } if(f->btype==DBUF_TYPE_MEMBUF) { i64 amt_overwrite, amt_newzeroes, amt_append; if(pos+len <= f->len) { // entirely within the current file amt_overwrite = len; amt_newzeroes = 0; amt_append = 0; } else if(pos >= f->len) { // starts after the end of the current file amt_overwrite = 0; amt_newzeroes = pos - f->len; amt_append = len; } else { // overlaps the end of the current file amt_overwrite = f->len - pos; amt_newzeroes = 0; amt_append = len - amt_overwrite; } if(amt_overwrite>0) { de_memcpy(&f->membuf_buf[pos], m, (size_t)amt_overwrite); } if(amt_newzeroes>0) { dbuf_write_zeroes(f, amt_newzeroes); } if(amt_append>0) { membuf_append(f, &m[amt_overwrite], amt_append); } } else if(f->btype==DBUF_TYPE_OFILE && !f->is_managed) { i64 curpos = de_ftell(f->fp); if(pos != curpos) { de_fseek(f->fp, pos, SEEK_SET); } fwrite(m, 1, (size_t)len, f->fp); if(pos+len > f->len) { f->len = pos+len; } } else if(f->btype==DBUF_TYPE_NULL) { ; } else { de_err(f->c, "internal: Attempt to seek on non-seekable stream"); de_fatalerror(f->c); } }
void read_file(const char *name, struct membuf *buf) { char block[1024]; FILE *in; int len; in = fopen(name, "rb"); if(in == NULL) { LOG(LOG_ERROR, ("Can't open file \"%s\" for input.\n", name)); exit(-1); } do { len = fread(block, 1, 1024, in); membuf_append(buf, block, len); } while(len == 1024); LOG(LOG_DEBUG, ("read %d bytes from file\n", len)); fclose(in); }
void dbuf_write(dbuf *f, const u8 *m, i64 len) { if(f->len + len > f->max_len_hard) { do_on_dbuf_size_exceeded(f); } if(f->writecallback_fn) { f->writecallback_fn(f, m, len); } if(f->btype==DBUF_TYPE_NULL) { f->len += len; return; } else if(f->btype==DBUF_TYPE_OFILE || f->btype==DBUF_TYPE_STDOUT) { if(!f->fp) return; if(f->c->debug_level>=3) { de_dbg3(f->c, "writing %d bytes to %s", (int)len, f->name); } fwrite(m, 1, (size_t)len, f->fp); f->len += len; return; } else if(f->btype==DBUF_TYPE_MEMBUF) { if(f->c->debug_level>=3 && f->name) { de_dbg3(f->c, "appending %d bytes to membuf %s", (int)len, f->name); } membuf_append(f, m, len); return; } else if(f->btype==DBUF_TYPE_ODBUF) { dbuf_write(f->parent_dbuf, m, len); f->len += len; return; } de_err(f->c, "Internal: Invalid output file type (%d)", f->btype); de_fatalerror(f->c); }
static int do_load(char *file_name, struct membuf *mem) { struct load_info info[1]; unsigned char *p; membuf_clear(mem); membuf_append(mem, NULL, 65536); p = membuf_get(mem); info->basic_txt_start = -1; load_located(file_name, p, info); /* move memory to beginning of buffer */ membuf_truncate(mem, info->end); membuf_trim(mem, info->start); LOG(LOG_NORMAL, (" Crunching from $%04X to $%04X.", info->start, info->end)); return info->start; }
static void load_plain_file(const char *name, struct membuf *mb) { int file_len; int read_len; int offset = 0; int len = -1; FILE *in; in = fopen(name, "rb"); if(in == NULL) { char *p = strrchr(name, ','); if(p == NULL) { /* not found and no comma */ LOG(LOG_ERROR, ("Error: file not found.\n")); exit(1); } *p = '\0'; if(str_to_int(p + 1, &offset)) { LOG(LOG_ERROR, ("Error: invalid value for plain file offset.\n")); exit(1); } in = fopen(name, "rb"); if(in == NULL) { p = strrchr(name, ','); len = offset; if(len < 0) { LOG(LOG_ERROR, ("Error, value for plain file " "len must not be negative.\n")); exit(1); } *p = '\0'; if(str_to_int(p + 1, &offset)) { LOG(LOG_ERROR, ("Error: invalid value for plain file offset.\n")); exit(1); } in = fopen(name, "rb"); if(in == NULL) { /* really not found */ LOG(LOG_ERROR, ("Error: file not found.\n")); exit(1); } } } /* get the real length of the file and validate the offset*/ if(fseek(in, 0, SEEK_END)) { LOG(LOG_ERROR, ("Error: can't seek to EOF.\n")); fclose(in); exit(1); } file_len = ftell(in); if(offset < 0) { offset += file_len; } if(len < 0) { len = file_len - offset; } if(fseek(in, offset, SEEK_SET)) { LOG(LOG_ERROR, ("Error: can't seek to offset %d.\n", offset)); fclose(in); exit(1); } if(offset + len > file_len) { LOG(LOG_ERROR, ("Error: can't read %d bytes from offset %d.\n", len, offset)); fclose(in); exit(1); } LOG(LOG_VERBOSE, ("Reading %d bytes from offset %d.\n", len, offset)); do { char buf[1024]; int r = 1024 < len? 1024: len; read_len = fread(buf, 1, r, in); if(read_len < r) { LOG(LOG_ERROR, ("Error: tried to read %d bytes but got %d.\n", r, read_len)); fclose(in); exit(1); } membuf_append(mb, buf, r); len -= r; } while(len > 0); fclose(in); }
static int do_loads(int filec, char *filev[], struct membuf *mem, int basic_txt_start, int sys_token, int *basic_var_startp, int *runp, int trim_sys) { int run = -1; int min_start = 65537; int max_end = -1; int basic_code = 0; int i; unsigned char *p; struct load_info info[1]; membuf_clear(mem); membuf_append(mem, NULL, 65536); p = membuf_get(mem); for (i = 0; i < filec; ++i) { info->basic_txt_start = basic_txt_start; load_located(filev[i], p, info); run = info->run; if(run != -1 && runp != NULL) { LOG(LOG_DEBUG, ("Propagating found run address $%04X.\n", info->run)); *runp = info->run; } /* do we expect any basic file? */ if(basic_txt_start >= 0) { if(info->basic_var_start >= 0) { basic_code = 1; if(basic_var_startp != NULL) { *basic_var_startp = info->basic_var_start; } if(runp != NULL && run == -1) { /* only if we didn't get run address from load_located * (run is not -1 if we did) */ int stub_len; run = find_sys(p + basic_txt_start, sys_token, &stub_len); *runp = run; if (trim_sys && basic_txt_start == info->start && min_start >= info->start) { if (run >= info->start && run < info->start + stub_len) { /* the run address points into the sys stub, trim up to it but no further */ info->start = run; } else { /* trim the sys stub*/ info->start += stub_len; } } } } } if (info->start < min_start) { min_start = info->start; } if (info->end > max_end) { max_end = info->end; } } if(basic_txt_start >= 0 && !basic_code && run == -1) { /* no program loaded to the basic start */ LOG(LOG_ERROR, ("\nError: nothing loaded at the start of basic " "text address ($%04X).\n", basic_txt_start)); exit(1); } /* if we have a basic code loaded and we are doing a proper basic start * (the caller don't expect a sys address so runp is NULL */ if(basic_code && runp == NULL) { int valuepos = basic_txt_start - 1; /* the byte immediatley preceeding the basic start must be 0 * for basic to function properly. */ if(min_start > valuepos) { /* It not covered by the files to crunch. Since the * default fill value is 0 we don't need to set it but we * need to include that location in the crunch as well. */ min_start = valuepos; } else { int value = p[valuepos]; /* it has been covered by at least one file. Let's check * if it is zero. */ if(value != 0) { /* Hm, its not, danger Will Robinson! */ LOG(LOG_WARNING, ("Warning, basic will probably not work since the value of" " the location \npreceeding the basic start ($%04X)" " is not 0 but %d.\n", valuepos, value)); } } } /* move memory to beginning of buffer */ membuf_truncate(mem, max_end); membuf_trim(mem, min_start); return min_start; }