//
// srecord - manipulate eprom load files
// Copyright (C) 1998-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
using namespace std;
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
srec_input *
srec_arglex::get_input()
{
//
// determine the file name
//
std::string fn = "-";
switch (token_cur())
{
case token_paren_begin:
{
token_next();
srec_input *ifp = get_input();
if (token_cur() != token_paren_end)
{
fatal_error
(
"closing parenthesis expected before %s",
token_name(token_cur())
);
// NOTREACHED
}
token_next();
return ifp;
}
case token_generator:
// Don't need a file name,
// but do NOT discard this token, yet.
break;
case token_string:
fn = value_string();
token_next();
break;
case token_stdio:
token_next();
// fall through...
default:
if (stdin_used)
{
fatal_error
(
"the standard input may only be named once on the command line"
);
// NOTREACHED
}
stdin_used = true;
break;
}
//
// determine the file format
// and open the input file
//
srec_input *ifp;
switch (token_cur())
{
case token_motorola:
token_next();
// fall through...
default:
ifp = new srec_input_file_srecord(fn);
break;
case token_aomf:
token_next();
ifp = new srec_input_file_aomf(fn);
break;
case token_ascii_hex:
token_next();
ifp = new srec_input_file_ascii_hex(fn);
break;
case token_atmel_generic_be:
token_next();
ifp = new srec_input_file_atmel_generic(fn, true);
break;
case token_atmel_generic_le:
token_next();
ifp = new srec_input_file_atmel_generic(fn, false);
break;
case token_binary:
token_next();
ifp = new srec_input_file_binary(fn);
break;
case token_brecord:
token_next();
ifp = new srec_input_file_brecord(fn);
break;
case token_cosmac:
token_next();
ifp = new srec_input_file_cosmac(fn);
break;
case token_dec_binary:
token_next();
ifp = new srec_input_file_dec_binary(fn);
break;
case token_emon52:
token_next();
ifp = new srec_input_file_emon52(fn);
break;
case token_fairchild:
token_next();
ifp = new srec_input_file_fairchild(fn);
break;
case token_fast_load:
token_next();
ifp = new srec_input_file_fastload(fn);
break;
case token_formatted_binary:
token_next();
ifp = new srec_input_file_formatted_binary(fn);
break;
case token_four_packed_code:
token_next();
ifp = new srec_input_file_four_packed_code(fn);
break;
case token_generator:
token_next();
ifp = srec_input_generator::create(this);
break;
case token_guess:
token_next();
ifp = srec_input_file_guess(fn);
break;
case token_intel:
token_next();
ifp = new srec_input_file_intel(fn);
break;
case token_intel16:
token_next();
ifp = new srec_input_file_intel16(fn);
break;
case token_mos_tech:
token_next();
ifp = new srec_input_file_mos_tech(fn);
break;
case token_ohio_scientific:
token_next();
ifp = new srec_input_file_os65v(fn);
break;
case token_needham_hex:
token_next();
ifp = new srec_input_file_needham(fn);
break;
case token_signetics:
token_next();
ifp = new srec_input_file_signetics(fn);
break;
case token_spasm_be:
token_next();
ifp = new srec_input_file_spasm(fn, true);
break;
case token_spasm_le:
token_next();
ifp = new srec_input_file_spasm(fn, false);
break;
case token_spectrum:
token_next();
ifp = new srec_input_file_spectrum(fn);
break;
case token_stewie:
token_next();
ifp = new srec_input_file_stewie(fn);
break;
case token_tektronix:
token_next();
ifp = new srec_input_file_tektronix(fn);
break;
case token_tektronix_extended:
token_next();
ifp = new srec_input_file_tektronix_extended(fn);
break;
case token_ti_tagged:
token_next();
ifp = new srec_input_file_ti_tagged(fn);
break;
case token_ti_tagged_16:
token_next();
ifp = new srec_input_file_ti_tagged_16(fn);
break;
case token_ti_txt:
token_next();
ifp = new srec_input_file_ti_txt(fn);
break;
case token_vmem:
token_next();
ifp = new srec_input_file_vmem(fn);
break;
case token_wilson:
token_next();
ifp = new srec_input_file_wilson(fn);
break;
}
//
// Process any additional format-specfic command line options.
//
ifp->command_line(this);
//
// Ignore checksums if asked to.
//
if (token_cur() == token_ignore_checksums)
{
ifp->disable_checksum_validation();
token_next();
}
//
// warn about data record sequences, if asked to
//
if (issue_sequence_warnings != 0)
ifp = new srec_input_filter_sequence(ifp);
//
// apply any filters specified
//
for (;;)
{
switch (token_cur())
{
case token_byte_swap:
token_next();
ifp = new srec_input_filter_byte_swap(ifp);
break;
case token_not:
token_next();
ifp = new srec_input_filter_not(ifp);
break;
case token_crc16_be:
{
token_next();
unsigned long address;
get_address("-Big_Endian_CRC16", address);
ifp = new srec_input_filter_crc16(ifp, address, 0);
}
break;
case token_crc16_le:
{
token_next();
unsigned long address;
get_address("-Little_Endian_CRC16", address);
ifp = new srec_input_filter_crc16(ifp, address, 1);
}
break;
case token_crc32_be:
{
token_next();
unsigned long address;
get_address("-Big_Endian_CRC32", address);
ifp = new srec_input_filter_crc32(ifp, address, 0);
}
break;
case token_crc32_le:
{
token_next();
unsigned long address;
get_address("-Little_Endian_CRC32", address);
ifp = new srec_input_filter_crc32(ifp, address, 1);
}
break;
case token_crop:
token_next();
ifp = new srec_input_filter_crop(ifp, get_interval("-Crop"));
break;
case token_exclude:
token_next();
ifp = new srec_input_filter_crop(ifp, -get_interval("-Exclude"));
break;
case token_fill:
{
token_next();
int filler = get_number("--Fill", 0, 255);
interval range = get_interval("--Fill");
ifp = new srec_input_filter_fill(ifp, filler, range);
}
break;
case token_random_fill:
{
token_next();
interval range = get_interval("-Random_Fill");
ifp = new srec_input_filter_random_fill(ifp, range);
}
break;
case token_and:
{
token_next();
int filler = get_number("--and", 0, 255);
if (filler < 0 || filler >= 256)
{
fatal_error("-and value %d out of range (0..255)", filler);
// NOTREACHED
}
ifp = new srec_input_filter_and(ifp, filler);
}
break;
case token_xor:
{
token_next();
int filler = get_number("--xor", 0, 255);
ifp = new srec_input_filter_xor(ifp, filler);
}
break;
case token_or:
{
token_next();
int filler = get_number("--or value", 0, 255);
ifp = new srec_input_filter_or(ifp, filler);
}
break;
case token_length:
fatal_error("Use --big-endian-length or --little-endian-length");
// NOTREACHED
case token_length_be:
{
token_next();
unsigned long address;
int nbytes;
get_address_and_nbytes("-Big_Endian_Length", address, nbytes);
ifp = new srec_input_filter_length(ifp, address, nbytes, 0);
}
break;
case token_length_le:
{
token_next();
unsigned long address;
int nbytes;
get_address_and_nbytes
(
"-Little_Endian_Length",
address,
nbytes
);
ifp = new srec_input_filter_length(ifp, address, nbytes, 1);
}
break;
case token_maximum:
fatal_error("Use --big-endian-maximum or --little-endian-maximum");
// NOTREACHED
case token_maximum_be:
{
token_next();
unsigned long address;
int nbytes;
get_address_and_nbytes("-Big_Endian_MAximum", address, nbytes);
ifp = new srec_input_filter_maximum(ifp, address, nbytes, 0);
}
break;
case token_maximum_le:
{
token_next();
unsigned long address;
int nbytes;
get_address_and_nbytes
(
"-Little_Endian_MAximum",
address,
nbytes
);
ifp = new srec_input_filter_maximum(ifp, address, nbytes, 1);
}
break;
case token_minimum:
fatal_error("Use --big-endian-minimum or --little-endian-minimum");
// NOTREACHED
case token_minimum_be:
{
token_next();
unsigned long address;
int nbytes;
get_address_and_nbytes("-Big_Endian_MInimum", address, nbytes);
ifp = new srec_input_filter_minimum(ifp, address, nbytes, 0);
}
break;
case token_minimum_le:
{
token_next();
unsigned long address;
int nbytes;
get_address_and_nbytes
(
"-Little_Endian_MInimum",
address,
nbytes
);
ifp = new srec_input_filter_minimum(ifp, address, nbytes, 1);
}
break;
case token_checksum_be_bitnot:
{
token_next();
unsigned long address;
int nbytes, width;
get_address_nbytes_width
(
"-Big_Endian_Checksum_BitNot",
address,
nbytes,
width
);
ifp =
new srec_input_filter_checksum_bitnot
(
ifp,
address,
nbytes,
0,
width
);
}
break;
case token_checksum_le_bitnot:
{
token_next();
unsigned long address;
int nbytes, width;
get_address_nbytes_width
(
"-Little_Endian_Checksum_BitNot",
address,
nbytes,
width
);
ifp =
new srec_input_filter_checksum_bitnot
(
ifp,
address,
nbytes,
1,
width
);
}
break;
case token_checksum_be_negative:
{
token_next();
unsigned long address;
int nbytes, width;
get_address_nbytes_width
(
"-Big_Endian_Checksum_Negative",
address,
nbytes,
width
);
ifp =
new srec_input_filter_checksum_negative
(
ifp,
address,
nbytes,
0,
width
);
}
break;
case token_checksum_le_negative:
{
token_next();
unsigned long address;
int nbytes, width;
get_address_nbytes_width
(
"-Little_Endian_Checksum_Negative",
address,
nbytes,
width
);
ifp =
new srec_input_filter_checksum_negative
(
ifp,
address,
nbytes,
1,
width
);
}
break;
case token_checksum_be_positive:
{
token_next();
unsigned long address;
int nbytes, width;
get_address_nbytes_width
(
"-Big_Endian_Checksum_Positive",
address,
nbytes,
width
);
ifp =
new srec_input_filter_checksum_positive
(
ifp,
address,
nbytes,
0,
width
);
}
break;
case token_checksum_le_positive:
{
token_next();
unsigned long address;
int nbytes, width;
get_address_nbytes_width
(
"-Little_Endian_Checksum_Positive",
address,
nbytes,
width
);
ifp =
new srec_input_filter_checksum_positive
(
ifp,
address,
nbytes,
1,
width
);
}
break;
case token_offset:
{
token_next();
unsigned long amount = get_number("--offset");
ifp = new srec_input_filter_offset(ifp, amount);
}
break;
case token_split:
{
token_next();
int split_modulus = get_number("--split modulus");
if (split_modulus < 2)
{
fatal_error("the -split modulus must be two or more");
// NOTREACHED
}
int split_offset = 0;
if (can_get_number())
{
split_offset =
get_number("split offset", 0, split_modulus - 1);
}
int split_width = 1;
if (can_get_number())
{
split_width =
get_number("split width", 1, split_modulus - 1);
}
ifp =
new srec_input_filter_split
(
ifp,
split_modulus,
split_offset,
split_width
);
}
break;
case token_unfill:
{
token_next();
int fill_value = get_number("--unfill value", 0, 255);
int fill_minimum = 1;
if (can_get_number())
{
fill_minimum = get_number("--unfill minimum", 1, 16);
}
ifp =
new srec_input_filter_unfill(ifp, fill_value, fill_minimum);
}
break;
case token_unsplit:
{
token_next();
int split_modulus = get_number("--unsplit modulus");
if (split_modulus < 2)
{
fatal_error("the -unsplit modulus must be two or more");
// NOTREACHED
}
int split_offset = 0;
if (can_get_number())
{
split_offset =
get_number("--unsplit offset", 0, split_modulus - 1);
}
int split_width = 1;
if (can_get_number())
{
split_width =
get_number("--unsplit width", 1, split_modulus - 1);
}
ifp =
new srec_input_filter_unsplit
(
ifp,
split_modulus,
split_offset,
split_width
);
}
break;
default:
//
// return the input stream determined
//
return ifp;
}
//
// Process any filter-specific command line options.
//
ifp->command_line(this);
}
}