//
// srecord - The "srecord" program.
// Copyright (C) 2007 Peter Miller
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// .
//
#include
#include
#include
#include
#include
#include
srec_input_generator::~srec_input_generator()
{
}
srec_input_generator::srec_input_generator(const interval &a_range) :
range(a_range)
{
}
int
srec_input_generator::read(srec_record &result)
{
//
// If there is not data left to generate,
// signal end-of-file
//
if (range.empty())
return 0;
//
// Calculate the address range for this chunk of data. Use the
// biggest record size available.
//
unsigned long addr = range.get_lowest();
interval partial(addr, addr + srec_record::max_data_length);
partial *= range;
//
// Only supply the first sub-interval, if the generation range has
// holes in it.
//
partial.first_interval_only();
//
// Generate the data and build the result record.
//
result.set_type(srec_record::type_data);
result.set_address(addr);
result.set_length(1);
interval::data_t size = partial.get_highest() - addr;
for (interval::data_t j = 0; j < size; ++j)
{
result.set_data_extend(j, generate_data(addr + j));
}
//
// Reduce the amount of data left to be generated.
//
range -= partial;
//
// Report that another record is available.
//
return 1;
}
srec_input *
srec_input_generator::create(srec_arglex *cmdln)
{
interval range = cmdln->get_interval("--generate");
srec_input *result = 0;
switch (cmdln->token_cur())
{
case srec_arglex::token_constant:
{
cmdln->token_next();
int n = cmdln->get_number("--generate --constant");
result = new srec_input_generator_constant(range, n);
}
break;
case srec_arglex::token_random:
{
cmdln->token_next();
result = new srec_input_generator_random(range);
}
break;
case srec_arglex::token_repeat_data:
{
cmdln->token_next();
size_t length = 0;
size_t maxlen = 16;
unsigned char *data = new unsigned char [maxlen];
for (;;)
{
//
// Get the next byte value from the command line
// (there must be at least one).
//
long byte_value = cmdln->get_number("--repeat-data");
//
// Make sure there is room for the next byte in the data array
//
if (length >= maxlen)
{
size_t new_maxlen = maxlen * 2 + 16;
unsigned char *new_data = new unsigned char [new_maxlen];
memcpy(new_data, data, length);
delete [] data;
data = new_data;
maxlen = new_maxlen;
}
if (byte_value < 0 || byte_value > 255)
{
cmdln->fatal_error
(
"data byte %ld out of range [0..255]",
byte_value
);
}
//
// Stash this byte
//
data[length++] = byte_value;
//
// If there are no more numbers on the command line, we
// are done.
//
if (!cmdln->can_get_number())
break;
}
//
// Build our new input data source.
//
if (length == 1)
result = new srec_input_generator_constant(range, data[0]);
else
result = new srec_input_generator_repeat(range, data, length);
delete [] data;
}
break;
case srec_arglex::token_repeat_string:
{
cmdln->token_next();
string s = cmdln->get_string("--repeat-string");
size_t len = s.size();
switch (len)
{
case 0:
cmdln->fatal_error("--repeat-string value may not be empty");
// NOTREACHED
case 1:
result = new srec_input_generator_constant(range, s[0]);
break;
default:
result =
new srec_input_generator_repeat
(
range,
(unsigned char *)s.c_str(),
s.size()
);
break;
}
}
break;
default:
cmdln->fatal_error
(
"the --generate option needs to be followed by a generation "
"type (e.g. --constant)"
);
// NOTREACHED
}
return result;
}
void
srec_input_generator::disable_checksum_validation()
{
// Do nothing.
// None of the generators have checksums.
}