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