1 //
2 // srecord - manipulate eprom load files
3 // Copyright (C) 1998-2014 Peter Miller
4 // Copyright (C) 2014 Scott Finneran
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU Lesser General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or (at
9 // your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 //
19
20 #include <iostream>
21
22 #include <srecord/arglex/tool.h>
23 #include <srecord/input/file.h>
24
25
arglex_tool(int argc,char ** argv)26 srecord::arglex_tool::arglex_tool(int argc, char **argv) :
27 arglex(argc, argv),
28 stdin_used(false),
29 stdout_used(false),
30 issue_sequence_warnings(-1),
31 redundant_bytes(srecord::defcon_warning),
32 contradictory_bytes(srecord::defcon_fatal_error)
33 {
34 static const table_ty table[] =
35 {
36 // sort using "!LC_ALL=C sort -f"
37 { "(", token_paren_begin, },
38 { ")", token_paren_end, },
39 { "+", token_union, },
40 { "-A430", token_a430, },
41 { "-Absolute_Object_Module_Format", token_aomf, },
42 { "-Adler_16_Big_Endian", token_adler16_be, },
43 { "-Adler_16_Little_Endian", token_adler16_le, },
44 { "-Adler_32_Big_Endian", token_adler32_be, },
45 { "-Adler_32_Little_Endian", token_adler32_le, },
46 { "-Adler_Checksum_16_Big_Endian", token_adler16_be, },
47 { "-Adler_Checksum_32_big_Endian", token_adler32_be, },
48 { "-AND", token_and, },
49 { "-Ascii_Hexadecimal", token_ascii_hex, },
50 { "-Ascii_Space_Hexadecimal", token_ascii_hex, },
51 { "-ASseMbler", token_assembler, },
52 { "-Atmel_Generic", token_atmel_generic_le, },
53 { "-Atmel_Generic_Big_Endian", token_atmel_generic_be, },
54 { "-Atmel_Generic_Little_Endian", token_atmel_generic_le, },
55 { "-AUGment", token_crc16_augment },
56 { "-BAsic", token_basic_data, },
57 { "-BIG", token_big, },
58 { "-BINary", token_binary, },
59 { "-Bit_REVerse", token_bitrev },
60 { "-BROken", token_crc16_broken, },
61 { "-Byte_Swap", token_byte_swap, },
62 { "-B_Record", token_brecord, },
63 { "-Checksum_Adler_16_Big_Endian", token_adler16_be, },
64 { "-Checksum_Adler_16_Little_Endian", token_adler16_le, },
65 { "-Checksum_Adler_32_Big_Endian", token_adler32_be, },
66 { "-Checksum_Adler_32_Little_Endian", token_adler32_le, },
67 { "-Checksum_BitNot_Big_Endian", token_checksum_be_bitnot, },
68 { "-Checksum_BitNot_Little_Endian", token_checksum_le_bitnot, },
69 { "-Checksum_Fletchers_16_Little_Endian", token_fletcher16_le, },
70 { "-Checksum_Fletchers_32_Little_Endian", token_fletcher32_le, },
71 { "-Checksum_Negative_Big_Endian", token_checksum_be_negative, },
72 { "-Checksum_Negative_Little_Endian", token_checksum_le_negative, },
73 { "-Checksum_Positive_Big_Endian", token_checksum_be_positive, },
74 { "-Checksum_Positive_Little_Endian", token_checksum_le_positive, },
75 { "-CL430", token_cl430, },
76 { "-COE", token_xilinx_coefficient_file },
77 { "-Comite_Consultatif_International_Telephonique_et_Telegraphique",
78 token_crc16_ccitt,},
79 { "-CONSTant", token_constant, },
80 { "-CONSTant_Big_Endian", token_constant_be, },
81 { "-CONSTant_Little_Endian", token_constant_le, },
82 { "-Contradictory_Bytes", token_contradictory_bytes },
83 { "-COsmac", token_cosmac, },
84 { "-CRop", token_crop, },
85 { "-Cyclic_Redundancy_Check_16_Big_Endian", token_crc16_be, },
86 { "-Cyclic_Redundancy_Check_16_Little_Endian", token_crc16_le,},
87 { "-Cyclic_Redundancy_Check_16_XMODEM", token_crc16_xmodem,},
88 { "-Cyclic_Redundancy_Check_32_Big_Endian", token_crc32_be, },
89 { "-Cyclic_Redundancy_Check_32_Little_Endian", token_crc32_le,},
90 { "-C_Array", token_c_array, },
91 { "-C_COMpressed", token_c_compressed, },
92 { "-DECimal_STyle", token_style_hexadecimal_not, },
93 { "-Dec_Binary", token_dec_binary, },
94 { "-DIFference", token_minus, },
95 { "-Disable_Sequence_Warnings", token_sequence_warnings_disable, },
96 { "-Dot_STyle", token_style_dot, },
97 { "-EEPROM", token_eeprom, },
98 { "-Elektor_Monitor52", token_emon52, },
99 { "-Enable_Sequence_Warnings", token_sequence_warnings_enable, },
100 { "-Exclude", token_exclude, },
101 { "-Exclusive_Length", token_exclusive_length, },
102 { "-Exclusive_Length_Big_Endian", token_exclusive_length_be, },
103 { "-Exclusive_Length_Little_Endian", token_exclusive_length_le, },
104 { "-Exclusive_MAximum", token_exclusive_maximum, },
105 { "-Exclusive_MAximum_Big_Endian", token_exclusive_maximum_be, },
106 { "-Exclusive_MAximum_Little_Endian", token_exclusive_maximum_le, },
107 { "-Exclusive_MInimum", token_exclusive_minimum, },
108 { "-Exclusive_MInimum_Big_Endian",token_exclusive_minimum_be, },
109 { "-Exclusive_MInimum_Little_Endian", token_exclusive_minimum_le, },
110 { "-FAIrchild", token_fairchild, },
111 { "-Fast_Load", token_fast_load, },
112 { "-Fill", token_fill, },
113 { "-Fletchers_16_Big_Endian", token_fletcher16_be, },
114 { "-Fletchers_16_Little_Endian", token_fletcher16_le, },
115 { "-Fletchers_32_Big_Endian", token_fletcher32_be, },
116 { "-Fletchers_32_Little_Endian", token_fletcher32_le, },
117 { "-Fletchers_Checksum_16_Big_Endian", token_fletcher16_be, },
118 { "-Fletchers_Checksum_32_Big_Endian", token_fletcher32_be, },
119 { "-Formatted_Binary", token_formatted_binary, },
120 { "-FORTH", token_forth, },
121 { "-Four_Packed_Code", token_four_packed_code, },
122 { "-GENerate", token_generator },
123 { "-GENerator", token_generator },
124 { "-Gnu_CRypt", token_gcrypt }, // undocumented
125 { "-GUess", token_guess, },
126 { "-HAVal", token_haval, },
127 { "-HEXadecimal_Dump", token_hexdump, },
128 { "-HEXadecimal_STyle", token_style_hexadecimal, },
129 { "-IGnore_Checksums", token_ignore_checksums, },
130 { "-INCLude", token_include, },
131 { "-Integrated_Device_Technology", token_idt, },
132 { "-Intel", token_intel, },
133 { "-INtel_HeXadecimal_16", token_intel16, },
134 { "-International_Telecommunication_Union", token_crc16_ccitt,},
135 { "-INTERSection", token_intersection, },
136 { "-Lattice_Memory_Initialization_Format",
137 token_lattice_memory_initialization_format },
138 { "-Least_To_Most", token_crc16_least_to_most },
139 { "-Length", token_length, },
140 { "-Length_Big_Endian", token_length_be, },
141 { "-Length_Little_Endian", token_length_le, },
142 { "-LOGisim", token_logisim },
143 { "-MAximum-Address", token_maximum_address, },
144 { "-MAximum_Big_Endian", token_maximum_be, },
145 { "-MAximum_Little_Endian", token_maximum_le, },
146 { "-MEM", token_lattice_memory_initialization_format },
147 { "-Memory_Initialization_File", token_memory_initialization_file },
148 { "-Message_Digest_2", token_md2 },
149 { "-Message_Digest_5", token_md5 },
150 { "-MInimum-Address", token_minimum_address, },
151 { "-MInimum_Big_Endian",token_minimum_be, },
152 { "-MInimum_Little_Endian", token_minimum_le, },
153 { "-MINUs", token_minus, },
154 { "-Mips_Flash_Big_Endian", token_mips_flash_be, },
155 { "-Mips_Flash_Little_Endian", token_mips_flash_le, },
156 { "-Most_To_Least", token_crc16_most_to_least },
157 { "-MOS_Technologies", token_mos_tech, },
158 { "-Motorola", token_motorola, },
159 { "-MsBin", token_msbin, },
160 { "-MULTiple", token_multiple, },
161 { "-Needham_Hexadecimal", token_needham_hex, },
162 { "-NOT", token_not, },
163 { "-Not_AUGment", token_crc16_augment_not },
164 { "-Not_CONSTant", token_constant_not, },
165 { "-Not_INCLude", token_include_not, },
166 { "-OFfset", token_offset, },
167 { "-Ohio_Scientific", token_ohio_scientific, },
168 { "-Ohio_Scientific65v", token_ohio_scientific, },
169 { "-OR", token_or, },
170 { "-Output", token_output, },
171 { "-Output_Words", token_output_word, },
172 { "-OVer", token_over, },
173 { "-POLYnomial", token_polynomial },
174 { "-PREfix", token_prefix, },
175 { "-POSTfix", token_postfix, },
176 { "-Prom_Pogrammer_Binary", token_ppb, },
177 { "-Prom_Pogrammer_heXadecimal", token_ppx, },
178 { "-RAM", token_ram, },
179 { "-RANDom", token_random, },
180 { "-Random_Fill", token_random_fill, },
181 { "-RAnge_PADding", token_range_padding, },
182 { "-RAw", token_binary, },
183 { "-Redundant_Bytes", token_redundant_bytes },
184 { "-REPeat_Data", token_repeat_data, },
185 { "-REPeat_String", token_repeat_string, },
186 { "-Ripe_Message_Digest_160", token_rmd160 },
187 { "-Round", token_round_nearest, },
188 { "-Round_Down", token_round_down, },
189 { "-Round_Nearest", token_round_nearest, },
190 { "-Round_Off", token_round_nearest, },
191 { "-Round_Up", token_round_up, },
192 { "-Section_STyle", token_style_section, },
193 { "-Secure_Hash_Algorithm_1", token_sha1 },
194 { "-Secure_Hash_Algorithm_224", token_sha224 },
195 { "-Secure_Hash_Algorithm_256", token_sha256 },
196 { "-Secure_Hash_Algorithm_384", token_sha384 },
197 { "-Secure_Hash_Algorithm_512", token_sha512 },
198 { "-Signed_BiNary", token_stewie, },
199 { "-SIGnetics", token_signetics, },
200 { "-SPAsm_Big_Endian", token_spasm_be, },
201 { "-SPAsm_Little_Endian", token_spasm_le, },
202 { "-SPAsm", token_spasm_be, }, // put after others
203 { "-SPEctrum", token_spectrum, },
204 { "-SPlit", token_split, },
205 { "-Stag_Binary", token_ppb, },
206 { "-Stag_Hexadecimal", token_ppx, },
207 { "-STewie", token_stewie, },
208 { "-STM32_Big_Endian", token_stm32_crc_be },
209 { "-STM32_Little_Endian", token_stm32_crc_le },
210 { "-STM32", token_stm32_crc_le }, // put after others
211 { "-SUBtract", token_minus, },
212 { "-S_record", token_motorola, },
213 { "-Tektronix", token_tektronix, },
214 { "-Tektronix_EXtended", token_tektronix_extended, },
215 { "-Texas_Instruments_Tagged", token_ti_tagged, },
216 { "-Texas_Instruments_Tagged_16", token_ti_tagged_16, },
217 { "-Texas_Instruments_TeXT", token_ti_txt, },
218 { "-TIGer", token_tiger },
219 { "-TRS80", token_trs80 },
220 { "-UNIon", token_union, },
221 { "-Un_Fill", token_unfill, },
222 { "-Un_SPlit", token_unsplit, },
223 { "-VHdl", token_vhdl, },
224 { "-VMem", token_vmem, },
225 { "-WHIrlpool", token_whirlpool },
226 { "-WILson", token_wilson, },
227 { "-Within", token_within, },
228 { "-Xilinx_Coefficient_File", token_xilinx_coefficient_file },
229 { "-XOR", token_xor, },
230 { "-X_MODEM", token_crc16_xmodem, },
231 { "[", token_paren_begin, },
232 { "]", token_paren_end, },
233 { "{", token_paren_begin, },
234 { "}", token_paren_end, },
235
236 // The deprecated options go at the end of the table, so that
237 // the preferred name will always be earlier in the table.
238 { "-Checksum_Big_Endian", token_checksum_be_positive, },
239 { "-Checksum_Little_Endian", token_checksum_le_positive, },
240 { "-INtel_16", token_intel16, },
241 { "-MAximum", token_maximum_address, },
242 { "-MInimum", token_minimum_address, },
243
244 SRECORD_ARGLEX_END_MARKER
245 };
246
247 table_set(table);
248 deprecated_option("-Checksum_Big_Endian");
249 deprecated_option("-Checksum_Little_Endian");
250 deprecated_option("-INtel_16");
251 deprecated_option("-MAximum");
252 deprecated_option("-MInimum");
253 }
254
255
~arglex_tool()256 srecord::arglex_tool::~arglex_tool()
257 {
258 }
259
260
261 bool
can_get_number(void) const262 srecord::arglex_tool::can_get_number(void)
263 const
264 {
265 switch (token_cur())
266 {
267 case token_paren_begin:
268 case token_number:
269 case token_minimum_address:
270 case token_maximum_address:
271 case token_length:
272 return true;
273
274 default:
275 return false;
276 }
277 }
278
279
280 void
get_address(const char * name,unsigned long & address)281 srecord::arglex_tool::get_address(const char *name, unsigned long &address)
282 {
283 if (!can_get_number())
284 {
285 fatal_error("the %s filter requires an address", name);
286 // NOTREACHED
287 }
288 address = get_number("address");
289 }
290
291
292 void
get_address_and_nbytes(const char * name,unsigned long & address,int & nbytes)293 srecord::arglex_tool::get_address_and_nbytes(const char *name,
294 unsigned long &address, int &nbytes)
295 {
296 if (!can_get_number())
297 {
298 fatal_error("the %s filter requires an address and a byte count", name);
299 // NOTREACHED
300 }
301 address = get_number("address");
302 nbytes = 4;
303 if (can_get_number())
304 {
305 nbytes = get_number("byte count", 1, 8);
306 }
307 if ((long long)address + nbytes > (1LL << 32))
308 {
309 fatal_error
310 (
311 "the %s address (0x%8.8lX) and byte count (%d) may not span the "
312 "top of memory",
313 name,
314 address,
315 nbytes
316 );
317 // NOTREACHED
318 }
319 }
320
321
322 void
get_address_nbytes_width(const char * name,unsigned long & address,int & nbytes,int & width)323 srecord::arglex_tool::get_address_nbytes_width(const char *name,
324 unsigned long &address, int &nbytes, int &width)
325 {
326 address = get_number("address");
327 nbytes = 4;
328 width = 1;
329 if (can_get_number())
330 {
331 nbytes = get_number("byte count", 1, 8);
332 if (can_get_number())
333 {
334 width = get_number("width", 1, nbytes);
335 }
336 }
337 if ((long long)address + nbytes > (1LL << 32))
338 {
339 fatal_error
340 (
341 "the %s address (0x%8.8lX) and byte count (%d) may not span the "
342 "top of memory",
343 name,
344 address,
345 nbytes
346 );
347 // NOTREACHED
348 }
349 }
350
351
352 void
default_command_line_processing(void)353 srecord::arglex_tool::default_command_line_processing(void)
354 {
355 switch (token_cur())
356 {
357 default:
358 arglex::default_command_line_processing();
359 break;
360
361 case token_ignore_checksums:
362 input_file::ignore_all_checksums();
363 token_next();
364 break;
365
366 case token_sequence_warnings_enable:
367 issue_sequence_warnings = 1;
368 token_next();
369 break;
370
371 case token_sequence_warnings_disable:
372 issue_sequence_warnings = 0;
373 token_next();
374 break;
375
376 case token_multiple:
377 // This one is intentionally not documented.
378 // Use one of the -rb or -cb options.
379 redundant_bytes = defcon_ignore;
380 contradictory_bytes = defcon_ignore;
381 token_next();
382 break;
383
384 case token_redundant_bytes:
385 {
386 if (token_next() != token_string)
387 {
388 fatal_error
389 (
390 "the %s option requires a string argument",
391 token_name(token_redundant_bytes)
392 );
393 }
394 int x = defcon_from_text(value_string().c_str());
395 if (x < 0)
396 {
397 fatal_error
398 (
399 "the %s=%s option value is unknown",
400 token_name(token_redundant_bytes),
401 value_string().c_str()
402 );
403 }
404 redundant_bytes = (defcon_t)x;
405 token_next();
406 }
407 break;
408
409 case token_contradictory_bytes:
410 {
411 if (token_next() != token_string)
412 {
413 fatal_error
414 (
415 "the %s option requires a string argument",
416 token_name(token_contradictory_bytes)
417 );
418 }
419 int x = defcon_from_text(value_string().c_str());
420 if (x < 0)
421 {
422 fatal_error
423 (
424 "the %s=%s option value is unknown",
425 token_name(token_contradictory_bytes),
426 value_string().c_str()
427 );
428 }
429 contradictory_bytes = (defcon_t)x;
430 token_next();
431 }
432 break;
433 }
434 }
435
436
437 // vim: set ts=8 sw=4 et :
438