1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2026-01-20 20:21:09 +00:00

Starts arg parsing. Cleans & refactors.

- Moves all arg parsing & tests to parseargs.rs
- Moves conversion tables to conversion_tables.rs
- Adds ebcdic_lcase and _ucase tables
- Refactors options: This **Breaks Write for Output**
This commit is contained in:
Tyler 2021-04-06 20:44:37 -07:00
parent 4996308753
commit 5c8c7efe68
6 changed files with 578 additions and 308 deletions

View file

@ -0,0 +1,139 @@
// Conversion tables are just lookup tables.
// eg. The ASCII->EBCDIC table stores the EBCDIC code at the index
// obtained by treating the ASCII representation as a number.
pub type ConversionTable = [u8; 256];
pub const ASCII_TO_EBCDIC: ConversionTable = [
0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d,
0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0x5f, 0x07,
0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x6a, 0x9b, 0x9c, 0x9d, 0x9e,
0x9f, 0xa0, 0xaa, 0xab, 0xac, 0x4a, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xa1, 0xbe, 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb,
0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
pub const ASCII_TO_IBM: ConversionTable = [
0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x5f, 0x6d,
0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07,
0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
0x9f, 0xa0, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb,
0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
pub const EBCDIC_TO_ASCII: ConversionTable = [
0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f, 0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x9d, 0x85, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x0a, 0x17, 0x1b, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,
0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a,
0x20, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xd5, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
0x26, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x7e,
0x2d, 0x2f, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xcb, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
0xc3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
0xca, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x5e, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
0xd1, 0xe5, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0xd2, 0xd3, 0xd4, 0x5b, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x5d, 0xe6, 0xe7,
0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed,
0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
0x5c, 0x9f, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
pub const ASCII_LCASE_TO_UCASE: ConversionTable = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
pub const ASCII_UCASE_TO_LCASE: ConversionTable = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
pub const EBCDIC_LCASE_TO_UCASE: ConversionTable = [
0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d,
0x79, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xc0, 0x4f, 0xd0, 0x5f, 0x07,
0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x6a, 0x9b, 0x9c, 0x9d, 0x9e,
0x9f, 0xa0, 0xaa, 0xab, 0xac, 0x4a, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xa1, 0xbe, 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb,
0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
pub const EBCDIC_UCASE_TO_LCASE: ConversionTable = [
0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
0x7c, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d,
0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0x5f, 0x07,
0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x6a, 0x9b, 0x9c, 0x9d, 0x9e,
0x9f, 0xa0, 0xaa, 0xab, 0xac, 0x4a, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xa1, 0xbe, 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb,
0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];

View file

@ -13,7 +13,11 @@ extern crate uucore;
#[cfg(test)]
mod test_dd_internal;
mod ddargs;
mod parseargs;
mod conversion_tables;
use conversion_tables::*;
use parseargs::*;
use std::error::Error;
use std::fs::File;
@ -24,117 +28,14 @@ use std::sync::mpsc;
use std::thread;
use getopts;
const NAME: &str = "dd";
const SUMMARY: &str = "convert and copy a file";
const LONG_HELP: &str = "TODO: This is where the long help string for dd goes!";
const SYNTAX: &str = "dd [OPERAND]...\ndd OPTION";
const SUMMARY: &str = "convert, and optionally copy, a file";
const LONG_HELP: &str = "";
const RTN_SUCCESS: i32 = 0;
const RTN_FAILURE: i32 = 1;
// ----- Conversion -----
//
// Conversion tables are just lookup tables.
// eg. The ASCII->EBCDIC table stores the EBCDIC code at the index
// obtained by treating the ASCII representation as a number.
type ConversionTable = [u8; 256];
const ASCII_TO_EBCDIC: ConversionTable = [
0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d,
0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0x5f, 0x07,
0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x6a, 0x9b, 0x9c, 0x9d, 0x9e,
0x9f, 0xa0, 0xaa, 0xab, 0xac, 0x4a, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xa1, 0xbe, 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb,
0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
const ASCII_TO_IBM: ConversionTable = [
0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x5f, 0x6d,
0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07,
0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b,
0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
0x9f, 0xa0, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb,
0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
const EBCDIC_TO_ASCII: ConversionTable = [
0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f, 0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x9d, 0x85, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x0a, 0x17, 0x1b, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,
0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a,
0x20, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xd5, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
0x26, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x7e,
0x2d, 0x2f, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xcb, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
0xc3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
0xca, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x5e, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
0xd1, 0xe5, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0xd2, 0xd3, 0xd4, 0x5b, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x5d, 0xe6, 0xe7,
0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed,
0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
0x5c, 0x9f, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
const LCASE_TO_UCASE: ConversionTable = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
const UCASE_TO_LCASE: ConversionTable = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
// ----- Types -----
// ----- Datatypes -----
enum SrcStat
{
Read(usize),
@ -161,7 +62,6 @@ struct Input<R: Read>
{
src: R,
ibs: usize,
output_progress: bool,
}
impl<R: Read> Read for Input<R>
@ -176,14 +76,12 @@ impl Input<io::Stdin>
{
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
{
let ibs: usize = ddargs::parse_ibs(matches)?;
let output_progress = ddargs::parse_progress_level(matches)?;
let ibs: usize = parseargs::parse_ibs(matches)?;
Ok(
Input {
src: io::stdin(),
ibs,
output_progress,
}
)
@ -194,15 +92,13 @@ impl Input<File>
{
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
{
let ibs: usize = ddargs::parse_ibs(matches)?;
let output_progress = ddargs::parse_progress_level(matches)?;
let ibs: usize = parseargs::parse_ibs(matches)?;
if let Some(fname) = matches.opt_str("if")
{
Ok(Input {
src: File::open(fname)?,
ibs,
output_progress,
})
}
else
@ -243,20 +139,17 @@ struct Output<W: Write>
{
dst: W,
obs: usize,
conv_table: Option<ConversionTable>,
}
impl Output<io::Stdout> {
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
{
let obs: usize = ddargs::parse_obs(matches)?;
let conv_table = ddargs::parse_conv_table(matches)?;
let obs: usize = parseargs::parse_obs(matches)?;
Ok(
Output {
dst: io::stdout(),
obs,
conv_table,
}
)
}
@ -265,15 +158,13 @@ impl Output<io::Stdout> {
impl Output<File> {
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
{
let obs: usize = ddargs::parse_obs(matches)?;
let conv_table = ddargs::parse_conv_table(matches)?;
let obs: usize = parseargs::parse_obs(matches)?;
if let Some(fname) = matches.opt_str("if")
{
Ok(Output {
dst: File::open(fname)?,
obs,
conv_table,
})
}
else
@ -310,6 +201,33 @@ impl<W: Write> Write for Output<W>
}
}
struct Options
{
conv: Option<ConversionOptions>,
status_level: StatusLevel,
// ...
}
struct ConversionOptions
{
table: Option<ConversionTable>,
block: bool,
unblock: bool,
lcase: bool,
ucase: bool,
sparse: bool,
swab: bool,
sync: bool,
}
#[derive(PartialEq)]
enum StatusLevel
{
Progress,
Noxfer,
None,
}
fn gen_prog_updater(rx: mpsc::Receiver<usize>) -> impl Fn() -> ()
{
move || {
@ -333,10 +251,12 @@ fn gen_prog_updater(rx: mpsc::Receiver<usize>) -> impl Fn() -> ()
}
}
fn dd<R: Read, W: Write>(mut i: Input<R>, mut o: Output<W>) -> Result<(usize, usize), Box<dyn Error>>
fn dd<R: Read, W: Write>(mut i: Input<R>, mut o: Output<W>, opts: Options) -> Result<(usize, usize), Box<dyn Error>>
{
let prog_tx = if i.output_progress {
let prog_tx = if opts.status_level == StatusLevel::Progress
{
let (prog_tx, prog_rx) = mpsc::channel();
thread::spawn(gen_prog_updater(prog_rx));
Some(prog_tx)
@ -364,7 +284,9 @@ fn dd<R: Read, W: Write>(mut i: Input<R>, mut o: Output<W>) -> Result<(usize, us
};
let w_len = o.write(&buf[..r_len])?;
o.flush()?;
// TODO: Some flag (sync?) controls this behaviour
// o.flush()?;
bytes_out += w_len;
@ -377,6 +299,44 @@ fn dd<R: Read, W: Write>(mut i: Input<R>, mut o: Output<W>) -> Result<(usize, us
Ok((bytes_in, bytes_out))
}
#[macro_export]
macro_rules! build_app (
() =>
{
app!(SYNTAX, SUMMARY, LONG_HELP)
.optopt(
"",
"if",
"The input file",
"FILE"
)
.optopt(
"",
"ibs",
"read up to BYTES bytes at a time (default: 512)",
"BYTES"
)
.optopt(
"",
"of",
"The output file",
"FILE"
)
.optopt(
"",
"obs",
"write BYTES bytes at a time (default: 512)",
"BYTES"
)
.optopt(
"",
"conv",
"One or more conversion options as a comma-serparated list",
"OPT[,OPT]..."
)
}
);
fn append_dashes_if_not_present(mut acc: Vec<String>, s: &String) -> Vec<String>
{
if Some("--") == s.get(0..=1) {
@ -393,43 +353,10 @@ pub fn uumain(args: impl uucore::Args) -> i32
.iter()
.fold(Vec::new(), append_dashes_if_not_present);
let syntax = format!(
"{0} [OPERAND]...\n{0} OPTION",
NAME
);
let matches = build_app!().parse(dashed_args);
let matches = app!(&syntax, SUMMARY, LONG_HELP)
.optopt(
"",
"if",
"The input file",
"FILE"
)
.optopt(
"",
"ibs",
"read up to BYTES bytes at a time (default: 512)",
"BYTES"
)
.optopt(
"",
"of",
"The output file",
"FILE"
)
.optopt(
"",
"obs",
"write BYTES bytes at a time (default: 512)",
"BYTES"
)
.optopt(
"",
"conv",
"One or more conversion options as a comma-serparated list",
"OPT[,OPT]..."
)
.parse(dashed_args);
let opts = parse_options(&matches)
.expect("TODO: Return correct error code");
let result = match (matches.opt_present("if"), matches.opt_present("of"))
{
@ -440,7 +367,7 @@ pub fn uumain(args: impl uucore::Args) -> i32
let o = Output::<File>::new(&matches)
.expect("TODO: Return correct error code");
dd(i, o)
dd(i, o, opts)
},
(true, false) =>
{
@ -449,7 +376,7 @@ pub fn uumain(args: impl uucore::Args) -> i32
let o = Output::<io::Stdout>::new(&matches)
.expect("TODO: Return correct error code");
dd(i, o)
dd(i, o, opts)
},
(false, true) =>
{
@ -458,7 +385,7 @@ pub fn uumain(args: impl uucore::Args) -> i32
let o = Output::<File>::new(&matches)
.expect("TODO: Return correct error code");
dd(i, o)
dd(i, o, opts)
},
(false, false) =>
{
@ -467,7 +394,7 @@ pub fn uumain(args: impl uucore::Args) -> i32
let o = Output::<io::Stdout>::new(&matches)
.expect("TODO: Return correct error code");
dd(i, o)
dd(i, o, opts)
},
};

View file

@ -1,8 +1,11 @@
use super::*;
use crate::conversion_tables::*;
#[derive(Debug)]
enum ParseError
{
ConvFlagNoMatch(String),
MultiplierString(String),
MultiplierStringWouldOverflow(String),
}
@ -16,6 +19,52 @@ impl std::fmt::Display for ParseError
impl Error for ParseError {}
enum ConvFlag
{
Table(ConversionTable),
Block,
Unblock,
UCase,
LCase,
Sparse,
Swab,
Sync,
}
impl std::str::FromStr for ConvFlag
{
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err>
{
match s
{
"ascii" =>
Ok(Self::Table(EBCDIC_TO_ASCII)),
"ebcdic" =>
Ok(Self::Table(ASCII_TO_EBCDIC)),
"ibm" =>
Ok(Self::Table(ASCII_TO_IBM)),
"block" =>
Ok(Self::Block),
"unblock" =>
Ok(Self::Unblock),
"lcase" =>
Ok(Self::LCase),
"ucase" =>
Ok(Self::UCase),
"sparse" =>
Ok(Self::Sparse),
"swab" =>
Ok(Self::Swab),
"sync" =>
Ok(Self::Sync),
_ =>
Err(ParseError::ConvFlagNoMatch(String::from(s)))
}
}
}
fn parse_multiplier<'a>(s: &'a str) -> Result<usize, Box<dyn Error>>
{
let s = s.trim();
@ -114,17 +163,13 @@ pub fn parse_progress_level(matches: &getopts::Matches) -> Result<bool, Box<dyn
pub fn parse_obs(matches: &getopts::Matches) -> Result<usize, Box<dyn Error>>
{
if let Some(str_with_prefixes) = matches.opt_str("bs")
if let Some(mixed_str) = matches.opt_str("bs")
{
// TODO: Parse a string containing the number with potential k, kB, kiB, ... multiplier
// possibly implemented elsewhere, but probably not in exactly the dd style
panic!()
parse_bytes_with_opt_multiplier(mixed_str)
}
else if let Some(str_with_prefixes) = matches.opt_str("obs")
else if let Some(mixed_str) = matches.opt_str("obs")
{
// TODO: Parse a string containing the number with potential k, kB, kiB, ... multiplier
// possibly implemented elsewhere, but probably not in exactly the dd style
panic!()
parse_bytes_with_opt_multiplier(mixed_str)
}
else
{
@ -132,19 +177,105 @@ pub fn parse_obs(matches: &getopts::Matches) -> Result<usize, Box<dyn Error>>
}
}
pub fn parse_conv_table(matches: &getopts::Matches) -> Result<Option<ConversionTable>, Box<dyn Error>>
/// Parse the options and flags that control the way
/// the file(s) is(are) copied and converted
pub fn parse_options(matches: &getopts::Matches) -> Result<Options, Box<dyn Error>>
{
// TODO: Complete this stub fn
Ok(None)
panic!()
}
/// Parse Conversion Options that control how the file is converted
pub fn parse_conv_options(matches: &getopts::Matches) -> Result<ConversionOptions, Box<dyn Error>>
{
let flags = parse_conv_opts(matches)?;
let mut table = None;
let mut block = false;
let mut unblock = false;
let mut ucase = false;
let mut lcase = false;
let mut sparse = false;
let mut swab = false;
let mut sync = false;
for flag in flags
{
match flag
{
ConvFlag::Table(ct) =>
{
table = Some(ct);
},
ConvFlag::Block =>
{
block = true;
},
ConvFlag::Unblock =>
{
unblock = true;
},
ConvFlag::UCase =>
{
ucase = true;
},
ConvFlag::LCase =>
{
lcase = true;
},
ConvFlag::Sparse =>
{
sparse = true;
},
ConvFlag::Swab =>
{
swab = true;
},
ConvFlag::Sync =>
{
sync = true;
},
}
}
Ok(ConversionOptions
{
table,
block,
unblock,
ucase,
lcase,
sparse,
swab,
sync,
})
}
fn parse_conv_opts(matches: &getopts::Matches) -> Result<Vec<ConvFlag>, Box<dyn Error>>
{
let mut flags = Vec::new();
if let Some(comma_str) = matches.opt_str("conv")
{
for s in comma_str.split(",")
{
let flag = s.parse()?;
flags.push(flag);
}
}
Ok(flags)
}
#[cfg(test)]
mod test {
use super::*;
macro_rules! test_byte_parser (
( $test_name:ident, $bs_str:expr, $bs:expr ) =>
{
#[allow(non_snake_case)]
#[test]
fn $test_name()
{
@ -167,9 +298,30 @@ mod test {
}
#[test]
fn test_conv_options_parser()
fn test_conv_parser_ibm_conv_table()
{
panic!()
let args = vec![
String::from("ketchup"),
String::from("mustard"),
String::from("--conv=ibm"),
String::from("relish"),
];
let matches = build_app!().parse(args);
assert!(matches.opt_present("conv"));
if let Some(table) = parse_conv_opts(&matches).unwrap()
{
for (s, t) in ASCII_TO_IBM.iter().zip(table.iter())
{
assert_eq!(s, t)
}
}
else
{
panic!()
}
}
test_byte_parser!(
@ -293,11 +445,31 @@ mod test {
#[test]
#[should_panic]
#[allow(non_snake_case)]
fn test_KB_multiplier_error()
{
// KB is not valid (kB, K, and KiB are)
let bs_str = String::from("2000 KB");
parse_bytes_with_opt_multiplier(bs_str).unwrap();
}
#[test]
#[should_panic]
fn test_overflow_panic()
{
let bs_str = format!("{} KiB", usize::MAX);
parse_bytes_with_opt_multiplier(bs_str).unwrap();
}
#[test]
#[should_panic]
fn test_neg_panic()
{
let bs_str = format!("{} KiB", -1);
parse_bytes_with_opt_multiplier(bs_str).unwrap();
}
}

View file

@ -3,13 +3,88 @@ use super::*;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs;
use md5::{ Md5, Digest, };
use hex_literal::hex;
// use md5::{ Md5, Digest, };
// use hex_literal::hex;
// use tempfile::tempfile;
// TODO: (Maybe) Use tempfiles in the tests.
macro_rules! make_hash_test (
( $test_id:ident, $test_name:expr, $src:expr, $exp:expr ) =>
//macro_rules! make_hash_test (
// ( $test_id:ident, $test_name:expr, $src:expr, $exp:expr ) =>
// {
// #[test]
// fn $test_id()
// {
// let tmp_fname = format!("./test-resources/FAILED-{}.test", $test_name);
//
// let i = Input {
// src: $src,
// ibs: 256,
// output_progress: false,
// };
//
// let o = Output {
// dst: File::create(&tmp_fname).unwrap(),
// obs: 1024,
// conv_table: None,
// };
//
// dd(i,o).unwrap();
//
// let res = {
// let res = File::open(&tmp_fname).unwrap();
// let res = BufReader::new(res);
//
// let mut h = Md5::new();
// for b in res.bytes()
// {
// h.update([b.unwrap()]);
// }
//
// h.finalize()
// };
//
// assert_eq!(hex!($exp), res[..]);
//
// fs::remove_file(&tmp_fname).unwrap();
// }
// };
// ( $test_id:ident, $test_name:expr, $i:expr, $o:expr, $exp:expr ) =>
// {
// #[test]
// fn $test_id()
// {
// let tmp_fname = format!("./test-resources/FAILED-{}.test", $test_name);
//
// let o = Output {
// dst: File::create(&tmp_fname).unwrap(),
// obs: $o.obs,
// };
//
// dd($i,o).unwrap();
//
// let res = {
// let res = File::open(&tmp_fname).unwrap();
// let res = BufReader::new(res);
//
// let mut h = Md5::new();
// for b in res.bytes()
// {
// h.update([b.unwrap()]);
// }
//
// h.finalize()
// };
//
// assert_eq!(hex!($exp), res[..]);
//
// fs::remove_file(&tmp_fname).unwrap();
// }
// };
//);
macro_rules! make_spec_test (
( $test_id:ident, $test_name:expr, $src:expr, $spec:expr ) =>
{
#[test]
fn $test_id()
@ -18,37 +93,45 @@ macro_rules! make_hash_test (
let i = Input {
src: $src,
ibs: 256,
output_progress: false,
ibs: 512,
};
let o = Output {
dst: File::create(&tmp_fname).unwrap(),
obs: 1024,
conv_table: None,
obs: 512,
};
dd(i,o).unwrap();
let res = {
let res = File::open(&tmp_fname).unwrap();
let res = BufReader::new(res);
let mut h = Md5::new();
for b in res.bytes()
{
h.update([b.unwrap()]);
}
h.finalize()
let opts = Options {
conv: Some(ConversionOptions {
table: None,
block: false,
unblock: false,
lcase: false,
ucase: false,
sparse: false,
swab: false,
sync: false,
}),
status_level: None,
};
assert_eq!(hex!($exp), res[..]);
dd($i,o,opts).unwrap();
let res = File::open(&tmp_fname).unwrap();
let res = BufReader::new(res);
let spec = BufReader::new($spec);
for (b_res, b_spec) in res.bytes().zip(spec.bytes())
{
assert_eq!(b_res.unwrap(),
b_spec.unwrap());
}
fs::remove_file(&tmp_fname).unwrap();
}
};
( $test_id:ident, $test_name:expr, $i:expr, $o:expr, $exp:expr ) =>
( $test_id:ident, $test_name:expr, $i:expr, $o:expr, $conv:expr, $spec:expr ) =>
{
#[test]
fn $test_id()
@ -58,46 +141,23 @@ macro_rules! make_hash_test (
let o = Output {
dst: File::create(&tmp_fname).unwrap(),
obs: $o.obs,
conv_table: $o.conv_table,
};
dd($i,o).unwrap();
let res = {
let res = File::open(&tmp_fname).unwrap();
let res = BufReader::new(res);
let mut h = Md5::new();
for b in res.bytes()
{
h.update([b.unwrap()]);
}
h.finalize()
let opts = Options {
conv: Some(ConversionOptions {
table: $conv,
block: false,
unblock: false,
lcase: false,
ucase: false,
sparse: false,
swab: false,
sync: false,
}),
status_level: None,
};
assert_eq!(hex!($exp), res[..]);
fs::remove_file(&tmp_fname).unwrap();
}
};
);
macro_rules! make_spec_test (
( $test_id:ident, $test_name:expr, $i:expr, $o:expr, $spec:expr ) =>
{
#[test]
fn $test_id()
{
let tmp_fname = format!("./test-resources/FAILED-{}.test", $test_name);
let o = Output {
dst: File::create(&tmp_fname).unwrap(),
obs: $o.obs,
conv_table: $o.conv_table,
};
dd($i,o).unwrap();
dd($i,o,opts).unwrap();
let res = File::open(&tmp_fname).unwrap();
let res = BufReader::new(res);
@ -115,39 +175,32 @@ macro_rules! make_spec_test (
};
);
make_hash_test!(
empty_file_test,
"stdio-empty-file",
io::empty(),
"d41d8cd98f00b204e9800998ecf8427e"
);
make_hash_test!(
make_spec_test!(
zeros_4k_test,
"zeros-4k",
File::open("./test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test").unwrap(),
"620f0b67a91f7f74151bc5be745b7110"
File::open("./test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test").unwrap()
);
make_hash_test!(
make_spec_test!(
ones_4k_test,
"ones-4k",
File::open("./test-resources/ones-6ae59e64850377ee5470c854761551ea.test").unwrap(),
"6ae59e64850377ee5470c854761551ea"
File::open("./test-resources/ones-6ae59e64850377ee5470c854761551ea.test").unwrap()
);
make_hash_test!(
make_spec_test!(
deadbeef_32k_test,
"deadbeef-32k",
File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap(),
"18d99661a1de1fc9af21b0ec2cd67ba3"
File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap()
);
make_hash_test!(
make_spec_test!(
random_73k_test,
"random-73k",
File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(),
"5828891cb1230748e146f34223bbd3b5"
File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap()
);
make_spec_test!(
@ -156,13 +209,12 @@ make_spec_test!(
Input {
src: File::open("./test-resources/seq-byte-values-b632a992d3aed5d8d1a59cc5a5a455ba.test").unwrap(),
ibs: 512,
output_progress: false,
},
Output {
dst: Vec::new(), // unused!
obs: 512,
conv_table: Some(ASCII_TO_EBCDIC),
},
Some(ASCII_TO_EBCDIC),
File::open("./test-resources/gnudd-conv-atoe-seq-byte-values.spec").unwrap()
);
@ -172,13 +224,12 @@ make_spec_test!(
Input {
src: File::open("./test-resources/seq-byte-values-b632a992d3aed5d8d1a59cc5a5a455ba.test").unwrap(),
ibs: 512,
output_progress: false,
},
Output {
dst: Vec::new(), // unused!
obs: 512,
conv_table: Some(EBCDIC_TO_ASCII),
},
Some(EBCDIC_TO_ASCII),
File::open("./test-resources/gnudd-conv-etoa-seq-byte-values.spec").unwrap()
);
@ -188,13 +239,12 @@ make_spec_test!(
Input {
src: File::open("./test-resources/seq-byte-values-b632a992d3aed5d8d1a59cc5a5a455ba.test").unwrap(),
ibs: 512,
output_progress: false,
},
Output {
dst: Vec::new(), // unused!
obs: 512,
conv_table: Some(ASCII_TO_IBM),
},
Some(ASCII_TO_IBM),
File::open("./test-resources/gnudd-conv-atoibm-seq-byte-values.spec").unwrap()
);
@ -204,13 +254,12 @@ make_spec_test!(
Input {
src: File::open("./test-resources/lcase-ascii.test").unwrap(),
ibs: 512,
output_progress: false,
},
Output {
dst: Vec::new(), // unused!
obs: 512,
conv_table: Some(LCASE_TO_UCASE),
},
Some(LCASE_TO_UCASE),
File::open("./test-resources/ucase-ascii.test").unwrap()
);
@ -220,13 +269,12 @@ make_spec_test!(
Input {
src: File::open("./test-resources/ucase-ascii.test").unwrap(),
ibs: 512,
output_progress: false,
},
Output {
dst: Vec::new(), // unused!
obs: 512,
conv_table: Some(UCASE_TO_LCASE),
},
Some(UCASE_TO_LCASE),
File::open("./test-resources/lcase-ascii.test").unwrap()
);
@ -240,16 +288,28 @@ fn all_valid_ascii_ebcdic_ascii_roundtrip_conv_test()
let i = Input {
src: File::open("./test-resources/all-valid-ascii-chars-37eff01866ba3f538421b30b7cbefcac.test").unwrap(),
ibs: 256,
output_progress: false,
};
let o = Output {
dst: File::create(&tmp_fname_ae).unwrap(),
obs: 1024,
conv_table: Some(ASCII_TO_EBCDIC),
};
dd(i,o).unwrap();
let opts = Options {
conv: Some(ConversionOptions {
table: Some(ASCII_TO_EBCDIC),
block: false,
unblock: false,
lcase: false,
ucase: false,
sparse: false,
swab: false,
sync: false,
}),
status_level: None,
};
dd(i,o,opts).unwrap();
// EBCDIC->ASCII
let test_name = "all-valid-ebcdic-to-ascii";
@ -258,16 +318,28 @@ fn all_valid_ascii_ebcdic_ascii_roundtrip_conv_test()
let i = Input {
src: File::open(&tmp_fname_ae).unwrap(),
ibs: 256,
output_progress: false,
};
let o = Output {
dst: File::create(&tmp_fname_ea).unwrap(),
obs: 1024,
conv_table: Some(EBCDIC_TO_ASCII),
};
dd(i,o).unwrap();
let opts = Options {
conv: Some(ConversionOptions {
table: Some(ASCII_TO_EBCDIC),
block: false,
unblock: false,
lcase: false,
ucase: false,
sparse: false,
swab: false,
sync: false,
}),
status_level: None,
};
dd(i,o,opts).unwrap();
let res = {
let res = File::open(&tmp_fname_ea).unwrap();
@ -287,43 +359,3 @@ fn all_valid_ascii_ebcdic_ascii_roundtrip_conv_test()
fs::remove_file(&tmp_fname_ae).unwrap();
fs::remove_file(&tmp_fname_ea).unwrap();
}
// #[test]
// fn copy_zerofile_from_args()
// {
// let spec = File::open("./test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test").unwrap();
// let tmp_fname = format!("./test-resources/{}", "zeros-from-args.test");
//
// let args = vec![
// String::from("if=./test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test"),
// String::from(&tmp_fname),
// ];
// let args = Args { args };
//
// uumain(args);
//
// let res = File::open(&tmp_fname).unwrap();
// let res = BufReader::new(res);
//
// let spec = BufReader::new(spec);
//
// for (b_res, b_spec) in res.bytes().zip(spec.bytes())
// {
// assert_eq!(b_res.unwrap(),
// b_spec.unwrap());
// }
//
// fs::remove_file(&tmp_fname).unwrap();
// }
//use rand::prelude::*;
//#[test]
//fn make_test_data()
//{
// let mut f = File::create("./test-resources/random-walk-through-the-ascii-ranged-forest.test").unwrap();
// // let mut rng = rand::thread_rng();
// for _ in 0..65536 {
// f.write(&[c]).unwrap();
// }
//}