From 273ac2d9aaf6024a2f5db2a1029c22e56321b9b3 Mon Sep 17 00:00:00 2001 From: Packit Service Date: Apr 14 2021 22:14:55 +0000 Subject: Prepare for a new update Reverting patches so we can apply the latest update and changes can be seen in the spec file and sources. --- diff --git a/configure b/configure index 64c7bdc..23a0ccc 100755 --- a/configure +++ b/configure @@ -60046,7 +60046,7 @@ shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/lib64 /lib64 /usr/lib64" +sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no @@ -64013,7 +64013,7 @@ shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/lib64" +sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no diff --git a/doc/credentials/Makefile.am b/doc/credentials/Makefile.am index 2577885..ecdd57a 100644 --- a/doc/credentials/Makefile.am +++ b/doc/credentials/Makefile.am @@ -31,27 +31,3 @@ EXTRA_DIST += srp-passwd.txt srp-tpasswd.conf EXTRA_DIST += psk-passwd.txt -EXTRA_DIST += \ - dhparams/rfc2409-group-1-768.pem \ - dhparams/rfc2409-group-2-1024.pem \ - dhparams/rfc3526-group-14-2048.pem \ - dhparams/rfc3526-group-15-3072.pem \ - dhparams/rfc3526-group-16-4096.pem \ - dhparams/rfc3526-group-17-6144.pem \ - dhparams/rfc3526-group-18-8192.pem \ - dhparams/rfc3526-group-5-1536.pem \ - dhparams/rfc5054-1024.pem \ - dhparams/rfc5054-1536.pem \ - dhparams/rfc5054-2048.pem \ - dhparams/rfc5054-3072.pem \ - dhparams/rfc5054-4096.pem \ - dhparams/rfc5054-6144.pem \ - dhparams/rfc5054-8192.pem \ - dhparams/rfc5114-group-22-1024.pem \ - dhparams/rfc5114-group-23-2048.pem \ - dhparams/rfc5114-group-24-2048.pem \ - dhparams/rfc7919-ffdhe2048.pem \ - dhparams/rfc7919-ffdhe3072.pem \ - dhparams/rfc7919-ffdhe4096.pem \ - dhparams/rfc7919-ffdhe6144.pem \ - dhparams/rfc7919-ffdhe8192.pem diff --git a/doc/credentials/dhparams/rfc2409-group-1-768.pem b/doc/credentials/dhparams/rfc2409-group-1-768.pem deleted file mode 100644 index 33a6170..0000000 --- a/doc/credentials/dhparams/rfc2409-group-1-768.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN DH PARAMETERS----- -MGYCYQD//////////8kP2qIhaMI0xMZii4DcHNEpAk4IimfMdAILvqY7E5siUUoI -eY40BN3vlRmzzTpDGzArCm3yXxQ3T+E1bW1RwkXkhbV2Yl5+xvRMQummOjYg//// -//////8CAQI= ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc2409-group-2-1024.pem b/doc/credentials/dhparams/rfc2409-group-2-1024.pem deleted file mode 100644 index bbfb1bf..0000000 --- a/doc/credentials/dhparams/rfc2409-group-2-1024.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE -3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/ta -iZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc3526-group-14-2048.pem b/doc/credentials/dhparams/rfc3526-group-14-2048.pem deleted file mode 100644 index b150715..0000000 --- a/doc/credentials/dhparams/rfc3526-group-14-2048.pem +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg== ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc3526-group-15-3072.pem b/doc/credentials/dhparams/rfc3526-group-15-3072.pem deleted file mode 100644 index f27b778..0000000 --- a/doc/credentials/dhparams/rfc3526-group-15-3072.pem +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBiAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM -fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq -ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS -yv//////////AgEC ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc3526-group-16-4096.pem b/doc/credentials/dhparams/rfc3526-group-16-4096.pem deleted file mode 100644 index a734b90..0000000 --- a/doc/credentials/dhparams/rfc3526-group-16-4096.pem +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM -fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq -ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI -ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O -+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI -HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQI= ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc3526-group-17-6144.pem b/doc/credentials/dhparams/rfc3526-group-17-6144.pem deleted file mode 100644 index d8307bd..0000000 --- a/doc/credentials/dhparams/rfc3526-group-17-6144.pem +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIDCAKCAwEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM -fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq -ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI -ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O -+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI -HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG -3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU -7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId -A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha -xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/ -8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebcxA -JP//////////AgEC ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc3526-group-18-8192.pem b/doc/credentials/dhparams/rfc3526-group-18-8192.pem deleted file mode 100644 index af54dd6..0000000 --- a/doc/credentials/dhparams/rfc3526-group-18-8192.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIECAKCBAEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM -fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq -ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI -ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O -+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI -HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG -3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU -7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId -A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha -xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/ -8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebb4R -WXSjkm8S/uXkOHd8tqky34zYvsTQc7kxujvIMraNndMAdB+nv4r8R+0ldvaTa6Qk -ZjqrY5xa5PVoNCO0dCvxyXgjjxbL451lLeP9uL78hIrZIiIuBKQDfAcT61eoGiPw -xzRz/GRs6jBrS8vIhi+Dhd36nUt/osCH6HloMwPtW906Bis89bOieKZtKhP4P0T4 -Ld8xDuB0q2o2RZfomaAlXcFk8xzFCEaFHfmrSBld7X6hsdUQvX7nTXP682vDHs+i -aDWQRvTrh5+SQAlDi0gcbNeImgAu1e44K8kZDab8Am5HlVjkR1Z36aqeMFDidlaU -38gfVuiAuW5xYMmA3Zjt09///////////wIBAg== ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc3526-group-5-1536.pem b/doc/credentials/dhparams/rfc3526-group-5-1536.pem deleted file mode 100644 index 44df6de..0000000 --- a/doc/credentials/dhparams/rfc3526-group-5-1536.pem +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR -Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL -/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORbPcIAfLihY78FmNpINhxV05pp -Fj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaWbWcMNU5KvJgE8XRsCMojcyf/ -/////////wIBAg== ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc5054-1024.pem b/doc/credentials/dhparams/rfc5054-1024.pem deleted file mode 100644 index 33aed9f..0000000 --- a/doc/credentials/dhparams/rfc5054-1024.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIGHAoGBAO6vCrmts43WnDP4CvqPxehgcmGHdf88C56iMUycJWV21nTfdJbqgdM4 -O0gT1pLG4ODV2OJQuYvkjklcHWCJ2tFdx9e0YVTWts6O9K1psV1JglWbKXvPGIXF -KfVmZg5X7GjtvDwFcmzAL9TL9Jduqpr9UTj+g3ZDW5/GHS/A6wbjAgEC ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc5054-1536.pem b/doc/credentials/dhparams/rfc5054-1536.pem deleted file mode 100644 index dc2db6b..0000000 --- a/doc/credentials/dhparams/rfc5054-1536.pem +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIHHAoHBAJ3vPK+5OSd6sfEqhheke7vbpR30maxMgL7uqWFLGcxNX09fVW4ny95R -xqlL5GB6KRVYkDug0PhDgLZVu5oi6NzfAop87Gfw0IE0sci5eYkUm2CeC+O6tj1H -VIOB28Wx/HZOP0tT3Z2hFYv9PiucjPVu3wGVOTSWJ9sv1T0kt8SGZXcuQ31sf4zk -QnNK98y3roN8Jkrjqb64f4ov6bi1KS5aAh//XpFHnoznoowkQsbzFRgPk0maI03P -duP+0TX5uwIBAg== ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc5054-2048.pem b/doc/credentials/dhparams/rfc5054-2048.pem deleted file mode 100644 index 814e70c..0000000 --- a/doc/credentials/dhparams/rfc5054-2048.pem +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEArGvbQTJKmpvxZt5eE4lYL69ytmUZh+4H/DGSlD21YFCjcynLtKCZ -7YGT4HV3Z6E91SMSq0sDMQ3Nf0ip2gT9UOgIOWntt2ewz2CVF5oWOrNmGgX71fqq -6CkYqZYvC5O4Vfl5k+yXXuqoDXQK2/T/dHNZ0EHVwz6nHSgeRGsUdzvKl7Q6I/uA -Fna9IHpDbGSB8dK5B4cXRhpbnTLmiPh3SFRFI7UksNV9Xqd6J3XS7PoDLPvb9S+z -eGFgJ5AE5Xrmr4dOcwPOUymczAQce8MI2CpWmPOo0MOCca41+Onb+7aUtcgD2J96 -5DXeI21SX1R1m2XjcvzWjvIPpxEfnkr/cwIBAg== ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc5054-3072.pem b/doc/credentials/dhparams/rfc5054-3072.pem deleted file mode 100644 index d84b242..0000000 --- a/doc/credentials/dhparams/rfc5054-3072.pem +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBiAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM -fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq -ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS -yv//////////AgEF ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc5054-4096.pem b/doc/credentials/dhparams/rfc5054-4096.pem deleted file mode 100644 index 99ca445..0000000 --- a/doc/credentials/dhparams/rfc5054-4096.pem +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM -fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq -ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI -ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O -+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI -HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQU= ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc5054-6144.pem b/doc/credentials/dhparams/rfc5054-6144.pem deleted file mode 100644 index 97d8d21..0000000 --- a/doc/credentials/dhparams/rfc5054-6144.pem +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIDCAKCAwEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM -fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq -ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI -ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O -+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI -HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG -3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU -7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId -A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha -xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/ -8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebcxA -JP//////////AgEF ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc5054-8192.pem b/doc/credentials/dhparams/rfc5054-8192.pem deleted file mode 100644 index bb54575..0000000 --- a/doc/credentials/dhparams/rfc5054-8192.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIECAKCBAEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb -IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft -awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT -mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh -fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq -5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM -fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq -ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI -ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O -+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI -HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0AoSSNsP6tNJ8cCbB1NyyYCZG -3sl1HnY9uje9+P+UBq2eUw7l2zgvQTABrrBqU+2QJ9gxF5cnsIZaiRjaPtvrz5sU -7UTObLrO1Lsb238UR+bMJUszIFFRK9evQm+49AE3jNK/WYPKAcZLkuzwMuoV0XId -A/SC185udP721V5wL0aYDIK1qEAxkAscnlnnyX++x+jzI6l6fjbMiL4PHUW3/1ha -xUvUB7IrQVSqzI9tfr9I4dgUzF7SD4A34KeXFe7ym+MoBqHVi7fF2nb1UKo9ih+/ -8OsZzLGjE9Vc2lbJ7C7yljI4f+jXbjwEaAQ+j2Y/SGDuEr8tWwt0dNbmlPkebb4R -WXSjkm8S/uXkOHd8tqky34zYvsTQc7kxujvIMraNndMAdB+nv4r8R+0ldvaTa6Qk -ZjqrY5xa5PVoNCO0dCvxyXgjjxbL451lLeP9uL78hIrZIiIuBKQDfAcT61eoGiPw -xzRz/GRs6jBrS8vIhi+Dhd36nUt/osCH6HloMwPtW906Bis89bOieKZtKhP4P0T4 -Ld8xDuB0q2o2RZfomaAlXcFk8xzFCEaFHfmrSBld7X6hsdUQvX7nTXP682vDHs+i -aDWQRvTrh5+SQAlDi0gcbNeImgAu1e44K8kZDab8Am5HlVjkR1Z36aqeMFDidlaU -38gfVuiAuW5xYMmA3Zjt09///////////wIBEw== ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc5114-group-22-1024.pem b/doc/credentials/dhparams/rfc5114-group-22-1024.pem deleted file mode 100644 index 759afcb..0000000 --- a/doc/credentials/dhparams/rfc5114-group-22-1024.pem +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBCAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y -mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4 -+qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV -w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0 -sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR -jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5Q== ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc5114-group-23-2048.pem b/doc/credentials/dhparams/rfc5114-group-23-2048.pem deleted file mode 100644 index d4f360e..0000000 --- a/doc/credentials/dhparams/rfc5114-group-23-2048.pem +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIICCgKCAQEArRB+HpEjqdDWYPqnlVnFH6INZOVoO5/RtUsVl7YdCnXm+hQd+VpW -26+aPEB7od8V6z1oijCcGA4d5rhaEnSgpm0/gVKtasISkDfJ7e/aTfjZHo/vVbc5 -S3rVt9C2wSIHyfmNEe002/bGugssi7wnvmoA4KC5xJcIs7+KMXCRiDaBKGEwvImF -2xYC5xRBXZMwJ4Jzx94x79xzEPcSH9WgdBWYfZrcCkhtzfk6zEQyg4cxXXXhmMZB -pIDNhqG55YfovmDmnMkosrnFIXLkEwQumyPxCw4W55djybU9z0uoCinj+3PBa451 -uX7zY+L/ox9xz53lOE5xuBwKxN/+DBDmTwKCAQEArEAy708tmuOd8wtcj/2sUGze -vnuJmYyvdIZqCM/k/+OmgkpOELmm8N2SHwGnDEr6q3OddwDCn1LFfbF8YgqGUr5e -kAGo1mrXwXZpEBmZAkr00CcnWsE0i7inYtBSG8mK4kcVBCLqHtQJk51U2nRgzbX2 -xrJQcXy+8YDrNBGOmNEZUppF1vg0Vm4wJeMWozDvu3eobwwasVsFGuPUKMj4rLcK -gTcVC47rEOGD7dGZY93Z4mPkdwWJ72qiHn9fL/OBtTnM40CdE81Wavu0jWwBkYHh -vP6UswJp7f5y/ptqpL17Wg8ccc//TBnEGOH27AF5gbwIfypwZbOEuJDTGR8r+g== ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc5114-group-24-2048.pem b/doc/credentials/dhparams/rfc5114-group-24-2048.pem deleted file mode 100644 index dc02116..0000000 --- a/doc/credentials/dhparams/rfc5114-group-24-2048.pem +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIICCQKCAQEAh6jmHbS2Zjz/u9GcZRlZmYzu9ghmDdDyXSzu1ENeOwDgDfjx1hlX -1Pr330VhsqowFsPZETQJb6o79Cltgw6afCCeDGSXUXq9WoqdMGvPZ+2R+eZyW0dY -wCLgse9Cdb97bFv8EdRfkIi5QfVOseWbuLw5oL8SMH9cT9twxYGyP3a2Osrhyqa3 -kC1SUmc1SIoO8TxtmlG/pKs62DR3llJNjvahZ7WkGCXZZ+FE5RQFZCUcysuD5rSG -9rPKP3lxUGAmwLhX9omWKFbe1AEKvQvmIcOjlgpU5xDDdfJjddcBQQOktUMwwZiv -EmEW0iduEXFfaTh3+tfvCcrbCUrpHhoVlwKCAQA/syybcxNNCy53UGZg7b1ITKex -jyHvIFQH9Hk6GguhJRDbwVB3vkY//0/tSqwLtVW+OmwbDGtHsbw3c79+jG9ikBIo -+MKMuxilWuMTQQAKZQGW+THHelfy3fRj5ensFEt3feYqqrioYorDdtKC1u04ZOZ5 -gkKOvIMdFDSPby+Rk7UEWvJ2cWTh38lnwfs/LlWkvRv/6DucgNBSuYXRguoK2yo7 -cxPT/hTISEseBSWIubfSu9LfAWGZ7NBuFVfNCRWzNTu7ZODsN3/QKDcN+StSx4kU -KM3GfrYYS1I9HbJGwy9jB4SQ8A741kfRSNR5VFFeIyfP75jFgmZLTA9sxBZZ ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc7919-ffdhe2048.pem b/doc/credentials/dhparams/rfc7919-ffdhe2048.pem deleted file mode 100644 index 9b182b7..0000000 --- a/doc/credentials/dhparams/rfc7919-ffdhe2048.pem +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz -+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a -87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 -YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi -7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD -ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc7919-ffdhe3072.pem b/doc/credentials/dhparams/rfc7919-ffdhe3072.pem deleted file mode 100644 index fb31ccd..0000000 --- a/doc/credentials/dhparams/rfc7919-ffdhe3072.pem +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBiAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz -+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a -87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 -YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi -7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD -ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3 -7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32 -nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu -N///////////AgEC ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc7919-ffdhe4096.pem b/doc/credentials/dhparams/rfc7919-ffdhe4096.pem deleted file mode 100644 index ad9f68b..0000000 --- a/doc/credentials/dhparams/rfc7919-ffdhe4096.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz -+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a -87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 -YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi -7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD -ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3 -7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32 -nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e -8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx -iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K -zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI= ------END DH PARAMETERS----- - diff --git a/doc/credentials/dhparams/rfc7919-ffdhe6144.pem b/doc/credentials/dhparams/rfc7919-ffdhe6144.pem deleted file mode 100644 index d8239bb..0000000 --- a/doc/credentials/dhparams/rfc7919-ffdhe6144.pem +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIDCAKCAwEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz -+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a -87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 -YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi -7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD -ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3 -7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32 -nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e -8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx -iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K -zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eDdkCC/1ktkUDbHpOZ30sOFMq -OiO6RELK9T6mO7RUMpt2JMiRe91kscD9TLOOjDNMcBw6za0GV/zP7HGbH1w+TkYE -HziBR/tM/bR3pSRx96mpaRC4VTIu22NA2KAO8JI1BRHjCr7B//njom5/sp+MGDAj -w1h+ONoAd9m0dj5OS5Syu8GUxmUed8r5ku6qwCMqKBv2s6c5wSJhFoIK6NtYR6Z8 -vvnJCRtGLVOM1ysDdGrnf15iKSwxFWKoRlBdyC24VDOK5J9SNclbkReMzy3Vys70 -A+ydGBDGJysEWztx+dxrgNY/3UqOmtseaWKmlSbUMWHBpB1XDXk42tSkDjKc0OQO -Zf//////////AgEC ------END DH PARAMETERS----- diff --git a/doc/credentials/dhparams/rfc7919-ffdhe8192.pem b/doc/credentials/dhparams/rfc7919-ffdhe8192.pem deleted file mode 100644 index 4484cf8..0000000 --- a/doc/credentials/dhparams/rfc7919-ffdhe8192.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIECAKCBAEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz -+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a -87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 -YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi -7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD -ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3 -7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32 -nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e -8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx -iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K -zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eDdkCC/1ktkUDbHpOZ30sOFMq -OiO6RELK9T6mO7RUMpt2JMiRe91kscD9TLOOjDNMcBw6za0GV/zP7HGbH1w+TkYE -HziBR/tM/bR3pSRx96mpaRC4VTIu22NA2KAO8JI1BRHjCr7B//njom5/sp+MGDAj -w1h+ONoAd9m0dj5OS5Syu8GUxmUed8r5ku6qwCMqKBv2s6c5wSJhFoIK6NtYR6Z8 -vvnJCRtGLVOM1ysDdGrnf15iKSwxFWKoRlBdyC24VDOK5J9SNclbkReMzy3Vys70 -A+ydGBDGJysEWztx+dxrgNY/3UqOmtseaWKmlSbUMWHBpB1XDXk42tSkDjKcz/Rq -qjatAEz2AMg4HkJaMdlRrmT9sj/OyVCdQ2h/62nt0cxeC4zDvfZLEO+GtjFCo6uI -KVVbL3R8kyZlyywPHMAb1wIpOIg50q8F5FRQSseLdYKCKEbAujXDX1xZFgzARv2C -UVQfxoychrAiu3CZh2pGDnRRqKkxCXA/7hwhfmw4JuUsUappHg5CPPyZ6eMWUMEh -e2JIFs2tmpX51bgBlIjZwKCh/jB1pXfiMYP4HUo/L6RXHvyM4LqKT+i2hV3+crCm -bt7S+6v75Yow+vq+HF1xqH4vdB74wf6G/qa7/eUwZ38Nl9EdSfeoRD0IIuUGqfRh -TgEeKpSDj/iM1oyLt8XGQkz//////////wIBAg== ------END DH PARAMETERS----- diff --git a/guile/src/Makefile.in b/guile/src/Makefile.in index 9284aee..0920fd8 100644 --- a/guile/src/Makefile.in +++ b/guile/src/Makefile.in @@ -1646,7 +1646,7 @@ guileextension_LTLIBRARIES = guile-gnutls-v-2.la # Use '-module' to build a "dlopenable module", in Libtool terms. # Use '-undefined' to placate Libtool on Windows; see # . -guile_gnutls_v_2_la_LDFLAGS = -module -no-undefined -Wl,-z,lazy +guile_gnutls_v_2_la_LDFLAGS = -module -no-undefined # Linking against GnuTLS. GNUTLS_CORE_LIBS = $(top_builddir)/lib/libgnutls.la diff --git a/lib/accelerated/x86/aes-xts-x86-aesni.c b/lib/accelerated/x86/aes-xts-x86-aesni.c index b904cbf..3371d08 100644 --- a/lib/accelerated/x86/aes-xts-x86-aesni.c +++ b/lib/accelerated/x86/aes-xts-x86-aesni.c @@ -72,7 +72,7 @@ x86_aes_xts_cipher_setkey(void *_ctx, const void *userkey, size_t keysize) /* Check key block according to FIPS-140-2 IG A.9 */ if (_gnutls_fips_mode_enabled()){ - if (gnutls_memcmp(key, key + (keysize / 2), keysize / 2) == 0) { + if (safe_memcmp(key, key + (keysize / 2), keysize / 2) == 0) { _gnutls_switch_lib_state(LIB_STATE_ERROR); return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } diff --git a/lib/accelerated/x86/coff/aes-ssse3-x86.s b/lib/accelerated/x86/coff/aes-ssse3-x86.s index 1dced3b..c58ea23 100644 --- a/lib/accelerated/x86/coff/aes-ssse3-x86.s +++ b/lib/accelerated/x86/coff/aes-ssse3-x86.s @@ -71,7 +71,6 @@ .def __vpaes_preheat; .scl 3; .type 32; .endef .align 16 __vpaes_preheat: -.byte 243,15,30,251 addl (%esp),%ebp movdqa -48(%ebp),%xmm7 movdqa -16(%ebp),%xmm6 @@ -79,7 +78,6 @@ __vpaes_preheat: .def __vpaes_encrypt_core; .scl 3; .type 32; .endef .align 16 __vpaes_encrypt_core: -.byte 243,15,30,251 movl $16,%ecx movl 240(%edx),%eax movdqa %xmm6,%xmm1 @@ -156,7 +154,6 @@ __vpaes_encrypt_core: .def __vpaes_decrypt_core; .scl 3; .type 32; .endef .align 16 __vpaes_decrypt_core: -.byte 243,15,30,251 leal 608(%ebp),%ebx movl 240(%edx),%eax movdqa %xmm6,%xmm1 @@ -244,7 +241,6 @@ __vpaes_decrypt_core: .def __vpaes_schedule_core; .scl 3; .type 32; .endef .align 16 __vpaes_schedule_core: -.byte 243,15,30,251 addl (%esp),%ebp movdqu (%esi),%xmm0 movdqa 320(%ebp),%xmm2 @@ -338,7 +334,6 @@ __vpaes_schedule_core: .def __vpaes_schedule_192_smear; .scl 3; .type 32; .endef .align 16 __vpaes_schedule_192_smear: -.byte 243,15,30,251 pshufd $128,%xmm6,%xmm1 pshufd $254,%xmm7,%xmm0 pxor %xmm1,%xmm6 @@ -350,7 +345,6 @@ __vpaes_schedule_192_smear: .def __vpaes_schedule_round; .scl 3; .type 32; .endef .align 16 __vpaes_schedule_round: -.byte 243,15,30,251 movdqa 8(%esp),%xmm2 pxor %xmm1,%xmm1 .byte 102,15,58,15,202,15 @@ -399,7 +393,6 @@ __vpaes_schedule_round: .def __vpaes_schedule_transform; .scl 3; .type 32; .endef .align 16 __vpaes_schedule_transform: -.byte 243,15,30,251 movdqa -16(%ebp),%xmm2 movdqa %xmm2,%xmm1 pandn %xmm0,%xmm1 @@ -414,7 +407,6 @@ __vpaes_schedule_transform: .def __vpaes_schedule_mangle; .scl 3; .type 32; .endef .align 16 __vpaes_schedule_mangle: -.byte 243,15,30,251 movdqa %xmm0,%xmm4 movdqa 128(%ebp),%xmm5 testl %edi,%edi @@ -475,7 +467,6 @@ __vpaes_schedule_mangle: .align 16 _vpaes_set_encrypt_key: .L_vpaes_set_encrypt_key_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -508,7 +499,6 @@ _vpaes_set_encrypt_key: .align 16 _vpaes_set_decrypt_key: .L_vpaes_set_decrypt_key_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -546,7 +536,6 @@ _vpaes_set_decrypt_key: .align 16 _vpaes_encrypt: .L_vpaes_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -575,7 +564,6 @@ _vpaes_encrypt: .align 16 _vpaes_decrypt: .L_vpaes_decrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -604,7 +592,6 @@ _vpaes_decrypt: .align 16 _vpaes_cbc_encrypt: .L_vpaes_cbc_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi diff --git a/lib/accelerated/x86/coff/aes-ssse3-x86_64.s b/lib/accelerated/x86/coff/aes-ssse3-x86_64.s index f3fee56..150c992 100644 --- a/lib/accelerated/x86/coff/aes-ssse3-x86_64.s +++ b/lib/accelerated/x86/coff/aes-ssse3-x86_64.s @@ -643,7 +643,6 @@ vpaes_set_encrypt_key: movq %r8,%rdx -.byte 243,15,30,250 leaq -184(%rsp),%rsp movaps %xmm6,16(%rsp) movaps %xmm7,32(%rsp) @@ -696,7 +695,6 @@ vpaes_set_decrypt_key: movq %r8,%rdx -.byte 243,15,30,250 leaq -184(%rsp),%rsp movaps %xmm6,16(%rsp) movaps %xmm7,32(%rsp) @@ -754,7 +752,6 @@ vpaes_encrypt: movq %r8,%rdx -.byte 243,15,30,250 leaq -184(%rsp),%rsp movaps %xmm6,16(%rsp) movaps %xmm7,32(%rsp) @@ -802,7 +799,6 @@ vpaes_decrypt: movq %r8,%rdx -.byte 243,15,30,250 leaq -184(%rsp),%rsp movaps %xmm6,16(%rsp) movaps %xmm7,32(%rsp) @@ -852,7 +848,6 @@ vpaes_cbc_encrypt: movq 48(%rsp),%r9 -.byte 243,15,30,250 xchgq %rcx,%rdx subq $16,%rcx jc .Lcbc_abort diff --git a/lib/accelerated/x86/coff/aesni-gcm-x86_64.s b/lib/accelerated/x86/coff/aesni-gcm-x86_64.s index 5784e4b..7988004 100644 --- a/lib/accelerated/x86/coff/aesni-gcm-x86_64.s +++ b/lib/accelerated/x86/coff/aesni-gcm-x86_64.s @@ -42,8 +42,6 @@ .def _aesni_ctr32_ghash_6x; .scl 3; .type 32; .endef .p2align 5 _aesni_ctr32_ghash_6x: - -.byte 243,15,30,250 vmovdqu 32(%r11),%xmm2 subq $6,%rdx vpxor %xmm4,%xmm4,%xmm4 @@ -352,7 +350,6 @@ _aesni_ctr32_ghash_6x: .byte 0xf3,0xc3 - .globl aesni_gcm_decrypt .def aesni_gcm_decrypt; .scl 2; .type 32; .endef .p2align 5 @@ -369,7 +366,6 @@ aesni_gcm_decrypt: movq 48(%rsp),%r9 -.byte 243,15,30,250 xorq %r10,%r10 cmpq $0x60,%rdx jb .Lgcm_dec_abort @@ -494,8 +490,6 @@ aesni_gcm_decrypt: .def _aesni_ctr32_6x; .scl 3; .type 32; .endef .p2align 5 _aesni_ctr32_6x: - -.byte 243,15,30,250 vmovdqu 0-128(%rcx),%xmm4 vmovdqu 32(%r11),%xmm2 leaq -1(%rbp),%r13 @@ -584,7 +578,6 @@ _aesni_ctr32_6x: jmp .Loop_ctr32 - .globl aesni_gcm_encrypt .def aesni_gcm_encrypt; .scl 2; .type 32; .endef .p2align 5 @@ -601,7 +594,6 @@ aesni_gcm_encrypt: movq 48(%rsp),%r9 -.byte 243,15,30,250 xorq %r10,%r10 cmpq $288,%rdx jb .Lgcm_enc_abort diff --git a/lib/accelerated/x86/coff/aesni-x86.s b/lib/accelerated/x86/coff/aesni-x86.s index 577dc4a..c6aa1a1 100644 --- a/lib/accelerated/x86/coff/aesni-x86.s +++ b/lib/accelerated/x86/coff/aesni-x86.s @@ -43,7 +43,6 @@ .align 16 _aesni_encrypt: .L_aesni_encrypt_begin: -.byte 243,15,30,251 movl 4(%esp),%eax movl 12(%esp),%edx movups (%eax),%xmm2 @@ -70,7 +69,6 @@ _aesni_encrypt: .align 16 _aesni_decrypt: .L_aesni_decrypt_begin: -.byte 243,15,30,251 movl 4(%esp),%eax movl 12(%esp),%edx movups (%eax),%xmm2 @@ -95,7 +93,6 @@ _aesni_decrypt: .def __aesni_encrypt2; .scl 3; .type 32; .endef .align 16 __aesni_encrypt2: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -122,7 +119,6 @@ __aesni_encrypt2: .def __aesni_decrypt2; .scl 3; .type 32; .endef .align 16 __aesni_decrypt2: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -149,7 +145,6 @@ __aesni_decrypt2: .def __aesni_encrypt3; .scl 3; .type 32; .endef .align 16 __aesni_encrypt3: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -181,7 +176,6 @@ __aesni_encrypt3: .def __aesni_decrypt3; .scl 3; .type 32; .endef .align 16 __aesni_decrypt3: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -213,7 +207,6 @@ __aesni_decrypt3: .def __aesni_encrypt4; .scl 3; .type 32; .endef .align 16 __aesni_encrypt4: -.byte 243,15,30,251 movups (%edx),%xmm0 movups 16(%edx),%xmm1 shll $4,%ecx @@ -251,7 +244,6 @@ __aesni_encrypt4: .def __aesni_decrypt4; .scl 3; .type 32; .endef .align 16 __aesni_decrypt4: -.byte 243,15,30,251 movups (%edx),%xmm0 movups 16(%edx),%xmm1 shll $4,%ecx @@ -289,7 +281,6 @@ __aesni_decrypt4: .def __aesni_encrypt6; .scl 3; .type 32; .endef .align 16 __aesni_encrypt6: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -343,7 +334,6 @@ __aesni_encrypt6: .def __aesni_decrypt6; .scl 3; .type 32; .endef .align 16 __aesni_decrypt6: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -399,7 +389,6 @@ __aesni_decrypt6: .align 16 _aesni_ecb_encrypt: .L_aesni_ecb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -634,7 +623,6 @@ _aesni_ecb_encrypt: .align 16 _aesni_ccm64_encrypt_blocks: .L_aesni_ccm64_encrypt_blocks_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -722,7 +710,6 @@ _aesni_ccm64_encrypt_blocks: .align 16 _aesni_ccm64_decrypt_blocks: .L_aesni_ccm64_decrypt_blocks_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -845,7 +832,6 @@ _aesni_ccm64_decrypt_blocks: .align 16 _aesni_ctr32_encrypt_blocks: .L_aesni_ctr32_encrypt_blocks_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -1083,7 +1069,6 @@ _aesni_ctr32_encrypt_blocks: .align 16 _aesni_xts_encrypt: .L_aesni_xts_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -1443,7 +1428,6 @@ _aesni_xts_encrypt: .align 16 _aesni_xts_decrypt: .L_aesni_xts_decrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -1833,7 +1817,6 @@ _aesni_xts_decrypt: .align 16 _aesni_ocb_encrypt: .L_aesni_ocb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -2228,7 +2211,6 @@ _aesni_ocb_encrypt: .align 16 _aesni_ocb_decrypt: .L_aesni_ocb_decrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -2623,7 +2605,6 @@ _aesni_ocb_decrypt: .align 16 _aesni_cbc_encrypt: .L_aesni_cbc_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -2882,7 +2863,6 @@ _aesni_cbc_encrypt: .def __aesni_set_encrypt_key; .scl 3; .type 32; .endef .align 16 __aesni_set_encrypt_key: -.byte 243,15,30,251 pushl %ebp pushl %ebx testl %eax,%eax @@ -3217,7 +3197,6 @@ __aesni_set_encrypt_key: .align 16 _aesni_set_encrypt_key: .L_aesni_set_encrypt_key_begin: -.byte 243,15,30,251 movl 4(%esp),%eax movl 8(%esp),%ecx movl 12(%esp),%edx @@ -3228,7 +3207,6 @@ _aesni_set_encrypt_key: .align 16 _aesni_set_decrypt_key: .L_aesni_set_decrypt_key_begin: -.byte 243,15,30,251 movl 4(%esp),%eax movl 8(%esp),%ecx movl 12(%esp),%edx diff --git a/lib/accelerated/x86/coff/aesni-x86_64.s b/lib/accelerated/x86/coff/aesni-x86_64.s index ba29929..4e8de06 100644 --- a/lib/accelerated/x86/coff/aesni-x86_64.s +++ b/lib/accelerated/x86/coff/aesni-x86_64.s @@ -44,7 +44,6 @@ .p2align 4 aesni_encrypt: -.byte 243,15,30,250 movups (%rcx),%xmm2 movl 240(%r8),%eax movups (%r8),%xmm0 @@ -71,7 +70,6 @@ aesni_encrypt: .p2align 4 aesni_decrypt: -.byte 243,15,30,250 movups (%rcx),%xmm2 movl 240(%r8),%eax movups (%r8),%xmm0 @@ -569,7 +567,6 @@ aesni_ecb_encrypt: movq 40(%rsp),%r8 -.byte 243,15,30,250 leaq -88(%rsp),%rsp movaps %xmm6,(%rsp) movaps %xmm7,16(%rsp) @@ -942,8 +939,6 @@ aesni_ccm64_encrypt_blocks: movq 40(%rsp),%r8 movq 48(%rsp),%r9 - -.byte 243,15,30,250 leaq -88(%rsp),%rsp movaps %xmm6,(%rsp) movaps %xmm7,16(%rsp) @@ -1020,7 +1015,6 @@ aesni_ccm64_encrypt_blocks: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_aesni_ccm64_encrypt_blocks: .globl aesni_ccm64_decrypt_blocks .def aesni_ccm64_decrypt_blocks; .scl 2; .type 32; .endef @@ -1037,8 +1031,6 @@ aesni_ccm64_decrypt_blocks: movq 40(%rsp),%r8 movq 48(%rsp),%r9 - -.byte 243,15,30,250 leaq -88(%rsp),%rsp movaps %xmm6,(%rsp) movaps %xmm7,16(%rsp) @@ -1149,7 +1141,6 @@ aesni_ccm64_decrypt_blocks: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_aesni_ccm64_decrypt_blocks: .globl aesni_ctr32_encrypt_blocks .def aesni_ctr32_encrypt_blocks; .scl 2; .type 32; .endef @@ -1166,7 +1157,6 @@ aesni_ctr32_encrypt_blocks: movq 40(%rsp),%r8 -.byte 243,15,30,250 cmpq $1,%rdx jne .Lctr32_bulk @@ -1779,7 +1769,6 @@ aesni_xts_encrypt: movq 48(%rsp),%r9 -.byte 243,15,30,250 leaq (%rsp),%r11 pushq %rbp @@ -2284,7 +2273,6 @@ aesni_xts_decrypt: movq 48(%rsp),%r9 -.byte 243,15,30,250 leaq (%rsp),%r11 pushq %rbp @@ -2826,7 +2814,6 @@ aesni_ocb_encrypt: movq 48(%rsp),%r9 -.byte 243,15,30,250 leaq (%rsp),%rax pushq %rbx @@ -3059,7 +3046,6 @@ aesni_ocb_encrypt: .def __ocb_encrypt6; .scl 3; .type 32; .endef .p2align 5 __ocb_encrypt6: - pxor %xmm9,%xmm15 movdqu (%rbx,%r12,1),%xmm11 movdqa %xmm10,%xmm12 @@ -3159,11 +3145,9 @@ __ocb_encrypt6: .byte 0xf3,0xc3 - .def __ocb_encrypt4; .scl 3; .type 32; .endef .p2align 5 __ocb_encrypt4: - pxor %xmm9,%xmm15 movdqu (%rbx,%r12,1),%xmm11 movdqa %xmm10,%xmm12 @@ -3230,11 +3214,9 @@ __ocb_encrypt4: .byte 0xf3,0xc3 - .def __ocb_encrypt1; .scl 3; .type 32; .endef .p2align 5 __ocb_encrypt1: - pxor %xmm15,%xmm7 pxor %xmm9,%xmm7 pxor %xmm2,%xmm8 @@ -3267,7 +3249,6 @@ __ocb_encrypt1: .byte 0xf3,0xc3 - .globl aesni_ocb_decrypt .def aesni_ocb_decrypt; .scl 2; .type 32; .endef .p2align 5 @@ -3284,7 +3265,6 @@ aesni_ocb_decrypt: movq 48(%rsp),%r9 -.byte 243,15,30,250 leaq (%rsp),%rax pushq %rbx @@ -3539,7 +3519,6 @@ aesni_ocb_decrypt: .def __ocb_decrypt6; .scl 3; .type 32; .endef .p2align 5 __ocb_decrypt6: - pxor %xmm9,%xmm15 movdqu (%rbx,%r12,1),%xmm11 movdqa %xmm10,%xmm12 @@ -3633,11 +3612,9 @@ __ocb_decrypt6: .byte 0xf3,0xc3 - .def __ocb_decrypt4; .scl 3; .type 32; .endef .p2align 5 __ocb_decrypt4: - pxor %xmm9,%xmm15 movdqu (%rbx,%r12,1),%xmm11 movdqa %xmm10,%xmm12 @@ -3700,11 +3677,9 @@ __ocb_decrypt4: .byte 0xf3,0xc3 - .def __ocb_decrypt1; .scl 3; .type 32; .endef .p2align 5 __ocb_decrypt1: - pxor %xmm15,%xmm7 pxor %xmm9,%xmm7 pxor %xmm7,%xmm2 @@ -3735,7 +3710,6 @@ __ocb_decrypt1: .byte 102,15,56,223,215 .byte 0xf3,0xc3 - .globl aesni_cbc_encrypt .def aesni_cbc_encrypt; .scl 2; .type 32; .endef .p2align 4 @@ -3752,7 +3726,6 @@ aesni_cbc_encrypt: movq 48(%rsp),%r9 -.byte 243,15,30,250 testq %rdx,%rdx jz .Lcbc_ret @@ -4714,6 +4687,7 @@ __aesni_set_encrypt_key: addq $8,%rsp .byte 0xf3,0xc3 + .LSEH_end_set_encrypt_key: .p2align 4 @@ -4786,7 +4760,6 @@ __aesni_set_encrypt_key: .byte 0xf3,0xc3 - .p2align 6 .Lbswap_mask: .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 diff --git a/lib/accelerated/x86/coff/e_padlock-x86.s b/lib/accelerated/x86/coff/e_padlock-x86.s index 9e27b93..41f87b1 100644 --- a/lib/accelerated/x86/coff/e_padlock-x86.s +++ b/lib/accelerated/x86/coff/e_padlock-x86.s @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2016, Andy Polyakov +# Copyright (c) 2011-2013, Andy Polyakov # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -37,13 +37,13 @@ # # *** This file is auto-generated *** # +.file "devel/perlasm/e_padlock-x86.s" .text .globl _padlock_capability .def _padlock_capability; .scl 2; .type 32; .endef .align 16 _padlock_capability: .L_padlock_capability_begin: -.byte 243,15,30,251 pushl %ebx pushfl popl %eax @@ -60,20 +60,11 @@ _padlock_capability: .byte 0x0f,0xa2 xorl %eax,%eax cmpl $0x746e6543,%ebx - jne .L001zhaoxin + jne .L000noluck cmpl $0x48727561,%edx jne .L000noluck cmpl $0x736c7561,%ecx jne .L000noluck - jmp .L002zhaoxinEnd -.L001zhaoxin: - cmpl $0x68532020,%ebx - jne .L000noluck - cmpl $0x68676e61,%edx - jne .L000noluck - cmpl $0x20206961,%ecx - jne .L000noluck -.L002zhaoxinEnd: movl $3221225472,%eax .byte 0x0f,0xa2 movl %eax,%edx @@ -103,41 +94,38 @@ _padlock_capability: .align 16 _padlock_key_bswap: .L_padlock_key_bswap_begin: -.byte 243,15,30,251 movl 4(%esp),%edx movl 240(%edx),%ecx -.L003bswap_loop: +.L001bswap_loop: movl (%edx),%eax bswap %eax movl %eax,(%edx) leal 4(%edx),%edx subl $1,%ecx - jnz .L003bswap_loop + jnz .L001bswap_loop ret .globl _padlock_verify_context .def _padlock_verify_context; .scl 2; .type 32; .endef .align 16 _padlock_verify_context: .L_padlock_verify_context_begin: -.byte 243,15,30,251 movl 4(%esp),%edx leal .Lpadlock_saved_context,%eax pushfl call __padlock_verify_ctx -.L004verify_pic_point: +.L002verify_pic_point: leal 4(%esp),%esp ret .def __padlock_verify_ctx; .scl 3; .type 32; .endef .align 16 __padlock_verify_ctx: -.byte 243,15,30,251 btl $30,4(%esp) - jnc .L005verified + jnc .L003verified cmpl (%eax),%edx - je .L005verified + je .L003verified pushfl popfl -.L005verified: +.L003verified: movl %edx,(%eax) ret .globl _padlock_reload_key @@ -145,7 +133,6 @@ __padlock_verify_ctx: .align 16 _padlock_reload_key: .L_padlock_reload_key_begin: -.byte 243,15,30,251 pushfl popfl ret @@ -154,7 +141,6 @@ _padlock_reload_key: .align 16 _padlock_aes_block: .L_padlock_aes_block_begin: -.byte 243,15,30,251 pushl %edi pushl %esi pushl %ebx @@ -174,7 +160,6 @@ _padlock_aes_block: .align 16 _padlock_ecb_encrypt: .L_padlock_ecb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -184,25 +169,25 @@ _padlock_ecb_encrypt: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz .L006ecb_abort + jnz .L004ecb_abort testl $15,%ecx - jnz .L006ecb_abort + jnz .L004ecb_abort leal .Lpadlock_saved_context,%eax pushfl cld call __padlock_verify_ctx -.L007ecb_pic_point: +.L005ecb_pic_point: leal 16(%edx),%edx xorl %eax,%eax xorl %ebx,%ebx testl $32,(%edx) - jnz .L008ecb_aligned + jnz .L006ecb_aligned testl $15,%edi setz %al testl $15,%esi setz %bl testl %ebx,%eax - jnz .L008ecb_aligned + jnz .L006ecb_aligned negl %eax movl $512,%ebx notl %eax @@ -221,7 +206,7 @@ _padlock_ecb_encrypt: andl $-16,%esp movl %eax,16(%ebp) cmpl %ebx,%ecx - ja .L009ecb_loop + ja .L007ecb_loop movl %esi,%eax cmpl %esp,%ebp cmovel %edi,%eax @@ -232,10 +217,10 @@ _padlock_ecb_encrypt: movl $-128,%eax cmovael %ebx,%eax andl %eax,%ebx - jz .L010ecb_unaligned_tail - jmp .L009ecb_loop + jz .L008ecb_unaligned_tail + jmp .L007ecb_loop .align 16 -.L009ecb_loop: +.L007ecb_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -244,13 +229,13 @@ _padlock_ecb_encrypt: testl $15,%edi cmovnzl %esp,%edi testl $15,%esi - jz .L011ecb_inp_aligned + jz .L009ecb_inp_aligned shrl $2,%ecx .byte 243,165 subl %ebx,%edi movl %ebx,%ecx movl %edi,%esi -.L011ecb_inp_aligned: +.L009ecb_inp_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -258,23 +243,23 @@ _padlock_ecb_encrypt: movl (%ebp),%edi movl 12(%ebp),%ebx testl $15,%edi - jz .L012ecb_out_aligned + jz .L010ecb_out_aligned movl %ebx,%ecx leal (%esp),%esi shrl $2,%ecx .byte 243,165 subl %ebx,%edi -.L012ecb_out_aligned: +.L010ecb_out_aligned: movl 4(%ebp),%esi movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jz .L013ecb_break + jz .L011ecb_break cmpl %ebx,%ecx - jae .L009ecb_loop -.L010ecb_unaligned_tail: + jae .L007ecb_loop +.L008ecb_unaligned_tail: xorl %eax,%eax cmpl %ebp,%esp cmovel %ecx,%eax @@ -287,24 +272,24 @@ _padlock_ecb_encrypt: movl %esp,%esi movl %eax,%edi movl %ebx,%ecx - jmp .L009ecb_loop + jmp .L007ecb_loop .align 16 -.L013ecb_break: +.L011ecb_break: cmpl %ebp,%esp - je .L014ecb_done + je .L012ecb_done pxor %xmm0,%xmm0 leal (%esp),%eax -.L015ecb_bzero: +.L013ecb_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja .L015ecb_bzero -.L014ecb_done: + ja .L013ecb_bzero +.L012ecb_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp - jmp .L016ecb_exit + jmp .L014ecb_exit .align 16 -.L008ecb_aligned: +.L006ecb_aligned: leal (%esi,%ecx,1),%ebp negl %ebp andl $4095,%ebp @@ -314,14 +299,14 @@ _padlock_ecb_encrypt: cmovael %eax,%ebp andl %ecx,%ebp subl %ebp,%ecx - jz .L017ecb_aligned_tail + jz .L015ecb_aligned_tail leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx .byte 243,15,167,200 testl %ebp,%ebp - jz .L016ecb_exit -.L017ecb_aligned_tail: + jz .L014ecb_exit +.L015ecb_aligned_tail: movl %ebp,%ecx leal -24(%esp),%ebp movl %ebp,%esp @@ -338,11 +323,11 @@ _padlock_ecb_encrypt: movl %esp,%esi movl %eax,%edi movl %ebx,%ecx - jmp .L009ecb_loop -.L016ecb_exit: + jmp .L007ecb_loop +.L014ecb_exit: movl $1,%eax leal 4(%esp),%esp -.L006ecb_abort: +.L004ecb_abort: popl %edi popl %esi popl %ebx @@ -353,7 +338,6 @@ _padlock_ecb_encrypt: .align 16 _padlock_cbc_encrypt: .L_padlock_cbc_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -363,25 +347,25 @@ _padlock_cbc_encrypt: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz .L018cbc_abort + jnz .L016cbc_abort testl $15,%ecx - jnz .L018cbc_abort + jnz .L016cbc_abort leal .Lpadlock_saved_context,%eax pushfl cld call __padlock_verify_ctx -.L019cbc_pic_point: +.L017cbc_pic_point: leal 16(%edx),%edx xorl %eax,%eax xorl %ebx,%ebx testl $32,(%edx) - jnz .L020cbc_aligned + jnz .L018cbc_aligned testl $15,%edi setz %al testl $15,%esi setz %bl testl %ebx,%eax - jnz .L020cbc_aligned + jnz .L018cbc_aligned negl %eax movl $512,%ebx notl %eax @@ -400,7 +384,7 @@ _padlock_cbc_encrypt: andl $-16,%esp movl %eax,16(%ebp) cmpl %ebx,%ecx - ja .L021cbc_loop + ja .L019cbc_loop movl %esi,%eax cmpl %esp,%ebp cmovel %edi,%eax @@ -411,10 +395,10 @@ _padlock_cbc_encrypt: movl $-64,%eax cmovael %ebx,%eax andl %eax,%ebx - jz .L022cbc_unaligned_tail - jmp .L021cbc_loop + jz .L020cbc_unaligned_tail + jmp .L019cbc_loop .align 16 -.L021cbc_loop: +.L019cbc_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -423,13 +407,13 @@ _padlock_cbc_encrypt: testl $15,%edi cmovnzl %esp,%edi testl $15,%esi - jz .L023cbc_inp_aligned + jz .L021cbc_inp_aligned shrl $2,%ecx .byte 243,165 subl %ebx,%edi movl %ebx,%ecx movl %edi,%esi -.L023cbc_inp_aligned: +.L021cbc_inp_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -439,23 +423,23 @@ _padlock_cbc_encrypt: movl (%ebp),%edi movl 12(%ebp),%ebx testl $15,%edi - jz .L024cbc_out_aligned + jz .L022cbc_out_aligned movl %ebx,%ecx leal (%esp),%esi shrl $2,%ecx .byte 243,165 subl %ebx,%edi -.L024cbc_out_aligned: +.L022cbc_out_aligned: movl 4(%ebp),%esi movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jz .L025cbc_break + jz .L023cbc_break cmpl %ebx,%ecx - jae .L021cbc_loop -.L022cbc_unaligned_tail: + jae .L019cbc_loop +.L020cbc_unaligned_tail: xorl %eax,%eax cmpl %ebp,%esp cmovel %ecx,%eax @@ -468,24 +452,24 @@ _padlock_cbc_encrypt: movl %esp,%esi movl %eax,%edi movl %ebx,%ecx - jmp .L021cbc_loop + jmp .L019cbc_loop .align 16 -.L025cbc_break: +.L023cbc_break: cmpl %ebp,%esp - je .L026cbc_done + je .L024cbc_done pxor %xmm0,%xmm0 leal (%esp),%eax -.L027cbc_bzero: +.L025cbc_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja .L027cbc_bzero -.L026cbc_done: + ja .L025cbc_bzero +.L024cbc_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp - jmp .L028cbc_exit + jmp .L026cbc_exit .align 16 -.L020cbc_aligned: +.L018cbc_aligned: leal (%esi,%ecx,1),%ebp negl %ebp andl $4095,%ebp @@ -495,7 +479,7 @@ _padlock_cbc_encrypt: cmovael %eax,%ebp andl %ecx,%ebp subl %ebp,%ecx - jz .L029cbc_aligned_tail + jz .L027cbc_aligned_tail leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -503,8 +487,8 @@ _padlock_cbc_encrypt: movaps (%eax),%xmm0 movaps %xmm0,-16(%edx) testl %ebp,%ebp - jz .L028cbc_exit -.L029cbc_aligned_tail: + jz .L026cbc_exit +.L027cbc_aligned_tail: movl %ebp,%ecx leal -24(%esp),%ebp movl %ebp,%esp @@ -521,11 +505,11 @@ _padlock_cbc_encrypt: movl %esp,%esi movl %eax,%edi movl %ebx,%ecx - jmp .L021cbc_loop -.L028cbc_exit: + jmp .L019cbc_loop +.L026cbc_exit: movl $1,%eax leal 4(%esp),%esp -.L018cbc_abort: +.L016cbc_abort: popl %edi popl %esi popl %ebx @@ -536,7 +520,6 @@ _padlock_cbc_encrypt: .align 16 _padlock_cfb_encrypt: .L_padlock_cfb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -546,25 +529,25 @@ _padlock_cfb_encrypt: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz .L030cfb_abort + jnz .L028cfb_abort testl $15,%ecx - jnz .L030cfb_abort + jnz .L028cfb_abort leal .Lpadlock_saved_context,%eax pushfl cld call __padlock_verify_ctx -.L031cfb_pic_point: +.L029cfb_pic_point: leal 16(%edx),%edx xorl %eax,%eax xorl %ebx,%ebx testl $32,(%edx) - jnz .L032cfb_aligned + jnz .L030cfb_aligned testl $15,%edi setz %al testl $15,%esi setz %bl testl %ebx,%eax - jnz .L032cfb_aligned + jnz .L030cfb_aligned negl %eax movl $512,%ebx notl %eax @@ -582,9 +565,9 @@ _padlock_cfb_encrypt: andl $-16,%ebp andl $-16,%esp movl %eax,16(%ebp) - jmp .L033cfb_loop + jmp .L031cfb_loop .align 16 -.L033cfb_loop: +.L031cfb_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -593,13 +576,13 @@ _padlock_cfb_encrypt: testl $15,%edi cmovnzl %esp,%edi testl $15,%esi - jz .L034cfb_inp_aligned + jz .L032cfb_inp_aligned shrl $2,%ecx .byte 243,165 subl %ebx,%edi movl %ebx,%ecx movl %edi,%esi -.L034cfb_inp_aligned: +.L032cfb_inp_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -609,45 +592,45 @@ _padlock_cfb_encrypt: movl (%ebp),%edi movl 12(%ebp),%ebx testl $15,%edi - jz .L035cfb_out_aligned + jz .L033cfb_out_aligned movl %ebx,%ecx leal (%esp),%esi shrl $2,%ecx .byte 243,165 subl %ebx,%edi -.L035cfb_out_aligned: +.L033cfb_out_aligned: movl 4(%ebp),%esi movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jnz .L033cfb_loop + jnz .L031cfb_loop cmpl %ebp,%esp - je .L036cfb_done + je .L034cfb_done pxor %xmm0,%xmm0 leal (%esp),%eax -.L037cfb_bzero: +.L035cfb_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja .L037cfb_bzero -.L036cfb_done: + ja .L035cfb_bzero +.L034cfb_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp - jmp .L038cfb_exit + jmp .L036cfb_exit .align 16 -.L032cfb_aligned: +.L030cfb_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx .byte 243,15,167,224 movaps (%eax),%xmm0 movaps %xmm0,-16(%edx) -.L038cfb_exit: +.L036cfb_exit: movl $1,%eax leal 4(%esp),%esp -.L030cfb_abort: +.L028cfb_abort: popl %edi popl %esi popl %ebx @@ -658,7 +641,6 @@ _padlock_cfb_encrypt: .align 16 _padlock_ofb_encrypt: .L_padlock_ofb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -668,25 +650,25 @@ _padlock_ofb_encrypt: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz .L039ofb_abort + jnz .L037ofb_abort testl $15,%ecx - jnz .L039ofb_abort + jnz .L037ofb_abort leal .Lpadlock_saved_context,%eax pushfl cld call __padlock_verify_ctx -.L040ofb_pic_point: +.L038ofb_pic_point: leal 16(%edx),%edx xorl %eax,%eax xorl %ebx,%ebx testl $32,(%edx) - jnz .L041ofb_aligned + jnz .L039ofb_aligned testl $15,%edi setz %al testl $15,%esi setz %bl testl %ebx,%eax - jnz .L041ofb_aligned + jnz .L039ofb_aligned negl %eax movl $512,%ebx notl %eax @@ -704,9 +686,9 @@ _padlock_ofb_encrypt: andl $-16,%ebp andl $-16,%esp movl %eax,16(%ebp) - jmp .L042ofb_loop + jmp .L040ofb_loop .align 16 -.L042ofb_loop: +.L040ofb_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -715,13 +697,13 @@ _padlock_ofb_encrypt: testl $15,%edi cmovnzl %esp,%edi testl $15,%esi - jz .L043ofb_inp_aligned + jz .L041ofb_inp_aligned shrl $2,%ecx .byte 243,165 subl %ebx,%edi movl %ebx,%ecx movl %edi,%esi -.L043ofb_inp_aligned: +.L041ofb_inp_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -731,45 +713,45 @@ _padlock_ofb_encrypt: movl (%ebp),%edi movl 12(%ebp),%ebx testl $15,%edi - jz .L044ofb_out_aligned + jz .L042ofb_out_aligned movl %ebx,%ecx leal (%esp),%esi shrl $2,%ecx .byte 243,165 subl %ebx,%edi -.L044ofb_out_aligned: +.L042ofb_out_aligned: movl 4(%ebp),%esi movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jnz .L042ofb_loop + jnz .L040ofb_loop cmpl %ebp,%esp - je .L045ofb_done + je .L043ofb_done pxor %xmm0,%xmm0 leal (%esp),%eax -.L046ofb_bzero: +.L044ofb_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja .L046ofb_bzero -.L045ofb_done: + ja .L044ofb_bzero +.L043ofb_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp - jmp .L047ofb_exit + jmp .L045ofb_exit .align 16 -.L041ofb_aligned: +.L039ofb_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx .byte 243,15,167,232 movaps (%eax),%xmm0 movaps %xmm0,-16(%edx) -.L047ofb_exit: +.L045ofb_exit: movl $1,%eax leal 4(%esp),%esp -.L039ofb_abort: +.L037ofb_abort: popl %edi popl %esi popl %ebx @@ -780,7 +762,6 @@ _padlock_ofb_encrypt: .align 16 _padlock_ctr32_encrypt: .L_padlock_ctr32_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -790,14 +771,14 @@ _padlock_ctr32_encrypt: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz .L048ctr32_abort + jnz .L046ctr32_abort testl $15,%ecx - jnz .L048ctr32_abort + jnz .L046ctr32_abort leal .Lpadlock_saved_context,%eax pushfl cld call __padlock_verify_ctx -.L049ctr32_pic_point: +.L047ctr32_pic_point: leal 16(%edx),%edx xorl %eax,%eax movq -16(%edx),%mm0 @@ -817,9 +798,9 @@ _padlock_ctr32_encrypt: andl $-16,%ebp andl $-16,%esp movl %eax,16(%ebp) - jmp .L050ctr32_loop + jmp .L048ctr32_loop .align 16 -.L050ctr32_loop: +.L048ctr32_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -828,7 +809,7 @@ _padlock_ctr32_encrypt: movl -4(%edx),%ecx xorl %edi,%edi movl -8(%edx),%eax -.L051ctr32_prepare: +.L049ctr32_prepare: movl %ecx,12(%esp,%edi,1) bswap %ecx movq %mm0,(%esp,%edi,1) @@ -837,7 +818,7 @@ _padlock_ctr32_encrypt: bswap %ecx leal 16(%edi),%edi cmpl %ebx,%edi - jb .L051ctr32_prepare + jb .L049ctr32_prepare movl %ecx,-4(%edx) leal (%esp),%esi leal (%esp),%edi @@ -850,33 +831,33 @@ _padlock_ctr32_encrypt: movl 12(%ebp),%ebx movl 4(%ebp),%esi xorl %ecx,%ecx -.L052ctr32_xor: +.L050ctr32_xor: movups (%esi,%ecx,1),%xmm1 leal 16(%ecx),%ecx pxor -16(%esp,%ecx,1),%xmm1 movups %xmm1,-16(%edi,%ecx,1) cmpl %ebx,%ecx - jb .L052ctr32_xor + jb .L050ctr32_xor movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jnz .L050ctr32_loop + jnz .L048ctr32_loop pxor %xmm0,%xmm0 leal (%esp),%eax -.L053ctr32_bzero: +.L051ctr32_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja .L053ctr32_bzero -.L054ctr32_done: + ja .L051ctr32_bzero +.L052ctr32_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp movl $1,%eax leal 4(%esp),%esp emms -.L048ctr32_abort: +.L046ctr32_abort: popl %edi popl %esi popl %ebx @@ -887,7 +868,6 @@ _padlock_ctr32_encrypt: .align 16 _padlock_xstore: .L_padlock_xstore_begin: -.byte 243,15,30,251 pushl %edi movl 8(%esp),%edi movl 12(%esp),%edx @@ -897,22 +877,20 @@ _padlock_xstore: .def __win32_segv_handler; .scl 3; .type 32; .endef .align 16 __win32_segv_handler: -.byte 243,15,30,251 movl $1,%eax movl 4(%esp),%edx movl 12(%esp),%ecx cmpl $3221225477,(%edx) - jne .L055ret + jne .L053ret addl $4,184(%ecx) movl $0,%eax -.L055ret: +.L053ret: ret .globl _padlock_sha1_oneshot .def _padlock_sha1_oneshot; .scl 2; .type 32; .endef .align 16 _padlock_sha1_oneshot: .L_padlock_sha1_oneshot_begin: -.byte 243,15,30,251 pushl %edi pushl %esi xorl %eax,%eax @@ -948,7 +926,6 @@ _padlock_sha1_oneshot: .align 16 _padlock_sha1_blocks: .L_padlock_sha1_blocks_begin: -.byte 243,15,30,251 pushl %edi pushl %esi movl 12(%esp),%edi @@ -978,7 +955,6 @@ _padlock_sha1_blocks: .align 16 _padlock_sha256_oneshot: .L_padlock_sha256_oneshot_begin: -.byte 243,15,30,251 pushl %edi pushl %esi xorl %eax,%eax @@ -1014,7 +990,6 @@ _padlock_sha256_oneshot: .align 16 _padlock_sha256_blocks: .L_padlock_sha256_blocks_begin: -.byte 243,15,30,251 pushl %edi pushl %esi movl 12(%esp),%edi @@ -1044,7 +1019,6 @@ _padlock_sha256_blocks: .align 16 _padlock_sha512_blocks: .L_padlock_sha512_blocks_begin: -.byte 243,15,30,251 pushl %edi pushl %esi movl 12(%esp),%edi diff --git a/lib/accelerated/x86/coff/e_padlock-x86_64.s b/lib/accelerated/x86/coff/e_padlock-x86_64.s index 71c9e1a..7edee19 100644 --- a/lib/accelerated/x86/coff/e_padlock-x86_64.s +++ b/lib/accelerated/x86/coff/e_padlock-x86_64.s @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2016, Andy Polyakov +# Copyright (c) 2011-2013, Andy Polyakov # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -42,50 +42,36 @@ .def padlock_capability; .scl 2; .type 32; .endef .p2align 4 padlock_capability: - -.byte 243,15,30,250 movq %rbx,%r8 xorl %eax,%eax cpuid xorl %eax,%eax - cmpl $0x746e6543,%ebx - jne .Lzhaoxin - cmpl $0x48727561,%edx - jne .Lnoluck - cmpl $0x736c7561,%ecx - jne .Lnoluck - jmp .LzhaoxinEnd -.Lzhaoxin: - cmpl $0x68532020,%ebx + cmpl $1953391939,%ebx jne .Lnoluck - cmpl $0x68676e61,%edx + cmpl $1215460705,%edx jne .Lnoluck - cmpl $0x20206961,%ecx + cmpl $1936487777,%ecx jne .Lnoluck -.LzhaoxinEnd: - movl $0xC0000000,%eax + movl $3221225472,%eax cpuid movl %eax,%edx xorl %eax,%eax - cmpl $0xC0000001,%edx + cmpl $3221225473,%edx jb .Lnoluck - movl $0xC0000001,%eax + movl $3221225473,%eax cpuid movl %edx,%eax - andl $0xffffffef,%eax - orl $0x10,%eax + andl $4294967279,%eax + orl $16,%eax .Lnoluck: movq %r8,%rbx .byte 0xf3,0xc3 - .globl padlock_key_bswap .def padlock_key_bswap; .scl 2; .type 32; .endef .p2align 4 padlock_key_bswap: - -.byte 243,15,30,250 movl 240(%rcx),%edx .Lbswap_loop: movl (%rcx),%eax @@ -97,13 +83,10 @@ padlock_key_bswap: .byte 0xf3,0xc3 - .globl padlock_verify_context .def padlock_verify_context; .scl 2; .type 32; .endef .p2align 4 padlock_verify_context: - -.byte 243,15,30,250 movq %rcx,%rdx pushf leaq .Lpadlock_saved_context(%rip),%rax @@ -112,12 +95,9 @@ padlock_verify_context: .byte 0xf3,0xc3 - .def _padlock_verify_ctx; .scl 3; .type 32; .endef .p2align 4 _padlock_verify_ctx: - -.byte 243,15,30,250 movq 8(%rsp),%r8 btq $30,%r8 jnc .Lverified @@ -130,19 +110,15 @@ _padlock_verify_ctx: .byte 0xf3,0xc3 - .globl padlock_reload_key .def padlock_reload_key; .scl 2; .type 32; .endef .p2align 4 padlock_reload_key: - -.byte 243,15,30,250 pushf popf .byte 0xf3,0xc3 - .globl padlock_aes_block .def padlock_aes_block; .scl 2; .type 32; .endef .p2align 4 @@ -155,18 +131,15 @@ padlock_aes_block: movq %rdx,%rsi movq %r8,%rdx - -.byte 243,15,30,250 movq %rbx,%r8 movq $1,%rcx leaq 32(%rdx),%rbx leaq 16(%rdx),%rdx -.byte 0xf3,0x0f,0xa7,0xc8 +.byte 0xf3,0x0f,0xa7,0xc8 movq %r8,%rbx movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_padlock_aes_block: .globl padlock_xstore @@ -180,14 +153,11 @@ padlock_xstore: movq %rcx,%rdi movq %rdx,%rsi - -.byte 243,15,30,250 movl %esi,%edx -.byte 0x0f,0xa7,0xc0 +.byte 0x0f,0xa7,0xc0 movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_padlock_xstore: .globl padlock_sha1_oneshot @@ -202,8 +172,6 @@ padlock_sha1_oneshot: movq %rdx,%rsi movq %r8,%rdx - -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -213,7 +181,7 @@ padlock_sha1_oneshot: movq %rsp,%rdi movl %eax,16(%rsp) xorq %rax,%rax -.byte 0xf3,0x0f,0xa6,0xc8 +.byte 0xf3,0x0f,0xa6,0xc8 movaps (%rsp),%xmm0 movl 16(%rsp),%eax addq $128+8,%rsp @@ -222,7 +190,6 @@ padlock_sha1_oneshot: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_padlock_sha1_oneshot: .globl padlock_sha1_blocks @@ -237,8 +204,6 @@ padlock_sha1_blocks: movq %rdx,%rsi movq %r8,%rdx - -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -248,7 +213,7 @@ padlock_sha1_blocks: movq %rsp,%rdi movl %eax,16(%rsp) movq $-1,%rax -.byte 0xf3,0x0f,0xa6,0xc8 +.byte 0xf3,0x0f,0xa6,0xc8 movaps (%rsp),%xmm0 movl 16(%rsp),%eax addq $128+8,%rsp @@ -257,7 +222,6 @@ padlock_sha1_blocks: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_padlock_sha1_blocks: .globl padlock_sha256_oneshot @@ -272,8 +236,6 @@ padlock_sha256_oneshot: movq %rdx,%rsi movq %r8,%rdx - -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -283,7 +245,7 @@ padlock_sha256_oneshot: movq %rsp,%rdi movaps %xmm1,16(%rsp) xorq %rax,%rax -.byte 0xf3,0x0f,0xa6,0xd0 +.byte 0xf3,0x0f,0xa6,0xd0 movaps (%rsp),%xmm0 movaps 16(%rsp),%xmm1 addq $128+8,%rsp @@ -292,7 +254,6 @@ padlock_sha256_oneshot: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_padlock_sha256_oneshot: .globl padlock_sha256_blocks @@ -307,8 +268,6 @@ padlock_sha256_blocks: movq %rdx,%rsi movq %r8,%rdx - -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -318,7 +277,7 @@ padlock_sha256_blocks: movq %rsp,%rdi movaps %xmm1,16(%rsp) movq $-1,%rax -.byte 0xf3,0x0f,0xa6,0xd0 +.byte 0xf3,0x0f,0xa6,0xd0 movaps (%rsp),%xmm0 movaps 16(%rsp),%xmm1 addq $128+8,%rsp @@ -327,7 +286,6 @@ padlock_sha256_blocks: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_padlock_sha256_blocks: .globl padlock_sha512_blocks @@ -342,8 +300,6 @@ padlock_sha512_blocks: movq %rdx,%rsi movq %r8,%rdx - -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -356,7 +312,7 @@ padlock_sha512_blocks: movaps %xmm1,16(%rsp) movaps %xmm2,32(%rsp) movaps %xmm3,48(%rsp) -.byte 0xf3,0x0f,0xa6,0xe0 +.byte 0xf3,0x0f,0xa6,0xe0 movaps (%rsp),%xmm0 movaps 16(%rsp),%xmm1 movaps 32(%rsp),%xmm2 @@ -369,7 +325,6 @@ padlock_sha512_blocks: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_padlock_sha512_blocks: .globl padlock_ecb_encrypt .def padlock_ecb_encrypt; .scl 2; .type 32; .endef @@ -384,8 +339,6 @@ padlock_ecb_encrypt: movq %r8,%rdx movq %r9,%rcx - -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -403,9 +356,9 @@ padlock_ecb_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz .Lecb_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz .Lecb_aligned @@ -429,7 +382,7 @@ padlock_ecb_encrypt: cmoveq %rdi,%rax addq %rcx,%rax negq %rax - andq $0xfff,%rax + andq $4095,%rax cmpq $128,%rax movq $-128,%rax cmovaeq %rbx,%rax @@ -445,12 +398,12 @@ padlock_ecb_encrypt: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz .Lecb_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -458,15 +411,15 @@ padlock_ecb_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,200 +.byte 0xf3,0x0f,0xa7,200 movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz .Lecb_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi .Lecb_out_aligned: movq %r9,%rsi @@ -487,7 +440,7 @@ padlock_ecb_encrypt: subq %rax,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 movq %rsp,%rsi movq %r8,%rdi movq %rbx,%rcx @@ -513,7 +466,7 @@ padlock_ecb_encrypt: .Lecb_aligned: leaq (%rsi,%rcx,1),%rbp negq %rbp - andq $0xfff,%rbp + andq $4095,%rbp xorl %eax,%eax cmpq $128,%rbp movq $128-1,%rbp @@ -524,7 +477,7 @@ padlock_ecb_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,200 +.byte 0xf3,0x0f,0xa7,200 testq %rbp,%rbp jz .Lecb_exit @@ -536,7 +489,7 @@ padlock_ecb_encrypt: subq %rcx,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 leaq (%r8),%rdi leaq (%rsp),%rsi movq %rbx,%rcx @@ -550,7 +503,6 @@ padlock_ecb_encrypt: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_padlock_ecb_encrypt: .globl padlock_cbc_encrypt .def padlock_cbc_encrypt; .scl 2; .type 32; .endef @@ -565,8 +517,6 @@ padlock_cbc_encrypt: movq %r8,%rdx movq %r9,%rcx - -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -584,9 +534,9 @@ padlock_cbc_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz .Lcbc_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz .Lcbc_aligned @@ -610,7 +560,7 @@ padlock_cbc_encrypt: cmoveq %rdi,%rax addq %rcx,%rax negq %rax - andq $0xfff,%rax + andq $4095,%rax cmpq $64,%rax movq $-64,%rax cmovaeq %rbx,%rax @@ -626,12 +576,12 @@ padlock_cbc_encrypt: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz .Lcbc_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -639,17 +589,17 @@ padlock_cbc_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,208 +.byte 0xf3,0x0f,0xa7,208 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz .Lcbc_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi .Lcbc_out_aligned: movq %r9,%rsi @@ -670,7 +620,7 @@ padlock_cbc_encrypt: subq %rax,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 movq %rsp,%rsi movq %r8,%rdi movq %rbx,%rcx @@ -696,7 +646,7 @@ padlock_cbc_encrypt: .Lcbc_aligned: leaq (%rsi,%rcx,1),%rbp negq %rbp - andq $0xfff,%rbp + andq $4095,%rbp xorl %eax,%eax cmpq $64,%rbp movq $64-1,%rbp @@ -707,7 +657,7 @@ padlock_cbc_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,208 +.byte 0xf3,0x0f,0xa7,208 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) testq %rbp,%rbp @@ -721,7 +671,7 @@ padlock_cbc_encrypt: subq %rcx,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 leaq (%r8),%rdi leaq (%rsp),%rsi movq %rbx,%rcx @@ -735,7 +685,6 @@ padlock_cbc_encrypt: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_padlock_cbc_encrypt: .globl padlock_cfb_encrypt .def padlock_cfb_encrypt; .scl 2; .type 32; .endef @@ -750,8 +699,6 @@ padlock_cfb_encrypt: movq %r8,%rdx movq %r9,%rcx - -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -769,9 +716,9 @@ padlock_cfb_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz .Lcfb_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz .Lcfb_aligned @@ -798,12 +745,12 @@ padlock_cfb_encrypt: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz .Lcfb_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -811,17 +758,17 @@ padlock_cfb_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,224 +.byte 0xf3,0x0f,0xa7,224 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz .Lcfb_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi .Lcfb_out_aligned: movq %r9,%rsi @@ -851,7 +798,7 @@ padlock_cfb_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,224 +.byte 0xf3,0x0f,0xa7,224 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) .Lcfb_exit: @@ -863,7 +810,6 @@ padlock_cfb_encrypt: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_padlock_cfb_encrypt: .globl padlock_ofb_encrypt .def padlock_ofb_encrypt; .scl 2; .type 32; .endef @@ -878,8 +824,6 @@ padlock_ofb_encrypt: movq %r8,%rdx movq %r9,%rcx - -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -897,9 +841,9 @@ padlock_ofb_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz .Lofb_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz .Lofb_aligned @@ -926,12 +870,12 @@ padlock_ofb_encrypt: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz .Lofb_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -939,17 +883,17 @@ padlock_ofb_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,232 +.byte 0xf3,0x0f,0xa7,232 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz .Lofb_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi .Lofb_out_aligned: movq %r9,%rsi @@ -979,7 +923,7 @@ padlock_ofb_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,232 +.byte 0xf3,0x0f,0xa7,232 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) .Lofb_exit: @@ -991,7 +935,6 @@ padlock_ofb_encrypt: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_padlock_ofb_encrypt: .globl padlock_ctr32_encrypt .def padlock_ctr32_encrypt; .scl 2; .type 32; .endef @@ -1006,8 +949,6 @@ padlock_ctr32_encrypt: movq %r8,%rdx movq %r9,%rcx - -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -1025,9 +966,9 @@ padlock_ctr32_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz .Lctr32_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz .Lctr32_aligned @@ -1062,7 +1003,7 @@ padlock_ctr32_encrypt: cmoveq %rdi,%rax addq %rcx,%rax negq %rax - andq $0xfff,%rax + andq $4095,%rax cmpq $32,%rax movq $-32,%rax cmovaeq %rbx,%rax @@ -1078,12 +1019,12 @@ padlock_ctr32_encrypt: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz .Lctr32_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -1091,23 +1032,23 @@ padlock_ctr32_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,216 +.byte 0xf3,0x0f,0xa7,216 movl -4(%rdx),%eax - testl $0xffff0000,%eax + testl $4294901760,%eax jnz .Lctr32_no_carry bswapl %eax - addl $0x10000,%eax + addl $65536,%eax bswapl %eax movl %eax,-4(%rdx) .Lctr32_no_carry: movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz .Lctr32_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi .Lctr32_out_aligned: movq %r9,%rsi @@ -1125,7 +1066,7 @@ padlock_ctr32_encrypt: cmoveq %rdi,%rax addq %rcx,%rax negq %rax - andq $0xfff,%rax + andq $4095,%rax cmpq $32,%rax movq $-32,%rax cmovaeq %rbx,%rax @@ -1140,7 +1081,7 @@ padlock_ctr32_encrypt: subq %rax,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 movq %rsp,%rsi movq %r8,%rdi movq %rbx,%rcx @@ -1167,7 +1108,7 @@ padlock_ctr32_encrypt: movl -4(%rdx),%eax bswapl %eax negl %eax - andl $0xffff,%eax + andl $65535,%eax movq $1048576,%rbx shll $4,%eax cmovzq %rbx,%rax @@ -1184,11 +1125,11 @@ padlock_ctr32_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,216 +.byte 0xf3,0x0f,0xa7,216 movl -4(%rdx),%eax bswapl %eax - addl $0x10000,%eax + addl $65536,%eax bswapl %eax movl %eax,-4(%rdx) @@ -1202,7 +1143,7 @@ padlock_ctr32_encrypt: .Lctr32_aligned_skip: leaq (%rsi,%rcx,1),%rbp negq %rbp - andq $0xfff,%rbp + andq $4095,%rbp xorl %eax,%eax cmpq $32,%rbp movq $32-1,%rbp @@ -1213,7 +1154,7 @@ padlock_ctr32_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,216 +.byte 0xf3,0x0f,0xa7,216 testq %rbp,%rbp jz .Lctr32_exit @@ -1225,7 +1166,7 @@ padlock_ctr32_encrypt: subq %rcx,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 leaq (%r8),%rdi leaq (%rsp),%rsi movq %rbx,%rcx @@ -1239,7 +1180,6 @@ padlock_ctr32_encrypt: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_padlock_ctr32_encrypt: .byte 86,73,65,32,80,97,100,108,111,99,107,32,120,56,54,95,54,52,32,109,111,100,117,108,101,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .p2align 4 diff --git a/lib/accelerated/x86/coff/ghash-x86_64.s b/lib/accelerated/x86/coff/ghash-x86_64.s index cfe2425..de207e4 100644 --- a/lib/accelerated/x86/coff/ghash-x86_64.s +++ b/lib/accelerated/x86/coff/ghash-x86_64.s @@ -52,7 +52,6 @@ gcm_gmult_4bit: movq %rdx,%rsi -.byte 243,15,30,250 pushq %rbx pushq %rbp @@ -169,7 +168,6 @@ gcm_ghash_4bit: movq %r9,%rcx -.byte 243,15,30,250 pushq %rbx pushq %rbp @@ -920,7 +918,6 @@ gcm_init_clmul: .p2align 4 gcm_gmult_clmul: -.byte 243,15,30,250 .L_gmult_clmul: movdqu (%rcx),%xmm0 movdqa .Lbswap_mask(%rip),%xmm5 @@ -974,7 +971,6 @@ gcm_gmult_clmul: .p2align 5 gcm_ghash_clmul: -.byte 243,15,30,250 .L_ghash_clmul: leaq -136(%rsp),%rax .LSEH_begin_gcm_ghash_clmul: @@ -1502,7 +1498,6 @@ gcm_init_avx: .p2align 5 gcm_gmult_avx: -.byte 243,15,30,250 jmp .L_gmult_clmul @@ -1511,7 +1506,6 @@ gcm_gmult_avx: .p2align 5 gcm_ghash_avx: -.byte 243,15,30,250 leaq -136(%rsp),%rax .LSEH_begin_gcm_ghash_avx: diff --git a/lib/accelerated/x86/coff/sha1-ssse3-x86.s b/lib/accelerated/x86/coff/sha1-ssse3-x86.s index 34b3360..30f9ded 100644 --- a/lib/accelerated/x86/coff/sha1-ssse3-x86.s +++ b/lib/accelerated/x86/coff/sha1-ssse3-x86.s @@ -43,7 +43,6 @@ .align 16 _sha1_block_data_order: .L_sha1_block_data_order_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi diff --git a/lib/accelerated/x86/coff/sha1-ssse3-x86_64.s b/lib/accelerated/x86/coff/sha1-ssse3-x86_64.s index 79f841f..cdfc882 100644 --- a/lib/accelerated/x86/coff/sha1-ssse3-x86_64.s +++ b/lib/accelerated/x86/coff/sha1-ssse3-x86_64.s @@ -1490,10 +1490,10 @@ _shaext_shortcut: movaps -8-16(%rax),%xmm9 movq %rax,%rsp .Lepilogue_shaext: + movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_sha1_block_data_order_shaext: .def sha1_block_data_order_ssse3; .scl 3; .type 32; .endef .p2align 4 diff --git a/lib/accelerated/x86/coff/sha256-ssse3-x86.s b/lib/accelerated/x86/coff/sha256-ssse3-x86.s index 8109c6b..05cd61d 100644 --- a/lib/accelerated/x86/coff/sha256-ssse3-x86.s +++ b/lib/accelerated/x86/coff/sha256-ssse3-x86.s @@ -43,7 +43,6 @@ .align 16 _sha256_block_data_order: .L_sha256_block_data_order_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi diff --git a/lib/accelerated/x86/coff/sha256-ssse3-x86_64.s b/lib/accelerated/x86/coff/sha256-ssse3-x86_64.s index 78fae2a..d2fc195 100644 --- a/lib/accelerated/x86/coff/sha256-ssse3-x86_64.s +++ b/lib/accelerated/x86/coff/sha256-ssse3-x86_64.s @@ -1832,7 +1832,6 @@ sha256_block_data_order_shaext: movq %r8,%rdx _shaext_shortcut: - leaq -88(%rsp),%rsp movaps %xmm6,-8-80(%rax) movaps %xmm7,-8-64(%rax) @@ -2051,7 +2050,6 @@ _shaext_shortcut: movq 8(%rsp),%rdi movq 16(%rsp),%rsi .byte 0xf3,0xc3 - .LSEH_end_sha256_block_data_order_shaext: .def sha256_block_data_order_ssse3; .scl 3; .type 32; .endef .p2align 6 @@ -5503,8 +5501,6 @@ sha256_block_data_order_avx2: leaq 448(%rsp),%rsp - - addl 0(%rdi),%eax addl 4(%rdi),%ebx addl 8(%rdi),%ecx @@ -5530,17 +5526,15 @@ sha256_block_data_order_avx2: jbe .Loop_avx2 leaq (%rsp),%rbp - - - .Ldone_avx2: - movq 88(%rbp),%rsi + leaq (%rbp),%rsp + movq 88(%rsp),%rsi vzeroupper - movaps 64+32(%rbp),%xmm6 - movaps 64+48(%rbp),%xmm7 - movaps 64+64(%rbp),%xmm8 - movaps 64+80(%rbp),%xmm9 + movaps 64+32(%rsp),%xmm6 + movaps 64+48(%rsp),%xmm7 + movaps 64+64(%rsp),%xmm8 + movaps 64+80(%rsp),%xmm9 movq -48(%rsi),%r15 movq -40(%rsi),%r14 diff --git a/lib/accelerated/x86/coff/sha512-ssse3-x86.s b/lib/accelerated/x86/coff/sha512-ssse3-x86.s index 321a185..72a7f73 100644 --- a/lib/accelerated/x86/coff/sha512-ssse3-x86.s +++ b/lib/accelerated/x86/coff/sha512-ssse3-x86.s @@ -43,7 +43,6 @@ .align 16 _sha512_block_data_order: .L_sha512_block_data_order_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi diff --git a/lib/accelerated/x86/coff/sha512-ssse3-x86_64.s b/lib/accelerated/x86/coff/sha512-ssse3-x86_64.s index 836e0cf..419fa2a 100644 --- a/lib/accelerated/x86/coff/sha512-ssse3-x86_64.s +++ b/lib/accelerated/x86/coff/sha512-ssse3-x86_64.s @@ -5494,8 +5494,6 @@ sha512_block_data_order_avx2: leaq 1152(%rsp),%rsp - - addq 0(%rdi),%rax addq 8(%rdi),%rbx addq 16(%rdi),%rcx @@ -5521,19 +5519,17 @@ sha512_block_data_order_avx2: jbe .Loop_avx2 leaq (%rsp),%rbp - - - .Ldone_avx2: - movq 152(%rbp),%rsi + leaq (%rbp),%rsp + movq 152(%rsp),%rsi vzeroupper - movaps 128+32(%rbp),%xmm6 - movaps 128+48(%rbp),%xmm7 - movaps 128+64(%rbp),%xmm8 - movaps 128+80(%rbp),%xmm9 - movaps 128+96(%rbp),%xmm10 - movaps 128+112(%rbp),%xmm11 + movaps 128+32(%rsp),%xmm6 + movaps 128+48(%rsp),%xmm7 + movaps 128+64(%rsp),%xmm8 + movaps 128+80(%rsp),%xmm9 + movaps 128+96(%rsp),%xmm10 + movaps 128+112(%rsp),%xmm11 movq -48(%rsi),%r15 movq -40(%rsi),%r14 diff --git a/lib/accelerated/x86/elf/aes-ssse3-x86.s b/lib/accelerated/x86/elf/aes-ssse3-x86.s index 7be5305..265e28a 100644 --- a/lib/accelerated/x86/elf/aes-ssse3-x86.s +++ b/lib/accelerated/x86/elf/aes-ssse3-x86.s @@ -71,7 +71,6 @@ .type _vpaes_preheat,@function .align 16 _vpaes_preheat: -.byte 243,15,30,251 addl (%esp),%ebp movdqa -48(%ebp),%xmm7 movdqa -16(%ebp),%xmm6 @@ -80,7 +79,6 @@ _vpaes_preheat: .type _vpaes_encrypt_core,@function .align 16 _vpaes_encrypt_core: -.byte 243,15,30,251 movl $16,%ecx movl 240(%edx),%eax movdqa %xmm6,%xmm1 @@ -158,7 +156,6 @@ _vpaes_encrypt_core: .type _vpaes_decrypt_core,@function .align 16 _vpaes_decrypt_core: -.byte 243,15,30,251 leal 608(%ebp),%ebx movl 240(%edx),%eax movdqa %xmm6,%xmm1 @@ -247,7 +244,6 @@ _vpaes_decrypt_core: .type _vpaes_schedule_core,@function .align 16 _vpaes_schedule_core: -.byte 243,15,30,251 addl (%esp),%ebp movdqu (%esi),%xmm0 movdqa 320(%ebp),%xmm2 @@ -342,7 +338,6 @@ _vpaes_schedule_core: .type _vpaes_schedule_192_smear,@function .align 16 _vpaes_schedule_192_smear: -.byte 243,15,30,251 pshufd $128,%xmm6,%xmm1 pshufd $254,%xmm7,%xmm0 pxor %xmm1,%xmm6 @@ -355,7 +350,6 @@ _vpaes_schedule_192_smear: .type _vpaes_schedule_round,@function .align 16 _vpaes_schedule_round: -.byte 243,15,30,251 movdqa 8(%esp),%xmm2 pxor %xmm1,%xmm1 .byte 102,15,58,15,202,15 @@ -405,7 +399,6 @@ _vpaes_schedule_round: .type _vpaes_schedule_transform,@function .align 16 _vpaes_schedule_transform: -.byte 243,15,30,251 movdqa -16(%ebp),%xmm2 movdqa %xmm2,%xmm1 pandn %xmm0,%xmm1 @@ -421,7 +414,6 @@ _vpaes_schedule_transform: .type _vpaes_schedule_mangle,@function .align 16 _vpaes_schedule_mangle: -.byte 243,15,30,251 movdqa %xmm0,%xmm4 movdqa 128(%ebp),%xmm5 testl %edi,%edi @@ -483,7 +475,6 @@ _vpaes_schedule_mangle: .align 16 vpaes_set_encrypt_key: .L_vpaes_set_encrypt_key_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -517,7 +508,6 @@ vpaes_set_encrypt_key: .align 16 vpaes_set_decrypt_key: .L_vpaes_set_decrypt_key_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -556,7 +546,6 @@ vpaes_set_decrypt_key: .align 16 vpaes_encrypt: .L_vpaes_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -586,7 +575,6 @@ vpaes_encrypt: .align 16 vpaes_decrypt: .L_vpaes_decrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -616,7 +604,6 @@ vpaes_decrypt: .align 16 vpaes_cbc_encrypt: .L_vpaes_cbc_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -684,21 +671,4 @@ vpaes_cbc_encrypt: ret .size vpaes_cbc_encrypt,.-.L_vpaes_cbc_encrypt_begin - .section ".note.gnu.property", "a" - .p2align 2 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - .asciz "GNU" -1: - .p2align 2 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 2 -4: - .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/elf/aes-ssse3-x86_64.s b/lib/accelerated/x86/elf/aes-ssse3-x86_64.s index 5a3f336..ea1216b 100644 --- a/lib/accelerated/x86/elf/aes-ssse3-x86_64.s +++ b/lib/accelerated/x86/elf/aes-ssse3-x86_64.s @@ -635,7 +635,6 @@ _vpaes_schedule_mangle: .align 16 vpaes_set_encrypt_key: .cfi_startproc -.byte 243,15,30,250 movl %esi,%eax shrl $5,%eax addl $5,%eax @@ -654,7 +653,6 @@ vpaes_set_encrypt_key: .align 16 vpaes_set_decrypt_key: .cfi_startproc -.byte 243,15,30,250 movl %esi,%eax shrl $5,%eax addl $5,%eax @@ -678,7 +676,6 @@ vpaes_set_decrypt_key: .align 16 vpaes_encrypt: .cfi_startproc -.byte 243,15,30,250 movdqu (%rdi),%xmm0 call _vpaes_preheat call _vpaes_encrypt_core @@ -692,7 +689,6 @@ vpaes_encrypt: .align 16 vpaes_decrypt: .cfi_startproc -.byte 243,15,30,250 movdqu (%rdi),%xmm0 call _vpaes_preheat call _vpaes_decrypt_core @@ -705,7 +701,6 @@ vpaes_decrypt: .align 16 vpaes_cbc_encrypt: .cfi_startproc -.byte 243,15,30,250 xchgq %rcx,%rdx subq $16,%rcx jc .Lcbc_abort @@ -868,26 +863,5 @@ _vpaes_consts: .byte 86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105,111,110,32,65,69,83,32,102,111,114,32,120,56,54,95,54,52,47,83,83,83,69,51,44,32,77,105,107,101,32,72,97,109,98,117,114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105,118,101,114,115,105,116,121,41,0 .align 64 .size _vpaes_consts,.-_vpaes_consts - .section ".note.gnu.property", "a" - .p2align 3 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - # "GNU" encoded with .byte, since .asciz isn't supported - # on Solaris. - .byte 0x47 - .byte 0x4e - .byte 0x55 - .byte 0 -1: - .p2align 3 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 3 -4: .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/elf/aesni-gcm-x86_64.s b/lib/accelerated/x86/elf/aesni-gcm-x86_64.s index 1a11222..e26d18d 100644 --- a/lib/accelerated/x86/elf/aesni-gcm-x86_64.s +++ b/lib/accelerated/x86/elf/aesni-gcm-x86_64.s @@ -42,8 +42,6 @@ .type _aesni_ctr32_ghash_6x,@function .align 32 _aesni_ctr32_ghash_6x: -.cfi_startproc -.byte 243,15,30,250 vmovdqu 32(%r11),%xmm2 subq $6,%rdx vpxor %xmm4,%xmm4,%xmm4 @@ -351,14 +349,12 @@ _aesni_ctr32_ghash_6x: vpxor %xmm4,%xmm8,%xmm8 .byte 0xf3,0xc3 -.cfi_endproc .size _aesni_ctr32_ghash_6x,.-_aesni_ctr32_ghash_6x .globl aesni_gcm_decrypt .type aesni_gcm_decrypt,@function .align 32 aesni_gcm_decrypt: .cfi_startproc -.byte 243,15,30,250 xorq %r10,%r10 cmpq $0x60,%rdx jb .Lgcm_dec_abort @@ -459,8 +455,6 @@ aesni_gcm_decrypt: .type _aesni_ctr32_6x,@function .align 32 _aesni_ctr32_6x: -.cfi_startproc -.byte 243,15,30,250 vmovdqu 0-128(%rcx),%xmm4 vmovdqu 32(%r11),%xmm2 leaq -1(%rbp),%r13 @@ -547,7 +541,6 @@ _aesni_ctr32_6x: vpshufb %xmm0,%xmm1,%xmm1 vpxor %xmm4,%xmm14,%xmm14 jmp .Loop_ctr32 -.cfi_endproc .size _aesni_ctr32_6x,.-_aesni_ctr32_6x .globl aesni_gcm_encrypt @@ -555,7 +548,6 @@ _aesni_ctr32_6x: .align 32 aesni_gcm_encrypt: .cfi_startproc -.byte 243,15,30,250 xorq %r10,%r10 cmpq $288,%rdx jb .Lgcm_enc_abort @@ -830,26 +822,5 @@ aesni_gcm_encrypt: .byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .byte 65,69,83,45,78,73,32,71,67,77,32,109,111,100,117,108,101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .align 64 - .section ".note.gnu.property", "a" - .p2align 3 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - # "GNU" encoded with .byte, since .asciz isn't supported - # on Solaris. - .byte 0x47 - .byte 0x4e - .byte 0x55 - .byte 0 -1: - .p2align 3 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 3 -4: .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/elf/aesni-x86.s b/lib/accelerated/x86/elf/aesni-x86.s index f41d5f9..6e48602 100644 --- a/lib/accelerated/x86/elf/aesni-x86.s +++ b/lib/accelerated/x86/elf/aesni-x86.s @@ -43,7 +43,6 @@ .align 16 aesni_encrypt: .L_aesni_encrypt_begin: -.byte 243,15,30,251 movl 4(%esp),%eax movl 12(%esp),%edx movups (%eax),%xmm2 @@ -71,7 +70,6 @@ aesni_encrypt: .align 16 aesni_decrypt: .L_aesni_decrypt_begin: -.byte 243,15,30,251 movl 4(%esp),%eax movl 12(%esp),%edx movups (%eax),%xmm2 @@ -97,7 +95,6 @@ aesni_decrypt: .type _aesni_encrypt2,@function .align 16 _aesni_encrypt2: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -125,7 +122,6 @@ _aesni_encrypt2: .type _aesni_decrypt2,@function .align 16 _aesni_decrypt2: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -153,7 +149,6 @@ _aesni_decrypt2: .type _aesni_encrypt3,@function .align 16 _aesni_encrypt3: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -186,7 +181,6 @@ _aesni_encrypt3: .type _aesni_decrypt3,@function .align 16 _aesni_decrypt3: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -219,7 +213,6 @@ _aesni_decrypt3: .type _aesni_encrypt4,@function .align 16 _aesni_encrypt4: -.byte 243,15,30,251 movups (%edx),%xmm0 movups 16(%edx),%xmm1 shll $4,%ecx @@ -258,7 +251,6 @@ _aesni_encrypt4: .type _aesni_decrypt4,@function .align 16 _aesni_decrypt4: -.byte 243,15,30,251 movups (%edx),%xmm0 movups 16(%edx),%xmm1 shll $4,%ecx @@ -297,7 +289,6 @@ _aesni_decrypt4: .type _aesni_encrypt6,@function .align 16 _aesni_encrypt6: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -352,7 +343,6 @@ _aesni_encrypt6: .type _aesni_decrypt6,@function .align 16 _aesni_decrypt6: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -409,7 +399,6 @@ _aesni_decrypt6: .align 16 aesni_ecb_encrypt: .L_aesni_ecb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -645,7 +634,6 @@ aesni_ecb_encrypt: .align 16 aesni_ccm64_encrypt_blocks: .L_aesni_ccm64_encrypt_blocks_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -734,7 +722,6 @@ aesni_ccm64_encrypt_blocks: .align 16 aesni_ccm64_decrypt_blocks: .L_aesni_ccm64_decrypt_blocks_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -858,7 +845,6 @@ aesni_ccm64_decrypt_blocks: .align 16 aesni_ctr32_encrypt_blocks: .L_aesni_ctr32_encrypt_blocks_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -1097,7 +1083,6 @@ aesni_ctr32_encrypt_blocks: .align 16 aesni_xts_encrypt: .L_aesni_xts_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -1458,7 +1443,6 @@ aesni_xts_encrypt: .align 16 aesni_xts_decrypt: .L_aesni_xts_decrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -1849,7 +1833,6 @@ aesni_xts_decrypt: .align 16 aesni_ocb_encrypt: .L_aesni_ocb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -2245,7 +2228,6 @@ aesni_ocb_encrypt: .align 16 aesni_ocb_decrypt: .L_aesni_ocb_decrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -2641,7 +2623,6 @@ aesni_ocb_decrypt: .align 16 aesni_cbc_encrypt: .L_aesni_cbc_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -2901,7 +2882,6 @@ aesni_cbc_encrypt: .type _aesni_set_encrypt_key,@function .align 16 _aesni_set_encrypt_key: -.byte 243,15,30,251 pushl %ebp pushl %ebx testl %eax,%eax @@ -3237,7 +3217,6 @@ _aesni_set_encrypt_key: .align 16 aesni_set_encrypt_key: .L_aesni_set_encrypt_key_begin: -.byte 243,15,30,251 movl 4(%esp),%eax movl 8(%esp),%ecx movl 12(%esp),%edx @@ -3249,7 +3228,6 @@ aesni_set_encrypt_key: .align 16 aesni_set_decrypt_key: .L_aesni_set_decrypt_key_begin: -.byte 243,15,30,251 movl 4(%esp),%eax movl 8(%esp),%ecx movl 12(%esp),%edx @@ -3297,21 +3275,4 @@ aesni_set_decrypt_key: .byte 115,108,46,111,114,103,62,0 .comm _gnutls_x86_cpuid_s,16,4 - .section ".note.gnu.property", "a" - .p2align 2 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - .asciz "GNU" -1: - .p2align 2 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 2 -4: - .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/elf/aesni-x86_64.s b/lib/accelerated/x86/elf/aesni-x86_64.s index e3f9d5a..43cf4e6 100644 --- a/lib/accelerated/x86/elf/aesni-x86_64.s +++ b/lib/accelerated/x86/elf/aesni-x86_64.s @@ -44,7 +44,6 @@ .align 16 aesni_encrypt: .cfi_startproc -.byte 243,15,30,250 movups (%rdi),%xmm2 movl 240(%rdx),%eax movups (%rdx),%xmm0 @@ -71,7 +70,6 @@ aesni_encrypt: .align 16 aesni_decrypt: .cfi_startproc -.byte 243,15,30,250 movups (%rdi),%xmm2 movl 240(%rdx),%eax movups (%rdx),%xmm0 @@ -559,7 +557,6 @@ _aesni_decrypt8: .align 16 aesni_ecb_encrypt: .cfi_startproc -.byte 243,15,30,250 andq $-16,%rdx jz .Lecb_ret @@ -903,8 +900,6 @@ aesni_ecb_encrypt: .type aesni_ccm64_encrypt_blocks,@function .align 16 aesni_ccm64_encrypt_blocks: -.cfi_startproc -.byte 243,15,30,250 movl 240(%rcx),%eax movdqu (%r8),%xmm6 movdqa .Lincrement64(%rip),%xmm9 @@ -963,14 +958,11 @@ aesni_ccm64_encrypt_blocks: pxor %xmm8,%xmm8 pxor %xmm6,%xmm6 .byte 0xf3,0xc3 -.cfi_endproc .size aesni_ccm64_encrypt_blocks,.-aesni_ccm64_encrypt_blocks .globl aesni_ccm64_decrypt_blocks .type aesni_ccm64_decrypt_blocks,@function .align 16 aesni_ccm64_decrypt_blocks: -.cfi_startproc -.byte 243,15,30,250 movl 240(%rcx),%eax movups (%r8),%xmm6 movdqu (%r9),%xmm3 @@ -1063,14 +1055,12 @@ aesni_ccm64_decrypt_blocks: pxor %xmm8,%xmm8 pxor %xmm6,%xmm6 .byte 0xf3,0xc3 -.cfi_endproc .size aesni_ccm64_decrypt_blocks,.-aesni_ccm64_decrypt_blocks .globl aesni_ctr32_encrypt_blocks .type aesni_ctr32_encrypt_blocks,@function .align 16 aesni_ctr32_encrypt_blocks: .cfi_startproc -.byte 243,15,30,250 cmpq $1,%rdx jne .Lctr32_bulk @@ -1649,7 +1639,6 @@ aesni_ctr32_encrypt_blocks: .align 16 aesni_xts_encrypt: .cfi_startproc -.byte 243,15,30,250 leaq (%rsp),%r11 .cfi_def_cfa_register %r11 pushq %rbp @@ -2120,7 +2109,6 @@ aesni_xts_encrypt: .align 16 aesni_xts_decrypt: .cfi_startproc -.byte 243,15,30,250 leaq (%rsp),%r11 .cfi_def_cfa_register %r11 pushq %rbp @@ -2628,7 +2616,6 @@ aesni_xts_decrypt: .align 32 aesni_ocb_encrypt: .cfi_startproc -.byte 243,15,30,250 leaq (%rsp),%rax pushq %rbx .cfi_adjust_cfa_offset 8 @@ -2842,7 +2829,6 @@ aesni_ocb_encrypt: .type __ocb_encrypt6,@function .align 32 __ocb_encrypt6: -.cfi_startproc pxor %xmm9,%xmm15 movdqu (%rbx,%r12,1),%xmm11 movdqa %xmm10,%xmm12 @@ -2940,13 +2926,11 @@ __ocb_encrypt6: .byte 102,65,15,56,221,246 .byte 102,65,15,56,221,255 .byte 0xf3,0xc3 -.cfi_endproc .size __ocb_encrypt6,.-__ocb_encrypt6 .type __ocb_encrypt4,@function .align 32 __ocb_encrypt4: -.cfi_startproc pxor %xmm9,%xmm15 movdqu (%rbx,%r12,1),%xmm11 movdqa %xmm10,%xmm12 @@ -3011,13 +2995,11 @@ __ocb_encrypt4: .byte 102,65,15,56,221,228 .byte 102,65,15,56,221,237 .byte 0xf3,0xc3 -.cfi_endproc .size __ocb_encrypt4,.-__ocb_encrypt4 .type __ocb_encrypt1,@function .align 32 __ocb_encrypt1: -.cfi_startproc pxor %xmm15,%xmm7 pxor %xmm9,%xmm7 pxor %xmm2,%xmm8 @@ -3048,7 +3030,6 @@ __ocb_encrypt1: .byte 102,15,56,221,215 .byte 0xf3,0xc3 -.cfi_endproc .size __ocb_encrypt1,.-__ocb_encrypt1 .globl aesni_ocb_decrypt @@ -3056,7 +3037,6 @@ __ocb_encrypt1: .align 32 aesni_ocb_decrypt: .cfi_startproc -.byte 243,15,30,250 leaq (%rsp),%rax pushq %rbx .cfi_adjust_cfa_offset 8 @@ -3292,7 +3272,6 @@ aesni_ocb_decrypt: .type __ocb_decrypt6,@function .align 32 __ocb_decrypt6: -.cfi_startproc pxor %xmm9,%xmm15 movdqu (%rbx,%r12,1),%xmm11 movdqa %xmm10,%xmm12 @@ -3384,13 +3363,11 @@ __ocb_decrypt6: .byte 102,65,15,56,223,246 .byte 102,65,15,56,223,255 .byte 0xf3,0xc3 -.cfi_endproc .size __ocb_decrypt6,.-__ocb_decrypt6 .type __ocb_decrypt4,@function .align 32 __ocb_decrypt4: -.cfi_startproc pxor %xmm9,%xmm15 movdqu (%rbx,%r12,1),%xmm11 movdqa %xmm10,%xmm12 @@ -3451,13 +3428,11 @@ __ocb_decrypt4: .byte 102,65,15,56,223,228 .byte 102,65,15,56,223,237 .byte 0xf3,0xc3 -.cfi_endproc .size __ocb_decrypt4,.-__ocb_decrypt4 .type __ocb_decrypt1,@function .align 32 __ocb_decrypt1: -.cfi_startproc pxor %xmm15,%xmm7 pxor %xmm9,%xmm7 pxor %xmm7,%xmm2 @@ -3487,14 +3462,12 @@ __ocb_decrypt1: .byte 102,15,56,223,215 .byte 0xf3,0xc3 -.cfi_endproc .size __ocb_decrypt1,.-__ocb_decrypt1 .globl aesni_cbc_encrypt .type aesni_cbc_encrypt,@function .align 16 aesni_cbc_encrypt: .cfi_startproc -.byte 243,15,30,250 testq %rdx,%rdx jz .Lcbc_ret @@ -4427,6 +4400,7 @@ __aesni_set_encrypt_key: addq $8,%rsp .cfi_adjust_cfa_offset -8 .byte 0xf3,0xc3 +.cfi_endproc .LSEH_end_set_encrypt_key: .align 16 @@ -4497,7 +4471,6 @@ __aesni_set_encrypt_key: shufps $170,%xmm1,%xmm1 xorps %xmm1,%xmm2 .byte 0xf3,0xc3 -.cfi_endproc .size aesni_set_encrypt_key,.-aesni_set_encrypt_key .size __aesni_set_encrypt_key,.-__aesni_set_encrypt_key .align 64 @@ -4522,26 +4495,5 @@ __aesni_set_encrypt_key: .byte 65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69,83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .align 64 - .section ".note.gnu.property", "a" - .p2align 3 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - # "GNU" encoded with .byte, since .asciz isn't supported - # on Solaris. - .byte 0x47 - .byte 0x4e - .byte 0x55 - .byte 0 -1: - .p2align 3 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 3 -4: .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/elf/e_padlock-x86.s b/lib/accelerated/x86/elf/e_padlock-x86.s index dd56518..ed8681e 100644 --- a/lib/accelerated/x86/elf/e_padlock-x86.s +++ b/lib/accelerated/x86/elf/e_padlock-x86.s @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2016, Andy Polyakov +# Copyright (c) 2011-2013, Andy Polyakov # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -37,13 +37,13 @@ # # *** This file is auto-generated *** # +.file "devel/perlasm/e_padlock-x86.s" .text .globl padlock_capability .type padlock_capability,@function .align 16 padlock_capability: .L_padlock_capability_begin: -.byte 243,15,30,251 pushl %ebx pushfl popl %eax @@ -60,20 +60,11 @@ padlock_capability: .byte 0x0f,0xa2 xorl %eax,%eax cmpl $0x746e6543,%ebx - jne .L001zhaoxin + jne .L000noluck cmpl $0x48727561,%edx jne .L000noluck cmpl $0x736c7561,%ecx jne .L000noluck - jmp .L002zhaoxinEnd -.L001zhaoxin: - cmpl $0x68532020,%ebx - jne .L000noluck - cmpl $0x68676e61,%edx - jne .L000noluck - cmpl $0x20206961,%ecx - jne .L000noluck -.L002zhaoxinEnd: movl $3221225472,%eax .byte 0x0f,0xa2 movl %eax,%edx @@ -104,16 +95,15 @@ padlock_capability: .align 16 padlock_key_bswap: .L_padlock_key_bswap_begin: -.byte 243,15,30,251 movl 4(%esp),%edx movl 240(%edx),%ecx -.L003bswap_loop: +.L001bswap_loop: movl (%edx),%eax bswap %eax movl %eax,(%edx) leal 4(%edx),%edx subl $1,%ecx - jnz .L003bswap_loop + jnz .L001bswap_loop ret .size padlock_key_bswap,.-.L_padlock_key_bswap_begin .globl padlock_verify_context @@ -121,27 +111,25 @@ padlock_key_bswap: .align 16 padlock_verify_context: .L_padlock_verify_context_begin: -.byte 243,15,30,251 movl 4(%esp),%edx - leal .Lpadlock_saved_context-.L004verify_pic_point,%eax + leal .Lpadlock_saved_context-.L002verify_pic_point,%eax pushfl call _padlock_verify_ctx -.L004verify_pic_point: +.L002verify_pic_point: leal 4(%esp),%esp ret .size padlock_verify_context,.-.L_padlock_verify_context_begin .type _padlock_verify_ctx,@function .align 16 _padlock_verify_ctx: -.byte 243,15,30,251 addl (%esp),%eax btl $30,4(%esp) - jnc .L005verified + jnc .L003verified cmpl (%eax),%edx - je .L005verified + je .L003verified pushfl popfl -.L005verified: +.L003verified: movl %edx,(%eax) ret .size _padlock_verify_ctx,.-_padlock_verify_ctx @@ -150,7 +138,6 @@ _padlock_verify_ctx: .align 16 padlock_reload_key: .L_padlock_reload_key_begin: -.byte 243,15,30,251 pushfl popfl ret @@ -160,7 +147,6 @@ padlock_reload_key: .align 16 padlock_aes_block: .L_padlock_aes_block_begin: -.byte 243,15,30,251 pushl %edi pushl %esi pushl %ebx @@ -181,7 +167,6 @@ padlock_aes_block: .align 16 padlock_ecb_encrypt: .L_padlock_ecb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -191,25 +176,25 @@ padlock_ecb_encrypt: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz .L006ecb_abort + jnz .L004ecb_abort testl $15,%ecx - jnz .L006ecb_abort - leal .Lpadlock_saved_context-.L007ecb_pic_point,%eax + jnz .L004ecb_abort + leal .Lpadlock_saved_context-.L005ecb_pic_point,%eax pushfl cld call _padlock_verify_ctx -.L007ecb_pic_point: +.L005ecb_pic_point: leal 16(%edx),%edx xorl %eax,%eax xorl %ebx,%ebx testl $32,(%edx) - jnz .L008ecb_aligned + jnz .L006ecb_aligned testl $15,%edi setz %al testl $15,%esi setz %bl testl %ebx,%eax - jnz .L008ecb_aligned + jnz .L006ecb_aligned negl %eax movl $512,%ebx notl %eax @@ -228,7 +213,7 @@ padlock_ecb_encrypt: andl $-16,%esp movl %eax,16(%ebp) cmpl %ebx,%ecx - ja .L009ecb_loop + ja .L007ecb_loop movl %esi,%eax cmpl %esp,%ebp cmovel %edi,%eax @@ -239,10 +224,10 @@ padlock_ecb_encrypt: movl $-128,%eax cmovael %ebx,%eax andl %eax,%ebx - jz .L010ecb_unaligned_tail - jmp .L009ecb_loop + jz .L008ecb_unaligned_tail + jmp .L007ecb_loop .align 16 -.L009ecb_loop: +.L007ecb_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -251,13 +236,13 @@ padlock_ecb_encrypt: testl $15,%edi cmovnzl %esp,%edi testl $15,%esi - jz .L011ecb_inp_aligned + jz .L009ecb_inp_aligned shrl $2,%ecx .byte 243,165 subl %ebx,%edi movl %ebx,%ecx movl %edi,%esi -.L011ecb_inp_aligned: +.L009ecb_inp_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -265,23 +250,23 @@ padlock_ecb_encrypt: movl (%ebp),%edi movl 12(%ebp),%ebx testl $15,%edi - jz .L012ecb_out_aligned + jz .L010ecb_out_aligned movl %ebx,%ecx leal (%esp),%esi shrl $2,%ecx .byte 243,165 subl %ebx,%edi -.L012ecb_out_aligned: +.L010ecb_out_aligned: movl 4(%ebp),%esi movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jz .L013ecb_break + jz .L011ecb_break cmpl %ebx,%ecx - jae .L009ecb_loop -.L010ecb_unaligned_tail: + jae .L007ecb_loop +.L008ecb_unaligned_tail: xorl %eax,%eax cmpl %ebp,%esp cmovel %ecx,%eax @@ -294,24 +279,24 @@ padlock_ecb_encrypt: movl %esp,%esi movl %eax,%edi movl %ebx,%ecx - jmp .L009ecb_loop + jmp .L007ecb_loop .align 16 -.L013ecb_break: +.L011ecb_break: cmpl %ebp,%esp - je .L014ecb_done + je .L012ecb_done pxor %xmm0,%xmm0 leal (%esp),%eax -.L015ecb_bzero: +.L013ecb_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja .L015ecb_bzero -.L014ecb_done: + ja .L013ecb_bzero +.L012ecb_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp - jmp .L016ecb_exit + jmp .L014ecb_exit .align 16 -.L008ecb_aligned: +.L006ecb_aligned: leal (%esi,%ecx,1),%ebp negl %ebp andl $4095,%ebp @@ -321,14 +306,14 @@ padlock_ecb_encrypt: cmovael %eax,%ebp andl %ecx,%ebp subl %ebp,%ecx - jz .L017ecb_aligned_tail + jz .L015ecb_aligned_tail leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx .byte 243,15,167,200 testl %ebp,%ebp - jz .L016ecb_exit -.L017ecb_aligned_tail: + jz .L014ecb_exit +.L015ecb_aligned_tail: movl %ebp,%ecx leal -24(%esp),%ebp movl %ebp,%esp @@ -345,11 +330,11 @@ padlock_ecb_encrypt: movl %esp,%esi movl %eax,%edi movl %ebx,%ecx - jmp .L009ecb_loop -.L016ecb_exit: + jmp .L007ecb_loop +.L014ecb_exit: movl $1,%eax leal 4(%esp),%esp -.L006ecb_abort: +.L004ecb_abort: popl %edi popl %esi popl %ebx @@ -361,7 +346,6 @@ padlock_ecb_encrypt: .align 16 padlock_cbc_encrypt: .L_padlock_cbc_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -371,25 +355,25 @@ padlock_cbc_encrypt: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz .L018cbc_abort + jnz .L016cbc_abort testl $15,%ecx - jnz .L018cbc_abort - leal .Lpadlock_saved_context-.L019cbc_pic_point,%eax + jnz .L016cbc_abort + leal .Lpadlock_saved_context-.L017cbc_pic_point,%eax pushfl cld call _padlock_verify_ctx -.L019cbc_pic_point: +.L017cbc_pic_point: leal 16(%edx),%edx xorl %eax,%eax xorl %ebx,%ebx testl $32,(%edx) - jnz .L020cbc_aligned + jnz .L018cbc_aligned testl $15,%edi setz %al testl $15,%esi setz %bl testl %ebx,%eax - jnz .L020cbc_aligned + jnz .L018cbc_aligned negl %eax movl $512,%ebx notl %eax @@ -408,7 +392,7 @@ padlock_cbc_encrypt: andl $-16,%esp movl %eax,16(%ebp) cmpl %ebx,%ecx - ja .L021cbc_loop + ja .L019cbc_loop movl %esi,%eax cmpl %esp,%ebp cmovel %edi,%eax @@ -419,10 +403,10 @@ padlock_cbc_encrypt: movl $-64,%eax cmovael %ebx,%eax andl %eax,%ebx - jz .L022cbc_unaligned_tail - jmp .L021cbc_loop + jz .L020cbc_unaligned_tail + jmp .L019cbc_loop .align 16 -.L021cbc_loop: +.L019cbc_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -431,13 +415,13 @@ padlock_cbc_encrypt: testl $15,%edi cmovnzl %esp,%edi testl $15,%esi - jz .L023cbc_inp_aligned + jz .L021cbc_inp_aligned shrl $2,%ecx .byte 243,165 subl %ebx,%edi movl %ebx,%ecx movl %edi,%esi -.L023cbc_inp_aligned: +.L021cbc_inp_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -447,23 +431,23 @@ padlock_cbc_encrypt: movl (%ebp),%edi movl 12(%ebp),%ebx testl $15,%edi - jz .L024cbc_out_aligned + jz .L022cbc_out_aligned movl %ebx,%ecx leal (%esp),%esi shrl $2,%ecx .byte 243,165 subl %ebx,%edi -.L024cbc_out_aligned: +.L022cbc_out_aligned: movl 4(%ebp),%esi movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jz .L025cbc_break + jz .L023cbc_break cmpl %ebx,%ecx - jae .L021cbc_loop -.L022cbc_unaligned_tail: + jae .L019cbc_loop +.L020cbc_unaligned_tail: xorl %eax,%eax cmpl %ebp,%esp cmovel %ecx,%eax @@ -476,24 +460,24 @@ padlock_cbc_encrypt: movl %esp,%esi movl %eax,%edi movl %ebx,%ecx - jmp .L021cbc_loop + jmp .L019cbc_loop .align 16 -.L025cbc_break: +.L023cbc_break: cmpl %ebp,%esp - je .L026cbc_done + je .L024cbc_done pxor %xmm0,%xmm0 leal (%esp),%eax -.L027cbc_bzero: +.L025cbc_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja .L027cbc_bzero -.L026cbc_done: + ja .L025cbc_bzero +.L024cbc_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp - jmp .L028cbc_exit + jmp .L026cbc_exit .align 16 -.L020cbc_aligned: +.L018cbc_aligned: leal (%esi,%ecx,1),%ebp negl %ebp andl $4095,%ebp @@ -503,7 +487,7 @@ padlock_cbc_encrypt: cmovael %eax,%ebp andl %ecx,%ebp subl %ebp,%ecx - jz .L029cbc_aligned_tail + jz .L027cbc_aligned_tail leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -511,8 +495,8 @@ padlock_cbc_encrypt: movaps (%eax),%xmm0 movaps %xmm0,-16(%edx) testl %ebp,%ebp - jz .L028cbc_exit -.L029cbc_aligned_tail: + jz .L026cbc_exit +.L027cbc_aligned_tail: movl %ebp,%ecx leal -24(%esp),%ebp movl %ebp,%esp @@ -529,11 +513,11 @@ padlock_cbc_encrypt: movl %esp,%esi movl %eax,%edi movl %ebx,%ecx - jmp .L021cbc_loop -.L028cbc_exit: + jmp .L019cbc_loop +.L026cbc_exit: movl $1,%eax leal 4(%esp),%esp -.L018cbc_abort: +.L016cbc_abort: popl %edi popl %esi popl %ebx @@ -545,7 +529,6 @@ padlock_cbc_encrypt: .align 16 padlock_cfb_encrypt: .L_padlock_cfb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -555,25 +538,25 @@ padlock_cfb_encrypt: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz .L030cfb_abort + jnz .L028cfb_abort testl $15,%ecx - jnz .L030cfb_abort - leal .Lpadlock_saved_context-.L031cfb_pic_point,%eax + jnz .L028cfb_abort + leal .Lpadlock_saved_context-.L029cfb_pic_point,%eax pushfl cld call _padlock_verify_ctx -.L031cfb_pic_point: +.L029cfb_pic_point: leal 16(%edx),%edx xorl %eax,%eax xorl %ebx,%ebx testl $32,(%edx) - jnz .L032cfb_aligned + jnz .L030cfb_aligned testl $15,%edi setz %al testl $15,%esi setz %bl testl %ebx,%eax - jnz .L032cfb_aligned + jnz .L030cfb_aligned negl %eax movl $512,%ebx notl %eax @@ -591,9 +574,9 @@ padlock_cfb_encrypt: andl $-16,%ebp andl $-16,%esp movl %eax,16(%ebp) - jmp .L033cfb_loop + jmp .L031cfb_loop .align 16 -.L033cfb_loop: +.L031cfb_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -602,13 +585,13 @@ padlock_cfb_encrypt: testl $15,%edi cmovnzl %esp,%edi testl $15,%esi - jz .L034cfb_inp_aligned + jz .L032cfb_inp_aligned shrl $2,%ecx .byte 243,165 subl %ebx,%edi movl %ebx,%ecx movl %edi,%esi -.L034cfb_inp_aligned: +.L032cfb_inp_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -618,45 +601,45 @@ padlock_cfb_encrypt: movl (%ebp),%edi movl 12(%ebp),%ebx testl $15,%edi - jz .L035cfb_out_aligned + jz .L033cfb_out_aligned movl %ebx,%ecx leal (%esp),%esi shrl $2,%ecx .byte 243,165 subl %ebx,%edi -.L035cfb_out_aligned: +.L033cfb_out_aligned: movl 4(%ebp),%esi movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jnz .L033cfb_loop + jnz .L031cfb_loop cmpl %ebp,%esp - je .L036cfb_done + je .L034cfb_done pxor %xmm0,%xmm0 leal (%esp),%eax -.L037cfb_bzero: +.L035cfb_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja .L037cfb_bzero -.L036cfb_done: + ja .L035cfb_bzero +.L034cfb_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp - jmp .L038cfb_exit + jmp .L036cfb_exit .align 16 -.L032cfb_aligned: +.L030cfb_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx .byte 243,15,167,224 movaps (%eax),%xmm0 movaps %xmm0,-16(%edx) -.L038cfb_exit: +.L036cfb_exit: movl $1,%eax leal 4(%esp),%esp -.L030cfb_abort: +.L028cfb_abort: popl %edi popl %esi popl %ebx @@ -668,7 +651,6 @@ padlock_cfb_encrypt: .align 16 padlock_ofb_encrypt: .L_padlock_ofb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -678,25 +660,25 @@ padlock_ofb_encrypt: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz .L039ofb_abort + jnz .L037ofb_abort testl $15,%ecx - jnz .L039ofb_abort - leal .Lpadlock_saved_context-.L040ofb_pic_point,%eax + jnz .L037ofb_abort + leal .Lpadlock_saved_context-.L038ofb_pic_point,%eax pushfl cld call _padlock_verify_ctx -.L040ofb_pic_point: +.L038ofb_pic_point: leal 16(%edx),%edx xorl %eax,%eax xorl %ebx,%ebx testl $32,(%edx) - jnz .L041ofb_aligned + jnz .L039ofb_aligned testl $15,%edi setz %al testl $15,%esi setz %bl testl %ebx,%eax - jnz .L041ofb_aligned + jnz .L039ofb_aligned negl %eax movl $512,%ebx notl %eax @@ -714,9 +696,9 @@ padlock_ofb_encrypt: andl $-16,%ebp andl $-16,%esp movl %eax,16(%ebp) - jmp .L042ofb_loop + jmp .L040ofb_loop .align 16 -.L042ofb_loop: +.L040ofb_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -725,13 +707,13 @@ padlock_ofb_encrypt: testl $15,%edi cmovnzl %esp,%edi testl $15,%esi - jz .L043ofb_inp_aligned + jz .L041ofb_inp_aligned shrl $2,%ecx .byte 243,165 subl %ebx,%edi movl %ebx,%ecx movl %edi,%esi -.L043ofb_inp_aligned: +.L041ofb_inp_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -741,45 +723,45 @@ padlock_ofb_encrypt: movl (%ebp),%edi movl 12(%ebp),%ebx testl $15,%edi - jz .L044ofb_out_aligned + jz .L042ofb_out_aligned movl %ebx,%ecx leal (%esp),%esi shrl $2,%ecx .byte 243,165 subl %ebx,%edi -.L044ofb_out_aligned: +.L042ofb_out_aligned: movl 4(%ebp),%esi movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jnz .L042ofb_loop + jnz .L040ofb_loop cmpl %ebp,%esp - je .L045ofb_done + je .L043ofb_done pxor %xmm0,%xmm0 leal (%esp),%eax -.L046ofb_bzero: +.L044ofb_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja .L046ofb_bzero -.L045ofb_done: + ja .L044ofb_bzero +.L043ofb_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp - jmp .L047ofb_exit + jmp .L045ofb_exit .align 16 -.L041ofb_aligned: +.L039ofb_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx .byte 243,15,167,232 movaps (%eax),%xmm0 movaps %xmm0,-16(%edx) -.L047ofb_exit: +.L045ofb_exit: movl $1,%eax leal 4(%esp),%esp -.L039ofb_abort: +.L037ofb_abort: popl %edi popl %esi popl %ebx @@ -791,7 +773,6 @@ padlock_ofb_encrypt: .align 16 padlock_ctr32_encrypt: .L_padlock_ctr32_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -801,14 +782,14 @@ padlock_ctr32_encrypt: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz .L048ctr32_abort + jnz .L046ctr32_abort testl $15,%ecx - jnz .L048ctr32_abort - leal .Lpadlock_saved_context-.L049ctr32_pic_point,%eax + jnz .L046ctr32_abort + leal .Lpadlock_saved_context-.L047ctr32_pic_point,%eax pushfl cld call _padlock_verify_ctx -.L049ctr32_pic_point: +.L047ctr32_pic_point: leal 16(%edx),%edx xorl %eax,%eax movq -16(%edx),%mm0 @@ -828,9 +809,9 @@ padlock_ctr32_encrypt: andl $-16,%ebp andl $-16,%esp movl %eax,16(%ebp) - jmp .L050ctr32_loop + jmp .L048ctr32_loop .align 16 -.L050ctr32_loop: +.L048ctr32_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -839,7 +820,7 @@ padlock_ctr32_encrypt: movl -4(%edx),%ecx xorl %edi,%edi movl -8(%edx),%eax -.L051ctr32_prepare: +.L049ctr32_prepare: movl %ecx,12(%esp,%edi,1) bswap %ecx movq %mm0,(%esp,%edi,1) @@ -848,7 +829,7 @@ padlock_ctr32_encrypt: bswap %ecx leal 16(%edi),%edi cmpl %ebx,%edi - jb .L051ctr32_prepare + jb .L049ctr32_prepare movl %ecx,-4(%edx) leal (%esp),%esi leal (%esp),%edi @@ -861,33 +842,33 @@ padlock_ctr32_encrypt: movl 12(%ebp),%ebx movl 4(%ebp),%esi xorl %ecx,%ecx -.L052ctr32_xor: +.L050ctr32_xor: movups (%esi,%ecx,1),%xmm1 leal 16(%ecx),%ecx pxor -16(%esp,%ecx,1),%xmm1 movups %xmm1,-16(%edi,%ecx,1) cmpl %ebx,%ecx - jb .L052ctr32_xor + jb .L050ctr32_xor movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jnz .L050ctr32_loop + jnz .L048ctr32_loop pxor %xmm0,%xmm0 leal (%esp),%eax -.L053ctr32_bzero: +.L051ctr32_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja .L053ctr32_bzero -.L054ctr32_done: + ja .L051ctr32_bzero +.L052ctr32_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp movl $1,%eax leal 4(%esp),%esp emms -.L048ctr32_abort: +.L046ctr32_abort: popl %edi popl %esi popl %ebx @@ -899,7 +880,6 @@ padlock_ctr32_encrypt: .align 16 padlock_xstore: .L_padlock_xstore_begin: -.byte 243,15,30,251 pushl %edi movl 8(%esp),%edi movl 12(%esp),%edx @@ -910,15 +890,14 @@ padlock_xstore: .type _win32_segv_handler,@function .align 16 _win32_segv_handler: -.byte 243,15,30,251 movl $1,%eax movl 4(%esp),%edx movl 12(%esp),%ecx cmpl $3221225477,(%edx) - jne .L055ret + jne .L053ret addl $4,184(%ecx) movl $0,%eax -.L055ret: +.L053ret: ret .size _win32_segv_handler,.-_win32_segv_handler .globl padlock_sha1_oneshot @@ -926,7 +905,6 @@ _win32_segv_handler: .align 16 padlock_sha1_oneshot: .L_padlock_sha1_oneshot_begin: -.byte 243,15,30,251 pushl %edi pushl %esi xorl %eax,%eax @@ -958,7 +936,6 @@ padlock_sha1_oneshot: .align 16 padlock_sha1_blocks: .L_padlock_sha1_blocks_begin: -.byte 243,15,30,251 pushl %edi pushl %esi movl 12(%esp),%edi @@ -989,7 +966,6 @@ padlock_sha1_blocks: .align 16 padlock_sha256_oneshot: .L_padlock_sha256_oneshot_begin: -.byte 243,15,30,251 pushl %edi pushl %esi xorl %eax,%eax @@ -1021,7 +997,6 @@ padlock_sha256_oneshot: .align 16 padlock_sha256_blocks: .L_padlock_sha256_blocks_begin: -.byte 243,15,30,251 pushl %edi pushl %esi movl 12(%esp),%edi @@ -1052,7 +1027,6 @@ padlock_sha256_blocks: .align 16 padlock_sha512_blocks: .L_padlock_sha512_blocks_begin: -.byte 243,15,30,251 pushl %edi pushl %esi movl 12(%esp),%edi @@ -1095,21 +1069,7 @@ padlock_sha512_blocks: .Lpadlock_saved_context: .long 0 - .section ".note.gnu.property", "a" - .p2align 2 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - .asciz "GNU" -1: - .p2align 2 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 2 -4: .section .note.GNU-stack,"",%progbits + + diff --git a/lib/accelerated/x86/elf/e_padlock-x86_64.s b/lib/accelerated/x86/elf/e_padlock-x86_64.s index f92da75..c161f0a 100644 --- a/lib/accelerated/x86/elf/e_padlock-x86_64.s +++ b/lib/accelerated/x86/elf/e_padlock-x86_64.s @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2016, Andy Polyakov +# Copyright (c) 2011-2013, Andy Polyakov # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -42,50 +42,36 @@ .type padlock_capability,@function .align 16 padlock_capability: -.cfi_startproc -.byte 243,15,30,250 movq %rbx,%r8 xorl %eax,%eax cpuid xorl %eax,%eax - cmpl $0x746e6543,%ebx - jne .Lzhaoxin - cmpl $0x48727561,%edx + cmpl $1953391939,%ebx jne .Lnoluck - cmpl $0x736c7561,%ecx + cmpl $1215460705,%edx jne .Lnoluck - jmp .LzhaoxinEnd -.Lzhaoxin: - cmpl $0x68532020,%ebx + cmpl $1936487777,%ecx jne .Lnoluck - cmpl $0x68676e61,%edx - jne .Lnoluck - cmpl $0x20206961,%ecx - jne .Lnoluck -.LzhaoxinEnd: - movl $0xC0000000,%eax + movl $3221225472,%eax cpuid movl %eax,%edx xorl %eax,%eax - cmpl $0xC0000001,%edx + cmpl $3221225473,%edx jb .Lnoluck - movl $0xC0000001,%eax + movl $3221225473,%eax cpuid movl %edx,%eax - andl $0xffffffef,%eax - orl $0x10,%eax + andl $4294967279,%eax + orl $16,%eax .Lnoluck: movq %r8,%rbx .byte 0xf3,0xc3 -.cfi_endproc .size padlock_capability,.-padlock_capability .globl padlock_key_bswap .type padlock_key_bswap,@function .align 16 padlock_key_bswap: -.cfi_startproc -.byte 243,15,30,250 movl 240(%rdi),%edx .Lbswap_loop: movl (%rdi),%eax @@ -95,29 +81,23 @@ padlock_key_bswap: subl $1,%edx jnz .Lbswap_loop .byte 0xf3,0xc3 -.cfi_endproc .size padlock_key_bswap,.-padlock_key_bswap .globl padlock_verify_context .type padlock_verify_context,@function .align 16 padlock_verify_context: -.cfi_startproc -.byte 243,15,30,250 movq %rdi,%rdx pushf leaq .Lpadlock_saved_context(%rip),%rax call _padlock_verify_ctx leaq 8(%rsp),%rsp .byte 0xf3,0xc3 -.cfi_endproc .size padlock_verify_context,.-padlock_verify_context .type _padlock_verify_ctx,@function .align 16 _padlock_verify_ctx: -.cfi_startproc -.byte 243,15,30,250 movq 8(%rsp),%r8 btq $30,%r8 jnc .Lverified @@ -128,55 +108,43 @@ _padlock_verify_ctx: .Lverified: movq %rdx,(%rax) .byte 0xf3,0xc3 -.cfi_endproc .size _padlock_verify_ctx,.-_padlock_verify_ctx .globl padlock_reload_key .type padlock_reload_key,@function .align 16 padlock_reload_key: -.cfi_startproc -.byte 243,15,30,250 pushf popf .byte 0xf3,0xc3 -.cfi_endproc .size padlock_reload_key,.-padlock_reload_key .globl padlock_aes_block .type padlock_aes_block,@function .align 16 padlock_aes_block: -.cfi_startproc -.byte 243,15,30,250 movq %rbx,%r8 movq $1,%rcx leaq 32(%rdx),%rbx leaq 16(%rdx),%rdx -.byte 0xf3,0x0f,0xa7,0xc8 +.byte 0xf3,0x0f,0xa7,0xc8 movq %r8,%rbx .byte 0xf3,0xc3 -.cfi_endproc .size padlock_aes_block,.-padlock_aes_block .globl padlock_xstore .type padlock_xstore,@function .align 16 padlock_xstore: -.cfi_startproc -.byte 243,15,30,250 movl %esi,%edx -.byte 0x0f,0xa7,0xc0 +.byte 0x0f,0xa7,0xc0 .byte 0xf3,0xc3 -.cfi_endproc .size padlock_xstore,.-padlock_xstore .globl padlock_sha1_oneshot .type padlock_sha1_oneshot,@function .align 16 padlock_sha1_oneshot: -.cfi_startproc -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -186,22 +154,19 @@ padlock_sha1_oneshot: movq %rsp,%rdi movl %eax,16(%rsp) xorq %rax,%rax -.byte 0xf3,0x0f,0xa6,0xc8 +.byte 0xf3,0x0f,0xa6,0xc8 movaps (%rsp),%xmm0 movl 16(%rsp),%eax addq $128+8,%rsp movups %xmm0,(%rdx) movl %eax,16(%rdx) .byte 0xf3,0xc3 -.cfi_endproc .size padlock_sha1_oneshot,.-padlock_sha1_oneshot .globl padlock_sha1_blocks .type padlock_sha1_blocks,@function .align 16 padlock_sha1_blocks: -.cfi_startproc -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -211,22 +176,19 @@ padlock_sha1_blocks: movq %rsp,%rdi movl %eax,16(%rsp) movq $-1,%rax -.byte 0xf3,0x0f,0xa6,0xc8 +.byte 0xf3,0x0f,0xa6,0xc8 movaps (%rsp),%xmm0 movl 16(%rsp),%eax addq $128+8,%rsp movups %xmm0,(%rdx) movl %eax,16(%rdx) .byte 0xf3,0xc3 -.cfi_endproc .size padlock_sha1_blocks,.-padlock_sha1_blocks .globl padlock_sha256_oneshot .type padlock_sha256_oneshot,@function .align 16 padlock_sha256_oneshot: -.cfi_startproc -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -236,22 +198,19 @@ padlock_sha256_oneshot: movq %rsp,%rdi movaps %xmm1,16(%rsp) xorq %rax,%rax -.byte 0xf3,0x0f,0xa6,0xd0 +.byte 0xf3,0x0f,0xa6,0xd0 movaps (%rsp),%xmm0 movaps 16(%rsp),%xmm1 addq $128+8,%rsp movups %xmm0,(%rdx) movups %xmm1,16(%rdx) .byte 0xf3,0xc3 -.cfi_endproc .size padlock_sha256_oneshot,.-padlock_sha256_oneshot .globl padlock_sha256_blocks .type padlock_sha256_blocks,@function .align 16 padlock_sha256_blocks: -.cfi_startproc -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -261,22 +220,19 @@ padlock_sha256_blocks: movq %rsp,%rdi movaps %xmm1,16(%rsp) movq $-1,%rax -.byte 0xf3,0x0f,0xa6,0xd0 +.byte 0xf3,0x0f,0xa6,0xd0 movaps (%rsp),%xmm0 movaps 16(%rsp),%xmm1 addq $128+8,%rsp movups %xmm0,(%rdx) movups %xmm1,16(%rdx) .byte 0xf3,0xc3 -.cfi_endproc .size padlock_sha256_blocks,.-padlock_sha256_blocks .globl padlock_sha512_blocks .type padlock_sha512_blocks,@function .align 16 padlock_sha512_blocks: -.cfi_startproc -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -289,7 +245,7 @@ padlock_sha512_blocks: movaps %xmm1,16(%rsp) movaps %xmm2,32(%rsp) movaps %xmm3,48(%rsp) -.byte 0xf3,0x0f,0xa6,0xe0 +.byte 0xf3,0x0f,0xa6,0xe0 movaps (%rsp),%xmm0 movaps 16(%rsp),%xmm1 movaps 32(%rsp),%xmm2 @@ -300,14 +256,11 @@ padlock_sha512_blocks: movups %xmm2,32(%rdx) movups %xmm3,48(%rdx) .byte 0xf3,0xc3 -.cfi_endproc .size padlock_sha512_blocks,.-padlock_sha512_blocks .globl padlock_ecb_encrypt .type padlock_ecb_encrypt,@function .align 16 padlock_ecb_encrypt: -.cfi_startproc -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -325,9 +278,9 @@ padlock_ecb_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz .Lecb_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz .Lecb_aligned @@ -351,7 +304,7 @@ padlock_ecb_encrypt: cmoveq %rdi,%rax addq %rcx,%rax negq %rax - andq $0xfff,%rax + andq $4095,%rax cmpq $128,%rax movq $-128,%rax cmovaeq %rbx,%rax @@ -367,12 +320,12 @@ padlock_ecb_encrypt: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz .Lecb_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -380,15 +333,15 @@ padlock_ecb_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,200 +.byte 0xf3,0x0f,0xa7,200 movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz .Lecb_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi .Lecb_out_aligned: movq %r9,%rsi @@ -409,7 +362,7 @@ padlock_ecb_encrypt: subq %rax,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 movq %rsp,%rsi movq %r8,%rdi movq %rbx,%rcx @@ -435,7 +388,7 @@ padlock_ecb_encrypt: .Lecb_aligned: leaq (%rsi,%rcx,1),%rbp negq %rbp - andq $0xfff,%rbp + andq $4095,%rbp xorl %eax,%eax cmpq $128,%rbp movq $128-1,%rbp @@ -446,7 +399,7 @@ padlock_ecb_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,200 +.byte 0xf3,0x0f,0xa7,200 testq %rbp,%rbp jz .Lecb_exit @@ -458,7 +411,7 @@ padlock_ecb_encrypt: subq %rcx,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 leaq (%r8),%rdi leaq (%rsp),%rsi movq %rbx,%rcx @@ -470,14 +423,11 @@ padlock_ecb_encrypt: popq %rbx popq %rbp .byte 0xf3,0xc3 -.cfi_endproc .size padlock_ecb_encrypt,.-padlock_ecb_encrypt .globl padlock_cbc_encrypt .type padlock_cbc_encrypt,@function .align 16 padlock_cbc_encrypt: -.cfi_startproc -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -495,9 +445,9 @@ padlock_cbc_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz .Lcbc_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz .Lcbc_aligned @@ -521,7 +471,7 @@ padlock_cbc_encrypt: cmoveq %rdi,%rax addq %rcx,%rax negq %rax - andq $0xfff,%rax + andq $4095,%rax cmpq $64,%rax movq $-64,%rax cmovaeq %rbx,%rax @@ -537,12 +487,12 @@ padlock_cbc_encrypt: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz .Lcbc_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -550,17 +500,17 @@ padlock_cbc_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,208 +.byte 0xf3,0x0f,0xa7,208 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz .Lcbc_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi .Lcbc_out_aligned: movq %r9,%rsi @@ -581,7 +531,7 @@ padlock_cbc_encrypt: subq %rax,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 movq %rsp,%rsi movq %r8,%rdi movq %rbx,%rcx @@ -607,7 +557,7 @@ padlock_cbc_encrypt: .Lcbc_aligned: leaq (%rsi,%rcx,1),%rbp negq %rbp - andq $0xfff,%rbp + andq $4095,%rbp xorl %eax,%eax cmpq $64,%rbp movq $64-1,%rbp @@ -618,7 +568,7 @@ padlock_cbc_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,208 +.byte 0xf3,0x0f,0xa7,208 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) testq %rbp,%rbp @@ -632,7 +582,7 @@ padlock_cbc_encrypt: subq %rcx,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 leaq (%r8),%rdi leaq (%rsp),%rsi movq %rbx,%rcx @@ -644,14 +594,11 @@ padlock_cbc_encrypt: popq %rbx popq %rbp .byte 0xf3,0xc3 -.cfi_endproc .size padlock_cbc_encrypt,.-padlock_cbc_encrypt .globl padlock_cfb_encrypt .type padlock_cfb_encrypt,@function .align 16 padlock_cfb_encrypt: -.cfi_startproc -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -669,9 +616,9 @@ padlock_cfb_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz .Lcfb_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz .Lcfb_aligned @@ -698,12 +645,12 @@ padlock_cfb_encrypt: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz .Lcfb_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -711,17 +658,17 @@ padlock_cfb_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,224 +.byte 0xf3,0x0f,0xa7,224 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz .Lcfb_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi .Lcfb_out_aligned: movq %r9,%rsi @@ -751,7 +698,7 @@ padlock_cfb_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,224 +.byte 0xf3,0x0f,0xa7,224 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) .Lcfb_exit: @@ -761,14 +708,11 @@ padlock_cfb_encrypt: popq %rbx popq %rbp .byte 0xf3,0xc3 -.cfi_endproc .size padlock_cfb_encrypt,.-padlock_cfb_encrypt .globl padlock_ofb_encrypt .type padlock_ofb_encrypt,@function .align 16 padlock_ofb_encrypt: -.cfi_startproc -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -786,9 +730,9 @@ padlock_ofb_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz .Lofb_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz .Lofb_aligned @@ -815,12 +759,12 @@ padlock_ofb_encrypt: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz .Lofb_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -828,17 +772,17 @@ padlock_ofb_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,232 +.byte 0xf3,0x0f,0xa7,232 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz .Lofb_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi .Lofb_out_aligned: movq %r9,%rsi @@ -868,7 +812,7 @@ padlock_ofb_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,232 +.byte 0xf3,0x0f,0xa7,232 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) .Lofb_exit: @@ -878,14 +822,11 @@ padlock_ofb_encrypt: popq %rbx popq %rbp .byte 0xf3,0xc3 -.cfi_endproc .size padlock_ofb_encrypt,.-padlock_ofb_encrypt .globl padlock_ctr32_encrypt .type padlock_ctr32_encrypt,@function .align 16 padlock_ctr32_encrypt: -.cfi_startproc -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -903,9 +844,9 @@ padlock_ctr32_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz .Lctr32_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz .Lctr32_aligned @@ -940,7 +881,7 @@ padlock_ctr32_encrypt: cmoveq %rdi,%rax addq %rcx,%rax negq %rax - andq $0xfff,%rax + andq $4095,%rax cmpq $32,%rax movq $-32,%rax cmovaeq %rbx,%rax @@ -956,12 +897,12 @@ padlock_ctr32_encrypt: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz .Lctr32_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -969,23 +910,23 @@ padlock_ctr32_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,216 +.byte 0xf3,0x0f,0xa7,216 movl -4(%rdx),%eax - testl $0xffff0000,%eax + testl $4294901760,%eax jnz .Lctr32_no_carry bswapl %eax - addl $0x10000,%eax + addl $65536,%eax bswapl %eax movl %eax,-4(%rdx) .Lctr32_no_carry: movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz .Lctr32_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi .Lctr32_out_aligned: movq %r9,%rsi @@ -1003,7 +944,7 @@ padlock_ctr32_encrypt: cmoveq %rdi,%rax addq %rcx,%rax negq %rax - andq $0xfff,%rax + andq $4095,%rax cmpq $32,%rax movq $-32,%rax cmovaeq %rbx,%rax @@ -1018,7 +959,7 @@ padlock_ctr32_encrypt: subq %rax,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 movq %rsp,%rsi movq %r8,%rdi movq %rbx,%rcx @@ -1045,7 +986,7 @@ padlock_ctr32_encrypt: movl -4(%rdx),%eax bswapl %eax negl %eax - andl $0xffff,%eax + andl $65535,%eax movq $1048576,%rbx shll $4,%eax cmovzq %rbx,%rax @@ -1062,11 +1003,11 @@ padlock_ctr32_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,216 +.byte 0xf3,0x0f,0xa7,216 movl -4(%rdx),%eax bswapl %eax - addl $0x10000,%eax + addl $65536,%eax bswapl %eax movl %eax,-4(%rdx) @@ -1080,7 +1021,7 @@ padlock_ctr32_encrypt: .Lctr32_aligned_skip: leaq (%rsi,%rcx,1),%rbp negq %rbp - andq $0xfff,%rbp + andq $4095,%rbp xorl %eax,%eax cmpq $32,%rbp movq $32-1,%rbp @@ -1091,7 +1032,7 @@ padlock_ctr32_encrypt: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,216 +.byte 0xf3,0x0f,0xa7,216 testq %rbp,%rbp jz .Lctr32_exit @@ -1103,7 +1044,7 @@ padlock_ctr32_encrypt: subq %rcx,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 leaq (%r8),%rdi leaq (%rsp),%rsi movq %rbx,%rcx @@ -1115,7 +1056,6 @@ padlock_ctr32_encrypt: popq %rbx popq %rbp .byte 0xf3,0xc3 -.cfi_endproc .size padlock_ctr32_encrypt,.-padlock_ctr32_encrypt .byte 86,73,65,32,80,97,100,108,111,99,107,32,120,56,54,95,54,52,32,109,111,100,117,108,101,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .align 16 @@ -1123,26 +1063,8 @@ padlock_ctr32_encrypt: .align 8 .Lpadlock_saved_context: .quad 0 - .section ".note.gnu.property", "a" - .p2align 3 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - # "GNU" encoded with .byte, since .asciz isn't supported - # on Solaris. - .byte 0x47 - .byte 0x4e - .byte 0x55 - .byte 0 -1: - .p2align 3 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 3 -4: + .section .note.GNU-stack,"",%progbits + + diff --git a/lib/accelerated/x86/elf/ghash-x86_64.s b/lib/accelerated/x86/elf/ghash-x86_64.s index 8da3f29..1e4d18b 100644 --- a/lib/accelerated/x86/elf/ghash-x86_64.s +++ b/lib/accelerated/x86/elf/ghash-x86_64.s @@ -45,7 +45,6 @@ .align 16 gcm_gmult_4bit: .cfi_startproc -.byte 243,15,30,250 pushq %rbx .cfi_adjust_cfa_offset 8 .cfi_offset %rbx,-16 @@ -157,7 +156,6 @@ gcm_gmult_4bit: .align 16 gcm_ghash_4bit: .cfi_startproc -.byte 243,15,30,250 pushq %rbx .cfi_adjust_cfa_offset 8 .cfi_offset %rbx,-16 @@ -905,7 +903,6 @@ gcm_init_clmul: .align 16 gcm_gmult_clmul: .cfi_startproc -.byte 243,15,30,250 .L_gmult_clmul: movdqu (%rdi),%xmm0 movdqa .Lbswap_mask(%rip),%xmm5 @@ -959,7 +956,6 @@ gcm_gmult_clmul: .align 32 gcm_ghash_clmul: .cfi_startproc -.byte 243,15,30,250 .L_ghash_clmul: movdqa .Lbswap_mask(%rip),%xmm10 @@ -1454,7 +1450,6 @@ gcm_init_avx: .align 32 gcm_gmult_avx: .cfi_startproc -.byte 243,15,30,250 jmp .L_gmult_clmul .cfi_endproc .size gcm_gmult_avx,.-gcm_gmult_avx @@ -1463,7 +1458,6 @@ gcm_gmult_avx: .align 32 gcm_ghash_avx: .cfi_startproc -.byte 243,15,30,250 vzeroupper vmovdqu (%rdi),%xmm10 @@ -1890,26 +1884,5 @@ gcm_ghash_avx: .byte 71,72,65,83,72,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .align 64 - .section ".note.gnu.property", "a" - .p2align 3 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - # "GNU" encoded with .byte, since .asciz isn't supported - # on Solaris. - .byte 0x47 - .byte 0x4e - .byte 0x55 - .byte 0 -1: - .p2align 3 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 3 -4: .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/elf/sha1-ssse3-x86.s b/lib/accelerated/x86/elf/sha1-ssse3-x86.s index 57b6ba5..8bfbcb6 100644 --- a/lib/accelerated/x86/elf/sha1-ssse3-x86.s +++ b/lib/accelerated/x86/elf/sha1-ssse3-x86.s @@ -43,7 +43,6 @@ .align 16 sha1_block_data_order: .L_sha1_block_data_order_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -1418,21 +1417,4 @@ sha1_block_data_order: .byte 89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112 .byte 114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 - .section ".note.gnu.property", "a" - .p2align 2 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - .asciz "GNU" -1: - .p2align 2 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 2 -4: - .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/elf/sha1-ssse3-x86_64.s b/lib/accelerated/x86/elf/sha1-ssse3-x86_64.s index 5409505..1e6546e 100644 --- a/lib/accelerated/x86/elf/sha1-ssse3-x86_64.s +++ b/lib/accelerated/x86/elf/sha1-ssse3-x86_64.s @@ -1460,8 +1460,8 @@ _shaext_shortcut: pshufd $27,%xmm1,%xmm1 movdqu %xmm0,(%rdi) movd %xmm1,16(%rdi) - .byte 0xf3,0xc3 .cfi_endproc + .byte 0xf3,0xc3 .size sha1_block_data_order_shaext,.-sha1_block_data_order_shaext .type sha1_block_data_order_ssse3,@function .align 16 @@ -5487,26 +5487,5 @@ K_XX_XX: .byte 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0 .byte 83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .align 64 - .section ".note.gnu.property", "a" - .p2align 3 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - # "GNU" encoded with .byte, since .asciz isn't supported - # on Solaris. - .byte 0x47 - .byte 0x4e - .byte 0x55 - .byte 0 -1: - .p2align 3 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 3 -4: .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/elf/sha256-ssse3-x86.s b/lib/accelerated/x86/elf/sha256-ssse3-x86.s index 6d16b91..8d9aaa4 100644 --- a/lib/accelerated/x86/elf/sha256-ssse3-x86.s +++ b/lib/accelerated/x86/elf/sha256-ssse3-x86.s @@ -43,7 +43,6 @@ .align 16 sha256_block_data_order: .L_sha256_block_data_order_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -3385,21 +3384,4 @@ sha256_block_data_order: ret .size sha256_block_data_order,.-.L_sha256_block_data_order_begin - .section ".note.gnu.property", "a" - .p2align 2 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - .asciz "GNU" -1: - .p2align 2 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 2 -4: - .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/elf/sha256-ssse3-x86_64.s b/lib/accelerated/x86/elf/sha256-ssse3-x86_64.s index 1514ee4..4b08e0c 100644 --- a/lib/accelerated/x86/elf/sha256-ssse3-x86_64.s +++ b/lib/accelerated/x86/elf/sha256-ssse3-x86_64.s @@ -1814,7 +1814,6 @@ K256: .align 64 sha256_block_data_order_shaext: _shaext_shortcut: -.cfi_startproc leaq K256+128(%rip),%rcx movdqu (%rdi),%xmm1 movdqu 16(%rdi),%xmm2 @@ -2017,7 +2016,6 @@ _shaext_shortcut: movdqu %xmm1,(%rdi) movdqu %xmm2,16(%rdi) .byte 0xf3,0xc3 -.cfi_endproc .size sha256_block_data_order_shaext,.-sha256_block_data_order_shaext .type sha256_block_data_order_ssse3,@function .align 64 @@ -4279,15 +4277,7 @@ sha256_block_data_order_avx2: vmovdqa %ymm4,0(%rsp) xorl %r14d,%r14d vmovdqa %ymm5,32(%rsp) - - movq 88(%rsp),%rdi -.cfi_def_cfa %rdi,8 leaq -64(%rsp),%rsp - - - - movq %rdi,-8(%rsp) -.cfi_escape 0x0f,0x05,0x77,0x78,0x06,0x23,0x08 movl %ebx,%edi vmovdqa %ymm6,0(%rsp) xorl %ecx,%edi @@ -4299,12 +4289,6 @@ sha256_block_data_order_avx2: .align 16 .Lavx2_00_47: leaq -64(%rsp),%rsp -.cfi_escape 0x0f,0x05,0x77,0x38,0x06,0x23,0x08 - - pushq 64-8(%rsp) -.cfi_escape 0x0f,0x05,0x77,0x00,0x06,0x23,0x08 - leaq 8(%rsp),%rsp -.cfi_escape 0x0f,0x05,0x77,0x78,0x06,0x23,0x08 vpalignr $4,%ymm0,%ymm1,%ymm4 addl 0+128(%rsp),%r11d andl %r8d,%r12d @@ -4560,12 +4544,6 @@ sha256_block_data_order_avx2: movl %r9d,%r12d vmovdqa %ymm6,32(%rsp) leaq -64(%rsp),%rsp -.cfi_escape 0x0f,0x05,0x77,0x38,0x06,0x23,0x08 - - pushq 64-8(%rsp) -.cfi_escape 0x0f,0x05,0x77,0x00,0x06,0x23,0x08 - leaq 8(%rsp),%rsp -.cfi_escape 0x0f,0x05,0x77,0x78,0x06,0x23,0x08 vpalignr $4,%ymm2,%ymm3,%ymm4 addl 0+128(%rsp),%r11d andl %r8d,%r12d @@ -5441,8 +5419,6 @@ sha256_block_data_order_avx2: leaq 448(%rsp),%rsp -.cfi_escape 0x0f,0x06,0x77,0xd8,0x00,0x06,0x23,0x08 - addl 0(%rdi),%eax addl 4(%rdi),%ebx addl 8(%rdi),%ecx @@ -5468,11 +5444,9 @@ sha256_block_data_order_avx2: jbe .Loop_avx2 leaq (%rsp),%rbp - -.cfi_escape 0x0f,0x06,0x76,0xd8,0x00,0x06,0x23,0x08 - .Ldone_avx2: - movq 88(%rbp),%rsi + leaq (%rbp),%rsp + movq 88(%rsp),%rsi .cfi_def_cfa %rsi,8 vzeroupper movq -48(%rsi),%r15 @@ -5493,26 +5467,5 @@ sha256_block_data_order_avx2: .byte 0xf3,0xc3 .cfi_endproc .size sha256_block_data_order_avx2,.-sha256_block_data_order_avx2 - .section ".note.gnu.property", "a" - .p2align 3 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - # "GNU" encoded with .byte, since .asciz isn't supported - # on Solaris. - .byte 0x47 - .byte 0x4e - .byte 0x55 - .byte 0 -1: - .p2align 3 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 3 -4: .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/elf/sha512-ssse3-x86.s b/lib/accelerated/x86/elf/sha512-ssse3-x86.s index afca4ea..481c777 100644 --- a/lib/accelerated/x86/elf/sha512-ssse3-x86.s +++ b/lib/accelerated/x86/elf/sha512-ssse3-x86.s @@ -43,7 +43,6 @@ .align 16 sha512_block_data_order: .L_sha512_block_data_order_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -603,21 +602,4 @@ sha512_block_data_order: .byte 112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103 .byte 62,0 - .section ".note.gnu.property", "a" - .p2align 2 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - .asciz "GNU" -1: - .p2align 2 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 2 -4: - .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/elf/sha512-ssse3-x86_64.s b/lib/accelerated/x86/elf/sha512-ssse3-x86_64.s index a7be2cd..e384d7e 100644 --- a/lib/accelerated/x86/elf/sha512-ssse3-x86_64.s +++ b/lib/accelerated/x86/elf/sha512-ssse3-x86_64.s @@ -4204,15 +4204,7 @@ sha512_block_data_order_avx2: vmovdqa %ymm10,64(%rsp) vpaddq 64(%rbp),%ymm6,%ymm10 vmovdqa %ymm11,96(%rsp) - - movq 152(%rsp),%rdi -.cfi_def_cfa %rdi,8 leaq -128(%rsp),%rsp - - - - movq %rdi,-8(%rsp) -.cfi_escape 0x0f,0x05,0x77,0x78,0x06,0x23,0x08 vpaddq 96(%rbp),%ymm7,%ymm11 vmovdqa %ymm8,0(%rsp) xorq %r14,%r14 @@ -4228,12 +4220,6 @@ sha512_block_data_order_avx2: .align 16 .Lavx2_00_47: leaq -128(%rsp),%rsp -.cfi_escape 0x0f,0x06,0x77,0xf8,0x00,0x06,0x23,0x08 - - pushq 128-8(%rsp) -.cfi_escape 0x0f,0x05,0x77,0x00,0x06,0x23,0x08 - leaq 8(%rsp),%rsp -.cfi_escape 0x0f,0x05,0x77,0x78,0x06,0x23,0x08 vpalignr $8,%ymm0,%ymm1,%ymm8 addq 0+256(%rsp),%r11 andq %r8,%r12 @@ -4527,12 +4513,6 @@ sha512_block_data_order_avx2: movq %r9,%r12 vmovdqa %ymm10,96(%rsp) leaq -128(%rsp),%rsp -.cfi_escape 0x0f,0x06,0x77,0xf8,0x00,0x06,0x23,0x08 - - pushq 128-8(%rsp) -.cfi_escape 0x0f,0x05,0x77,0x00,0x06,0x23,0x08 - leaq 8(%rsp),%rsp -.cfi_escape 0x0f,0x05,0x77,0x78,0x06,0x23,0x08 vpalignr $8,%ymm4,%ymm5,%ymm8 addq 0+256(%rsp),%r11 andq %r8,%r12 @@ -5446,8 +5426,6 @@ sha512_block_data_order_avx2: leaq 1152(%rsp),%rsp -.cfi_escape 0x0f,0x06,0x77,0x98,0x01,0x06,0x23,0x08 - addq 0(%rdi),%rax addq 8(%rdi),%rbx addq 16(%rdi),%rcx @@ -5473,11 +5451,9 @@ sha512_block_data_order_avx2: jbe .Loop_avx2 leaq (%rsp),%rbp - -.cfi_escape 0x0f,0x06,0x76,0x98,0x01,0x06,0x23,0x08 - .Ldone_avx2: - movq 152(%rbp),%rsi + leaq (%rbp),%rsp + movq 152(%rsp),%rsi .cfi_def_cfa %rsi,8 vzeroupper movq -48(%rsi),%r15 @@ -5498,26 +5474,5 @@ sha512_block_data_order_avx2: .byte 0xf3,0xc3 .cfi_endproc .size sha512_block_data_order_avx2,.-sha512_block_data_order_avx2 - .section ".note.gnu.property", "a" - .p2align 3 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - # "GNU" encoded with .byte, since .asciz isn't supported - # on Solaris. - .byte 0x47 - .byte 0x4e - .byte 0x55 - .byte 0 -1: - .p2align 3 - .long 0xc0000002 - .long 3f - 2f -2: - .long 3 -3: - .p2align 3 -4: .section .note.GNU-stack,"",%progbits diff --git a/lib/accelerated/x86/macosx/aes-ssse3-x86.s b/lib/accelerated/x86/macosx/aes-ssse3-x86.s index 6cc2b03..4be8992 100644 --- a/lib/accelerated/x86/macosx/aes-ssse3-x86.s +++ b/lib/accelerated/x86/macosx/aes-ssse3-x86.s @@ -70,14 +70,12 @@ L_vpaes_consts: .align 6,0x90 .align 4 __vpaes_preheat: -.byte 243,15,30,251 addl (%esp),%ebp movdqa -48(%ebp),%xmm7 movdqa -16(%ebp),%xmm6 ret .align 4 __vpaes_encrypt_core: -.byte 243,15,30,251 movl $16,%ecx movl 240(%edx),%eax movdqa %xmm6,%xmm1 @@ -153,7 +151,6 @@ L000enc_entry: ret .align 4 __vpaes_decrypt_core: -.byte 243,15,30,251 leal 608(%ebp),%ebx movl 240(%edx),%eax movdqa %xmm6,%xmm1 @@ -240,7 +237,6 @@ L002dec_entry: ret .align 4 __vpaes_schedule_core: -.byte 243,15,30,251 addl (%esp),%ebp movdqu (%esi),%xmm0 movdqa 320(%ebp),%xmm2 @@ -333,7 +329,6 @@ L013schedule_mangle_last_dec: ret .align 4 __vpaes_schedule_192_smear: -.byte 243,15,30,251 pshufd $128,%xmm6,%xmm1 pshufd $254,%xmm7,%xmm0 pxor %xmm1,%xmm6 @@ -344,7 +339,6 @@ __vpaes_schedule_192_smear: ret .align 4 __vpaes_schedule_round: -.byte 243,15,30,251 movdqa 8(%esp),%xmm2 pxor %xmm1,%xmm1 .byte 102,15,58,15,202,15 @@ -392,7 +386,6 @@ L_vpaes_schedule_low_round: ret .align 4 __vpaes_schedule_transform: -.byte 243,15,30,251 movdqa -16(%ebp),%xmm2 movdqa %xmm2,%xmm1 pandn %xmm0,%xmm1 @@ -406,7 +399,6 @@ __vpaes_schedule_transform: ret .align 4 __vpaes_schedule_mangle: -.byte 243,15,30,251 movdqa %xmm0,%xmm4 movdqa 128(%ebp),%xmm5 testl %edi,%edi @@ -466,7 +458,6 @@ L015schedule_mangle_both: .align 4 _vpaes_set_encrypt_key: L_vpaes_set_encrypt_key_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -498,7 +489,6 @@ L016pic_point: .align 4 _vpaes_set_decrypt_key: L_vpaes_set_decrypt_key_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -535,7 +525,6 @@ L017pic_point: .align 4 _vpaes_encrypt: L_vpaes_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -563,7 +552,6 @@ L018pic_point: .align 4 _vpaes_decrypt: L_vpaes_decrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -591,7 +579,6 @@ L019pic_point: .align 4 _vpaes_cbc_encrypt: L_vpaes_cbc_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi diff --git a/lib/accelerated/x86/macosx/aes-ssse3-x86_64.s b/lib/accelerated/x86/macosx/aes-ssse3-x86_64.s index c2e2f2e..3d5c652 100644 --- a/lib/accelerated/x86/macosx/aes-ssse3-x86_64.s +++ b/lib/accelerated/x86/macosx/aes-ssse3-x86_64.s @@ -635,7 +635,6 @@ L$schedule_mangle_both: .p2align 4 _vpaes_set_encrypt_key: -.byte 243,15,30,250 movl %esi,%eax shrl $5,%eax addl $5,%eax @@ -654,7 +653,6 @@ _vpaes_set_encrypt_key: .p2align 4 _vpaes_set_decrypt_key: -.byte 243,15,30,250 movl %esi,%eax shrl $5,%eax addl $5,%eax @@ -678,7 +676,6 @@ _vpaes_set_decrypt_key: .p2align 4 _vpaes_encrypt: -.byte 243,15,30,250 movdqu (%rdi),%xmm0 call _vpaes_preheat call _vpaes_encrypt_core @@ -692,7 +689,6 @@ _vpaes_encrypt: .p2align 4 _vpaes_decrypt: -.byte 243,15,30,250 movdqu (%rdi),%xmm0 call _vpaes_preheat call _vpaes_decrypt_core @@ -705,7 +701,6 @@ _vpaes_decrypt: .p2align 4 _vpaes_cbc_encrypt: -.byte 243,15,30,250 xchgq %rcx,%rdx subq $16,%rcx jc L$cbc_abort diff --git a/lib/accelerated/x86/macosx/aesni-gcm-x86_64.s b/lib/accelerated/x86/macosx/aesni-gcm-x86_64.s index be6d885..d540930 100644 --- a/lib/accelerated/x86/macosx/aesni-gcm-x86_64.s +++ b/lib/accelerated/x86/macosx/aesni-gcm-x86_64.s @@ -42,8 +42,6 @@ .p2align 5 _aesni_ctr32_ghash_6x: - -.byte 243,15,30,250 vmovdqu 32(%r11),%xmm2 subq $6,%rdx vpxor %xmm4,%xmm4,%xmm4 @@ -352,13 +350,11 @@ L$6x_done: .byte 0xf3,0xc3 - .globl _aesni_gcm_decrypt .p2align 5 _aesni_gcm_decrypt: -.byte 243,15,30,250 xorq %r10,%r10 cmpq $0x60,%rdx jb L$gcm_dec_abort @@ -459,8 +455,6 @@ L$gcm_dec_abort: .p2align 5 _aesni_ctr32_6x: - -.byte 243,15,30,250 vmovdqu 0-128(%rcx),%xmm4 vmovdqu 32(%r11),%xmm2 leaq -1(%rbp),%r13 @@ -549,13 +543,11 @@ L$handle_ctr32_2: jmp L$oop_ctr32 - .globl _aesni_gcm_encrypt .p2align 5 _aesni_gcm_encrypt: -.byte 243,15,30,250 xorq %r10,%r10 cmpq $288,%rdx jb L$gcm_enc_abort diff --git a/lib/accelerated/x86/macosx/aesni-x86.s b/lib/accelerated/x86/macosx/aesni-x86.s index 64e4e52..ee50089 100644 --- a/lib/accelerated/x86/macosx/aesni-x86.s +++ b/lib/accelerated/x86/macosx/aesni-x86.s @@ -42,7 +42,6 @@ .align 4 _aesni_encrypt: L_aesni_encrypt_begin: -.byte 243,15,30,251 movl 4(%esp),%eax movl 12(%esp),%edx movups (%eax),%xmm2 @@ -68,7 +67,6 @@ L000enc1_loop_1: .align 4 _aesni_decrypt: L_aesni_decrypt_begin: -.byte 243,15,30,251 movl 4(%esp),%eax movl 12(%esp),%edx movups (%eax),%xmm2 @@ -92,7 +90,6 @@ L001dec1_loop_2: ret .align 4 __aesni_encrypt2: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -118,7 +115,6 @@ L002enc2_loop: ret .align 4 __aesni_decrypt2: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -144,7 +140,6 @@ L003dec2_loop: ret .align 4 __aesni_encrypt3: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -175,7 +170,6 @@ L004enc3_loop: ret .align 4 __aesni_decrypt3: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -206,7 +200,6 @@ L005dec3_loop: ret .align 4 __aesni_encrypt4: -.byte 243,15,30,251 movups (%edx),%xmm0 movups 16(%edx),%xmm1 shll $4,%ecx @@ -243,7 +236,6 @@ L006enc4_loop: ret .align 4 __aesni_decrypt4: -.byte 243,15,30,251 movups (%edx),%xmm0 movups 16(%edx),%xmm1 shll $4,%ecx @@ -280,7 +272,6 @@ L007dec4_loop: ret .align 4 __aesni_encrypt6: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -333,7 +324,6 @@ L_aesni_encrypt6_enter: ret .align 4 __aesni_decrypt6: -.byte 243,15,30,251 movups (%edx),%xmm0 shll $4,%ecx movups 16(%edx),%xmm1 @@ -388,7 +378,6 @@ L_aesni_decrypt6_enter: .align 4 _aesni_ecb_encrypt: L_aesni_ecb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -622,7 +611,6 @@ L012ecb_ret: .align 4 _aesni_ccm64_encrypt_blocks: L_aesni_ccm64_encrypt_blocks_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -709,7 +697,6 @@ L031ccm64_enc2_loop: .align 4 _aesni_ccm64_decrypt_blocks: L_aesni_ccm64_decrypt_blocks_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -831,7 +818,6 @@ L036enc1_loop_6: .align 4 _aesni_ctr32_encrypt_blocks: L_aesni_ctr32_encrypt_blocks_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -1068,7 +1054,6 @@ L040ctr32_ret: .align 4 _aesni_xts_encrypt: L_aesni_xts_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -1427,7 +1412,6 @@ L056xts_enc_ret: .align 4 _aesni_xts_decrypt: L_aesni_xts_decrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -1816,7 +1800,6 @@ L069xts_dec_ret: .align 4 _aesni_ocb_encrypt: L_aesni_ocb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -2210,7 +2193,6 @@ L078done: .align 4 _aesni_ocb_decrypt: L_aesni_ocb_decrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -2604,7 +2586,6 @@ L088done: .align 4 _aesni_cbc_encrypt: L_aesni_cbc_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -2862,7 +2843,6 @@ L094cbc_abort: ret .align 4 __aesni_set_encrypt_key: -.byte 243,15,30,251 pushl %ebp pushl %ebx testl %eax,%eax @@ -3196,7 +3176,6 @@ L115bad_keybits: .align 4 _aesni_set_encrypt_key: L_aesni_set_encrypt_key_begin: -.byte 243,15,30,251 movl 4(%esp),%eax movl 8(%esp),%ecx movl 12(%esp),%edx @@ -3206,7 +3185,6 @@ L_aesni_set_encrypt_key_begin: .align 4 _aesni_set_decrypt_key: L_aesni_set_decrypt_key_begin: -.byte 243,15,30,251 movl 4(%esp),%eax movl 8(%esp),%ecx movl 12(%esp),%edx diff --git a/lib/accelerated/x86/macosx/aesni-x86_64.s b/lib/accelerated/x86/macosx/aesni-x86_64.s index 484122c..f6145f1 100644 --- a/lib/accelerated/x86/macosx/aesni-x86_64.s +++ b/lib/accelerated/x86/macosx/aesni-x86_64.s @@ -44,7 +44,6 @@ .p2align 4 _aesni_encrypt: -.byte 243,15,30,250 movups (%rdi),%xmm2 movl 240(%rdx),%eax movups (%rdx),%xmm0 @@ -71,7 +70,6 @@ L$oop_enc1_1: .p2align 4 _aesni_decrypt: -.byte 243,15,30,250 movups (%rdi),%xmm2 movl 240(%rdx),%eax movups (%rdx),%xmm0 @@ -559,7 +557,6 @@ L$dec_loop8_enter: .p2align 4 _aesni_ecb_encrypt: -.byte 243,15,30,250 andq $-16,%rdx jz L$ecb_ret @@ -903,8 +900,6 @@ L$ecb_ret: .p2align 4 _aesni_ccm64_encrypt_blocks: - -.byte 243,15,30,250 movl 240(%rcx),%eax movdqu (%r8),%xmm6 movdqa L$increment64(%rip),%xmm9 @@ -964,13 +959,10 @@ L$ccm64_enc2_loop: pxor %xmm6,%xmm6 .byte 0xf3,0xc3 - .globl _aesni_ccm64_decrypt_blocks .p2align 4 _aesni_ccm64_decrypt_blocks: - -.byte 243,15,30,250 movl 240(%rcx),%eax movups (%r8),%xmm6 movdqu (%r9),%xmm3 @@ -1064,13 +1056,11 @@ L$oop_enc1_6: pxor %xmm6,%xmm6 .byte 0xf3,0xc3 - .globl _aesni_ctr32_encrypt_blocks .p2align 4 _aesni_ctr32_encrypt_blocks: -.byte 243,15,30,250 cmpq $1,%rdx jne L$ctr32_bulk @@ -1649,7 +1639,6 @@ L$ctr32_epilogue: .p2align 4 _aesni_xts_encrypt: -.byte 243,15,30,250 leaq (%rsp),%r11 pushq %rbp @@ -2120,7 +2109,6 @@ L$xts_enc_epilogue: .p2align 4 _aesni_xts_decrypt: -.byte 243,15,30,250 leaq (%rsp),%r11 pushq %rbp @@ -2628,7 +2616,6 @@ L$xts_dec_epilogue: .p2align 5 _aesni_ocb_encrypt: -.byte 243,15,30,250 leaq (%rsp),%rax pushq %rbx @@ -2837,7 +2824,6 @@ L$ocb_enc_epilogue: .p2align 5 __ocb_encrypt6: - pxor %xmm9,%xmm15 movdqu (%rbx,%r12,1),%xmm11 movdqa %xmm10,%xmm12 @@ -2938,10 +2924,8 @@ L$ocb_enc_loop6: - .p2align 5 __ocb_encrypt4: - pxor %xmm9,%xmm15 movdqu (%rbx,%r12,1),%xmm11 movdqa %xmm10,%xmm12 @@ -3009,10 +2993,8 @@ L$ocb_enc_loop4: - .p2align 5 __ocb_encrypt1: - pxor %xmm15,%xmm7 pxor %xmm9,%xmm7 pxor %xmm2,%xmm8 @@ -3045,13 +3027,11 @@ L$ocb_enc_loop1: .byte 0xf3,0xc3 - .globl _aesni_ocb_decrypt .p2align 5 _aesni_ocb_decrypt: -.byte 243,15,30,250 leaq (%rsp),%rax pushq %rbx @@ -3282,7 +3262,6 @@ L$ocb_dec_epilogue: .p2align 5 __ocb_decrypt6: - pxor %xmm9,%xmm15 movdqu (%rbx,%r12,1),%xmm11 movdqa %xmm10,%xmm12 @@ -3377,10 +3356,8 @@ L$ocb_dec_loop6: - .p2align 5 __ocb_decrypt4: - pxor %xmm9,%xmm15 movdqu (%rbx,%r12,1),%xmm11 movdqa %xmm10,%xmm12 @@ -3444,10 +3421,8 @@ L$ocb_dec_loop4: - .p2align 5 __ocb_decrypt1: - pxor %xmm15,%xmm7 pxor %xmm9,%xmm7 pxor %xmm7,%xmm2 @@ -3478,13 +3453,11 @@ L$ocb_dec_loop1: .byte 102,15,56,223,215 .byte 0xf3,0xc3 - .globl _aesni_cbc_encrypt .p2align 4 _aesni_cbc_encrypt: -.byte 243,15,30,250 testq %rdx,%rdx jz L$cbc_ret @@ -4417,6 +4390,7 @@ L$enc_key_ret: addq $8,%rsp .byte 0xf3,0xc3 + L$SEH_end_set_encrypt_key: .p2align 4 @@ -4489,7 +4463,6 @@ L$key_expansion_256b: .byte 0xf3,0xc3 - .p2align 6 L$bswap_mask: .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 diff --git a/lib/accelerated/x86/macosx/e_padlock-x86.s b/lib/accelerated/x86/macosx/e_padlock-x86.s index 9a72938..367962c 100644 --- a/lib/accelerated/x86/macosx/e_padlock-x86.s +++ b/lib/accelerated/x86/macosx/e_padlock-x86.s @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2016, Andy Polyakov +# Copyright (c) 2011-2013, Andy Polyakov # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -37,12 +37,12 @@ # # *** This file is auto-generated *** # +.file "devel/perlasm/e_padlock-x86.s" .text .globl _padlock_capability .align 4 _padlock_capability: L_padlock_capability_begin: -.byte 243,15,30,251 pushl %ebx pushfl popl %eax @@ -59,20 +59,11 @@ L_padlock_capability_begin: .byte 0x0f,0xa2 xorl %eax,%eax cmpl $0x746e6543,%ebx - jne L001zhaoxin + jne L000noluck cmpl $0x48727561,%edx jne L000noluck cmpl $0x736c7561,%ecx jne L000noluck - jmp L002zhaoxinEnd -L001zhaoxin: - cmpl $0x68532020,%ebx - jne L000noluck - cmpl $0x68676e61,%edx - jne L000noluck - cmpl $0x20206961,%ecx - jne L000noluck -L002zhaoxinEnd: movl $3221225472,%eax .byte 0x0f,0xa2 movl %eax,%edx @@ -101,47 +92,43 @@ L000noluck: .align 4 _padlock_key_bswap: L_padlock_key_bswap_begin: -.byte 243,15,30,251 movl 4(%esp),%edx movl 240(%edx),%ecx -L003bswap_loop: +L001bswap_loop: movl (%edx),%eax bswap %eax movl %eax,(%edx) leal 4(%edx),%edx subl $1,%ecx - jnz L003bswap_loop + jnz L001bswap_loop ret .globl _padlock_verify_context .align 4 _padlock_verify_context: L_padlock_verify_context_begin: -.byte 243,15,30,251 movl 4(%esp),%edx - leal Lpadlock_saved_context-L004verify_pic_point,%eax + leal Lpadlock_saved_context-L002verify_pic_point,%eax pushfl call __padlock_verify_ctx -L004verify_pic_point: +L002verify_pic_point: leal 4(%esp),%esp ret .align 4 __padlock_verify_ctx: -.byte 243,15,30,251 addl (%esp),%eax btl $30,4(%esp) - jnc L005verified + jnc L003verified cmpl (%eax),%edx - je L005verified + je L003verified pushfl popfl -L005verified: +L003verified: movl %edx,(%eax) ret .globl _padlock_reload_key .align 4 _padlock_reload_key: L_padlock_reload_key_begin: -.byte 243,15,30,251 pushfl popfl ret @@ -149,7 +136,6 @@ L_padlock_reload_key_begin: .align 4 _padlock_aes_block: L_padlock_aes_block_begin: -.byte 243,15,30,251 pushl %edi pushl %esi pushl %ebx @@ -168,7 +154,6 @@ L_padlock_aes_block_begin: .align 4 _padlock_ecb_encrypt: L_padlock_ecb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -178,25 +163,25 @@ L_padlock_ecb_encrypt_begin: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz L006ecb_abort + jnz L004ecb_abort testl $15,%ecx - jnz L006ecb_abort - leal Lpadlock_saved_context-L007ecb_pic_point,%eax + jnz L004ecb_abort + leal Lpadlock_saved_context-L005ecb_pic_point,%eax pushfl cld call __padlock_verify_ctx -L007ecb_pic_point: +L005ecb_pic_point: leal 16(%edx),%edx xorl %eax,%eax xorl %ebx,%ebx testl $32,(%edx) - jnz L008ecb_aligned + jnz L006ecb_aligned testl $15,%edi setz %al testl $15,%esi setz %bl testl %ebx,%eax - jnz L008ecb_aligned + jnz L006ecb_aligned negl %eax movl $512,%ebx notl %eax @@ -215,7 +200,7 @@ L007ecb_pic_point: andl $-16,%esp movl %eax,16(%ebp) cmpl %ebx,%ecx - ja L009ecb_loop + ja L007ecb_loop movl %esi,%eax cmpl %esp,%ebp cmovel %edi,%eax @@ -226,10 +211,10 @@ L007ecb_pic_point: movl $-128,%eax cmovael %ebx,%eax andl %eax,%ebx - jz L010ecb_unaligned_tail - jmp L009ecb_loop + jz L008ecb_unaligned_tail + jmp L007ecb_loop .align 4,0x90 -L009ecb_loop: +L007ecb_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -238,13 +223,13 @@ L009ecb_loop: testl $15,%edi cmovnzl %esp,%edi testl $15,%esi - jz L011ecb_inp_aligned + jz L009ecb_inp_aligned shrl $2,%ecx .byte 243,165 subl %ebx,%edi movl %ebx,%ecx movl %edi,%esi -L011ecb_inp_aligned: +L009ecb_inp_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -252,23 +237,23 @@ L011ecb_inp_aligned: movl (%ebp),%edi movl 12(%ebp),%ebx testl $15,%edi - jz L012ecb_out_aligned + jz L010ecb_out_aligned movl %ebx,%ecx leal (%esp),%esi shrl $2,%ecx .byte 243,165 subl %ebx,%edi -L012ecb_out_aligned: +L010ecb_out_aligned: movl 4(%ebp),%esi movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jz L013ecb_break + jz L011ecb_break cmpl %ebx,%ecx - jae L009ecb_loop -L010ecb_unaligned_tail: + jae L007ecb_loop +L008ecb_unaligned_tail: xorl %eax,%eax cmpl %ebp,%esp cmovel %ecx,%eax @@ -281,24 +266,24 @@ L010ecb_unaligned_tail: movl %esp,%esi movl %eax,%edi movl %ebx,%ecx - jmp L009ecb_loop + jmp L007ecb_loop .align 4,0x90 -L013ecb_break: +L011ecb_break: cmpl %ebp,%esp - je L014ecb_done + je L012ecb_done pxor %xmm0,%xmm0 leal (%esp),%eax -L015ecb_bzero: +L013ecb_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja L015ecb_bzero -L014ecb_done: + ja L013ecb_bzero +L012ecb_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp - jmp L016ecb_exit + jmp L014ecb_exit .align 4,0x90 -L008ecb_aligned: +L006ecb_aligned: leal (%esi,%ecx,1),%ebp negl %ebp andl $4095,%ebp @@ -308,14 +293,14 @@ L008ecb_aligned: cmovael %eax,%ebp andl %ecx,%ebp subl %ebp,%ecx - jz L017ecb_aligned_tail + jz L015ecb_aligned_tail leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx .byte 243,15,167,200 testl %ebp,%ebp - jz L016ecb_exit -L017ecb_aligned_tail: + jz L014ecb_exit +L015ecb_aligned_tail: movl %ebp,%ecx leal -24(%esp),%ebp movl %ebp,%esp @@ -332,11 +317,11 @@ L017ecb_aligned_tail: movl %esp,%esi movl %eax,%edi movl %ebx,%ecx - jmp L009ecb_loop -L016ecb_exit: + jmp L007ecb_loop +L014ecb_exit: movl $1,%eax leal 4(%esp),%esp -L006ecb_abort: +L004ecb_abort: popl %edi popl %esi popl %ebx @@ -346,7 +331,6 @@ L006ecb_abort: .align 4 _padlock_cbc_encrypt: L_padlock_cbc_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -356,25 +340,25 @@ L_padlock_cbc_encrypt_begin: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz L018cbc_abort + jnz L016cbc_abort testl $15,%ecx - jnz L018cbc_abort - leal Lpadlock_saved_context-L019cbc_pic_point,%eax + jnz L016cbc_abort + leal Lpadlock_saved_context-L017cbc_pic_point,%eax pushfl cld call __padlock_verify_ctx -L019cbc_pic_point: +L017cbc_pic_point: leal 16(%edx),%edx xorl %eax,%eax xorl %ebx,%ebx testl $32,(%edx) - jnz L020cbc_aligned + jnz L018cbc_aligned testl $15,%edi setz %al testl $15,%esi setz %bl testl %ebx,%eax - jnz L020cbc_aligned + jnz L018cbc_aligned negl %eax movl $512,%ebx notl %eax @@ -393,7 +377,7 @@ L019cbc_pic_point: andl $-16,%esp movl %eax,16(%ebp) cmpl %ebx,%ecx - ja L021cbc_loop + ja L019cbc_loop movl %esi,%eax cmpl %esp,%ebp cmovel %edi,%eax @@ -404,10 +388,10 @@ L019cbc_pic_point: movl $-64,%eax cmovael %ebx,%eax andl %eax,%ebx - jz L022cbc_unaligned_tail - jmp L021cbc_loop + jz L020cbc_unaligned_tail + jmp L019cbc_loop .align 4,0x90 -L021cbc_loop: +L019cbc_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -416,13 +400,13 @@ L021cbc_loop: testl $15,%edi cmovnzl %esp,%edi testl $15,%esi - jz L023cbc_inp_aligned + jz L021cbc_inp_aligned shrl $2,%ecx .byte 243,165 subl %ebx,%edi movl %ebx,%ecx movl %edi,%esi -L023cbc_inp_aligned: +L021cbc_inp_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -432,23 +416,23 @@ L023cbc_inp_aligned: movl (%ebp),%edi movl 12(%ebp),%ebx testl $15,%edi - jz L024cbc_out_aligned + jz L022cbc_out_aligned movl %ebx,%ecx leal (%esp),%esi shrl $2,%ecx .byte 243,165 subl %ebx,%edi -L024cbc_out_aligned: +L022cbc_out_aligned: movl 4(%ebp),%esi movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jz L025cbc_break + jz L023cbc_break cmpl %ebx,%ecx - jae L021cbc_loop -L022cbc_unaligned_tail: + jae L019cbc_loop +L020cbc_unaligned_tail: xorl %eax,%eax cmpl %ebp,%esp cmovel %ecx,%eax @@ -461,24 +445,24 @@ L022cbc_unaligned_tail: movl %esp,%esi movl %eax,%edi movl %ebx,%ecx - jmp L021cbc_loop + jmp L019cbc_loop .align 4,0x90 -L025cbc_break: +L023cbc_break: cmpl %ebp,%esp - je L026cbc_done + je L024cbc_done pxor %xmm0,%xmm0 leal (%esp),%eax -L027cbc_bzero: +L025cbc_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja L027cbc_bzero -L026cbc_done: + ja L025cbc_bzero +L024cbc_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp - jmp L028cbc_exit + jmp L026cbc_exit .align 4,0x90 -L020cbc_aligned: +L018cbc_aligned: leal (%esi,%ecx,1),%ebp negl %ebp andl $4095,%ebp @@ -488,7 +472,7 @@ L020cbc_aligned: cmovael %eax,%ebp andl %ecx,%ebp subl %ebp,%ecx - jz L029cbc_aligned_tail + jz L027cbc_aligned_tail leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -496,8 +480,8 @@ L020cbc_aligned: movaps (%eax),%xmm0 movaps %xmm0,-16(%edx) testl %ebp,%ebp - jz L028cbc_exit -L029cbc_aligned_tail: + jz L026cbc_exit +L027cbc_aligned_tail: movl %ebp,%ecx leal -24(%esp),%ebp movl %ebp,%esp @@ -514,11 +498,11 @@ L029cbc_aligned_tail: movl %esp,%esi movl %eax,%edi movl %ebx,%ecx - jmp L021cbc_loop -L028cbc_exit: + jmp L019cbc_loop +L026cbc_exit: movl $1,%eax leal 4(%esp),%esp -L018cbc_abort: +L016cbc_abort: popl %edi popl %esi popl %ebx @@ -528,7 +512,6 @@ L018cbc_abort: .align 4 _padlock_cfb_encrypt: L_padlock_cfb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -538,25 +521,25 @@ L_padlock_cfb_encrypt_begin: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz L030cfb_abort + jnz L028cfb_abort testl $15,%ecx - jnz L030cfb_abort - leal Lpadlock_saved_context-L031cfb_pic_point,%eax + jnz L028cfb_abort + leal Lpadlock_saved_context-L029cfb_pic_point,%eax pushfl cld call __padlock_verify_ctx -L031cfb_pic_point: +L029cfb_pic_point: leal 16(%edx),%edx xorl %eax,%eax xorl %ebx,%ebx testl $32,(%edx) - jnz L032cfb_aligned + jnz L030cfb_aligned testl $15,%edi setz %al testl $15,%esi setz %bl testl %ebx,%eax - jnz L032cfb_aligned + jnz L030cfb_aligned negl %eax movl $512,%ebx notl %eax @@ -574,9 +557,9 @@ L031cfb_pic_point: andl $-16,%ebp andl $-16,%esp movl %eax,16(%ebp) - jmp L033cfb_loop + jmp L031cfb_loop .align 4,0x90 -L033cfb_loop: +L031cfb_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -585,13 +568,13 @@ L033cfb_loop: testl $15,%edi cmovnzl %esp,%edi testl $15,%esi - jz L034cfb_inp_aligned + jz L032cfb_inp_aligned shrl $2,%ecx .byte 243,165 subl %ebx,%edi movl %ebx,%ecx movl %edi,%esi -L034cfb_inp_aligned: +L032cfb_inp_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -601,45 +584,45 @@ L034cfb_inp_aligned: movl (%ebp),%edi movl 12(%ebp),%ebx testl $15,%edi - jz L035cfb_out_aligned + jz L033cfb_out_aligned movl %ebx,%ecx leal (%esp),%esi shrl $2,%ecx .byte 243,165 subl %ebx,%edi -L035cfb_out_aligned: +L033cfb_out_aligned: movl 4(%ebp),%esi movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jnz L033cfb_loop + jnz L031cfb_loop cmpl %ebp,%esp - je L036cfb_done + je L034cfb_done pxor %xmm0,%xmm0 leal (%esp),%eax -L037cfb_bzero: +L035cfb_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja L037cfb_bzero -L036cfb_done: + ja L035cfb_bzero +L034cfb_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp - jmp L038cfb_exit + jmp L036cfb_exit .align 4,0x90 -L032cfb_aligned: +L030cfb_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx .byte 243,15,167,224 movaps (%eax),%xmm0 movaps %xmm0,-16(%edx) -L038cfb_exit: +L036cfb_exit: movl $1,%eax leal 4(%esp),%esp -L030cfb_abort: +L028cfb_abort: popl %edi popl %esi popl %ebx @@ -649,7 +632,6 @@ L030cfb_abort: .align 4 _padlock_ofb_encrypt: L_padlock_ofb_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -659,25 +641,25 @@ L_padlock_ofb_encrypt_begin: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz L039ofb_abort + jnz L037ofb_abort testl $15,%ecx - jnz L039ofb_abort - leal Lpadlock_saved_context-L040ofb_pic_point,%eax + jnz L037ofb_abort + leal Lpadlock_saved_context-L038ofb_pic_point,%eax pushfl cld call __padlock_verify_ctx -L040ofb_pic_point: +L038ofb_pic_point: leal 16(%edx),%edx xorl %eax,%eax xorl %ebx,%ebx testl $32,(%edx) - jnz L041ofb_aligned + jnz L039ofb_aligned testl $15,%edi setz %al testl $15,%esi setz %bl testl %ebx,%eax - jnz L041ofb_aligned + jnz L039ofb_aligned negl %eax movl $512,%ebx notl %eax @@ -695,9 +677,9 @@ L040ofb_pic_point: andl $-16,%ebp andl $-16,%esp movl %eax,16(%ebp) - jmp L042ofb_loop + jmp L040ofb_loop .align 4,0x90 -L042ofb_loop: +L040ofb_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -706,13 +688,13 @@ L042ofb_loop: testl $15,%edi cmovnzl %esp,%edi testl $15,%esi - jz L043ofb_inp_aligned + jz L041ofb_inp_aligned shrl $2,%ecx .byte 243,165 subl %ebx,%edi movl %ebx,%ecx movl %edi,%esi -L043ofb_inp_aligned: +L041ofb_inp_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx @@ -722,45 +704,45 @@ L043ofb_inp_aligned: movl (%ebp),%edi movl 12(%ebp),%ebx testl $15,%edi - jz L044ofb_out_aligned + jz L042ofb_out_aligned movl %ebx,%ecx leal (%esp),%esi shrl $2,%ecx .byte 243,165 subl %ebx,%edi -L044ofb_out_aligned: +L042ofb_out_aligned: movl 4(%ebp),%esi movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jnz L042ofb_loop + jnz L040ofb_loop cmpl %ebp,%esp - je L045ofb_done + je L043ofb_done pxor %xmm0,%xmm0 leal (%esp),%eax -L046ofb_bzero: +L044ofb_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja L046ofb_bzero -L045ofb_done: + ja L044ofb_bzero +L043ofb_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp - jmp L047ofb_exit + jmp L045ofb_exit .align 4,0x90 -L041ofb_aligned: +L039ofb_aligned: leal -16(%edx),%eax leal 16(%edx),%ebx shrl $4,%ecx .byte 243,15,167,232 movaps (%eax),%xmm0 movaps %xmm0,-16(%edx) -L047ofb_exit: +L045ofb_exit: movl $1,%eax leal 4(%esp),%esp -L039ofb_abort: +L037ofb_abort: popl %edi popl %esi popl %ebx @@ -770,7 +752,6 @@ L039ofb_abort: .align 4 _padlock_ctr32_encrypt: L_padlock_ctr32_encrypt_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi @@ -780,14 +761,14 @@ L_padlock_ctr32_encrypt_begin: movl 28(%esp),%edx movl 32(%esp),%ecx testl $15,%edx - jnz L048ctr32_abort + jnz L046ctr32_abort testl $15,%ecx - jnz L048ctr32_abort - leal Lpadlock_saved_context-L049ctr32_pic_point,%eax + jnz L046ctr32_abort + leal Lpadlock_saved_context-L047ctr32_pic_point,%eax pushfl cld call __padlock_verify_ctx -L049ctr32_pic_point: +L047ctr32_pic_point: leal 16(%edx),%edx xorl %eax,%eax movq -16(%edx),%mm0 @@ -807,9 +788,9 @@ L049ctr32_pic_point: andl $-16,%ebp andl $-16,%esp movl %eax,16(%ebp) - jmp L050ctr32_loop + jmp L048ctr32_loop .align 4,0x90 -L050ctr32_loop: +L048ctr32_loop: movl %edi,(%ebp) movl %esi,4(%ebp) movl %ecx,8(%ebp) @@ -818,7 +799,7 @@ L050ctr32_loop: movl -4(%edx),%ecx xorl %edi,%edi movl -8(%edx),%eax -L051ctr32_prepare: +L049ctr32_prepare: movl %ecx,12(%esp,%edi,1) bswap %ecx movq %mm0,(%esp,%edi,1) @@ -827,7 +808,7 @@ L051ctr32_prepare: bswap %ecx leal 16(%edi),%edi cmpl %ebx,%edi - jb L051ctr32_prepare + jb L049ctr32_prepare movl %ecx,-4(%edx) leal (%esp),%esi leal (%esp),%edi @@ -840,33 +821,33 @@ L051ctr32_prepare: movl 12(%ebp),%ebx movl 4(%ebp),%esi xorl %ecx,%ecx -L052ctr32_xor: +L050ctr32_xor: movups (%esi,%ecx,1),%xmm1 leal 16(%ecx),%ecx pxor -16(%esp,%ecx,1),%xmm1 movups %xmm1,-16(%edi,%ecx,1) cmpl %ebx,%ecx - jb L052ctr32_xor + jb L050ctr32_xor movl 8(%ebp),%ecx addl %ebx,%edi addl %ebx,%esi subl %ebx,%ecx movl $512,%ebx - jnz L050ctr32_loop + jnz L048ctr32_loop pxor %xmm0,%xmm0 leal (%esp),%eax -L053ctr32_bzero: +L051ctr32_bzero: movaps %xmm0,(%eax) leal 16(%eax),%eax cmpl %eax,%ebp - ja L053ctr32_bzero -L054ctr32_done: + ja L051ctr32_bzero +L052ctr32_done: movl 16(%ebp),%ebp leal 24(%ebp),%esp movl $1,%eax leal 4(%esp),%esp emms -L048ctr32_abort: +L046ctr32_abort: popl %edi popl %esi popl %ebx @@ -876,7 +857,6 @@ L048ctr32_abort: .align 4 _padlock_xstore: L_padlock_xstore_begin: -.byte 243,15,30,251 pushl %edi movl 8(%esp),%edi movl 12(%esp),%edx @@ -885,21 +865,19 @@ L_padlock_xstore_begin: ret .align 4 __win32_segv_handler: -.byte 243,15,30,251 movl $1,%eax movl 4(%esp),%edx movl 12(%esp),%ecx cmpl $3221225477,(%edx) - jne L055ret + jne L053ret addl $4,184(%ecx) movl $0,%eax -L055ret: +L053ret: ret .globl _padlock_sha1_oneshot .align 4 _padlock_sha1_oneshot: L_padlock_sha1_oneshot_begin: -.byte 243,15,30,251 pushl %edi pushl %esi xorl %eax,%eax @@ -929,7 +907,6 @@ L_padlock_sha1_oneshot_begin: .align 4 _padlock_sha1_blocks: L_padlock_sha1_blocks_begin: -.byte 243,15,30,251 pushl %edi pushl %esi movl 12(%esp),%edi @@ -958,7 +935,6 @@ L_padlock_sha1_blocks_begin: .align 4 _padlock_sha256_oneshot: L_padlock_sha256_oneshot_begin: -.byte 243,15,30,251 pushl %edi pushl %esi xorl %eax,%eax @@ -988,7 +964,6 @@ L_padlock_sha256_oneshot_begin: .align 4 _padlock_sha256_blocks: L_padlock_sha256_blocks_begin: -.byte 243,15,30,251 pushl %edi pushl %esi movl 12(%esp),%edi @@ -1017,7 +992,6 @@ L_padlock_sha256_blocks_begin: .align 4 _padlock_sha512_blocks: L_padlock_sha512_blocks_begin: -.byte 243,15,30,251 pushl %edi pushl %esi movl 12(%esp),%edi diff --git a/lib/accelerated/x86/macosx/e_padlock-x86_64.s b/lib/accelerated/x86/macosx/e_padlock-x86_64.s index 64aff29..a73d7a6 100644 --- a/lib/accelerated/x86/macosx/e_padlock-x86_64.s +++ b/lib/accelerated/x86/macosx/e_padlock-x86_64.s @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2016, Andy Polyakov +# Copyright (c) 2011-2013, Andy Polyakov # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -42,50 +42,36 @@ .p2align 4 _padlock_capability: - -.byte 243,15,30,250 movq %rbx,%r8 xorl %eax,%eax cpuid xorl %eax,%eax - cmpl $0x746e6543,%ebx - jne L$zhaoxin - cmpl $0x48727561,%edx - jne L$noluck - cmpl $0x736c7561,%ecx - jne L$noluck - jmp L$zhaoxinEnd -L$zhaoxin: - cmpl $0x68532020,%ebx + cmpl $1953391939,%ebx jne L$noluck - cmpl $0x68676e61,%edx + cmpl $1215460705,%edx jne L$noluck - cmpl $0x20206961,%ecx + cmpl $1936487777,%ecx jne L$noluck -L$zhaoxinEnd: - movl $0xC0000000,%eax + movl $3221225472,%eax cpuid movl %eax,%edx xorl %eax,%eax - cmpl $0xC0000001,%edx + cmpl $3221225473,%edx jb L$noluck - movl $0xC0000001,%eax + movl $3221225473,%eax cpuid movl %edx,%eax - andl $0xffffffef,%eax - orl $0x10,%eax + andl $4294967279,%eax + orl $16,%eax L$noluck: movq %r8,%rbx .byte 0xf3,0xc3 - .globl _padlock_key_bswap .p2align 4 _padlock_key_bswap: - -.byte 243,15,30,250 movl 240(%rdi),%edx L$bswap_loop: movl (%rdi),%eax @@ -97,13 +83,10 @@ L$bswap_loop: .byte 0xf3,0xc3 - .globl _padlock_verify_context .p2align 4 _padlock_verify_context: - -.byte 243,15,30,250 movq %rdi,%rdx pushf leaq L$padlock_saved_context(%rip),%rax @@ -113,11 +96,8 @@ _padlock_verify_context: - .p2align 4 _padlock_verify_ctx: - -.byte 243,15,30,250 movq 8(%rsp),%r8 btq $30,%r8 jnc L$verified @@ -130,53 +110,41 @@ L$verified: .byte 0xf3,0xc3 - .globl _padlock_reload_key .p2align 4 _padlock_reload_key: - -.byte 243,15,30,250 pushf popf .byte 0xf3,0xc3 - .globl _padlock_aes_block .p2align 4 _padlock_aes_block: - -.byte 243,15,30,250 movq %rbx,%r8 movq $1,%rcx leaq 32(%rdx),%rbx leaq 16(%rdx),%rdx -.byte 0xf3,0x0f,0xa7,0xc8 +.byte 0xf3,0x0f,0xa7,0xc8 movq %r8,%rbx .byte 0xf3,0xc3 - .globl _padlock_xstore .p2align 4 _padlock_xstore: - -.byte 243,15,30,250 movl %esi,%edx -.byte 0x0f,0xa7,0xc0 +.byte 0x0f,0xa7,0xc0 .byte 0xf3,0xc3 - .globl _padlock_sha1_oneshot .p2align 4 _padlock_sha1_oneshot: - -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -186,7 +154,7 @@ _padlock_sha1_oneshot: movq %rsp,%rdi movl %eax,16(%rsp) xorq %rax,%rax -.byte 0xf3,0x0f,0xa6,0xc8 +.byte 0xf3,0x0f,0xa6,0xc8 movaps (%rsp),%xmm0 movl 16(%rsp),%eax addq $128+8,%rsp @@ -195,13 +163,10 @@ _padlock_sha1_oneshot: .byte 0xf3,0xc3 - .globl _padlock_sha1_blocks .p2align 4 _padlock_sha1_blocks: - -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -211,7 +176,7 @@ _padlock_sha1_blocks: movq %rsp,%rdi movl %eax,16(%rsp) movq $-1,%rax -.byte 0xf3,0x0f,0xa6,0xc8 +.byte 0xf3,0x0f,0xa6,0xc8 movaps (%rsp),%xmm0 movl 16(%rsp),%eax addq $128+8,%rsp @@ -220,13 +185,10 @@ _padlock_sha1_blocks: .byte 0xf3,0xc3 - .globl _padlock_sha256_oneshot .p2align 4 _padlock_sha256_oneshot: - -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -236,7 +198,7 @@ _padlock_sha256_oneshot: movq %rsp,%rdi movaps %xmm1,16(%rsp) xorq %rax,%rax -.byte 0xf3,0x0f,0xa6,0xd0 +.byte 0xf3,0x0f,0xa6,0xd0 movaps (%rsp),%xmm0 movaps 16(%rsp),%xmm1 addq $128+8,%rsp @@ -245,13 +207,10 @@ _padlock_sha256_oneshot: .byte 0xf3,0xc3 - .globl _padlock_sha256_blocks .p2align 4 _padlock_sha256_blocks: - -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -261,7 +220,7 @@ _padlock_sha256_blocks: movq %rsp,%rdi movaps %xmm1,16(%rsp) movq $-1,%rax -.byte 0xf3,0x0f,0xa6,0xd0 +.byte 0xf3,0x0f,0xa6,0xd0 movaps (%rsp),%xmm0 movaps 16(%rsp),%xmm1 addq $128+8,%rsp @@ -270,13 +229,10 @@ _padlock_sha256_blocks: .byte 0xf3,0xc3 - .globl _padlock_sha512_blocks .p2align 4 _padlock_sha512_blocks: - -.byte 243,15,30,250 movq %rdx,%rcx movq %rdi,%rdx movups (%rdi),%xmm0 @@ -289,7 +245,7 @@ _padlock_sha512_blocks: movaps %xmm1,16(%rsp) movaps %xmm2,32(%rsp) movaps %xmm3,48(%rsp) -.byte 0xf3,0x0f,0xa6,0xe0 +.byte 0xf3,0x0f,0xa6,0xe0 movaps (%rsp),%xmm0 movaps 16(%rsp),%xmm1 movaps 32(%rsp),%xmm2 @@ -301,13 +257,10 @@ _padlock_sha512_blocks: movups %xmm3,48(%rdx) .byte 0xf3,0xc3 - .globl _padlock_ecb_encrypt .p2align 4 _padlock_ecb_encrypt: - -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -325,9 +278,9 @@ _padlock_ecb_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz L$ecb_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz L$ecb_aligned @@ -351,7 +304,7 @@ _padlock_ecb_encrypt: cmoveq %rdi,%rax addq %rcx,%rax negq %rax - andq $0xfff,%rax + andq $4095,%rax cmpq $128,%rax movq $-128,%rax cmovaeq %rbx,%rax @@ -367,12 +320,12 @@ L$ecb_loop: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz L$ecb_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -380,15 +333,15 @@ L$ecb_inp_aligned: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,200 +.byte 0xf3,0x0f,0xa7,200 movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz L$ecb_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi L$ecb_out_aligned: movq %r9,%rsi @@ -409,7 +362,7 @@ L$ecb_unaligned_tail: subq %rax,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 movq %rsp,%rsi movq %r8,%rdi movq %rbx,%rcx @@ -435,7 +388,7 @@ L$ecb_done: L$ecb_aligned: leaq (%rsi,%rcx,1),%rbp negq %rbp - andq $0xfff,%rbp + andq $4095,%rbp xorl %eax,%eax cmpq $128,%rbp movq $128-1,%rbp @@ -446,7 +399,7 @@ L$ecb_aligned: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,200 +.byte 0xf3,0x0f,0xa7,200 testq %rbp,%rbp jz L$ecb_exit @@ -458,7 +411,7 @@ L$ecb_aligned_tail: subq %rcx,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 leaq (%r8),%rdi leaq (%rsp),%rsi movq %rbx,%rcx @@ -471,13 +424,10 @@ L$ecb_abort: popq %rbp .byte 0xf3,0xc3 - .globl _padlock_cbc_encrypt .p2align 4 _padlock_cbc_encrypt: - -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -495,9 +445,9 @@ _padlock_cbc_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz L$cbc_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz L$cbc_aligned @@ -521,7 +471,7 @@ _padlock_cbc_encrypt: cmoveq %rdi,%rax addq %rcx,%rax negq %rax - andq $0xfff,%rax + andq $4095,%rax cmpq $64,%rax movq $-64,%rax cmovaeq %rbx,%rax @@ -537,12 +487,12 @@ L$cbc_loop: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz L$cbc_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -550,17 +500,17 @@ L$cbc_inp_aligned: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,208 +.byte 0xf3,0x0f,0xa7,208 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz L$cbc_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi L$cbc_out_aligned: movq %r9,%rsi @@ -581,7 +531,7 @@ L$cbc_unaligned_tail: subq %rax,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 movq %rsp,%rsi movq %r8,%rdi movq %rbx,%rcx @@ -607,7 +557,7 @@ L$cbc_done: L$cbc_aligned: leaq (%rsi,%rcx,1),%rbp negq %rbp - andq $0xfff,%rbp + andq $4095,%rbp xorl %eax,%eax cmpq $64,%rbp movq $64-1,%rbp @@ -618,7 +568,7 @@ L$cbc_aligned: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,208 +.byte 0xf3,0x0f,0xa7,208 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) testq %rbp,%rbp @@ -632,7 +582,7 @@ L$cbc_aligned_tail: subq %rcx,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 leaq (%r8),%rdi leaq (%rsp),%rsi movq %rbx,%rcx @@ -645,13 +595,10 @@ L$cbc_abort: popq %rbp .byte 0xf3,0xc3 - .globl _padlock_cfb_encrypt .p2align 4 _padlock_cfb_encrypt: - -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -669,9 +616,9 @@ _padlock_cfb_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz L$cfb_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz L$cfb_aligned @@ -698,12 +645,12 @@ L$cfb_loop: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz L$cfb_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -711,17 +658,17 @@ L$cfb_inp_aligned: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,224 +.byte 0xf3,0x0f,0xa7,224 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz L$cfb_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi L$cfb_out_aligned: movq %r9,%rsi @@ -751,7 +698,7 @@ L$cfb_aligned: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,224 +.byte 0xf3,0x0f,0xa7,224 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) L$cfb_exit: @@ -762,13 +709,10 @@ L$cfb_abort: popq %rbp .byte 0xf3,0xc3 - .globl _padlock_ofb_encrypt .p2align 4 _padlock_ofb_encrypt: - -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -786,9 +730,9 @@ _padlock_ofb_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz L$ofb_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz L$ofb_aligned @@ -815,12 +759,12 @@ L$ofb_loop: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz L$ofb_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -828,17 +772,17 @@ L$ofb_inp_aligned: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,232 +.byte 0xf3,0x0f,0xa7,232 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz L$ofb_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi L$ofb_out_aligned: movq %r9,%rsi @@ -868,7 +812,7 @@ L$ofb_aligned: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,232 +.byte 0xf3,0x0f,0xa7,232 movdqa (%rax),%xmm0 movdqa %xmm0,-16(%rdx) L$ofb_exit: @@ -879,13 +823,10 @@ L$ofb_abort: popq %rbp .byte 0xf3,0xc3 - .globl _padlock_ctr32_encrypt .p2align 4 _padlock_ctr32_encrypt: - -.byte 243,15,30,250 pushq %rbp pushq %rbx @@ -903,9 +844,9 @@ _padlock_ctr32_encrypt: xorl %ebx,%ebx testl $32,(%rdx) jnz L$ctr32_aligned - testq $0x0f,%rdi + testq $15,%rdi setz %al - testq $0x0f,%rsi + testq $15,%rsi setz %bl testl %ebx,%eax jnz L$ctr32_aligned @@ -940,7 +881,7 @@ L$ctr32_reenter: cmoveq %rdi,%rax addq %rcx,%rax negq %rax - andq $0xfff,%rax + andq $4095,%rax cmpq $32,%rax movq $-32,%rax cmovaeq %rbx,%rax @@ -956,12 +897,12 @@ L$ctr32_loop: movq %rcx,%r10 movq %rbx,%rcx movq %rbx,%r11 - testq $0x0f,%rdi + testq $15,%rdi cmovnzq %rsp,%rdi - testq $0x0f,%rsi + testq $15,%rsi jz L$ctr32_inp_aligned shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi movq %rbx,%rcx movq %rdi,%rsi @@ -969,23 +910,23 @@ L$ctr32_inp_aligned: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,216 +.byte 0xf3,0x0f,0xa7,216 movl -4(%rdx),%eax - testl $0xffff0000,%eax + testl $4294901760,%eax jnz L$ctr32_no_carry bswapl %eax - addl $0x10000,%eax + addl $65536,%eax bswapl %eax movl %eax,-4(%rdx) L$ctr32_no_carry: movq %r8,%rdi movq %r11,%rbx - testq $0x0f,%rdi + testq $15,%rdi jz L$ctr32_out_aligned movq %rbx,%rcx leaq (%rsp),%rsi shrq $3,%rcx -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 subq %rbx,%rdi L$ctr32_out_aligned: movq %r9,%rsi @@ -1003,7 +944,7 @@ L$ctr32_out_aligned: cmoveq %rdi,%rax addq %rcx,%rax negq %rax - andq $0xfff,%rax + andq $4095,%rax cmpq $32,%rax movq $-32,%rax cmovaeq %rbx,%rax @@ -1018,7 +959,7 @@ L$ctr32_unaligned_tail: subq %rax,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 movq %rsp,%rsi movq %r8,%rdi movq %rbx,%rcx @@ -1045,7 +986,7 @@ L$ctr32_aligned: movl -4(%rdx),%eax bswapl %eax negl %eax - andl $0xffff,%eax + andl $65535,%eax movq $1048576,%rbx shll $4,%eax cmovzq %rbx,%rax @@ -1062,11 +1003,11 @@ L$ctr32_aligned_loop: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,216 +.byte 0xf3,0x0f,0xa7,216 movl -4(%rdx),%eax bswapl %eax - addl $0x10000,%eax + addl $65536,%eax bswapl %eax movl %eax,-4(%rdx) @@ -1080,7 +1021,7 @@ L$ctr32_aligned_loop: L$ctr32_aligned_skip: leaq (%rsi,%rcx,1),%rbp negq %rbp - andq $0xfff,%rbp + andq $4095,%rbp xorl %eax,%eax cmpq $32,%rbp movq $32-1,%rbp @@ -1091,7 +1032,7 @@ L$ctr32_aligned_skip: leaq -16(%rdx),%rax leaq 16(%rdx),%rbx shrq $4,%rcx -.byte 0xf3,0x0f,0xa7,216 +.byte 0xf3,0x0f,0xa7,216 testq %rbp,%rbp jz L$ctr32_exit @@ -1103,7 +1044,7 @@ L$ctr32_aligned_tail: subq %rcx,%rsp shrq $3,%rcx leaq (%rsp),%rdi -.byte 0xf3,0x48,0xa5 +.byte 0xf3,0x48,0xa5 leaq (%r8),%rdi leaq (%rsp),%rsi movq %rbx,%rcx @@ -1116,7 +1057,6 @@ L$ctr32_abort: popq %rbp .byte 0xf3,0xc3 - .byte 86,73,65,32,80,97,100,108,111,99,107,32,120,56,54,95,54,52,32,109,111,100,117,108,101,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0 .p2align 4 .data diff --git a/lib/accelerated/x86/macosx/ghash-x86_64.s b/lib/accelerated/x86/macosx/ghash-x86_64.s index 974d34d..5fd3216 100644 --- a/lib/accelerated/x86/macosx/ghash-x86_64.s +++ b/lib/accelerated/x86/macosx/ghash-x86_64.s @@ -45,7 +45,6 @@ .p2align 4 _gcm_gmult_4bit: -.byte 243,15,30,250 pushq %rbx pushq %rbp @@ -151,7 +150,6 @@ L$gmult_epilogue: .p2align 4 _gcm_ghash_4bit: -.byte 243,15,30,250 pushq %rbx pushq %rbp @@ -893,7 +891,6 @@ L$_init_clmul: .p2align 4 _gcm_gmult_clmul: -.byte 243,15,30,250 L$_gmult_clmul: movdqu (%rdi),%xmm0 movdqa L$bswap_mask(%rip),%xmm5 @@ -947,7 +944,6 @@ L$_gmult_clmul: .p2align 5 _gcm_ghash_clmul: -.byte 243,15,30,250 L$_ghash_clmul: movdqa L$bswap_mask(%rip),%xmm10 @@ -1442,7 +1438,6 @@ L$init_start_avx: .p2align 5 _gcm_gmult_avx: -.byte 243,15,30,250 jmp L$_gmult_clmul @@ -1451,7 +1446,6 @@ _gcm_gmult_avx: .p2align 5 _gcm_ghash_avx: -.byte 243,15,30,250 vzeroupper vmovdqu (%rdi),%xmm10 diff --git a/lib/accelerated/x86/macosx/sha1-ssse3-x86.s b/lib/accelerated/x86/macosx/sha1-ssse3-x86.s index f51c5a3..985d4af 100644 --- a/lib/accelerated/x86/macosx/sha1-ssse3-x86.s +++ b/lib/accelerated/x86/macosx/sha1-ssse3-x86.s @@ -42,7 +42,6 @@ .align 4 _sha1_block_data_order: L_sha1_block_data_order_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi diff --git a/lib/accelerated/x86/macosx/sha1-ssse3-x86_64.s b/lib/accelerated/x86/macosx/sha1-ssse3-x86_64.s index 7b5d9df..a576acc 100644 --- a/lib/accelerated/x86/macosx/sha1-ssse3-x86_64.s +++ b/lib/accelerated/x86/macosx/sha1-ssse3-x86_64.s @@ -1460,8 +1460,8 @@ L$oop_shaext: pshufd $27,%xmm1,%xmm1 movdqu %xmm0,(%rdi) movd %xmm1,16(%rdi) - .byte 0xf3,0xc3 + .byte 0xf3,0xc3 .p2align 4 diff --git a/lib/accelerated/x86/macosx/sha256-ssse3-x86.s b/lib/accelerated/x86/macosx/sha256-ssse3-x86.s index 36781d4..8d25710 100644 --- a/lib/accelerated/x86/macosx/sha256-ssse3-x86.s +++ b/lib/accelerated/x86/macosx/sha256-ssse3-x86.s @@ -42,7 +42,6 @@ .align 4 _sha256_block_data_order: L_sha256_block_data_order_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi diff --git a/lib/accelerated/x86/macosx/sha256-ssse3-x86_64.s b/lib/accelerated/x86/macosx/sha256-ssse3-x86_64.s index 9fed36b..fd0c247 100644 --- a/lib/accelerated/x86/macosx/sha256-ssse3-x86_64.s +++ b/lib/accelerated/x86/macosx/sha256-ssse3-x86_64.s @@ -1814,7 +1814,6 @@ K256: .p2align 6 sha256_block_data_order_shaext: _shaext_shortcut: - leaq K256+128(%rip),%rcx movdqu (%rdi),%xmm1 movdqu 16(%rdi),%xmm2 @@ -2019,7 +2018,6 @@ L$oop_shaext: .byte 0xf3,0xc3 - .p2align 6 sha256_block_data_order_ssse3: @@ -4279,15 +4277,7 @@ L$oop_avx2: vmovdqa %ymm4,0(%rsp) xorl %r14d,%r14d vmovdqa %ymm5,32(%rsp) - - movq 88(%rsp),%rdi - leaq -64(%rsp),%rsp - - - - movq %rdi,-8(%rsp) - movl %ebx,%edi vmovdqa %ymm6,0(%rsp) xorl %ecx,%edi @@ -4299,12 +4289,6 @@ L$oop_avx2: .p2align 4 L$avx2_00_47: leaq -64(%rsp),%rsp - - - pushq 64-8(%rsp) - - leaq 8(%rsp),%rsp - vpalignr $4,%ymm0,%ymm1,%ymm4 addl 0+128(%rsp),%r11d andl %r8d,%r12d @@ -4560,12 +4544,6 @@ L$avx2_00_47: movl %r9d,%r12d vmovdqa %ymm6,32(%rsp) leaq -64(%rsp),%rsp - - - pushq 64-8(%rsp) - - leaq 8(%rsp),%rsp - vpalignr $4,%ymm2,%ymm3,%ymm4 addl 0+128(%rsp),%r11d andl %r8d,%r12d @@ -5441,8 +5419,6 @@ L$ower_avx2: leaq 448(%rsp),%rsp - - addl 0(%rdi),%eax addl 4(%rdi),%ebx addl 8(%rdi),%ecx @@ -5468,11 +5444,9 @@ L$ower_avx2: jbe L$oop_avx2 leaq (%rsp),%rbp - - - L$done_avx2: - movq 88(%rbp),%rsi + leaq (%rbp),%rsp + movq 88(%rsp),%rsi vzeroupper movq -48(%rsi),%r15 diff --git a/lib/accelerated/x86/macosx/sha512-ssse3-x86.s b/lib/accelerated/x86/macosx/sha512-ssse3-x86.s index 248a35e..4e60bb4 100644 --- a/lib/accelerated/x86/macosx/sha512-ssse3-x86.s +++ b/lib/accelerated/x86/macosx/sha512-ssse3-x86.s @@ -42,7 +42,6 @@ .align 4 _sha512_block_data_order: L_sha512_block_data_order_begin: -.byte 243,15,30,251 pushl %ebp pushl %ebx pushl %esi diff --git a/lib/accelerated/x86/macosx/sha512-ssse3-x86_64.s b/lib/accelerated/x86/macosx/sha512-ssse3-x86_64.s index e78d90f..8bf1616 100644 --- a/lib/accelerated/x86/macosx/sha512-ssse3-x86_64.s +++ b/lib/accelerated/x86/macosx/sha512-ssse3-x86_64.s @@ -4204,15 +4204,7 @@ L$oop_avx2: vmovdqa %ymm10,64(%rsp) vpaddq 64(%rbp),%ymm6,%ymm10 vmovdqa %ymm11,96(%rsp) - - movq 152(%rsp),%rdi - leaq -128(%rsp),%rsp - - - - movq %rdi,-8(%rsp) - vpaddq 96(%rbp),%ymm7,%ymm11 vmovdqa %ymm8,0(%rsp) xorq %r14,%r14 @@ -4228,12 +4220,6 @@ L$oop_avx2: .p2align 4 L$avx2_00_47: leaq -128(%rsp),%rsp - - - pushq 128-8(%rsp) - - leaq 8(%rsp),%rsp - vpalignr $8,%ymm0,%ymm1,%ymm8 addq 0+256(%rsp),%r11 andq %r8,%r12 @@ -4527,12 +4513,6 @@ L$avx2_00_47: movq %r9,%r12 vmovdqa %ymm10,96(%rsp) leaq -128(%rsp),%rsp - - - pushq 128-8(%rsp) - - leaq 8(%rsp),%rsp - vpalignr $8,%ymm4,%ymm5,%ymm8 addq 0+256(%rsp),%r11 andq %r8,%r12 @@ -5446,8 +5426,6 @@ L$ower_avx2: leaq 1152(%rsp),%rsp - - addq 0(%rdi),%rax addq 8(%rdi),%rbx addq 16(%rdi),%rcx @@ -5473,11 +5451,9 @@ L$ower_avx2: jbe L$oop_avx2 leaq (%rsp),%rbp - - - L$done_avx2: - movq 152(%rbp),%rsi + leaq (%rbp),%rsp + movq 152(%rsp),%rsi vzeroupper movq -48(%rsi),%r15 diff --git a/lib/auth/dh_common.c b/lib/auth/dh_common.c index fcd696d..19c205b 100644 --- a/lib/auth/dh_common.c +++ b/lib/auth/dh_common.c @@ -257,14 +257,6 @@ _gnutls_proc_dh_common_server_kx(gnutls_session_t session, } } -#ifdef ENABLE_FIPS140 - if (gnutls_fips140_mode_enabled() && - !_gnutls_dh_prime_match_fips_approved(data_p, n_p, data_g, n_g, NULL, NULL)) { - gnutls_assert(); - return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; - } -#endif - if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.params.params[DH_G], data_g, _n_g) != 0) { gnutls_assert(); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; diff --git a/lib/crypto-api.c b/lib/crypto-api.c index 8524f5e..45be64e 100644 --- a/lib/crypto-api.c +++ b/lib/crypto-api.c @@ -891,23 +891,32 @@ gnutls_aead_cipher_encrypt(gnutls_aead_cipher_hd_t handle, struct iov_store_st { void *data; size_t size; + unsigned allocated; }; static void iov_store_free(struct iov_store_st *s) { - gnutls_free(s->data); + if (s->allocated) { + gnutls_free(s->data); + s->allocated = 0; + } } static int iov_store_grow(struct iov_store_st *s, size_t length) { - void *data; - - s->size += length; - data = gnutls_realloc(s->data, s->size); - if (data == NULL) - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - - s->data = data; + if (s->allocated || s->data == NULL) { + s->size += length; + s->data = gnutls_realloc(s->data, s->size); + if (s->data == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + s->allocated = 1; + } else { + void *data = s->data; + size_t size = s->size + length; + s->data = gnutls_malloc(size); + memcpy(s->data, data, s->size); + s->size += length; + } return 0; } @@ -917,6 +926,11 @@ copy_from_iov(struct iov_store_st *dst, const giovec_t *iov, int iovcnt) memset(dst, 0, sizeof(*dst)); if (iovcnt == 0) { return 0; + } else if (iovcnt == 1) { + dst->data = iov[0].iov_base; + dst->size = iov[0].iov_len; + /* implies: dst->allocated = 0; */ + return 0; } else { int i; uint8_t *p; @@ -930,11 +944,11 @@ copy_from_iov(struct iov_store_st *dst, const giovec_t *iov, int iovcnt) p = dst->data; for (i=0;i 0) - memcpy(p, iov[i].iov_base, iov[i].iov_len); + memcpy(p, iov[i].iov_base, iov[i].iov_len); p += iov[i].iov_len; } + dst->allocated = 1; return 0; } } diff --git a/lib/crypto-selftests-pk.c b/lib/crypto-selftests-pk.c index 52bc327..6f66cd8 100644 --- a/lib/crypto-selftests-pk.c +++ b/lib/crypto-selftests-pk.c @@ -613,150 +613,32 @@ static int test_dh(void) gnutls_pk_params_st priv; gnutls_pk_params_st pub; gnutls_datum_t out = {NULL, 0}; - - /* FFDHE 3072 test vector provided by Stephan Mueller in: - * https://gitlab.com/gnutls/gnutls/-/merge_requests/1342#note_424430996 - */ static const uint8_t known_dh_k[] = { - 0xec, 0xb3, 0x85, 0x0c, 0x72, 0x55, 0x55, 0xc2, 0x98, 0x36, - 0xbe, 0x75, 0x9e, 0xc9, 0x9d, 0x8b, 0x16, 0xa6, 0xe6, 0x84, - 0x33, 0x12, 0x80, 0x1d, 0xac, 0xde, 0x6a, 0xd7, 0x3b, 0x1e, - 0x15, 0xca, 0x5d, 0x26, 0xb3, 0x0a, 0x35, 0xf4, 0xbb, 0xad, - 0x71, 0xcb, 0x03, 0x1a, 0xcb, 0xfb, 0x83, 0xf0, 0xa8, 0xde, - 0xed, 0x5e, 0x3d, 0x98, 0xd2, 0xb0, 0xef, 0xad, 0xdf, 0x32, - 0xa0, 0x16, 0x7d, 0x0e, 0x29, 0xd8, 0x85, 0xca, 0x12, 0x97, - 0x56, 0xab, 0x6a, 0x26, 0xa4, 0x46, 0x3d, 0x87, 0xd7, 0xe0, - 0xb4, 0x3e, 0x28, 0x75, 0xac, 0x59, 0xc5, 0x71, 0x3a, 0x24, - 0x15, 0x76, 0x98, 0x72, 0x94, 0x2d, 0xd0, 0x0e, 0xbc, 0x9a, - 0x77, 0xd4, 0xe2, 0xb2, 0x76, 0x54, 0x4a, 0x56, 0xbe, 0x0b, - 0x43, 0xf8, 0x21, 0x6f, 0x54, 0x32, 0xde, 0xb7, 0xd5, 0xb7, - 0x08, 0x00, 0xd2, 0x57, 0x8c, 0x0b, 0x8b, 0x02, 0x3e, 0xdb, - 0x72, 0x54, 0x3a, 0xc0, 0x50, 0x66, 0xbc, 0xc9, 0x67, 0xf5, - 0x22, 0x28, 0xf2, 0x3c, 0x51, 0x94, 0x61, 0x26, 0x9a, 0xc6, - 0x42, 0x0e, 0x8b, 0x42, 0xad, 0x79, 0x40, 0xa9, 0x0b, 0xdc, - 0x84, 0xd5, 0x71, 0x83, 0x94, 0xd9, 0x83, 0x2f, 0x08, 0x74, - 0xbc, 0x37, 0x6a, 0x3e, 0x1e, 0xbc, 0xcc, 0x09, 0x23, 0x30, - 0x79, 0x01, 0x39, 0xf6, 0xe3, 0xa8, 0xc0, 0xfa, 0x7e, 0xdb, - 0x0b, 0x71, 0x3e, 0x4f, 0x1f, 0x69, 0x84, 0xa6, 0x58, 0x6c, - 0x36, 0x2c, 0xcc, 0xb4, 0x7c, 0x94, 0xec, 0x06, 0x0b, 0x11, - 0x53, 0x95, 0xe6, 0x05, 0x43, 0xa4, 0xe4, 0xea, 0x1d, 0x4f, - 0xdc, 0xd0, 0x38, 0x0e, 0x32, 0xa1, 0xde, 0xd9, 0x8d, 0xd8, - 0x20, 0xac, 0x04, 0x83, 0xf8, 0x1b, 0x55, 0x52, 0x16, 0x20, - 0xe3, 0x2e, 0x6d, 0x11, 0x15, 0x29, 0x2f, 0x3a, 0x7c, 0x80, - 0x0a, 0x71, 0x3d, 0x31, 0x9c, 0x1b, 0x73, 0x59, 0xe1, 0x0d, - 0x27, 0xc5, 0xc0, 0x6a, 0x72, 0x3a, 0x5b, 0xd6, 0xf6, 0x50, - 0xe6, 0x69, 0x48, 0x1e, 0xfd, 0xeb, 0x4a, 0x47, 0x73, 0xfb, - 0x88, 0x14, 0xea, 0x6d, 0x36, 0xe1, 0x4c, 0x2c, 0xf9, 0x04, - 0xc1, 0xb7, 0x29, 0xfc, 0x5d, 0x02, 0x5d, 0x1c, 0x4d, 0x31, - 0x4a, 0x51, 0x3f, 0xa4, 0x45, 0x19, 0x29, 0xc4, 0x32, 0xa6, - 0x45, 0xdb, 0x94, 0x3a, 0xbd, 0x76, 0x2c, 0xd6, 0x1a, 0xb1, - 0xff, 0xe7, 0x62, 0x75, 0x16, 0xe5, 0x0b, 0xa3, 0x3a, 0x93, - 0x84, 0xd6, 0xad, 0xc2, 0x24, 0x68, 0x3d, 0xd6, 0x07, 0xe4, - 0xbe, 0x5a, 0x49, 0x31, 0x06, 0xad, 0x3f, 0x31, 0x4a, 0x1c, - 0xf7, 0x58, 0xdf, 0x34, 0xcb, 0xc8, 0xa9, 0x07, 0x24, 0x42, - 0x63, 0xa5, 0x8e, 0xdd, 0x37, 0x78, 0x92, 0x68, 0x3f, 0xd8, - 0x2f, 0xea, 0x8c, 0xf1, 0x8e, 0xd4, 0x8b, 0xa7, 0x3f, 0xa0, - 0xfa, 0xaf, 0xf0, 0x35, - }; + 0x10, 0x25, 0x04, 0xb5, 0xc6, 0xc2, 0xcb, + 0x0c, 0xe9, 0xc5, 0x58, 0x0d, 0x22, 0x62}; + static const uint8_t test_p[] = { + 0x24, 0x85, 0xdd, 0x3a, 0x74, 0x42, 0xe4, + 0xb3, 0xf1, 0x0b, 0x13, 0xf9, 0x17, 0x4d }; + static const uint8_t test_g[] = { 0x02 }; static const uint8_t test_x[] = { - 0x16, 0x5c, 0xa6, 0xe0, 0x9b, 0x87, 0xfa, 0x2d, 0xbc, 0x13, - 0x20, 0xcd, 0xac, 0x4e, 0xcc, 0x60, 0x1e, 0x48, 0xec, 0xbe, - 0x73, 0x0c, 0xa8, 0x6b, 0x6e, 0x2a, 0xee, 0xdd, 0xd8, 0xf3, - 0x2d, 0x5f, 0x75, 0xf3, 0x07, 0x94, 0x88, 0x3d, 0xb1, 0x38, - 0xcf, 0xae, 0x4a, 0xcc, 0xcb, 0x6a, 0x80, 0xbc, 0xeb, 0x3b, - 0xaa, 0x0b, 0x18, 0x74, 0x58, 0x7c, 0x3e, 0x74, 0xef, 0xb6, - 0xd3, 0x15, 0xee, 0x73, 0x29, 0x88, 0x7b, 0x65, 0x02, 0x39, - 0x33, 0xec, 0x22, 0x06, 0x8c, 0x5b, 0xd6, 0x2f, 0x4c, 0xf7, - 0xe0, 0x97, 0x6d, 0x2a, 0x90, 0x36, 0xfe, 0x1a, 0x44, 0x4d, - 0x9d, 0x41, 0x4b, 0xcb, 0xec, 0x25, 0xf4, 0xc3, 0xa5, 0x91, - 0xd0, 0x90, 0xc9, 0x34, 0x7b, 0xba, 0x27, 0x30, 0x5a, 0xa2, - 0x21, 0x58, 0xce, 0x88, 0x25, 0x39, 0xaf, 0xf1, 0x17, 0x02, - 0x12, 0xf8, 0x55, 0xdc, 0xd2, 0x08, 0x5b, 0xd3, 0xc7, 0x8e, - 0xcf, 0x29, 0x85, 0x85, 0xdb, 0x5c, 0x08, 0xc2, 0xd7, 0xb0, - 0x33, 0x0e, 0xe3, 0xb9, 0x2c, 0x1a, 0x1d, 0x4b, 0xe5, 0x76, - 0x8f, 0xd3, 0x14, 0xb6, 0x8c, 0xdc, 0x9a, 0xe8, 0x15, 0x60, - 0x60, 0x5e, 0xaa, 0xf9, 0xfa, 0xa6, 0xb2, 0x4f, 0xff, 0x46, - 0xc1, 0x5e, 0x93, 0x50, 0x90, 0x7e, 0x4c, 0x26, 0xd7, 0xbb, - 0x21, 0x05, 0x3d, 0x27, 0xc5, 0x9b, 0x0d, 0x46, 0x69, 0xe4, - 0x74, 0x87, 0x74, 0x55, 0xee, 0x5f, 0xe5, 0x72, 0x04, 0x46, - 0x1f, 0x2e, 0x55, 0xc7, 0xcc, 0x2b, 0x2b, 0x39, 0x6d, 0x90, - 0x60, 0x31, 0x37, 0x5b, 0x44, 0xde, 0xfd, 0xf2, 0xd1, 0xc6, - 0x9c, 0x12, 0x82, 0xcc, 0x7c, 0xb1, 0x0e, 0xa9, 0x95, 0x9d, - 0xe0, 0xa8, 0x3e, 0xc1, 0xa3, 0x4a, 0x6a, 0x37, 0x59, 0x17, - 0x93, 0x63, 0x1e, 0xbf, 0x04, 0xa3, 0xaa, 0xc0, 0x1d, 0xc4, - 0x6d, 0x7a, 0xdc, 0x69, 0x9c, 0xb0, 0x22, 0x56, 0xd9, 0x76, - 0x92, 0x2d, 0x1e, 0x62, 0xae, 0xfd, 0xd6, 0x9b, 0xfd, 0x08, - 0x2c, 0x95, 0xec, 0xe7, 0x02, 0x43, 0x62, 0x68, 0x1a, 0xaf, - 0x46, 0x59, 0xb7, 0xce, 0x8e, 0x42, 0x24, 0xae, 0xf7, 0x0e, - 0x9a, 0x3b, 0xf8, 0x77, 0xdf, 0x26, 0x85, 0x9f, 0x45, 0xad, - 0x8c, 0xa9, 0x54, 0x9c, 0x46, 0x44, 0xd5, 0x8a, 0xe9, 0xcc, - 0x34, 0x5e, 0xc5, 0xd1, 0x42, 0x6f, 0x44, 0xf3, 0x0f, 0x90, - 0x3a, 0x32, 0x1a, 0x9c, 0x2a, 0x63, 0xec, 0x21, 0xb4, 0xfc, - 0xfa, 0xa5, 0xcf, 0xe7, 0x9e, 0x43, 0xc7, 0x49, 0x56, 0xbc, - 0x50, 0xc5, 0x84, 0xf0, 0x42, 0xc8, 0x6a, 0xf1, 0x78, 0xe4, - 0xaa, 0x06, 0x37, 0xe1, 0x30, 0xf7, 0x65, 0x97, 0xca, 0xfd, - 0x35, 0xfa, 0xeb, 0x48, 0x6d, 0xaa, 0x45, 0x46, 0x9d, 0xbc, - 0x1d, 0x98, 0x17, 0x45, 0xa3, 0xee, 0x21, 0xa0, 0x97, 0x38, - 0x80, 0xc5, 0x28, 0x1f, - }; + 0x06, 0x2c, 0x96, 0xae, 0x0e, 0x9e, 0x9b, + 0xbb, 0x41, 0x51, 0x7a, 0xa7, 0xc5, 0xfe }; static const uint8_t test_y[] = { /* y=g^x mod p */ - 0x93, 0xeb, 0x5c, 0x37, 0x1d, 0x3c, 0x06, 0x6f, 0xbf, 0xbe, - 0x96, 0x51, 0x26, 0x58, 0x81, 0x36, 0xc6, 0x4f, 0x9a, 0x34, - 0xc4, 0xc5, 0xa8, 0xa3, 0x2c, 0x41, 0x76, 0xa8, 0xc6, 0xc0, - 0xa0, 0xc8, 0x51, 0x36, 0xc4, 0x40, 0x4e, 0x2c, 0x69, 0xf7, - 0x51, 0xbb, 0xb0, 0xd6, 0xf5, 0xdb, 0x40, 0x29, 0x50, 0x3b, - 0x8a, 0xf9, 0xf3, 0x53, 0x78, 0xfc, 0x86, 0xe9, 0xf1, 0xe9, - 0xac, 0x85, 0x13, 0x65, 0x62, 0x22, 0x04, 0x1b, 0x14, 0x2a, - 0xf4, 0x8f, 0x2f, 0xf1, 0x2f, 0x81, 0xd6, 0x18, 0x0e, 0x76, - 0x91, 0x43, 0xb2, 0xfc, 0x7c, 0x6f, 0x0c, 0x45, 0x37, 0x31, - 0x31, 0x58, 0x5c, 0xdf, 0x42, 0x24, 0x7a, 0xba, 0x8b, 0x7f, - 0x79, 0x06, 0x07, 0xef, 0xd6, 0x06, 0xeb, 0xcb, 0x3c, 0xbd, - 0xbc, 0xe5, 0xff, 0xfd, 0x62, 0x15, 0x0c, 0x40, 0x46, 0x37, - 0xef, 0xd0, 0xa1, 0xde, 0x63, 0x4f, 0x20, 0x0b, 0x45, 0x7d, - 0x06, 0x77, 0xfd, 0x23, 0xc1, 0x32, 0x8a, 0x89, 0x65, 0x16, - 0xe8, 0x48, 0x12, 0x1c, 0x25, 0x33, 0x2d, 0xbd, 0xd8, 0x9f, - 0x1c, 0x9d, 0xbc, 0xe3, 0x08, 0x60, 0x87, 0x1a, 0xc6, 0x06, - 0x36, 0xd2, 0xac, 0x09, 0x6d, 0x99, 0x02, 0x89, 0xc6, 0x12, - 0x93, 0x8c, 0x4b, 0xd0, 0x7e, 0x36, 0x8a, 0xd6, 0xa0, 0x97, - 0x4f, 0x97, 0x3f, 0x97, 0x0b, 0xfe, 0x05, 0xfc, 0xc8, 0xef, - 0x21, 0x4d, 0x4a, 0x06, 0x6e, 0xb4, 0xa6, 0x4f, 0xe1, 0xdd, - 0x44, 0x06, 0xfa, 0xd5, 0x0e, 0x54, 0xf5, 0x54, 0x3e, 0x8c, - 0xb9, 0x85, 0x86, 0x00, 0x40, 0x98, 0xe7, 0x01, 0xdd, 0x93, - 0x9d, 0x95, 0xea, 0xf0, 0xd3, 0x99, 0x4b, 0xeb, 0xd5, 0x79, - 0x47, 0xa4, 0xad, 0x2a, 0xe0, 0x4d, 0x36, 0x3b, 0x46, 0x10, - 0x96, 0xbb, 0x48, 0xe9, 0xa1, 0x78, 0x01, 0x35, 0x0a, 0x5c, - 0x7b, 0x3f, 0xf5, 0xf7, 0xb1, 0xe3, 0x97, 0x17, 0x4d, 0x76, - 0x10, 0x8d, 0x68, 0x4c, 0x94, 0x7d, 0xee, 0x0e, 0x20, 0x8b, - 0xce, 0x7d, 0x0a, 0xa3, 0x51, 0xfb, 0xe6, 0xcf, 0xf0, 0x0e, - 0x7f, 0x3c, 0xd4, 0xef, 0x56, 0x31, 0xb2, 0x95, 0xf0, 0x5f, - 0x4b, 0x9c, 0x03, 0x9e, 0xae, 0xb1, 0xc1, 0x46, 0xd7, 0xc0, - 0x4f, 0xb0, 0xf6, 0x6c, 0xe1, 0xe9, 0x2a, 0x97, 0xe0, 0x3f, - 0x3a, 0x93, 0x04, 0xcd, 0x41, 0x7d, 0x45, 0x03, 0xb3, 0x40, - 0x20, 0xe6, 0xad, 0x2d, 0xd3, 0xf7, 0x32, 0x7b, 0xcc, 0x4f, - 0x81, 0x18, 0x4c, 0x50, 0x77, 0xc4, 0xb7, 0x6a, 0x4d, 0x05, - 0xd8, 0x6d, 0xbf, 0x6f, 0xba, 0x1d, 0x38, 0x78, 0x87, 0xd2, - 0x8e, 0xc2, 0x6d, 0xb6, 0xed, 0x66, 0x61, 0xa8, 0xb9, 0x19, - 0x0e, 0x93, 0xd1, 0xcd, 0x5b, 0xbe, 0x19, 0x05, 0x52, 0x43, - 0xd6, 0xc1, 0x07, 0x3c, 0x6a, 0x62, 0xbd, 0x33, 0x9b, 0x1b, - 0x02, 0x42, 0x61, 0x14, - }; + 0x1e, 0xca, 0x23, 0x2a, 0xfd, 0x34, 0xe1, + 0x10, 0x7a, 0xff, 0xaf, 0x2d, 0xaa, 0x53 }; gnutls_pk_params_init(&priv); gnutls_pk_params_init(&pub); priv.algo = pub.algo = GNUTLS_PK_DH; - ret = _gnutls_mpi_init_scan(&priv.params[DH_P], - gnutls_ffdhe_3072_group_prime.data, - gnutls_ffdhe_3072_group_prime.size); + ret = _gnutls_mpi_init_scan(&priv.params[DH_P], test_p, sizeof(test_p)); if (ret < 0) { gnutls_assert(); goto cleanup; } - ret = _gnutls_mpi_init_scan(&priv.params[DH_G], - gnutls_ffdhe_3072_group_generator.data, - gnutls_ffdhe_3072_group_generator.size); + ret = _gnutls_mpi_init_scan(&priv.params[DH_G], test_g, sizeof(test_g)); if (ret < 0) { gnutls_assert(); goto cleanup; diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c index 9be41a2..a589a77 100644 --- a/lib/crypto-selftests.c +++ b/lib/crypto-selftests.c @@ -2188,465 +2188,3 @@ int gnutls_digest_self_test(unsigned flags, gnutls_digest_algorithm_t digest) return 0; } - -struct hkdf_vectors_st { - const uint8_t *ikm; - unsigned int ikm_size; - const uint8_t *salt; - unsigned int salt_size; - const uint8_t *prk; - unsigned int prk_size; - const uint8_t *info; - unsigned int info_size; - const uint8_t *okm; - unsigned int okm_size; -}; - -const struct hkdf_vectors_st hkdf_sha256_vectors[] = { - /* RFC 5869: A.1. Test Case 1: Basic test case with SHA-256 */ - { - STR(ikm, ikm_size, - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"), - STR(salt, salt_size, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c"), - STR(prk, prk_size, - "\x07\x77\x09\x36\x2c\x2e\x32\xdf\x0d\xdc\x3f\x0d\xc4\x7b" - "\xba\x63\x90\xb6\xc7\x3b\xb5\x0f\x9c\x31\x22\xec\x84\x4a" - "\xd7\xc2\xb3\xe5"), - STR(info, info_size, - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9"), - STR(okm, okm_size, - "\x3c\xb2\x5f\x25\xfa\xac\xd5\x7a\x90\x43\x4f\x64\xd0\x36" - "\x2f\x2a\x2d\x2d\x0a\x90\xcf\x1a\x5a\x4c\x5d\xb0\x2d\x56" - "\xec\xc4\xc5\xbf\x34\x00\x72\x08\xd5\xb8\x87\x18\x58\x65"), - }, - /* RFC 5869: A.2. Test Case 2: Test with SHA-256 and longer inputs/outputs */ - { - STR(ikm, ikm_size, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d" - "\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b" - "\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29" - "\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37" - "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45" - "\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"), - STR(salt, salt_size, - "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d" - "\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b" - "\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89" - "\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97" - "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5" - "\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"), - STR(prk, prk_size, - "\x06\xa6\xb8\x8c\x58\x53\x36\x1a\x06\x10\x4c\x9c\xeb\x35" - "\xb4\x5c\xef\x76\x00\x14\x90\x46\x71\x01\x4a\x19\x3f\x40" - "\xc1\x5f\xc2\x44"), - STR(info, info_size, - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd" - "\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb" - "\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9" - "\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" - "\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5" - "\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"), - STR(okm, okm_size, - "\xb1\x1e\x39\x8d\xc8\x03\x27\xa1\xc8\xe7\xf7\x8c\x59\x6a" - "\x49\x34\x4f\x01\x2e\xda\x2d\x4e\xfa\xd8\xa0\x50\xcc\x4c" - "\x19\xaf\xa9\x7c\x59\x04\x5a\x99\xca\xc7\x82\x72\x71\xcb" - "\x41\xc6\x5e\x59\x0e\x09\xda\x32\x75\x60\x0c\x2f\x09\xb8" - "\x36\x77\x93\xa9\xac\xa3\xdb\x71\xcc\x30\xc5\x81\x79\xec" - "\x3e\x87\xc1\x4c\x01\xd5\xc1\xf3\x43\x4f\x1d\x87"), - }, -}; - -static int test_hkdf(gnutls_mac_algorithm_t mac, - const struct hkdf_vectors_st *vectors, - size_t vectors_size, unsigned flags) -{ - unsigned int i; - - for (i = 0; i < vectors_size; i++) { - gnutls_datum_t ikm, prk, salt, info; - uint8_t output[4096]; - int ret; - - ikm.data = (void *) vectors[i].ikm; - ikm.size = vectors[i].ikm_size; - salt.data = (void *) vectors[i].salt; - salt.size = vectors[i].salt_size; - - ret = gnutls_hkdf_extract(mac, &ikm, &salt, output); - if (ret < 0) { - _gnutls_debug_log("error extracting HKDF: MAC-%s\n", - gnutls_mac_get_name(mac)); - return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); - } - - if (memcmp(output, vectors[i].prk, vectors[i].prk_size) != 0) { - _gnutls_debug_log - ("HKDF extract: MAC-%s test vector failed!\n", - gnutls_mac_get_name(mac)); - - return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); - } - - prk.data = (void *) vectors[i].prk; - prk.size = vectors[i].prk_size; - info.data = (void *) vectors[i].info; - info.size = vectors[i].info_size; - - ret = gnutls_hkdf_expand(mac, &prk, &info, - output, vectors[i].okm_size); - if (ret < 0) { - _gnutls_debug_log("error extracting HKDF: MAC-%s\n", - gnutls_mac_get_name(mac)); - return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); - } - - if (memcmp(output, vectors[i].okm, vectors[i].okm_size) != 0) { - _gnutls_debug_log - ("HKDF expand: MAC-%s test vector failed!\n", - gnutls_mac_get_name(mac)); - - return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); - } - } - - _gnutls_debug_log - ("HKDF: MAC-%s self check succeeded\n", - gnutls_mac_get_name(mac)); - - return 0; -} - -/*- - * gnutls_hkdf_self_test: - * @flags: GNUTLS_SELF_TEST_FLAG flags - * @mac: the message authentication algorithm to use - * - * This function will run self tests on HKDF with the provided mac. - * - * Returns: Zero or a negative error code on error. - * - * Since: 3.3.0-FIPS140 - -*/ -int gnutls_hkdf_self_test(unsigned flags, gnutls_mac_algorithm_t mac) -{ - int ret; - - if (flags & GNUTLS_SELF_TEST_FLAG_ALL) - mac = GNUTLS_MAC_UNKNOWN; - - switch (mac) { - case GNUTLS_MAC_UNKNOWN: - CASE(GNUTLS_MAC_SHA256, test_hkdf, hkdf_sha256_vectors); - - break; - default: - return gnutls_assert_val(GNUTLS_E_NO_SELF_TEST); - } - - return 0; -} - -struct pbkdf2_vectors_st { - const uint8_t *key; - size_t key_size; - const uint8_t *salt; - size_t salt_size; - unsigned iter_count; - const uint8_t *output; - size_t output_size; -}; - -const struct pbkdf2_vectors_st pbkdf2_sha256_vectors[] = { - /* RFC 7914: 11. Test Vectors for PBKDF2 with HMAC-SHA-256 */ - { - STR(key, key_size, "passwd"), - STR(salt, salt_size, "salt"), - .iter_count = 1, - STR(output, output_size, - "\x55\xac\x04\x6e\x56\xe3\x08\x9f\xec\x16\x91\xc2\x25\x44" - "\xb6\x05\xf9\x41\x85\x21\x6d\xde\x04\x65\xe6\x8b\x9d\x57" - "\xc2\x0d\xac\xbc\x49\xca\x9c\xcc\xf1\x79\xb6\x45\x99\x16" - "\x64\xb3\x9d\x77\xef\x31\x7c\x71\xb8\x45\xb1\xe3\x0b\xd5" - "\x09\x11\x20\x41\xd3\xa1\x97\x83"), - }, - /* RFC 7914: 11. Test Vectors for PBKDF2 with HMAC-SHA-256 */ - { - STR(key, key_size, "Password"), - STR(salt, salt_size, "NaCl"), - .iter_count = 80000, - STR(output, output_size, - "\x4d\xdc\xd8\xf6\x0b\x98\xbe\x21\x83\x0c\xee\x5e\xf2\x27" - "\x01\xf9\x64\x1a\x44\x18\xd0\x4c\x04\x14\xae\xff\x08\x87" - "\x6b\x34\xab\x56\xa1\xd4\x25\xa1\x22\x58\x33\x54\x9a\xdb" - "\x84\x1b\x51\xc9\xb3\x17\x6a\x27\x2b\xde\xbb\xa1\xd0\x78" - "\x47\x8f\x62\xb3\x97\xf3\x3c\x8d"), - }, -}; - -static int test_pbkdf2(gnutls_mac_algorithm_t mac, - const struct pbkdf2_vectors_st *vectors, - size_t vectors_size, unsigned flags) -{ - unsigned int i; - - for (i = 0; i < vectors_size; i++) { - gnutls_datum_t key, salt; - uint8_t output[4096]; - int ret; - - key.data = (void *) vectors[i].key; - key.size = vectors[i].key_size; - salt.data = (void *) vectors[i].salt; - salt.size = vectors[i].salt_size; - - ret = gnutls_pbkdf2(mac, &key, &salt, vectors[i].iter_count, - output, vectors[i].output_size); - if (ret < 0) { - _gnutls_debug_log("error calculating PBKDF2: MAC-%s\n", - gnutls_mac_get_name(mac)); - return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); - } - - if (memcmp(output, vectors[i].output, vectors[i].output_size) != 0) { - _gnutls_debug_log - ("PBKDF2: MAC-%s test vector failed!\n", - gnutls_mac_get_name(mac)); - - return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); - } - } - - _gnutls_debug_log - ("PBKDF2: MAC-%s self check succeeded\n", - gnutls_mac_get_name(mac)); - - return 0; -} - -/*- - * gnutls_pbkdf2_self_test: - * @flags: GNUTLS_SELF_TEST_FLAG flags - * @mac: the message authentication algorithm to use - * - * This function will run self tests on PBKDF2 with the provided mac. - * - * Returns: Zero or a negative error code on error. - * - * Since: 3.3.0-FIPS140 - -*/ -int gnutls_pbkdf2_self_test(unsigned flags, gnutls_mac_algorithm_t mac) -{ - int ret; - - if (flags & GNUTLS_SELF_TEST_FLAG_ALL) - mac = GNUTLS_MAC_UNKNOWN; - - switch (mac) { - case GNUTLS_MAC_UNKNOWN: - CASE(GNUTLS_MAC_SHA256, test_pbkdf2, pbkdf2_sha256_vectors); - - break; - default: - return gnutls_assert_val(GNUTLS_E_NO_SELF_TEST); - } - - return 0; -} - -struct tlsprf_vectors_st { - const uint8_t *key; - size_t key_size; - const uint8_t *label; - size_t label_size; - const uint8_t *seed; - size_t seed_size; - const uint8_t *output; - size_t output_size; -}; - -const struct tlsprf_vectors_st tls10prf_vectors[] = { - /* tests/tls10-prf.c: test1 */ - { - STR(key, key_size, - "\x26\x3b\xdb\xbb\x6f\x6d\x4c\x66\x4e\x05\x8d\x0a\xa9\xd3" - "\x21\xbe"), - STR(label, label_size, - "test label"), - STR(seed, seed_size, - "\xb9\x20\x57\x3b\x19\x96\x01\x02\x4f\x04\xd6\xdc\x61\x96" - "\x6e\x65"), - STR(output, output_size, - "\x66\x17\x99\x37\x65\xfa\x6c\xa7\x03\xd1\x9e\xc7\x0d\xd5" - "\xdd\x16\x0f\xfc\xc0\x77\x25\xfa\xfb\x71\x4a\x9f\x81\x5a" - "\x2a\x30\xbf\xb7\xe3\xbb\xfb\x7e\xee\x57\x4b\x3b\x61\x3e" - "\xb7\xfe\x80\xee\xc9\x69\x1d\x8c\x1b\x0e\x2d\x9b\x3c\x8b" - "\x4b\x02\xb6\xb6\xd6\xdb\x88\xe2\x09\x46\x23\xef\x62\x40" - "\x60\x7e\xda\x7a\xbe\x3c\x84\x6e\x82\xa3"), - }, -}; - -const struct tlsprf_vectors_st tls12prf_sha256_vectors[] = { - /* tests/tls12-prf.c: sha256_test1 */ - { - STR(key, key_size, - "\x04\x50\xb0\xea\x9e\xcd\x36\x02\xee\x0d\x76\xc5\xc3\xc8" - "\x6f\x4a"), - STR(label, label_size, - "test label"), - STR(seed, seed_size, - "\x20\x7a\xcc\x02\x54\xb8\x67\xf5\xb9\x25\xb4\x5a\x33\x60" - "\x1d\x8b"), - STR(output, output_size, - "\xae\x67\x9e\x0e\x71\x4f\x59\x75\x76\x37\x68\xb1\x66\x97" - "\x9e\x1d"), - }, - /* tests/tls12-prf.c: sha256_test2 */ - { - STR(key, key_size, - "\x34\x20\x4a\x9d\xf0\xbe\x6e\xb4\xe9\x25\xa8\x02\x7c\xf6" - "\xc6\x02"), - STR(label, label_size, - "test label"), - STR(seed, seed_size, - "\x98\xb2\xc4\x0b\xcd\x66\x4c\x83\xbb\x92\x0c\x18\x20\x1a" - "\x63\x95"), - STR(output, output_size, - "\xaf\xa9\x31\x24\x53\xc2\x2f\xa8\x3d\x2b\x51\x1b\x37\x2d" - "\x73\xa4\x02\xa2\xa6\x28\x73\x23\x9a\x51\xfa\xde\x45\x08" - "\x2f\xaf\x3f\xd2\xbb\x7f\xfb\x3e\x9b\xf3\x6e\x28\xb3\x14" - "\x1a\xab\xa4\x84\x00\x53\x32\xa9\xf9\xe3\x88\xa4\xd3\x29" - "\xf1\x58\x7a\x4b\x31\x7d\xa0\x77\x08\xea\x1b\xa9\x5a\x53" - "\xf8\x78\x67\x24\xbd\x83\xce\x4b\x03\xaf"), - }, - /* tests/tls12-prf.c: sha256_test3 */ - { - STR(key, key_size, - "\xa3\x69\x1a\xa1\xf6\x81\x4b\x80\x59\x2b\xf1\xcf\x2a\xcf" - "\x16\x97"), - STR(label, label_size, - "test label"), - STR(seed, seed_size, - "\x55\x23\xd4\x1e\x32\x0e\x69\x4d\x0c\x1f\xf5\x73\x4d\x83" - "\x0b\x93\x3e\x46\x92\x70\x71\xc9\x26\x21"), - STR(output, output_size, - "\x6a\xd0\x98\x4f\xa0\x6f\x78\xfe\x16\x1b\xd4\x6d\x7c\x26" - "\x1d\xe4\x33\x40\xd7\x28\xdd\xdc\x3d\x0f\xf0\xdd\x7e\x0d"), - }, - /* tests/tls12-prf.c: sha256_test4 */ - { - STR(key, key_size, - "\x21\x0e\xc9\x37\x06\x97\x07\xe5\x46\x5b\xc4\x6b\xf7\x79" - "\xe1\x04\x10\x8b\x18\xfd\xb7\x93\xbe\x7b\x21\x8d\xbf\x14" - "\x5c\x86\x41\xf3"), - STR(label, label_size, - "test label"), - STR(seed, seed_size, - "\x1e\x35\x1a\x0b\xaf\x35\xc7\x99\x45\x92\x43\x94\xb8\x81" - "\xcf\xe3\x1d\xae\x8f\x1c\x1e\xd5\x4d\x3b"), - STR(output, output_size, - "\x76\x53\xfa\x80\x9c\xde\x3b\x55\x3c\x4a\x17\xe2\xcd\xbc" - "\xc9\x18\xf3\x65\x27\xf2\x22\x19\xa7\xd7\xf9\x5d\x97\x24" - "\x3f\xf2\xd5\xde\xe8\x26\x5e\xf0\xaf\x03"), - }, -}; - -const struct tlsprf_vectors_st tls12prf_sha384_vectors[] = { - /* tests/tls12-prf.c: sha384_test1 - * https://www.ietf.org/mail-archive/web/tls/current/msg03416.html - */ - { - STR(key, key_size, - "\xb8\x0b\x73\x3d\x6c\xee\xfc\xdc\x71\x56\x6e\xa4\x8e\x55" - "\x67\xdf"), - STR(label, label_size, - "test label"), - STR(seed, seed_size, - "\xcd\x66\x5c\xf6\xa8\x44\x7d\xd6\xff\x8b\x27\x55\x5e\xdb" - "\x74\x65"), - STR(output, output_size, - "\x7b\x0c\x18\xe9\xce\xd4\x10\xed\x18\x04\xf2\xcf\xa3\x4a" - "\x33\x6a\x1c\x14\xdf\xfb\x49\x00\xbb\x5f\xd7\x94\x21\x07" - "\xe8\x1c\x83\xcd\xe9\xca\x0f\xaa\x60\xbe\x9f\xe3\x4f\x82" - "\xb1\x23\x3c\x91\x46\xa0\xe5\x34\xcb\x40\x0f\xed\x27\x00" - "\x88\x4f\x9d\xc2\x36\xf8\x0e\xdd\x8b\xfa\x96\x11\x44\xc9" - "\xe8\xd7\x92\xec\xa7\x22\xa7\xb3\x2f\xc3\xd4\x16\xd4\x73" - "\xeb\xc2\xc5\xfd\x4a\xbf\xda\xd0\x5d\x91\x84\x25\x9b\x5b" - "\xf8\xcd\x4d\x90\xfa\x0d\x31\xe2\xde\xc4\x79\xe4\xf1\xa2" - "\x60\x66\xf2\xee\xa9\xa6\x92\x36\xa3\xe5\x26\x55\xc9\xe9" - "\xae\xe6\x91\xc8\xf3\xa2\x68\x54\x30\x8d\x5e\xaa\x3b\xe8" - "\x5e\x09\x90\x70\x3d\x73\xe5\x6f"), - }, -}; - -static int test_tlsprf(gnutls_mac_algorithm_t mac, - const struct tlsprf_vectors_st *vectors, - size_t vectors_size, unsigned flags) -{ - unsigned int i; - - for (i = 0; i < vectors_size; i++) { - char output[4096]; - int ret; - - ret = _gnutls_prf_raw(mac, - vectors[i].key_size, vectors[i].key, - vectors[i].label_size, (const char *)vectors[i].label, - vectors[i].seed_size, vectors[i].seed, - vectors[i].output_size, output); - if (ret < 0) { - _gnutls_debug_log("error calculating TLS-PRF: MAC-%s\n", - gnutls_mac_get_name(mac)); - return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); - } - - if (memcmp(output, vectors[i].output, vectors[i].output_size) != 0) { - _gnutls_debug_log - ("TLS-PRF: MAC-%s test vector failed!\n", - gnutls_mac_get_name(mac)); - - return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); - } - } - - _gnutls_debug_log - ("TLS-PRF: MAC-%s self check succeeded\n", - gnutls_mac_get_name(mac)); - - return 0; -} - -/*- - * gnutls_tlsprf_self_test: - * @flags: GNUTLS_SELF_TEST_FLAG flags - * @mac: the message authentication algorithm to use - * - * This function will run self tests on TLS-PRF with the provided mac. - * - * Returns: Zero or a negative error code on error. - * - * Since: 3.3.0-FIPS140 - -*/ -int gnutls_tlsprf_self_test(unsigned flags, gnutls_mac_algorithm_t mac) -{ - int ret; - - if (flags & GNUTLS_SELF_TEST_FLAG_ALL) - mac = GNUTLS_MAC_UNKNOWN; - - switch (mac) { - case GNUTLS_MAC_UNKNOWN: - NON_FIPS_CASE(GNUTLS_MAC_MD5_SHA1, test_tlsprf, tls10prf_vectors); - FALLTHROUGH; - CASE(GNUTLS_MAC_SHA256, test_tlsprf, tls12prf_sha256_vectors); - FALLTHROUGH; - CASE(GNUTLS_MAC_SHA384, test_tlsprf, tls12prf_sha384_vectors); - - break; - default: - return gnutls_assert_val(GNUTLS_E_NO_SELF_TEST); - } - - return 0; -} diff --git a/lib/dh-primes.c b/lib/dh-primes.c index 94b69e3..d785584 100644 --- a/lib/dh-primes.c +++ b/lib/dh-primes.c @@ -23,6 +23,8 @@ #include "gnutls_int.h" #include +#if defined(ENABLE_DHE) || defined(ENABLE_ANON) + #include "dh.h" static const unsigned char ffdhe_generator = 0x02; @@ -958,977 +960,4 @@ const gnutls_datum_t gnutls_ffdhe_8192_group_generator = { }; const unsigned int gnutls_ffdhe_8192_key_bits = 512; -static const unsigned char modp_generator = 0x02; - -static const unsigned char modp_params_2048[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, - 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, - 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, - 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, - 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, - 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, - 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, - 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, - 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, - 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, - 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, - 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, - 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, - 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, - 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, - 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, - 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, - 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, - 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, - 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, - 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, - 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, - 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, - 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, - 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, - 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, - 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, - 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, - 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, - 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, - 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF -}; - -static const unsigned char modp_q_2048[] = { - 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, - 0x61, 0x1A, 0x62, 0x63, 0x31, 0x45, 0xC0, - 0x6E, 0x0E, 0x68, 0x94, 0x81, 0x27, 0x04, - 0x45, 0x33, 0xE6, 0x3A, 0x01, 0x05, 0xDF, - 0x53, 0x1D, 0x89, 0xCD, 0x91, 0x28, 0xA5, - 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, 0xF7, - 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, - 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, - 0x1B, 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, - 0xE1, 0x22, 0xF2, 0x42, 0xDA, 0xBB, 0x31, - 0x2F, 0x3F, 0x63, 0x7A, 0x26, 0x21, 0x74, - 0xD3, 0x1B, 0xF6, 0xB5, 0x85, 0xFF, 0xAE, - 0x5B, 0x7A, 0x03, 0x5B, 0xF6, 0xF7, 0x1C, - 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, 0xD7, - 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, - 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, - 0x9E, 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, - 0xDF, 0x82, 0xCC, 0x6D, 0x24, 0x1B, 0x0E, - 0x2A, 0xE9, 0xCD, 0x34, 0x8B, 0x1F, 0xD4, - 0x7E, 0x92, 0x67, 0xAF, 0xC1, 0xB2, 0xAE, - 0x91, 0xEE, 0x51, 0xD6, 0xCB, 0x0E, 0x31, - 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, 0xCF, - 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, - 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, - 0x02, 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, - 0x10, 0xBE, 0x19, 0x48, 0x2F, 0x23, 0x17, - 0x1B, 0x67, 0x1D, 0xF1, 0xCF, 0x3B, 0x96, - 0x0C, 0x07, 0x43, 0x01, 0xCD, 0x93, 0xC1, - 0xD1, 0x76, 0x03, 0xD1, 0x47, 0xDA, 0xE2, - 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, 0xEF, - 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, - 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, - 0x72, 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, - 0x02, 0x88, 0x0A, 0xB9, 0x47, 0x2D, 0x45, - 0x56, 0x55, 0x34, 0x7F, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF -}; - -const gnutls_datum_t gnutls_modp_2048_group_prime = { - (void *) modp_params_2048, sizeof(modp_params_2048) -}; -const gnutls_datum_t gnutls_modp_2048_group_q = { - (void *) modp_q_2048, sizeof(modp_q_2048) -}; -const gnutls_datum_t gnutls_modp_2048_group_generator = { - (void *) &modp_generator, sizeof(modp_generator) -}; -const unsigned int gnutls_modp_2048_key_bits = 256; - -static const unsigned char modp_params_3072[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, - 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, - 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, - 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, - 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, - 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, - 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, - 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, - 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, - 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, - 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, - 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, - 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, - 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, - 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, - 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, - 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, - 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, - 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, - 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, - 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, - 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, - 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, - 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, - 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, - 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, - 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, - 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, - 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, - 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, - 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, - 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, - 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, - 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, - 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, - 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, - 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, - 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, - 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, - 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, - 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, - 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, - 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, - 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, - 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, - 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, - 0x20, 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -static const unsigned char modp_q_3072[] = { - 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, - 0x61, 0x1A, 0x62, 0x63, 0x31, 0x45, 0xC0, - 0x6E, 0x0E, 0x68, 0x94, 0x81, 0x27, 0x04, - 0x45, 0x33, 0xE6, 0x3A, 0x01, 0x05, 0xDF, - 0x53, 0x1D, 0x89, 0xCD, 0x91, 0x28, 0xA5, - 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, 0xF7, - 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, - 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, - 0x1B, 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, - 0xE1, 0x22, 0xF2, 0x42, 0xDA, 0xBB, 0x31, - 0x2F, 0x3F, 0x63, 0x7A, 0x26, 0x21, 0x74, - 0xD3, 0x1B, 0xF6, 0xB5, 0x85, 0xFF, 0xAE, - 0x5B, 0x7A, 0x03, 0x5B, 0xF6, 0xF7, 0x1C, - 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, 0xD7, - 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, - 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, - 0x9E, 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, - 0xDF, 0x82, 0xCC, 0x6D, 0x24, 0x1B, 0x0E, - 0x2A, 0xE9, 0xCD, 0x34, 0x8B, 0x1F, 0xD4, - 0x7E, 0x92, 0x67, 0xAF, 0xC1, 0xB2, 0xAE, - 0x91, 0xEE, 0x51, 0xD6, 0xCB, 0x0E, 0x31, - 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, 0xCF, - 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, - 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, - 0x02, 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, - 0x10, 0xBE, 0x19, 0x48, 0x2F, 0x23, 0x17, - 0x1B, 0x67, 0x1D, 0xF1, 0xCF, 0x3B, 0x96, - 0x0C, 0x07, 0x43, 0x01, 0xCD, 0x93, 0xC1, - 0xD1, 0x76, 0x03, 0xD1, 0x47, 0xDA, 0xE2, - 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, 0xEF, - 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, - 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, - 0x72, 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, - 0x02, 0x88, 0x0A, 0xB9, 0x47, 0x2D, 0x45, - 0x55, 0x62, 0x16, 0xD6, 0x99, 0x8B, 0x86, - 0x82, 0x28, 0x3D, 0x19, 0xD4, 0x2A, 0x90, - 0xD5, 0xEF, 0x8E, 0x5D, 0x32, 0x76, 0x7D, - 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, 0x45, - 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, - 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, - 0x63, 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, - 0x99, 0xEB, 0x8F, 0x46, 0x4A, 0x70, 0x25, - 0x12, 0xB0, 0xCE, 0xE7, 0x71, 0xE9, 0x13, - 0x0D, 0x69, 0x77, 0x35, 0xF8, 0x97, 0xFD, - 0x03, 0x6C, 0xC5, 0x04, 0x32, 0x6C, 0x3B, - 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, 0x29, - 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, - 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, - 0xB6, 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, - 0xA3, 0x71, 0x04, 0x71, 0x27, 0xD0, 0x3A, - 0x72, 0xD5, 0x98, 0xA1, 0xED, 0xAD, 0xFE, - 0x70, 0x7E, 0x88, 0x47, 0x25, 0xC1, 0x68, - 0x90, 0x54, 0x9D, 0x69, 0x65, 0x7F, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -const gnutls_datum_t gnutls_modp_3072_group_prime = { - (void *) modp_params_3072, sizeof(modp_params_3072) -}; -const gnutls_datum_t gnutls_modp_3072_group_q = { - (void *) modp_q_3072, sizeof(modp_q_3072) -}; -const gnutls_datum_t gnutls_modp_3072_group_generator = { - (void *) &modp_generator, sizeof(modp_generator) -}; -const unsigned int gnutls_modp_3072_key_bits = 276; - -static const unsigned char modp_params_4096[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, - 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, - 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, - 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, - 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, - 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, - 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, - 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, - 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, - 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, - 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, - 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, - 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, - 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, - 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, - 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, - 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, - 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, - 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, - 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, - 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, - 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, - 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, - 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, - 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, - 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, - 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, - 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, - 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, - 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, - 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, - 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, - 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, - 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, - 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, - 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, - 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, - 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, - 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, - 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, - 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, - 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, - 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, - 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, - 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, - 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, - 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, - 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, - 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, - 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, - 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, - 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, - 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, - 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, - 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, - 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, - 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, - 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, - 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, - 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, - 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, - 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, - 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, - 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, - 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF -}; - -static const unsigned char modp_q_4096[] = { - 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, - 0x61, 0x1A, 0x62, 0x63, 0x31, 0x45, 0xC0, - 0x6E, 0x0E, 0x68, 0x94, 0x81, 0x27, 0x04, - 0x45, 0x33, 0xE6, 0x3A, 0x01, 0x05, 0xDF, - 0x53, 0x1D, 0x89, 0xCD, 0x91, 0x28, 0xA5, - 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, 0xF7, - 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, - 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, - 0x1B, 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, - 0xE1, 0x22, 0xF2, 0x42, 0xDA, 0xBB, 0x31, - 0x2F, 0x3F, 0x63, 0x7A, 0x26, 0x21, 0x74, - 0xD3, 0x1B, 0xF6, 0xB5, 0x85, 0xFF, 0xAE, - 0x5B, 0x7A, 0x03, 0x5B, 0xF6, 0xF7, 0x1C, - 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, 0xD7, - 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, - 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, - 0x9E, 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, - 0xDF, 0x82, 0xCC, 0x6D, 0x24, 0x1B, 0x0E, - 0x2A, 0xE9, 0xCD, 0x34, 0x8B, 0x1F, 0xD4, - 0x7E, 0x92, 0x67, 0xAF, 0xC1, 0xB2, 0xAE, - 0x91, 0xEE, 0x51, 0xD6, 0xCB, 0x0E, 0x31, - 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, 0xCF, - 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, - 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, - 0x02, 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, - 0x10, 0xBE, 0x19, 0x48, 0x2F, 0x23, 0x17, - 0x1B, 0x67, 0x1D, 0xF1, 0xCF, 0x3B, 0x96, - 0x0C, 0x07, 0x43, 0x01, 0xCD, 0x93, 0xC1, - 0xD1, 0x76, 0x03, 0xD1, 0x47, 0xDA, 0xE2, - 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, 0xEF, - 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, - 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, - 0x72, 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, - 0x02, 0x88, 0x0A, 0xB9, 0x47, 0x2D, 0x45, - 0x55, 0x62, 0x16, 0xD6, 0x99, 0x8B, 0x86, - 0x82, 0x28, 0x3D, 0x19, 0xD4, 0x2A, 0x90, - 0xD5, 0xEF, 0x8E, 0x5D, 0x32, 0x76, 0x7D, - 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, 0x45, - 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, - 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, - 0x63, 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, - 0x99, 0xEB, 0x8F, 0x46, 0x4A, 0x70, 0x25, - 0x12, 0xB0, 0xCE, 0xE7, 0x71, 0xE9, 0x13, - 0x0D, 0x69, 0x77, 0x35, 0xF8, 0x97, 0xFD, - 0x03, 0x6C, 0xC5, 0x04, 0x32, 0x6C, 0x3B, - 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, 0x29, - 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, - 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, - 0xB6, 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, - 0xA3, 0x71, 0x04, 0x71, 0x27, 0xD0, 0x3A, - 0x72, 0xD5, 0x98, 0xA1, 0xED, 0xAD, 0xFE, - 0x70, 0x7E, 0x88, 0x47, 0x25, 0xC1, 0x68, - 0x90, 0x54, 0x90, 0x84, 0x00, 0x8D, 0x39, - 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B, 0xC4, - 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93, - 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, - 0x1E, 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, - 0x85, 0xED, 0x12, 0xC1, 0xF4, 0xE5, 0x15, - 0x6A, 0x26, 0x74, 0x6D, 0xDD, 0xE1, 0x6D, - 0x82, 0x6F, 0x47, 0x7C, 0x97, 0x47, 0x7E, - 0x0A, 0x0F, 0xDF, 0x65, 0x53, 0x14, 0x3E, - 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E, 0xCC, - 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1, - 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, - 0xF6, 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, - 0x6B, 0xD7, 0xDC, 0x0D, 0xEE, 0xBB, 0x10, - 0xB8, 0x24, 0x0E, 0x68, 0x03, 0x48, 0x93, - 0xEA, 0xD8, 0x2D, 0x54, 0xC9, 0xDA, 0x75, - 0x4C, 0x46, 0xC7, 0xEE, 0xE0, 0xC3, 0x7F, - 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47, 0xA6, - 0xFA, 0x1A, 0xE4, 0x9A, 0x03, 0x18, 0xCC, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF -}; - -const gnutls_datum_t gnutls_modp_4096_group_prime = { - (void *) modp_params_4096, sizeof(modp_params_4096) -}; -const gnutls_datum_t gnutls_modp_4096_group_q = { - (void *) modp_q_4096, sizeof(modp_q_4096) -}; -const gnutls_datum_t gnutls_modp_4096_group_generator = { - (void *) &modp_generator, sizeof(modp_generator) -}; -const unsigned int gnutls_modp_4096_key_bits = 336; - -static const unsigned char modp_params_6144[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, - 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, - 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, - 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, - 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, - 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, - 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, - 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, - 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, - 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, - 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, - 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, - 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, - 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, - 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, - 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, - 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, - 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, - 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, - 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, - 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, - 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, - 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, - 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, - 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, - 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, - 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, - 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, - 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, - 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, - 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, - 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, - 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, - 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, - 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, - 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, - 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, - 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, - 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, - 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, - 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, - 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, - 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, - 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, - 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, - 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, - 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, - 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, - 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, - 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, - 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, - 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, - 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, - 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, - 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, - 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, - 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, - 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, - 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, - 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, - 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, - 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, - 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, - 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, - 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, - 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, - 0x26, 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, - 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, - 0xBA, 0x37, 0xBD, 0xF8, 0xFF, 0x94, 0x06, - 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, - 0x2F, 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, - 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, 0x17, - 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, - 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, - 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, - 0xBB, 0x1B, 0xDB, 0x7F, 0x14, 0x47, 0xE6, - 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, - 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, - 0x01, 0x37, 0x8C, 0xD2, 0xBF, 0x59, 0x83, - 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, - 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, - 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, - 0xF6, 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, - 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, - 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, - 0xBE, 0xC7, 0xE8, 0xF3, 0x23, 0xA9, 0x7A, - 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, - 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, - 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, - 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, - 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, - 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, - 0x9B, 0xE3, 0x28, 0x06, 0xA1, 0xD5, 0x8B, - 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, - 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, - 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, 0xDA, - 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, - 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, - 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, - 0x60, 0xEE, 0x12, 0xBF, 0x2D, 0x5B, 0x0B, - 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E, - 0x6D, 0xCC, 0x40, 0x24, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -static const unsigned char modp_q_6144[] = { - 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, - 0x61, 0x1A, 0x62, 0x63, 0x31, 0x45, 0xC0, - 0x6E, 0x0E, 0x68, 0x94, 0x81, 0x27, 0x04, - 0x45, 0x33, 0xE6, 0x3A, 0x01, 0x05, 0xDF, - 0x53, 0x1D, 0x89, 0xCD, 0x91, 0x28, 0xA5, - 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, 0xF7, - 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, - 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, - 0x1B, 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, - 0xE1, 0x22, 0xF2, 0x42, 0xDA, 0xBB, 0x31, - 0x2F, 0x3F, 0x63, 0x7A, 0x26, 0x21, 0x74, - 0xD3, 0x1B, 0xF6, 0xB5, 0x85, 0xFF, 0xAE, - 0x5B, 0x7A, 0x03, 0x5B, 0xF6, 0xF7, 0x1C, - 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, 0xD7, - 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, - 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, - 0x9E, 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, - 0xDF, 0x82, 0xCC, 0x6D, 0x24, 0x1B, 0x0E, - 0x2A, 0xE9, 0xCD, 0x34, 0x8B, 0x1F, 0xD4, - 0x7E, 0x92, 0x67, 0xAF, 0xC1, 0xB2, 0xAE, - 0x91, 0xEE, 0x51, 0xD6, 0xCB, 0x0E, 0x31, - 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, 0xCF, - 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, - 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, - 0x02, 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, - 0x10, 0xBE, 0x19, 0x48, 0x2F, 0x23, 0x17, - 0x1B, 0x67, 0x1D, 0xF1, 0xCF, 0x3B, 0x96, - 0x0C, 0x07, 0x43, 0x01, 0xCD, 0x93, 0xC1, - 0xD1, 0x76, 0x03, 0xD1, 0x47, 0xDA, 0xE2, - 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, 0xEF, - 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, - 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, - 0x72, 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, - 0x02, 0x88, 0x0A, 0xB9, 0x47, 0x2D, 0x45, - 0x55, 0x62, 0x16, 0xD6, 0x99, 0x8B, 0x86, - 0x82, 0x28, 0x3D, 0x19, 0xD4, 0x2A, 0x90, - 0xD5, 0xEF, 0x8E, 0x5D, 0x32, 0x76, 0x7D, - 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, 0x45, - 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, - 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, - 0x63, 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, - 0x99, 0xEB, 0x8F, 0x46, 0x4A, 0x70, 0x25, - 0x12, 0xB0, 0xCE, 0xE7, 0x71, 0xE9, 0x13, - 0x0D, 0x69, 0x77, 0x35, 0xF8, 0x97, 0xFD, - 0x03, 0x6C, 0xC5, 0x04, 0x32, 0x6C, 0x3B, - 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, 0x29, - 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, - 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, - 0xB6, 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, - 0xA3, 0x71, 0x04, 0x71, 0x27, 0xD0, 0x3A, - 0x72, 0xD5, 0x98, 0xA1, 0xED, 0xAD, 0xFE, - 0x70, 0x7E, 0x88, 0x47, 0x25, 0xC1, 0x68, - 0x90, 0x54, 0x90, 0x84, 0x00, 0x8D, 0x39, - 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B, 0xC4, - 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93, - 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, - 0x1E, 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, - 0x85, 0xED, 0x12, 0xC1, 0xF4, 0xE5, 0x15, - 0x6A, 0x26, 0x74, 0x6D, 0xDD, 0xE1, 0x6D, - 0x82, 0x6F, 0x47, 0x7C, 0x97, 0x47, 0x7E, - 0x0A, 0x0F, 0xDF, 0x65, 0x53, 0x14, 0x3E, - 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E, 0xCC, - 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1, - 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, - 0xF6, 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, - 0x6B, 0xD7, 0xDC, 0x0D, 0xEE, 0xBB, 0x10, - 0xB8, 0x24, 0x0E, 0x68, 0x03, 0x48, 0x93, - 0xEA, 0xD8, 0x2D, 0x54, 0xC9, 0xDA, 0x75, - 0x4C, 0x46, 0xC7, 0xEE, 0xE0, 0xC3, 0x7F, - 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47, 0xA6, - 0xFA, 0x1A, 0xE4, 0x9A, 0x01, 0x42, 0x49, - 0x1B, 0x61, 0xFD, 0x5A, 0x69, 0x3E, 0x38, - 0x13, 0x60, 0xEA, 0x6E, 0x59, 0x30, 0x13, - 0x23, 0x6F, 0x64, 0xBA, 0x8F, 0x3B, 0x1E, - 0xDD, 0x1B, 0xDE, 0xFC, 0x7F, 0xCA, 0x03, - 0x56, 0xCF, 0x29, 0x87, 0x72, 0xED, 0x9C, - 0x17, 0xA0, 0x98, 0x00, 0xD7, 0x58, 0x35, - 0x29, 0xF6, 0xC8, 0x13, 0xEC, 0x18, 0x8B, - 0xCB, 0x93, 0xD8, 0x43, 0x2D, 0x44, 0x8C, - 0x6D, 0x1F, 0x6D, 0xF5, 0xE7, 0xCD, 0x8A, - 0x76, 0xA2, 0x67, 0x36, 0x5D, 0x67, 0x6A, - 0x5D, 0x8D, 0xED, 0xBF, 0x8A, 0x23, 0xF3, - 0x66, 0x12, 0xA5, 0x99, 0x90, 0x28, 0xA8, - 0x95, 0xEB, 0xD7, 0xA1, 0x37, 0xDC, 0x7A, - 0x00, 0x9B, 0xC6, 0x69, 0x5F, 0xAC, 0xC1, - 0xE5, 0x00, 0xE3, 0x25, 0xC9, 0x76, 0x78, - 0x19, 0x75, 0x0A, 0xE8, 0xB9, 0x0E, 0x81, - 0xFA, 0x41, 0x6B, 0xE7, 0x37, 0x3A, 0x7F, - 0x7B, 0x6A, 0xAF, 0x38, 0x17, 0xA3, 0x4C, - 0x06, 0x41, 0x5A, 0xD4, 0x20, 0x18, 0xC8, - 0x05, 0x8E, 0x4F, 0x2C, 0xF3, 0xE4, 0xBF, - 0xDF, 0x63, 0xF4, 0x79, 0x91, 0xD4, 0xBD, - 0x3F, 0x1B, 0x66, 0x44, 0x5F, 0x07, 0x8E, - 0xA2, 0xDB, 0xFF, 0xAC, 0x2D, 0x62, 0xA5, - 0xEA, 0x03, 0xD9, 0x15, 0xA0, 0xAA, 0x55, - 0x66, 0x47, 0xB6, 0xBF, 0x5F, 0xA4, 0x70, - 0xEC, 0x0A, 0x66, 0x2F, 0x69, 0x07, 0xC0, - 0x1B, 0xF0, 0x53, 0xCB, 0x8A, 0xF7, 0x79, - 0x4D, 0xF1, 0x94, 0x03, 0x50, 0xEA, 0xC5, - 0xDB, 0xE2, 0xED, 0x3B, 0x7A, 0xA8, 0x55, - 0x1E, 0xC5, 0x0F, 0xDF, 0xF8, 0x75, 0x8C, - 0xE6, 0x58, 0xD1, 0x89, 0xEA, 0xAE, 0x6D, - 0x2B, 0x64, 0xF6, 0x17, 0x79, 0x4B, 0x19, - 0x1C, 0x3F, 0xF4, 0x6B, 0xB7, 0x1E, 0x02, - 0x34, 0x02, 0x1F, 0x47, 0xB3, 0x1F, 0xA4, - 0x30, 0x77, 0x09, 0x5F, 0x96, 0xAD, 0x85, - 0xBA, 0x3A, 0x6B, 0x73, 0x4A, 0x7C, 0x8F, - 0x36, 0xE6, 0x20, 0x12, 0x7F, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -const gnutls_datum_t gnutls_modp_6144_group_prime = { - (void *) modp_params_6144, sizeof(modp_params_6144) -}; -const gnutls_datum_t gnutls_modp_6144_group_q = { - (void *) modp_q_6144, sizeof(modp_q_6144) -}; -const gnutls_datum_t gnutls_modp_6144_group_generator = { - (void *) &modp_generator, sizeof(modp_generator) -}; -const unsigned int gnutls_modp_6144_key_bits = 376; - -static const unsigned char modp_params_8192[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, - 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, - 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, - 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, - 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, - 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, - 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, - 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, - 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, - 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, - 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, - 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, - 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, - 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, - 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, - 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, - 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, - 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, - 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, - 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, - 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, - 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, - 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, - 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, - 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, - 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, - 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, - 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, - 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, - 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, - 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, - 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, - 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, - 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, - 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, - 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, - 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, - 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, - 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, - 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, - 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, - 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, - 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, - 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, - 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, - 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, - 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, - 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, - 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, - 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, - 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, - 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, - 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, - 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, - 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, - 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, - 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, - 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, - 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, - 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, - 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, - 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, - 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, - 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, - 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, - 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, - 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, - 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, - 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, - 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, - 0x26, 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, - 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, - 0xBA, 0x37, 0xBD, 0xF8, 0xFF, 0x94, 0x06, - 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, - 0x2F, 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, - 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, 0x17, - 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, - 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, - 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, - 0xBB, 0x1B, 0xDB, 0x7F, 0x14, 0x47, 0xE6, - 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, - 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, - 0x01, 0x37, 0x8C, 0xD2, 0xBF, 0x59, 0x83, - 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, - 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, - 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, - 0xF6, 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, - 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, - 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, - 0xBE, 0xC7, 0xE8, 0xF3, 0x23, 0xA9, 0x7A, - 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, - 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, - 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, - 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, - 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, - 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, - 0x9B, 0xE3, 0x28, 0x06, 0xA1, 0xD5, 0x8B, - 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, - 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, - 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, 0xDA, - 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, - 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, - 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, - 0x60, 0xEE, 0x12, 0xBF, 0x2D, 0x5B, 0x0B, - 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E, - 0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, - 0x6F, 0x12, 0xFE, 0xE5, 0xE4, 0x38, 0x77, - 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, - 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, - 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, - 0x00, 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, - 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93, 0x6B, - 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, - 0x5A, 0xE4, 0xF5, 0x68, 0x34, 0x23, 0xB4, - 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, - 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, 0xE3, - 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, - 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, - 0x07, 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, - 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, - 0xEA, 0x30, 0x6B, 0x4B, 0xCB, 0xC8, 0x86, - 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, - 0x7F, 0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, - 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, 0x06, - 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, - 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, - 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, - 0x6A, 0x36, 0x45, 0x97, 0xE8, 0x99, 0xA0, - 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5, - 0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, - 0x19, 0x5D, 0xED, 0x7E, 0xA1, 0xB1, 0xD5, - 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, - 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, - 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, - 0x92, 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, - 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E, 0xD5, - 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, - 0xFC, 0x02, 0x6E, 0x47, 0x95, 0x58, 0xE4, - 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, - 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, 0xC8, - 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, - 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, - 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF -}; - -static const unsigned char modp_q_8192[] = { - 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, - 0x61, 0x1A, 0x62, 0x63, 0x31, 0x45, 0xC0, - 0x6E, 0x0E, 0x68, 0x94, 0x81, 0x27, 0x04, - 0x45, 0x33, 0xE6, 0x3A, 0x01, 0x05, 0xDF, - 0x53, 0x1D, 0x89, 0xCD, 0x91, 0x28, 0xA5, - 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, 0xF7, - 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, - 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, - 0x1B, 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, - 0xE1, 0x22, 0xF2, 0x42, 0xDA, 0xBB, 0x31, - 0x2F, 0x3F, 0x63, 0x7A, 0x26, 0x21, 0x74, - 0xD3, 0x1B, 0xF6, 0xB5, 0x85, 0xFF, 0xAE, - 0x5B, 0x7A, 0x03, 0x5B, 0xF6, 0xF7, 0x1C, - 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, 0xD7, - 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, - 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, - 0x9E, 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, - 0xDF, 0x82, 0xCC, 0x6D, 0x24, 0x1B, 0x0E, - 0x2A, 0xE9, 0xCD, 0x34, 0x8B, 0x1F, 0xD4, - 0x7E, 0x92, 0x67, 0xAF, 0xC1, 0xB2, 0xAE, - 0x91, 0xEE, 0x51, 0xD6, 0xCB, 0x0E, 0x31, - 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, 0xCF, - 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, - 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, - 0x02, 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, - 0x10, 0xBE, 0x19, 0x48, 0x2F, 0x23, 0x17, - 0x1B, 0x67, 0x1D, 0xF1, 0xCF, 0x3B, 0x96, - 0x0C, 0x07, 0x43, 0x01, 0xCD, 0x93, 0xC1, - 0xD1, 0x76, 0x03, 0xD1, 0x47, 0xDA, 0xE2, - 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, 0xEF, - 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, - 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, - 0x72, 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, - 0x02, 0x88, 0x0A, 0xB9, 0x47, 0x2D, 0x45, - 0x55, 0x62, 0x16, 0xD6, 0x99, 0x8B, 0x86, - 0x82, 0x28, 0x3D, 0x19, 0xD4, 0x2A, 0x90, - 0xD5, 0xEF, 0x8E, 0x5D, 0x32, 0x76, 0x7D, - 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, 0x45, - 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, - 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, - 0x63, 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, - 0x99, 0xEB, 0x8F, 0x46, 0x4A, 0x70, 0x25, - 0x12, 0xB0, 0xCE, 0xE7, 0x71, 0xE9, 0x13, - 0x0D, 0x69, 0x77, 0x35, 0xF8, 0x97, 0xFD, - 0x03, 0x6C, 0xC5, 0x04, 0x32, 0x6C, 0x3B, - 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, 0x29, - 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, - 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, - 0xB6, 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, - 0xA3, 0x71, 0x04, 0x71, 0x27, 0xD0, 0x3A, - 0x72, 0xD5, 0x98, 0xA1, 0xED, 0xAD, 0xFE, - 0x70, 0x7E, 0x88, 0x47, 0x25, 0xC1, 0x68, - 0x90, 0x54, 0x90, 0x84, 0x00, 0x8D, 0x39, - 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B, 0xC4, - 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93, - 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, - 0x1E, 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, - 0x85, 0xED, 0x12, 0xC1, 0xF4, 0xE5, 0x15, - 0x6A, 0x26, 0x74, 0x6D, 0xDD, 0xE1, 0x6D, - 0x82, 0x6F, 0x47, 0x7C, 0x97, 0x47, 0x7E, - 0x0A, 0x0F, 0xDF, 0x65, 0x53, 0x14, 0x3E, - 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E, 0xCC, - 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1, - 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, - 0xF6, 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, - 0x6B, 0xD7, 0xDC, 0x0D, 0xEE, 0xBB, 0x10, - 0xB8, 0x24, 0x0E, 0x68, 0x03, 0x48, 0x93, - 0xEA, 0xD8, 0x2D, 0x54, 0xC9, 0xDA, 0x75, - 0x4C, 0x46, 0xC7, 0xEE, 0xE0, 0xC3, 0x7F, - 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47, 0xA6, - 0xFA, 0x1A, 0xE4, 0x9A, 0x01, 0x42, 0x49, - 0x1B, 0x61, 0xFD, 0x5A, 0x69, 0x3E, 0x38, - 0x13, 0x60, 0xEA, 0x6E, 0x59, 0x30, 0x13, - 0x23, 0x6F, 0x64, 0xBA, 0x8F, 0x3B, 0x1E, - 0xDD, 0x1B, 0xDE, 0xFC, 0x7F, 0xCA, 0x03, - 0x56, 0xCF, 0x29, 0x87, 0x72, 0xED, 0x9C, - 0x17, 0xA0, 0x98, 0x00, 0xD7, 0x58, 0x35, - 0x29, 0xF6, 0xC8, 0x13, 0xEC, 0x18, 0x8B, - 0xCB, 0x93, 0xD8, 0x43, 0x2D, 0x44, 0x8C, - 0x6D, 0x1F, 0x6D, 0xF5, 0xE7, 0xCD, 0x8A, - 0x76, 0xA2, 0x67, 0x36, 0x5D, 0x67, 0x6A, - 0x5D, 0x8D, 0xED, 0xBF, 0x8A, 0x23, 0xF3, - 0x66, 0x12, 0xA5, 0x99, 0x90, 0x28, 0xA8, - 0x95, 0xEB, 0xD7, 0xA1, 0x37, 0xDC, 0x7A, - 0x00, 0x9B, 0xC6, 0x69, 0x5F, 0xAC, 0xC1, - 0xE5, 0x00, 0xE3, 0x25, 0xC9, 0x76, 0x78, - 0x19, 0x75, 0x0A, 0xE8, 0xB9, 0x0E, 0x81, - 0xFA, 0x41, 0x6B, 0xE7, 0x37, 0x3A, 0x7F, - 0x7B, 0x6A, 0xAF, 0x38, 0x17, 0xA3, 0x4C, - 0x06, 0x41, 0x5A, 0xD4, 0x20, 0x18, 0xC8, - 0x05, 0x8E, 0x4F, 0x2C, 0xF3, 0xE4, 0xBF, - 0xDF, 0x63, 0xF4, 0x79, 0x91, 0xD4, 0xBD, - 0x3F, 0x1B, 0x66, 0x44, 0x5F, 0x07, 0x8E, - 0xA2, 0xDB, 0xFF, 0xAC, 0x2D, 0x62, 0xA5, - 0xEA, 0x03, 0xD9, 0x15, 0xA0, 0xAA, 0x55, - 0x66, 0x47, 0xB6, 0xBF, 0x5F, 0xA4, 0x70, - 0xEC, 0x0A, 0x66, 0x2F, 0x69, 0x07, 0xC0, - 0x1B, 0xF0, 0x53, 0xCB, 0x8A, 0xF7, 0x79, - 0x4D, 0xF1, 0x94, 0x03, 0x50, 0xEA, 0xC5, - 0xDB, 0xE2, 0xED, 0x3B, 0x7A, 0xA8, 0x55, - 0x1E, 0xC5, 0x0F, 0xDF, 0xF8, 0x75, 0x8C, - 0xE6, 0x58, 0xD1, 0x89, 0xEA, 0xAE, 0x6D, - 0x2B, 0x64, 0xF6, 0x17, 0x79, 0x4B, 0x19, - 0x1C, 0x3F, 0xF4, 0x6B, 0xB7, 0x1E, 0x02, - 0x34, 0x02, 0x1F, 0x47, 0xB3, 0x1F, 0xA4, - 0x30, 0x77, 0x09, 0x5F, 0x96, 0xAD, 0x85, - 0xBA, 0x3A, 0x6B, 0x73, 0x4A, 0x7C, 0x8F, - 0x36, 0xDF, 0x08, 0xAC, 0xBA, 0x51, 0xC9, - 0x37, 0x89, 0x7F, 0x72, 0xF2, 0x1C, 0x3B, - 0xBE, 0x5B, 0x54, 0x99, 0x6F, 0xC6, 0x6C, - 0x5F, 0x62, 0x68, 0x39, 0xDC, 0x98, 0xDD, - 0x1D, 0xE4, 0x19, 0x5B, 0x46, 0xCE, 0xE9, - 0x80, 0x3A, 0x0F, 0xD3, 0xDF, 0xC5, 0x7E, - 0x23, 0xF6, 0x92, 0xBB, 0x7B, 0x49, 0xB5, - 0xD2, 0x12, 0x33, 0x1D, 0x55, 0xB1, 0xCE, - 0x2D, 0x72, 0x7A, 0xB4, 0x1A, 0x11, 0xDA, - 0x3A, 0x15, 0xF8, 0xE4, 0xBC, 0x11, 0xC7, - 0x8B, 0x65, 0xF1, 0xCE, 0xB2, 0x96, 0xF1, - 0xFE, 0xDC, 0x5F, 0x7E, 0x42, 0x45, 0x6C, - 0x91, 0x11, 0x17, 0x02, 0x52, 0x01, 0xBE, - 0x03, 0x89, 0xF5, 0xAB, 0xD4, 0x0D, 0x11, - 0xF8, 0x63, 0x9A, 0x39, 0xFE, 0x32, 0x36, - 0x75, 0x18, 0x35, 0xA5, 0xE5, 0xE4, 0x43, - 0x17, 0xC1, 0xC2, 0xEE, 0xFD, 0x4E, 0xA5, - 0xBF, 0xD1, 0x60, 0x43, 0xF4, 0x3C, 0xB4, - 0x19, 0x81, 0xF6, 0xAD, 0xEE, 0x9D, 0x03, - 0x15, 0x9E, 0x7A, 0xD9, 0xD1, 0x3C, 0x53, - 0x36, 0x95, 0x09, 0xFC, 0x1F, 0xA2, 0x7C, - 0x16, 0xEF, 0x98, 0x87, 0x70, 0x3A, 0x55, - 0xB5, 0x1B, 0x22, 0xCB, 0xF4, 0x4C, 0xD0, - 0x12, 0xAE, 0xE0, 0xB2, 0x79, 0x8E, 0x62, - 0x84, 0x23, 0x42, 0x8E, 0xFC, 0xD5, 0xA4, - 0x0C, 0xAE, 0xF6, 0xBF, 0x50, 0xD8, 0xEA, - 0x88, 0x5E, 0xBF, 0x73, 0xA6, 0xB9, 0xFD, - 0x79, 0xB5, 0xE1, 0x8F, 0x67, 0xD1, 0x34, - 0x1A, 0xC8, 0x23, 0x7A, 0x75, 0xC3, 0xCF, - 0xC9, 0x20, 0x04, 0xA1, 0xC5, 0xA4, 0x0E, - 0x36, 0x6B, 0xC4, 0x4D, 0x00, 0x17, 0x6A, - 0xF7, 0x1C, 0x15, 0xE4, 0x8C, 0x86, 0xD3, - 0x7E, 0x01, 0x37, 0x23, 0xCA, 0xAC, 0x72, - 0x23, 0xAB, 0x3B, 0xF4, 0xD5, 0x4F, 0x18, - 0x28, 0x71, 0x3B, 0x2B, 0x4A, 0x6F, 0xE4, - 0x0F, 0xAB, 0x74, 0x40, 0x5C, 0xB7, 0x38, - 0xB0, 0x64, 0xC0, 0x6E, 0xCC, 0x76, 0xE9, - 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF -}; - -const gnutls_datum_t gnutls_modp_8192_group_prime = { - (void *) modp_params_8192, sizeof(modp_params_8192) -}; -const gnutls_datum_t gnutls_modp_8192_group_q = { - (void *) modp_q_8192, sizeof(modp_q_8192) -}; -const gnutls_datum_t gnutls_modp_8192_group_generator = { - (void *) &modp_generator, sizeof(modp_generator) -}; -const unsigned int gnutls_modp_8192_key_bits = 512; - -unsigned -_gnutls_dh_prime_match_fips_approved(const uint8_t *prime, - size_t prime_size, - const uint8_t *generator, - size_t generator_size, - uint8_t **q, - size_t *q_size) -{ - static const struct { - const gnutls_datum_t *prime; - const gnutls_datum_t *generator; - const gnutls_datum_t *q; - } primes[] = { - { &gnutls_ffdhe_8192_group_prime, &gnutls_ffdhe_8192_group_generator, &gnutls_ffdhe_8192_group_q }, - { &gnutls_ffdhe_6144_group_prime, &gnutls_ffdhe_6144_group_generator, &gnutls_ffdhe_6144_group_q }, - { &gnutls_ffdhe_4096_group_prime, &gnutls_ffdhe_4096_group_generator, &gnutls_ffdhe_4096_group_q }, - { &gnutls_ffdhe_3072_group_prime, &gnutls_ffdhe_3072_group_generator, &gnutls_ffdhe_3072_group_q }, - { &gnutls_ffdhe_2048_group_prime, &gnutls_ffdhe_2048_group_generator, &gnutls_ffdhe_2048_group_q }, - { &gnutls_modp_8192_group_prime, &gnutls_modp_8192_group_generator, &gnutls_modp_8192_group_q }, - { &gnutls_modp_6144_group_prime, &gnutls_modp_6144_group_generator, &gnutls_modp_6144_group_q }, - { &gnutls_modp_4096_group_prime, &gnutls_modp_4096_group_generator, &gnutls_modp_4096_group_q }, - { &gnutls_modp_3072_group_prime, &gnutls_modp_3072_group_generator, &gnutls_modp_3072_group_q }, - { &gnutls_modp_2048_group_prime, &gnutls_modp_2048_group_generator, &gnutls_modp_2048_group_q }, - }; - size_t i; - - for (i = 0; i < sizeof(primes) / sizeof(primes[0]); i++) { - if (primes[i].prime->size == prime_size && - memcmp(primes[i].prime->data, prime, primes[i].prime->size) == 0 && - primes[i].generator->size == generator_size && - memcmp(primes[i].generator->data, generator, primes[i].generator->size) == 0) { - if (q) { - *q = primes[i].q->data; - *q_size = primes[i].q->size; - } - return 1; - } - } - - return 0; -} +#endif diff --git a/lib/dh.h b/lib/dh.h index f5c2c09..9f3dc2a 100644 --- a/lib/dh.h +++ b/lib/dh.h @@ -31,41 +31,4 @@ _gnutls_figure_dh_params(gnutls_session_t session, gnutls_dh_params_t dh_params, int _gnutls_set_cred_dh_params(gnutls_dh_params_t *cparams, gnutls_sec_param_t sec_param); -/* The static parameters defined in RFC 3526, used for the approved - * primes check in SP800-56A (Appendix D). - */ - -extern const gnutls_datum_t gnutls_modp_8192_group_prime; -extern const gnutls_datum_t gnutls_modp_8192_group_q; -extern const gnutls_datum_t gnutls_modp_8192_group_generator; -extern const unsigned int gnutls_modp_8192_key_bits; - -extern const gnutls_datum_t gnutls_modp_6144_group_prime; -extern const gnutls_datum_t gnutls_modp_6144_group_q; -extern const gnutls_datum_t gnutls_modp_6144_group_generator; -extern const unsigned int gnutls_modp_6144_key_bits; - -extern const gnutls_datum_t gnutls_modp_4096_group_prime; -extern const gnutls_datum_t gnutls_modp_4096_group_q; -extern const gnutls_datum_t gnutls_modp_4096_group_generator; -extern const unsigned int gnutls_modp_4096_key_bits; - -extern const gnutls_datum_t gnutls_modp_3072_group_prime; -extern const gnutls_datum_t gnutls_modp_3072_group_q; -extern const gnutls_datum_t gnutls_modp_3072_group_generator; -extern const unsigned int gnutls_modp_3072_key_bits; - -extern const gnutls_datum_t gnutls_modp_2048_group_prime; -extern const gnutls_datum_t gnutls_modp_2048_group_q; -extern const gnutls_datum_t gnutls_modp_2048_group_generator; -extern const unsigned int gnutls_modp_2048_key_bits; - -unsigned -_gnutls_dh_prime_match_fips_approved(const uint8_t *prime, - size_t prime_size, - const uint8_t *generator, - size_t generator_size, - uint8_t **q, - size_t *q_size); - #endif /* GNUTLS_LIB_DH_H */ diff --git a/lib/ext/pre_shared_key.c b/lib/ext/pre_shared_key.c index 240be21..fef67d3 100644 --- a/lib/ext/pre_shared_key.c +++ b/lib/ext/pre_shared_key.c @@ -650,7 +650,7 @@ static int server_recv_params(gnutls_session_t session, } if (_gnutls_mac_get_algo_len(prf) != binder_recvd.size || - gnutls_memcmp(binder_value, binder_recvd.data, binder_recvd.size)) { + safe_memcmp(binder_value, binder_recvd.data, binder_recvd.size)) { gnutls_assert(); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto fail; diff --git a/lib/fips.c b/lib/fips.c index 5156795..acdd2ec 100644 --- a/lib/fips.c +++ b/lib/fips.c @@ -398,12 +398,6 @@ int _gnutls_fips_perform_self_checks2(void) goto error; } - ret = gnutls_mac_self_test(0, GNUTLS_MAC_AES_CMAC_256); - if (ret < 0) { - gnutls_assert(); - goto error; - } - /* PK */ ret = gnutls_pk_self_test(0, GNUTLS_PK_RSA); if (ret < 0) { @@ -429,27 +423,6 @@ int _gnutls_fips_perform_self_checks2(void) goto error; } - /* HKDF */ - ret = gnutls_hkdf_self_test(0, GNUTLS_MAC_SHA256); - if (ret < 0) { - gnutls_assert(); - goto error; - } - - /* PBKDF2 */ - ret = gnutls_pbkdf2_self_test(0, GNUTLS_MAC_SHA256); - if (ret < 0) { - gnutls_assert(); - goto error; - } - - /* TLS-PRF */ - ret = gnutls_tlsprf_self_test(0, GNUTLS_MAC_SHA256); - if (ret < 0) { - gnutls_assert(); - goto error; - } - if (_gnutls_rnd_ops.self_test == NULL) { gnutls_assert(); goto error; @@ -518,17 +491,8 @@ unsigned gnutls_fips140_mode_enabled(void) #ifdef ENABLE_FIPS140 unsigned ret = _gnutls_fips_mode_enabled(); - if (ret > GNUTLS_FIPS140_DISABLED) { - /* If the previous run of selftests has failed, return as if - * the FIPS mode is disabled. We could use HAVE_LIB_ERROR, if - * we can assume that all the selftests run atomically from - * the ELF constructor. - */ - if (_gnutls_get_lib_state() == LIB_STATE_ERROR) - return 0; - + if (ret > GNUTLS_FIPS140_DISABLED) return ret; - } #endif return 0; } diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index b9eace5..4db7a25 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -1370,7 +1370,6 @@ typedef struct { #define HSK_RECORD_SIZE_LIMIT_RECEIVED (1<<26) /* server: record_size_limit extension was seen but not accepted yet */ #define HSK_OCSP_REQUESTED (1<<27) /* server: client requested OCSP stapling */ #define HSK_CLIENT_OCSP_REQUESTED (1<<28) /* client: server requested OCSP stapling */ -#define HSK_SERVER_HELLO_RECEIVED (1<<29) /* client: Server Hello message has been received */ /* The hsk_flags are for use within the ongoing handshake; * they are reset to zero prior to handshake start by gnutls_handshake. */ diff --git a/lib/handshake.c b/lib/handshake.c index 06468ff..8d58fa4 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -2051,8 +2051,6 @@ read_server_hello(gnutls_session_t session, if (ret < 0) return gnutls_assert_val(ret); - session->internals.hsk_flags |= HSK_SERVER_HELLO_RECEIVED; - return 0; } @@ -2577,42 +2575,16 @@ int gnutls_rehandshake(gnutls_session_t session) return 0; } -/* This function checks whether the error code should be treated fatal - * or not, and also does the necessary state transition. In - * particular, in the case of a rehandshake abort it resets the - * handshake's internal state. - */ inline static int _gnutls_abort_handshake(gnutls_session_t session, int ret) { - switch (ret) { - case GNUTLS_E_WARNING_ALERT_RECEIVED: - if (gnutls_alert_get(session) == GNUTLS_A_NO_RENEGOTIATION) { - /* The server always toleretes a "no_renegotiation" alert. */ - if (session->security_parameters.entity == GNUTLS_SERVER) { - STATE = STATE0; - return ret; - } - - /* The client should tolerete a "no_renegotiation" alert only if: - * - the initial handshake has completed, or - * - a Server Hello is not yet received - */ - if (session->internals.initial_negotiation_completed || - !(session->internals.hsk_flags & HSK_SERVER_HELLO_RECEIVED)) { - STATE = STATE0; - return ret; - } + if (((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) && + (gnutls_alert_get(session) == GNUTLS_A_NO_RENEGOTIATION)) + || ret == GNUTLS_E_GOT_APPLICATION_DATA) + return 0; - return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); - } - return ret; - case GNUTLS_E_GOT_APPLICATION_DATA: - STATE = STATE0; - return ret; - default: - return ret; - } + /* this doesn't matter */ + return GNUTLS_E_INTERNAL_ERROR; } @@ -2774,7 +2746,13 @@ int gnutls_handshake(gnutls_session_t session) } if (ret < 0) { - return _gnutls_abort_handshake(session, ret); + /* In the case of a rehandshake abort + * we should reset the handshake's internal state. + */ + if (_gnutls_abort_handshake(session, ret) == 0) + STATE = STATE0; + + return ret; } /* clear handshake buffer */ diff --git a/lib/includes/gnutls/self-test.h b/lib/includes/gnutls/self-test.h index f9c0a53..8771749 100644 --- a/lib/includes/gnutls/self-test.h +++ b/lib/includes/gnutls/self-test.h @@ -34,8 +34,5 @@ int gnutls_cipher_self_test(unsigned flags, gnutls_cipher_algorithm_t cipher); int gnutls_mac_self_test(unsigned flags, gnutls_mac_algorithm_t mac); int gnutls_digest_self_test(unsigned flags, gnutls_digest_algorithm_t digest); int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk); -int gnutls_hkdf_self_test(unsigned flags, gnutls_mac_algorithm_t mac); -int gnutls_pbkdf2_self_test(unsigned flags, gnutls_mac_algorithm_t mac); -int gnutls_tlsprf_self_test(unsigned flags, gnutls_mac_algorithm_t mac); #endif diff --git a/lib/libgnutls.map b/lib/libgnutls.map index d2f7c0a..ac6be47 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1337,9 +1337,6 @@ GNUTLS_FIPS140_3_4 { gnutls_pk_self_test; gnutls_mac_self_test; gnutls_digest_self_test; - gnutls_hkdf_self_test; - gnutls_pbkdf2_self_test; - gnutls_tlsprf_self_test; #for FIPS140-2 validation drbg_aes_reseed; drbg_aes_init; diff --git a/lib/mem.h b/lib/mem.h index d3eea97..dc838a2 100644 --- a/lib/mem.h +++ b/lib/mem.h @@ -35,6 +35,15 @@ char *_gnutls_strdup(const char *); unsigned _gnutls_mem_is_zero(const uint8_t *ptr, unsigned size); +/* To avoid undefined behavior when s1 or s2 are null and n = 0 */ +inline static +int safe_memcmp(const void *s1, const void *s2, size_t n) +{ + if (n == 0) + return 0; + return memcmp(s1, s2, n); +} + #define zrelease_mpi_key(mpi) if (*mpi!=NULL) { \ _gnutls_mpi_clear(*mpi); \ _gnutls_mpi_release(mpi); \ diff --git a/lib/minitasn1/coding.c b/lib/minitasn1/coding.c new file mode 100644 index 0000000..245ea64 --- /dev/null +++ b/lib/minitasn1/coding.c @@ -0,0 +1,1415 @@ +/* + * Copyright (C) 2002-2014 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + + +/*****************************************************/ +/* File: coding.c */ +/* Description: Functions to create a DER coding of */ +/* an ASN1 type. */ +/*****************************************************/ + +#include +#include "parser_aux.h" +#include +#include "element.h" +#include "minmax.h" +#include + +#define MAX_TAG_LEN 16 + +/******************************************************/ +/* Function : _asn1_error_description_value_not_found */ +/* Description: creates the ErrorDescription string */ +/* for the ASN1_VALUE_NOT_FOUND error. */ +/* Parameters: */ +/* node: node of the tree where the value is NULL. */ +/* ErrorDescription: string returned. */ +/* Return: */ +/******************************************************/ +static void +_asn1_error_description_value_not_found (asn1_node node, + char *ErrorDescription) +{ + + if (ErrorDescription == NULL) + return; + + Estrcpy (ErrorDescription, ":: value of element '"); + _asn1_hierarchical_name (node, ErrorDescription + strlen (ErrorDescription), + ASN1_MAX_ERROR_DESCRIPTION_SIZE - 40); + Estrcat (ErrorDescription, "' not found"); + +} + +/** + * asn1_length_der: + * @len: value to convert. + * @der: buffer to hold the returned encoding (may be %NULL). + * @der_len: number of meaningful bytes of ANS (der[0]..der[der_len-1]). + * + * Creates the DER encoding of the provided length value. + * The @der buffer must have enough room for the output. The maximum + * length this function will encode is %ASN1_MAX_LENGTH_SIZE. + * + * To know the size of the DER encoding use a %NULL value for @der. + **/ +void +asn1_length_der (unsigned long int len, unsigned char *der, int *der_len) +{ + int k; + unsigned char temp[ASN1_MAX_LENGTH_SIZE]; +#if SIZEOF_UNSIGNED_LONG_INT > 8 + len &= 0xFFFFFFFFFFFFFFFF; +#endif + + if (len < 128) + { + /* short form */ + if (der != NULL) + der[0] = (unsigned char) len; + *der_len = 1; + } + else + { + /* Long form */ + k = 0; + while (len) + { + temp[k++] = len & 0xFF; + len = len >> 8; + } + *der_len = k + 1; + if (der != NULL) + { + der[0] = ((unsigned char) k & 0x7F) + 128; + while (k--) + der[*der_len - 1 - k] = temp[k]; + } + } +} + +/******************************************************/ +/* Function : _asn1_tag_der */ +/* Description: creates the DER coding for the CLASS */ +/* and TAG parameters. */ +/* It is limited by the ASN1_MAX_TAG_SIZE variable */ +/* Parameters: */ +/* class: value to convert. */ +/* tag_value: value to convert. */ +/* ans: string returned. */ +/* ans_len: number of meaningful bytes of ANS */ +/* (ans[0]..ans[ans_len-1]). */ +/* Return: */ +/******************************************************/ +static void +_asn1_tag_der (unsigned char class, unsigned int tag_value, + unsigned char ans[ASN1_MAX_TAG_SIZE], int *ans_len) +{ + int k; + unsigned char temp[ASN1_MAX_TAG_SIZE]; + + if (tag_value < 31) + { + /* short form */ + ans[0] = (class & 0xE0) + ((unsigned char) (tag_value & 0x1F)); + *ans_len = 1; + } + else + { + /* Long form */ + ans[0] = (class & 0xE0) + 31; + k = 0; + while (tag_value != 0) + { + temp[k++] = tag_value & 0x7F; + tag_value >>= 7; + + if (k > ASN1_MAX_TAG_SIZE - 1) + break; /* will not encode larger tags */ + } + *ans_len = k + 1; + while (k--) + ans[*ans_len - 1 - k] = temp[k] + 128; + ans[*ans_len - 1] -= 128; + } +} + +/** + * asn1_octet_der: + * @str: the input data. + * @str_len: STR length (str[0]..str[*str_len-1]). + * @der: encoded string returned. + * @der_len: number of meaningful bytes of DER (der[0]..der[der_len-1]). + * + * Creates a length-value DER encoding for the input data. + * The DER encoding of the input data will be placed in the @der variable. + * + * Note that the OCTET STRING tag is not included in the output. + * + * This function does not return any value because it is expected + * that @der_len will contain enough bytes to store the string + * plus the DER encoding. The DER encoding size can be obtained using + * asn1_length_der(). + **/ +void +asn1_octet_der (const unsigned char *str, int str_len, + unsigned char *der, int *der_len) +{ + int len_len; + + if (der == NULL || str_len < 0) + return; + + asn1_length_der (str_len, der, &len_len); + memcpy (der + len_len, str, str_len); + *der_len = str_len + len_len; +} + + +/** + * asn1_encode_simple_der: + * @etype: The type of the string to be encoded (ASN1_ETYPE_) + * @str: the string data. + * @str_len: the string length + * @tl: the encoded tag and length + * @tl_len: the bytes of the @tl field + * + * Creates the DER encoding for various simple ASN.1 types like strings etc. + * It stores the tag and length in @tl, which should have space for at least + * %ASN1_MAX_TL_SIZE bytes. Initially @tl_len should contain the size of @tl. + * + * The complete DER encoding should consist of the value in @tl appended + * with the provided @str. + * + * Returns: %ASN1_SUCCESS if successful or an error value. + **/ +int +asn1_encode_simple_der (unsigned int etype, const unsigned char *str, + unsigned int str_len, unsigned char *tl, + unsigned int *tl_len) +{ + int tag_len, len_len; + unsigned tlen; + unsigned char der_tag[ASN1_MAX_TAG_SIZE]; + unsigned char der_length[ASN1_MAX_LENGTH_SIZE]; + unsigned char *p; + + if (str == NULL) + return ASN1_VALUE_NOT_VALID; + + if (ETYPE_OK (etype) == 0) + return ASN1_VALUE_NOT_VALID; + + /* doesn't handle constructed classes */ + if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL) + return ASN1_VALUE_NOT_VALID; + + _asn1_tag_der (ETYPE_CLASS (etype), ETYPE_TAG (etype), der_tag, &tag_len); + + asn1_length_der (str_len, der_length, &len_len); + + if (tag_len <= 0 || len_len <= 0) + return ASN1_VALUE_NOT_VALID; + + tlen = tag_len + len_len; + + if (*tl_len < tlen) + return ASN1_MEM_ERROR; + + p = tl; + memcpy (p, der_tag, tag_len); + p += tag_len; + memcpy (p, der_length, len_len); + + *tl_len = tlen; + + return ASN1_SUCCESS; +} + +/******************************************************/ +/* Function : _asn1_time_der */ +/* Description: creates the DER coding for a TIME */ +/* type (length included). */ +/* Parameters: */ +/* str: TIME null-terminated string. */ +/* der: string returned. */ +/* der_len: number of meaningful bytes of DER */ +/* (der[0]..der[ans_len-1]). Initially it */ +/* if must store the lenght of DER. */ +/* Return: */ +/* ASN1_MEM_ERROR when DER isn't big enough */ +/* ASN1_SUCCESS otherwise */ +/******************************************************/ +static int +_asn1_time_der (unsigned char *str, int str_len, unsigned char *der, + int *der_len) +{ + int len_len; + int max_len; + + if (der == NULL) + return ASN1_VALUE_NOT_VALID; + + max_len = *der_len; + + asn1_length_der (str_len, (max_len > 0) ? der : NULL, &len_len); + + if ((len_len + str_len) <= max_len) + memcpy (der + len_len, str, str_len); + *der_len = len_len + str_len; + + if ((*der_len) > max_len) + return ASN1_MEM_ERROR; + + return ASN1_SUCCESS; +} + + +/* +void +_asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str) +{ + int len_len,str_len; + char temp[20]; + + if(str==NULL) return; + str_len=asn1_get_length_der(der,*der_len,&len_len); + if (str_len<0) return; + memcpy(temp,der+len_len,str_len); + *der_len=str_len+len_len; + switch(str_len) + { + case 11: + temp[10]=0; + strcat(temp,"00+0000"); + break; + case 13: + temp[12]=0; + strcat(temp,"+0000"); + break; + case 15: + temp[15]=0; + memmove(temp+12,temp+10,6); + temp[10]=temp[11]='0'; + break; + case 17: + temp[17]=0; + break; + default: + return; + } + strcpy(str,temp); +} +*/ + +static +void encode_val(uint64_t val, unsigned char *der, int max_len, int *der_len) +{ + int first, k; + unsigned char bit7; + + first = 0; + for (k = sizeof(val); k >= 0; k--) + { + bit7 = (val >> (k * 7)) & 0x7F; + if (bit7 || first || !k) + { + if (k) + bit7 |= 0x80; + if (max_len > (*der_len)) + der[*der_len] = bit7; + (*der_len)++; + first = 1; + } + } +} + +/******************************************************/ +/* Function : _asn1_object_id_der */ +/* Description: creates the DER coding for an */ +/* OBJECT IDENTIFIER type (length included). */ +/* Parameters: */ +/* str: OBJECT IDENTIFIER null-terminated string. */ +/* der: string returned. */ +/* der_len: number of meaningful bytes of DER */ +/* (der[0]..der[ans_len-1]). Initially it */ +/* must store the length of DER. */ +/* Return: */ +/* ASN1_MEM_ERROR when DER isn't big enough */ +/* ASN1_SUCCESS if succesful */ +/* or an error value. */ +/******************************************************/ +static int +_asn1_object_id_der (const char *str, unsigned char *der, int *der_len) +{ + int len_len, counter, max_len; + char *temp, *n_end, *n_start; + uint64_t val, val1 = 0; + int str_len = _asn1_strlen (str); + + max_len = *der_len; + *der_len = 0; + + if (der == NULL && max_len > 0) + return ASN1_VALUE_NOT_VALID; + + temp = malloc (str_len + 2); + if (temp == NULL) + return ASN1_MEM_ALLOC_ERROR; + + memcpy (temp, str, str_len); + temp[str_len] = '.'; + temp[str_len + 1] = 0; + + counter = 0; + n_start = temp; + while ((n_end = strchr (n_start, '.'))) + { + *n_end = 0; + val = _asn1_strtou64 (n_start, NULL, 10); + counter++; + + if (counter == 1) + { + val1 = val; + } + else if (counter == 2) + { + uint64_t val0; + + if (val1 > 2) + { + free(temp); + return ASN1_VALUE_NOT_VALID; + } + else if ((val1 == 0 || val1 == 1) && val > 39) + { + free(temp); + return ASN1_VALUE_NOT_VALID; + } + + val0 = 40 * val1 + val; + encode_val(val0, der, max_len, der_len); + } + else + { + encode_val(val, der, max_len, der_len); + } + n_start = n_end + 1; + } + + asn1_length_der (*der_len, NULL, &len_len); + if (max_len >= (*der_len + len_len)) + { + memmove (der + len_len, der, *der_len); + asn1_length_der (*der_len, der, &len_len); + } + *der_len += len_len; + + free (temp); + + if (max_len < (*der_len)) + return ASN1_MEM_ERROR; + + return ASN1_SUCCESS; +} + +/** + * asn1_object_id_der: + * @str: An object identifier in numeric, dot format. + * @der: buffer to hold the returned encoding (may be %NULL). + * @der_len: initially the size of @der; will hold the final size. + * @flags: must be zero + * + * Creates the DER encoding of the provided object identifier. + * + * Returns: %ASN1_SUCCESS if DER encoding was OK, %ASN1_VALUE_NOT_VALID + * if @str is not a valid OID, %ASN1_MEM_ERROR if the @der + * vector isn't big enough and in this case @der_len will contain the + * length needed. + **/ +int asn1_object_id_der(const char *str, unsigned char *der, int *der_len, unsigned flags) +{ + unsigned char tag_der[MAX_TAG_LEN]; + int tag_len = 0, r; + int max_len = *der_len; + + *der_len = 0; + + _asn1_tag_der (ETYPE_CLASS (ASN1_ETYPE_OBJECT_ID), ETYPE_TAG (ASN1_ETYPE_OBJECT_ID), + tag_der, &tag_len); + + if (max_len > tag_len) + { + memcpy(der, tag_der, tag_len); + } + max_len -= tag_len; + der += tag_len; + + r = _asn1_object_id_der (str, der, &max_len); + if (r == ASN1_MEM_ERROR || r == ASN1_SUCCESS) + { + *der_len = max_len + tag_len; + } + + return r; +} + +static const unsigned char bit_mask[] = + { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 }; + +/** + * asn1_bit_der: + * @str: BIT string. + * @bit_len: number of meaningful bits in STR. + * @der: string returned. + * @der_len: number of meaningful bytes of DER + * (der[0]..der[ans_len-1]). + * + * Creates a length-value DER encoding for the input data + * as it would have been for a BIT STRING. + * The DER encoded data will be copied in @der. + * + * Note that the BIT STRING tag is not included in the output. + * + * This function does not return any value because it is expected + * that @der_len will contain enough bytes to store the string + * plus the DER encoding. The DER encoding size can be obtained using + * asn1_length_der(). + **/ +void +asn1_bit_der (const unsigned char *str, int bit_len, + unsigned char *der, int *der_len) +{ + int len_len, len_byte, len_pad; + + if (der == NULL) + return; + + len_byte = bit_len >> 3; + len_pad = 8 - (bit_len & 7); + if (len_pad == 8) + len_pad = 0; + else + len_byte++; + asn1_length_der (len_byte + 1, der, &len_len); + der[len_len] = len_pad; + + if (str) + memcpy (der + len_len + 1, str, len_byte); + der[len_len + len_byte] &= bit_mask[len_pad]; + *der_len = len_byte + len_len + 1; +} + + +/******************************************************/ +/* Function : _asn1_complete_explicit_tag */ +/* Description: add the length coding to the EXPLICIT */ +/* tags. */ +/* Parameters: */ +/* node: pointer to the tree element. */ +/* der: string with the DER coding of the whole tree*/ +/* counter: number of meaningful bytes of DER */ +/* (der[0]..der[*counter-1]). */ +/* max_len: size of der vector */ +/* Return: */ +/* ASN1_MEM_ERROR if der vector isn't big enough, */ +/* otherwise ASN1_SUCCESS. */ +/******************************************************/ +static int +_asn1_complete_explicit_tag (asn1_node node, unsigned char *der, + int *counter, int *max_len) +{ + asn1_node p; + int is_tag_implicit, len2, len3; + unsigned char temp[SIZEOF_UNSIGNED_INT]; + + if (der == NULL && *max_len > 0) + return ASN1_VALUE_NOT_VALID; + + is_tag_implicit = 0; + + if (node->type & CONST_TAG) + { + p = node->down; + if (p == NULL) + return ASN1_DER_ERROR; + /* When there are nested tags we must complete them reverse to + the order they were created. This is because completing a tag + modifies all data within it, including the incomplete tags + which store buffer positions -- simon@josefsson.org 2002-09-06 + */ + while (p->right) + p = p->right; + while (p && p != node->down->left) + { + if (type_field (p->type) == ASN1_ETYPE_TAG) + { + if (p->type & CONST_EXPLICIT) + { + len2 = strtol (p->name, NULL, 10); + _asn1_set_name (p, NULL); + + asn1_length_der (*counter - len2, temp, &len3); + if (len3 <= (*max_len)) + { + memmove (der + len2 + len3, der + len2, + *counter - len2); + memcpy (der + len2, temp, len3); + } + *max_len -= len3; + *counter += len3; + is_tag_implicit = 0; + } + else + { /* CONST_IMPLICIT */ + if (!is_tag_implicit) + { + is_tag_implicit = 1; + } + } + } + p = p->left; + } + } + + if (*max_len < 0) + return ASN1_MEM_ERROR; + + return ASN1_SUCCESS; +} + +const tag_and_class_st _asn1_tags[] = { + [ASN1_ETYPE_GENERALSTRING] = + {ASN1_TAG_GENERALSTRING, ASN1_CLASS_UNIVERSAL, "type:GENERALSTRING"}, + [ASN1_ETYPE_NUMERIC_STRING] = + {ASN1_TAG_NUMERIC_STRING, ASN1_CLASS_UNIVERSAL, "type:NUMERIC_STR"}, + [ASN1_ETYPE_IA5_STRING] = + {ASN1_TAG_IA5_STRING, ASN1_CLASS_UNIVERSAL, "type:IA5_STR"}, + [ASN1_ETYPE_TELETEX_STRING] = + {ASN1_TAG_TELETEX_STRING, ASN1_CLASS_UNIVERSAL, "type:TELETEX_STR"}, + [ASN1_ETYPE_PRINTABLE_STRING] = + {ASN1_TAG_PRINTABLE_STRING, ASN1_CLASS_UNIVERSAL, "type:PRINTABLE_STR"}, + [ASN1_ETYPE_UNIVERSAL_STRING] = + {ASN1_TAG_UNIVERSAL_STRING, ASN1_CLASS_UNIVERSAL, "type:UNIVERSAL_STR"}, + [ASN1_ETYPE_BMP_STRING] = + {ASN1_TAG_BMP_STRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"}, + [ASN1_ETYPE_UTF8_STRING] = + {ASN1_TAG_UTF8_STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"}, + [ASN1_ETYPE_VISIBLE_STRING] = + {ASN1_TAG_VISIBLE_STRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"}, + [ASN1_ETYPE_OCTET_STRING] = + {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"}, + [ASN1_ETYPE_BIT_STRING] = + {ASN1_TAG_BIT_STRING, ASN1_CLASS_UNIVERSAL, "type:BIT_STR"}, + [ASN1_ETYPE_OBJECT_ID] = + {ASN1_TAG_OBJECT_ID, ASN1_CLASS_UNIVERSAL, "type:OBJ_ID"}, + [ASN1_ETYPE_NULL] = {ASN1_TAG_NULL, ASN1_CLASS_UNIVERSAL, "type:NULL"}, + [ASN1_ETYPE_BOOLEAN] = + {ASN1_TAG_BOOLEAN, ASN1_CLASS_UNIVERSAL, "type:BOOLEAN"}, + [ASN1_ETYPE_INTEGER] = + {ASN1_TAG_INTEGER, ASN1_CLASS_UNIVERSAL, "type:INTEGER"}, + [ASN1_ETYPE_ENUMERATED] = + {ASN1_TAG_ENUMERATED, ASN1_CLASS_UNIVERSAL, "type:ENUMERATED"}, + [ASN1_ETYPE_SEQUENCE] = + {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, + "type:SEQUENCE"}, + [ASN1_ETYPE_SEQUENCE_OF] = + {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, + "type:SEQ_OF"}, + [ASN1_ETYPE_SET] = + {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET"}, + [ASN1_ETYPE_SET_OF] = + {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, + "type:SET_OF"}, + [ASN1_ETYPE_GENERALIZED_TIME] = + {ASN1_TAG_GENERALIZEDTime, ASN1_CLASS_UNIVERSAL, "type:GENERALIZED_TIME"}, + [ASN1_ETYPE_UTC_TIME] = + {ASN1_TAG_UTCTime, ASN1_CLASS_UNIVERSAL, "type:UTC_TIME"}, +}; + +unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]); + +/******************************************************/ +/* Function : _asn1_insert_tag_der */ +/* Description: creates the DER coding of tags of one */ +/* NODE. */ +/* Parameters: */ +/* node: pointer to the tree element. */ +/* der: string returned */ +/* counter: number of meaningful bytes of DER */ +/* (counter[0]..der[*counter-1]). */ +/* max_len: size of der vector */ +/* Return: */ +/* ASN1_GENERIC_ERROR if the type is unknown, */ +/* ASN1_MEM_ERROR if der vector isn't big enough, */ +/* otherwise ASN1_SUCCESS. */ +/******************************************************/ +static int +_asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter, + int *max_len) +{ + asn1_node p; + int tag_len, is_tag_implicit; + unsigned char class, class_implicit = 0, temp[MAX(SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)]; + unsigned long tag_implicit = 0; + unsigned char tag_der[MAX_TAG_LEN]; + + is_tag_implicit = 0; + + if (node->type & CONST_TAG) + { + p = node->down; + while (p) + { + if (type_field (p->type) == ASN1_ETYPE_TAG) + { + if (p->type & CONST_APPLICATION) + class = ASN1_CLASS_APPLICATION; + else if (p->type & CONST_UNIVERSAL) + class = ASN1_CLASS_UNIVERSAL; + else if (p->type & CONST_PRIVATE) + class = ASN1_CLASS_PRIVATE; + else + class = ASN1_CLASS_CONTEXT_SPECIFIC; + + if (p->type & CONST_EXPLICIT) + { + if (is_tag_implicit) + _asn1_tag_der (class_implicit, tag_implicit, tag_der, + &tag_len); + else + _asn1_tag_der (class | ASN1_CLASS_STRUCTURED, + _asn1_strtoul (p->value, NULL, 10), + tag_der, &tag_len); + + *max_len -= tag_len; + if (der && *max_len >= 0) + memcpy (der + *counter, tag_der, tag_len); + *counter += tag_len; + + _asn1_ltostr (*counter, (char *) temp); + _asn1_set_name (p, (const char *) temp); + + is_tag_implicit = 0; + } + else + { /* CONST_IMPLICIT */ + if (!is_tag_implicit) + { + if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) || + (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) + || (type_field (node->type) == ASN1_ETYPE_SET) + || (type_field (node->type) == ASN1_ETYPE_SET_OF)) + class |= ASN1_CLASS_STRUCTURED; + class_implicit = class; + tag_implicit = _asn1_strtoul (p->value, NULL, 10); + is_tag_implicit = 1; + } + } + } + p = p->right; + } + } + + if (is_tag_implicit) + { + _asn1_tag_der (class_implicit, tag_implicit, tag_der, &tag_len); + } + else + { + unsigned type = type_field (node->type); + switch (type) + { + CASE_HANDLED_ETYPES: + _asn1_tag_der (_asn1_tags[type].class, _asn1_tags[type].tag, + tag_der, &tag_len); + break; + case ASN1_ETYPE_TAG: + case ASN1_ETYPE_CHOICE: + case ASN1_ETYPE_ANY: + tag_len = 0; + break; + default: + return ASN1_GENERIC_ERROR; + } + } + + *max_len -= tag_len; + if (der && *max_len >= 0) + memcpy (der + *counter, tag_der, tag_len); + *counter += tag_len; + + if (*max_len < 0) + return ASN1_MEM_ERROR; + + return ASN1_SUCCESS; +} + +/******************************************************/ +/* Function : _asn1_ordering_set */ +/* Description: puts the elements of a SET type in */ +/* the correct order according to DER rules. */ +/* Parameters: */ +/* der: string with the DER coding. */ +/* node: pointer to the SET element. */ +/* Return: */ +/* ASN1_SUCCESS if successful */ +/* or an error value. */ +/******************************************************/ +static int +_asn1_ordering_set (unsigned char *der, int der_len, asn1_node node) +{ + struct vet + { + int end; + unsigned long value; + struct vet *next, *prev; + }; + + int counter, len, len2; + struct vet *first, *last, *p_vet, *p2_vet; + asn1_node p; + unsigned char class, *temp; + unsigned long tag, t; + int err; + + counter = 0; + + if (type_field (node->type) != ASN1_ETYPE_SET) + return ASN1_VALUE_NOT_VALID; + + p = node->down; + while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) || + (type_field (p->type) == ASN1_ETYPE_SIZE))) + p = p->right; + + if ((p == NULL) || (p->right == NULL)) + return ASN1_SUCCESS; + + first = last = NULL; + while (p) + { + p_vet = malloc (sizeof (struct vet)); + if (p_vet == NULL) + { + err = ASN1_MEM_ALLOC_ERROR; + goto error; + } + + p_vet->next = NULL; + p_vet->prev = last; + if (first == NULL) + first = p_vet; + else + last->next = p_vet; + last = p_vet; + + /* tag value calculation */ + err = asn1_get_tag_der (der + counter, der_len - counter, &class, &len2, + &tag); + if (err != ASN1_SUCCESS) + goto error; + + t = ((unsigned int)class) << 24; + p_vet->value = t | tag; + counter += len2; + + /* extraction and length */ + len2 = asn1_get_length_der (der + counter, der_len - counter, &len); + if (len2 < 0) + { + err = ASN1_DER_ERROR; + goto error; + } + counter += len + len2; + + p_vet->end = counter; + p = p->right; + } + + p_vet = first; + + while (p_vet) + { + p2_vet = p_vet->next; + counter = 0; + while (p2_vet) + { + if (p_vet->value > p2_vet->value) + { + /* change position */ + temp = malloc (p_vet->end - counter); + if (temp == NULL) + { + err = ASN1_MEM_ALLOC_ERROR; + goto error; + } + + memcpy (temp, der + counter, p_vet->end - counter); + memcpy (der + counter, der + p_vet->end, + p2_vet->end - p_vet->end); + memcpy (der + counter + p2_vet->end - p_vet->end, temp, + p_vet->end - counter); + free (temp); + + tag = p_vet->value; + p_vet->value = p2_vet->value; + p2_vet->value = tag; + + p_vet->end = counter + (p2_vet->end - p_vet->end); + } + counter = p_vet->end; + + p2_vet = p2_vet->next; + p_vet = p_vet->next; + } + + if (p_vet != first) + p_vet->prev->next = NULL; + else + first = NULL; + free (p_vet); + p_vet = first; + } + return ASN1_SUCCESS; + +error: + while (first != NULL) + { + p_vet = first; + first = first->next; + free(p_vet); + } + return err; +} + +struct vet +{ + unsigned char *ptr; + int size; +}; + +static int setof_compar(const void *_e1, const void *_e2) +{ + unsigned length; + const struct vet *e1 = _e1, *e2 = _e2; + int rval; + + /* The encodings of the component values of a set-of value shall + * appear in ascending order, the encodings being compared + * as octet strings with the shorter components being + * padded at their trailing end with 0-octets. + * The padding octets are for comparison purposes and + * do not appear in the encodings. + */ + length = MIN(e1->size, e2->size); + + rval = memcmp(e1->ptr, e2->ptr, length); + if (rval == 0 && e1->size != e2->size) + { + if (e1->size > e2->size) + rval = 1; + else if (e2->size > e1->size) + rval = -1; + } + + return rval; +} + +/******************************************************/ +/* Function : _asn1_ordering_set_of */ +/* Description: puts the elements of a SET OF type in */ +/* the correct order according to DER rules. */ +/* Parameters: */ +/* der: string with the DER coding. */ +/* node: pointer to the SET OF element. */ +/* Return: */ +/* ASN1_SUCCESS if successful */ +/* or an error value. */ +/******************************************************/ +static int +_asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) +{ + int counter, len, len2; + struct vet *list = NULL, *tlist; + unsigned list_size = 0; + struct vet *p_vet; + asn1_node p; + unsigned char class; + unsigned i; + unsigned char *out = NULL; + int err; + + if (der == NULL) + return ASN1_VALUE_NOT_VALID; + + counter = 0; + + if (type_field (node->type) != ASN1_ETYPE_SET_OF) + return ASN1_VALUE_NOT_VALID; + + p = node->down; + while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) || + (type_field (p->type) == ASN1_ETYPE_SIZE))) + p = p->right; + if (p == NULL) + return ASN1_VALUE_NOT_VALID; + p = p->right; + + if ((p == NULL) || (p->right == NULL)) + return ASN1_SUCCESS; + + while (p) + { + list_size++; + tlist = realloc (list, list_size*sizeof(struct vet)); + if (tlist == NULL) + { + err = ASN1_MEM_ALLOC_ERROR; + goto error; + } + list = tlist; + p_vet = &list[list_size-1]; + + p_vet->ptr = der+counter; + p_vet->size = 0; + + /* extraction of tag and length */ + if (der_len - counter > 0) + { + err = asn1_get_tag_der (der + counter, der_len - counter, &class, + &len, NULL); + if (err != ASN1_SUCCESS) + goto error; + counter += len; + p_vet->size += len; + + len2 = asn1_get_length_der (der + counter, der_len - counter, &len); + if (len2 < 0) + { + err = ASN1_DER_ERROR; + goto error; + } + counter += len + len2; + p_vet->size += len + len2; + + } + else + { + err = ASN1_DER_ERROR; + goto error; + } + p = p->right; + } + + if (counter > der_len) + { + err = ASN1_DER_ERROR; + goto error; + } + + qsort(list, list_size, sizeof(struct vet), setof_compar); + + out = malloc(der_len); + if (out == NULL) + { + err = ASN1_MEM_ERROR; + goto error; + } + + /* the sum of p_vet->size == der_len */ + counter = 0; + for (i = 0; i < list_size; i++) + { + p_vet = &list[i]; + memcpy(out+counter, p_vet->ptr, p_vet->size); + counter += p_vet->size; + } + memcpy(der, out, der_len); + free(out); + + err = ASN1_SUCCESS; + +error: + free(list); + return err; +} + +/** + * asn1_der_coding: + * @element: pointer to an ASN1 element + * @name: the name of the structure you want to encode (it must be + * inside *POINTER). + * @ider: vector that will contain the DER encoding. DER must be a + * pointer to memory cells already allocated. + * @len: number of bytes of *@ider: @ider[0]..@ider[len-1], Initialy + * holds the sizeof of der vector. + * @ErrorDescription: return the error description or an empty + * string if success. + * + * Creates the DER encoding for the NAME structure (inside *POINTER + * structure). + * + * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND + * if @name is not a valid element, %ASN1_VALUE_NOT_FOUND if there + * is an element without a value, %ASN1_MEM_ERROR if the @ider + * vector isn't big enough and in this case @len will contain the + * length needed. + **/ +int +asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len, + char *ErrorDescription) +{ + asn1_node node, p, p2; + unsigned char temp[MAX(LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)]; + int counter, counter_old, len2, len3, move, max_len, max_len_old; + int err; + unsigned char *der = ider; + + if (ErrorDescription) + ErrorDescription[0] = 0; + + node = asn1_find_node (element, name); + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + /* Node is now a locally allocated variable. + * That is because in some point we modify the + * structure, and I don't know why! --nmav + */ + node = _asn1_copy_structure3 (node); + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + max_len = *len; + + if (der == NULL && max_len > 0) + return ASN1_VALUE_NOT_VALID; + + counter = 0; + move = DOWN; + p = node; + + while (1) + { + + counter_old = counter; + max_len_old = max_len; + if (move != UP) + { + p->start = counter; + err = _asn1_insert_tag_der (p, der, &counter, &max_len); + if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) + goto error; + } + switch (type_field (p->type)) + { + case ASN1_ETYPE_NULL: + max_len--; + if (der != NULL && max_len >= 0) + der[counter] = 0; + counter++; + move = RIGHT; + break; + case ASN1_ETYPE_BOOLEAN: + if ((p->type & CONST_DEFAULT) && (p->value == NULL)) + { + counter = counter_old; + max_len = max_len_old; + } + else + { + if (p->value == NULL) + { + _asn1_error_description_value_not_found (p, + ErrorDescription); + err = ASN1_VALUE_NOT_FOUND; + goto error; + } + max_len -= 2; + if (der != NULL && max_len >= 0) + { + der[counter++] = 1; + if (p->value[0] == 'F') + der[counter++] = 0; + else + der[counter++] = 0xFF; + } + else + counter += 2; + } + move = RIGHT; + break; + case ASN1_ETYPE_INTEGER: + case ASN1_ETYPE_ENUMERATED: + if ((p->type & CONST_DEFAULT) && (p->value == NULL)) + { + counter = counter_old; + max_len = max_len_old; + } + else + { + if (p->value == NULL) + { + _asn1_error_description_value_not_found (p, + ErrorDescription); + err = ASN1_VALUE_NOT_FOUND; + goto error; + } + len2 = asn1_get_length_der (p->value, p->value_len, &len3); + if (len2 < 0) + { + err = ASN1_DER_ERROR; + goto error; + } + max_len -= len2 + len3; + if (der != NULL && max_len >= 0) + memcpy (der + counter, p->value, len3 + len2); + counter += len3 + len2; + } + move = RIGHT; + break; + case ASN1_ETYPE_OBJECT_ID: + if ((p->type & CONST_DEFAULT) && (p->value == NULL)) + { + counter = counter_old; + max_len = max_len_old; + } + else + { + if (p->value == NULL) + { + _asn1_error_description_value_not_found (p, + ErrorDescription); + err = ASN1_VALUE_NOT_FOUND; + goto error; + } + len2 = max_len; + err = _asn1_object_id_der ((char*)p->value, der + counter, &len2); + if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) + goto error; + + max_len -= len2; + counter += len2; + } + move = RIGHT; + break; + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: + if (p->value == NULL) + { + _asn1_error_description_value_not_found (p, ErrorDescription); + err = ASN1_VALUE_NOT_FOUND; + goto error; + } + len2 = max_len; + err = _asn1_time_der (p->value, p->value_len, der + counter, &len2); + if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) + goto error; + + max_len -= len2; + counter += len2; + move = RIGHT; + break; + case ASN1_ETYPE_OCTET_STRING: + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + case ASN1_ETYPE_BIT_STRING: + if (p->value == NULL) + { + _asn1_error_description_value_not_found (p, ErrorDescription); + err = ASN1_VALUE_NOT_FOUND; + goto error; + } + len2 = asn1_get_length_der (p->value, p->value_len, &len3); + if (len2 < 0) + { + err = ASN1_DER_ERROR; + goto error; + } + max_len -= len2 + len3; + if (der != NULL && max_len >= 0) + memcpy (der + counter, p->value, len3 + len2); + counter += len3 + len2; + move = RIGHT; + break; + case ASN1_ETYPE_SEQUENCE: + case ASN1_ETYPE_SET: + if (move != UP) + { + p->tmp_ival = counter; + if (p->down == NULL) + { + move = UP; + continue; + } + else + { + p2 = p->down; + while (p2 && (type_field (p2->type) == ASN1_ETYPE_TAG)) + p2 = p2->right; + if (p2) + { + p = p2; + move = RIGHT; + continue; + } + move = UP; + continue; + } + } + else + { /* move==UP */ + len2 = p->tmp_ival; + p->tmp_ival = 0; + if ((type_field (p->type) == ASN1_ETYPE_SET) && (max_len >= 0)) + { + err = _asn1_ordering_set (der + len2, counter - len2, p); + if (err != ASN1_SUCCESS) + goto error; + } + asn1_length_der (counter - len2, temp, &len3); + max_len -= len3; + if (der != NULL && max_len >= 0) + { + memmove (der + len2 + len3, der + len2, counter - len2); + memcpy (der + len2, temp, len3); + } + counter += len3; + move = RIGHT; + } + break; + case ASN1_ETYPE_SEQUENCE_OF: + case ASN1_ETYPE_SET_OF: + if (move != UP) + { + p->tmp_ival = counter; + p = p->down; + while ((type_field (p->type) == ASN1_ETYPE_TAG) + || (type_field (p->type) == ASN1_ETYPE_SIZE)) + p = p->right; + if (p->right) + { + p = p->right; + move = RIGHT; + continue; + } + else + p = _asn1_find_up (p); + move = UP; + } + if (move == UP) + { + len2 = p->tmp_ival; + p->tmp_ival = 0; + if ((type_field (p->type) == ASN1_ETYPE_SET_OF) + && (counter - len2 > 0) && (max_len >= 0)) + { + err = _asn1_ordering_set_of (der + len2, counter - len2, p); + if (err != ASN1_SUCCESS) + goto error; + } + asn1_length_der (counter - len2, temp, &len3); + max_len -= len3; + if (der != NULL && max_len >= 0) + { + memmove (der + len2 + len3, der + len2, counter - len2); + memcpy (der + len2, temp, len3); + } + counter += len3; + move = RIGHT; + } + break; + case ASN1_ETYPE_ANY: + if (p->value == NULL) + { + _asn1_error_description_value_not_found (p, ErrorDescription); + err = ASN1_VALUE_NOT_FOUND; + goto error; + } + len2 = asn1_get_length_der (p->value, p->value_len, &len3); + if (len2 < 0) + { + err = ASN1_DER_ERROR; + goto error; + } + max_len -= len2; + if (der != NULL && max_len >= 0) + memcpy (der + counter, p->value + len3, len2); + counter += len2; + move = RIGHT; + break; + default: + move = (move == UP) ? RIGHT : DOWN; + break; + } + + if ((move != DOWN) && (counter != counter_old)) + { + p->end = counter - 1; + err = _asn1_complete_explicit_tag (p, der, &counter, &max_len); + if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) + goto error; + } + + if (p == node && move != DOWN) + break; + + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + if (move == RIGHT) + { + if (p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + *len = counter; + + if (max_len < 0) + { + err = ASN1_MEM_ERROR; + goto error; + } + + err = ASN1_SUCCESS; + +error: + asn1_delete_structure (&node); + return err; +} diff --git a/lib/minitasn1/decoding.c b/lib/minitasn1/decoding.c new file mode 100644 index 0000000..ff04eb7 --- /dev/null +++ b/lib/minitasn1/decoding.c @@ -0,0 +1,2478 @@ +/* + * Copyright (C) 2002-2016 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + + +/*****************************************************/ +/* File: decoding.c */ +/* Description: Functions to manage DER decoding */ +/*****************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG +# define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__) +#else +# define warn() +#endif + +#define IS_ERR(len, flags) (len < -1 || ((flags & ASN1_DECODE_FLAG_STRICT_DER) && len < 0)) + +#define HAVE_TWO(x) (x>=2?1:0) + +/* Decoding flags (dflags) used in several decoding functions. + * DECODE_FLAG_HAVE_TAG: The provided buffer includes a tag + * DECODE_FLAG_CONSTRUCTED: The provided buffer is of indefinite encoding (useful + * when no tags are present). + * DECODE_FLAG_LEVEL1: Internal flag to indicate a level of recursion for BER strings. + * DECODE_FLAG_LEVEL2: Internal flag to indicate two levels of recursion for BER strings. + * DECODE_FLAG_LEVEL3: Internal flag to indicate three levels of recursion for BER strings. + * This is the maximum levels of recursion possible to prevent stack + * exhaustion. + */ + +#define DECODE_FLAG_HAVE_TAG 1 +#define DECODE_FLAG_CONSTRUCTED (1<<1) +#define DECODE_FLAG_LEVEL1 (1<<2) +#define DECODE_FLAG_LEVEL2 (1<<3) +#define DECODE_FLAG_LEVEL3 (1<<4) + +#define DECR_LEN(l, s) do { \ + l -= s; \ + if (l < 0) { \ + warn(); \ + result = ASN1_DER_ERROR; \ + goto cleanup; \ + } \ + } while (0) + +static int +_asn1_get_indefinite_length_string (const unsigned char *der, int der_len, int *len); + +static int +_asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, + unsigned int _der_len, unsigned char **str, + unsigned int *str_len, unsigned int *ber_len, + unsigned dflags); + +static int +_asn1_decode_simple_der (unsigned int etype, const unsigned char *der, + unsigned int _der_len, const unsigned char **str, + unsigned int *str_len, unsigned dflags); + +static void +_asn1_error_description_tag_error (asn1_node node, char *ErrorDescription) +{ + + Estrcpy (ErrorDescription, ":: tag error near element '"); + _asn1_hierarchical_name (node, ErrorDescription + strlen (ErrorDescription), + ASN1_MAX_ERROR_DESCRIPTION_SIZE - 40); + Estrcat (ErrorDescription, "'"); + +} + +/** + * asn1_get_length_der: + * @der: DER data to decode. + * @der_len: Length of DER data to decode. + * @len: Output variable containing the length of the DER length field. + * + * Extract a length field from DER data. + * + * Returns: Return the decoded length value, or -1 on indefinite + * length, or -2 when the value was too big to fit in a int, or -4 + * when the decoded length value plus @len would exceed @der_len. + **/ +long +asn1_get_length_der (const unsigned char *der, int der_len, int *len) +{ + unsigned int ans; + int k, punt, sum; + + *len = 0; + if (der_len <= 0) + return 0; + + if (!(der[0] & 128)) + { + /* short form */ + *len = 1; + ans = der[0]; + } + else + { + /* Long form */ + k = der[0] & 0x7F; + punt = 1; + if (k) + { /* definite length method */ + ans = 0; + while (punt <= k && punt < der_len) + { + if (INT_MULTIPLY_OVERFLOW (ans, 256)) + return -2; + ans *= 256; + + if (INT_ADD_OVERFLOW (ans, ((unsigned) der[punt]))) + return -2; + ans += der[punt]; + punt++; + } + } + else + { /* indefinite length method */ + *len = punt; + return -1; + } + + *len = punt; + } + + sum = ans; + if (ans >= INT_MAX || INT_ADD_OVERFLOW (sum, (*len))) + return -2; + sum += *len; + + if (sum > der_len) + return -4; + + return ans; +} + +/** + * asn1_get_tag_der: + * @der: DER data to decode. + * @der_len: Length of DER data to decode. + * @cls: Output variable containing decoded class. + * @len: Output variable containing the length of the DER TAG data. + * @tag: Output variable containing the decoded tag (may be %NULL). + * + * Decode the class and TAG from DER code. + * + * Returns: Returns %ASN1_SUCCESS on success, or an error. + **/ +int +asn1_get_tag_der (const unsigned char *der, int der_len, + unsigned char *cls, int *len, unsigned long *tag) +{ + unsigned int ris; + int punt; + + if (der == NULL || der_len < 2 || len == NULL) + return ASN1_DER_ERROR; + + *cls = der[0] & 0xE0; + if ((der[0] & 0x1F) != 0x1F) + { + /* short form */ + *len = 1; + ris = der[0] & 0x1F; + } + else + { + /* Long form */ + punt = 1; + ris = 0; + while (punt < der_len && der[punt] & 128) + { + + if (INT_MULTIPLY_OVERFLOW (ris, 128)) + return ASN1_DER_ERROR; + ris *= 128; + + if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F)))) + return ASN1_DER_ERROR; + ris += (der[punt] & 0x7F); + punt++; + } + + if (punt >= der_len) + return ASN1_DER_ERROR; + + if (INT_MULTIPLY_OVERFLOW (ris, 128)) + return ASN1_DER_ERROR; + ris *= 128; + + if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F)))) + return ASN1_DER_ERROR; + ris += (der[punt] & 0x7F); + punt++; + + *len = punt; + } + + if (tag) + *tag = ris; + return ASN1_SUCCESS; +} + +/** + * asn1_get_length_ber: + * @ber: BER data to decode. + * @ber_len: Length of BER data to decode. + * @len: Output variable containing the length of the BER length field. + * + * Extract a length field from BER data. The difference to + * asn1_get_length_der() is that this function will return a length + * even if the value has indefinite encoding. + * + * Returns: Return the decoded length value, or negative value when + * the value was too big. + * + * Since: 2.0 + **/ +long +asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len) +{ + int ret; + long err; + + ret = asn1_get_length_der (ber, ber_len, len); + + if (ret == -1 && ber_len > 1) + { /* indefinite length method */ + err = _asn1_get_indefinite_length_string (ber + 1, ber_len-1, &ret); + if (err != ASN1_SUCCESS) + return -3; + } + + return ret; +} + +/** + * asn1_get_octet_der: + * @der: DER data to decode containing the OCTET SEQUENCE. + * @der_len: The length of the @der data to decode. + * @ret_len: Output variable containing the encoded length of the DER data. + * @str: Pre-allocated output buffer to put decoded OCTET SEQUENCE in. + * @str_size: Length of pre-allocated output buffer. + * @str_len: Output variable containing the length of the contents of the OCTET SEQUENCE. + * + * Extract an OCTET SEQUENCE from DER data. Note that this function + * expects the DER data past the tag field, i.e., the length and + * content octets. + * + * Returns: Returns %ASN1_SUCCESS on success, or an error. + **/ +int +asn1_get_octet_der (const unsigned char *der, int der_len, + int *ret_len, unsigned char *str, int str_size, + int *str_len) +{ + int len_len = 0; + + if (der_len <= 0) + return ASN1_GENERIC_ERROR; + + *str_len = asn1_get_length_der (der, der_len, &len_len); + + if (*str_len < 0) + return ASN1_DER_ERROR; + + *ret_len = *str_len + len_len; + if (str_size >= *str_len) + { + if (*str_len > 0 && str != NULL) + memcpy (str, der + len_len, *str_len); + } + else + { + return ASN1_MEM_ERROR; + } + + return ASN1_SUCCESS; +} + + +/*- + * _asn1_get_time_der: + * @type: %ASN1_ETYPE_GENERALIZED_TIME or %ASN1_ETYPE_UTC_TIME + * @der: DER data to decode containing the time + * @der_len: Length of DER data to decode. + * @ret_len: Output variable containing the length of the DER data. + * @str: Pre-allocated output buffer to put the textual time in. + * @str_size: Length of pre-allocated output buffer. + * @flags: Zero or %ASN1_DECODE_FLAG_STRICT_DER + * + * Performs basic checks in the DER encoded time object and returns its textual form. + * The textual form will be in the YYYYMMDD000000Z format for GeneralizedTime + * and YYMMDD000000Z for UTCTime. + * + * Returns: %ASN1_SUCCESS on success, or an error. + -*/ +static int +_asn1_get_time_der (unsigned type, const unsigned char *der, int der_len, int *ret_len, + char *str, int str_size, unsigned flags) +{ + int len_len, str_len; + unsigned i; + unsigned sign_count = 0; + unsigned dot_count = 0; + const unsigned char *p; + + if (der_len <= 0 || str == NULL) + return ASN1_DER_ERROR; + + str_len = asn1_get_length_der (der, der_len, &len_len); + if (str_len <= 0 || str_size < str_len) + return ASN1_DER_ERROR; + + /* perform some sanity checks on the data */ + if (str_len < 8) + { + warn(); + return ASN1_TIME_ENCODING_ERROR; + } + + if ((flags & ASN1_DECODE_FLAG_STRICT_DER) && !(flags & ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME)) + { + p = &der[len_len]; + for (i=0;i<(unsigned)(str_len-1);i++) + { + if (c_isdigit(p[i]) == 0) + { + if (type == ASN1_ETYPE_GENERALIZED_TIME) + { + /* tolerate lax encodings */ + if (p[i] == '.' && dot_count == 0) + { + dot_count++; + continue; + } + + /* This is not really valid DER, but there are + * structures using that */ + if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) && + (p[i] == '+' || p[i] == '-') && sign_count == 0) + { + sign_count++; + continue; + } + } + + warn(); + return ASN1_TIME_ENCODING_ERROR; + } + } + + if (sign_count == 0 && p[str_len-1] != 'Z') + { + warn(); + return ASN1_TIME_ENCODING_ERROR; + } + } + memcpy (str, der + len_len, str_len); + str[str_len] = 0; + *ret_len = str_len + len_len; + + return ASN1_SUCCESS; +} + +/** + * asn1_get_object_id_der: + * @der: DER data to decode containing the OBJECT IDENTIFIER + * @der_len: Length of DER data to decode. + * @ret_len: Output variable containing the length of the DER data. + * @str: Pre-allocated output buffer to put the textual object id in. + * @str_size: Length of pre-allocated output buffer. + * + * Converts a DER encoded object identifier to its textual form. This + * function expects the DER object identifier without the tag. + * + * Returns: %ASN1_SUCCESS on success, or an error. + **/ +int +asn1_get_object_id_der (const unsigned char *der, int der_len, int *ret_len, + char *str, int str_size) +{ + int len_len, len, k; + int leading, parsed; + char temp[LTOSTR_MAX_SIZE]; + uint64_t val, val1, val0; + + *ret_len = 0; + if (str && str_size > 0) + str[0] = 0; /* no oid */ + + if (str == NULL || der_len <= 0) + return ASN1_GENERIC_ERROR; + + len = asn1_get_length_der (der, der_len, &len_len); + + if (len <= 0 || len + len_len > der_len) + return ASN1_DER_ERROR; + + /* leading octet can never be 0x80 */ + if (der[len_len] == 0x80) + return ASN1_DER_ERROR; + + val0 = 0; + + for (k = 0; k < len; k++) + { + if (INT_LEFT_SHIFT_OVERFLOW (val0, 7)) + return ASN1_DER_ERROR; + + val0 <<= 7; + val0 |= der[len_len + k] & 0x7F; + if (!(der[len_len + k] & 0x80)) + break; + } + parsed = ++k; + + /* val0 = (X*40) + Y, X={0,1,2}, Y<=39 when X={0,1} */ + /* X = val, Y = val1 */ + + /* check if X == 0 */ + val = 0; + val1 = val0; + if (val1 > 39) + { + val = 1; + val1 = val0 - 40; + if (val1 > 39) + { + val = 2; + val1 = val0 - 80; + } + } + + _asn1_str_cpy (str, str_size, _asn1_ltostr (val, temp)); + _asn1_str_cat (str, str_size, "."); + _asn1_str_cat (str, str_size, _asn1_ltostr (val1, temp)); + + val = 0; + leading = 1; + for (k = parsed; k < len; k++) + { + /* X.690 mandates that the leading byte must never be 0x80 + */ + if (leading != 0 && der[len_len + k] == 0x80) + return ASN1_DER_ERROR; + leading = 0; + + /* check for wrap around */ + if (INT_LEFT_SHIFT_OVERFLOW (val, 7)) + return ASN1_DER_ERROR; + + val = val << 7; + val |= der[len_len + k] & 0x7F; + + if (!(der[len_len + k] & 0x80)) + { + _asn1_str_cat (str, str_size, "."); + _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp)); + val = 0; + leading = 1; + } + } + + if (INT_ADD_OVERFLOW (len, len_len)) + return ASN1_DER_ERROR; + + *ret_len = len + len_len; + + return ASN1_SUCCESS; +} + +/** + * asn1_get_bit_der: + * @der: DER data to decode containing the BIT SEQUENCE. + * @der_len: Length of DER data to decode. + * @ret_len: Output variable containing the length of the DER data. + * @str: Pre-allocated output buffer to put decoded BIT SEQUENCE in. + * @str_size: Length of pre-allocated output buffer. + * @bit_len: Output variable containing the size of the BIT SEQUENCE. + * + * Extract a BIT SEQUENCE from DER data. + * + * Returns: %ASN1_SUCCESS on success, or an error. + **/ +int +asn1_get_bit_der (const unsigned char *der, int der_len, + int *ret_len, unsigned char *str, int str_size, + int *bit_len) +{ + int len_len = 0, len_byte; + + if (der_len <= 0) + return ASN1_GENERIC_ERROR; + + len_byte = asn1_get_length_der (der, der_len, &len_len) - 1; + if (len_byte < 0) + return ASN1_DER_ERROR; + + *ret_len = len_byte + len_len + 1; + *bit_len = len_byte * 8 - der[len_len]; + + if (*bit_len < 0) + return ASN1_DER_ERROR; + + if (str_size >= len_byte) + { + if (len_byte > 0 && str) + memcpy (str, der + len_len + 1, len_byte); + } + else + { + return ASN1_MEM_ERROR; + } + + return ASN1_SUCCESS; +} + +/* tag_len: the total tag length (explicit+inner) + * inner_tag_len: the inner_tag length + */ +static int +_asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, + int *tag_len, int *inner_tag_len, unsigned flags) +{ + asn1_node p; + int counter, len2, len3, is_tag_implicit; + int result; + unsigned long tag, tag_implicit = 0; + unsigned char class, class2, class_implicit = 0; + + if (der_len <= 0) + return ASN1_GENERIC_ERROR; + + counter = is_tag_implicit = 0; + + if (node->type & CONST_TAG) + { + p = node->down; + while (p) + { + if (type_field (p->type) == ASN1_ETYPE_TAG) + { + if (p->type & CONST_APPLICATION) + class2 = ASN1_CLASS_APPLICATION; + else if (p->type & CONST_UNIVERSAL) + class2 = ASN1_CLASS_UNIVERSAL; + else if (p->type & CONST_PRIVATE) + class2 = ASN1_CLASS_PRIVATE; + else + class2 = ASN1_CLASS_CONTEXT_SPECIFIC; + + if (p->type & CONST_EXPLICIT) + { + if (asn1_get_tag_der + (der + counter, der_len, &class, &len2, + &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; + + DECR_LEN(der_len, len2); + counter += len2; + + if (flags & ASN1_DECODE_FLAG_STRICT_DER) + len3 = + asn1_get_length_der (der + counter, der_len, + &len2); + else + len3 = + asn1_get_length_ber (der + counter, der_len, + &len2); + if (len3 < 0) + return ASN1_DER_ERROR; + + DECR_LEN(der_len, len2); + counter += len2; + + if (!is_tag_implicit) + { + if ((class != (class2 | ASN1_CLASS_STRUCTURED)) || + (tag != strtoul ((char *) p->value, NULL, 10))) + return ASN1_TAG_ERROR; + } + else + { /* ASN1_TAG_IMPLICIT */ + if ((class != class_implicit) || (tag != tag_implicit)) + return ASN1_TAG_ERROR; + } + is_tag_implicit = 0; + } + else + { /* ASN1_TAG_IMPLICIT */ + if (!is_tag_implicit) + { + if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) || + (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) + || (type_field (node->type) == ASN1_ETYPE_SET) + || (type_field (node->type) == ASN1_ETYPE_SET_OF)) + class2 |= ASN1_CLASS_STRUCTURED; + class_implicit = class2; + tag_implicit = strtoul ((char *) p->value, NULL, 10); + is_tag_implicit = 1; + } + } + } + p = p->right; + } + } + + if (is_tag_implicit) + { + if (asn1_get_tag_der + (der + counter, der_len, &class, &len2, + &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; + + DECR_LEN(der_len, len2); + + if ((class != class_implicit) || (tag != tag_implicit)) + { + if (type_field (node->type) == ASN1_ETYPE_OCTET_STRING) + { + class_implicit |= ASN1_CLASS_STRUCTURED; + if ((class != class_implicit) || (tag != tag_implicit)) + return ASN1_TAG_ERROR; + } + else + return ASN1_TAG_ERROR; + } + } + else + { + unsigned type = type_field (node->type); + if (type == ASN1_ETYPE_TAG) + { + *tag_len = 0; + if (inner_tag_len) + *inner_tag_len = 0; + return ASN1_SUCCESS; + } + + if (asn1_get_tag_der + (der + counter, der_len, &class, &len2, + &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; + + DECR_LEN(der_len, len2); + + switch (type) + { + case ASN1_ETYPE_NULL: + case ASN1_ETYPE_BOOLEAN: + case ASN1_ETYPE_INTEGER: + case ASN1_ETYPE_ENUMERATED: + case ASN1_ETYPE_OBJECT_ID: + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + case ASN1_ETYPE_BIT_STRING: + case ASN1_ETYPE_SEQUENCE: + case ASN1_ETYPE_SEQUENCE_OF: + case ASN1_ETYPE_SET: + case ASN1_ETYPE_SET_OF: + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: + if ((class != _asn1_tags[type].class) + || (tag != _asn1_tags[type].tag)) + return ASN1_DER_ERROR; + break; + + case ASN1_ETYPE_OCTET_STRING: + /* OCTET STRING is handled differently to allow + * BER encodings (structured class). */ + if (((class != ASN1_CLASS_UNIVERSAL) + && (class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED))) + || (tag != ASN1_TAG_OCTET_STRING)) + return ASN1_DER_ERROR; + break; + case ASN1_ETYPE_ANY: + counter -= len2; + break; + case ASN1_ETYPE_CHOICE: + counter -= len2; + break; + default: + return ASN1_DER_ERROR; + break; + } + } + + counter += len2; + *tag_len = counter; + if (inner_tag_len) + *inner_tag_len = len2; + return ASN1_SUCCESS; + +cleanup: + return result; +} + +static int +extract_tag_der_recursive(asn1_node node, const unsigned char *der, int der_len, + int *ret_len, int *inner_len, unsigned flags) +{ +asn1_node p; +int ris = ASN1_DER_ERROR; + + if (type_field (node->type) == ASN1_ETYPE_CHOICE) + { + p = node->down; + while (p) + { + ris = _asn1_extract_tag_der (p, der, der_len, ret_len, inner_len, flags); + if (ris == ASN1_SUCCESS) + break; + p = p->right; + } + + *ret_len = 0; + return ris; + } + else + return _asn1_extract_tag_der (node, der, der_len, ret_len, inner_len, flags); +} + +static int +_asn1_delete_not_used (asn1_node node) +{ + asn1_node p, p2; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + while (p) + { + if (p->type & CONST_NOT_USED) + { + p2 = NULL; + if (p != node) + { + p2 = _asn1_find_left (p); + if (!p2) + p2 = _asn1_find_up (p); + } + asn1_delete_structure (&p); + p = p2; + } + + if (!p) + break; /* reach node */ + + if (p->down) + { + p = p->down; + } + else + { + if (p == node) + p = NULL; + else if (p->right) + p = p->right; + else + { + while (1) + { + p = _asn1_find_up (p); + if (p == node) + { + p = NULL; + break; + } + if (p->right) + { + p = p->right; + break; + } + } + } + } + } + return ASN1_SUCCESS; +} + +static int +_asn1_get_indefinite_length_string (const unsigned char *der, + int der_len, int *len) +{ + int len2, len3, counter, indefinite; + int result; + unsigned long tag; + unsigned char class; + + counter = indefinite = 0; + + while (1) + { + if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0)) + { + counter += 2; + DECR_LEN(der_len, 2); + + indefinite--; + if (indefinite <= 0) + break; + else + continue; + } + + if (asn1_get_tag_der + (der + counter, der_len, &class, &len2, + &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; + + DECR_LEN(der_len, len2); + counter += len2; + + len2 = asn1_get_length_der (der + counter, der_len, &len3); + if (len2 < -1) + return ASN1_DER_ERROR; + + if (len2 == -1) + { + indefinite++; + counter += 1; + DECR_LEN(der_len, 1); + } + else + { + counter += len2 + len3; + DECR_LEN(der_len, len2+len3); + } + } + + *len = counter; + return ASN1_SUCCESS; + +cleanup: + return result; +} + +static void delete_unneeded_choice_fields(asn1_node p) +{ + asn1_node p2; + + while (p->right) + { + p2 = p->right; + asn1_delete_structure (&p2); + } +} + + +/** + * asn1_der_decoding2 + * @element: pointer to an ASN1 structure. + * @ider: vector that contains the DER encoding. + * @max_ider_len: pointer to an integer giving the information about the + * maximal number of bytes occupied by *@ider. The real size of the DER + * encoding is returned through this pointer. + * @flags: flags controlling the behaviour of the function. + * @errorDescription: null-terminated string contains details when an + * error occurred. + * + * Fill the structure *@element with values of a DER encoding string. The + * structure must just be created with function asn1_create_element(). + * + * If %ASN1_DECODE_FLAG_ALLOW_PADDING flag is set then the function will ignore + * padding after the decoded DER data. Upon a successful return the value of + * *@max_ider_len will be set to the number of bytes decoded. + * + * If %ASN1_DECODE_FLAG_STRICT_DER flag is set then the function will + * not decode any BER-encoded elements. + * + * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND + * if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or + * %ASN1_DER_ERROR if the der encoding doesn't match the structure + * name (*@ELEMENT deleted). + **/ +int +asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, + unsigned int flags, char *errorDescription) +{ + asn1_node node, p, p2, p3; + char temp[128]; + int counter, len2, len3, len4, move, ris, tlen; + struct node_tail_cache_st tcache = {NULL, NULL}; + unsigned char class; + unsigned long tag; + int tag_len; + int indefinite, result, total_len = *max_ider_len, ider_len = *max_ider_len; + int inner_tag_len; + unsigned char *ptmp; + const unsigned char *ptag; + const unsigned char *der = ider; + + node = *element; + + if (errorDescription != NULL) + errorDescription[0] = 0; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + if (node->type & CONST_OPTION) + { + result = ASN1_GENERIC_ERROR; + warn(); + goto cleanup; + } + + counter = 0; + move = DOWN; + p = node; + while (1) + { + tag_len = 0; + inner_tag_len = 0; + ris = ASN1_SUCCESS; + if (move != UP) + { + if (p->type & CONST_SET) + { + p2 = _asn1_find_up (p); + len2 = p2->tmp_ival; + if (len2 == -1) + { + if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) + { + p = p2; + move = UP; + counter += 2; + DECR_LEN(ider_len, 2); + continue; + } + } + else if (counter == len2) + { + p = p2; + move = UP; + continue; + } + else if (counter > len2) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + p2 = p2->down; + while (p2) + { + if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED)) + { + ris = + extract_tag_der_recursive (p2, der + counter, + ider_len, &len2, NULL, flags); + if (ris == ASN1_SUCCESS) + { + p2->type &= ~CONST_NOT_USED; + p = p2; + break; + } + } + p2 = p2->right; + } + if (p2 == NULL) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + } + + /* the position in the DER structure this starts */ + p->start = counter; + p->end = total_len - 1; + + if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT)) + { + p2 = _asn1_find_up (p); + len2 = p2->tmp_ival; + if (counter == len2) + { + if (p->right) + { + p2 = p->right; + move = RIGHT; + } + else + move = UP; + + if (p->type & CONST_OPTION) + asn1_delete_structure (&p); + + p = p2; + continue; + } + } + + if (type_field (p->type) == ASN1_ETYPE_CHOICE) + { + while (p->down) + { + ris = + extract_tag_der_recursive (p->down, der + counter, + ider_len, &len2, NULL, flags); + + if (ris == ASN1_SUCCESS) + { + delete_unneeded_choice_fields(p->down); + break; + } + else if (ris == ASN1_ERROR_TYPE_ANY) + { + result = ASN1_ERROR_TYPE_ANY; + warn(); + goto cleanup; + } + else + { + p2 = p->down; + asn1_delete_structure (&p2); + } + } + + if (p->down == NULL) + { + if (!(p->type & CONST_OPTION)) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + } + else if (type_field (p->type) != ASN1_ETYPE_CHOICE) + p = p->down; + + p->start = counter; + } + + if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT)) + { + p2 = _asn1_find_up (p); + len2 = p2->tmp_ival; + + if ((len2 != -1) && (counter > len2)) + ris = ASN1_TAG_ERROR; + } + + if (ris == ASN1_SUCCESS) + ris = + extract_tag_der_recursive (p, der + counter, ider_len, + &tag_len, &inner_tag_len, flags); + + if (ris != ASN1_SUCCESS) + { + if (p->type & CONST_OPTION) + { + p->type |= CONST_NOT_USED; + move = RIGHT; + } + else if (p->type & CONST_DEFAULT) + { + _asn1_set_value (p, NULL, 0); + move = RIGHT; + } + else + { + if (errorDescription != NULL) + _asn1_error_description_tag_error (p, errorDescription); + + result = ASN1_TAG_ERROR; + warn(); + goto cleanup; + } + } + else + { + DECR_LEN(ider_len, tag_len); + counter += tag_len; + } + } + + if (ris == ASN1_SUCCESS) + { + switch (type_field (p->type)) + { + case ASN1_ETYPE_NULL: + DECR_LEN(ider_len, 1); + if (der[counter]) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + counter++; + move = RIGHT; + break; + case ASN1_ETYPE_BOOLEAN: + DECR_LEN(ider_len, 2); + + if (der[counter++] != 1) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + if (der[counter++] == 0) + _asn1_set_value (p, "F", 1); + else + _asn1_set_value (p, "T", 1); + move = RIGHT; + break; + case ASN1_ETYPE_INTEGER: + case ASN1_ETYPE_ENUMERATED: + len2 = + asn1_get_length_der (der + counter, ider_len, &len3); + if (len2 < 0) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len3+len2); + + _asn1_set_value (p, der + counter, len3 + len2); + counter += len3 + len2; + move = RIGHT; + break; + case ASN1_ETYPE_OBJECT_ID: + result = + asn1_get_object_id_der (der + counter, ider_len, &len2, + temp, sizeof (temp)); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len2); + + tlen = strlen (temp); + if (tlen > 0) + _asn1_set_value (p, temp, tlen + 1); + + counter += len2; + move = RIGHT; + break; + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: + result = + _asn1_get_time_der (type_field (p->type), der + counter, ider_len, &len2, temp, + sizeof (temp) - 1, flags); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len2); + + tlen = strlen (temp); + if (tlen > 0) + _asn1_set_value (p, temp, tlen); + + counter += len2; + move = RIGHT; + break; + case ASN1_ETYPE_OCTET_STRING: + if (counter < inner_tag_len) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + ptag = der + counter - inner_tag_len; + if ((flags & ASN1_DECODE_FLAG_STRICT_DER) || !(ptag[0] & ASN1_CLASS_STRUCTURED)) + { + if (ptag[0] & ASN1_CLASS_STRUCTURED) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + len2 = + asn1_get_length_der (der + counter, ider_len, &len3); + if (len2 < 0) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len3+len2); + + _asn1_set_value (p, der + counter, len3 + len2); + counter += len3 + len2; + } + else + { + unsigned dflags = 0, vlen, ber_len; + + if (ptag[0] & ASN1_CLASS_STRUCTURED) + dflags |= DECODE_FLAG_CONSTRUCTED; + + result = _asn1_decode_simple_ber(type_field (p->type), der+counter, ider_len, &ptmp, &vlen, &ber_len, dflags); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, ber_len); + + _asn1_set_value_lv (p, ptmp, vlen); + + counter += ber_len; + free(ptmp); + } + move = RIGHT; + break; + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + case ASN1_ETYPE_BIT_STRING: + len2 = + asn1_get_length_der (der + counter, ider_len, &len3); + if (len2 < 0) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len3+len2); + + _asn1_set_value (p, der + counter, len3 + len2); + counter += len3 + len2; + move = RIGHT; + break; + case ASN1_ETYPE_SEQUENCE: + case ASN1_ETYPE_SET: + if (move == UP) + { + len2 = p->tmp_ival; + p->tmp_ival = 0; + if (len2 == -1) + { /* indefinite length method */ + DECR_LEN(ider_len, 2); + if ((der[counter]) || der[counter + 1]) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + counter += 2; + } + else + { /* definite length method */ + if (len2 != counter) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + } + move = RIGHT; + } + else + { /* move==DOWN || move==RIGHT */ + len3 = + asn1_get_length_der (der + counter, ider_len, &len2); + if (IS_ERR(len3, flags)) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len2); + counter += len2; + + if (len3 > 0) + { + p->tmp_ival = counter + len3; + move = DOWN; + } + else if (len3 == 0) + { + p2 = p->down; + while (p2) + { + if (type_field (p2->type) != ASN1_ETYPE_TAG) + { + p3 = p2->right; + asn1_delete_structure (&p2); + p2 = p3; + } + else + p2 = p2->right; + } + move = RIGHT; + } + else + { /* indefinite length method */ + p->tmp_ival = -1; + move = DOWN; + } + } + break; + case ASN1_ETYPE_SEQUENCE_OF: + case ASN1_ETYPE_SET_OF: + if (move == UP) + { + len2 = p->tmp_ival; + if (len2 == -1) + { /* indefinite length method */ + if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1])) + { + result = _asn1_append_sequence_set (p, &tcache); + if (result != 0) + { + warn(); + goto cleanup; + } + p = tcache.tail; + move = RIGHT; + continue; + } + + p->tmp_ival = 0; + tcache.tail = NULL; /* finished decoding this structure */ + tcache.head = NULL; + DECR_LEN(ider_len, 2); + counter += 2; + } + else + { /* definite length method */ + if (len2 > counter) + { + result = _asn1_append_sequence_set (p, &tcache); + if (result != 0) + { + warn(); + goto cleanup; + } + p = tcache.tail; + move = RIGHT; + continue; + } + + p->tmp_ival = 0; + tcache.tail = NULL; /* finished decoding this structure */ + tcache.head = NULL; + + if (len2 != counter) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + } + } + else + { /* move==DOWN || move==RIGHT */ + len3 = + asn1_get_length_der (der + counter, ider_len, &len2); + if (IS_ERR(len3, flags)) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len2); + counter += len2; + if (len3) + { + if (len3 > 0) + { /* definite length method */ + p->tmp_ival = counter + len3; + } + else + { /* indefinite length method */ + p->tmp_ival = -1; + } + + p2 = p->down; + if (p2 == NULL) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + while ((type_field (p2->type) == ASN1_ETYPE_TAG) + || (type_field (p2->type) == ASN1_ETYPE_SIZE)) + p2 = p2->right; + if (p2->right == NULL) + { + result = _asn1_append_sequence_set (p, &tcache); + if (result != 0) + { + warn(); + goto cleanup; + } + } + p = p2; + } + } + move = RIGHT; + break; + case ASN1_ETYPE_ANY: + /* Check indefinite lenth method in an EXPLICIT TAG */ + + if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) && (p->type & CONST_TAG) && + tag_len == 2 && (der[counter - 1] == 0x80)) + indefinite = 1; + else + indefinite = 0; + + if (asn1_get_tag_der + (der + counter, ider_len, &class, &len2, + &tag) != ASN1_SUCCESS) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len2); + + len4 = + asn1_get_length_der (der + counter + len2, + ider_len, &len3); + if (IS_ERR(len4, flags)) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + if (len4 != -1) /* definite */ + { + len2 += len4; + + DECR_LEN(ider_len, len4+len3); + _asn1_set_value_lv (p, der + counter, len2 + len3); + counter += len2 + len3; + } + else /* == -1 */ + { /* indefinite length */ + ider_len += len2; /* undo DECR_LEN */ + + if (counter == 0) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + result = + _asn1_get_indefinite_length_string (der + counter, ider_len, &len2); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len2); + _asn1_set_value_lv (p, der + counter, len2); + counter += len2; + + } + + /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with + an indefinite length method. */ + if (indefinite) + { + DECR_LEN(ider_len, 2); + if (!der[counter] && !der[counter + 1]) + { + counter += 2; + } + else + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + } + + move = RIGHT; + break; + default: + move = (move == UP) ? RIGHT : DOWN; + break; + } + } + + if (p) + { + p->end = counter - 1; + } + + if (p == node && move != DOWN) + break; + + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + if ((move == RIGHT) && !(p->type & CONST_SET)) + { + if (p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + _asn1_delete_not_used (*element); + + if ((ider_len < 0) || + (!(flags & ASN1_DECODE_FLAG_ALLOW_PADDING) && (ider_len != 0))) + { + warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } + + *max_ider_len = total_len - ider_len; + + return ASN1_SUCCESS; + +cleanup: + asn1_delete_structure (element); + return result; +} + + +/** + * asn1_der_decoding: + * @element: pointer to an ASN1 structure. + * @ider: vector that contains the DER encoding. + * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1]. + * @errorDescription: null-terminated string contains details when an + * error occurred. + * + * Fill the structure *@element with values of a DER encoding + * string. The structure must just be created with function + * asn1_create_element(). + * + * Note that the *@element variable is provided as a pointer for + * historical reasons. + * + * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND + * if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or + * %ASN1_DER_ERROR if the der encoding doesn't match the structure + * name (*@ELEMENT deleted). + **/ +int +asn1_der_decoding (asn1_node * element, const void *ider, int ider_len, + char *errorDescription) +{ + return asn1_der_decoding2 (element, ider, &ider_len, 0, errorDescription); +} + +/** + * asn1_der_decoding_element: + * @structure: pointer to an ASN1 structure + * @elementName: name of the element to fill + * @ider: vector that contains the DER encoding of the whole structure. + * @len: number of bytes of *der: der[0]..der[len-1] + * @errorDescription: null-terminated string contains details when an + * error occurred. + * + * Fill the element named @ELEMENTNAME with values of a DER encoding + * string. The structure must just be created with function + * asn1_create_element(). The DER vector must contain the encoding + * string of the whole @STRUCTURE. If an error occurs during the + * decoding procedure, the *@STRUCTURE is deleted and set equal to + * %NULL. + * + * This function is deprecated and may just be an alias to asn1_der_decoding + * in future versions. Use asn1_der_decoding() instead. + * + * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND + * if ELEMENT is %NULL or @elementName == NULL, and + * %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding doesn't + * match the structure @structure (*ELEMENT deleted). + **/ +int +asn1_der_decoding_element (asn1_node * structure, const char *elementName, + const void *ider, int len, char *errorDescription) +{ + return asn1_der_decoding(structure, ider, len, errorDescription); +} + +/** + * asn1_der_decoding_startEnd: + * @element: pointer to an ASN1 element + * @ider: vector that contains the DER encoding. + * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1] + * @name_element: an element of NAME structure. + * @start: the position of the first byte of NAME_ELEMENT decoding + * (@ider[*start]) + * @end: the position of the last byte of NAME_ELEMENT decoding + * (@ider[*end]) + * + * Find the start and end point of an element in a DER encoding + * string. I mean that if you have a der encoding and you have already + * used the function asn1_der_decoding() to fill a structure, it may + * happen that you want to find the piece of string concerning an + * element of the structure. + * + * One example is the sequence "tbsCertificate" inside an X509 + * certificate. + * + * Note that since libtasn1 3.7 the @ider and @ider_len parameters + * can be omitted, if the element is already decoded using asn1_der_decoding(). + * + * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND + * if ELEMENT is %asn1_node EMPTY or @name_element is not a valid + * element, %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding + * doesn't match the structure ELEMENT. + **/ +int +asn1_der_decoding_startEnd (asn1_node element, const void *ider, int ider_len, + const char *name_element, int *start, int *end) +{ + asn1_node node, node_to_find; + int result = ASN1_DER_ERROR; + + node = element; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + node_to_find = asn1_find_node (node, name_element); + + if (node_to_find == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + *start = node_to_find->start; + *end = node_to_find->end; + + if (*start == 0 && *end == 0) + { + if (ider == NULL || ider_len == 0) + return ASN1_GENERIC_ERROR; + + /* it seems asn1_der_decoding() wasn't called before. Do it now */ + result = asn1_der_decoding (&node, ider, ider_len, NULL); + if (result != ASN1_SUCCESS) + { + warn(); + return result; + } + + node_to_find = asn1_find_node (node, name_element); + if (node_to_find == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + *start = node_to_find->start; + *end = node_to_find->end; + } + + if (*end < *start) + return ASN1_GENERIC_ERROR; + + return ASN1_SUCCESS; +} + +/** + * asn1_expand_any_defined_by: + * @definitions: ASN1 definitions + * @element: pointer to an ASN1 structure + * + * Expands every "ANY DEFINED BY" element of a structure created from + * a DER decoding process (asn1_der_decoding function). The element + * ANY must be defined by an OBJECT IDENTIFIER. The type used to + * expand the element ANY is the first one following the definition of + * the actual value of the OBJECT IDENTIFIER. + * + * Returns: %ASN1_SUCCESS if Substitution OK, %ASN1_ERROR_TYPE_ANY if + * some "ANY DEFINED BY" element couldn't be expanded due to a + * problem in OBJECT_ID -> TYPE association, or other error codes + * depending on DER decoding. + **/ +int +asn1_expand_any_defined_by (asn1_node_const definitions, asn1_node * element) +{ + char name[2 * ASN1_MAX_NAME_SIZE + 2], + value[ASN1_MAX_NAME_SIZE]; + int retCode = ASN1_SUCCESS, result; + int len, len2, len3; + asn1_node_const p2; + asn1_node p, p3, aux = NULL; + char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; + const char *definitionsName; + + if ((definitions == NULL) || (*element == NULL)) + return ASN1_ELEMENT_NOT_FOUND; + + definitionsName = definitions->name; + + p = *element; + while (p) + { + + switch (type_field (p->type)) + { + case ASN1_ETYPE_ANY: + if ((p->type & CONST_DEFINED_BY) && (p->value)) + { + /* search the "DEF_BY" element */ + p2 = p->down; + while ((p2) && (type_field (p2->type) != ASN1_ETYPE_CONSTANT)) + p2 = p2->right; + + if (!p2) + { + retCode = ASN1_ERROR_TYPE_ANY; + break; + } + + p3 = _asn1_find_up (p); + + if (!p3) + { + retCode = ASN1_ERROR_TYPE_ANY; + break; + } + + p3 = p3->down; + while (p3) + { + if (!(strcmp (p3->name, p2->name))) + break; + p3 = p3->right; + } + + if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || + (p3->value == NULL)) + { + + p3 = _asn1_find_up (p); + p3 = _asn1_find_up (p3); + + if (!p3) + { + retCode = ASN1_ERROR_TYPE_ANY; + break; + } + + p3 = p3->down; + + while (p3) + { + if (!(strcmp (p3->name, p2->name))) + break; + p3 = p3->right; + } + + if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) + || (p3->value == NULL)) + { + retCode = ASN1_ERROR_TYPE_ANY; + break; + } + } + + /* search the OBJECT_ID into definitions */ + p2 = definitions->down; + while (p2) + { + if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) && + (p2->type & CONST_ASSIGN)) + { + snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name); + + len = ASN1_MAX_NAME_SIZE; + result = + asn1_read_value (definitions, name, value, &len); + + if ((result == ASN1_SUCCESS) + && (!_asn1_strcmp (p3->value, value))) + { + p2 = p2->right; /* pointer to the structure to + use for expansion */ + while ((p2) && (p2->type & CONST_ASSIGN)) + p2 = p2->right; + + if (p2) + { + snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name); + + result = + asn1_create_element (definitions, name, &aux); + if (result == ASN1_SUCCESS) + { + _asn1_cpy_name (aux, p); + len2 = + asn1_get_length_der (p->value, + p->value_len, &len3); + if (len2 < 0) + return ASN1_DER_ERROR; + + result = + asn1_der_decoding (&aux, p->value + len3, + len2, + errorDescription); + if (result == ASN1_SUCCESS) + { + + _asn1_set_right (aux, p->right); + _asn1_set_right (p, aux); + + result = asn1_delete_structure (&p); + if (result == ASN1_SUCCESS) + { + p = aux; + aux = NULL; + break; + } + else + { /* error with asn1_delete_structure */ + asn1_delete_structure (&aux); + retCode = result; + break; + } + } + else + { /* error with asn1_der_decoding */ + retCode = result; + break; + } + } + else + { /* error with asn1_create_element */ + retCode = result; + break; + } + } + else + { /* error with the pointer to the structure to exapand */ + retCode = ASN1_ERROR_TYPE_ANY; + break; + } + } + } + p2 = p2->right; + } /* end while */ + + if (!p2) + { + retCode = ASN1_ERROR_TYPE_ANY; + break; + } + + } + break; + default: + break; + } + + + if (p->down) + { + p = p->down; + } + else if (p == *element) + { + p = NULL; + break; + } + else if (p->right) + p = p->right; + else + { + while (1) + { + p = _asn1_find_up (p); + if (p == *element) + { + p = NULL; + break; + } + if (p->right) + { + p = p->right; + break; + } + } + } + } + + return retCode; +} + +/** + * asn1_expand_octet_string: + * @definitions: ASN1 definitions + * @element: pointer to an ASN1 structure + * @octetName: name of the OCTECT STRING field to expand. + * @objectName: name of the OBJECT IDENTIFIER field to use to define + * the type for expansion. + * + * Expands an "OCTET STRING" element of a structure created from a DER + * decoding process (the asn1_der_decoding() function). The type used + * for expansion is the first one following the definition of the + * actual value of the OBJECT IDENTIFIER indicated by OBJECTNAME. + * + * Returns: %ASN1_SUCCESS if substitution OK, %ASN1_ELEMENT_NOT_FOUND + * if @objectName or @octetName are not correct, + * %ASN1_VALUE_NOT_VALID if it wasn't possible to find the type to + * use for expansion, or other errors depending on DER decoding. + **/ +int +asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element, + const char *octetName, const char *objectName) +{ + char name[2 * ASN1_MAX_NAME_SIZE + 1], value[ASN1_MAX_NAME_SIZE]; + int retCode = ASN1_SUCCESS, result; + int len, len2, len3; + asn1_node_const p2; + asn1_node aux = NULL; + asn1_node octetNode = NULL, objectNode = NULL; + char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; + + if ((definitions == NULL) || (*element == NULL)) + return ASN1_ELEMENT_NOT_FOUND; + + octetNode = asn1_find_node (*element, octetName); + if (octetNode == NULL) + return ASN1_ELEMENT_NOT_FOUND; + if (type_field (octetNode->type) != ASN1_ETYPE_OCTET_STRING) + return ASN1_ELEMENT_NOT_FOUND; + if (octetNode->value == NULL) + return ASN1_VALUE_NOT_FOUND; + + objectNode = asn1_find_node (*element, objectName); + if (objectNode == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + if (type_field (objectNode->type) != ASN1_ETYPE_OBJECT_ID) + return ASN1_ELEMENT_NOT_FOUND; + + if (objectNode->value == NULL) + return ASN1_VALUE_NOT_FOUND; + + + /* search the OBJECT_ID into definitions */ + p2 = definitions->down; + while (p2) + { + if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) && + (p2->type & CONST_ASSIGN)) + { + strcpy (name, definitions->name); + strcat (name, "."); + strcat (name, p2->name); + + len = sizeof (value); + result = asn1_read_value (definitions, name, value, &len); + + if ((result == ASN1_SUCCESS) + && (!_asn1_strcmp (objectNode->value, value))) + { + + p2 = p2->right; /* pointer to the structure to + use for expansion */ + while ((p2) && (p2->type & CONST_ASSIGN)) + p2 = p2->right; + + if (p2) + { + strcpy (name, definitions->name); + strcat (name, "."); + strcat (name, p2->name); + + result = asn1_create_element (definitions, name, &aux); + if (result == ASN1_SUCCESS) + { + _asn1_cpy_name (aux, octetNode); + len2 = + asn1_get_length_der (octetNode->value, + octetNode->value_len, &len3); + if (len2 < 0) + return ASN1_DER_ERROR; + + result = + asn1_der_decoding (&aux, octetNode->value + len3, + len2, errorDescription); + if (result == ASN1_SUCCESS) + { + + _asn1_set_right (aux, octetNode->right); + _asn1_set_right (octetNode, aux); + + result = asn1_delete_structure (&octetNode); + if (result == ASN1_SUCCESS) + { + aux = NULL; + break; + } + else + { /* error with asn1_delete_structure */ + asn1_delete_structure (&aux); + retCode = result; + break; + } + } + else + { /* error with asn1_der_decoding */ + retCode = result; + break; + } + } + else + { /* error with asn1_create_element */ + retCode = result; + break; + } + } + else + { /* error with the pointer to the structure to exapand */ + retCode = ASN1_VALUE_NOT_VALID; + break; + } + } + } + + p2 = p2->right; + + } + + if (!p2) + retCode = ASN1_VALUE_NOT_VALID; + + return retCode; +} + +/*- + * _asn1_decode_simple_der: + * @etype: The type of the string to be encoded (ASN1_ETYPE_) + * @der: the encoded string + * @_der_len: the bytes of the encoded string + * @str: a pointer to the data + * @str_len: the length of the data + * @dflags: DECODE_FLAG_* + * + * Decodes a simple DER encoded type (e.g. a string, which is not constructed). + * The output is a pointer inside the @der. + * + * Returns: %ASN1_SUCCESS if successful or an error value. + -*/ +static int +_asn1_decode_simple_der (unsigned int etype, const unsigned char *der, + unsigned int _der_len, const unsigned char **str, + unsigned int *str_len, unsigned dflags) +{ + int tag_len, len_len; + const unsigned char *p; + int der_len = _der_len; + unsigned char class; + unsigned long tag; + long ret; + + if (der == NULL || der_len == 0) + return ASN1_VALUE_NOT_VALID; + + if (ETYPE_OK (etype) == 0 || ETYPE_IS_STRING(etype) == 0) + return ASN1_VALUE_NOT_VALID; + + /* doesn't handle constructed classes */ + class = ETYPE_CLASS(etype); + if (class != ASN1_CLASS_UNIVERSAL) + return ASN1_VALUE_NOT_VALID; + + p = der; + + if (dflags & DECODE_FLAG_HAVE_TAG) + { + ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); + if (ret != ASN1_SUCCESS) + return ret; + + if (class != ETYPE_CLASS (etype) || tag != ETYPE_TAG (etype)) + { + warn(); + return ASN1_DER_ERROR; + } + + p += tag_len; + der_len -= tag_len; + if (der_len <= 0) + return ASN1_DER_ERROR; + } + + ret = asn1_get_length_der (p, der_len, &len_len); + if (ret < 0) + return ASN1_DER_ERROR; + + p += len_len; + der_len -= len_len; + if (der_len <= 0) + return ASN1_DER_ERROR; + + *str_len = ret; + *str = p; + + return ASN1_SUCCESS; +} + +/** + * asn1_decode_simple_der: + * @etype: The type of the string to be encoded (ASN1_ETYPE_) + * @der: the encoded string + * @_der_len: the bytes of the encoded string + * @str: a pointer to the data + * @str_len: the length of the data + * + * Decodes a simple DER encoded type (e.g. a string, which is not constructed). + * The output is a pointer inside the @der. + * + * Returns: %ASN1_SUCCESS if successful or an error value. + **/ +int +asn1_decode_simple_der (unsigned int etype, const unsigned char *der, + unsigned int _der_len, const unsigned char **str, + unsigned int *str_len) +{ + return _asn1_decode_simple_der(etype, der, _der_len, str, str_len, DECODE_FLAG_HAVE_TAG); +} + +static int append(uint8_t **dst, unsigned *dst_size, const unsigned char *src, unsigned src_size) +{ + if (src_size == 0) + return ASN1_SUCCESS; + + *dst = _asn1_realloc(*dst, *dst_size+src_size); + if (*dst == NULL) + return ASN1_MEM_ALLOC_ERROR; + memcpy(*dst + *dst_size, src, src_size); + *dst_size += src_size; + return ASN1_SUCCESS; +} + +/*- + * _asn1_decode_simple_ber: + * @etype: The type of the string to be encoded (ASN1_ETYPE_) + * @der: the encoded string + * @_der_len: the bytes of the encoded string + * @str: a pointer to the data + * @str_len: the length of the data + * @ber_len: the total length occupied by BER (may be %NULL) + * @have_tag: whether a DER tag is included + * + * Decodes a BER encoded type. The output is an allocated value + * of the data. This decodes BER STRINGS only. Other types are + * decoded as DER. + * + * Returns: %ASN1_SUCCESS if successful or an error value. + -*/ +static int +_asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, + unsigned int _der_len, unsigned char **str, + unsigned int *str_len, unsigned int *ber_len, + unsigned dflags) +{ + int tag_len, len_len; + const unsigned char *p; + int der_len = _der_len; + uint8_t *total = NULL; + unsigned total_size = 0; + unsigned char class; + unsigned long tag; + unsigned char *out = NULL; + const unsigned char *cout = NULL; + unsigned out_len; + long result; + + if (ber_len) *ber_len = 0; + + if (der == NULL || der_len == 0) + { + warn(); + return ASN1_VALUE_NOT_VALID; + } + + if (ETYPE_OK (etype) == 0) + { + warn(); + return ASN1_VALUE_NOT_VALID; + } + + /* doesn't handle constructed + definite classes */ + class = ETYPE_CLASS (etype); + if (class != ASN1_CLASS_UNIVERSAL) + { + warn(); + return ASN1_VALUE_NOT_VALID; + } + + p = der; + + if (dflags & DECODE_FLAG_HAVE_TAG) + { + result = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); + if (result != ASN1_SUCCESS) + { + warn(); + return result; + } + + if (tag != ETYPE_TAG (etype)) + { + warn(); + return ASN1_DER_ERROR; + } + + p += tag_len; + + DECR_LEN(der_len, tag_len); + + if (ber_len) *ber_len += tag_len; + } + + /* indefinite constructed */ + if ((((dflags & DECODE_FLAG_CONSTRUCTED) || class == ASN1_CLASS_STRUCTURED) && ETYPE_IS_STRING(etype)) && + !(dflags & DECODE_FLAG_LEVEL3)) + { + if (der_len == 0) + { + warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } + + if (der_len > 0 && p[0] == 0x80) /* indefinite */ + { + len_len = 1; + DECR_LEN(der_len, len_len); + p += len_len; + + if (ber_len) *ber_len += len_len; + + /* decode the available octet strings */ + do + { + unsigned tmp_len; + unsigned flags = DECODE_FLAG_HAVE_TAG; + + if (dflags & DECODE_FLAG_LEVEL1) + flags |= DECODE_FLAG_LEVEL2; + else if (dflags & DECODE_FLAG_LEVEL2) + flags |= DECODE_FLAG_LEVEL3; + else + flags |= DECODE_FLAG_LEVEL1; + + result = _asn1_decode_simple_ber(etype, p, der_len, &out, &out_len, &tmp_len, + flags); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + p += tmp_len; + DECR_LEN(der_len, tmp_len); + + if (ber_len) *ber_len += tmp_len; + + DECR_LEN(der_len, 2); /* we need the EOC */ + + result = append(&total, &total_size, out, out_len); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + free(out); + out = NULL; + + if (p[0] == 0 && p[1] == 0) /* EOC */ + { + if (ber_len) *ber_len += 2; + break; + } + + /* no EOC */ + der_len += 2; + + if (der_len == 2) + { + warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } + } + while(1); + } + else /* constructed */ + { + long const_len; + + result = asn1_get_length_ber(p, der_len, &len_len); + if (result < 0) + { + warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } + + DECR_LEN(der_len, len_len); + p += len_len; + + const_len = result; + + if (ber_len) *ber_len += len_len; + + /* decode the available octet strings */ + while(const_len > 0) + { + unsigned tmp_len; + unsigned flags = DECODE_FLAG_HAVE_TAG; + + if (dflags & DECODE_FLAG_LEVEL1) + flags |= DECODE_FLAG_LEVEL2; + else if (dflags & DECODE_FLAG_LEVEL2) + flags |= DECODE_FLAG_LEVEL3; + else + flags |= DECODE_FLAG_LEVEL1; + + result = _asn1_decode_simple_ber(etype, p, der_len, &out, &out_len, &tmp_len, + flags); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + p += tmp_len; + DECR_LEN(der_len, tmp_len); + DECR_LEN(const_len, tmp_len); + + if (ber_len) *ber_len += tmp_len; + + result = append(&total, &total_size, out, out_len); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + free(out); + out = NULL; + } + } + } + else if (class == ETYPE_CLASS(etype)) + { + if (ber_len) + { + result = asn1_get_length_der (p, der_len, &len_len); + if (result < 0) + { + warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } + *ber_len += result + len_len; + } + + /* non-string values are decoded as DER */ + result = _asn1_decode_simple_der(etype, der, _der_len, &cout, &out_len, dflags); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + result = append(&total, &total_size, cout, out_len); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + } + else + { + warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } + + *str = total; + *str_len = total_size; + + return ASN1_SUCCESS; +cleanup: + free(out); + free(total); + return result; +} + +/** + * asn1_decode_simple_ber: + * @etype: The type of the string to be encoded (ASN1_ETYPE_) + * @der: the encoded string + * @_der_len: the bytes of the encoded string + * @str: a pointer to the data + * @str_len: the length of the data + * @ber_len: the total length occupied by BER (may be %NULL) + * + * Decodes a BER encoded type. The output is an allocated value + * of the data. This decodes BER STRINGS only. Other types are + * decoded as DER. + * + * Returns: %ASN1_SUCCESS if successful or an error value. + **/ +int +asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, + unsigned int _der_len, unsigned char **str, + unsigned int *str_len, unsigned int *ber_len) +{ + return _asn1_decode_simple_ber(etype, der, _der_len, str, str_len, ber_len, DECODE_FLAG_HAVE_TAG); +} diff --git a/lib/minitasn1/element.c b/lib/minitasn1/element.c new file mode 100644 index 0000000..997eb27 --- /dev/null +++ b/lib/minitasn1/element.c @@ -0,0 +1,1111 @@ +/* + * Copyright (C) 2000-2014 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +/*****************************************************/ +/* File: element.c */ +/* Description: Functions with the read and write */ +/* functions. */ +/*****************************************************/ + + +#include +#include "parser_aux.h" +#include +#include "structure.h" +#include "c-ctype.h" +#include "element.h" + +void +_asn1_hierarchical_name (asn1_node_const node, char *name, int name_size) +{ + asn1_node_const p; + char tmp_name[64]; + + p = node; + + name[0] = 0; + + while (p != NULL) + { + if (p->name[0] != 0) + { + _asn1_str_cpy (tmp_name, sizeof (tmp_name), name), + _asn1_str_cpy (name, name_size, p->name); + _asn1_str_cat (name, name_size, "."); + _asn1_str_cat (name, name_size, tmp_name); + } + p = _asn1_find_up (p); + } + + if (name[0] == 0) + _asn1_str_cpy (name, name_size, "ROOT"); +} + + +/******************************************************************/ +/* Function : _asn1_convert_integer */ +/* Description: converts an integer from a null terminated string */ +/* to der decoding. The convertion from a null */ +/* terminated string to an integer is made with */ +/* the 'strtol' function. */ +/* Parameters: */ +/* value: null terminated string to convert. */ +/* value_out: convertion result (memory must be already */ +/* allocated). */ +/* value_out_size: number of bytes of value_out. */ +/* len: number of significant byte of value_out. */ +/* Return: ASN1_MEM_ERROR or ASN1_SUCCESS */ +/******************************************************************/ +int +_asn1_convert_integer (const unsigned char *value, unsigned char *value_out, + int value_out_size, int *len) +{ + char negative; + unsigned char val[SIZEOF_UNSIGNED_LONG_INT]; + long valtmp; + int k, k2; + + valtmp = _asn1_strtol (value, NULL, 10); + + for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++) + { + val[SIZEOF_UNSIGNED_LONG_INT - k - 1] = (valtmp >> (8 * k)) & 0xFF; + } + + if (val[0] & 0x80) + negative = 1; + else + negative = 0; + + for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT - 1; k++) + { + if (negative && (val[k] != 0xFF)) + break; + else if (!negative && val[k]) + break; + } + + if ((negative && !(val[k] & 0x80)) || (!negative && (val[k] & 0x80))) + k--; + + *len = SIZEOF_UNSIGNED_LONG_INT - k; + + if (SIZEOF_UNSIGNED_LONG_INT - k > value_out_size) + /* VALUE_OUT is too short to contain the value conversion */ + return ASN1_MEM_ERROR; + + if (value_out != NULL) + { + for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++) + value_out[k2 - k] = val[k2]; + } + +#if 0 + printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len); + for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++) + printf (", vOut[%d]=%d", k, value_out[k]); + printf ("\n"); +#endif + + return ASN1_SUCCESS; +} + +/* Appends a new element into the sequence (or set) defined by this + * node. The new element will have a name of '?number', where number + * is a monotonically increased serial number. + * + * The last element in the list may be provided in @pcache, to avoid + * traversing the list, an expensive operation in long lists. + * + * On success it returns in @pcache the added element (which is the + * tail in the list of added elements). + */ +int +_asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcache) +{ + asn1_node p, p2; + char temp[LTOSTR_MAX_SIZE]; + long n; + + if (!node || !(node->down)) + return ASN1_GENERIC_ERROR; + + p = node->down; + while ((type_field (p->type) == ASN1_ETYPE_TAG) + || (type_field (p->type) == ASN1_ETYPE_SIZE)) + p = p->right; + + p2 = _asn1_copy_structure3 (p); + if (p2 == NULL) + return ASN1_GENERIC_ERROR; + + if (pcache == NULL || pcache->tail == NULL || pcache->head != node) + { + while (p->right) + { + p = p->right; + } + } + else + { + p = pcache->tail; + } + + _asn1_set_right (p, p2); + if (pcache) + { + pcache->head = node; + pcache->tail = p2; + } + + if (p->name[0] == 0) + _asn1_str_cpy (temp, sizeof (temp), "?1"); + else + { + n = strtol (p->name + 1, NULL, 0); + n++; + temp[0] = '?'; + _asn1_ltostr (n, temp + 1); + } + _asn1_set_name (p2, temp); + /* p2->type |= CONST_OPTION; */ + + return ASN1_SUCCESS; +} + + +/** + * asn1_write_value: + * @node_root: pointer to a structure + * @name: the name of the element inside the structure that you want to set. + * @ivalue: vector used to specify the value to set. If len is >0, + * VALUE must be a two's complement form integer. if len=0 *VALUE + * must be a null terminated string with an integer value. + * @len: number of bytes of *value to use to set the value: + * value[0]..value[len-1] or 0 if value is a null terminated string + * + * Set the value of one element inside a structure. + * + * If an element is OPTIONAL and you want to delete it, you must use + * the value=NULL and len=0. Using "pkix.asn": + * + * result=asn1_write_value(cert, "tbsCertificate.issuerUniqueID", + * NULL, 0); + * + * Description for each type: + * + * INTEGER: VALUE must contain a two's complement form integer. + * + * value[0]=0xFF , len=1 -> integer=-1. + * value[0]=0xFF value[1]=0xFF , len=2 -> integer=-1. + * value[0]=0x01 , len=1 -> integer= 1. + * value[0]=0x00 value[1]=0x01 , len=2 -> integer= 1. + * value="123" , len=0 -> integer= 123. + * + * ENUMERATED: As INTEGER (but only with not negative numbers). + * + * BOOLEAN: VALUE must be the null terminated string "TRUE" or + * "FALSE" and LEN != 0. + * + * value="TRUE" , len=1 -> boolean=TRUE. + * value="FALSE" , len=1 -> boolean=FALSE. + * + * OBJECT IDENTIFIER: VALUE must be a null terminated string with + * each number separated by a dot (e.g. "1.2.3.543.1"). LEN != 0. + * + * value="1 2 840 10040 4 3" , len=1 -> OID=dsa-with-sha. + * + * UTCTime: VALUE must be a null terminated string in one of these + * formats: "YYMMDDhhmmssZ", "YYMMDDhhmmssZ", + * "YYMMDDhhmmss+hh'mm'", "YYMMDDhhmmss-hh'mm'", + * "YYMMDDhhmm+hh'mm'", or "YYMMDDhhmm-hh'mm'". LEN != 0. + * + * value="9801011200Z" , len=1 -> time=Jannuary 1st, 1998 + * at 12h 00m Greenwich Mean Time + * + * GeneralizedTime: VALUE must be in one of this format: + * "YYYYMMDDhhmmss.sZ", "YYYYMMDDhhmmss.sZ", + * "YYYYMMDDhhmmss.s+hh'mm'", "YYYYMMDDhhmmss.s-hh'mm'", + * "YYYYMMDDhhmm+hh'mm'", or "YYYYMMDDhhmm-hh'mm'" where ss.s + * indicates the seconds with any precision like "10.1" or "01.02". + * LEN != 0 + * + * value="2001010112001.12-0700" , len=1 -> time=Jannuary + * 1st, 2001 at 12h 00m 01.12s Pacific Daylight Time + * + * OCTET STRING: VALUE contains the octet string and LEN is the + * number of octets. + * + * value="$\backslash$x01$\backslash$x02$\backslash$x03" , + * len=3 -> three bytes octet string + * + * GeneralString: VALUE contains the generalstring and LEN is the + * number of octets. + * + * value="$\backslash$x01$\backslash$x02$\backslash$x03" , + * len=3 -> three bytes generalstring + * + * BIT STRING: VALUE contains the bit string organized by bytes and + * LEN is the number of bits. + * + * value="$\backslash$xCF" , len=6 -> bit string="110011" (six + * bits) + * + * CHOICE: if NAME indicates a choice type, VALUE must specify one of + * the alternatives with a null terminated string. LEN != 0. Using + * "pkix.asn"\: + * + * result=asn1_write_value(cert, + * "certificate1.tbsCertificate.subject", "rdnSequence", + * 1); + * + * ANY: VALUE indicates the der encoding of a structure. LEN != 0. + * + * SEQUENCE OF: VALUE must be the null terminated string "NEW" and + * LEN != 0. With this instruction another element is appended in + * the sequence. The name of this element will be "?1" if it's the + * first one, "?2" for the second and so on. + * + * Using "pkix.asn"\: + * + * result=asn1_write_value(cert, + * "certificate1.tbsCertificate.subject.rdnSequence", "NEW", 1); + * + * SET OF: the same as SEQUENCE OF. Using "pkix.asn": + * + * result=asn1_write_value(cert, + * "tbsCertificate.subject.rdnSequence.?LAST", "NEW", 1); + * + * Returns: %ASN1_SUCCESS if the value was set, + * %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, and + * %ASN1_VALUE_NOT_VALID if @ivalue has a wrong format. + **/ +int +asn1_write_value (asn1_node node_root, const char *name, + const void *ivalue, int len) +{ + asn1_node node, p, p2; + unsigned char *temp, *value_temp = NULL, *default_temp = NULL; + int len2, k, k2, negative; + size_t i; + const unsigned char *value = ivalue; + unsigned int type; + + node = asn1_find_node (node_root, name); + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + if ((node->type & CONST_OPTION) && (value == NULL) && (len == 0)) + { + asn1_delete_structure (&node); + return ASN1_SUCCESS; + } + + type = type_field (node->type); + + if ((type == ASN1_ETYPE_SEQUENCE_OF || type == ASN1_ETYPE_SET_OF) && (value == NULL) && (len == 0)) + { + p = node->down; + while ((type_field (p->type) == ASN1_ETYPE_TAG) + || (type_field (p->type) == ASN1_ETYPE_SIZE)) + p = p->right; + + while (p->right) + asn1_delete_structure (&p->right); + + return ASN1_SUCCESS; + } + + /* Don't allow element deletion for other types */ + if (value == NULL) + { + return ASN1_VALUE_NOT_VALID; + } + + switch (type) + { + case ASN1_ETYPE_BOOLEAN: + if (!_asn1_strcmp (value, "TRUE")) + { + if (node->type & CONST_DEFAULT) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + if (p->type & CONST_TRUE) + _asn1_set_value (node, NULL, 0); + else + _asn1_set_value (node, "T", 1); + } + else + _asn1_set_value (node, "T", 1); + } + else if (!_asn1_strcmp (value, "FALSE")) + { + if (node->type & CONST_DEFAULT) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + if (p->type & CONST_FALSE) + _asn1_set_value (node, NULL, 0); + else + _asn1_set_value (node, "F", 1); + } + else + _asn1_set_value (node, "F", 1); + } + else + return ASN1_VALUE_NOT_VALID; + break; + case ASN1_ETYPE_INTEGER: + case ASN1_ETYPE_ENUMERATED: + if (len == 0) + { + if ((c_isdigit (value[0])) || (value[0] == '-')) + { + value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); + if (value_temp == NULL) + return ASN1_MEM_ALLOC_ERROR; + + _asn1_convert_integer (value, value_temp, + SIZEOF_UNSIGNED_LONG_INT, &len); + } + else + { /* is an identifier like v1 */ + if (!(node->type & CONST_LIST)) + return ASN1_VALUE_NOT_VALID; + p = node->down; + while (p) + { + if (type_field (p->type) == ASN1_ETYPE_CONSTANT) + { + if (!_asn1_strcmp (p->name, value)) + { + value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); + if (value_temp == NULL) + return ASN1_MEM_ALLOC_ERROR; + + _asn1_convert_integer (p->value, + value_temp, + SIZEOF_UNSIGNED_LONG_INT, + &len); + break; + } + } + p = p->right; + } + if (p == NULL) + return ASN1_VALUE_NOT_VALID; + } + } + else + { /* len != 0 */ + value_temp = malloc (len); + if (value_temp == NULL) + return ASN1_MEM_ALLOC_ERROR; + memcpy (value_temp, value, len); + } + + if (value_temp[0] & 0x80) + negative = 1; + else + negative = 0; + + if (negative && (type_field (node->type) == ASN1_ETYPE_ENUMERATED)) + { + free (value_temp); + return ASN1_VALUE_NOT_VALID; + } + + for (k = 0; k < len - 1; k++) + if (negative && (value_temp[k] != 0xFF)) + break; + else if (!negative && value_temp[k]) + break; + + if ((negative && !(value_temp[k] & 0x80)) || + (!negative && (value_temp[k] & 0x80))) + k--; + + _asn1_set_value_lv (node, value_temp + k, len - k); + + if (node->type & CONST_DEFAULT) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + if ((c_isdigit (p->value[0])) || (p->value[0] == '-')) + { + default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); + if (default_temp == NULL) + { + free (value_temp); + return ASN1_MEM_ALLOC_ERROR; + } + + _asn1_convert_integer (p->value, default_temp, + SIZEOF_UNSIGNED_LONG_INT, &len2); + } + else + { /* is an identifier like v1 */ + if (!(node->type & CONST_LIST)) + { + free (value_temp); + return ASN1_VALUE_NOT_VALID; + } + p2 = node->down; + while (p2) + { + if (type_field (p2->type) == ASN1_ETYPE_CONSTANT) + { + if (!_asn1_strcmp (p2->name, p->value)) + { + default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); + if (default_temp == NULL) + { + free (value_temp); + return ASN1_MEM_ALLOC_ERROR; + } + + _asn1_convert_integer (p2->value, + default_temp, + SIZEOF_UNSIGNED_LONG_INT, + &len2); + break; + } + } + p2 = p2->right; + } + if (p2 == NULL) + { + free (value_temp); + return ASN1_VALUE_NOT_VALID; + } + } + + + if ((len - k) == len2) + { + for (k2 = 0; k2 < len2; k2++) + if (value_temp[k + k2] != default_temp[k2]) + { + break; + } + if (k2 == len2) + _asn1_set_value (node, NULL, 0); + } + free (default_temp); + } + free (value_temp); + break; + case ASN1_ETYPE_OBJECT_ID: + for (i = 0; i < _asn1_strlen (value); i++) + if ((!c_isdigit (value[i])) && (value[i] != '.') && (value[i] != '+')) + return ASN1_VALUE_NOT_VALID; + if (node->type & CONST_DEFAULT) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + if (!_asn1_strcmp (value, p->value)) + { + _asn1_set_value (node, NULL, 0); + break; + } + } + _asn1_set_value (node, value, _asn1_strlen (value) + 1); + break; + case ASN1_ETYPE_UTC_TIME: + { + len = _asn1_strlen (value); + if (len < 11) + return ASN1_VALUE_NOT_VALID; + for (k = 0; k < 10; k++) + if (!c_isdigit (value[k])) + return ASN1_VALUE_NOT_VALID; + switch (len) + { + case 11: + if (value[10] != 'Z') + return ASN1_VALUE_NOT_VALID; + break; + case 13: + if ((!c_isdigit (value[10])) || (!c_isdigit (value[11])) || + (value[12] != 'Z')) + return ASN1_VALUE_NOT_VALID; + break; + case 15: + if ((value[10] != '+') && (value[10] != '-')) + return ASN1_VALUE_NOT_VALID; + for (k = 11; k < 15; k++) + if (!c_isdigit (value[k])) + return ASN1_VALUE_NOT_VALID; + break; + case 17: + if ((!c_isdigit (value[10])) || (!c_isdigit (value[11]))) + return ASN1_VALUE_NOT_VALID; + if ((value[12] != '+') && (value[12] != '-')) + return ASN1_VALUE_NOT_VALID; + for (k = 13; k < 17; k++) + if (!c_isdigit (value[k])) + return ASN1_VALUE_NOT_VALID; + break; + default: + return ASN1_VALUE_NOT_FOUND; + } + _asn1_set_value (node, value, len); + } + break; + case ASN1_ETYPE_GENERALIZED_TIME: + len = _asn1_strlen (value); + _asn1_set_value (node, value, len); + break; + case ASN1_ETYPE_OCTET_STRING: + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + if (len == 0) + len = _asn1_strlen (value); + _asn1_set_value_lv (node, value, len); + break; + case ASN1_ETYPE_BIT_STRING: + if (len == 0) + len = _asn1_strlen (value); + asn1_length_der ((len >> 3) + 2, NULL, &len2); + temp = malloc ((len >> 3) + 2 + len2); + if (temp == NULL) + return ASN1_MEM_ALLOC_ERROR; + + asn1_bit_der (value, len, temp, &len2); + _asn1_set_value_m (node, temp, len2); + temp = NULL; + break; + case ASN1_ETYPE_CHOICE: + p = node->down; + while (p) + { + if (!_asn1_strcmp (p->name, value)) + { + p2 = node->down; + while (p2) + { + if (p2 != p) + { + asn1_delete_structure (&p2); + p2 = node->down; + } + else + p2 = p2->right; + } + break; + } + p = p->right; + } + if (!p) + return ASN1_ELEMENT_NOT_FOUND; + break; + case ASN1_ETYPE_ANY: + _asn1_set_value_lv (node, value, len); + break; + case ASN1_ETYPE_SEQUENCE_OF: + case ASN1_ETYPE_SET_OF: + if (_asn1_strcmp (value, "NEW")) + return ASN1_VALUE_NOT_VALID; + _asn1_append_sequence_set (node, NULL); + break; + default: + return ASN1_ELEMENT_NOT_FOUND; + break; + } + + return ASN1_SUCCESS; +} + + +#define PUT_VALUE( ptr, ptr_size, data, data_size) \ + *len = data_size; \ + if (ptr_size < data_size) { \ + return ASN1_MEM_ERROR; \ + } else { \ + if (ptr && data_size > 0) \ + memcpy (ptr, data, data_size); \ + } + +#define PUT_STR_VALUE( ptr, ptr_size, data) \ + *len = _asn1_strlen (data) + 1; \ + if (ptr_size < *len) { \ + return ASN1_MEM_ERROR; \ + } else { \ + /* this strcpy is checked */ \ + if (ptr) { \ + _asn1_strcpy (ptr, data); \ + } \ + } + +#define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \ + *len = data_size + 1; \ + if (ptr_size < *len) { \ + return ASN1_MEM_ERROR; \ + } else { \ + /* this strcpy is checked */ \ + if (ptr) { \ + if (data_size > 0) \ + memcpy (ptr, data, data_size); \ + ptr[data_size] = 0; \ + } \ + } + +#define ADD_STR_VALUE( ptr, ptr_size, data) \ + *len += _asn1_strlen(data); \ + if (ptr_size < (int) *len) { \ + (*len)++; \ + return ASN1_MEM_ERROR; \ + } else { \ + /* this strcat is checked */ \ + if (ptr) _asn1_strcat (ptr, data); \ + } + +/** + * asn1_read_value: + * @root: pointer to a structure. + * @name: the name of the element inside a structure that you want to read. + * @ivalue: vector that will contain the element's content, must be a + * pointer to memory cells already allocated (may be %NULL). + * @len: number of bytes of *value: value[0]..value[len-1]. Initialy + * holds the sizeof value. + * + * Returns the value of one element inside a structure. + * If an element is OPTIONAL and this returns + * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present + * in the der encoding that created the structure. The first element + * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and + * so on. If the @root provided is a node to specific sequence element, + * then the keyword "?CURRENT" is also acceptable and indicates the + * current sequence element of this node. + * + * Note that there can be valid values with length zero. In these case + * this function will succeed and @len will be zero. + * + * INTEGER: VALUE will contain a two's complement form integer. + * + * integer=-1 -> value[0]=0xFF , len=1. + * integer=1 -> value[0]=0x01 , len=1. + * + * ENUMERATED: As INTEGER (but only with not negative numbers). + * + * BOOLEAN: VALUE will be the null terminated string "TRUE" or + * "FALSE" and LEN=5 or LEN=6. + * + * OBJECT IDENTIFIER: VALUE will be a null terminated string with + * each number separated by a dot (i.e. "1.2.3.543.1"). + * + * LEN = strlen(VALUE)+1 + * + * UTCTime: VALUE will be a null terminated string in one of these + * formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'". + * LEN=strlen(VALUE)+1. + * + * GeneralizedTime: VALUE will be a null terminated string in the + * same format used to set the value. + * + * OCTET STRING: VALUE will contain the octet string and LEN will be + * the number of octets. + * + * GeneralString: VALUE will contain the generalstring and LEN will + * be the number of octets. + * + * BIT STRING: VALUE will contain the bit string organized by bytes + * and LEN will be the number of bits. + * + * CHOICE: If NAME indicates a choice type, VALUE will specify the + * alternative selected. + * + * ANY: If NAME indicates an any type, VALUE will indicate the DER + * encoding of the structure actually used. + * + * Returns: %ASN1_SUCCESS if value is returned, + * %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, + * %ASN1_VALUE_NOT_FOUND if there isn't any value for the element + * selected, and %ASN1_MEM_ERROR if The value vector isn't big enough + * to store the result, and in this case @len will contain the number of + * bytes needed. On the occasion that the stored data are of zero-length + * this function may return %ASN1_SUCCESS even if the provided @len is zero. + **/ +int +asn1_read_value (asn1_node_const root, const char *name, void *ivalue, int *len) +{ + return asn1_read_value_type (root, name, ivalue, len, NULL); +} + +/** + * asn1_read_value_type: + * @root: pointer to a structure. + * @name: the name of the element inside a structure that you want to read. + * @ivalue: vector that will contain the element's content, must be a + * pointer to memory cells already allocated (may be %NULL). + * @len: number of bytes of *value: value[0]..value[len-1]. Initialy + * holds the sizeof value. + * @etype: The type of the value read (ASN1_ETYPE) + * + * Returns the type and value of one element inside a structure. + * If an element is OPTIONAL and this returns + * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present + * in the der encoding that created the structure. The first element + * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and + * so on. If the @root provided is a node to specific sequence element, + * then the keyword "?CURRENT" is also acceptable and indicates the + * current sequence element of this node. + * + * Note that there can be valid values with length zero. In these case + * this function will succeed and @len will be zero. + * + * + * INTEGER: VALUE will contain a two's complement form integer. + * + * integer=-1 -> value[0]=0xFF , len=1. + * integer=1 -> value[0]=0x01 , len=1. + * + * ENUMERATED: As INTEGER (but only with not negative numbers). + * + * BOOLEAN: VALUE will be the null terminated string "TRUE" or + * "FALSE" and LEN=5 or LEN=6. + * + * OBJECT IDENTIFIER: VALUE will be a null terminated string with + * each number separated by a dot (i.e. "1.2.3.543.1"). + * + * LEN = strlen(VALUE)+1 + * + * UTCTime: VALUE will be a null terminated string in one of these + * formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'". + * LEN=strlen(VALUE)+1. + * + * GeneralizedTime: VALUE will be a null terminated string in the + * same format used to set the value. + * + * OCTET STRING: VALUE will contain the octet string and LEN will be + * the number of octets. + * + * GeneralString: VALUE will contain the generalstring and LEN will + * be the number of octets. + * + * BIT STRING: VALUE will contain the bit string organized by bytes + * and LEN will be the number of bits. + * + * CHOICE: If NAME indicates a choice type, VALUE will specify the + * alternative selected. + * + * ANY: If NAME indicates an any type, VALUE will indicate the DER + * encoding of the structure actually used. + * + * Returns: %ASN1_SUCCESS if value is returned, + * %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, + * %ASN1_VALUE_NOT_FOUND if there isn't any value for the element + * selected, and %ASN1_MEM_ERROR if The value vector isn't big enough + * to store the result, and in this case @len will contain the number of + * bytes needed. On the occasion that the stored data are of zero-length + * this function may return %ASN1_SUCCESS even if the provided @len is zero. + **/ +int +asn1_read_value_type (asn1_node_const root, const char *name, void *ivalue, + int *len, unsigned int *etype) +{ + asn1_node_const node, p, p2; + int len2, len3, result; + int value_size = *len; + unsigned char *value = ivalue; + unsigned type; + + node = asn1_find_node (root, name); + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + type = type_field (node->type); + + if ((type != ASN1_ETYPE_NULL) && + (type != ASN1_ETYPE_CHOICE) && + !(node->type & CONST_DEFAULT) && !(node->type & CONST_ASSIGN) && + (node->value == NULL)) + return ASN1_VALUE_NOT_FOUND; + + if (etype) + *etype = type; + switch (type) + { + case ASN1_ETYPE_NULL: + PUT_STR_VALUE (value, value_size, "NULL"); + break; + case ASN1_ETYPE_BOOLEAN: + if ((node->type & CONST_DEFAULT) && (node->value == NULL)) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + if (p->type & CONST_TRUE) + { + PUT_STR_VALUE (value, value_size, "TRUE"); + } + else + { + PUT_STR_VALUE (value, value_size, "FALSE"); + } + } + else if (node->value[0] == 'T') + { + PUT_STR_VALUE (value, value_size, "TRUE"); + } + else + { + PUT_STR_VALUE (value, value_size, "FALSE"); + } + break; + case ASN1_ETYPE_INTEGER: + case ASN1_ETYPE_ENUMERATED: + if ((node->type & CONST_DEFAULT) && (node->value == NULL)) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + if ((c_isdigit (p->value[0])) || (p->value[0] == '-') + || (p->value[0] == '+')) + { + result = _asn1_convert_integer + (p->value, value, value_size, len); + if (result != ASN1_SUCCESS) + return result; + } + else + { /* is an identifier like v1 */ + p2 = node->down; + while (p2) + { + if (type_field (p2->type) == ASN1_ETYPE_CONSTANT) + { + if (!_asn1_strcmp (p2->name, p->value)) + { + result = _asn1_convert_integer + (p2->value, value, value_size, + len); + if (result != ASN1_SUCCESS) + return result; + break; + } + } + p2 = p2->right; + } + } + } + else + { + len2 = -1; + result = asn1_get_octet_der + (node->value, node->value_len, &len2, value, value_size, + len); + if (result != ASN1_SUCCESS) + return result; + } + break; + case ASN1_ETYPE_OBJECT_ID: + if (node->type & CONST_ASSIGN) + { + *len = 0; + if (value) + value[0] = 0; + p = node->down; + while (p) + { + if (type_field (p->type) == ASN1_ETYPE_CONSTANT) + { + ADD_STR_VALUE (value, value_size, p->value); + if (p->right) + { + ADD_STR_VALUE (value, value_size, "."); + } + } + p = p->right; + } + (*len)++; + } + else if ((node->type & CONST_DEFAULT) && (node->value == NULL)) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + PUT_STR_VALUE (value, value_size, p->value); + } + else + { + PUT_STR_VALUE (value, value_size, node->value); + } + break; + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: + PUT_AS_STR_VALUE (value, value_size, node->value, node->value_len); + break; + case ASN1_ETYPE_OCTET_STRING: + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + len2 = -1; + result = asn1_get_octet_der + (node->value, node->value_len, &len2, value, value_size, + len); + if (result != ASN1_SUCCESS) + return result; + break; + case ASN1_ETYPE_BIT_STRING: + len2 = -1; + result = asn1_get_bit_der + (node->value, node->value_len, &len2, value, value_size, + len); + if (result != ASN1_SUCCESS) + return result; + break; + case ASN1_ETYPE_CHOICE: + PUT_STR_VALUE (value, value_size, node->down->name); + break; + case ASN1_ETYPE_ANY: + len3 = -1; + len2 = asn1_get_length_der (node->value, node->value_len, &len3); + if (len2 < 0) + return ASN1_DER_ERROR; + PUT_VALUE (value, value_size, node->value + len3, len2); + break; + default: + return ASN1_ELEMENT_NOT_FOUND; + break; + } + return ASN1_SUCCESS; +} + + +/** + * asn1_read_tag: + * @root: pointer to a structure + * @name: the name of the element inside a structure. + * @tagValue: variable that will contain the TAG value. + * @classValue: variable that will specify the TAG type. + * + * Returns the TAG and the CLASS of one element inside a structure. + * CLASS can have one of these constants: %ASN1_CLASS_APPLICATION, + * %ASN1_CLASS_UNIVERSAL, %ASN1_CLASS_PRIVATE or + * %ASN1_CLASS_CONTEXT_SPECIFIC. + * + * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if + * @name is not a valid element. + **/ +int +asn1_read_tag (asn1_node_const root, const char *name, int *tagValue, + int *classValue) +{ + asn1_node node, p, pTag; + + node = asn1_find_node (root, name); + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node->down; + + /* pTag will points to the IMPLICIT TAG */ + pTag = NULL; + if (node->type & CONST_TAG) + { + while (p) + { + if (type_field (p->type) == ASN1_ETYPE_TAG) + { + if ((p->type & CONST_IMPLICIT) && (pTag == NULL)) + pTag = p; + else if (p->type & CONST_EXPLICIT) + pTag = NULL; + } + p = p->right; + } + } + + if (pTag) + { + *tagValue = _asn1_strtoul (pTag->value, NULL, 10); + + if (pTag->type & CONST_APPLICATION) + *classValue = ASN1_CLASS_APPLICATION; + else if (pTag->type & CONST_UNIVERSAL) + *classValue = ASN1_CLASS_UNIVERSAL; + else if (pTag->type & CONST_PRIVATE) + *classValue = ASN1_CLASS_PRIVATE; + else + *classValue = ASN1_CLASS_CONTEXT_SPECIFIC; + } + else + { + unsigned type = type_field (node->type); + *classValue = ASN1_CLASS_UNIVERSAL; + + switch (type) + { + CASE_HANDLED_ETYPES: + *tagValue = _asn1_tags[type].tag; + break; + case ASN1_ETYPE_TAG: + case ASN1_ETYPE_CHOICE: + case ASN1_ETYPE_ANY: + *tagValue = -1; + break; + default: + break; + } + } + + return ASN1_SUCCESS; +} + +/** + * asn1_read_node_value: + * @node: pointer to a node. + * @data: a point to a asn1_data_node_st + * + * Returns the value a data node inside a asn1_node structure. + * The data returned should be handled as constant values. + * + * Returns: %ASN1_SUCCESS if the node exists. + **/ +int +asn1_read_node_value (asn1_node_const node, asn1_data_node_st * data) +{ + data->name = node->name; + data->value = node->value; + data->value_len = node->value_len; + data->type = type_field (node->type); + + return ASN1_SUCCESS; +} diff --git a/lib/minitasn1/element.h b/lib/minitasn1/element.h new file mode 100644 index 0000000..440a33f --- /dev/null +++ b/lib/minitasn1/element.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2000-2014 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifndef _ELEMENT_H +#define _ELEMENT_H + + +struct node_tail_cache_st +{ + asn1_node head; /* the first element of the sequence */ + asn1_node tail; +}; + +int _asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcached); + +int _asn1_convert_integer (const unsigned char *value, + unsigned char *value_out, + int value_out_size, int *len); + +void _asn1_hierarchical_name (asn1_node_const node, char *name, int name_size); + +#endif diff --git a/lib/minitasn1/errors.c b/lib/minitasn1/errors.c new file mode 100644 index 0000000..cee74da --- /dev/null +++ b/lib/minitasn1/errors.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2002-2014 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#include +#ifdef STDC_HEADERS +#include +#endif + +#define LIBTASN1_ERROR_ENTRY(name) { #name, name } + +struct libtasn1_error_entry +{ + const char *name; + int number; +}; +typedef struct libtasn1_error_entry libtasn1_error_entry; + +static const libtasn1_error_entry error_algorithms[] = { + LIBTASN1_ERROR_ENTRY (ASN1_SUCCESS), + LIBTASN1_ERROR_ENTRY (ASN1_FILE_NOT_FOUND), + LIBTASN1_ERROR_ENTRY (ASN1_ELEMENT_NOT_FOUND), + LIBTASN1_ERROR_ENTRY (ASN1_IDENTIFIER_NOT_FOUND), + LIBTASN1_ERROR_ENTRY (ASN1_DER_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_VALUE_NOT_FOUND), + LIBTASN1_ERROR_ENTRY (ASN1_GENERIC_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_VALUE_NOT_VALID), + LIBTASN1_ERROR_ENTRY (ASN1_TAG_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_TAG_IMPLICIT), + LIBTASN1_ERROR_ENTRY (ASN1_ERROR_TYPE_ANY), + LIBTASN1_ERROR_ENTRY (ASN1_SYNTAX_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_MEM_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_MEM_ALLOC_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_DER_OVERFLOW), + LIBTASN1_ERROR_ENTRY (ASN1_NAME_TOO_LONG), + LIBTASN1_ERROR_ENTRY (ASN1_ARRAY_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_ELEMENT_NOT_EMPTY), + LIBTASN1_ERROR_ENTRY (ASN1_TIME_ENCODING_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_RECURSION), + {0, 0} +}; + +/** + * asn1_perror: + * @error: is an error returned by a libtasn1 function. + * + * Prints a string to stderr with a description of an error. This + * function is like perror(). The only difference is that it accepts + * an error returned by a libtasn1 function. + * + * Since: 1.6 + **/ +void +asn1_perror (int error) +{ + const char *str = asn1_strerror (error); + fprintf (stderr, "LIBTASN1 ERROR: %s\n", str ? str : "(null)"); +} + +/** + * asn1_strerror: + * @error: is an error returned by a libtasn1 function. + * + * Returns a string with a description of an error. This function is + * similar to strerror. The only difference is that it accepts an + * error (number) returned by a libtasn1 function. + * + * Returns: Pointer to static zero-terminated string describing error + * code. + * + * Since: 1.6 + **/ +const char * +asn1_strerror (int error) +{ + const libtasn1_error_entry *p; + + for (p = error_algorithms; p->name != NULL; p++) + if (p->number == error) + return p->name + sizeof ("ASN1_") - 1; + + return NULL; +} diff --git a/lib/minitasn1/gstr.c b/lib/minitasn1/gstr.c new file mode 100644 index 0000000..e91a3a1 --- /dev/null +++ b/lib/minitasn1/gstr.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2002-2014 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#include +#include "gstr.h" + +/* These function are like strcat, strcpy. They only + * do bounds checking (they shouldn't cause buffer overruns), + * and they always produce null terminated strings. + * + * They should be used only with null terminated strings. + */ +void +_asn1_str_cat (char *dest, size_t dest_tot_size, const char *src) +{ + size_t str_size = strlen (src); + size_t dest_size = strlen (dest); + + if (dest_tot_size - dest_size > str_size) + { + strcat (dest, src); + } + else + { + if (dest_tot_size - dest_size > 0) + { + strncat (dest, src, (dest_tot_size - dest_size) - 1); + dest[dest_tot_size - 1] = 0; + } + } +} + +/* Returns the bytes copied (not including the null terminator) */ +unsigned int +_asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src) +{ + size_t str_size = strlen (src); + + if (dest_tot_size > str_size) + { + strcpy (dest, src); + return str_size; + } + else + { + if (dest_tot_size > 0) + { + str_size = dest_tot_size - 1; + memcpy (dest, src, str_size); + dest[str_size] = 0; + return str_size; + } + else + return 0; + } +} diff --git a/lib/minitasn1/gstr.h b/lib/minitasn1/gstr.h new file mode 100644 index 0000000..4822984 --- /dev/null +++ b/lib/minitasn1/gstr.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2002-2014 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifndef GSTR_H +# define GSTR_H + +unsigned int _asn1_str_cpy (char *dest, size_t dest_tot_size, + const char *src); +void _asn1_str_cat (char *dest, size_t dest_tot_size, const char *src); + +#define Estrcpy(x,y) _asn1_str_cpy(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y) +#define Estrcat(x,y) _asn1_str_cat(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y) + +inline static +void safe_memset(void *data, int c, size_t size) +{ + volatile unsigned volatile_zero = 0; + volatile char *vdata = (volatile char*)data; + + /* This is based on a nice trick for safe memset, + * sent by David Jacobson in the openssl-dev mailing list. + */ + + if (size > 0) do { + memset(data, c, size); + } while(vdata[volatile_zero] != c); +} + +#endif /* GSTR_H */ diff --git a/lib/minitasn1/int.h b/lib/minitasn1/int.h new file mode 100644 index 0000000..ea16257 --- /dev/null +++ b/lib/minitasn1/int.h @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2002-2014 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifndef INT_H +#define INT_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#include + +#define ASN1_SMALL_VALUE_SIZE 16 + +/* This structure is also in libtasn1.h, but then contains less + fields. You cannot make any modifications to these first fields + without breaking ABI. */ +struct asn1_node_st +{ + /* public fields: */ + char name[ASN1_MAX_NAME_SIZE + 1]; /* Node name */ + unsigned int name_hash; + unsigned int type; /* Node type */ + unsigned char *value; /* Node value */ + int value_len; + asn1_node down; /* Pointer to the son node */ + asn1_node right; /* Pointer to the brother node */ + asn1_node left; /* Pointer to the next list element */ + /* private fields: */ + unsigned char small_value[ASN1_SMALL_VALUE_SIZE]; /* For small values */ + + /* values used during decoding/coding */ + int tmp_ival; + unsigned start; /* the start of the DER sequence - if decoded */ + unsigned end; /* the end of the DER sequence - if decoded */ +}; + +typedef struct tag_and_class_st +{ + unsigned tag; + unsigned class; + const char *desc; +} tag_and_class_st; + +/* the types that are handled in _asn1_tags */ +#define CASE_HANDLED_ETYPES \ + case ASN1_ETYPE_NULL: \ + case ASN1_ETYPE_BOOLEAN: \ + case ASN1_ETYPE_INTEGER: \ + case ASN1_ETYPE_ENUMERATED: \ + case ASN1_ETYPE_OBJECT_ID: \ + case ASN1_ETYPE_OCTET_STRING: \ + case ASN1_ETYPE_GENERALSTRING: \ + case ASN1_ETYPE_NUMERIC_STRING: \ + case ASN1_ETYPE_IA5_STRING: \ + case ASN1_ETYPE_TELETEX_STRING: \ + case ASN1_ETYPE_PRINTABLE_STRING: \ + case ASN1_ETYPE_UNIVERSAL_STRING: \ + case ASN1_ETYPE_BMP_STRING: \ + case ASN1_ETYPE_UTF8_STRING: \ + case ASN1_ETYPE_VISIBLE_STRING: \ + case ASN1_ETYPE_BIT_STRING: \ + case ASN1_ETYPE_SEQUENCE: \ + case ASN1_ETYPE_SEQUENCE_OF: \ + case ASN1_ETYPE_SET: \ + case ASN1_ETYPE_UTC_TIME: \ + case ASN1_ETYPE_GENERALIZED_TIME: \ + case ASN1_ETYPE_SET_OF + +#define ETYPE_TAG(etype) (_asn1_tags[etype].tag) +#define ETYPE_CLASS(etype) (_asn1_tags[etype].class) +#define ETYPE_OK(etype) (((etype) != ASN1_ETYPE_INVALID && \ + (etype) <= _asn1_tags_size && \ + _asn1_tags[(etype)].desc != NULL)?1:0) + +#define ETYPE_IS_STRING(etype) ((etype == ASN1_ETYPE_GENERALSTRING || \ + etype == ASN1_ETYPE_NUMERIC_STRING || etype == ASN1_ETYPE_IA5_STRING || \ + etype == ASN1_ETYPE_TELETEX_STRING || etype == ASN1_ETYPE_PRINTABLE_STRING || \ + etype == ASN1_ETYPE_UNIVERSAL_STRING || etype == ASN1_ETYPE_BMP_STRING || \ + etype == ASN1_ETYPE_UTF8_STRING || etype == ASN1_ETYPE_VISIBLE_STRING || \ + etype == ASN1_ETYPE_OCTET_STRING)?1:0) + +extern unsigned int _asn1_tags_size; +extern const tag_and_class_st _asn1_tags[]; + +#define _asn1_strlen(s) strlen((const char *) s) +#define _asn1_strtol(n,e,b) strtol((const char *) n, e, b) +#define _asn1_strtoul(n,e,b) strtoul((const char *) n, e, b) +#define _asn1_strcmp(a,b) strcmp((const char *)a, (const char *)b) +#define _asn1_strcpy(a,b) strcpy((char *)a, (const char *)b) +#define _asn1_strcat(a,b) strcat((char *)a, (const char *)b) + +#if SIZEOF_UNSIGNED_LONG_INT == 8 +# define _asn1_strtou64(n,e,b) strtoul((const char *) n, e, b) +#else +# define _asn1_strtou64(n,e,b) strtoull((const char *) n, e, b) +#endif + +#define MAX_LOG_SIZE 1024 /* maximum number of characters of a log message */ + +/* Define used for visiting trees. */ +#define UP 1 +#define RIGHT 2 +#define DOWN 3 + +/***********************************************************************/ +/* List of constants to better specify the type of typedef asn1_node_st. */ +/***********************************************************************/ +/* Used with TYPE_TAG */ +#define CONST_UNIVERSAL (1U<<8) +#define CONST_PRIVATE (1U<<9) +#define CONST_APPLICATION (1U<<10) +#define CONST_EXPLICIT (1U<<11) +#define CONST_IMPLICIT (1U<<12) + +#define CONST_TAG (1U<<13) /* Used in ASN.1 assignement */ +#define CONST_OPTION (1U<<14) +#define CONST_DEFAULT (1U<<15) +#define CONST_TRUE (1U<<16) +#define CONST_FALSE (1U<<17) + +#define CONST_LIST (1U<<18) /* Used with TYPE_INTEGER and TYPE_BIT_STRING */ +#define CONST_MIN_MAX (1U<<19) + +#define CONST_1_PARAM (1U<<20) + +#define CONST_SIZE (1U<<21) + +#define CONST_DEFINED_BY (1U<<22) + +/* Those two are deprecated and used for backwards compatibility */ +#define CONST_GENERALIZED (1U<<23) +#define CONST_UTC (1U<<24) + +/* #define CONST_IMPORTS (1U<<25) */ + +#define CONST_NOT_USED (1U<<26) +#define CONST_SET (1U<<27) +#define CONST_ASSIGN (1U<<28) + +#define CONST_DOWN (1U<<29) +#define CONST_RIGHT (1U<<30) + + +#define ASN1_ETYPE_TIME 17 +/****************************************/ +/* Returns the first 8 bits. */ +/* Used with the field type of asn1_node_st */ +/****************************************/ +inline static unsigned int +type_field (unsigned int ntype) +{ + return (ntype & 0xff); +} + +/* To convert old types from a static structure */ +inline static unsigned int +convert_old_type (unsigned int ntype) +{ + unsigned int type = ntype & 0xff; + if (type == ASN1_ETYPE_TIME) + { + if (ntype & CONST_UTC) + type = ASN1_ETYPE_UTC_TIME; + else + type = ASN1_ETYPE_GENERALIZED_TIME; + + ntype &= ~(CONST_UTC | CONST_GENERALIZED); + ntype &= 0xffffff00; + ntype |= type; + + return ntype; + } + else + return ntype; +} + +static inline +void *_asn1_realloc(void *ptr, size_t size) +{ + void *ret; + + if (size == 0) + return ptr; + + ret = realloc(ptr, size); + if (ret == NULL) + { + free(ptr); + } + return ret; +} + +#endif /* INT_H */ diff --git a/lib/minitasn1/libtasn1.h b/lib/minitasn1/libtasn1.h new file mode 100644 index 0000000..6fd7a30 --- /dev/null +++ b/lib/minitasn1/libtasn1.h @@ -0,0 +1,588 @@ +/* + * Copyright (C) 2002-2014 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * LIBTASN1 is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * LIBTASN1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with LIBTASN1; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +/** + * libtasn1:Short_Description: + * + * GNU ASN.1 library + */ +/** + * libtasn1:Long_Description: + * + * The Libtasn1 library provides Abstract Syntax Notation One (ASN.1, as + * specified by the X.680 ITU-T recommendation) parsing and structures + * management, and Distinguished Encoding Rules (DER, as per X.690) + * encoding and decoding functions. + */ + + +#ifndef LIBTASN1_H +#define LIBTASN1_H + +#ifndef ASN1_API +#if defined ASN1_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY +#define ASN1_API __attribute__((__visibility__("default"))) +#elif defined ASN1_BUILDING && defined _MSC_VER && ! defined ASN1_STATIC +#define ASN1_API __declspec(dllexport) +#elif defined _MSC_VER && ! defined ASN1_STATIC +#define ASN1_API __declspec(dllimport) +#else +#define ASN1_API +#endif +#endif + +#ifdef __GNUC__ +# define __LIBTASN1_CONST__ __attribute__((const)) +# define __LIBTASN1_PURE__ __attribute__((pure)) +#else +# define __LIBTASN1_CONST__ +# define __LIBTASN1_PURE__ +#endif + +#include +#include +#include /* for FILE* */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * ASN1_VERSION: + * + * Version of the library as a string. + */ +#define ASN1_VERSION "4.16.0" + +/** + * ASN1_VERSION_MAJOR: + * + * Major version number of the library. + */ +#define ASN1_VERSION_MAJOR 4 + +/** + * ASN1_VERSION_MINOR: + * + * Minor version number of the library. + */ +#define ASN1_VERSION_MINOR 16 + +/** + * ASN1_VERSION_PATCH: + * + * Patch version number of the library. + */ +#define ASN1_VERSION_PATCH 0 + +/** + * ASN1_VERSION_NUMBER: + * + * Version number of the library as a number. + */ +#define ASN1_VERSION_NUMBER 0x041000 + + +#if defined __GNUC__ && !defined ASN1_INTERNAL_BUILD +# define _ASN1_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +# if _ASN1_GCC_VERSION >= 30100 +# define _ASN1_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__)) +# endif +#endif + +#ifndef _ASN1_GCC_ATTR_DEPRECATED +#define _ASN1_GCC_ATTR_DEPRECATED +#endif + +/*****************************************/ +/* Errors returned by libtasn1 functions */ +/*****************************************/ +#define ASN1_SUCCESS 0 +#define ASN1_FILE_NOT_FOUND 1 +#define ASN1_ELEMENT_NOT_FOUND 2 +#define ASN1_IDENTIFIER_NOT_FOUND 3 +#define ASN1_DER_ERROR 4 +#define ASN1_VALUE_NOT_FOUND 5 +#define ASN1_GENERIC_ERROR 6 +#define ASN1_VALUE_NOT_VALID 7 +#define ASN1_TAG_ERROR 8 +#define ASN1_TAG_IMPLICIT 9 +#define ASN1_ERROR_TYPE_ANY 10 +#define ASN1_SYNTAX_ERROR 11 +#define ASN1_MEM_ERROR 12 +#define ASN1_MEM_ALLOC_ERROR 13 +#define ASN1_DER_OVERFLOW 14 +#define ASN1_NAME_TOO_LONG 15 +#define ASN1_ARRAY_ERROR 16 +#define ASN1_ELEMENT_NOT_EMPTY 17 +#define ASN1_TIME_ENCODING_ERROR 18 +#define ASN1_RECURSION 19 + +/*************************************/ +/* Constants used in asn1_visit_tree */ +/*************************************/ +#define ASN1_PRINT_NAME 1 +#define ASN1_PRINT_NAME_TYPE 2 +#define ASN1_PRINT_NAME_TYPE_VALUE 3 +#define ASN1_PRINT_ALL 4 + +/*****************************************/ +/* Constants returned by asn1_read_tag */ +/*****************************************/ +#define ASN1_CLASS_UNIVERSAL 0x00 /* old: 1 */ +#define ASN1_CLASS_APPLICATION 0x40 /* old: 2 */ +#define ASN1_CLASS_CONTEXT_SPECIFIC 0x80 /* old: 3 */ +#define ASN1_CLASS_PRIVATE 0xC0 /* old: 4 */ +#define ASN1_CLASS_STRUCTURED 0x20 + +/*****************************************/ +/* Constants returned by asn1_read_tag */ +/*****************************************/ +#define ASN1_TAG_BOOLEAN 0x01 +#define ASN1_TAG_INTEGER 0x02 +#define ASN1_TAG_SEQUENCE 0x10 +#define ASN1_TAG_SET 0x11 +#define ASN1_TAG_OCTET_STRING 0x04 +#define ASN1_TAG_BIT_STRING 0x03 +#define ASN1_TAG_UTCTime 0x17 +#define ASN1_TAG_GENERALIZEDTime 0x18 +#define ASN1_TAG_OBJECT_ID 0x06 +#define ASN1_TAG_ENUMERATED 0x0A +#define ASN1_TAG_NULL 0x05 +#define ASN1_TAG_GENERALSTRING 0x1B +#define ASN1_TAG_NUMERIC_STRING 0x12 +#define ASN1_TAG_IA5_STRING 0x16 +#define ASN1_TAG_TELETEX_STRING 0x14 +#define ASN1_TAG_PRINTABLE_STRING 0x13 +#define ASN1_TAG_UNIVERSAL_STRING 0x1C +#define ASN1_TAG_BMP_STRING 0x1E +#define ASN1_TAG_UTF8_STRING 0x0C +#define ASN1_TAG_VISIBLE_STRING 0x1A + +/** + * asn1_node: + * + * Structure definition used for the node of the tree + * that represents an ASN.1 DEFINITION. + */ +typedef struct asn1_node_st asn1_node_st; + +typedef asn1_node_st *asn1_node; +typedef const asn1_node_st *asn1_node_const; + +/** + * ASN1_MAX_NAME_SIZE: + * + * Maximum number of characters of a name + * inside a file with ASN1 definitions. + */ +#define ASN1_MAX_NAME_SIZE 64 + + +/** + * asn1_static_node: + * @name: Node name + * @type: Node typ + * @value: Node value + * + * For the on-disk format of ASN.1 trees, created by asn1_parser2array(). + */ +struct asn1_static_node_st +{ + const char *name; /* Node name */ + unsigned int type; /* Node type */ + const void *value; /* Node value */ +}; +typedef struct asn1_static_node_st asn1_static_node; + +/* List of constants for field type of node_asn */ +#define ASN1_ETYPE_INVALID 0 +#define ASN1_ETYPE_CONSTANT 1 +#define ASN1_ETYPE_IDENTIFIER 2 +#define ASN1_ETYPE_INTEGER 3 +#define ASN1_ETYPE_BOOLEAN 4 +#define ASN1_ETYPE_SEQUENCE 5 +#define ASN1_ETYPE_BIT_STRING 6 +#define ASN1_ETYPE_OCTET_STRING 7 +#define ASN1_ETYPE_TAG 8 +#define ASN1_ETYPE_DEFAULT 9 +#define ASN1_ETYPE_SIZE 10 +#define ASN1_ETYPE_SEQUENCE_OF 11 +#define ASN1_ETYPE_OBJECT_ID 12 +#define ASN1_ETYPE_ANY 13 +#define ASN1_ETYPE_SET 14 +#define ASN1_ETYPE_SET_OF 15 +#define ASN1_ETYPE_DEFINITIONS 16 +#define ASN1_ETYPE_CHOICE 18 +#define ASN1_ETYPE_IMPORTS 19 +#define ASN1_ETYPE_NULL 20 +#define ASN1_ETYPE_ENUMERATED 21 +#define ASN1_ETYPE_GENERALSTRING 27 +#define ASN1_ETYPE_NUMERIC_STRING 28 +#define ASN1_ETYPE_IA5_STRING 29 +#define ASN1_ETYPE_TELETEX_STRING 30 +#define ASN1_ETYPE_PRINTABLE_STRING 31 +#define ASN1_ETYPE_UNIVERSAL_STRING 32 +#define ASN1_ETYPE_BMP_STRING 33 +#define ASN1_ETYPE_UTF8_STRING 34 +#define ASN1_ETYPE_VISIBLE_STRING 35 +#define ASN1_ETYPE_UTC_TIME 36 +#define ASN1_ETYPE_GENERALIZED_TIME 37 + +/** + * ASN1_DELETE_FLAG_ZEROIZE: + * + * Used by: asn1_delete_structure2() + * + * Zeroize values prior to deinitialization. + */ +#define ASN1_DELETE_FLAG_ZEROIZE 1 + +/** + * ASN1_DECODE_FLAG_ALLOW_PADDING: + * + * Used by: asn1_der_decoding2() + * + * This flag would allow arbitrary data past the DER data. + */ +#define ASN1_DECODE_FLAG_ALLOW_PADDING 1 +/** + * ASN1_DECODE_FLAG_STRICT_DER: + * + * Used by: asn1_der_decoding2() + * + * This flag would ensure that no BER decoding takes place. + */ +#define ASN1_DECODE_FLAG_STRICT_DER (1<<1) +/** + * ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME: + * + * Used by: asn1_der_decoding2() + * + * This flag will tolerate Time encoding errors when in strict DER. + */ +#define ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME (1<<2) + + +/** + * asn1_data_node_st: + * @name: Node name + * @value: Node value + * @value_len: Node value size + * @type: Node value type (ASN1_ETYPE_*) + * + * Data node inside a #asn1_node structure. + */ +struct asn1_data_node_st +{ + const char *name; /* Node name */ + const void *value; /* Node value */ + unsigned int value_len; /* Node value size */ + unsigned int type; /* Node value type (ASN1_ETYPE_*) */ +}; +typedef struct asn1_data_node_st asn1_data_node_st; + +/***********************************/ +/* Fixed constants */ +/***********************************/ + +/** + * ASN1_MAX_ERROR_DESCRIPTION_SIZE: + * + * Maximum number of characters + * of a description message + * (null character included). + */ +#define ASN1_MAX_ERROR_DESCRIPTION_SIZE 128 + +/***********************************/ +/* Functions definitions */ +/***********************************/ + +extern ASN1_API int + asn1_parser2tree (const char *file, + asn1_node * definitions, char *error_desc); + +extern ASN1_API int + asn1_parser2array (const char *inputFileName, + const char *outputFileName, + const char *vectorName, char *error_desc); + +extern ASN1_API int + asn1_array2tree (const asn1_static_node * array, + asn1_node * definitions, char *errorDescription); + +extern ASN1_API void + asn1_print_structure (FILE * out, asn1_node_const structure, + const char *name, int mode); + +extern ASN1_API int + asn1_create_element (asn1_node_const definitions, + const char *source_name, asn1_node * element); + +extern ASN1_API int asn1_delete_structure (asn1_node * structure); + +extern ASN1_API int asn1_delete_structure2 (asn1_node * structure, unsigned int flags); + +extern ASN1_API int + asn1_delete_element (asn1_node structure, const char *element_name); + +extern ASN1_API int + asn1_write_value (asn1_node node_root, const char *name, + const void *ivalue, int len); + +extern ASN1_API int + asn1_read_value (asn1_node_const root, const char *name, + void *ivalue, int *len); + +extern ASN1_API int + asn1_read_value_type (asn1_node_const root, const char *name, + void *ivalue, int *len, unsigned int *etype); + +extern ASN1_API int + asn1_read_node_value (asn1_node_const node, asn1_data_node_st * data); + +extern ASN1_API int + asn1_number_of_elements (asn1_node_const element, const char *name, int *num); + +extern ASN1_API int + asn1_der_coding (asn1_node_const element, const char *name, + void *ider, int *len, char *ErrorDescription); + +extern ASN1_API int + asn1_der_decoding2 (asn1_node *element, const void *ider, + int *max_ider_len, unsigned int flags, + char *errorDescription); + +extern ASN1_API int + asn1_der_decoding (asn1_node * element, const void *ider, + int ider_len, char *errorDescription); + +/* Do not use. Use asn1_der_decoding() instead. */ +extern ASN1_API int + asn1_der_decoding_element (asn1_node * structure, + const char *elementName, + const void *ider, int len, + char *errorDescription) _ASN1_GCC_ATTR_DEPRECATED; + +extern ASN1_API int + asn1_der_decoding_startEnd (asn1_node element, + const void *ider, int ider_len, + const char *name_element, + int *start, int *end); + +extern ASN1_API int + asn1_expand_any_defined_by (asn1_node_const definitions, asn1_node * element); + +extern ASN1_API int + asn1_expand_octet_string (asn1_node_const definitions, + asn1_node * element, + const char *octetName, const char *objectName); + +extern ASN1_API int + asn1_read_tag (asn1_node_const root, const char *name, + int *tagValue, int *classValue); + +extern ASN1_API const char *asn1_find_structure_from_oid (asn1_node_const + definitions, + const char + *oidValue); + +__LIBTASN1_PURE__ +extern ASN1_API const char *asn1_check_version (const char *req_version); + +__LIBTASN1_PURE__ +extern ASN1_API const char *asn1_strerror (int error); + +extern ASN1_API void asn1_perror (int error); + +#define ASN1_MAX_TAG_SIZE 4 +#define ASN1_MAX_LENGTH_SIZE 9 +#define ASN1_MAX_TL_SIZE (ASN1_MAX_TAG_SIZE+ASN1_MAX_LENGTH_SIZE) +extern ASN1_API long + asn1_get_length_der (const unsigned char *der, int der_len, int *len); + +extern ASN1_API long + asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len); + +extern ASN1_API void + asn1_length_der (unsigned long int len, unsigned char *der, int *der_len); + +/* Other utility functions. */ + +extern ASN1_API + int asn1_decode_simple_der (unsigned int etype, const unsigned char *der, + unsigned int _der_len, + const unsigned char **str, + unsigned int *str_len); + +extern ASN1_API + int asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, + unsigned int _der_len, + unsigned char **str, + unsigned int *str_len, + unsigned int *ber_len); + +extern ASN1_API int + asn1_encode_simple_der (unsigned int etype, const unsigned char *str, + unsigned int str_len, unsigned char *tl, + unsigned int *tl_len); + +extern ASN1_API asn1_node + asn1_find_node (asn1_node_const pointer, const char *name); + +extern ASN1_API int + asn1_copy_node (asn1_node dst, const char *dst_name, + asn1_node_const src, const char *src_name); +extern ASN1_API asn1_node + asn1_dup_node (asn1_node_const src, const char *src_name); + +/* Internal and low-level DER utility functions. */ + +extern ASN1_API int + asn1_get_tag_der (const unsigned char *der, int der_len, + unsigned char *cls, int *len, unsigned long *tag); + +extern ASN1_API void + asn1_octet_der (const unsigned char *str, int str_len, + unsigned char *der, int *der_len); + +extern ASN1_API int + asn1_get_octet_der (const unsigned char *der, int der_len, + int *ret_len, unsigned char *str, + int str_size, int *str_len); + +extern ASN1_API void asn1_bit_der (const unsigned char *str, int bit_len, + unsigned char *der, int *der_len); + +extern ASN1_API int + asn1_get_bit_der (const unsigned char *der, int der_len, + int *ret_len, unsigned char *str, + int str_size, int *bit_len); + +extern ASN1_API int + asn1_get_object_id_der (const unsigned char *der, + int der_len, int *ret_len, + char *str, int str_size); + +extern ASN1_API int + asn1_object_id_der (const char *str, unsigned char *der, int *der_len, + unsigned flags); + +/* Compatibility types */ + +/** + * asn1_retCode: + * + * Type formerly returned by libtasn1 functions. + * + * Deprecated: 3.0: Use int instead. + */ +typedef int asn1_retCode; + +/** + * node_asn_struct: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_node instead. + */ +#define node_asn_struct asn1_node_st + +/** + * node_asn: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_node instead. + */ +#define node_asn asn1_node_st + +/** + * ASN1_TYPE: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_node instead. + */ +#define ASN1_TYPE asn1_node + +/** + * ASN1_TYPE_EMPTY: + * + * Compat #define. + * + * Deprecated: 3.0: Use NULL instead. + */ +#define ASN1_TYPE_EMPTY NULL + +/** + * static_struct_asn: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_static_node instead. + */ +#define static_struct_asn asn1_static_node_st + +/** + * ASN1_ARRAY_TYPE: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_static_node instead. + */ +#define ASN1_ARRAY_TYPE asn1_static_node + +/** + * asn1_static_node_t: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_static_node instead. + */ +#define asn1_static_node_t asn1_static_node + +/** + * node_data_struct: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_data_node_st instead. + */ +#define node_data_struct asn1_data_node_st + +/** + * ASN1_DATA_NODE: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_data_node_st instead. + */ +#define ASN1_DATA_NODE asn1_data_node_st + +#ifdef __cplusplus +} +#endif + +#endif /* LIBTASN1_H */ diff --git a/lib/minitasn1/parser_aux.c b/lib/minitasn1/parser_aux.c new file mode 100644 index 0000000..d5dbbf8 --- /dev/null +++ b/lib/minitasn1/parser_aux.c @@ -0,0 +1,1173 @@ +/* + * Copyright (C) 2000-2016 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#include // WORD_BIT + +#include "int.h" +#include "parser_aux.h" +#include "gstr.h" +#include "structure.h" +#include "element.h" +#include "c-ctype.h" + +char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1]; /* identifier name not found */ + +/* Return a hash of the N bytes of X using the method described by + Bruno Haible in https://www.haible.de/bruno/hashfunc.html. + Note that while many hash functions reduce their result via modulo + to a 0..table_size-1 range, this function does not do that. + + This implementation has been changed from size_t -> unsigned int. */ + +#ifdef __clang__ +__attribute__((no_sanitize("integer"))) +#endif +_GL_ATTRIBUTE_PURE +static unsigned int +_asn1_hash_name (const char *x) +{ + const unsigned char *s = (unsigned char *) x; + unsigned h = 0; + + while (*s) + h = (*s++) + ((h << 9) | (h >> (WORD_BIT - 9))); + + return h; +} + +/******************************************************/ +/* Function : _asn1_add_static_node */ +/* Description: creates a new NODE_ASN element and */ +/* puts it in the list pointed by e_list. */ +/* Parameters: */ +/* e_list: of type list_type; must be NULL initially */ +/* type: type of the new element (see ASN1_ETYPE_ */ +/* and CONST_ constants). */ +/* Return: pointer to the new element. */ +/******************************************************/ +asn1_node +_asn1_add_static_node (list_type **e_list, unsigned int type) +{ + list_type *p; + asn1_node punt; + + punt = calloc (1, sizeof (struct asn1_node_st)); + if (punt == NULL) + return NULL; + + p = malloc (sizeof (list_type)); + if (p == NULL) + { + free (punt); + return NULL; + } + + p->node = punt; + p->next = *e_list; + *e_list = p; + + punt->type = type; + + return punt; +} + +static +int _asn1_add_static_node2 (list_type **e_list, asn1_node node) +{ + list_type *p; + + p = malloc (sizeof (list_type)); + if (p == NULL) + { + return -1; + } + + p->node = node; + p->next = *e_list; + *e_list = p; + + return 0; +} + +/** + * asn1_find_node: + * @pointer: NODE_ASN element pointer. + * @name: null terminated string with the element's name to find. + * + * Searches for an element called @name starting from @pointer. The + * name is composed by different identifiers separated by dots. When + * *@pointer has a name, the first identifier must be the name of + * *@pointer, otherwise it must be the name of one child of *@pointer. + * + * Returns: the search result, or %NULL if not found. + **/ +asn1_node +asn1_find_node (asn1_node_const pointer, const char *name) +{ + asn1_node_const p; + char *n_end, n[ASN1_MAX_NAME_SIZE + 1]; + const char *n_start; + unsigned int nsize; + unsigned int nhash; + + if (pointer == NULL) + return NULL; + + if (name == NULL) + return NULL; + + p = pointer; + n_start = name; + + if (name[0] == '?' && name[1] == 'C' && p->name[0] == '?') + { /* ?CURRENT */ + n_start = strchr(n_start, '.'); + if (n_start) + n_start++; + } + else if (p->name[0] != 0) + { /* has *pointer got a name ? */ + n_end = strchr (n_start, '.'); /* search the first dot */ + if (n_end) + { + nsize = n_end - n_start; + if (nsize >= sizeof(n)) + return NULL; + + memcpy (n, n_start, nsize); + n[nsize] = 0; + n_start = n_end; + n_start++; + + nhash = _asn1_hash_name (n); + } + else + { + _asn1_str_cpy (n, sizeof (n), n_start); + nhash = _asn1_hash_name (n); + + n_start = NULL; + } + + while (p) + { + if (nhash == p->name_hash && (!strcmp (p->name, n))) + break; + else + p = p->right; + } /* while */ + + if (p == NULL) + return NULL; + } + else + { /* *pointer doesn't have a name */ + if (n_start[0] == 0) + return (asn1_node) p; + } + + while (n_start) + { /* Has the end of NAME been reached? */ + n_end = strchr (n_start, '.'); /* search the next dot */ + if (n_end) + { + nsize = n_end - n_start; + if (nsize >= sizeof(n)) + return NULL; + + memcpy (n, n_start, nsize); + n[nsize] = 0; + n_start = n_end; + n_start++; + + nhash = _asn1_hash_name (n); + } + else + { + _asn1_str_cpy (n, sizeof (n), n_start); + nhash = _asn1_hash_name (n); + n_start = NULL; + } + + if (p->down == NULL) + return NULL; + + p = p->down; + if (p == NULL) + return NULL; + + /* The identifier "?LAST" indicates the last element + in the right chain. */ + if (n[0] == '?' && n[1] == 'L') /* ?LAST */ + { + while (p->right) + p = p->right; + } + else + { /* no "?LAST" */ + while (p) + { + if (p->name_hash == nhash && !strcmp (p->name, n)) + break; + else + p = p->right; + } + } + if (p == NULL) + return NULL; + } /* while */ + + return (asn1_node) p; +} + + +/******************************************************************/ +/* Function : _asn1_set_value */ +/* Description: sets the field VALUE in a NODE_ASN element. The */ +/* previous value (if exist) will be lost */ +/* Parameters: */ +/* node: element pointer. */ +/* value: pointer to the value that you want to set. */ +/* len: character number of value. */ +/* Return: pointer to the NODE_ASN element. */ +/******************************************************************/ +asn1_node +_asn1_set_value (asn1_node node, const void *value, unsigned int len) +{ + if (node == NULL) + return node; + if (node->value) + { + if (node->value != node->small_value) + free (node->value); + node->value = NULL; + node->value_len = 0; + } + + if (!len) + return node; + + if (len < sizeof (node->small_value)) + { + node->value = node->small_value; + } + else + { + node->value = malloc (len); + if (node->value == NULL) + return NULL; + } + node->value_len = len; + + memcpy (node->value, value, len); + return node; +} + +/******************************************************************/ +/* Function : _asn1_set_value_lv */ +/* Description: sets the field VALUE in a NODE_ASN element. The */ +/* previous value (if exist) will be lost. The value */ +/* given is stored as an length-value format (LV */ +/* Parameters: */ +/* node: element pointer. */ +/* value: pointer to the value that you want to set. */ +/* len: character number of value. */ +/* Return: pointer to the NODE_ASN element. */ +/******************************************************************/ +asn1_node +_asn1_set_value_lv (asn1_node node, const void *value, unsigned int len) +{ + int len2; + void *temp; + + if (node == NULL) + return node; + + asn1_length_der (len, NULL, &len2); + temp = malloc (len + len2); + if (temp == NULL) + return NULL; + + asn1_octet_der (value, len, temp, &len2); + return _asn1_set_value_m (node, temp, len2); +} + +/* the same as _asn1_set_value except that it sets an already malloc'ed + * value. + */ +asn1_node +_asn1_set_value_m (asn1_node node, void *value, unsigned int len) +{ + if (node == NULL) + return node; + + if (node->value) + { + if (node->value != node->small_value) + free (node->value); + node->value = NULL; + node->value_len = 0; + } + + if (!len) + return node; + + node->value = value; + node->value_len = len; + + return node; +} + +/******************************************************************/ +/* Function : _asn1_append_value */ +/* Description: appends to the field VALUE in a NODE_ASN element. */ +/* */ +/* Parameters: */ +/* node: element pointer. */ +/* value: pointer to the value that you want to be appended. */ +/* len: character number of value. */ +/* Return: pointer to the NODE_ASN element. */ +/******************************************************************/ +asn1_node +_asn1_append_value (asn1_node node, const void *value, unsigned int len) +{ + if (node == NULL) + return node; + + if (node->value == NULL) + return _asn1_set_value (node, value, len); + + if (len == 0) + return node; + + if (node->value == node->small_value) + { + /* value is in node */ + int prev_len = node->value_len; + node->value_len += len; + node->value = malloc (node->value_len); + if (node->value == NULL) + { + node->value_len = 0; + return NULL; + } + + if (prev_len > 0) + memcpy (node->value, node->small_value, prev_len); + + memcpy (&node->value[prev_len], value, len); + + return node; + } + else /* if (node->value != NULL && node->value != node->small_value) */ + { + /* value is allocated */ + int prev_len = node->value_len; + node->value_len += len; + + node->value = _asn1_realloc (node->value, node->value_len); + if (node->value == NULL) + { + node->value_len = 0; + return NULL; + } + + memcpy (&node->value[prev_len], value, len); + + return node; + } +} + +/******************************************************************/ +/* Function : _asn1_set_name */ +/* Description: sets the field NAME in a NODE_ASN element. The */ +/* previous value (if exist) will be lost */ +/* Parameters: */ +/* node: element pointer. */ +/* name: a null terminated string with the name that you want */ +/* to set. */ +/* Return: pointer to the NODE_ASN element. */ +/******************************************************************/ +asn1_node +_asn1_set_name (asn1_node node, const char *name) +{ + if (node == NULL) + return node; + + _asn1_str_cpy (node->name, sizeof (node->name), name ? name : ""); + node->name_hash = _asn1_hash_name (node->name); + + return node; +} + +/******************************************************************/ +/* Function : _asn1_cpy_name */ +/* Description: copies the field NAME in a NODE_ASN element. */ +/* Parameters: */ +/* dst: a dest element pointer. */ +/* src: a source element pointer. */ +/* Return: pointer to the NODE_ASN element. */ +/******************************************************************/ +asn1_node +_asn1_cpy_name (asn1_node dst, asn1_node_const src) +{ + if (dst == NULL) + return dst; + + if (src == NULL) + { + dst->name[0] = 0; + dst->name_hash = _asn1_hash_name (dst->name); + return dst; + } + + _asn1_str_cpy (dst->name, sizeof (dst->name), src->name); + dst->name_hash = src->name_hash; + + return dst; +} + +/******************************************************************/ +/* Function : _asn1_set_right */ +/* Description: sets the field RIGHT in a NODE_ASN element. */ +/* Parameters: */ +/* node: element pointer. */ +/* right: pointer to a NODE_ASN element that you want be pointed*/ +/* by NODE. */ +/* Return: pointer to *NODE. */ +/******************************************************************/ +asn1_node +_asn1_set_right (asn1_node node, asn1_node right) +{ + if (node == NULL) + return node; + node->right = right; + if (right) + right->left = node; + return node; +} + + +/******************************************************************/ +/* Function : _asn1_get_last_right */ +/* Description: return the last element along the right chain. */ +/* Parameters: */ +/* node: starting element pointer. */ +/* Return: pointer to the last element along the right chain. */ +/******************************************************************/ +asn1_node +_asn1_get_last_right (asn1_node_const node) +{ + asn1_node_const p; + + if (node == NULL) + return NULL; + p = node; + while (p->right) + p = p->right; + return (asn1_node) p; +} + +/******************************************************************/ +/* Function : _asn1_remove_node */ +/* Description: gets free the memory allocated for an NODE_ASN */ +/* element (not the elements pointed by it). */ +/* Parameters: */ +/* node: NODE_ASN element pointer. */ +/* flags: ASN1_DELETE_FLAG_* */ +/******************************************************************/ +void +_asn1_remove_node (asn1_node node, unsigned int flags) +{ + if (node == NULL) + return; + + if (node->value != NULL) + { + if (flags & ASN1_DELETE_FLAG_ZEROIZE) + { + safe_memset(node->value, 0, node->value_len); + } + + if (node->value != node->small_value) + free (node->value); + } + free (node); +} + +/******************************************************************/ +/* Function : _asn1_find_up */ +/* Description: return the father of the NODE_ASN element. */ +/* Parameters: */ +/* node: NODE_ASN element pointer. */ +/* Return: Null if not found. */ +/******************************************************************/ +asn1_node +_asn1_find_up (asn1_node_const node) +{ + asn1_node_const p; + + if (node == NULL) + return NULL; + + p = node; + + while ((p->left != NULL) && (p->left->right == p)) + p = p->left; + + return p->left; +} + +static +unsigned _asn1_is_up (asn1_node_const up_cand, asn1_node_const down) +{ + asn1_node_const d, u; + + if (up_cand == NULL || down == NULL) + return 0; + + d = down; + + while ((u = _asn1_find_up(d)) != NULL && u != d) + { + if (u == up_cand) + return 1; + d = u; + } + + return 0; +} + +/******************************************************************/ +/* Function : _asn1_delete_node_from_list */ +/* Description: deletes the list element given */ +/******************************************************************/ +void +_asn1_delete_node_from_list (list_type *list, asn1_node node) +{ + list_type *p = list; + + while (p) + { + if (p->node == node) + p->node = NULL; + p = p->next; + } +} + +/******************************************************************/ +/* Function : _asn1_delete_list */ +/* Description: deletes the list elements (not the elements */ +/* pointed by them). */ +/******************************************************************/ +void +_asn1_delete_list (list_type *e_list) +{ + list_type *p; + + while (e_list) + { + p = e_list; + e_list = e_list->next; + free (p); + } +} + +/******************************************************************/ +/* Function : _asn1_delete_list_and nodes */ +/* Description: deletes the list elements and the elements */ +/* pointed by them. */ +/******************************************************************/ +void +_asn1_delete_list_and_nodes (list_type *e_list) +{ + list_type *p; + + while (e_list) + { + p = e_list; + e_list = e_list->next; + _asn1_remove_node (p->node, 0); + free (p); + } +} + + +char * +_asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE]) +{ + uint64_t d, r; + char temp[LTOSTR_MAX_SIZE]; + int count, k, start; + uint64_t val; + + if (v < 0) + { + str[0] = '-'; + start = 1; + val = -((uint64_t)v); + } + else + { + val = v; + start = 0; + } + + count = 0; + do + { + d = val / 10; + r = val - d * 10; + temp[start + count] = '0' + (char) r; + count++; + val = d; + } + while (val && ((start+count) < LTOSTR_MAX_SIZE-1)); + + for (k = 0; k < count; k++) + str[k + start] = temp[start + count - k - 1]; + str[count + start] = 0; + return str; +} + + +/******************************************************************/ +/* Function : _asn1_change_integer_value */ +/* Description: converts into DER coding the value assign to an */ +/* INTEGER constant. */ +/* Parameters: */ +/* node: root of an ASN1element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +int +_asn1_change_integer_value (asn1_node node) +{ + asn1_node p; + unsigned char val[SIZEOF_UNSIGNED_LONG_INT]; + unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1]; + int len; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + while (p) + { + if ((type_field (p->type) == ASN1_ETYPE_INTEGER) + && (p->type & CONST_ASSIGN)) + { + if (p->value) + { + _asn1_convert_integer (p->value, val, sizeof (val), &len); + asn1_octet_der (val, len, val2, &len); + _asn1_set_value (p, val2, len); + } + } + + if (p->down) + { + p = p->down; + } + else + { + if (p == node) + p = NULL; + else if (p->right) + p = p->right; + else + { + while (1) + { + p = _asn1_find_up (p); + if (p == node) + { + p = NULL; + break; + } + if (p && p->right) + { + p = p->right; + break; + } + } + } + } + } + + return ASN1_SUCCESS; +} + +#define MAX_CONSTANTS 1024 +/******************************************************************/ +/* Function : _asn1_expand_object_id */ +/* Description: expand the IDs of an OBJECT IDENTIFIER constant. */ +/* Parameters: */ +/* list: root of an object list */ +/* node: root of an ASN1 element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +int +_asn1_expand_object_id (list_type **list, asn1_node node) +{ + asn1_node p, p2, p3, p4, p5; + char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1]; + int move, tlen, tries; + unsigned max_constants; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + _asn1_str_cpy (name_root, sizeof (name_root), node->name); + + p = node; + move = DOWN; + tries = 0; + + while (!((p == node) && (move == UP))) + { + if (move != UP) + { + if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) + && (p->type & CONST_ASSIGN)) + { + p2 = p->down; + if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT)) + { + if (p2->value && !c_isdigit (p2->value[0])) + { + _asn1_str_cpy (name2, sizeof (name2), name_root); + _asn1_str_cat (name2, sizeof (name2), "."); + _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); + p3 = asn1_find_node (node, name2); + if (!p3 || _asn1_is_up(p2, p3) || + (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || + !(p3->type & CONST_ASSIGN)) + return ASN1_ELEMENT_NOT_FOUND; + + _asn1_set_down (p, p2->right); + if (p2->down) + _asn1_delete_structure (*list, &p2->down, 0); + _asn1_delete_node_from_list(*list, p2); + _asn1_remove_node (p2, 0); + p2 = p; + p4 = p3->down; + max_constants = 0; + while (p4) + { + if (type_field (p4->type) == ASN1_ETYPE_CONSTANT) + { + max_constants++; + if (max_constants == MAX_CONSTANTS) + return ASN1_RECURSION; + + p5 = + _asn1_add_single_node (ASN1_ETYPE_CONSTANT); + _asn1_set_name (p5, p4->name); + if (p4->value) + { + tlen = _asn1_strlen (p4->value); + if (tlen > 0) + _asn1_set_value (p5, p4->value, tlen + 1); + } + _asn1_add_static_node2(list, p5); + + if (p2 == p) + { + _asn1_set_right (p5, p->down); + _asn1_set_down (p, p5); + } + else + { + _asn1_set_right (p5, p2->right); + _asn1_set_right (p2, p5); + } + p2 = p5; + } + p4 = p4->right; + } + move = DOWN; + + tries++; + if (tries >= EXPAND_OBJECT_ID_MAX_RECURSION) + return ASN1_RECURSION; + + continue; + } + } + } + move = DOWN; + } + else + move = RIGHT; + + tries = 0; + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + + if (p == node) + { + move = UP; + continue; + } + + if (move == RIGHT) + { + if (p && p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + /*******************************/ + /* expand DEFAULT */ + /*******************************/ + p = node; + move = DOWN; + + while (!((p == node) && (move == UP))) + { + if (move != UP) + { + if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && + (p->type & CONST_DEFAULT)) + { + p2 = p->down; + if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT)) + { + _asn1_str_cpy (name2, sizeof (name2), name_root); + _asn1_str_cat (name2, sizeof (name2), "."); + if (p2->value) + _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); + p3 = asn1_find_node (node, name2); + if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) + || !(p3->type & CONST_ASSIGN)) + return ASN1_ELEMENT_NOT_FOUND; + p4 = p3->down; + name2[0] = 0; + while (p4) + { + if (type_field (p4->type) == ASN1_ETYPE_CONSTANT) + { + if (p4->value == NULL) + return ASN1_VALUE_NOT_FOUND; + + if (name2[0]) + _asn1_str_cat (name2, sizeof (name2), "."); + _asn1_str_cat (name2, sizeof (name2), + (char *) p4->value); + } + p4 = p4->right; + } + tlen = strlen (name2); + if (tlen > 0) + _asn1_set_value (p2, name2, tlen + 1); + } + } + move = DOWN; + } + else + move = RIGHT; + + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + + if (p == node) + { + move = UP; + continue; + } + + if (move == RIGHT) + { + if (p && p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + return ASN1_SUCCESS; +} + + +/******************************************************************/ +/* Function : _asn1_type_set_config */ +/* Description: sets the CONST_SET and CONST_NOT_USED properties */ +/* in the fields of the SET elements. */ +/* Parameters: */ +/* node: root of an ASN1 element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +int +_asn1_type_set_config (asn1_node node) +{ + asn1_node p, p2; + int move; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + move = DOWN; + + while (!((p == node) && (move == UP))) + { + if (move != UP) + { + if (type_field (p->type) == ASN1_ETYPE_SET) + { + p2 = p->down; + while (p2) + { + if (type_field (p2->type) != ASN1_ETYPE_TAG) + p2->type |= CONST_SET | CONST_NOT_USED; + p2 = p2->right; + } + } + move = DOWN; + } + else + move = RIGHT; + + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + + if (p == node) + { + move = UP; + continue; + } + + if (move == RIGHT) + { + if (p && p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + return ASN1_SUCCESS; +} + + +/******************************************************************/ +/* Function : _asn1_check_identifier */ +/* Description: checks the definitions of all the identifiers */ +/* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */ +/* The _asn1_identifierMissing global variable is filled if */ +/* necessary. */ +/* Parameters: */ +/* node: root of an ASN1 element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ +/* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +int +_asn1_check_identifier (asn1_node_const node) +{ + asn1_node_const p, p2; + char name2[ASN1_MAX_NAME_SIZE * 2 + 2]; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + while (p) + { + if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER) + { + _asn1_str_cpy (name2, sizeof (name2), node->name); + _asn1_str_cat (name2, sizeof (name2), "."); + _asn1_str_cat (name2, sizeof (name2), (char *) p->value); + p2 = asn1_find_node (node, name2); + if (p2 == NULL) + { + if (p->value) + _asn1_str_cpy (_asn1_identifierMissing, sizeof(_asn1_identifierMissing), (char*)p->value); + else + _asn1_strcpy (_asn1_identifierMissing, "(null)"); + return ASN1_IDENTIFIER_NOT_FOUND; + } + } + else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && + (p->type & CONST_DEFAULT)) + { + p2 = p->down; + if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT)) + { + _asn1_str_cpy (name2, sizeof (name2), node->name); + if (p2->value) + { + _asn1_str_cat (name2, sizeof (name2), "."); + _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); + _asn1_str_cpy (_asn1_identifierMissing, sizeof(_asn1_identifierMissing), (char*)p2->value); + } + else + _asn1_strcpy (_asn1_identifierMissing, "(null)"); + + p2 = asn1_find_node (node, name2); + if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) || + !(p2->type & CONST_ASSIGN)) + return ASN1_IDENTIFIER_NOT_FOUND; + else + _asn1_identifierMissing[0] = 0; + } + } + else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && + (p->type & CONST_ASSIGN)) + { + p2 = p->down; + if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT)) + { + if (p2->value && !c_isdigit (p2->value[0])) + { + _asn1_str_cpy (name2, sizeof (name2), node->name); + _asn1_str_cat (name2, sizeof (name2), "."); + _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); + _asn1_str_cpy (_asn1_identifierMissing, sizeof(_asn1_identifierMissing), (char*)p2->value); + + p2 = asn1_find_node (node, name2); + if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) + || !(p2->type & CONST_ASSIGN)) + return ASN1_IDENTIFIER_NOT_FOUND; + else + _asn1_identifierMissing[0] = 0; + } + } + } + + if (p->down) + { + p = p->down; + } + else if (p->right) + p = p->right; + else + { + while (p) + { + p = _asn1_find_up (p); + if (p == node) + { + p = NULL; + break; + } + if (p && p->right) + { + p = p->right; + break; + } + } + } + } + + return ASN1_SUCCESS; +} + + +/******************************************************************/ +/* Function : _asn1_set_default_tag */ +/* Description: sets the default IMPLICIT or EXPLICIT property in */ +/* the tagged elements that don't have this declaration. */ +/* Parameters: */ +/* node: pointer to a DEFINITIONS element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */ +/* a DEFINITIONS element, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +int +_asn1_set_default_tag (asn1_node node) +{ + asn1_node p; + + if ((node == NULL) || (type_field (node->type) != ASN1_ETYPE_DEFINITIONS)) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + while (p) + { + if ((type_field (p->type) == ASN1_ETYPE_TAG) && + !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT)) + { + if (node->type & CONST_EXPLICIT) + p->type |= CONST_EXPLICIT; + else + p->type |= CONST_IMPLICIT; + } + + if (p->down) + { + p = p->down; + } + else if (p->right) + p = p->right; + else + { + while (1) + { + p = _asn1_find_up (p); + if (p == node) + { + p = NULL; + break; + } + if (p && p->right) + { + p = p->right; + break; + } + } + } + } + + return ASN1_SUCCESS; +} diff --git a/lib/minitasn1/parser_aux.h b/lib/minitasn1/parser_aux.h new file mode 100644 index 0000000..598e684 --- /dev/null +++ b/lib/minitasn1/parser_aux.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2000-2014 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifndef _PARSER_AUX_H +#define _PARSER_AUX_H + +/***********************************************/ +/* Type: list_type */ +/* Description: type used in the list during */ +/* the structure creation. */ +/***********************************************/ +typedef struct list_struct +{ + asn1_node node; + struct list_struct *next; +} list_type; + +/***************************************/ +/* Functions used by ASN.1 parser */ +/***************************************/ +asn1_node _asn1_add_static_node (list_type **e_list, unsigned int type); + +void _asn1_delete_list (list_type *e_list); + +void _asn1_delete_list_and_nodes (list_type *e_list); + +void _asn1_delete_node_from_list (list_type *list, asn1_node node); + +asn1_node +_asn1_set_value (asn1_node node, const void *value, unsigned int len); + +asn1_node _asn1_set_value_m (asn1_node node, void *value, unsigned int len); + +asn1_node +_asn1_set_value_lv (asn1_node node, const void *value, unsigned int len); + +asn1_node +_asn1_append_value (asn1_node node, const void *value, unsigned int len); + +asn1_node _asn1_set_name (asn1_node node, const char *name); + +asn1_node _asn1_cpy_name (asn1_node dst, asn1_node_const src); + +asn1_node _asn1_set_right (asn1_node node, asn1_node right); + +asn1_node _asn1_get_last_right (asn1_node_const node); + +void _asn1_remove_node (asn1_node node, unsigned int flags); + +/* Max 64-bit integer length is 20 chars + 1 for sign + 1 for null termination */ +#define LTOSTR_MAX_SIZE 22 +char *_asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE]); + +asn1_node _asn1_find_up (asn1_node_const node); + +int _asn1_change_integer_value (asn1_node node); + +#define EXPAND_OBJECT_ID_MAX_RECURSION 16 +int _asn1_expand_object_id (list_type **list, asn1_node node); + +int _asn1_type_set_config (asn1_node node); + +int _asn1_check_identifier (asn1_node_const node); + +int _asn1_set_default_tag (asn1_node node); + +/******************************************************************/ +/* Function : _asn1_get_right */ +/* Description: returns the element pointed by the RIGHT field of */ +/* a NODE_ASN element. */ +/* Parameters: */ +/* node: NODE_ASN element pointer. */ +/* Return: field RIGHT of NODE. */ +/******************************************************************/ +inline static asn1_node +_asn1_get_right (asn1_node_const node) +{ + if (node == NULL) + return NULL; + return node->right; +} + +/******************************************************************/ +/* Function : _asn1_set_down */ +/* Description: sets the field DOWN in a NODE_ASN element. */ +/* Parameters: */ +/* node: element pointer. */ +/* down: pointer to a NODE_ASN element that you want be pointed */ +/* by NODE. */ +/* Return: pointer to *NODE. */ +/******************************************************************/ +inline static asn1_node +_asn1_set_down (asn1_node node, asn1_node down) +{ + if (node == NULL) + return node; + node->down = down; + if (down) + down->left = node; + return node; +} + +/******************************************************************/ +/* Function : _asn1_get_down */ +/* Description: returns the element pointed by the DOWN field of */ +/* a NODE_ASN element. */ +/* Parameters: */ +/* node: NODE_ASN element pointer. */ +/* Return: field DOWN of NODE. */ +/******************************************************************/ +inline static asn1_node +_asn1_get_down (asn1_node_const node) +{ + if (node == NULL) + return NULL; + return node->down; +} + +/******************************************************************/ +/* Function : _asn1_get_name */ +/* Description: returns the name of a NODE_ASN element. */ +/* Parameters: */ +/* node: NODE_ASN element pointer. */ +/* Return: a null terminated string. */ +/******************************************************************/ +inline static char * +_asn1_get_name (asn1_node_const node) +{ + if (node == NULL) + return NULL; + return (char *) node->name; +} + +/******************************************************************/ +/* Function : _asn1_mod_type */ +/* Description: change the field TYPE of an NODE_ASN element. */ +/* The new value is the old one | (bitwise or) the */ +/* paramener VALUE. */ +/* Parameters: */ +/* node: NODE_ASN element pointer. */ +/* value: the integer value that must be or-ed with the current */ +/* value of field TYPE. */ +/* Return: NODE pointer. */ +/******************************************************************/ +inline static asn1_node +_asn1_mod_type (asn1_node node, unsigned int value) +{ + if (node == NULL) + return node; + node->type |= value; + return node; +} + +#endif diff --git a/lib/minitasn1/structure.c b/lib/minitasn1/structure.c new file mode 100644 index 0000000..8189c56 --- /dev/null +++ b/lib/minitasn1/structure.c @@ -0,0 +1,1220 @@ +/* + * Copyright (C) 2002-2014 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + + +/*****************************************************/ +/* File: structure.c */ +/* Description: Functions to create and delete an */ +/* ASN1 tree. */ +/*****************************************************/ + + +#include +#include +#include "parser_aux.h" +#include + + +extern char _asn1_identifierMissing[]; + + +/******************************************************/ +/* Function : _asn1_add_single_node */ +/* Description: creates a new NODE_ASN element. */ +/* Parameters: */ +/* type: type of the new element (see ASN1_ETYPE_ */ +/* and CONST_ constants). */ +/* Return: pointer to the new element. */ +/******************************************************/ +asn1_node +_asn1_add_single_node (unsigned int type) +{ + asn1_node punt; + + punt = calloc (1, sizeof (struct asn1_node_st)); + if (punt == NULL) + return NULL; + + punt->type = type; + + return punt; +} + + +/******************************************************************/ +/* Function : _asn1_find_left */ +/* Description: returns the NODE_ASN element with RIGHT field that*/ +/* points the element NODE. */ +/* Parameters: */ +/* node: NODE_ASN element pointer. */ +/* Return: NULL if not found. */ +/******************************************************************/ +asn1_node +_asn1_find_left (asn1_node_const node) +{ + if ((node == NULL) || (node->left == NULL) || (node->left->down == node)) + return NULL; + + return node->left; +} + + +int +_asn1_create_static_structure (asn1_node_const pointer, char *output_file_name, + char *vector_name) +{ + FILE *file; + asn1_node_const p; + unsigned long t; + + file = fopen (output_file_name, "w"); + + if (file == NULL) + return ASN1_FILE_NOT_FOUND; + + fprintf (file, "#if HAVE_CONFIG_H\n"); + fprintf (file, "# include \"config.h\"\n"); + fprintf (file, "#endif\n\n"); + + fprintf (file, "#include \n\n"); + + fprintf (file, "const asn1_static_node %s[] = {\n", vector_name); + + p = pointer; + + while (p) + { + fprintf (file, " { "); + + if (p->name[0] != 0) + fprintf (file, "\"%s\", ", p->name); + else + fprintf (file, "NULL, "); + + t = p->type; + if (p->down) + t |= CONST_DOWN; + if (p->right) + t |= CONST_RIGHT; + + fprintf (file, "%lu, ", t); + + if (p->value) + fprintf (file, "\"%s\"},\n", p->value); + else + fprintf (file, "NULL },\n"); + + if (p->down) + { + p = p->down; + } + else if (p->right) + { + p = p->right; + } + else + { + while (1) + { + p = _asn1_find_up (p); + if (p == pointer) + { + p = NULL; + break; + } + if (p->right) + { + p = p->right; + break; + } + } + } + } + + fprintf (file, " { NULL, 0, NULL }\n};\n"); + + fclose (file); + + return ASN1_SUCCESS; +} + + +/** + * asn1_array2tree: + * @array: specify the array that contains ASN.1 declarations + * @definitions: return the pointer to the structure created by + * *ARRAY ASN.1 declarations + * @errorDescription: return the error description. + * + * Creates the structures needed to manage the ASN.1 definitions. + * @array is a vector created by asn1_parser2array(). + * + * Returns: %ASN1_SUCCESS if structure was created correctly, + * %ASN1_ELEMENT_NOT_EMPTY if *@definitions not NULL, + * %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an identifier + * that is not defined (see @errorDescription for more information), + * %ASN1_ARRAY_ERROR if the array pointed by @array is wrong. + **/ +int +asn1_array2tree (const asn1_static_node * array, asn1_node * definitions, + char *errorDescription) +{ + asn1_node p, p_last = NULL; + unsigned long k; + int move; + int result; + unsigned int type; + list_type *e_list = NULL; + + if (errorDescription) + errorDescription[0] = 0; + + if (*definitions != NULL) + return ASN1_ELEMENT_NOT_EMPTY; + + move = UP; + + for (k = 0; array[k].value || array[k].type || array[k].name; k++) + { + type = convert_old_type (array[k].type); + + p = _asn1_add_static_node (&e_list, type & (~CONST_DOWN)); + if (array[k].name) + _asn1_set_name (p, array[k].name); + if (array[k].value) + _asn1_set_value (p, array[k].value, strlen (array[k].value) + 1); + + if (*definitions == NULL) + *definitions = p; + + if (move == DOWN) + { + if (p_last && p_last->down) + _asn1_delete_structure (e_list, &p_last->down, 0); + _asn1_set_down (p_last, p); + } + else if (move == RIGHT) + { + if (p_last && p_last->right) + _asn1_delete_structure (e_list, &p_last->right, 0); + _asn1_set_right (p_last, p); + } + + p_last = p; + + if (type & CONST_DOWN) + move = DOWN; + else if (type & CONST_RIGHT) + move = RIGHT; + else + { + while (p_last != *definitions) + { + p_last = _asn1_find_up (p_last); + + if (p_last == NULL) + break; + + if (p_last->type & CONST_RIGHT) + { + p_last->type &= ~CONST_RIGHT; + move = RIGHT; + break; + } + } /* while */ + } + } /* while */ + + if (p_last == *definitions) + { + result = _asn1_check_identifier (*definitions); + if (result == ASN1_SUCCESS) + { + _asn1_change_integer_value (*definitions); + result = _asn1_expand_object_id (&e_list, *definitions); + } + } + else + { + result = ASN1_ARRAY_ERROR; + } + + if (errorDescription != NULL) + { + if (result == ASN1_IDENTIFIER_NOT_FOUND) + { + Estrcpy (errorDescription, ":: identifier '"); + Estrcat (errorDescription, _asn1_identifierMissing); + Estrcat (errorDescription, "' not found"); + } + else + errorDescription[0] = 0; + } + + if (result != ASN1_SUCCESS) + { + _asn1_delete_list_and_nodes (e_list); + *definitions = NULL; + } + else + _asn1_delete_list (e_list); + + return result; +} + +/** + * asn1_delete_structure: + * @structure: pointer to the structure that you want to delete. + * + * Deletes the structure *@structure. At the end, *@structure is set + * to NULL. + * + * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if + * *@structure was NULL. + **/ +int +asn1_delete_structure (asn1_node * structure) +{ + return _asn1_delete_structure (NULL, structure, 0); +} + +/** + * asn1_delete_structure2: + * @structure: pointer to the structure that you want to delete. + * @flags: additional flags (see %ASN1_DELETE_FLAG) + * + * Deletes the structure *@structure. At the end, *@structure is set + * to NULL. + * + * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if + * *@structure was NULL. + **/ +int +asn1_delete_structure2 (asn1_node * structure, unsigned int flags) +{ + return _asn1_delete_structure (NULL, structure, flags); +} + +int +_asn1_delete_structure (list_type *e_list, asn1_node * structure, unsigned int flags) +{ + asn1_node p, p2, p3; + + if (*structure == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = *structure; + while (p) + { + if (p->down) + { + p = p->down; + } + else + { /* no down */ + p2 = p->right; + if (p != *structure) + { + p3 = _asn1_find_up (p); + _asn1_set_down (p3, p2); + if (e_list) + _asn1_delete_node_from_list (e_list, p); + _asn1_remove_node (p, flags); + p = p3; + } + else + { /* p==root */ + p3 = _asn1_find_left (p); + if (!p3) + { + p3 = _asn1_find_up (p); + if (p3) + _asn1_set_down (p3, p2); + else + { + if (p->right) + p->right->left = NULL; + } + } + else + _asn1_set_right (p3, p2); + if (e_list) + _asn1_delete_node_from_list (e_list, p); + _asn1_remove_node (p, flags); + p = NULL; + } + } + } + + *structure = NULL; + return ASN1_SUCCESS; +} + + +/** + * asn1_delete_element: + * @structure: pointer to the structure that contains the element you + * want to delete. + * @element_name: element's name you want to delete. + * + * Deletes the element named *@element_name inside *@structure. + * + * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if + * the @element_name was not found. + **/ +int +asn1_delete_element (asn1_node structure, const char *element_name) +{ + asn1_node p2, p3, source_node; + + source_node = asn1_find_node (structure, element_name); + + if (source_node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p2 = source_node->right; + p3 = _asn1_find_left (source_node); + if (!p3) + { + p3 = _asn1_find_up (source_node); + if (p3) + _asn1_set_down (p3, p2); + else if (source_node->right) + source_node->right->left = NULL; + } + else + _asn1_set_right (p3, p2); + + return asn1_delete_structure (&source_node); +} + +#ifndef __clang_analyzer__ +asn1_node +_asn1_copy_structure3 (asn1_node_const source_node) +{ + asn1_node_const p_s; + asn1_node dest_node, p_d, p_d_prev; + int move; + + if (source_node == NULL) + return NULL; + + dest_node = _asn1_add_single_node (source_node->type); + + p_s = source_node; + p_d = dest_node; + + move = DOWN; + + do + { + if (move != UP) + { + if (p_s->name[0] != 0) + _asn1_cpy_name (p_d, p_s); + if (p_s->value) + _asn1_set_value (p_d, p_s->value, p_s->value_len); + if (p_s->down) + { + p_s = p_s->down; + p_d_prev = p_d; + p_d = _asn1_add_single_node (p_s->type); + _asn1_set_down (p_d_prev, p_d); + continue; + } + p_d->start = p_s->start; + p_d->end = p_s->end; + } + + if (p_s == source_node) + break; + + if (p_s->right) + { + move = RIGHT; + p_s = p_s->right; + p_d_prev = p_d; + p_d = _asn1_add_single_node (p_s->type); + _asn1_set_right (p_d_prev, p_d); + } + else + { + move = UP; + p_s = _asn1_find_up (p_s); + p_d = _asn1_find_up (p_d); + } + } + while (p_s != source_node); + return dest_node; +} +#else + +/* Non-production code */ +asn1_node +_asn1_copy_structure3 (asn1_node_const source_node) +{ + return NULL; +} +#endif /* __clang_analyzer__ */ + + +static asn1_node +_asn1_copy_structure2 (asn1_node_const root, const char *source_name) +{ + asn1_node source_node; + + source_node = asn1_find_node (root, source_name); + + return _asn1_copy_structure3 (source_node); + +} + + +static int +_asn1_type_choice_config (asn1_node node) +{ + asn1_node p, p2, p3, p4; + int move, tlen; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + move = DOWN; + + while (!((p == node) && (move == UP))) + { + if (move != UP) + { + if ((type_field (p->type) == ASN1_ETYPE_CHOICE) + && (p->type & CONST_TAG)) + { + p2 = p->down; + while (p2) + { + if (type_field (p2->type) != ASN1_ETYPE_TAG) + { + p2->type |= CONST_TAG; + p3 = _asn1_find_left (p2); + while (p3) + { + if (type_field (p3->type) == ASN1_ETYPE_TAG) + { + p4 = _asn1_add_single_node (p3->type); + tlen = _asn1_strlen (p3->value); + if (tlen > 0) + _asn1_set_value (p4, p3->value, tlen + 1); + _asn1_set_right (p4, p2->down); + _asn1_set_down (p2, p4); + } + p3 = _asn1_find_left (p3); + } + } + p2 = p2->right; + } + p->type &= ~(CONST_TAG); + p2 = p->down; + while (p2) + { + p3 = p2->right; + if (type_field (p2->type) == ASN1_ETYPE_TAG) + asn1_delete_structure (&p2); + p2 = p3; + } + } + move = DOWN; + } + else + move = RIGHT; + + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + + if (p == node) + { + move = UP; + continue; + } + + if (move == RIGHT) + { + if (p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + return ASN1_SUCCESS; +} + + +static int +_asn1_expand_identifier (asn1_node * node, asn1_node_const root) +{ + asn1_node p, p2, p3; + char name2[ASN1_MAX_NAME_SIZE + 2]; + int move; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = *node; + move = DOWN; + + while (!((p == *node) && (move == UP))) + { + if (move != UP) + { + if (type_field (p->type) == ASN1_ETYPE_IDENTIFIER) + { + snprintf (name2, sizeof (name2), "%s.%s", root->name, p->value); + p2 = _asn1_copy_structure2 (root, name2); + if (p2 == NULL) + { + return ASN1_IDENTIFIER_NOT_FOUND; + } + _asn1_cpy_name (p2, p); + p2->right = p->right; + p2->left = p->left; + if (p->right) + p->right->left = p2; + p3 = p->down; + if (p3) + { + while (p3->right) + p3 = p3->right; + _asn1_set_right (p3, p2->down); + _asn1_set_down (p2, p->down); + } + + p3 = _asn1_find_left (p); + if (p3) + _asn1_set_right (p3, p2); + else + { + p3 = _asn1_find_up (p); + if (p3) + _asn1_set_down (p3, p2); + else + { + p2->left = NULL; + } + } + + if (p->type & CONST_SIZE) + p2->type |= CONST_SIZE; + if (p->type & CONST_TAG) + p2->type |= CONST_TAG; + if (p->type & CONST_OPTION) + p2->type |= CONST_OPTION; + if (p->type & CONST_DEFAULT) + p2->type |= CONST_DEFAULT; + if (p->type & CONST_SET) + p2->type |= CONST_SET; + if (p->type & CONST_NOT_USED) + p2->type |= CONST_NOT_USED; + + if (p == *node) + *node = p2; + _asn1_remove_node (p, 0); + p = p2; + move = DOWN; + continue; + } + move = DOWN; + } + else + move = RIGHT; + + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + + if (p == *node) + { + move = UP; + continue; + } + + if (move == RIGHT) + { + if (p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + return ASN1_SUCCESS; +} + + +/** + * asn1_create_element: + * @definitions: pointer to the structure returned by "parser_asn1" function + * @source_name: the name of the type of the new structure (must be + * inside p_structure). + * @element: pointer to the structure created. + * + * Creates a structure of type @source_name. Example using + * "pkix.asn": + * + * rc = asn1_create_element(cert_def, "PKIX1.Certificate", certptr); + * + * Returns: %ASN1_SUCCESS if creation OK, %ASN1_ELEMENT_NOT_FOUND if + * @source_name is not known. + **/ +int +asn1_create_element (asn1_node_const definitions, const char *source_name, + asn1_node * element) +{ + asn1_node dest_node; + int res; + + dest_node = _asn1_copy_structure2 (definitions, source_name); + + if (dest_node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + _asn1_set_name (dest_node, ""); + + res = _asn1_expand_identifier (&dest_node, definitions); + _asn1_type_choice_config (dest_node); + + *element = dest_node; + + return res; +} + + +/** + * asn1_print_structure: + * @out: pointer to the output file (e.g. stdout). + * @structure: pointer to the structure that you want to visit. + * @name: an element of the structure + * @mode: specify how much of the structure to print, can be + * %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE, + * %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL. + * + * Prints on the @out file descriptor the structure's tree starting + * from the @name element inside the structure @structure. + **/ +void +asn1_print_structure (FILE * out, asn1_node_const structure, const char *name, + int mode) +{ + asn1_node_const p, root; + int k, indent = 0, len, len2, len3; + + if (out == NULL) + return; + + root = asn1_find_node (structure, name); + + if (root == NULL) + return; + + p = root; + while (p) + { + if (mode == ASN1_PRINT_ALL) + { + for (k = 0; k < indent; k++) + fprintf (out, " "); + fprintf (out, "name:"); + if (p->name[0] != 0) + fprintf (out, "%s ", p->name); + else + fprintf (out, "NULL "); + } + else + { + switch (type_field (p->type)) + { + case ASN1_ETYPE_CONSTANT: + case ASN1_ETYPE_TAG: + case ASN1_ETYPE_SIZE: + break; + default: + for (k = 0; k < indent; k++) + fprintf (out, " "); + fprintf (out, "name:"); + if (p->name[0] != 0) + fprintf (out, "%s ", p->name); + else + fprintf (out, "NULL "); + } + } + + if (mode != ASN1_PRINT_NAME) + { + unsigned type = type_field (p->type); + switch (type) + { + case ASN1_ETYPE_CONSTANT: + if (mode == ASN1_PRINT_ALL) + fprintf (out, "type:CONST"); + break; + case ASN1_ETYPE_TAG: + if (mode == ASN1_PRINT_ALL) + fprintf (out, "type:TAG"); + break; + case ASN1_ETYPE_SIZE: + if (mode == ASN1_PRINT_ALL) + fprintf (out, "type:SIZE"); + break; + case ASN1_ETYPE_DEFAULT: + fprintf (out, "type:DEFAULT"); + break; + case ASN1_ETYPE_IDENTIFIER: + fprintf (out, "type:IDENTIFIER"); + break; + case ASN1_ETYPE_ANY: + fprintf (out, "type:ANY"); + break; + case ASN1_ETYPE_CHOICE: + fprintf (out, "type:CHOICE"); + break; + case ASN1_ETYPE_DEFINITIONS: + fprintf (out, "type:DEFINITIONS"); + break; + CASE_HANDLED_ETYPES: + fprintf (out, "%s", _asn1_tags[type].desc); + break; + default: + break; + } + } + + if ((mode == ASN1_PRINT_NAME_TYPE_VALUE) || (mode == ASN1_PRINT_ALL)) + { + switch (type_field (p->type)) + { + case ASN1_ETYPE_CONSTANT: + if (mode == ASN1_PRINT_ALL) + if (p->value) + fprintf (out, " value:%s", p->value); + break; + case ASN1_ETYPE_TAG: + if (mode == ASN1_PRINT_ALL) + if (p->value) + fprintf (out, " value:%s", p->value); + break; + case ASN1_ETYPE_SIZE: + if (mode == ASN1_PRINT_ALL) + if (p->value) + fprintf (out, " value:%s", p->value); + break; + case ASN1_ETYPE_DEFAULT: + if (p->value) + fprintf (out, " value:%s", p->value); + else if (p->type & CONST_TRUE) + fprintf (out, " value:TRUE"); + else if (p->type & CONST_FALSE) + fprintf (out, " value:FALSE"); + break; + case ASN1_ETYPE_IDENTIFIER: + if (p->value) + fprintf (out, " value:%s", p->value); + break; + case ASN1_ETYPE_INTEGER: + if (p->value) + { + len2 = -1; + len = asn1_get_length_der (p->value, p->value_len, &len2); + fprintf (out, " value:0x"); + if (len > 0) + for (k = 0; k < len; k++) + fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); + } + break; + case ASN1_ETYPE_ENUMERATED: + if (p->value) + { + len2 = -1; + len = asn1_get_length_der (p->value, p->value_len, &len2); + fprintf (out, " value:0x"); + if (len > 0) + for (k = 0; k < len; k++) + fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); + } + break; + case ASN1_ETYPE_BOOLEAN: + if (p->value) + { + if (p->value[0] == 'T') + fprintf (out, " value:TRUE"); + else if (p->value[0] == 'F') + fprintf (out, " value:FALSE"); + } + break; + case ASN1_ETYPE_BIT_STRING: + if (p->value) + { + len2 = -1; + len = asn1_get_length_der (p->value, p->value_len, &len2); + if (len > 0) + { + fprintf (out, " value(%i):", + (len - 1) * 8 - (p->value[len2])); + for (k = 1; k < len; k++) + fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); + } + } + break; + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: + if (p->value) + { + fprintf (out, " value:"); + for (k = 0; k < p->value_len; k++) + fprintf (out, "%c", (p->value)[k]); + } + break; + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + if (p->value) + { + len2 = -1; + len = asn1_get_length_der (p->value, p->value_len, &len2); + fprintf (out, " value:"); + if (len > 0) + for (k = 0; k < len; k++) + fprintf (out, "%c", (p->value)[k + len2]); + } + break; + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_OCTET_STRING: + if (p->value) + { + len2 = -1; + len = asn1_get_length_der (p->value, p->value_len, &len2); + fprintf (out, " value:"); + if (len > 0) + for (k = 0; k < len; k++) + fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); + } + break; + case ASN1_ETYPE_OBJECT_ID: + if (p->value) + fprintf (out, " value:%s", p->value); + break; + case ASN1_ETYPE_ANY: + if (p->value) + { + len3 = -1; + len2 = asn1_get_length_der (p->value, p->value_len, &len3); + fprintf (out, " value:"); + if (len2 > 0) + for (k = 0; k < len2; k++) + fprintf (out, "%02x", (unsigned) (p->value)[k + len3]); + } + break; + case ASN1_ETYPE_SET: + case ASN1_ETYPE_SET_OF: + case ASN1_ETYPE_CHOICE: + case ASN1_ETYPE_DEFINITIONS: + case ASN1_ETYPE_SEQUENCE_OF: + case ASN1_ETYPE_SEQUENCE: + case ASN1_ETYPE_NULL: + break; + default: + break; + } + } + + if (mode == ASN1_PRINT_ALL) + { + if (p->type & 0x1FFFFF00) + { + fprintf (out, " attr:"); + if (p->type & CONST_UNIVERSAL) + fprintf (out, "UNIVERSAL,"); + if (p->type & CONST_PRIVATE) + fprintf (out, "PRIVATE,"); + if (p->type & CONST_APPLICATION) + fprintf (out, "APPLICATION,"); + if (p->type & CONST_EXPLICIT) + fprintf (out, "EXPLICIT,"); + if (p->type & CONST_IMPLICIT) + fprintf (out, "IMPLICIT,"); + if (p->type & CONST_TAG) + fprintf (out, "TAG,"); + if (p->type & CONST_DEFAULT) + fprintf (out, "DEFAULT,"); + if (p->type & CONST_TRUE) + fprintf (out, "TRUE,"); + if (p->type & CONST_FALSE) + fprintf (out, "FALSE,"); + if (p->type & CONST_LIST) + fprintf (out, "LIST,"); + if (p->type & CONST_MIN_MAX) + fprintf (out, "MIN_MAX,"); + if (p->type & CONST_OPTION) + fprintf (out, "OPTION,"); + if (p->type & CONST_1_PARAM) + fprintf (out, "1_PARAM,"); + if (p->type & CONST_SIZE) + fprintf (out, "SIZE,"); + if (p->type & CONST_DEFINED_BY) + fprintf (out, "DEF_BY,"); + if (p->type & CONST_GENERALIZED) + fprintf (out, "GENERALIZED,"); + if (p->type & CONST_UTC) + fprintf (out, "UTC,"); + if (p->type & CONST_SET) + fprintf (out, "SET,"); + if (p->type & CONST_NOT_USED) + fprintf (out, "NOT_USED,"); + if (p->type & CONST_ASSIGN) + fprintf (out, "ASSIGNMENT,"); + } + } + + if (mode == ASN1_PRINT_ALL) + { + fprintf (out, "\n"); + } + else + { + switch (type_field (p->type)) + { + case ASN1_ETYPE_CONSTANT: + case ASN1_ETYPE_TAG: + case ASN1_ETYPE_SIZE: + break; + default: + fprintf (out, "\n"); + } + } + + if (p->down) + { + p = p->down; + indent += 2; + } + else if (p == root) + { + p = NULL; + break; + } + else if (p->right) + p = p->right; + else + { + while (1) + { + p = _asn1_find_up (p); + if (p == root) + { + p = NULL; + break; + } + indent -= 2; + if (p->right) + { + p = p->right; + break; + } + } + } + } +} + + + +/** + * asn1_number_of_elements: + * @element: pointer to the root of an ASN1 structure. + * @name: the name of a sub-structure of ROOT. + * @num: pointer to an integer where the result will be stored + * + * Counts the number of elements of a sub-structure called NAME with + * names equal to "?1","?2", ... + * + * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if + * @name is not known, %ASN1_GENERIC_ERROR if pointer @num is %NULL. + **/ +int +asn1_number_of_elements (asn1_node_const element, const char *name, int *num) +{ + asn1_node_const node, p; + + if (num == NULL) + return ASN1_GENERIC_ERROR; + + *num = 0; + + node = asn1_find_node (element, name); + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node->down; + + while (p) + { + if (p->name[0] == '?') + (*num)++; + p = p->right; + } + + return ASN1_SUCCESS; +} + + +/** + * asn1_find_structure_from_oid: + * @definitions: ASN1 definitions + * @oidValue: value of the OID to search (e.g. "1.2.3.4"). + * + * Search the structure that is defined just after an OID definition. + * + * Returns: %NULL when @oidValue not found, otherwise the pointer to a + * constant string that contains the element name defined just after + * the OID. + **/ +const char * +asn1_find_structure_from_oid (asn1_node_const definitions, const char *oidValue) +{ + char name[2 * ASN1_MAX_NAME_SIZE + 2]; + char value[ASN1_MAX_NAME_SIZE]; + asn1_node p; + int len; + int result; + const char *definitionsName; + + if ((definitions == NULL) || (oidValue == NULL)) + return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ + + definitionsName = definitions->name; + + /* search the OBJECT_ID into definitions */ + p = definitions->down; + while (p) + { + if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && + (p->type & CONST_ASSIGN)) + { + snprintf(name, sizeof(name), "%s.%s", definitionsName, p->name); + + len = ASN1_MAX_NAME_SIZE; + result = asn1_read_value (definitions, name, value, &len); + + if ((result == ASN1_SUCCESS) && (!strcmp (oidValue, value))) + { + p = p->right; + if (p == NULL) /* reach the end of ASN1 definitions */ + return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ + + return p->name; + } + } + p = p->right; + } + + return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ +} + +/** + * asn1_copy_node: + * @dst: Destination asn1 node. + * @dst_name: Field name in destination node. + * @src: Source asn1 node. + * @src_name: Field name in source node. + * + * Create a deep copy of a asn1_node variable. That + * function requires @dst to be expanded using asn1_create_element(). + * + * Returns: Return %ASN1_SUCCESS on success. + **/ +int +asn1_copy_node (asn1_node dst, const char *dst_name, + asn1_node_const src, const char *src_name) +{ + int result; + asn1_node dst_node; + void *data = NULL; + int size = 0; + + result = asn1_der_coding (src, src_name, NULL, &size, NULL); + if (result != ASN1_MEM_ERROR) + return result; + + data = malloc (size); + if (data == NULL) + return ASN1_MEM_ERROR; + + result = asn1_der_coding (src, src_name, data, &size, NULL); + if (result != ASN1_SUCCESS) + { + free (data); + return result; + } + + dst_node = asn1_find_node (dst, dst_name); + if (dst_node == NULL) + { + free (data); + return ASN1_ELEMENT_NOT_FOUND; + } + + result = asn1_der_decoding (&dst_node, data, size, NULL); + + free (data); + + return result; +} + +/** + * asn1_dup_node: + * @src: Source asn1 node. + * @src_name: Field name in source node. + * + * Create a deep copy of a asn1_node variable. This function + * will return an exact copy of the provided structure. + * + * Returns: Return %NULL on failure. + **/ +asn1_node +asn1_dup_node (asn1_node_const src, const char *src_name) +{ + return _asn1_copy_structure2(src, src_name); +} diff --git a/lib/minitasn1/structure.h b/lib/minitasn1/structure.h new file mode 100644 index 0000000..99e685d --- /dev/null +++ b/lib/minitasn1/structure.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2002-2014 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +/*************************************************/ +/* File: structure.h */ +/* Description: list of exported object by */ +/* "structure.c" */ +/*************************************************/ + +#ifndef _STRUCTURE_H +#define _STRUCTURE_H + +#include "parser_aux.h" // list_type + +int _asn1_create_static_structure (asn1_node_const pointer, + char *output_file_name, char *vector_name); + +asn1_node _asn1_copy_structure3 (asn1_node_const source_node); + +asn1_node _asn1_add_single_node (unsigned int type); + +asn1_node _asn1_find_left (asn1_node_const node); + +int +_asn1_delete_structure (list_type *e_list, asn1_node *structure, unsigned int flags); + +#endif diff --git a/lib/minitasn1/version.c b/lib/minitasn1/version.c new file mode 100644 index 0000000..25f8a8f --- /dev/null +++ b/lib/minitasn1/version.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2000-2014 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include /* for strverscmp */ + +#include "libtasn1.h" + +/** + * asn1_check_version: + * @req_version: Required version number, or %NULL. + * + * Check that the version of the library is at minimum the + * requested one and return the version string; return %NULL if the + * condition is not satisfied. If a %NULL is passed to this function, + * no check is done, but the version string is simply returned. + * + * See %ASN1_VERSION for a suitable @req_version string. + * + * Returns: Version string of run-time library, or %NULL if the + * run-time library does not meet the required version number. + */ +const char * +asn1_check_version (const char *req_version) +{ + if (!req_version || strverscmp (req_version, ASN1_VERSION) <= 0) + return ASN1_VERSION; + + return NULL; +} diff --git a/lib/nettle/cipher.c b/lib/nettle/cipher.c index 93afca2..69ed702 100644 --- a/lib/nettle/cipher.c +++ b/lib/nettle/cipher.c @@ -396,7 +396,7 @@ _xts_aes128_set_encrypt_key(struct xts_aes128_key *xts_key, const uint8_t *key) { if (_gnutls_fips_mode_enabled() && - gnutls_memcmp(key, key + AES128_KEY_SIZE, AES128_KEY_SIZE) == 0) + safe_memcmp(key, key + AES128_KEY_SIZE, AES128_KEY_SIZE) == 0) _gnutls_switch_lib_state(LIB_STATE_ERROR); xts_aes128_set_encrypt_key(xts_key, key); @@ -407,7 +407,7 @@ _xts_aes128_set_decrypt_key(struct xts_aes128_key *xts_key, const uint8_t *key) { if (_gnutls_fips_mode_enabled() && - gnutls_memcmp(key, key + AES128_KEY_SIZE, AES128_KEY_SIZE) == 0) + safe_memcmp(key, key + AES128_KEY_SIZE, AES128_KEY_SIZE) == 0) _gnutls_switch_lib_state(LIB_STATE_ERROR); xts_aes128_set_decrypt_key(xts_key, key); @@ -418,7 +418,7 @@ _xts_aes256_set_encrypt_key(struct xts_aes256_key *xts_key, const uint8_t *key) { if (_gnutls_fips_mode_enabled() && - gnutls_memcmp(key, key + AES256_KEY_SIZE, AES256_KEY_SIZE) == 0) + safe_memcmp(key, key + AES256_KEY_SIZE, AES256_KEY_SIZE) == 0) _gnutls_switch_lib_state(LIB_STATE_ERROR); xts_aes256_set_encrypt_key(xts_key, key); @@ -429,7 +429,7 @@ _xts_aes256_set_decrypt_key(struct xts_aes256_key *xts_key, const uint8_t *key) { if (_gnutls_fips_mode_enabled() && - gnutls_memcmp(key, key + AES256_KEY_SIZE, AES256_KEY_SIZE) == 0) + safe_memcmp(key, key + AES256_KEY_SIZE, AES256_KEY_SIZE) == 0) _gnutls_switch_lib_state(LIB_STATE_ERROR); xts_aes256_set_decrypt_key(xts_key, key); diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index 05146ca..ccf403b 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -71,7 +71,6 @@ #include "int/dsa-compute-k.h" #include #include -#include "dh.h" static inline const struct ecc_curve *get_supported_nist_curve(int curve); static inline const struct ecc_curve *get_supported_gost_curve(int curve); @@ -230,38 +229,25 @@ _gost_params_to_pubkey(const gnutls_pk_params_st * pk_params, } #endif -static int +static void ecc_shared_secret(struct ecc_scalar *private_key, struct ecc_point *public_key, void *out, unsigned size) { struct ecc_point r; - mpz_t x, y; - int ret = 0; + mpz_t x; mpz_init(x); - mpz_init(y); ecc_point_init(&r, public_key->ecc); ecc_point_mul(&r, private_key, public_key); - ecc_point_get(&r, x, y); - - /* Check if the point is not an identity element. Note that this cannot - * happen in nettle implementation, because it cannot represent an - * infinity point. */ - if (mpz_cmp_ui(x, 0) == 0 && mpz_cmp_ui(y, 0) == 0) { - ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); - goto cleanup; - } - + ecc_point_get(&r, x, NULL); nettle_mpz_get_str_256(size, out, x); - cleanup: mpz_clear(x); - mpz_clear(y); ecc_point_clear(&r); - return ret; + return; } #define MAX_DH_BITS DEFAULT_MAX_VERIFY_BITS @@ -302,7 +288,7 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo, switch (algo) { case GNUTLS_PK_DH: { bigint_t f, x, q, prime; - bigint_t k = NULL, primesub1 = NULL, r = NULL; + bigint_t k = NULL, ff = NULL, r = NULL; unsigned int bits; if (nonce != NULL) @@ -313,20 +299,21 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo, q = priv->params[DH_Q]; prime = priv->params[DH_P]; - ret = _gnutls_mpi_init_multi(&k, &primesub1, &r, NULL); + ret = _gnutls_mpi_init_multi(&k, &ff, &r, NULL); if (ret < 0) return gnutls_assert_val(ret); - ret = _gnutls_mpi_sub_ui(primesub1, prime, 1); + ret = _gnutls_mpi_add_ui(ff, f, 1); if (ret < 0) { gnutls_assert(); goto dh_cleanup; } - /* check if f==0,1, or f >= p-1 */ - if ((_gnutls_mpi_cmp_ui(f, 1) == 0) - || (_gnutls_mpi_cmp_ui(f, 0) == 0) - || (_gnutls_mpi_cmp(f, primesub1) >= 0)) { + /* check if f==0,1, or f >= p-1. + * or (ff=f+1) equivalently ff==1,2, ff >= p */ + if ((_gnutls_mpi_cmp_ui(ff, 2) == 0) + || (_gnutls_mpi_cmp_ui(ff, 1) == 0) + || (_gnutls_mpi_cmp(ff, prime) >= 0)) { gnutls_assert(); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto dh_cleanup; @@ -367,15 +354,6 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo, goto dh_cleanup; } - /* check if k==0,1, or k = p-1 */ - if ((_gnutls_mpi_cmp_ui(k, 1) == 0) - || (_gnutls_mpi_cmp_ui(k, 0) == 0) - || (_gnutls_mpi_cmp(k, primesub1) == 0)) { - gnutls_assert(); - ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; - goto dh_cleanup; - } - if (flags & PK_DERIVE_TLS13) { ret = _gnutls_mpi_dprint_size(k, out, @@ -392,7 +370,7 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo, ret = 0; dh_cleanup: _gnutls_mpi_release(&r); - _gnutls_mpi_release(&primesub1); + _gnutls_mpi_release(&ff); zrelease_temp_mpi_key(&k); if (ret < 0) goto cleanup; @@ -437,10 +415,8 @@ dh_cleanup: goto ecc_cleanup; } - ret = ecc_shared_secret(&ecc_priv, &ecc_pub, out->data, - out->size); - if (ret < 0) - gnutls_free(out->data); + ecc_shared_secret(&ecc_priv, &ecc_pub, out->data, + out->size); ecc_cleanup: ecc_point_clear(&ecc_pub); @@ -1552,80 +1528,6 @@ static inline const struct ecc_curve *get_supported_nist_curve(int curve) } } -static inline const char *get_supported_nist_curve_order(int curve) -{ - static const struct { - int curve; - const char *order; - } orders[] = { -#ifdef ENABLE_NON_SUITEB_CURVES - { GNUTLS_ECC_CURVE_SECP192R1, - "ffffffffffffffffffffffff99def836" - "146bc9b1b4d22831" }, - { GNUTLS_ECC_CURVE_SECP224R1, - "ffffffffffffffffffffffffffff16a2" - "e0b8f03e13dd29455c5c2a3d" }, -#endif - { GNUTLS_ECC_CURVE_SECP256R1, - "ffffffff00000000ffffffffffffffff" - "bce6faada7179e84f3b9cac2fc632551" }, - { GNUTLS_ECC_CURVE_SECP384R1, - "ffffffffffffffffffffffffffffffff" - "ffffffffffffffffc7634d81f4372ddf" - "581a0db248b0a77aecec196accc52973" }, - { GNUTLS_ECC_CURVE_SECP521R1, - "1fffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffff" - "ffa51868783bf2f966b7fcc0148f709a" - "5d03bb5c9b8899c47aebb6fb71e91386" - "409" }, - }; - size_t i; - - for (i = 0; i < sizeof(orders)/sizeof(orders[0]); i++) { - if (orders[i].curve == curve) - return orders[i].order; - } - return NULL; -} - -static inline const char *get_supported_nist_curve_modulus(int curve) -{ - static const struct { - int curve; - const char *order; - } orders[] = { -#ifdef ENABLE_NON_SUITEB_CURVES - { GNUTLS_ECC_CURVE_SECP192R1, - "fffffffffffffffffffffffffffffffe" - "ffffffffffffffff" }, - { GNUTLS_ECC_CURVE_SECP224R1, - "ffffffffffffffffffffffffffffffff" - "000000000000000000000001" }, -#endif - { GNUTLS_ECC_CURVE_SECP256R1, - "ffffffff000000010000000000000000" - "00000000ffffffffffffffffffffffff" }, - { GNUTLS_ECC_CURVE_SECP384R1, - "ffffffffffffffffffffffffffffffff" - "fffffffffffffffffffffffffffffffe" - "ffffffff0000000000000000ffffffff" }, - { GNUTLS_ECC_CURVE_SECP521R1, - "1ff" - "ffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffff" - "ffffffffffffffffffffffffffffffff" }, - }; - size_t i; - - for (i = 0; i < sizeof(orders)/sizeof(orders[0]); i++) { - if (orders[i].curve == curve) - return orders[i].order; - } - return NULL; -} - static inline const struct ecc_curve *get_supported_gost_curve(int curve) { switch (curve) { @@ -2206,53 +2108,6 @@ edwards_curve_mul_g(gnutls_pk_algorithm_t algo, } } -static inline int -dh_find_q(const gnutls_pk_params_st *pk_params, mpz_t q) -{ - gnutls_datum_t prime = { NULL, 0 }; - gnutls_datum_t generator = { NULL, 0 }; - uint8_t *data_q; - size_t n_q; - bigint_t _q; - int ret = 0; - - ret = _gnutls_mpi_dprint(pk_params->params[DSA_P], &prime); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - - ret = _gnutls_mpi_dprint(pk_params->params[DSA_G], &generator); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - - if (!_gnutls_dh_prime_match_fips_approved(prime.data, - prime.size, - generator.data, - generator.size, - &data_q, - &n_q)) { - ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - goto cleanup; - } - - if (_gnutls_mpi_init_scan_nz(&_q, data_q, n_q) != 0) { - ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); - goto cleanup; - } - - mpz_set(q, TOMPZ(_q)); - _gnutls_mpi_release(&_q); - - cleanup: - gnutls_free(prime.data); - gnutls_free(generator.data); - - return ret; -} - /* To generate a DH key either q must be set in the params or * level should be set to the number of required bits. */ @@ -2334,9 +2189,6 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, mpz_t x, y; int max_tries; unsigned have_q = 0; - mpz_t q; - mpz_t primesub1; - mpz_t ypowq; if (algo != params->algo) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); @@ -2354,10 +2206,6 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, mpz_init(x); mpz_init(y); - mpz_init(q); - mpz_init(primesub1); - mpz_init(ypowq); - max_tries = 3; do { if (have_q) { @@ -2389,40 +2237,8 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, ret = GNUTLS_E_LIB_IN_ERROR_STATE; goto dh_fail; } - } while(mpz_cmp_ui(y, 1) == 0); -#ifdef ENABLE_FIPS140 - if (_gnutls_fips_mode_enabled()) { - /* Perform FFC full public key validation checks - * according to SP800-56A (revision 3), 5.6.2.3.1. - */ - - /* Step 1: 2 <= y <= p - 2 */ - mpz_sub_ui(primesub1, pub.p, 1); - - if (mpz_cmp_ui(y, 2) < 0 || mpz_cmp(y, primesub1) >= 0) { - ret = gnutls_assert_val(GNUTLS_E_RANDOM_FAILED); - goto dh_fail; - } - - /* Step 2: 1 = y^q mod p */ - if (have_q) - mpz_set(q, pub.q); - else { - ret = dh_find_q(params, q); - if (ret < 0) - goto dh_fail; - } - - mpz_powm(ypowq, y, q, pub.p); - if (mpz_cmp_ui(ypowq, 1) != 0) { - ret = gnutls_assert_val(GNUTLS_E_RANDOM_FAILED); - goto dh_fail; - } - } -#endif - ret = _gnutls_mpi_init_multi(¶ms->params[DSA_Y], ¶ms->params[DSA_X], NULL); if (ret < 0) { gnutls_assert(); @@ -2439,9 +2255,6 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, mpz_clear(r); mpz_clear(x); mpz_clear(y); - mpz_clear(q); - mpz_clear(primesub1); - mpz_clear(ypowq); if (ret < 0) goto fail; @@ -2581,10 +2394,6 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, struct ecc_scalar key; struct ecc_point pub; const struct ecc_curve *curve; - struct ecc_scalar n; - struct ecc_scalar m; - struct ecc_point r; - mpz_t x, y, xx, yy, nn, mm; curve = get_supported_nist_curve(level); if (curve == NULL) @@ -2592,18 +2401,8 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, gnutls_assert_val (GNUTLS_E_ECC_UNSUPPORTED_CURVE); - mpz_init(x); - mpz_init(y); - mpz_init(xx); - mpz_init(yy); - mpz_init(nn); - mpz_init(mm); - ecc_scalar_init(&key, curve); ecc_point_init(&pub, curve); - ecc_scalar_init(&n, curve); - ecc_scalar_init(&m, curve); - ecc_point_init(&r, curve); ecdsa_generate_keypair(&pub, &key, NULL, rnd_func); if (HAVE_LIB_ERROR()) { @@ -2621,105 +2420,15 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, params->curve = level; params->params_nr = ECC_PRIVATE_PARAMS; - ecc_point_get(&pub, x, y); - -#ifdef ENABLE_FIPS140 - if (_gnutls_fips_mode_enabled()) { - /* Perform ECC full public key validation checks - * according to SP800-56A (revision 3), 5.6.2.3.3. - */ - - const char *order, *modulus; - - /* Step 1: verify that Q is not an identity - * element (an infinity point). Note that this - * cannot happen in the nettle implementation, - * because it cannot represent an infinity point - * on curves. */ - if (mpz_cmp_ui(x, 0) == 0 && mpz_cmp_ui(y, 0) == 0) { - ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); - goto ecc_fail; - } - - /* Step 2: verify that both coordinates of Q are - * in the range [0, p - 1]. - * - * Step 3: verify that Q lie on the curve - * - * Both checks are performed in nettle. */ - if (!ecc_point_set(&r, x, y)) { - ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); - goto ecc_fail; - } - - /* Step 4: verify that n * Q, where n is the - * curve order, result in an identity element - * - * Since nettle internally cannot represent an - * identity element on curves, we validate this - * instead: - * - * (n - 1) * Q = -Q - * - * That effectively means: n * Q = -Q + Q = O - */ - order = get_supported_nist_curve_order(level); - if (unlikely(order == NULL)) { - ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); - goto ecc_fail; - } - - ret = mpz_set_str(nn, order, 16); - if (unlikely(ret < 0)) { - ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); - goto ecc_fail; - } - - modulus = get_supported_nist_curve_modulus(level); - if (unlikely(modulus == NULL)) { - ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); - goto ecc_fail; - } - - ret = mpz_set_str(mm, modulus, 16); - if (unlikely(ret < 0)) { - ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); - goto ecc_fail; - } - - /* (n - 1) * Q = -Q */ - mpz_sub_ui (nn, nn, 1); - ecc_scalar_set(&n, nn); - ecc_point_mul(&r, &n, &r); - ecc_point_get(&r, xx, yy); - mpz_sub (mm, mm, y); - - if (mpz_cmp(xx, x) != 0 || mpz_cmp(yy, mm) != 0) { - ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); - goto ecc_fail; - } - } -#endif - - mpz_set(TOMPZ(params->params[ECC_X]), x); - mpz_set(TOMPZ(params->params[ECC_Y]), y); - + ecc_point_get(&pub, TOMPZ(params->params[ECC_X]), + TOMPZ(params->params[ECC_Y])); ecc_scalar_get(&key, TOMPZ(params->params[ECC_K])); ret = 0; ecc_fail: - mpz_clear(x); - mpz_clear(y); - mpz_clear(xx); - mpz_clear(yy); - mpz_clear(nn); - mpz_clear(mm); ecc_point_clear(&pub); ecc_scalar_clear(&key); - ecc_point_clear(&r); - ecc_scalar_clear(&n); - ecc_scalar_clear(&m); if (ret < 0) goto fail; diff --git a/lib/tls13/finished.c b/lib/tls13/finished.c index 4cc1a84..35ab87f 100644 --- a/lib/tls13/finished.c +++ b/lib/tls13/finished.c @@ -112,7 +112,7 @@ int _gnutls13_recv_finished(gnutls_session_t session) #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) # warning This is unsafe for production builds #else - if (gnutls_memcmp(verifier, buf.data, buf.length) != 0) { + if (safe_memcmp(verifier, buf.data, buf.length) != 0) { gnutls_assert(); ret = GNUTLS_E_ERROR_IN_FINISHED_PACKET; goto cleanup; diff --git a/lib/x509/x509.c b/lib/x509/x509.c index 2b68fe4..2091f3a 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -360,8 +360,7 @@ static int compare_sig_algorithm(gnutls_x509_crt_t cert) } if (empty1 != empty2 || - sp1.size != sp2.size || - (sp1.size > 0 && memcmp(sp1.data, sp2.data, sp1.size) != 0)) { + sp1.size != sp2.size || safe_memcmp(sp1.data, sp2.data, sp1.size) != 0) { gnutls_assert(); ret = GNUTLS_E_CERTIFICATE_ERROR; goto cleanup; diff --git a/src/libopts/ag-char-map.h b/src/libopts/ag-char-map.h new file mode 100644 index 0000000..cced230 --- /dev/null +++ b/src/libopts/ag-char-map.h @@ -0,0 +1,526 @@ +/* + * 29 bits for 46 character classifications + * generated by char-mapper on 08/26/18 at 10:44:22 + * + * This file contains the character classifications + * used by AutoGen and AutoOpts for identifying tokens. + * The table is static scope, so %guard is empty. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ +#ifndef AG_CHAR_MAP_H_GUARD +#define AG_CHAR_MAP_H_GUARD 1 + +#ifdef HAVE_CONFIG_H +# if defined(HAVE_INTTYPES_H) +# include + +# elif defined(HAVE_STDINT_H) +# include + +# elif !defined(HAVE_UINT32_T) +# if SIZEOF_INT == 4 + typedef unsigned int uint32_t; +# elif SIZEOF_LONG == 4 + typedef unsigned long uint32_t; +# endif +# endif /* HAVE_*INT*_H header */ + +#else /* not HAVE_CONFIG_H -- */ +# include +#endif /* HAVE_CONFIG_H */ + +#if 0 /* mapping specification source (from autogen.map) */ +// +// %guard +// %file ag-char-map.h +// %backup +// %optimize +// +// %comment -- see above +// % +// +// newline "\n" +// nul-byte "\x00" +// dir-sep "/\\" +// percent "%" +// comma "," +// colon ":" +// underscore "_" +// plus "+" +// dollar "$" +// option-marker "-" +// +// horiz-white "\t " +// alt-white "\v\f\r\b" +// whitespace +horiz-white +newline +alt-white +// non-nl-white +horiz-white +alt-white +// quote "'\"" +// parentheses "()" +// +// graphic "!-~" +// inversion "~-" +// oct-digit "0-7" +// dec-digit "89" +oct-digit +// hex-digit "a-fA-F" +dec-digit +// lower-case "a-z" +// upper-case "A-Z" +// alphabetic +lower-case +upper-case +// alphanumeric +alphabetic +dec-digit +// var-first +underscore +alphabetic +// variable-name +var-first +dec-digit +// option-name "^-" +variable-name +// value-name +colon +option-name +// name-sep "[.]" +// compound-name +value-name +name-sep +horiz-white +// scheme-note +parentheses +quote +// +// unquotable "!-~" -"#,;<=>[\\]`{}?*" -quote -parentheses +// end-xml-token "/>" +whitespace +// plus-n-space +plus +whitespace +// punctuation "!-~" -alphanumeric -"_" +// suffix "-._" +alphanumeric +// suffix-fmt +percent +suffix +dir-sep +// false-type "nNfF0" +nul-byte +// file-name +dir-sep +suffix +// end-token +nul-byte +whitespace +// end-list-entry +comma +end-token +// set-separator "|+-!" +end-list-entry +// signed-number +inversion +dec-digit +// make-script +dollar +newline +// load-line-skip +horiz-white +option-marker +// +#endif /* 0 -- mapping spec. source */ + + +typedef uint32_t ag_char_map_mask_t; + +#define IS_NEWLINE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000001) +#define SPN_NEWLINE_CHARS(_s) spn_ag_char_map_chars(_s, 0) +#define BRK_NEWLINE_CHARS(_s) brk_ag_char_map_chars(_s, 0) +#define SPN_NEWLINE_BACK(s,e) spn_ag_char_map_back(s, e, 0) +#define BRK_NEWLINE_BACK(s,e) brk_ag_char_map_back(s, e, 0) +#define IS_NUL_BYTE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000002) +#define SPN_NUL_BYTE_CHARS(_s) spn_ag_char_map_chars(_s, 1) +#define BRK_NUL_BYTE_CHARS(_s) brk_ag_char_map_chars(_s, 1) +#define SPN_NUL_BYTE_BACK(s,e) spn_ag_char_map_back(s, e, 1) +#define BRK_NUL_BYTE_BACK(s,e) brk_ag_char_map_back(s, e, 1) +#define IS_DIR_SEP_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000004) +#define SPN_DIR_SEP_CHARS(_s) spn_ag_char_map_chars(_s, 2) +#define BRK_DIR_SEP_CHARS(_s) brk_ag_char_map_chars(_s, 2) +#define SPN_DIR_SEP_BACK(s,e) spn_ag_char_map_back(s, e, 2) +#define BRK_DIR_SEP_BACK(s,e) brk_ag_char_map_back(s, e, 2) +#define IS_PERCENT_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000008) +#define SPN_PERCENT_CHARS(_s) spn_ag_char_map_chars(_s, 3) +#define BRK_PERCENT_CHARS(_s) brk_ag_char_map_chars(_s, 3) +#define SPN_PERCENT_BACK(s,e) spn_ag_char_map_back(s, e, 3) +#define BRK_PERCENT_BACK(s,e) brk_ag_char_map_back(s, e, 3) +#define IS_COMMA_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000010) +#define SPN_COMMA_CHARS(_s) spn_ag_char_map_chars(_s, 4) +#define BRK_COMMA_CHARS(_s) brk_ag_char_map_chars(_s, 4) +#define SPN_COMMA_BACK(s,e) spn_ag_char_map_back(s, e, 4) +#define BRK_COMMA_BACK(s,e) brk_ag_char_map_back(s, e, 4) +#define IS_COLON_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000020) +#define SPN_COLON_CHARS(_s) spn_ag_char_map_chars(_s, 5) +#define BRK_COLON_CHARS(_s) brk_ag_char_map_chars(_s, 5) +#define SPN_COLON_BACK(s,e) spn_ag_char_map_back(s, e, 5) +#define BRK_COLON_BACK(s,e) brk_ag_char_map_back(s, e, 5) +#define IS_UNDERSCORE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000040) +#define SPN_UNDERSCORE_CHARS(_s) spn_ag_char_map_chars(_s, 6) +#define BRK_UNDERSCORE_CHARS(_s) brk_ag_char_map_chars(_s, 6) +#define SPN_UNDERSCORE_BACK(s,e) spn_ag_char_map_back(s, e, 6) +#define BRK_UNDERSCORE_BACK(s,e) brk_ag_char_map_back(s, e, 6) +#define IS_PLUS_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000080) +#define SPN_PLUS_CHARS(_s) spn_ag_char_map_chars(_s, 7) +#define BRK_PLUS_CHARS(_s) brk_ag_char_map_chars(_s, 7) +#define SPN_PLUS_BACK(s,e) spn_ag_char_map_back(s, e, 7) +#define BRK_PLUS_BACK(s,e) brk_ag_char_map_back(s, e, 7) +#define IS_DOLLAR_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000100) +#define SPN_DOLLAR_CHARS(_s) spn_ag_char_map_chars(_s, 8) +#define BRK_DOLLAR_CHARS(_s) brk_ag_char_map_chars(_s, 8) +#define SPN_DOLLAR_BACK(s,e) spn_ag_char_map_back(s, e, 8) +#define BRK_DOLLAR_BACK(s,e) brk_ag_char_map_back(s, e, 8) +#define IS_OPTION_MARKER_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000200) +#define SPN_OPTION_MARKER_CHARS(_s) spn_ag_char_map_chars(_s, 9) +#define BRK_OPTION_MARKER_CHARS(_s) brk_ag_char_map_chars(_s, 9) +#define SPN_OPTION_MARKER_BACK(s,e) spn_ag_char_map_back(s, e, 9) +#define BRK_OPTION_MARKER_BACK(s,e) brk_ag_char_map_back(s, e, 9) +#define IS_HORIZ_WHITE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000400) +#define SPN_HORIZ_WHITE_CHARS(_s) spn_ag_char_map_chars(_s, 10) +#define BRK_HORIZ_WHITE_CHARS(_s) brk_ag_char_map_chars(_s, 10) +#define SPN_HORIZ_WHITE_BACK(s,e) spn_ag_char_map_back(s, e, 10) +#define BRK_HORIZ_WHITE_BACK(s,e) brk_ag_char_map_back(s, e, 10) +#define IS_ALT_WHITE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000800) +#define SPN_ALT_WHITE_CHARS(_s) spn_ag_char_map_chars(_s, 11) +#define BRK_ALT_WHITE_CHARS(_s) brk_ag_char_map_chars(_s, 11) +#define SPN_ALT_WHITE_BACK(s,e) spn_ag_char_map_back(s, e, 11) +#define BRK_ALT_WHITE_BACK(s,e) brk_ag_char_map_back(s, e, 11) +#define IS_WHITESPACE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000C01) +#define SPN_WHITESPACE_CHARS(_s) spn_ag_char_map_chars(_s, 12) +#define BRK_WHITESPACE_CHARS(_s) brk_ag_char_map_chars(_s, 12) +#define SPN_WHITESPACE_BACK(s,e) spn_ag_char_map_back(s, e, 12) +#define BRK_WHITESPACE_BACK(s,e) brk_ag_char_map_back(s, e, 12) +#define IS_NON_NL_WHITE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000C00) +#define SPN_NON_NL_WHITE_CHARS(_s) spn_ag_char_map_chars(_s, 13) +#define BRK_NON_NL_WHITE_CHARS(_s) brk_ag_char_map_chars(_s, 13) +#define SPN_NON_NL_WHITE_BACK(s,e) spn_ag_char_map_back(s, e, 13) +#define BRK_NON_NL_WHITE_BACK(s,e) brk_ag_char_map_back(s, e, 13) +#define IS_QUOTE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00001000) +#define SPN_QUOTE_CHARS(_s) spn_ag_char_map_chars(_s, 14) +#define BRK_QUOTE_CHARS(_s) brk_ag_char_map_chars(_s, 14) +#define SPN_QUOTE_BACK(s,e) spn_ag_char_map_back(s, e, 14) +#define BRK_QUOTE_BACK(s,e) brk_ag_char_map_back(s, e, 14) +#define IS_PARENTHESES_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00002000) +#define SPN_PARENTHESES_CHARS(_s) spn_ag_char_map_chars(_s, 15) +#define BRK_PARENTHESES_CHARS(_s) brk_ag_char_map_chars(_s, 15) +#define SPN_PARENTHESES_BACK(s,e) spn_ag_char_map_back(s, e, 15) +#define BRK_PARENTHESES_BACK(s,e) brk_ag_char_map_back(s, e, 15) +#define IS_GRAPHIC_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00004000) +#define SPN_GRAPHIC_CHARS(_s) spn_ag_char_map_chars(_s, 16) +#define BRK_GRAPHIC_CHARS(_s) brk_ag_char_map_chars(_s, 16) +#define SPN_GRAPHIC_BACK(s,e) spn_ag_char_map_back(s, e, 16) +#define BRK_GRAPHIC_BACK(s,e) brk_ag_char_map_back(s, e, 16) +#define IS_INVERSION_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00008000) +#define SPN_INVERSION_CHARS(_s) spn_ag_char_map_chars(_s, 17) +#define BRK_INVERSION_CHARS(_s) brk_ag_char_map_chars(_s, 17) +#define SPN_INVERSION_BACK(s,e) spn_ag_char_map_back(s, e, 17) +#define BRK_INVERSION_BACK(s,e) brk_ag_char_map_back(s, e, 17) +#define IS_OCT_DIGIT_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00010000) +#define SPN_OCT_DIGIT_CHARS(_s) spn_ag_char_map_chars(_s, 18) +#define BRK_OCT_DIGIT_CHARS(_s) brk_ag_char_map_chars(_s, 18) +#define SPN_OCT_DIGIT_BACK(s,e) spn_ag_char_map_back(s, e, 18) +#define BRK_OCT_DIGIT_BACK(s,e) brk_ag_char_map_back(s, e, 18) +#define IS_DEC_DIGIT_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00030000) +#define SPN_DEC_DIGIT_CHARS(_s) spn_ag_char_map_chars(_s, 19) +#define BRK_DEC_DIGIT_CHARS(_s) brk_ag_char_map_chars(_s, 19) +#define SPN_DEC_DIGIT_BACK(s,e) spn_ag_char_map_back(s, e, 19) +#define BRK_DEC_DIGIT_BACK(s,e) brk_ag_char_map_back(s, e, 19) +#define IS_HEX_DIGIT_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00070000) +#define SPN_HEX_DIGIT_CHARS(_s) spn_ag_char_map_chars(_s, 20) +#define BRK_HEX_DIGIT_CHARS(_s) brk_ag_char_map_chars(_s, 20) +#define SPN_HEX_DIGIT_BACK(s,e) spn_ag_char_map_back(s, e, 20) +#define BRK_HEX_DIGIT_BACK(s,e) brk_ag_char_map_back(s, e, 20) +#define IS_LOWER_CASE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00080000) +#define SPN_LOWER_CASE_CHARS(_s) spn_ag_char_map_chars(_s, 21) +#define BRK_LOWER_CASE_CHARS(_s) brk_ag_char_map_chars(_s, 21) +#define SPN_LOWER_CASE_BACK(s,e) spn_ag_char_map_back(s, e, 21) +#define BRK_LOWER_CASE_BACK(s,e) brk_ag_char_map_back(s, e, 21) +#define IS_UPPER_CASE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00100000) +#define SPN_UPPER_CASE_CHARS(_s) spn_ag_char_map_chars(_s, 22) +#define BRK_UPPER_CASE_CHARS(_s) brk_ag_char_map_chars(_s, 22) +#define SPN_UPPER_CASE_BACK(s,e) spn_ag_char_map_back(s, e, 22) +#define BRK_UPPER_CASE_BACK(s,e) brk_ag_char_map_back(s, e, 22) +#define IS_ALPHABETIC_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00180000) +#define SPN_ALPHABETIC_CHARS(_s) spn_ag_char_map_chars(_s, 23) +#define BRK_ALPHABETIC_CHARS(_s) brk_ag_char_map_chars(_s, 23) +#define SPN_ALPHABETIC_BACK(s,e) spn_ag_char_map_back(s, e, 23) +#define BRK_ALPHABETIC_BACK(s,e) brk_ag_char_map_back(s, e, 23) +#define IS_ALPHANUMERIC_CHAR( _c) is_ag_char_map_char((char)(_c), 0x001B0000) +#define SPN_ALPHANUMERIC_CHARS(_s) spn_ag_char_map_chars(_s, 24) +#define BRK_ALPHANUMERIC_CHARS(_s) brk_ag_char_map_chars(_s, 24) +#define SPN_ALPHANUMERIC_BACK(s,e) spn_ag_char_map_back(s, e, 24) +#define BRK_ALPHANUMERIC_BACK(s,e) brk_ag_char_map_back(s, e, 24) +#define IS_VAR_FIRST_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00180040) +#define SPN_VAR_FIRST_CHARS(_s) spn_ag_char_map_chars(_s, 25) +#define BRK_VAR_FIRST_CHARS(_s) brk_ag_char_map_chars(_s, 25) +#define SPN_VAR_FIRST_BACK(s,e) spn_ag_char_map_back(s, e, 25) +#define BRK_VAR_FIRST_BACK(s,e) brk_ag_char_map_back(s, e, 25) +#define IS_VARIABLE_NAME_CHAR( _c) is_ag_char_map_char((char)(_c), 0x001B0040) +#define SPN_VARIABLE_NAME_CHARS(_s) spn_ag_char_map_chars(_s, 26) +#define BRK_VARIABLE_NAME_CHARS(_s) brk_ag_char_map_chars(_s, 26) +#define SPN_VARIABLE_NAME_BACK(s,e) spn_ag_char_map_back(s, e, 26) +#define BRK_VARIABLE_NAME_BACK(s,e) brk_ag_char_map_back(s, e, 26) +#define IS_OPTION_NAME_CHAR( _c) is_ag_char_map_char((char)(_c), 0x003B0040) +#define SPN_OPTION_NAME_CHARS(_s) spn_ag_char_map_chars(_s, 27) +#define BRK_OPTION_NAME_CHARS(_s) brk_ag_char_map_chars(_s, 27) +#define SPN_OPTION_NAME_BACK(s,e) spn_ag_char_map_back(s, e, 27) +#define BRK_OPTION_NAME_BACK(s,e) brk_ag_char_map_back(s, e, 27) +#define IS_VALUE_NAME_CHAR( _c) is_ag_char_map_char((char)(_c), 0x003B0060) +#define SPN_VALUE_NAME_CHARS(_s) spn_ag_char_map_chars(_s, 28) +#define BRK_VALUE_NAME_CHARS(_s) brk_ag_char_map_chars(_s, 28) +#define SPN_VALUE_NAME_BACK(s,e) spn_ag_char_map_back(s, e, 28) +#define BRK_VALUE_NAME_BACK(s,e) brk_ag_char_map_back(s, e, 28) +#define IS_NAME_SEP_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00400000) +#define SPN_NAME_SEP_CHARS(_s) spn_ag_char_map_chars(_s, 29) +#define BRK_NAME_SEP_CHARS(_s) brk_ag_char_map_chars(_s, 29) +#define SPN_NAME_SEP_BACK(s,e) spn_ag_char_map_back(s, e, 29) +#define BRK_NAME_SEP_BACK(s,e) brk_ag_char_map_back(s, e, 29) +#define IS_COMPOUND_NAME_CHAR( _c) is_ag_char_map_char((char)(_c), 0x007B0460) +#define SPN_COMPOUND_NAME_CHARS(_s) spn_ag_char_map_chars(_s, 30) +#define BRK_COMPOUND_NAME_CHARS(_s) brk_ag_char_map_chars(_s, 30) +#define SPN_COMPOUND_NAME_BACK(s,e) spn_ag_char_map_back(s, e, 30) +#define BRK_COMPOUND_NAME_BACK(s,e) brk_ag_char_map_back(s, e, 30) +#define IS_SCHEME_NOTE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00003000) +#define SPN_SCHEME_NOTE_CHARS(_s) spn_ag_char_map_chars(_s, 31) +#define BRK_SCHEME_NOTE_CHARS(_s) brk_ag_char_map_chars(_s, 31) +#define SPN_SCHEME_NOTE_BACK(s,e) spn_ag_char_map_back(s, e, 31) +#define BRK_SCHEME_NOTE_BACK(s,e) brk_ag_char_map_back(s, e, 31) +#define IS_UNQUOTABLE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00800000) +#define SPN_UNQUOTABLE_CHARS(_s) spn_ag_char_map_chars(_s, 32) +#define BRK_UNQUOTABLE_CHARS(_s) brk_ag_char_map_chars(_s, 32) +#define SPN_UNQUOTABLE_BACK(s,e) spn_ag_char_map_back(s, e, 32) +#define BRK_UNQUOTABLE_BACK(s,e) brk_ag_char_map_back(s, e, 32) +#define IS_END_XML_TOKEN_CHAR( _c) is_ag_char_map_char((char)(_c), 0x01000C01) +#define SPN_END_XML_TOKEN_CHARS(_s) spn_ag_char_map_chars(_s, 33) +#define BRK_END_XML_TOKEN_CHARS(_s) brk_ag_char_map_chars(_s, 33) +#define SPN_END_XML_TOKEN_BACK(s,e) spn_ag_char_map_back(s, e, 33) +#define BRK_END_XML_TOKEN_BACK(s,e) brk_ag_char_map_back(s, e, 33) +#define IS_PLUS_N_SPACE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000C81) +#define SPN_PLUS_N_SPACE_CHARS(_s) spn_ag_char_map_chars(_s, 34) +#define BRK_PLUS_N_SPACE_CHARS(_s) brk_ag_char_map_chars(_s, 34) +#define SPN_PLUS_N_SPACE_BACK(s,e) spn_ag_char_map_back(s, e, 34) +#define BRK_PLUS_N_SPACE_BACK(s,e) brk_ag_char_map_back(s, e, 34) +#define IS_PUNCTUATION_CHAR( _c) is_ag_char_map_char((char)(_c), 0x02000000) +#define SPN_PUNCTUATION_CHARS(_s) spn_ag_char_map_chars(_s, 35) +#define BRK_PUNCTUATION_CHARS(_s) brk_ag_char_map_chars(_s, 35) +#define SPN_PUNCTUATION_BACK(s,e) spn_ag_char_map_back(s, e, 35) +#define BRK_PUNCTUATION_BACK(s,e) brk_ag_char_map_back(s, e, 35) +#define IS_SUFFIX_CHAR( _c) is_ag_char_map_char((char)(_c), 0x041B0000) +#define SPN_SUFFIX_CHARS(_s) spn_ag_char_map_chars(_s, 36) +#define BRK_SUFFIX_CHARS(_s) brk_ag_char_map_chars(_s, 36) +#define SPN_SUFFIX_BACK(s,e) spn_ag_char_map_back(s, e, 36) +#define BRK_SUFFIX_BACK(s,e) brk_ag_char_map_back(s, e, 36) +#define IS_SUFFIX_FMT_CHAR( _c) is_ag_char_map_char((char)(_c), 0x041B000C) +#define SPN_SUFFIX_FMT_CHARS(_s) spn_ag_char_map_chars(_s, 37) +#define BRK_SUFFIX_FMT_CHARS(_s) brk_ag_char_map_chars(_s, 37) +#define SPN_SUFFIX_FMT_BACK(s,e) spn_ag_char_map_back(s, e, 37) +#define BRK_SUFFIX_FMT_BACK(s,e) brk_ag_char_map_back(s, e, 37) +#define IS_FALSE_TYPE_CHAR( _c) is_ag_char_map_char((char)(_c), 0x08000002) +#define SPN_FALSE_TYPE_CHARS(_s) spn_ag_char_map_chars(_s, 38) +#define BRK_FALSE_TYPE_CHARS(_s) brk_ag_char_map_chars(_s, 38) +#define SPN_FALSE_TYPE_BACK(s,e) spn_ag_char_map_back(s, e, 38) +#define BRK_FALSE_TYPE_BACK(s,e) brk_ag_char_map_back(s, e, 38) +#define IS_FILE_NAME_CHAR( _c) is_ag_char_map_char((char)(_c), 0x041B0004) +#define SPN_FILE_NAME_CHARS(_s) spn_ag_char_map_chars(_s, 39) +#define BRK_FILE_NAME_CHARS(_s) brk_ag_char_map_chars(_s, 39) +#define SPN_FILE_NAME_BACK(s,e) spn_ag_char_map_back(s, e, 39) +#define BRK_FILE_NAME_BACK(s,e) brk_ag_char_map_back(s, e, 39) +#define IS_END_TOKEN_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000C03) +#define SPN_END_TOKEN_CHARS(_s) spn_ag_char_map_chars(_s, 40) +#define BRK_END_TOKEN_CHARS(_s) brk_ag_char_map_chars(_s, 40) +#define SPN_END_TOKEN_BACK(s,e) spn_ag_char_map_back(s, e, 40) +#define BRK_END_TOKEN_BACK(s,e) brk_ag_char_map_back(s, e, 40) +#define IS_END_LIST_ENTRY_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000C13) +#define SPN_END_LIST_ENTRY_CHARS(_s) spn_ag_char_map_chars(_s, 41) +#define BRK_END_LIST_ENTRY_CHARS(_s) brk_ag_char_map_chars(_s, 41) +#define SPN_END_LIST_ENTRY_BACK(s,e) spn_ag_char_map_back(s, e, 41) +#define BRK_END_LIST_ENTRY_BACK(s,e) brk_ag_char_map_back(s, e, 41) +#define IS_SET_SEPARATOR_CHAR( _c) is_ag_char_map_char((char)(_c), 0x10000C13) +#define SPN_SET_SEPARATOR_CHARS(_s) spn_ag_char_map_chars(_s, 42) +#define BRK_SET_SEPARATOR_CHARS(_s) brk_ag_char_map_chars(_s, 42) +#define SPN_SET_SEPARATOR_BACK(s,e) spn_ag_char_map_back(s, e, 42) +#define BRK_SET_SEPARATOR_BACK(s,e) brk_ag_char_map_back(s, e, 42) +#define IS_SIGNED_NUMBER_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00038000) +#define SPN_SIGNED_NUMBER_CHARS(_s) spn_ag_char_map_chars(_s, 43) +#define BRK_SIGNED_NUMBER_CHARS(_s) brk_ag_char_map_chars(_s, 43) +#define SPN_SIGNED_NUMBER_BACK(s,e) spn_ag_char_map_back(s, e, 43) +#define BRK_SIGNED_NUMBER_BACK(s,e) brk_ag_char_map_back(s, e, 43) +#define IS_MAKE_SCRIPT_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000101) +#define SPN_MAKE_SCRIPT_CHARS(_s) spn_ag_char_map_chars(_s, 44) +#define BRK_MAKE_SCRIPT_CHARS(_s) brk_ag_char_map_chars(_s, 44) +#define SPN_MAKE_SCRIPT_BACK(s,e) spn_ag_char_map_back(s, e, 44) +#define BRK_MAKE_SCRIPT_BACK(s,e) brk_ag_char_map_back(s, e, 44) +#define IS_LOAD_LINE_SKIP_CHAR( _c) is_ag_char_map_char((char)(_c), 0x00000600) +#define SPN_LOAD_LINE_SKIP_CHARS(_s) spn_ag_char_map_chars(_s, 45) +#define BRK_LOAD_LINE_SKIP_CHARS(_s) brk_ag_char_map_chars(_s, 45) +#define SPN_LOAD_LINE_SKIP_BACK(s,e) spn_ag_char_map_back(s, e, 45) +#define BRK_LOAD_LINE_SKIP_BACK(s,e) brk_ag_char_map_back(s, e, 45) + +static ag_char_map_mask_t const ag_char_map_table[128] = { + /*NUL*/ 0x00000002, /*x01*/ 0x00000000, /*x02*/ 0x00000000, /*x03*/ 0x00000000, + /*x04*/ 0x00000000, /*x05*/ 0x00000000, /*x06*/ 0x00000000, /*BEL*/ 0x00000000, + /* BS*/ 0x00000800, /* HT*/ 0x00000400, /* NL*/ 0x00000001, /* VT*/ 0x00000800, + /* FF*/ 0x00000800, /* CR*/ 0x00000800, /*x0E*/ 0x00000000, /*x0F*/ 0x00000000, + /*x10*/ 0x00000000, /*x11*/ 0x00000000, /*x12*/ 0x00000000, /*x13*/ 0x00000000, + /*x14*/ 0x00000000, /*x15*/ 0x00000000, /*x16*/ 0x00000000, /*x17*/ 0x00000000, + /*x18*/ 0x00000000, /*x19*/ 0x00000000, /*x1A*/ 0x00000000, /*ESC*/ 0x00000000, + /*x1C*/ 0x00000000, /*x1D*/ 0x00000000, /*x1E*/ 0x00000000, /*x1F*/ 0x00000000, + /* */ 0x00000400, /* ! */ 0x02804000, /* " */ 0x02005000, /* # */ 0x02004000, + /* $ */ 0x02804100, /* % */ 0x02804008, /* & */ 0x02804000, /* ' */ 0x02005000, + /* ( */ 0x02006000, /* ) */ 0x02006000, /* * */ 0x02004000, /* + */ 0x12804080, + /* , */ 0x02004010, /* - */ 0x06A0C200, /* . */ 0x06C04000, /* / */ 0x03804004, + /* 0 */ 0x08814000, /* 1 */ 0x00814000, /* 2 */ 0x00814000, /* 3 */ 0x00814000, + /* 4 */ 0x00814000, /* 5 */ 0x00814000, /* 6 */ 0x00814000, /* 7 */ 0x00814000, + /* 8 */ 0x00824000, /* 9 */ 0x00824000, /* : */ 0x02804020, /* ; */ 0x02004000, + /* < */ 0x02004000, /* = */ 0x02004000, /* > */ 0x03004000, /* ? */ 0x02004000, + /* @ */ 0x02804000, /* A */ 0x00944000, /* B */ 0x00944000, /* C */ 0x00944000, + /* D */ 0x00944000, /* E */ 0x00944000, /* F */ 0x08944000, /* G */ 0x00904000, + /* H */ 0x00904000, /* I */ 0x00904000, /* J */ 0x00904000, /* K */ 0x00904000, + /* L */ 0x00904000, /* M */ 0x00904000, /* N */ 0x08904000, /* O */ 0x00904000, + /* P */ 0x00904000, /* Q */ 0x00904000, /* R */ 0x00904000, /* S */ 0x00904000, + /* T */ 0x00904000, /* U */ 0x00904000, /* V */ 0x00904000, /* W */ 0x00904000, + /* X */ 0x00904000, /* Y */ 0x00904000, /* Z */ 0x00904000, /* [ */ 0x02404000, + /* \ */ 0x02004004, /* ] */ 0x02404000, /* ^ */ 0x02A04000, /* _ */ 0x04804040, + /* ` */ 0x02004000, /* a */ 0x008C4000, /* b */ 0x008C4000, /* c */ 0x008C4000, + /* d */ 0x008C4000, /* e */ 0x008C4000, /* f */ 0x088C4000, /* g */ 0x00884000, + /* h */ 0x00884000, /* i */ 0x00884000, /* j */ 0x00884000, /* k */ 0x00884000, + /* l */ 0x00884000, /* m */ 0x00884000, /* n */ 0x08884000, /* o */ 0x00884000, + /* p */ 0x00884000, /* q */ 0x00884000, /* r */ 0x00884000, /* s */ 0x00884000, + /* t */ 0x00884000, /* u */ 0x00884000, /* v */ 0x00884000, /* w */ 0x00884000, + /* x */ 0x00884000, /* y */ 0x00884000, /* z */ 0x00884000, /* { */ 0x02004000, + /* | */ 0x12804000, /* } */ 0x02004000, /* ~ */ 0x0280C000, /*x7F*/ 0x00000000 +}; + +#include +#include +#include + +#ifndef _ +# define _(_s) _s +#endif + +static unsigned char const * ag_char_map_spanners[46]; +/** + * Character category masks. Some categories may have multiple bits, + * if their definition incorporates other character categories. + * This mask array is only used by calc_ag_char_map_spanners(). + */ +static ag_char_map_mask_t const ag_char_map_masks[46] = { + 0x00000001, /* NEWLINE */ + 0x00000002, /* NUL_BYTE */ + 0x00000004, /* DIR_SEP */ + 0x00000008, /* PERCENT */ + 0x00000010, /* COMMA */ + 0x00000020, /* COLON */ + 0x00000040, /* UNDERSCORE */ + 0x00000080, /* PLUS */ + 0x00000100, /* DOLLAR */ + 0x00000200, /* OPTION_MARKER */ + 0x00000400, /* HORIZ_WHITE */ + 0x00000800, /* ALT_WHITE */ + 0x00000C01, /* WHITESPACE */ + 0x00000C00, /* NON_NL_WHITE */ + 0x00001000, /* QUOTE */ + 0x00002000, /* PARENTHESES */ + 0x00004000, /* GRAPHIC */ + 0x00008000, /* INVERSION */ + 0x00010000, /* OCT_DIGIT */ + 0x00030000, /* DEC_DIGIT */ + 0x00070000, /* HEX_DIGIT */ + 0x00080000, /* LOWER_CASE */ + 0x00100000, /* UPPER_CASE */ + 0x00180000, /* ALPHABETIC */ + 0x001B0000, /* ALPHANUMERIC */ + 0x00180040, /* VAR_FIRST */ + 0x001B0040, /* VARIABLE_NAME */ + 0x003B0040, /* OPTION_NAME */ + 0x003B0060, /* VALUE_NAME */ + 0x00400000, /* NAME_SEP */ + 0x007B0460, /* COMPOUND_NAME */ + 0x00003000, /* SCHEME_NOTE */ + 0x00800000, /* UNQUOTABLE */ + 0x01000C01, /* END_XML_TOKEN */ + 0x00000C81, /* PLUS_N_SPACE */ + 0x02000000, /* PUNCTUATION */ + 0x041B0000, /* SUFFIX */ + 0x041B000C, /* SUFFIX_FMT */ + 0x08000002, /* FALSE_TYPE */ + 0x041B0004, /* FILE_NAME */ + 0x00000C03, /* END_TOKEN */ + 0x00000C13, /* END_LIST_ENTRY */ + 0x10000C13, /* SET_SEPARATOR */ + 0x00038000, /* SIGNED_NUMBER */ + 0x00000101, /* MAKE_SCRIPT */ + 0x00000600, /* LOAD_LINE_SKIP */ +}; +#undef LOCK_SPANNER_TABLES + +static unsigned char const * +calc_ag_char_map_spanners(unsigned int mask_ix) +{ +#ifdef LOCK_SPANNER_TABLES + if (ag_char_map_spanners[mask_ix] != NULL) + return ag_char_map_spanners[mask_ix]; + + pthread_mutex_lock(&ag_char_map_mutex); + if (ag_char_map_spanners[mask_ix] == NULL) +#endif + { + int ix = 1; + ag_char_map_mask_t mask = ag_char_map_masks[mask_ix]; + unsigned char * res = malloc(256 /* 1 << NBBY */); + if (res == NULL) { + fputs(_("no memory for char-mapper span map\n"), stderr); + exit(EXIT_FAILURE); + } + + memset(res, 0, 256); + for (; ix < 128; ix++) + if (ag_char_map_table[ix] & mask) + res[ix] = 1; + ag_char_map_spanners[mask_ix] = res; + } +#ifdef LOCK_SPANNER_TABLES + pthread_mutex_unlock(&ag_char_map_mutex); +#endif + return ag_char_map_spanners[mask_ix]; +} +#define ag_char_map_masks POISONED_ag_char_map_masks + +static inline int +is_ag_char_map_char(char ch, ag_char_map_mask_t mask) +{ + unsigned int ix = (unsigned char)ch; + return ((ix < 128) && ((ag_char_map_table[ix] & mask) != 0)); +} + +static inline char * +spn_ag_char_map_chars(char const * p, unsigned int mask_ix) +{ + unsigned char const * v = ag_char_map_spanners[mask_ix]; + if (v == NULL) + v = calc_ag_char_map_spanners(mask_ix); + while (v[(unsigned char)*p]) p++; + return (char *)(uintptr_t)p; +} + +static inline char * +brk_ag_char_map_chars(char const * p, unsigned int mask_ix) +{ + unsigned char const * v = ag_char_map_spanners[mask_ix]; + if (v == NULL) + v = calc_ag_char_map_spanners(mask_ix); + while ((*p != '\0') && (! v[(unsigned char)*p])) p++; + return (char *)(uintptr_t)p; +} + +static inline char * +spn_ag_char_map_back(char const * s, char const * e, unsigned int mask_ix) +{ + unsigned char const * v = ag_char_map_spanners[mask_ix]; + if (v == NULL) + v = calc_ag_char_map_spanners(mask_ix); + if (s >= e) e = s + strlen(s); + while ((e > s) && v[(unsigned char)e[-1]]) e--; + return (char *)(uintptr_t)e; +} + +static inline char * +brk_ag_char_map_back(char const * s, char const * e, unsigned int mask_ix) +{ + unsigned char const * v = ag_char_map_spanners[mask_ix]; + if (v == NULL) + v = calc_ag_char_map_spanners(mask_ix); + if (s == e) e += strlen(e); + while ((e > s) && (! v[(unsigned char)e[-1]])) e--; + return (char *)(uintptr_t)e; +} +#endif /* AG_CHAR_MAP_H_GUARD */ diff --git a/src/libopts/alias.c b/src/libopts/alias.c new file mode 100644 index 0000000..231f275 --- /dev/null +++ b/src/libopts/alias.c @@ -0,0 +1,116 @@ + +/** + * \file alias.c + * + * Handle options that are aliases for another option. + * + * @addtogroup autoopts + * @{ + */ +/* + * This routine will forward an option alias to the correct option code. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +static tSuccess +too_many_occurrences(tOptions * opts, tOptDesc * od) +{ + if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) { + char const * eqv = (od->optEquivIndex != NO_EQUIVALENT) ? zequiv : zNil; + + fprintf(stderr, ztoo_often_fmt, opts->pzProgName); + + if (od->optMaxCt > 1) + fprintf(stderr, zat_most, od->optMaxCt, od->pz_Name, eqv); + else + fprintf(stderr, zonly_one, od->pz_Name, eqv); + (*opts->pUsageProc)(opts, EXIT_FAILURE); + /* NOTREACHED */ + } + + return FAILURE; +} + +/*=export_func optionAlias + * private: + * + * what: relay an option to its alias + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + old_od + the descriptor for this arg + + * arg: + unsigned int + alias + the aliased-to option index + + * ret-type: int + * + * doc: + * Handle one option as if it had been specified as another. Exactly. + * Returns "-1" if the aliased-to option has appeared too many times. +=*/ +int +optionAlias(tOptions * opts, tOptDesc * old_od, unsigned int alias) +{ + tOptDesc * new_od; + + if (opts <= OPTPROC_EMIT_LIMIT) + return 0; + + new_od = opts->pOptDesc + alias; + if ((unsigned)opts->optCt <= alias) { + fputs(zbad_alias_id, stderr); + option_exits(EXIT_FAILURE); + } + + /* + * Copy over the option instance flags + */ + new_od->fOptState &= OPTST_PERSISTENT_MASK; + new_od->fOptState |= (old_od->fOptState & ~OPTST_PERSISTENT_MASK); + new_od->optArg.argString = old_od->optArg.argString; + + /* + * Keep track of count only for DEFINED (command line) options. + * IF we have too many, build up an error message and bail. + */ + if ( (new_od->fOptState & OPTST_DEFINED) + && (++new_od->optOccCt > new_od->optMaxCt) ) + return too_many_occurrences(opts, new_od); + + /* + * Clear the state bits and counters + */ + old_od->fOptState &= OPTST_PERSISTENT_MASK; + old_od->optOccCt = 0; + + /* + * If there is a procedure to call, call it + */ + if (new_od->pOptProc != NULL) + (*new_od->pOptProc)(opts, new_od); + return 0; +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/alias.c */ diff --git a/src/libopts/ao-strs.c b/src/libopts/ao-strs.c new file mode 100644 index 0000000..7f59372 --- /dev/null +++ b/src/libopts/ao-strs.c @@ -0,0 +1,379 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (ao-strs.c) + * + * It has been AutoGen-ed + * From the definitions ao-strs.def + * and the template file strings + * + * Copyright (C) 2011-2018 Bruce Korb, all rights reserved. + * This is free software. It is licensed for use, modification and + * redistribution under the terms of the + * Modified (3 clause) Berkeley Software Distribution License + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name ``Bruce Korb'' nor the name of any other + * contributor may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * strings IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "ao-strs.h" + +char const ao_strs_strtable[6714] = +/* 0 */ "-_^\0" +/* 4 */ " %s%s\n\0" +/* 12 */ "\n\0" +/* 64 */ "\n" + "%s\n\n\0" +/* 70 */ "=file\0" +/* 76 */ "=Mbr\0" +/* 81 */ "=Cplx\0" +/* 87 */ "[=arg]\0" +/* 94 */ "--%2$s%1$s\0" +/* 105 */ "=Tim\0" +/* 110 */ "none\0" +/* 115 */ "# preset/initialization file\n" + "# %s#\n\0" +/* 153 */ " %3s %-14s %s\0" +/* 167 */ "%s\0" +/* 170 */ "T/F\0" +/* 174 */ "\n" + "%s\n\n" + "%s\0" +/* 182 */ "Fil\0" +/* 186 */ "KWd\0" +/* 190 */ "Mbr\0" +/* 194 */ "Cpx\0" +/* 198 */ "no \0" +/* 202 */ "Num\0" +/* 206 */ "opt\0" +/* 210 */ "YES\0" +/* 214 */ "Str\0" +/* 218 */ "Tim\0" +/* 222 */ "\t\t\t\t- \0" +/* 229 */ "\t\t\t\t \0" +/* 236 */ "\t\t\t\t-- and \0" +/* 248 */ "\t\t\t\t%s\n\0" +/* 256 */ " \0" +/* 263 */ " \0" +/* 269 */ " \0" +/* 273 */ " \0" +/* 276 */ "all\0" +/* 280 */ " \t\n" + ":=\0" +/* 286 */ "%s_%s_%d=\0" +/* 296 */ "''\0" +/* 299 */ " ;;\n\n\0" +/* 312 */ "'\n\n\0" +/* 316 */ "\n\0" +/* 323 */ " %s\n\0" +/* 329 */ "%%-%ds\0" +/* 336 */ "\n" + "export %s_%s_%d\n\0" +/* 354 */ "false\0" +/* 360 */ " -* )\n\0" +/* 370 */ "flag\0" +/* 375 */ "INVALID-%d\0" +/* 386 */ "*INVALID*\0" +/* 396 */ "\\n\\\n\0" +/* 401 */ " --* )\n\0" +/* 412 */ "--\0" +/* 415 */ "LONGUSAGE\0" +/* 425 */ " %s\n\0" +/* 441 */ "\\%03o\0" +/* 447 */ "more\0" +/* 452 */ "<%s type=nested>\n\0" +/* 470 */ "%s\n\0" +/* 474 */ "%s\n" + " \0" +/* 480 */ "OPT_ARG_NEEDED=NO\0" +/* 498 */ "<%s/>\n\0" +/* 505 */ "OPT_ARG_NEEDED=OK\0" +/* 523 */ "\t\0" +/* 525 */ "<%s>\0" +/* 530 */ "option\0" +/* 537 */ "\n" + "export %s_%s\n\0" +/* 552 */ "%s_%s=\0" +/* 559 */ " | \0" +/* 563 */ "PAGER\0" +/* 569 */ "%1$s %2$s ; rm -f %2$s\0" +/* 592 */ " + \0" +/* 596 */ " puts(_(%s));\n\0" +/* 612 */ "\\'\0" +/* 615 */ "'%s'\0" +/* 620 */ " -- %s\0" +/* 627 */ "%s_%s_TEXT='\0" +/* 640 */ "#! %s\n\0" +/* 647 */ "\n" + "env | grep '^%s_'\n\0" +/* 667 */ "=%1$lu # 0x%1$lX\n\0" +/* 685 */ "stdout\0" +/* 692 */ "%A %B %e, %Y at %r %Z\0" +/* 714 */ "TMPDIR\0" +/* 721 */ "%s/use-%u.XXXXXX\0" +/* 738 */ "true\0" +/* 743 */ "<%s type=%s>\0" +/* 756 */ "VERSION\0" +/* 764 */ "#x%02X;\0" +/* 772 */ "OPT_ARG_NEEDED=YES\0" +/* 791 */ "\n" + "# %s -- %s\n\0" +/* 804 */ "# DEFAULT: \0" +/* 816 */ "'\\''\0" +/* 821 */ " '%s'\0" +/* 827 */ "libopts misguessed length of string\n\0" +/* 864 */ "\n" + "OPTION_CT=0\n\0" +/* 878 */ "set --\0" +/* 885 */ "/tmp\0" +/* 890 */ " ;;\n\n\0" +/* 907 */ " '%c' )\n\0" +/* 923 */ " '%s' )\n\0" +/* 939 */ " '%s' | \\\n\0" +/* 957 */ "<%1$s type=boolean>%2$s\n\0" +/* 989 */ "# From the %s option definitions\n" + "#\n\0" +/* 1026 */ "echo 'Warning: Cannot load options files' >&2\0" +/* 1073 */ "echo 'Warning: Cannot save options files' >&2\0" +/* 1120 */ "echo 'Warning: Cannot suppress the loading of options files' >&2\0" +/* 1186 */ "<%1$s type=integer>0x%2$lX\n\0" +/* 1221 */ "%1$s_%2$s_TEXT='no %2$s text'\n\0" +/* 1252 */ "%1$s_%2$s_MODE='%3$s'\n" + "export %1$s_%2$s_MODE\n\0" +/* 1297 */ "%1$s_%2$s='%3$s'\n" + "export %1$s_%2$s\n\0" +/* 1332 */ "%1$s_%2$s_CT=%3$d\n" + "export %1$s_%2$s_CT\n\0" +/* 1371 */ "OPTION_CT=%d\n" + "export OPTION_CT\n\0" +/* 1402 */ "%1$s_%2$s=%3$s\n" + "export %1$s_%2$s\n\0" +/* 1435 */ "%1$s_%2$s=%3$d # 0x%3$X\n" + "export %1$s_%2$s\n\0" +/* 1477 */ " case \"${OPT_CODE}\" in\n\0" +/* 1508 */ " if [ $%1$s_%2$s_CT -gt %3$u ] ; then\n" + " echo 'Error: more than %3$d %2$s options'\n" + " echo \"$%1$s_USAGE_TEXT\"\n" + " exit 1\n" + " fi >&2\n\0" +/* 1699 */ "test ${%1$s_%2$s_CT-0} -ge %3$u || {\n" + " echo %1$s_%2$s has not been set\n" + " exit 1\n" + "} 1>&2\n\0" +/* 1791 */ "test -n \"$%1$s_%2$s\" || {\n" + " echo %1$s_%2$s has not been set\n" + " exit 1\n" + "} 1>&2\n\0" +/* 1872 */ " echo \"$%s_%s_TEXT\"\n" + " exit 0\n\0" +/* 1923 */ "\n" + "# # # # # # # # # #\n" + "#\n" + "# END OF AUTOMATED OPTION PROCESSING\n" + "#\n" + "# # # # # # # # # # -- do not modify this marker --\n\0" +/* 2039 */ " if [ -n \"${OPT_ARG_VAL}\" ]\n" + " then\n" + " eval %1$s_${OPT_NAME}${OPT_ELEMENT}=\"'${OPT_ARG_VAL}'\"\n" + " export %1$s_${OPT_NAME}${OPT_ELEMENT}\n" + " fi\n" + "done\n" + "OPTION_COUNT=`expr $ARG_COUNT - $#`\n" + "OPERAND_COUNT=$#\n" + "unset OPT_PROCESS || :\n" + "unset OPT_ELEMENT || :\n" + "unset OPT_ARG || :\n" + "unset OPT_ARG_NEEDED || :\n" + "unset OPT_NAME || :\n" + "unset OPT_CODE || :\n" + "unset OPT_ARG_VAL || :\n\0" +/* 2418 */ " OPT_CODE=`echo \"X${OPT_ARG}\"|sed 's/^X-*//'`\n" + " shift\n" + " OPT_ARG=$1\n" + " case \"${OPT_CODE}\" in *=* )\n" + " OPT_ARG_VAL=`echo \"${OPT_CODE}\"|sed 's/^[^=]*=//'`\n" + " OPT_CODE=`echo \"${OPT_CODE}\"|sed 's/=.*$//'` ;; esac\n\0" +/* 2669 */ " OPT_CODE=`echo \"X${OPT_ARG}\" | sed 's/X-\\(.\\).*/\\1/'`\n" + " OPT_ARG=` echo \"X${OPT_ARG}\" | sed 's/X-.//'`\n\0" +/* 2786 */ "\n" + "ARG_COUNT=$#\n" + "OPT_PROCESS=true\n" + "OPT_ARG=$1\n" + "while ${OPT_PROCESS} && [ $# -gt 0 ]\n" + "do\n" + " OPT_ELEMENT=''\n" + " OPT_ARG_VAL=''\n\n" + " case \"${OPT_ARG}\" in\n" + " -- )\n" + " OPT_PROCESS=false\n" + " shift\n" + " ;;\n\0" +/* 2993 */ " case \"${OPT_ARG_NEEDED}\" in\n" + " NO )\n" + " OPT_ARG_VAL=''\n" + " ;;\n" + " YES )\n" + " if [ -z \"${OPT_ARG_VAL}\" ]\n" + " then\n" + " if [ $# -eq 0 ]\n" + " then\n" + " echo No argument provided for ${OPT_NAME} option\n" + " echo \"$%s_USAGE_TEXT\"\n" + " exit 1\n" + " fi >&2\n" + " OPT_ARG_VAL=${OPT_ARG}\n" + " shift\n" + " OPT_ARG=$1\n" + " fi\n" + " ;;\n" + " OK )\n" + " if [ -z \"${OPT_ARG_VAL}\" ] && [ $# -gt 0 ]\n" + " then\n" + " case \"${OPT_ARG}\" in -* ) ;; * )\n" + " OPT_ARG_VAL=${OPT_ARG}\n" + " shift\n" + " OPT_ARG=$1 ;; esac\n" + " fi\n" + " ;;\n" + " esac\n\0" +/* 3772 */ " %1$s_%2$s_CT=`expr ${%1$s_%2$s_CT} + 1`\n" + " OPT_ELEMENT=\"_${%1$s_%2$s_CT}\"\n" + " OPT_NAME='%2$s'\n\0" +/* 3896 */ "\n" + "if test -z \"${%1$s_%2$s}\"\n" + "then\n" + " %1$s_%2$s_CT=0\n" + " export %1$s_%2$s_CT\n" + "else\n" + " %1$s_%2$s_CT=1\n" + " %1$s_%2$s_1=${%1$s_%2$s}\n" + " export %1$s_%2$s_CT %1$s_%2$s_1\n" + "fi\n\0" +/* 4054 */ " * )\n" + " OPT_PROCESS=false\n" + " ;;\n" + " esac\n\0" +/* 4111 */ " %1$s_%2$s_CT=0\n" + " OPT_ELEMENT=''\n" + " %1$s_%2$s='%3$s'\n" + " export %1$s_%2$s\n" + " OPT_NAME='%2$s'\n\0" +/* 4252 */ " if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n" + " echo 'Error: duplicate %2$s option'\n" + " echo \"$%1$s_USAGE_TEXT\"\n" + " exit 1\n" + " fi >&2\n" + " %1$s_%2$s_set=true\n" + " %1$s_%2$s='%3$s'\n" + " export %1$s_%2$s\n" + " OPT_NAME='%2$s'\n\0" +/* 4569 */ "\n" + "ARG_COUNT=$#\n" + "OPT_ARG=$1\n" + "while [ $# -gt 0 ]\n" + "do\n" + " OPT_ELEMENT=''\n" + " OPT_ARG_VAL=''\n" + " OPT_ARG=${1}\n\0" +/* 4672 */ " case \"${OPT_ARG_NEEDED}\" in\n" + " NO )\n" + " if [ -n \"${OPT_ARG}\" ]\n" + " then\n" + " OPT_ARG=-${OPT_ARG}\n" + " else\n" + " shift\n" + " OPT_ARG=$1\n" + " fi\n" + " ;;\n" + " YES )\n" + " if [ -n \"${OPT_ARG}\" ]\n" + " then\n" + " OPT_ARG_VAL=${OPT_ARG}\n" + " else\n" + " if [ $# -eq 0 ]\n" + " then\n" + " echo No argument provided for ${OPT_NAME} option\n" + " echo \"$%s_USAGE_TEXT\"\n" + " exit 1\n" + " fi >&2\n" + " shift\n" + " OPT_ARG_VAL=$1\n" + " fi\n" + " shift\n" + " OPT_ARG=$1\n" + " ;;\n" + " OK )\n" + " if [ -n \"${OPT_ARG}\" ]\n" + " then\n" + " OPT_ARG_VAL=${OPT_ARG}\n" + " shift\n" + " OPT_ARG=$1\n" + " else\n" + " shift\n" + " if [ $# -gt 0 ]\n" + " then\n" + " case \"$1\" in -* ) ;; * )\n" + " OPT_ARG_VAL=$1\n" + " shift ;; esac\n" + " OPT_ARG=$1\n" + " fi\n" + " fi\n" + " ;;\n" + " esac\n\0" +/* 5826 */ " echo \"$%s_LONGUSAGE_TEXT\" | ${PAGER-more}\n" + " exit 0\n\0" +/* 5900 */ "%s OF %s\n" + "#\n" + "# From here to the next `-- do not modify this marker --',\n" + "# the text has been generated %s\n\0" +/* 6006 */ " eval %1$s_%2$s${OPT_ELEMENT}=true\n" + " export %1$s_%2$s${OPT_ELEMENT}\n\0" +/* 6096 */ " if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n" + " echo 'Error: duplicate %2$s option'\n" + " echo \"$%1$s_USAGE_TEXT\"\n" + " exit 1\n" + " fi >&2\n" + " %1$s_%2$s_set=true\n" + " OPT_NAME='%2$s'\n\0" +/* 6355 */ "\n" + "%1$s_%2$s=${%1$s_%2$s-'%3$s'}\n" + "%1$s_%2$s_set=false\n" + "export %1$s_%2$s\n\0" +/* 6424 */ "\n" + "%1$s_%2$s=${%1$s_%2$s}\n" + "%1$s_%2$s_set=false\n" + "export %1$s_%2$s\n\0" +/* 6486 */ "# # # # # # # # # # -- do not modify this marker --\n" + "#\n" + "# DO NOT EDIT THIS SECTION\n\0" +/* 6569 */ " * )\n" + " echo Unknown %s: \"${OPT_CODE}\" >&2\n" + " echo \"$%s_USAGE_TEXT\" >&2\n" + " exit 1\n" + " ;;\n" + " esac\n"; + +/* end of ao-strs.c */ diff --git a/src/libopts/ao-strs.h b/src/libopts/ao-strs.h new file mode 100644 index 0000000..95036ef --- /dev/null +++ b/src/libopts/ao-strs.h @@ -0,0 +1,338 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (ao-strs.h) + * + * It has been AutoGen-ed + * From the definitions ao-strs.def + * and the template file strings + * + * Copyright (C) 2011-2018 Bruce Korb, all rights reserved. + * This is free software. It is licensed for use, modification and + * redistribution under the terms of the + * Modified (3 clause) Berkeley Software Distribution License + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name ``Bruce Korb'' nor the name of any other + * contributor may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * strings IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef STRINGS_AO_STRS_H_GUARD +#define STRINGS_AO_STRS_H_GUARD 1 +/* + * 146 strings in ao_strs_strtable string table + */ +#define ARG_BREAK_STR (ao_strs_strtable+280) +#define ARG_BREAK_STR_LEN 5 +#define ARG_BY_NUM_FMT (ao_strs_strtable+286) +#define ARG_BY_NUM_FMT_LEN 9 +#define BOOL_ATR_FMT (ao_strs_strtable+957) +#define BOOL_ATR_FMT_LEN 31 +#define CHK_MAX_COUNT (ao_strs_strtable+1508) +#define CHK_MAX_COUNT_LEN 190 +#define CHK_MIN_COUNT (ao_strs_strtable+1699) +#define CHK_MIN_COUNT_LEN 91 +#define CHK_ONE_REQUIRED (ao_strs_strtable+1791) +#define CHK_ONE_REQUIRED_LEN 80 +#define ECHO_N_EXIT (ao_strs_strtable+1872) +#define ECHO_N_EXIT_LEN 50 +#define EMPTY_ARG (ao_strs_strtable+296) +#define EMPTY_ARG_LEN 2 +#define END_MARK (ao_strs_strtable+1923) +#define END_MARK_LEN 115 +#define END_OPT_SEL_STR (ao_strs_strtable+299) +#define END_OPT_SEL_STR_LEN 12 +#define END_PRE_FMT (ao_strs_strtable+989) +#define END_PRE_FMT_LEN 36 +#define END_SET_TEXT (ao_strs_strtable+312) +#define END_SET_TEXT_LEN 3 +#define END_XML_FMT (ao_strs_strtable+316) +#define END_XML_FMT_LEN 6 +#define ENUM_ERR_LINE (ao_strs_strtable+323) +#define ENUM_ERR_LINE_LEN 5 +#define ENUM_ERR_WIDTH (ao_strs_strtable+329) +#define ENUM_ERR_WIDTH_LEN 6 +#define EXPORT_ARG_FMT (ao_strs_strtable+336) +#define EXPORT_ARG_FMT_LEN 17 +#define FALSE_STR (ao_strs_strtable+354) +#define FALSE_STR_LEN 5 +#define FINISH_LOOP (ao_strs_strtable+2039) +#define FINISH_LOOP_LEN 378 +#define FLAG_OPT_MARK (ao_strs_strtable+360) +#define FLAG_OPT_MARK_LEN 9 +#define FLAG_STR (ao_strs_strtable+370) +#define FLAG_STR_LEN 4 +#define INIT_LOPT_STR (ao_strs_strtable+2418) +#define INIT_LOPT_STR_LEN 250 +#define INIT_OPT_STR (ao_strs_strtable+2669) +#define INIT_OPT_STR_LEN 116 +#define INVALID_FMT (ao_strs_strtable+375) +#define INVALID_FMT_LEN 10 +#define INVALID_STR (ao_strs_strtable+386) +#define INVALID_STR_LEN 9 +#define LINE_SPLICE (ao_strs_strtable+396) +#define LINE_SPLICE_LEN 4 +#define LONG_OPT_MARK (ao_strs_strtable+401) +#define LONG_OPT_MARKER (ao_strs_strtable+412) +#define LONG_OPT_MARKER_LEN 2 +#define LONG_OPT_MARK_LEN 10 +#define LONG_USE_STR (ao_strs_strtable+415) +#define LONG_USE_STR_LEN 9 +#define LOOP_STR (ao_strs_strtable+2786) +#define LOOP_STR_LEN 206 +#define LOPT_ARG_FMT (ao_strs_strtable+2993) +#define LOPT_ARG_FMT_LEN 778 +#define LVL3_CMD (ao_strs_strtable+425) +#define LVL3_CMD_LEN 15 +#define MK_STR_OCT_FMT (ao_strs_strtable+441) +#define MK_STR_OCT_FMT_LEN 5 +#define MORE_STR (ao_strs_strtable+447) +#define MORE_STR_LEN 4 +#define MULTI_ARG_FMT (ao_strs_strtable+3772) +#define MULTI_ARG_FMT_LEN 123 +#define MULTI_DEF_FMT (ao_strs_strtable+3896) +#define MULTI_DEF_FMT_LEN 157 +#define NESTED_OPT_FMT (ao_strs_strtable+452) +#define NESTED_OPT_FMT_LEN 17 +#define NLSTR_FMT (ao_strs_strtable+470) +#define NLSTR_FMT_LEN 3 +#define NLSTR_SPACE_FMT (ao_strs_strtable+474) +#define NLSTR_SPACE_FMT_LEN 5 +#define NONE_STR (ao_strs_strtable+110) +#define NONE_STR_LEN 4 +#define NOT_FOUND_STR (ao_strs_strtable+4054) +#define NOT_FOUND_STR_LEN 56 +#define NO_ARG_NEEDED (ao_strs_strtable+480) +#define NO_ARG_NEEDED_LEN 17 +#define NO_LOAD_WARN (ao_strs_strtable+1026) +#define NO_LOAD_WARN_LEN 46 +#define NO_MULTI_ARG_FMT (ao_strs_strtable+4111) +#define NO_MULTI_ARG_FMT_LEN 140 +#define NO_SAVE_OPTS (ao_strs_strtable+1073) +#define NO_SAVE_OPTS_LEN 46 +#define NO_SGL_ARG_FMT (ao_strs_strtable+4252) +#define NO_SGL_ARG_FMT_LEN 316 +#define NO_SUPPRESS_LOAD (ao_strs_strtable+1120) +#define NO_SUPPRESS_LOAD_LEN 65 +#define NULL_ATR_FMT (ao_strs_strtable+498) +#define NULL_ATR_FMT_LEN 6 +#define NUMB_ATR_FMT (ao_strs_strtable+1186) +#define NUMB_ATR_FMT_LEN 34 +#define OK_NEED_OPT_ARG (ao_strs_strtable+505) +#define OK_NEED_OPT_ARG_LEN 17 +#define ONE_TAB_STR (ao_strs_strtable+523) +#define ONE_TAB_STR_LEN 1 +#define ONLY_OPTS_LOOP (ao_strs_strtable+4569) +#define ONLY_OPTS_LOOP_LEN 102 +#define OPEN_CLOSE_FMT (ao_strs_strtable+498) +#define OPEN_CLOSE_FMT_LEN 6 +#define OPEN_XML_FMT (ao_strs_strtable+525) +#define OPEN_XML_FMT_LEN 4 +#define OPTION_STR (ao_strs_strtable+530) +#define OPTION_STR_LEN 6 +#define OPT_ARG_FMT (ao_strs_strtable+4672) +#define OPT_ARG_FMT_LEN 1153 +#define OPT_END_FMT (ao_strs_strtable+537) +#define OPT_END_FMT_LEN 14 +#define OPT_VAL_FMT (ao_strs_strtable+552) +#define OPT_VAL_FMT_LEN 6 +#define OR_STR (ao_strs_strtable+559) +#define OR_STR_LEN 3 +#define PAGER_NAME (ao_strs_strtable+563) +#define PAGER_NAME_LEN 5 +#define PAGE_USAGE_FMT (ao_strs_strtable+569) +#define PAGE_USAGE_FMT_LEN 22 +#define PAGE_USAGE_TEXT (ao_strs_strtable+5826) +#define PAGE_USAGE_TEXT_LEN 73 +#define PLUS_STR (ao_strs_strtable+592) +#define PLUS_STR_LEN 3 +#define PREAMBLE_FMT (ao_strs_strtable+5900) +#define PREAMBLE_FMT_LEN 105 +#define PUTS_FMT (ao_strs_strtable+596) +#define PUTS_FMT_LEN 15 +#define QUOT_APOS (ao_strs_strtable+612) +#define QUOT_APOS_LEN 2 +#define QUOT_ARG_FMT (ao_strs_strtable+615) +#define QUOT_ARG_FMT_LEN 4 +#define SET_MULTI_ARG (ao_strs_strtable+6006) +#define SET_MULTI_ARG_LEN 89 +#define SET_NO_TEXT_FMT (ao_strs_strtable+1221) +#define SET_NO_TEXT_FMT_LEN 30 +#define SET_OFF_FMT (ao_strs_strtable+620) +#define SET_OFF_FMT_LEN 6 +#define SET_TEXT_FMT (ao_strs_strtable+627) +#define SET_TEXT_FMT_LEN 12 +#define SGL_ARG_FMT (ao_strs_strtable+6096) +#define SGL_ARG_FMT_LEN 258 +#define SGL_DEF_FMT (ao_strs_strtable+6355) +#define SGL_DEF_FMT_LEN 68 +#define SGL_NO_DEF_FMT (ao_strs_strtable+6424) +#define SGL_NO_DEF_FMT_LEN 61 +#define SHELL_MAGIC (ao_strs_strtable+640) +#define SHELL_MAGIC_LEN 6 +#define SHOW_PROG_ENV (ao_strs_strtable+647) +#define SHOW_PROG_ENV_LEN 19 +#define SHOW_VAL_FMT (ao_strs_strtable+667) +#define SHOW_VAL_FMT_LEN 17 +#define START_MARK (ao_strs_strtable+6486) +#define START_MARK_LEN 82 +#define STDOUT (ao_strs_strtable+685) +#define STDOUT_LEN 6 +#define TIME_FMT (ao_strs_strtable+692) +#define TIME_FMT_LEN 21 +#define TMPDIR (ao_strs_strtable+714) +#define TMPDIR_LEN 6 +#define TMP_FILE_FMT (ao_strs_strtable+721) +#define TMP_FILE_FMT_LEN 16 +#define TMP_USAGE_FMT (ao_strs_strtable+721) +#define TMP_USAGE_FMT_LEN 16 +#define TRUE_STR (ao_strs_strtable+738) +#define TRUE_STR_LEN 4 +#define TWO_SPACES_STR (ao_strs_strtable+273) +#define TWO_SPACES_STR_LEN 2 +#define TYPE_ATR_FMT (ao_strs_strtable+743) +#define TYPE_ATR_FMT_LEN 12 +#define UNK_OPT_FMT (ao_strs_strtable+6569) +#define UNK_OPT_FMT_LEN 144 +#define VER_STR (ao_strs_strtable+756) +#define VER_STR_LEN 7 +#define XML_HEX_BYTE_FMT (ao_strs_strtable+764) +#define XML_HEX_BYTE_FMT_LEN 7 +#define YES_NEED_OPT_ARG (ao_strs_strtable+772) +#define YES_NEED_OPT_ARG_LEN 18 +#define ao_default_use (ao_strs_strtable+804) +#define ao_default_use_LEN 11 +#define ao_name_use_fmt (ao_strs_strtable+791) +#define ao_name_use_fmt_LEN 12 +#define apostrophe (ao_strs_strtable+816) +#define apostrophe_LEN 4 +#define arg_fmt (ao_strs_strtable+821) +#define arg_fmt_LEN 5 +#define init_optct (ao_strs_strtable+864) +#define init_optct_LEN 13 +#define misguess_len (ao_strs_strtable+827) +#define misguess_len_LEN 36 +#define set_dash (ao_strs_strtable+878) +#define set_dash_LEN 6 +#define tmp_dir (ao_strs_strtable+885) +#define tmp_dir_LEN 4 +#define zAll (ao_strs_strtable+276) +#define zAll_LEN 3 +#define zCfgAO_Flags (ao_strs_strtable+12) +#define zCfgAO_Flags_LEN 14 +#define zCfgProg (ao_strs_strtable+27) +#define zCfgProg_LEN 9 +#define zEquivMode (ao_strs_strtable+1252) +#define zEquivMode_LEN 44 +#define zFiveSpaces (ao_strs_strtable+263) +#define zFiveSpaces_LEN 5 +#define zFmtFmt (ao_strs_strtable+37) +#define zFmtFmt_LEN 11 +#define zFmtProg (ao_strs_strtable+49) +#define zFmtProg_LEN 14 +#define zFullOptFmt (ao_strs_strtable+1297) +#define zFullOptFmt_LEN 34 +#define zGnuBreak (ao_strs_strtable+64) +#define zGnuBreak_LEN 5 +#define zGnuFileArg (ao_strs_strtable+70) +#define zGnuFileArg_LEN 5 +#define zGnuKeyLArg (ao_strs_strtable+76) +#define zGnuKeyLArg_LEN 4 +#define zGnuNestArg (ao_strs_strtable+81) +#define zGnuNestArg_LEN 5 +#define zGnuOptArg (ao_strs_strtable+87) +#define zGnuOptArg_LEN 6 +#define zGnuOptFmt (ao_strs_strtable+94) +#define zGnuOptFmt_LEN 10 +#define zGnuTimeArg (ao_strs_strtable+105) +#define zGnuTimeArg_LEN 4 +#define zNone (ao_strs_strtable+110) +#define zNone_LEN 4 +#define zOptCookieCt (ao_strs_strtable+1332) +#define zOptCookieCt_LEN 38 +#define zOptCtFmt (ao_strs_strtable+1371) +#define zOptCtFmt_LEN 30 +#define zOptDisabl (ao_strs_strtable+1402) +#define zOptDisabl_LEN 32 +#define zOptNumFmt (ao_strs_strtable+1435) +#define zOptNumFmt_LEN 41 +#define zOptionCase (ao_strs_strtable+1477) +#define zOptionCase_LEN 30 +#define zOptionEndSelect (ao_strs_strtable+890) +#define zOptionEndSelect_LEN 16 +#define zOptionFlag (ao_strs_strtable+907) +#define zOptionFlag_LEN 15 +#define zOptionFullName (ao_strs_strtable+923) +#define zOptionFullName_LEN 15 +#define zOptionPartName (ao_strs_strtable+939) +#define zOptionPartName_LEN 17 +#define zPresetFile (ao_strs_strtable+115) +#define zPresetFile_LEN 37 +#define zReqOptFmt (ao_strs_strtable+153) +#define zReqOptFmt_LEN 13 +#define zSepChars (ao_strs_strtable+0) +#define zSepChars_LEN 3 +#define zShrtGnuOptFmt (ao_strs_strtable+167) +#define zShrtGnuOptFmt_LEN 2 +#define zSixSpaces (ao_strs_strtable+256) +#define zSixSpaces_LEN 6 +#define zStdBoolArg (ao_strs_strtable+170) +#define zStdBoolArg_LEN 3 +#define zStdBreak (ao_strs_strtable+174) +#define zStdBreak_LEN 7 +#define zStdFileArg (ao_strs_strtable+182) +#define zStdFileArg_LEN 3 +#define zStdKeyArg (ao_strs_strtable+186) +#define zStdKeyArg_LEN 3 +#define zStdKeyLArg (ao_strs_strtable+190) +#define zStdKeyLArg_LEN 3 +#define zStdNestArg (ao_strs_strtable+194) +#define zStdNestArg_LEN 3 +#define zStdNoArg (ao_strs_strtable+198) +#define zStdNoArg_LEN 3 +#define zStdNumArg (ao_strs_strtable+202) +#define zStdNumArg_LEN 3 +#define zStdOptArg (ao_strs_strtable+206) +#define zStdOptArg_LEN 3 +#define zStdReqArg (ao_strs_strtable+210) +#define zStdReqArg_LEN 3 +#define zStdStrArg (ao_strs_strtable+214) +#define zStdStrArg_LEN 3 +#define zStdTimeArg (ao_strs_strtable+218) +#define zStdTimeArg_LEN 3 +#define zTabHyp (ao_strs_strtable+222) +#define zTabHypAnd (ao_strs_strtable+236) +#define zTabHypAnd_LEN 11 +#define zTabHyp_LEN 6 +#define zTabSpace (ao_strs_strtable+229) +#define zTabSpace_LEN 6 +#define zTabout (ao_strs_strtable+248) +#define zTabout_LEN 7 +#define zThreeSpaces (ao_strs_strtable+269) +#define zThreeSpaces_LEN 3 +#define zTwoSpaces (ao_strs_strtable+273) +#define zTwoSpaces_LEN 2 +#define zambig_file (ao_strs_strtable+4) +#define zambig_file_LEN 7 +extern char const ao_strs_strtable[6714]; + +#endif /* STRINGS_AO_STRS_H_GUARD */ diff --git a/src/libopts/autoopts.c b/src/libopts/autoopts.c new file mode 100644 index 0000000..643d277 --- /dev/null +++ b/src/libopts/autoopts.c @@ -0,0 +1,391 @@ + +/** + * \file autoopts.c + * + * This file contains all of the routines that must be linked into + * an executable to use the generated option processing. The optional + * routines are in separately compiled modules so that they will not + * necessarily be linked in. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/** + * The number of tab characters to skip when printing continuation lines. + */ + static unsigned int tab_skip_ct = 0; + +#ifndef HAVE_PATHFIND +# define pathfind(_p, _n, _m) option_pathfind(_p, _n, _m) +# include "compat/pathfind.c" +#endif + +#ifndef HAVE_SNPRINTF +# define vsnprintf option_vsnprintf +# define snprintf option_snprintf +# include "compat/snprintf.c" +#endif + +#ifndef HAVE_STRDUP +# define strdup(_s) option_strdup(_s) +# include "compat/strdup.c" +#endif + +#ifndef HAVE_STRCHR +# define strrchr(_s, _c) option_strrchr(_s, _c) +# define strchr(_s, _c) option_strchr(_s, _c) +# include "compat/strchr.c" +#endif + +static void * +ao_malloc(size_t sz) +{ + void * res = malloc(sz); + if (res == NULL) { + fprintf(stderr, zalloc_fail, (int)sz); + option_exits(EXIT_FAILURE); + } + return res; +} + +static void * +ao_realloc(void *p, size_t sz) +{ + void * res = (p == NULL) ? malloc(sz) : realloc(p, sz); + if (res == NULL) { + fprintf(stderr, zrealloc_fail, (int)sz, p); + option_exits(EXIT_FAILURE); + } + return res; +} + +static char * +ao_strdup(char const *str) +{ + char * res = strdup(str); + if (res == NULL) { + fprintf(stderr, zalloc_fail, (int)strlen(str)); + option_exits(EXIT_FAILURE); + } + return res; +} + +/** + * handle an option. + * + * This routine handles equivalencing, sets the option state flags and + * invokes the handler procedure, if any. + */ +static tSuccess +handle_opt(tOptions * opts, tOptState * o_st) +{ + /* + * Save a copy of the option procedure pointer. + * If this is an equivalence class option, we still want this proc. + */ + tOptDesc * od = o_st->pOD; + tOptProc * opt_proc = od->pOptProc; + if (od->fOptState & OPTST_ALLOC_ARG) + AGFREE(od->optArg.argString); + + od->optArg.argString = o_st->pzOptArg; + + /* + * IF we are presetting options, then we will ignore any un-presettable + * options. They are the ones either marked as such. + */ + if ( ((opts->fOptSet & OPTPROC_PRESETTING) != 0) + && ((od->fOptState & OPTST_NO_INIT) != 0) + ) + return PROBLEM; + + /* + * IF this is an equivalence class option, + * THEN + * Save the option value that got us to this option + * entry. (It may not be od->optChar[0], if this is an + * equivalence entry.) + * set the pointer to the equivalence class base + */ + if (od->optEquivIndex != NO_EQUIVALENT) { + tOptDesc * eqv_od = opts->pOptDesc + od->optEquivIndex; + + /* + * IF the current option state has not been defined (set on the + * command line), THEN we will allow continued resetting of + * the value. Once "defined", then it must not change. + */ + if ((od->fOptState & OPTST_DEFINED) != 0) { + /* + * The equivalenced-to option has been found on the command + * line before. Make sure new occurrences are the same type. + * + * IF this option has been previously equivalenced and + * it was not the same equivalenced-to option, + * THEN we have a usage problem. + */ + if (eqv_od->optActualIndex != od->optIndex) { + fprintf(stderr, zmultiway_bug, eqv_od->pz_Name, od->pz_Name, + (opts->pOptDesc + eqv_od->optActualIndex)->pz_Name); + return FAILURE; + } + } else { + /* + * Set the equivalenced-to actual option index to no-equivalent + * so that we set all the entries below. This option may either + * never have been selected before, or else it was selected by + * some sort of "presetting" mechanism. + */ + eqv_od->optActualIndex = NO_EQUIVALENT; + } + + if (eqv_od->optActualIndex != od->optIndex) { + /* + * First time through, copy over the state + * and add in the equivalence flag + */ + eqv_od->optActualValue = od->optValue; + eqv_od->optActualIndex = od->optIndex; + o_st->flags |= OPTST_EQUIVALENCE; + } + + /* + * Copy the most recent option argument. set membership state + * is kept in 'eqv_od->optCookie'. Do not overwrite. + */ + eqv_od->optArg.argString = od->optArg.argString; + od = eqv_od; + + } else { + od->optActualValue = od->optValue; + od->optActualIndex = od->optIndex; + } + + od->fOptState &= OPTST_PERSISTENT_MASK; + od->fOptState |= (o_st->flags & ~OPTST_PERSISTENT_MASK); + + /* + * Keep track of count only for DEFINED (command line) options. + * IF we have too many, build up an error message and bail. + */ + if ( (od->fOptState & OPTST_DEFINED) + && (++od->optOccCt > od->optMaxCt) ) + return too_many_occurrences(opts, od); + /* + * If provided a procedure to call, call it + */ + if (opt_proc != NULL) + (*opt_proc)(opts, od); + + return SUCCESS; +} + +/** + * Find the option descriptor and option argument (if any) for the + * next command line argument. DO NOT modify the descriptor. Put + * all the state in the state argument so that the option can be skipped + * without consequence (side effect). + * + * @param opts the program option descriptor + * @param o_st the state of the next found option + */ +static tSuccess +next_opt(tOptions * opts, tOptState * o_st) +{ + { + tSuccess res = find_opt(opts, o_st); + if (! SUCCESSFUL(res)) + return res; + } + + if ( ((o_st->flags & OPTST_DEFINED) != 0) + && ((o_st->pOD->fOptState & OPTST_NO_COMMAND) != 0)) { + fprintf(stderr, zNotCmdOpt, o_st->pOD->pz_Name); + return FAILURE; + } + + return get_opt_arg(opts, o_st); +} + +/** + * Process all the options from our current position onward. (This allows + * interspersed options and arguments for the few non-standard programs that + * require it.) Thus, do not rewind option indexes because some programs + * choose to re-invoke after a non-option. + * + * @param[in,out] opts program options descriptor + * @returns SUCCESS or FAILURE + */ +static tSuccess +regular_opts(tOptions * opts) +{ + /* assert: opts->fOptSet & OPTPROC_IMMEDIATE == 0 */ + for (;;) { + tOptState opt_st = OPTSTATE_INITIALIZER(DEFINED); + + switch (next_opt(opts, &opt_st)) { + case FAILURE: goto failed_option; + case PROBLEM: return SUCCESS; /* no more args */ + case SUCCESS: break; + } + + /* + * IF this is an immediate action option, + * THEN skip it (unless we are supposed to do it a second time). + */ + if (! DO_NORMALLY(opt_st.flags)) { + if (! DO_SECOND_TIME(opt_st.flags)) + continue; + opt_st.pOD->optOccCt--; /* don't count this repetition */ + } + + if (! SUCCESSFUL(handle_opt(opts, &opt_st))) + break; + } failed_option:; + + if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) + (*opts->pUsageProc)(opts, EXIT_FAILURE); + + return FAILURE; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * THESE ROUTINES ARE CALLABLE FROM THE GENERATED OPTION PROCESSING CODE + */ +/*=--subblock=arg=arg_type,arg_name,arg_desc =*/ +/*=* + * library: opts + * header: your-opts.h + * + * lib_description: + * + * These are the routines that libopts users may call directly from their + * code. There are several other routines that can be called by code + * generated by the libopts option templates, but they are not to be + * called from any other user code. The @file{options.h} header is + * fairly clear about this, too. +=*/ + +/*=export_func optionProcess + * + * what: this is the main option processing routine + * + * arg: + tOptions * + opts + program options descriptor + + * arg: + int + a_ct + program arg count + + * arg: + char ** + a_v + program arg vector + + * + * ret_type: int + * ret_desc: the count of the arguments processed + * + * doc: + * + * This is the main entry point for processing options. It is intended + * that this procedure be called once at the beginning of the execution of + * a program. Depending on options selected earlier, it is sometimes + * necessary to stop and restart option processing, or to select completely + * different sets of options. This can be done easily, but you generally + * do not want to do this. + * + * The number of arguments processed always includes the program name. + * If one of the arguments is "--", then it is counted and the processing + * stops. If an error was encountered and errors are to be tolerated, then + * the returned value is the index of the argument causing the error. + * A hyphen by itself ("-") will also cause processing to stop and will + * @emph{not} be counted among the processed arguments. A hyphen by itself + * is treated as an operand. Encountering an operand stops option + * processing. + * + * err: Errors will cause diagnostics to be printed. @code{exit(3)} may + * or may not be called. It depends upon whether or not the options + * were generated with the "allow-errors" attribute, or if the + * ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked. +=*/ +int +optionProcess(tOptions * opts, int a_ct, char ** a_v) +{ + if (! SUCCESSFUL(validate_struct(opts, a_v[0]))) + ao_bug(zbad_data_msg); + + /* + * Establish the real program name, the program full path, + * and do all the presetting the first time thru only. + */ + if (! ao_initialize(opts, a_ct, a_v)) + return 0; + + /* + * IF we are (re)starting, + * THEN reset option location + */ + if (opts->curOptIdx <= 0) { + opts->curOptIdx = 1; + opts->pzCurOpt = NULL; + } + + if (! SUCCESSFUL(regular_opts(opts))) + return (int)opts->origArgCt; + + /* + * IF there were no errors + * AND we have RC/INI files + * AND there is a request to save the files + * THEN do that now before testing for conflicts. + * (conflicts are ignored in preset options) + */ + switch (opts->specOptIdx.save_opts) { + case 0: + case NO_EQUIVALENT: + break; + default: + { + tOptDesc * od = opts->pOptDesc + opts->specOptIdx.save_opts; + + if (SELECTED_OPT(od)) { + optionSaveFile(opts); + option_exits(EXIT_SUCCESS); + } + } + } + + /* + * IF we are checking for errors, + * THEN look for too few occurrences of required options + */ + if (((opts->fOptSet & OPTPROC_ERRSTOP) != 0) + && (! is_consistent(opts))) + (*opts->pUsageProc)(opts, EXIT_FAILURE); + + return (int)opts->curOptIdx; +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/autoopts.c */ diff --git a/src/libopts/autoopts.h b/src/libopts/autoopts.h new file mode 100644 index 0000000..36bb43f --- /dev/null +++ b/src/libopts/autoopts.h @@ -0,0 +1,494 @@ + +/* + * \file autoopts.h + * + * This file defines all the global structures and special values + * used in the automated option processing library. + * + * @group autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +#ifndef AUTOGEN_AUTOOPTS_H +#define AUTOGEN_AUTOOPTS_H +#include + +#define AO_NAME_LIMIT 127 +#define AO_NAME_SIZE ((size_t)(AO_NAME_LIMIT + 1)) + +#ifndef AG_PATH_MAX +# ifdef PATH_MAX +# define AG_PATH_MAX ((size_t)PATH_MAX) +# else +# ifdef __gnu_hurd__ +# define size_t unsigned long +# endif +# define AG_PATH_MAX ((size_t)4096) +# endif +#else +# if defined(PATH_MAX) && (PATH_MAX > MAXPATHLEN) +# undef AG_PATH_MAX +# define AG_PATH_MAX ((size_t)PATH_MAX) +# endif +#endif + +#undef EXPORT +#define EXPORT + +#ifndef NUL +#define NUL '\0' +#endif +#define BEL '\a' +#define BS '\b' +#define HT '\t' +#define LF '\n' +#define VT '\v' +#define FF '\f' +#define CR '\r' + +#if defined(_WIN32) && !defined(__CYGWIN__) +# define DIRCH '\\' +#else +# define DIRCH '/' +#endif + +#ifndef EX_USAGE + /** + * Command line usage problem + */ +# define EX_USAGE 64 +#endif +#ifndef EX_DATAERR + /** + * The input data was incorrect in some way. + */ +# define EX_DATAERR 64 +#endif +#ifndef EX_NOINPUT + /** + * option state was requested from a file that cannot be loaded. + */ +# define EX_NOINPUT 66 +#endif +#ifndef EX_SOFTWARE + /** + * AutoOpts Software failure. + */ +# define EX_SOFTWARE 70 +#endif +#ifndef EX_OSERR + /** + * Command line usage problem + */ +# define EX_OSERR 71 +#endif + +#define NL '\n' +#ifndef C +/** + * Coercive cast. Compel an address to be interpreted as the type + * of the first argument. No complaints, just do it. + */ +#define C(_t,_p) ((_t)VOIDP(_p)) +#endif + +/* The __attribute__((__warn_unused_result__)) feature + is available in gcc versions 3.4 and newer, + while the typeof feature has been available since 2.7 at least. */ +# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) +# define ignore_val(x) ((void) (x)) +# else +# define ignore_val(x) (({ __typeof__ (x) __x = (x); (void) __x; })) +# endif + +/* + * Convert the number to a list usable in a printf call + */ +#define NUM_TO_VER(n) ((n) >> 12), ((n) >> 7) & 0x001F, (n) & 0x007F + +#define NAMED_OPTS(po) \ + (((po)->fOptSet & (OPTPROC_SHORTOPT | OPTPROC_LONGOPT)) == 0) + +#define SKIP_OPT(p) (((p)->fOptState & OPTST_IMMUTABLE_MASK) != 0) + +typedef int tDirection; +/** + * handling option presets. Start with command line and work through + * config settings in reverse order. + */ +#define DIRECTION_PRESET -1 +/** + * handling normal options. Start with first config file, then environment + * variables and finally the command line. + */ +#define DIRECTION_PROCESS 1 +/** + * An initialzation phase or an option being loaded from program sources. + */ +#define DIRECTION_CALLED 0 + +#define PROCESSING(d) ((d)>0) +#define PRESETTING(d) ((d)<0) +#define CALLED(d) ((d)==0) + +/** + * When loading a line (or block) of text as an option, the value can + * be processed in any of several modes. + */ +typedef enum { + /** + * If the value looks like a quoted string, then process it. Double + * quoted strings are processed the way strings are in "C" programs, + * except they are treated as regular characters if the following + * character is not a well-established escape sequence. Single quoted + * strings (quoted with apostrophies) are handled the way strings are + * handled in shell scripts, *except* that backslash escapes are + * honored before backslash escapes and apostrophies. + */ + OPTION_LOAD_COOKED, + + /** + * Even if the value begins with quote characters, do not do quote + * processing. Strip leading and trailing white space. + */ + OPTION_LOAD_UNCOOKED, + + /** + * Keep every part of the value between the delimiters. + */ + OPTION_LOAD_KEEP +} tOptionLoadMode; + +static tOptionLoadMode option_load_mode; + +/** + * The pager state is used by optionPagedUsage() procedure. + * When it runs, it sets itself up to be called again on exit. + * If, however, a routine needs a child process to do some work + * before it is done, then 'pagerState' must be set to + * 'PAGER_STATE_CHILD' so that optionPagedUsage() will not try + * to run the pager program before its time. + */ +typedef enum { + PAGER_STATE_INITIAL, //@< initial option paging state + + /** + * temp file created and optionPagedUsage is scheduled to run at exit + */ + PAGER_STATE_READY, + + /** + * This is a child process used in creating shell script usage. + */ + PAGER_STATE_CHILD +} tePagerState; + +typedef enum { + ENV_ALL, + ENV_IMM, + ENV_NON_IMM +} teEnvPresetType; + +typedef enum { + TOPT_UNDEFINED = 0, + TOPT_SHORT, + TOPT_LONG, + TOPT_DEFAULT +} teOptType; + +typedef struct { + tOptDesc * pOD; + char const * pzOptArg; + opt_state_mask_t flags; + teOptType optType; +} tOptState; +#define OPTSTATE_INITIALIZER(st) \ + { NULL, NULL, OPTST_ ## st, TOPT_UNDEFINED } + +#define TEXTTO_TABLE \ + _TT_(LONGUSAGE) \ + _TT_(USAGE) \ + _TT_(VERSION) +#define _TT_(n) \ + TT_ ## n , + +typedef enum { TEXTTO_TABLE COUNT_TT } teTextTo; + +#undef _TT_ + +/** + * option argument types. Used to create usage information for + * particular options. + */ +typedef struct { + char const * pzStr; + char const * pzReq; + char const * pzNum; + char const * pzFile; + char const * pzKey; + char const * pzKeyL; + char const * pzBool; + char const * pzNest; + char const * pzOpt; + char const * pzNo; + char const * pzBrk; + char const * pzNoF; + char const * pzSpc; + char const * pzOptFmt; + char const * pzTime; +} arg_types_t; + +#define AGALOC(_c, _w) ao_malloc((size_t)_c) +#define AGREALOC(_p, _c, _w) ao_realloc(VOIDP(_p), (size_t)_c) +#define AGFREE(_p) free(VOIDP(_p)) +#define AGDUPSTR(_p, _s, _w) (_p = ao_strdup(_s)) + +static void * +ao_malloc(size_t sz); + +static void * +ao_realloc(void *p, size_t sz); + +#define ao_free(_p) free(VOIDP(_p)) + +static char * +ao_strdup(char const * str); + +/** + * DO option handling? + * + * Options are examined at two times: at immediate handling time and at + * normal handling time. If an option is disabled, the timing may be + * different from the handling of the undisabled option. The OPTST_DIABLED + * bit indicates the state of the currently discovered option. + * So, here's how it works: + * + * A) handling at "immediate" time, either 1 or 2: + * + * 1. OPTST_DISABLED is not set: + * IMM must be set + * DISABLE_IMM don't care + * TWICE don't care + * DISABLE_TWICE don't care + * 0 -and- 1 x x x + * + * 2. OPTST_DISABLED is set: + * IMM don't care + * DISABLE_IMM must be set + * TWICE don't care + * DISABLE_TWICE don't care + * 1 -and- x 1 x x + */ +#define DO_IMMEDIATELY(_flg) \ + ( (((_flg) & (OPTST_DISABLED|OPTST_IMM)) == OPTST_IMM) \ + || ( ((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM)) \ + == (OPTST_DISABLED|OPTST_DISABLE_IMM) )) + +/** + * B) handling at "regular" time because it was not immediate + * + * 1. OPTST_DISABLED is not set: + * IMM must *NOT* be set + * DISABLE_IMM don't care + * TWICE don't care + * DISABLE_TWICE don't care + * 0 -and- 0 x x x + * + * 2. OPTST_DISABLED is set: + * IMM don't care + * DISABLE_IMM don't care + * TWICE must be set + * DISABLE_TWICE don't care + * 1 -and- x x 1 x + */ +#define DO_NORMALLY(_flg) ( \ + (((_flg) & (OPTST_DISABLED|OPTST_IMM)) == 0) \ + || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM)) == \ + OPTST_DISABLED) ) + +/** + * C) handling at "regular" time because it is to be handled twice. + * The immediate bit was already tested and found to be set: + * + * 3. OPTST_DISABLED is not set: + * IMM is set (but don't care) + * DISABLE_IMM don't care + * TWICE must be set + * DISABLE_TWICE don't care + * 0 -and- ? x 1 x + * + * 4. OPTST_DISABLED is set: + * IMM don't care + * DISABLE_IMM is set (but don't care) + * TWICE don't care + * DISABLE_TWICE must be set + * 1 -and- x ? x 1 + */ +#define DO_SECOND_TIME(_flg) ( \ + (((_flg) & (OPTST_DISABLED|OPTST_TWICE)) == \ + OPTST_TWICE) \ + || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_TWICE)) == \ + (OPTST_DISABLED|OPTST_DISABLE_TWICE) )) + +/* + * text_mmap structure. Only active on platforms with mmap(2). + */ +#ifdef HAVE_SYS_MMAN_H +# include +#else +# ifndef PROT_READ +# define PROT_READ 0x01 +# endif +# ifndef PROT_WRITE +# define PROT_WRITE 0x02 +# endif +# ifndef MAP_SHARED +# define MAP_SHARED 0x01 +# endif +# ifndef MAP_PRIVATE +# define MAP_PRIVATE 0x02 +# endif +#endif + +#ifndef MAP_FAILED +# define MAP_FAILED VOIDP(-1) +#endif + +#ifndef _SC_PAGESIZE +# ifdef _SC_PAGE_SIZE +# define _SC_PAGESIZE _SC_PAGE_SIZE +# endif +#endif + +#ifndef HAVE_STRCHR +extern char * strchr(char const * s, int c); +extern char * strrchr(char const * s, int c); +#endif + +/** + * INQUERY_CALL() tests whether the option handling function has been + * called by an inquery (help text needed, or option being reset), + * or called by a set-the-option operation. + */ +#define INQUERY_CALL(_o, _d) ( \ + ((_o) <= OPTPROC_EMIT_LIMIT) \ + || ((_d) == NULL) \ + || (((_d)->fOptState & OPTST_RESET) != 0) ) + +/** + * Define and initialize all the user visible strings. + * We do not do translations. If translations are to be done, then + * the client will provide a callback for that purpose. + */ +#undef DO_TRANSLATIONS +#include "autoopts/usage-txt.h" + +/** + * File pointer for usage output + */ +FILE * option_usage_fp; +/** + * If provided in the option structure + */ +static char const * program_pkgdatadir; +/** + * privately exported functions + */ +extern tOptProc optionPrintVersion, optionPagedUsage, optionLoadOpt; + +#ifdef AUTOOPTS_INTERNAL + +#ifndef PKGDATADIR +# define PKGDATADIR "" +#endif +#define APOSTROPHE '\'' + +#define OPTPROC_L_N_S (OPTPROC_LONGOPT | OPTPROC_SHORTOPT) +#if defined(ENABLE_NLS) && defined(HAVE_LIBINTL_H) +# include +#endif + +typedef struct { + size_t fnm_len; + uint32_t fnm_mask; + char const * fnm_name; +} ao_flag_names_t; + +/** + * Automated Options Usage Flags. + * NB: no entry may be a prefix of another entry + */ +#define AOFLAG_TABLE \ + _aof_(gnu, OPTPROC_GNUUSAGE ) \ + _aof_(autoopts, ~OPTPROC_GNUUSAGE) \ + _aof_(no_misuse_usage, OPTPROC_MISUSE ) \ + _aof_(misuse_usage, ~OPTPROC_MISUSE ) \ + _aof_(compute, OPTPROC_COMPUTE ) + +#define _aof_(_n, _f) AOUF_ ## _n ## _ID, +typedef enum { AOFLAG_TABLE AOUF_COUNT } ao_flag_id_t; +#undef _aof_ + +#define _aof_(_n, _f) AOUF_ ## _n = (1 << AOUF_ ## _n ## _ID), +typedef enum { AOFLAG_TABLE } ao_flags_t; +#undef _aof_ + +static char const zNil[] = ""; +static arg_types_t argTypes = { NULL }; +static char line_fmt_buf[32]; +static bool displayEnum = false; +static char const pkgdatadir_default[] = PKGDATADIR; +static char const * program_pkgdatadir = pkgdatadir_default; +static tOptionLoadMode option_load_mode = OPTION_LOAD_UNCOOKED; +static tePagerState pagerState = PAGER_STATE_INITIAL; + +static noreturn void option_exits(int exit_code); +static noreturn void fserr_exit(char const * prog, char const * op, + char const * fname); +static void fserr_warn(char const * prog, char const * op, + char const * fname); +static noreturn void ao_bug(char const * msg); + + FILE * option_usage_fp = NULL; + +static char const * pz_enum_err_fmt; + +tOptions * optionParseShellOptions = NULL; + +static char const * shell_prog = NULL; +static char * script_leader = NULL; +static char * script_trailer = NULL; +static char * script_text = NULL; +static bool print_exit = false; +#endif /* AUTOOPTS_INTERNAL */ + +#endif /* AUTOGEN_AUTOOPTS_H */ +/** + * @} + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/autoopts.h */ diff --git a/src/libopts/boolean.c b/src/libopts/boolean.c new file mode 100644 index 0000000..80e0b0e --- /dev/null +++ b/src/libopts/boolean.c @@ -0,0 +1,95 @@ + +/** + * \file boolean.c + * + * Handle options with true/false values for arguments. + * + * @addtogroup autoopts + * @{ + */ +/* + * This routine will run run-on options through a pager so the + * user may examine, print or edit them at their leisure. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/*=export_func optionBooleanVal + * private: + * + * what: Decipher a boolean value + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + od + the descriptor for this arg + + * + * doc: + * Decipher a true or false value for a boolean valued option argument. + * The value is true, unless it starts with 'n' or 'f' or "#f" or + * it is an empty string or it is a number that evaluates to zero. +=*/ +void +optionBooleanVal(tOptions * opts, tOptDesc * od) +{ + char * pz; + bool res = true; + + if (INQUERY_CALL(opts, od)) + return; + + if (od->optArg.argString == NULL) { + od->optArg.argBool = false; + return; + } + + switch (*(od->optArg.argString)) { + case '0': + { + long val = strtol(od->optArg.argString, &pz, 0); + if ((val != 0) || (*pz != NUL)) + break; + } + /* FALLTHROUGH */ + case 'N': + case 'n': + case 'F': + case 'f': + case NUL: + res = false; + break; + case '#': + if (od->optArg.argString[1] != 'f') + break; + res = false; + } + + if (od->fOptState & OPTST_ALLOC_ARG) { + AGFREE(od->optArg.argString); + od->fOptState &= ~OPTST_ALLOC_ARG; + } + od->optArg.argBool = res; +} +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/boolean.c */ diff --git a/src/libopts/check.c b/src/libopts/check.c new file mode 100644 index 0000000..7e75e7e --- /dev/null +++ b/src/libopts/check.c @@ -0,0 +1,177 @@ +/** + * @file check.c + * + * @brief option consistency checks. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/** + * Check for conflicts based on "must" and "cannot" attributes. + */ +static bool +has_conflict(tOptions * pOpts, tOptDesc * od) +{ + if (od->pOptMust != NULL) { + int const * must = od->pOptMust; + + while (*must != NO_EQUIVALENT) { + tOptDesc * p = pOpts->pOptDesc + *(must++); + if (UNUSED_OPT(p)) { + const tOptDesc * ood = pOpts->pOptDesc + must[-1]; + fprintf(stderr, zneed_fmt, pOpts->pzProgName, + od->pz_Name, ood->pz_Name); + return true; + } + } + } + + if (od->pOptCant != NULL) { + int const * cant = od->pOptCant; + + while (*cant != NO_EQUIVALENT) { + tOptDesc * p = pOpts->pOptDesc + *(cant++); + if (SELECTED_OPT(p)) { + const tOptDesc * ood = pOpts->pOptDesc + cant[-1]; + fprintf(stderr, zconflict_fmt, pOpts->pzProgName, + od->pz_Name, ood->pz_Name); + return true; + } + } + } + + return false; +} + +/** + * Check that the option occurs often enough. Too often is already checked. + */ +static bool +occurs_enough(tOptions * pOpts, tOptDesc * pOD) +{ + (void)pOpts; + + /* + * IF the occurrence counts have been satisfied, + * THEN there is no problem. + */ + if (pOD->optOccCt >= pOD->optMinCt) + return true; + + /* + * IF MUST_SET means SET and PRESET are okay, + * so min occurrence count doesn't count + */ + if ( (pOD->fOptState & OPTST_MUST_SET) + && (pOD->fOptState & (OPTST_PRESET | OPTST_SET)) ) + return true; + + if (pOD->optMinCt > 1) + fprintf(stderr, zneed_more, pOpts->pzProgName, pOD->pz_Name, + pOD->optMinCt); + else fprintf(stderr, zneed_one, pOpts->pzProgName, pOD->pz_Name); + return false; +} + +/** + * Verify option consistency. + * + * Make sure that the argument list passes our consistency tests. + */ +static bool +is_consistent(tOptions * pOpts) +{ + tOptDesc * pOD = pOpts->pOptDesc; + int oCt = pOpts->presetOptCt; + + /* + * FOR each of "oCt" options, ... + */ + for (;;) { + /* + * IF the current option was provided on the command line + * THEN ensure that any "MUST" requirements are not + * "DEFAULT" (unspecified) *AND* ensure that any + * "CANT" options have not been SET or DEFINED. + */ + if (SELECTED_OPT(pOD)) { + if (has_conflict(pOpts, pOD)) + return false; + } + + /* + * IF this option is not equivalenced to another, + * OR it is equivalenced to itself (is the equiv. root) + * THEN we need to make sure it occurs often enough. + */ + if ( (pOD->optEquivIndex == NO_EQUIVALENT) + || (pOD->optEquivIndex == pOD->optIndex) ) + + if (! occurs_enough(pOpts, pOD)) + return false; + + if (--oCt <= 0) + break; + pOD++; + } + + /* + * IF we are stopping on errors, check to see if any remaining + * arguments are required to be there or prohibited from being there. + */ + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { + + /* + * Check for prohibition + */ + if ((pOpts->fOptSet & OPTPROC_NO_ARGS) != 0) { + if (pOpts->origArgCt > pOpts->curOptIdx) { + fprintf(stderr, zNoArgs, pOpts->pzProgName); + return false; + } + } + + /* + * ELSE not prohibited, check for being required + */ + else if ((pOpts->fOptSet & OPTPROC_ARGS_REQ) != 0) { + if (pOpts->origArgCt <= pOpts->curOptIdx) { + fprintf(stderr, zargs_must, pOpts->pzProgName); + return false; + } + } + } + + return true; +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/check.c */ diff --git a/src/libopts/compat/_Noreturn.h b/src/libopts/compat/_Noreturn.h new file mode 100644 index 0000000..c44ad89 --- /dev/null +++ b/src/libopts/compat/_Noreturn.h @@ -0,0 +1,10 @@ +#if !defined _Noreturn && __STDC_VERSION__ < 201112 +# if (3 <= __GNUC__ || (__GNUC__ == 2 && 8 <= __GNUC_MINOR__) \ + || 0x5110 <= __SUNPRO_C) +# define _Noreturn __attribute__ ((__noreturn__)) +# elif 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn +# endif +#endif diff --git a/src/libopts/compat/compat.h b/src/libopts/compat/compat.h new file mode 100644 index 0000000..70a5652 --- /dev/null +++ b/src/libopts/compat/compat.h @@ -0,0 +1,383 @@ +/* -*- Mode: C -*- + * + * compat.h is free software. + * This file is part of AutoGen and AutoOpts. + * + * AutoGen Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/** + * \file compat.h + * fake the preprocessor into handlng stuff portability + */ +#ifndef COMPAT_H_GUARD +#define COMPAT_H_GUARD 1 + +#if defined(HAVE_CONFIG_H) +# include + +#elif defined(_WIN32) && !defined(__CYGWIN__) +# include "windows-config.h" + +#else +# error "compat.h" requires "config.h" + choke me. +#endif + + +#ifndef HAVE_STRSIGNAL +# ifndef HAVE_RAW_DECL_STRSIGNAL + char * strsignal(int signo); +# endif +#endif + +#define _GNU_SOURCE 1 /* for strsignal in GNU's libc */ +#define __USE_GNU 1 /* exact same thing as above */ +#define __EXTENSIONS__ 1 /* and another way to call for it */ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * SYSTEM HEADERS: + */ +#include +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#include +#if HAVE_SYS_PROCSET_H +# include +#endif +#include +#ifdef HAVE_SYS_WAIT_H +# include +#endif + +#if defined( HAVE_SOLARIS_SYSINFO ) +# include +#elif defined( HAVE_UNAME_SYSCALL ) +# include +#endif + +#ifdef DAEMON_ENABLED +# if HAVE_SYS_STROPTS_H +# include +# endif + +# if HAVE_SYS_SOCKET_H +# include +# endif + +# if ! defined(HAVE_SYS_POLL_H) && ! defined(HAVE_SYS_SELECT_H) +# error This system cannot support daemon processing + Choke Me. +# endif + +# if HAVE_SYS_POLL_H +# include +# endif + +# if HAVE_SYS_SELECT_H +# include +# endif + +# if HAVE_NETINET_IN_H +# include +# endif + +# if HAVE_SYS_UN_H +# include +# endif +#endif + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * USER HEADERS: + */ +#include +#include +#include + +/* + * Directory opening stuff: + */ +# if defined (_POSIX_SOURCE) +/* Posix does not require that the d_ino field be present, and some + systems do not provide it. */ +# define REAL_DIR_ENTRY(dp) 1 +# else /* !_POSIX_SOURCE */ +# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) +# endif /* !_POSIX_SOURCE */ + +# if defined (HAVE_DIRENT_H) +# include +# define D_NAMLEN(dirent) strlen((dirent)->d_name) +# else /* !HAVE_DIRENT_H */ +# define dirent direct +# define D_NAMLEN(dirent) (dirent)->d_namlen +# if defined (HAVE_SYS_NDIR_H) +# include +# endif /* HAVE_SYS_NDIR_H */ +# if defined (HAVE_SYS_DIR_H) +# include +# endif /* HAVE_SYS_DIR_H */ +# if defined (HAVE_NDIR_H) +# include +# endif /* HAVE_NDIR_H */ +# endif /* !HAVE_DIRENT_H */ + +#include +#ifdef HAVE_FCNTL_H +# include +#endif +#ifndef O_NONBLOCK +# define O_NONBLOCK FNDELAY +#endif + +#if defined(HAVE_LIBGEN) && defined(HAVE_LIBGEN_H) +# include +#endif + +#if defined(HAVE_LIMITS_H) /* this is also in options.h */ +# include +#elif defined(HAVE_SYS_LIMITS_H) +# include +#endif /* HAVE_LIMITS/SYS_LIMITS_H */ + +#include +#include +#include + +#if defined(HAVE_STDINT_H) +# include + +#elif defined(HAVE_INTTYPES_H) +# include +#endif + +#include +#include +#include + +#ifdef HAVE_UTIME_H +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#if defined(HAVE_STDBOOL_H) +# include +#elif ! defined(bool) + typedef enum { false = 0, true = 1 } _Bool; +# define bool _Bool + + /* The other macros must be usable in preprocessor directives. */ +# define false 0 +# define true 1 +#endif + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * FIXUPS and CONVIENCE STUFF: + */ +#ifdef __cplusplus +# define EXTERN extern "C" +#else +# define EXTERN extern +#endif + +/* some systems #def errno! and others do not declare it!! */ +#ifndef errno + extern int errno; +#endif + +/* Some machines forget this! */ + +# ifndef EXIT_FAILURE +# define EXIT_SUCCESS 0 +# define EXIT_FAILURE 1 +# endif + +#ifndef NUL +# define NUL '\0' +#endif + +#ifndef NULL +# define NULL 0 +#endif + +#if !defined (MAXPATHLEN) && defined (HAVE_SYS_PARAM_H) +# include +#endif /* !MAXPATHLEN && HAVE_SYS_PARAM_H */ + +#if !defined (MAXPATHLEN) && defined (PATH_MAX) +# define MAXPATHLEN PATH_MAX +#endif /* !MAXPATHLEN && PATH_MAX */ + +#if !defined (MAXPATHLEN) && defined(_MAX_PATH) +# define PATH_MAX _MAX_PATH +# define MAXPATHLEN _MAX_PATH +#endif + +#if !defined (MAXPATHLEN) +# define MAXPATHLEN 4096 +#endif /* MAXPATHLEN */ + +#define AG_PATH_MAX ((size_t)MAXPATHLEN) + +#ifndef LONG_MAX +# define LONG_MAX ~(1L << (8*sizeof(long) -1)) +# define INT_MAX ~(1 << (8*sizeof(int) -1)) +#endif + +#ifndef ULONG_MAX +# define ULONG_MAX ~(OUL) +# define UINT_MAX ~(OU) +#endif + +#ifndef SHORT_MAX +# define SHORT_MAX ~(1 << (8*sizeof(short) - 1)) +#else +# define USHORT_MAX ~(OUS) +#endif + +#ifndef HAVE_INT8_T + typedef signed char int8_t; +# define HAVE_INT8_T 1 +#endif +#ifndef HAVE_UINT8_T + typedef unsigned char uint8_t; +# define HAVE_UINT8_T 1 +#endif +#ifndef HAVE_INT16_T + typedef signed short int16_t; +# define HAVE_INT16_T 1 +#endif +#ifndef HAVE_UINT16_T + typedef unsigned short uint16_t; +# define HAVE_UINT16_T 1 +#endif + +#ifndef HAVE_INT32_T +# if SIZEOF_INT == 4 + typedef signed int int32_t; +# elif SIZEOF_LONG == 4 + typedef signed long int32_t; +# endif +# define HAVE_INT32_T 1 +#endif + +#ifndef HAVE_UINT32_T +# if SIZEOF_INT == 4 + typedef unsigned int uint32_t; +# elif SIZEOF_LONG == 4 + typedef unsigned long uint32_t; +# else +# error Cannot create a uint32_t type. + Choke Me. +# endif +# define HAVE_UINT32_T 1 +#endif + +#ifndef HAVE_INTPTR_T +# if SIZEOF_CHARP == SIZEOF_LONG + typedef signed long intptr_t; +# else + typedef signed int intptr_t; +# endif +# define HAVE_INTPTR_T 1 +#endif + +#ifndef HAVE_UINTPTR_T +# if SIZEOF_CHARP == SIZEOF_LONG + typedef unsigned long intptr_t; +# else + typedef unsigned int intptr_t; +# endif +# define HAVE_INTPTR_T 1 +#endif + +#ifndef HAVE_UINT_T + typedef unsigned int uint_t; +# define HAVE_UINT_T 1 +#endif + +#ifndef HAVE_SIZE_T + typedef unsigned int size_t; +# define HAVE_SIZE_T 1 +#endif +#ifndef HAVE_WINT_T + typedef unsigned int wint_t; +# define HAVE_WINT_T 1 +#endif +#ifndef HAVE_PID_T + typedef signed int pid_t; +# define HAVE_PID_T 1 +#endif + +/* redefine these for BSD style string libraries */ +#ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +#endif + +#ifdef USE_FOPEN_BINARY +# ifndef FOPEN_BINARY_FLAG +# define FOPEN_BINARY_FLAG "b" +# endif +# ifndef FOPEN_TEXT_FLAG +# define FOPEN_TEXT_FLAG "t" +# endif +#else +# ifndef FOPEN_BINARY_FLAG +# define FOPEN_BINARY_FLAG +# endif +# ifndef FOPEN_TEXT_FLAG +# define FOPEN_TEXT_FLAG +# endif +#endif + +#ifndef STR +# define _STR(s) #s +# define STR(s) _STR(s) +#endif + +/* ##### Pointer sized word ##### */ + +/* FIXME: the MAX stuff in here is broken! */ +#if SIZEOF_CHARP > SIZEOF_INT + typedef long t_word; + #define WORD_MAX LONG_MAX + #define WORD_MIN LONG_MIN +#else /* SIZEOF_CHARP <= SIZEOF_INT */ + typedef int t_word; + #define WORD_MAX INT_MAX + #define WORD_MIN INT_MIN +#endif + +#endif /* COMPAT_H_GUARD */ + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of compat/compat.h */ diff --git a/src/libopts/compat/pathfind.c b/src/libopts/compat/pathfind.c new file mode 100644 index 0000000..e188b72 --- /dev/null +++ b/src/libopts/compat/pathfind.c @@ -0,0 +1,283 @@ +/* -*- Mode: C -*- */ + +/* pathfind.c --- find a FILE MODE along PATH */ + +/* Author: Gary V Vaughan */ + +/* Code: */ + +static char * +pathfind( char const * path, + char const * fname, + char const * mode ); + +#include "compat.h" +#ifndef HAVE_PATHFIND +#if defined(__windows__) && !defined(__CYGWIN__) +static char * +pathfind( char const * path, + char const * fname, + char const * mode ) +{ + return strdup(fname); +} +#else + +static char * make_absolute(char const * string, char const * dot_path); +static char * canonicalize_pathname(char * path); +static char * extract_colon_unit(char * dir, char const * string, int * p_index); + +/** + * local implementation of pathfind. + * @param[in] path colon separated list of directories + * @param[in] fname the name we are hunting for + * @param[in] mode the required file mode + * @returns an allocated string with the full path, or NULL + */ +static char * +pathfind( char const * path, + char const * fname, + char const * mode ) +{ + int p_index = 0; + int mode_bits = 0; + char * res_path = NULL; + char zPath[ AG_PATH_MAX + 1 ]; + + if (strchr( mode, 'r' )) mode_bits |= R_OK; + if (strchr( mode, 'w' )) mode_bits |= W_OK; + if (strchr( mode, 'x' )) mode_bits |= X_OK; + + /* + * FOR each non-null entry in the colon-separated path, DO ... + */ + for (;;) { + DIR * dirP; + char * colon_unit = extract_colon_unit( zPath, path, &p_index ); + + if (colon_unit == NULL) + break; + + dirP = opendir( colon_unit ); + + /* + * IF the directory is inaccessable, THEN next directory + */ + if (dirP == NULL) + continue; + + for (;;) { + struct dirent *entP = readdir( dirP ); + + if (entP == (struct dirent *)NULL) + break; + + /* + * IF the file name matches the one we are looking for, ... + */ + if (strcmp(entP->d_name, fname) == 0) { + char * abs_name = make_absolute(fname, colon_unit); + + /* + * Make sure we can access it in the way we want + */ + if (access(abs_name, mode_bits) >= 0) { + /* + * We can, so normalize the name and return it below + */ + res_path = canonicalize_pathname(abs_name); + } + + free(abs_name); + break; + } + } + + closedir( dirP ); + + if (res_path != NULL) + break; + } + + return res_path; +} + +/* + * Turn STRING (a pathname) into an absolute pathname, assuming that + * DOT_PATH contains the symbolic location of `.'. This always returns + * a new string, even if STRING was an absolute pathname to begin with. + */ +static char * +make_absolute( char const * string, char const * dot_path ) +{ + char * result; + int result_len; + + if (!dot_path || *string == '/') { + result = strdup( string ); + } else { + if (dot_path && dot_path[0]) { + result = malloc( 2 + strlen( dot_path ) + strlen( string ) ); + strcpy( result, dot_path ); + result_len = (int)strlen(result); + if (result[result_len - 1] != '/') { + result[result_len++] = '/'; + result[result_len] = '\0'; + } + } else { + result = malloc( 3 + strlen( string ) ); + result[0] = '.'; result[1] = '/'; result[2] = '\0'; + result_len = 2; + } + + strcpy( result + result_len, string ); + } + + return result; +} + +/* + * Canonicalize PATH, and return a new path. The new path differs from + * PATH in that: + * + * Multiple `/'s are collapsed to a single `/'. + * Leading `./'s are removed. + * Trailing `/.'s are removed. + * Trailing `/'s are removed. + * Non-leading `../'s and trailing `..'s are handled by removing + * portions of the path. + */ +static char * +canonicalize_pathname( char *path ) +{ + int i, start; + char stub_char, *result; + + /* The result cannot be larger than the input PATH. */ + result = strdup( path ); + + stub_char = (*path == '/') ? '/' : '.'; + + /* Walk along RESULT looking for things to compact. */ + i = 0; + while (result[i]) { + while (result[i] != '\0' && result[i] != '/') + i++; + + start = i++; + + /* If we didn't find any slashes, then there is nothing left to + * do. + */ + if (!result[start]) + break; + + /* Handle multiple `/'s in a row. */ + while (result[i] == '/') + i++; + +#if !defined (apollo) + if ((start + 1) != i) +#else + if ((start + 1) != i && (start != 0 || i != 2)) +#endif /* apollo */ + { + strcpy( result + start + 1, result + i ); + i = start + 1; + } + + /* Handle backquoted `/'. */ + if (start > 0 && result[start - 1] == '\\') + continue; + + /* Check for trailing `/', and `.' by itself. */ + if ((start && !result[i]) + || (result[i] == '.' && !result[i+1])) { + result[--i] = '\0'; + break; + } + + /* Check for `../', `./' or trailing `.' by itself. */ + if (result[i] == '.') { + /* Handle `./'. */ + if (result[i + 1] == '/') { + strcpy( result + i, result + i + 1 ); + i = (start < 0) ? 0 : start; + continue; + } + + /* Handle `../' or trailing `..' by itself. */ + if (result[i + 1] == '.' && + (result[i + 2] == '/' || !result[i + 2])) { + while (--start > -1 && result[start] != '/') + ; + memmove( result + start + 1, result + i + 2, strlen(result + i + 2) + 1 ); + i = (start < 0) ? 0 : start; + continue; + } + } + } + + if (!*result) { + *result = stub_char; + result[1] = '\0'; + } + + return result; +} + +/* + * Given a string containing units of information separated by colons, + * return the next one pointed to by (P_INDEX), or NULL if there are no + * more. Advance (P_INDEX) to the character after the colon. + */ +static char * +extract_colon_unit(char * pzDir, char const * string, int * p_index) +{ + char * pzDest = pzDir; + int ix = *p_index; + + if (string == NULL) + return NULL; + + if ((unsigned)ix >= strlen( string )) + return NULL; + + { + char const * pzSrc = string + ix; + + while (*pzSrc == ':') pzSrc++; + + for (;;) { + char ch = (*(pzDest++) = *(pzSrc++)); + switch (ch) { + case ':': + pzDest[-1] = NUL; + /* FALLTHROUGH */ + case NUL: + goto copy_done; + } + + if ((unsigned long)(pzDest - pzDir) >= AG_PATH_MAX) + break; + } copy_done:; + + ix = (int)(pzSrc - string); + } + + if (*pzDir == NUL) + return NULL; + + *p_index = ix; + return pzDir; +} +#endif /* __windows__ / __CYGWIN__ */ +#endif /* HAVE_PATHFIND */ + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of compat/pathfind.c */ diff --git a/src/libopts/compat/snprintf.c b/src/libopts/compat/snprintf.c new file mode 100644 index 0000000..eccea1f --- /dev/null +++ b/src/libopts/compat/snprintf.c @@ -0,0 +1,62 @@ + +#ifndef HAVE_VPRINTF +#include "choke-me: no vprintf and no snprintf" + choke me. +#endif + +#if defined(HAVE_STDARG_H) +# include +# ifndef VA_START +# define VA_START(a, f) va_start(a, f) +# define VA_END(a) va_end(a) +# endif /* VA_START */ +# define SNV_USING_STDARG_H + +#elif defined(HAVE_VARARGS_H) +# include +# ifndef VA_START +# define VA_START(a, f) va_start(a) +# define VA_END(a) va_end(a) +# endif /* VA_START */ +# undef SNV_USING_STDARG_H + +#else +# include "must-have-stdarg-or-varargs" + choke me. +#endif + +static int +snprintf(char *str, size_t n, char const *fmt, ...) +{ + va_list ap; + int rval; + +#ifdef VSPRINTF_CHARSTAR + char *rp; + VA_START(ap, fmt); + rp = vsprintf(str, fmt, ap); + VA_END(ap); + rval = strlen(rp); + +#else + VA_START(ap, fmt); + rval = vsprintf(str, fmt, ap); + VA_END(ap); +#endif + + if (rval > n) { + fprintf(stderr, "snprintf buffer overrun %d > %d\n", rval, (int)n); + abort(); + } + return rval; +} + +static int +vsnprintf( char *str, size_t n, char const *fmt, va_list ap ) +{ +#ifdef VSPRINTF_CHARSTAR + return (strlen(vsprintf(str, fmt, ap))); +#else + return (vsprintf(str, fmt, ap)); +#endif +} diff --git a/src/libopts/compat/strchr.c b/src/libopts/compat/strchr.c new file mode 100644 index 0000000..f409387 --- /dev/null +++ b/src/libopts/compat/strchr.c @@ -0,0 +1,66 @@ +/* + SYNOPSIS + #include + + char *strchr(char const *s, int c); + + char *strrchr(char const *s, int c); + + DESCRIPTION + The strchr() function returns a pointer to the first occurrence of the + character c in the string s. + + The strrchr() function returns a pointer to the last occurrence of the + character c in the string s. + + Here "character" means "byte" - these functions do not work with wide + or multi-byte characters. + + RETURN VALUE + The strchr() and strrchr() functions return a pointer to the matched + character or NULL if the character is not found. + + CONFORMING TO + SVID 3, POSIX, BSD 4.3, ISO 9899 +*/ + +static char * +strchr(char const *s, int c); + +static char * +strrchr(char const *s, int c); + +static char * +strchr(char const *s, int c) +{ + do { + if ((unsigned char)*s == (unsigned char)c) + return s; + + } while (*(++s) != NUL); + + return NULL; +} + +static char * +strrchr(char const *s, int c) +{ + char const *e = s + strlen(s); + + for (;;) { + if (--e < s) + break; + + if ((unsigned char)*e == (unsigned char)c) + return e; + } + return NULL; +} + +/* + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of compat/strsignal.c */ diff --git a/src/libopts/compat/strdup.c b/src/libopts/compat/strdup.c new file mode 100644 index 0000000..f3a4077 --- /dev/null +++ b/src/libopts/compat/strdup.c @@ -0,0 +1,22 @@ +/* + * Platforms without strdup ?!?!?! + */ + +static char * +strdup( char const *s ); + +static char * +strdup( char const *s ) +{ + char *cp; + + if (s == NULL) + return NULL; + + cp = (char *) AGALOC((unsigned) (strlen(s)+1), "strdup"); + + if (cp != NULL) + (void) strcpy(cp, s); + + return cp; +} diff --git a/src/libopts/compat/windows-config.h b/src/libopts/compat/windows-config.h new file mode 100644 index 0000000..7ce1636 --- /dev/null +++ b/src/libopts/compat/windows-config.h @@ -0,0 +1,144 @@ + +/** + * \file windows-config.h + * + * This file contains all of the routines that must be linked into + * an executable to use the generated option processing. The optional + * routines are in separately compiled modules so that they will not + * necessarily be linked in. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +#ifndef WINDOWS_CONFIG_HACKERY +#define WINDOWS_CONFIG_HACKERY 1 + +/* + * The definitions below have been stolen from NTP's config.h for Windows. + * However, they may be kept here in order to keep libopts independent from + * the NTP project. + */ +#ifndef __windows__ +# define __windows__ 4 +#endif + +/* + * Miscellaneous functions that Microsoft maps to other names + */ +#define snprintf _snprintf + +#define SIZEOF_INT 4 +#define SIZEOF_CHARP 4 +#define SIZEOF_LONG 4 +#define SIZEOF_SHORT 2 + +#define HAVE_LIMITS_H 1 +#define HAVE_STRDUP 1 +#define HAVE_STRCHR 1 +#define HAVE_FCNTL_H 1 + +/* + * VS.NET's version of wspiapi.h has a bug in it where it assigns a value + * to a variable inside an if statement. It should be comparing them. + * We prevent inclusion since we are not using this code so we don't have + * to see the warning messages + */ +#ifndef _WSPIAPI_H_ +#define _WSPIAPI_H_ +#endif + +/* Prevent inclusion of winsock.h in windows.h */ +#ifndef _WINSOCKAPI_ +#define _WINSOCKAPI_ +#endif + +#ifndef __RPCASYNC_H__ +#define __RPCASYNC_H__ +#endif + +/* Include Windows headers */ +#include +#include +#include + +/* + * Compatibility declarations for Windows, assuming SYS_WINNT + * has been defined. + */ +#define strdup _strdup +#define stat _stat /* struct stat from */ +#define unlink _unlink +#define fchmod( _x, _y ) +#define ssize_t SSIZE_T + +#include +#define open _open +#define close _close +#define read _read +#define write _write +#define lseek _lseek +#define pipe _pipe +#define dup2 _dup2 + +#define O_RDWR _O_RDWR +#define O_RDONLY _O_RDONLY +#define O_EXCL _O_EXCL + +#ifndef S_ISREG +# define S_IFREG _S_IFREG +# define S_ISREG(mode) (((mode) & S_IFREG) == S_IFREG) +#endif + +#ifndef S_ISDIR +# define S_IFDIR _S_IFDIR +# define S_ISDIR(mode) (((mode) & S_IFDIR) == S_IFDIR) +#endif + +/* C99 exact size integer support. */ +#if defined(HAVE_INTTYPES_H) +# include + +#elif defined(HAVE_STDINT_H) +# include +# define MISSING_INTTYPES_H 1 + +#elif ! defined(ADDED_EXACT_SIZE_INTEGERS) +# define ADDED_EXACT_SIZE_INTEGERS 1 +# define MISSING_INTTYPES_H 1 + + typedef __int8 int8_t; + typedef unsigned __int8 uint8_t; + + typedef __int16 int16_t; + typedef unsigned __int16 uint16_t; + + typedef __int32 int32_t; + typedef unsigned __int32 uint32_t; + + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + + typedef unsigned long uintptr_t; + typedef long intptr_t; +#endif + +#endif /* WINDOWS_CONFIG_HACKERY */ +/* windows-config.h ends here */ diff --git a/src/libopts/configfile.c b/src/libopts/configfile.c new file mode 100644 index 0000000..783a9d8 --- /dev/null +++ b/src/libopts/configfile.c @@ -0,0 +1,1337 @@ +/** + * \file configfile.c + * + * configuration/rc/ini file handling. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/** + * Skip over some unknown attribute + * @param[in] txt start of skpped text + * @returns character after skipped text + */ +inline static char const * +skip_unkn(char const * txt) +{ + txt = BRK_END_XML_TOKEN_CHARS(txt); + return (*txt == NUL) ? NULL : txt; +} + +/*=export_func configFileLoad + * + * what: parse a configuration file + * arg: + char const * + fname + the file to load + + * + * ret_type: const tOptionValue * + * ret_desc: An allocated, compound value structure + * + * doc: + * This routine will load a named configuration file and parse the + * text as a hierarchically valued option. The option descriptor + * created from an option definition file is not used via this interface. + * The returned value is "named" with the input file name and is of + * type "@code{OPARG_TYPE_HIERARCHY}". It may be used in calls to + * @code{optionGetValue()}, @code{optionNextValue()} and + * @code{optionUnloadNested()}. + * + * err: + * If the file cannot be loaded or processed, @code{NULL} is returned and + * @var{errno} is set. It may be set by a call to either @code{open(2)} + * @code{mmap(2)} or other file system calls, or it may be: + * @itemize @bullet + * @item + * @code{ENOENT} - the file was not found. + * @item + * @code{ENOMSG} - the file was empty. + * @item + * @code{EINVAL} - the file contents are invalid -- not properly formed. + * @item + * @code{ENOMEM} - not enough memory to allocate the needed structures. + * @end itemize +=*/ +const tOptionValue * +configFileLoad(char const * fname) +{ + tmap_info_t cfgfile; + tOptionValue * res = NULL; + tOptionLoadMode save_mode = option_load_mode; + + char * txt = text_mmap(fname, PROT_READ, MAP_PRIVATE, &cfgfile); + + if (TEXT_MMAP_FAILED_ADDR(txt)) + return NULL; /* errno is set */ + + option_load_mode = OPTION_LOAD_COOKED; + res = optionLoadNested(txt, fname, strlen(fname)); + + if (res == NULL) { + int err = errno; + text_munmap(&cfgfile); + errno = err; + } else + text_munmap(&cfgfile); + + option_load_mode = save_mode; + return res; +} + + +/*=export_func optionFindValue + * + * what: find a hierarcicaly valued option instance + * arg: + const tOptDesc * + odesc + an option with a nested arg type + + * arg: + char const * + name + name of value to find + + * arg: + char const * + val + the matching value + + * + * ret_type: const tOptionValue * + * ret_desc: a compound value structure + * + * doc: + * This routine will find an entry in a nested value option or configurable. + * It will search through the list and return a matching entry. + * + * err: + * The returned result is NULL and errno is set: + * @itemize @bullet + * @item + * @code{EINVAL} - the @code{pOptValue} does not point to a valid + * hierarchical option value. + * @item + * @code{ENOENT} - no entry matched the given name. + * @end itemize +=*/ +const tOptionValue * +optionFindValue(const tOptDesc * odesc, char const * name, char const * val) +{ + const tOptionValue * res = NULL; + + if ( (odesc == NULL) + || (OPTST_GET_ARGTYPE(odesc->fOptState) != OPARG_TYPE_HIERARCHY)) { + errno = EINVAL; + } + + else if (odesc->optCookie == NULL) { + errno = ENOENT; + } + + else do { + tArgList * argl = odesc->optCookie; + int argct = argl->useCt; + void ** poptv = (void **)(argl->apzArgs); + + if (argct == 0) { + errno = ENOENT; + break; + } + + if (name == NULL) { + res = (tOptionValue *)*poptv; + break; + } + + while (--argct >= 0) { + const tOptionValue * ov = *(poptv++); + const tOptionValue * rv = optionGetValue(ov, name); + + if (rv == NULL) + continue; + + if (val == NULL) { + res = ov; + break; + } + } + if (res == NULL) + errno = ENOENT; + } while (false); + + return res; +} + + +/*=export_func optionFindNextValue + * + * FIXME: the handling of 'pzName' and 'pzVal' is just wrong. + * + * what: find a hierarcicaly valued option instance + * arg: + const tOptDesc * + odesc + an option with a nested arg type + + * arg: + const tOptionValue * + pPrevVal + the last entry + + * arg: + char const * + name + name of value to find + + * arg: + char const * + value + the matching value + + * + * ret_type: const tOptionValue * + * ret_desc: a compound value structure + * + * doc: + * This routine will find the next entry in a nested value option or + * configurable. It will search through the list and return the next entry + * that matches the criteria. + * + * err: + * The returned result is NULL and errno is set: + * @itemize @bullet + * @item + * @code{EINVAL} - the @code{pOptValue} does not point to a valid + * hierarchical option value. + * @item + * @code{ENOENT} - no entry matched the given name. + * @end itemize +=*/ +tOptionValue const * +optionFindNextValue(const tOptDesc * odesc, const tOptionValue * pPrevVal, + char const * pzName, char const * pzVal) +{ + bool old_found = false; + tOptionValue * res = NULL; + + (void)pzName; + (void)pzVal; + + if ( (odesc == NULL) + || (OPTST_GET_ARGTYPE(odesc->fOptState) != OPARG_TYPE_HIERARCHY)) { + errno = EINVAL; + } + + else if (odesc->optCookie == NULL) { + errno = ENOENT; + } + + else do { + tArgList * argl = odesc->optCookie; + int ct = argl->useCt; + void ** poptv = (void **)argl->apzArgs; + + while (--ct >= 0) { + tOptionValue * pOV = *(poptv++); + if (old_found) { + res = pOV; + break; + } + if (pOV == pPrevVal) + old_found = true; + } + if (res == NULL) + errno = ENOENT; + } while (false); + + return res; +} + + +/*=export_func optionGetValue + * + * what: get a specific value from a hierarcical list + * arg: + const tOptionValue * + pOptValue + a hierarchcal value + + * arg: + char const * + valueName + name of value to get + + * + * ret_type: const tOptionValue * + * ret_desc: a compound value structure + * + * doc: + * This routine will find an entry in a nested value option or configurable. + * If "valueName" is NULL, then the first entry is returned. Otherwise, + * the first entry with a name that exactly matches the argument will be + * returned. If there is no matching value, NULL is returned and errno is + * set to ENOENT. If the provided option value is not a hierarchical value, + * NULL is also returned and errno is set to EINVAL. + * + * err: + * The returned result is NULL and errno is set: + * @itemize @bullet + * @item + * @code{EINVAL} - the @code{pOptValue} does not point to a valid + * hierarchical option value. + * @item + * @code{ENOENT} - no entry matched the given name. + * @end itemize +=*/ +tOptionValue const * +optionGetValue(tOptionValue const * oov, char const * vname) +{ + tArgList * arg_list; + tOptionValue * res = NULL; + + if ((oov == NULL) || (oov->valType != OPARG_TYPE_HIERARCHY)) { + errno = EINVAL; + return res; + } + arg_list = oov->v.nestVal; + + if (arg_list->useCt > 0) { + int ct = arg_list->useCt; + void ** ovlist = (void **)(arg_list->apzArgs); + + if (vname == NULL) { + res = (tOptionValue *)*ovlist; + + } else do { + tOptionValue * opt_val = *(ovlist++); + if (strcmp(opt_val->pzName, vname) == 0) { + res = opt_val; + break; + } + } while (--ct > 0); + } + if (res == NULL) + errno = ENOENT; + return res; +} + +/*=export_func optionNextValue + * + * what: get the next value from a hierarchical list + * arg: + const tOptionValue * + pOptValue + a hierarchcal list value + + * arg: + const tOptionValue * + pOldValue + a value from this list + + * + * ret_type: const tOptionValue * + * ret_desc: a compound value structure + * + * doc: + * This routine will return the next entry after the entry passed in. At the + * end of the list, NULL will be returned. If the entry is not found on the + * list, NULL will be returned and "@var{errno}" will be set to EINVAL. + * The "@var{pOldValue}" must have been gotten from a prior call to this + * routine or to "@code{opitonGetValue()}". + * + * err: + * The returned result is NULL and errno is set: + * @itemize @bullet + * @item + * @code{EINVAL} - the @code{pOptValue} does not point to a valid + * hierarchical option value or @code{pOldValue} does not point to a + * member of that option value. + * @item + * @code{ENOENT} - the supplied @code{pOldValue} pointed to the last entry. + * @end itemize +=*/ +tOptionValue const * +optionNextValue(tOptionValue const * ov_list,tOptionValue const * oov ) +{ + tArgList * arg_list; + tOptionValue * res = NULL; + int err = EINVAL; + + if ((ov_list == NULL) || (ov_list->valType != OPARG_TYPE_HIERARCHY)) { + errno = EINVAL; + return NULL; + } + arg_list = ov_list->v.nestVal; + { + int ct = arg_list->useCt; + void ** o_list = (void **)(arg_list->apzArgs); + + while (ct-- > 0) { + tOptionValue * nov = *(o_list++); + if (nov == oov) { + if (ct == 0) { + err = ENOENT; + + } else { + err = 0; + res = (tOptionValue *)*o_list; + } + break; + } + } + } + if (err != 0) + errno = err; + return res; +} + +/** + * Load a file containing presetting information (a configuration file). + */ +static void +file_preset(tOptions * opts, char const * fname, int dir) +{ + tmap_info_t cfgfile; + tOptState optst = OPTSTATE_INITIALIZER(PRESET); + opt_state_mask_t st_flags = optst.flags; + opt_state_mask_t fl_save = opts->fOptSet; + char * ftext = + text_mmap(fname, PROT_READ|PROT_WRITE, MAP_PRIVATE, &cfgfile); + + if (TEXT_MMAP_FAILED_ADDR(ftext)) + return; + + /* + * While processing config files, we ignore errors. + */ + opts->fOptSet &= ~OPTPROC_ERRSTOP; + + if (dir == DIRECTION_CALLED) { + st_flags = OPTST_DEFINED; + dir = DIRECTION_PROCESS; + } + + /* + * IF this is called via "optionProcess", then we are presetting. + * This is the default and the PRESETTING bit will be set. + * If this is called via "optionFileLoad", then the bit is not set + * and we consider stuff set herein to be "set" by the client program. + */ + if ((opts->fOptSet & OPTPROC_PRESETTING) == 0) + st_flags = OPTST_SET; + + do { + optst.flags = st_flags; + ftext = SPN_WHITESPACE_CHARS(ftext); + + if (IS_VAR_FIRST_CHAR(*ftext)) { + ftext = handle_cfg(opts, &optst, ftext, dir); + + } else switch (*ftext) { + case '<': + if (IS_VAR_FIRST_CHAR(ftext[1])) + ftext = handle_struct(opts, &optst, ftext, dir); + + else switch (ftext[1]) { + case '?': + ftext = handle_directive(opts, ftext); + break; + + case '!': + ftext = handle_comment(ftext); + break; + + case '/': + ftext = strchr(ftext + 2, '>'); + if (ftext++ != NULL) + break; + /* FALLTHROUGH */ + + default: + ftext = NULL; + } + if (ftext == NULL) + goto all_done; + break; + + case '[': + ftext = handle_section(opts, ftext); + break; + + case '#': + ftext = strchr(ftext + 1, NL); + break; + + default: + goto all_done; /* invalid format */ + } + } while (ftext != NULL); + + all_done: + text_munmap(&cfgfile); + opts->fOptSet = fl_save; +} + +/** + * "txt" points to a "". + */ +static char * +handle_comment(char * txt) +{ + char * pz = strstr(txt, "-->"); + if (pz != NULL) + pz += 3; + return pz; +} + +/** + * "txt" points to the start of some value name. + * The end of the entry is the end of the line that is not preceded by + * a backslash escape character. The string value is always processed + * in "cooked" mode. + */ +static char * +handle_cfg(tOptions * opts, tOptState * ost, char * txt, int dir) +{ + char * pzName = txt++; + char * pzEnd = strchr(txt, NL); + + if (pzEnd == NULL) + return txt + strlen(txt); + + txt = SPN_VALUE_NAME_CHARS(txt); + txt = SPN_WHITESPACE_CHARS(txt); + if (txt > pzEnd) { + name_only: + *pzEnd++ = NUL; + load_opt_line(opts, ost, pzName, dir, OPTION_LOAD_UNCOOKED); + return pzEnd; + } + + /* + * Either the first character after the name is a ':' or '=', + * or else we must have skipped over white space. Anything else + * is an invalid format and we give up parsing the text. + */ + if ((*txt == '=') || (*txt == ':')) { + txt = SPN_WHITESPACE_CHARS(txt+1); + if (txt > pzEnd) + goto name_only; + } else if (! IS_WHITESPACE_CHAR(txt[-1])) + return NULL; + + /* + * IF the value is continued, remove the backslash escape and push "pzEnd" + * on to a newline *not* preceded by a backslash. + */ + if (pzEnd[-1] == '\\') { + char * pcD = pzEnd-1; + char * pcS = pzEnd; + + for (;;) { + char ch = *(pcS++); + switch (ch) { + case NUL: + pcS = NULL; + /* FALLTHROUGH */ + + case NL: + *pcD = NUL; + pzEnd = pcS; + goto copy_done; + + case '\\': + if (*pcS == NL) + ch = *(pcS++); + /* FALLTHROUGH */ + default: + *(pcD++) = ch; + } + } copy_done:; + + } else { + /* + * The newline was not preceded by a backslash. NUL it out + */ + *(pzEnd++) = NUL; + } + + /* + * "pzName" points to what looks like text for one option/configurable. + * It is NUL terminated. Process it. + */ + load_opt_line(opts, ost, pzName, dir, OPTION_LOAD_UNCOOKED); + + return pzEnd; +} + +/** + * "txt" points to a "'); + if (txt != NULL) + txt++; + return txt; +# undef DIRECTIVE_TABLE +} + +/** + * handle AutoOpts mode flags. + * + * @param[in,out] opts program option descriptor + * @param[in] txt scanning pointer + * @returns the next character to look at + */ +static char * +aoflags_directive(tOptions * opts, char * txt) +{ + char * pz; + + pz = SPN_WHITESPACE_CHARS(txt+1); + txt = strchr(pz, '>'); + if (txt != NULL) { + + size_t len = (unsigned)(txt - pz); + char * ftxt = AGALOC(len + 1, "aoflags"); + + memcpy(ftxt, pz, len); + ftxt[len] = NUL; + set_usage_flags(opts, ftxt); + AGFREE(ftxt); + + txt++; + } + + return txt; +} + +/** + * handle program segmentation of config file. + * + * @param[in,out] opts program option descriptor + * @param[in] txt scanning pointer + * @returns the next character to look at + */ +static char * +program_directive(tOptions * opts, char * txt) +{ + size_t name_len = strlen(opts->pzProgName); + + for (;; txt += zCfgProg_LEN) { + txt = SPN_WHITESPACE_CHARS(txt); + + if ( (strneqvcmp(txt, opts->pzProgName, (int)name_len) == 0) + && (IS_END_XML_TOKEN_CHAR(txt[name_len])) ) + + return txt + name_len; + + txt = strstr(txt, zCfgProg); + if (txt == NULL) + return txt; + } + + for (;;) { + if (*txt == NUL) + return NULL; + + if (*(txt++) == '>') + return txt; + } +} + +/** + * "txt" points to a '[' character. + * The "traditional" [PROG_NAME] segmentation of the config file. + * Do not ever mix with the "" variation. + * The templates reject program names over 16 characters. + * + * @param[in,out] opts program option descriptor + * @param[in] txt scanning pointer + * @returns the next character to look at + */ +static char * +handle_section(tOptions * opts, char * txt) +{ + size_t len = strlen(opts->pzPROGNAME); + if ( (strncmp(txt+1, opts->pzPROGNAME, len) == 0) + && (txt[len+1] == ']')) + return strchr(txt + len + 2, NL); + + if (len > 16) + return NULL; + + { + char z[24] = "["; + memcpy(z+1, opts->pzPROGNAME, len); + z[++len] = ']'; + z[++len] = NUL; + txt = strstr(txt, z); + } + + if (txt != NULL) + txt = strchr(txt, NL); + return txt; +} + +/** + * parse XML encodings + */ +static int +parse_xml_encoding(char ** ppz) +{ +# define XMLTABLE \ + _xmlNm_(amp, '&') \ + _xmlNm_(lt, '<') \ + _xmlNm_(gt, '>') \ + _xmlNm_(ff, '\f') \ + _xmlNm_(ht, '\t') \ + _xmlNm_(cr, '\r') \ + _xmlNm_(vt, '\v') \ + _xmlNm_(bel, '\a') \ + _xmlNm_(nl, NL) \ + _xmlNm_(space, ' ') \ + _xmlNm_(quot, '"') \ + _xmlNm_(apos, '\'') + + static struct { + char const * const nm_str; + unsigned short nm_len; + short nm_val; + } const xml_names[] = { +# define _xmlNm_(_n, _v) { #_n ";", sizeof(#_n), _v }, + XMLTABLE +# undef _xmlNm_ +# undef XMLTABLE + }; + + static int const nm_ct = sizeof(xml_names) / sizeof(xml_names[0]); + int base = 10; + + char * pz = *ppz; + + if (*pz == '#') { + pz++; + goto parse_number; + } + + if (IS_DEC_DIGIT_CHAR(*pz)) { + unsigned long v; + + parse_number: + switch (*pz) { + case 'x': case 'X': + /* + * Some forms specify hex with: &#xNN; + */ + base = 16; + pz++; + break; + + case '0': + /* + *  is hex and  is decimal. Cool. + * Ya gotta love it. + */ + if (pz[1] == '0') + base = 16; + break; + } + + v = strtoul(pz, &pz, base); + if ((*pz != ';') || (v > 0x7F)) + return NUL; + *ppz = pz + 1; + return (int)v; + } + + { + int ix = 0; + do { + if (strncmp(pz, xml_names[ix].nm_str, xml_names[ix].nm_len) + == 0) { + *ppz = pz + xml_names[ix].nm_len; + return xml_names[ix].nm_val; + } + } while (++ix < nm_ct); + } + + return NUL; +} + +/** + * Find the end marker for the named section of XML. + * Trim that text there, trimming trailing white space for all modes + * except for OPTION_LOAD_UNCOOKED. + */ +static char * +trim_xml_text(char * intxt, char const * pznm, tOptionLoadMode mode) +{ + size_t nm_len = strlen(pznm); + char * etext; + + { + char z[64], *pz = z; + + if (nm_len + 4 >= sizeof(z)) + pz = AGALOC(nm_len + 4, "scan name"); + + pz[0] = '<'; + pz[1] = '/'; + memcpy(pz+2, pznm, nm_len); + nm_len += 2; + pz[nm_len++] = '>'; + pz[nm_len] = NUL; + + *intxt = ' '; + etext = strstr(intxt, pz); + if (pz != z) AGFREE(pz); + } + + if (etext == NULL) + return etext; + + { + char * result = etext + nm_len; + + if (mode != OPTION_LOAD_UNCOOKED) + etext = SPN_WHITESPACE_BACK(intxt, etext); + + *etext = NUL; + return result; + } +} + +/** + */ +static void +cook_xml_text(char * pzData) +{ + char * pzs = pzData; + char * pzd = pzData; + char bf[4]; + bf[2] = NUL; + + for (;;) { + int ch = ((int)*(pzs++)) & 0xFF; + switch (ch) { + case NUL: + *pzd = NUL; + return; + + case '&': + ch = parse_xml_encoding(&pzs); + *(pzd++) = (char)ch; + if (ch == NUL) + return; + break; + + case '%': + bf[0] = *(pzs++); + bf[1] = *(pzs++); + if ((bf[0] == NUL) || (bf[1] == NUL)) { + *pzd = NUL; + return; + } + + ch = (int)strtoul(bf, NULL, 16); + /* FALLTHROUGH */ + + default: + *(pzd++) = (char)ch; + } + } +} + +/** + * "txt" points to a '<' character, followed by an alpha. + * The end of the entry is either the "/>" following the name, or else a + * "" string. + */ +static char * +handle_struct(tOptions * opts, tOptState * ost, char * txt, int dir) +{ + tOptionLoadMode mode = option_load_mode; + tOptionValue valu; + + char * pzName = ++txt; + char * pzData; + char * pcNulPoint; + + txt = SPN_VALUE_NAME_CHARS(txt); + pcNulPoint = txt; + valu.valType = OPARG_TYPE_STRING; + + switch (*txt) { + case ' ': + case '\t': + txt = VOIDP(parse_attrs( + opts, SPN_WHITESPACE_CHARS(txt), &mode, &valu)); + if (txt == NULL) + return txt; + if (*txt == '>') + break; + if (*txt != '/') + return NULL; + /* FALLTHROUGH */ + + case '/': + if (txt[1] != '>') + return NULL; + *txt = NUL; + txt += 2; + load_opt_line(opts, ost, pzName, dir, mode); + return txt; + + case '>': + break; + + default: + txt = strchr(txt, '>'); + if (txt != NULL) + txt++; + return txt; + } + + /* + * If we are here, we have a value. "txt" points to a closing angle + * bracket. Separate the name from the value for a moment. + */ + *pcNulPoint = NUL; + pzData = ++txt; + txt = trim_xml_text(txt, pzName, mode); + if (txt == NULL) + return txt; + + /* + * Rejoin the name and value for parsing by "load_opt_line()". + * Erase any attributes parsed by "parse_attrs()". + */ + memset(pcNulPoint, ' ', (size_t)(pzData - pcNulPoint)); + + /* + * If we are getting a "string" value that is to be cooked, + * then process the XML-ish &xx; XML-ish and %XX hex characters. + */ + if ( (valu.valType == OPARG_TYPE_STRING) + && (mode == OPTION_LOAD_COOKED)) + cook_xml_text(pzData); + + /* + * "pzName" points to what looks like text for one option/configurable. + * It is NUL terminated. Process it. + */ + load_opt_line(opts, ost, pzName, dir, mode); + + return txt; +} + +/** + * Load a configuration file. This may be invoked either from + * scanning the "homerc" list, or from a specific file request. + * (see "optionFileLoad()", the implementation for --load-opts) + */ +static void +intern_file_load(tOptions * opts) +{ + uint32_t svfl; + int idx; + int inc; + char f_name[ AG_PATH_MAX+1 ]; + + if (opts->papzHomeList == NULL) + return; + + svfl = opts->fOptSet; + inc = DIRECTION_PRESET; + + /* + * Never stop on errors in config files. + */ + opts->fOptSet &= ~OPTPROC_ERRSTOP; + + /* + * Find the last RC entry (highest priority entry) + */ + for (idx = 0; opts->papzHomeList[ idx+1 ] != NULL; ++idx) ; + + /* + * For every path in the home list, ... *TWICE* We start at the last + * (highest priority) entry, work our way down to the lowest priority, + * handling the immediate options. + * Then we go back up, doing the normal options. + */ + for (;;) { + struct stat sb; + cch_t * path; + + /* + * IF we've reached the bottom end, change direction + */ + if (idx < 0) { + inc = DIRECTION_PROCESS; + idx = 0; + } + + path = opts->papzHomeList[ idx ]; + + /* + * IF we've reached the top end, bail out + */ + if (path == NULL) + break; + + idx += inc; + + if (! optionMakePath(f_name, (int)sizeof(f_name), + path, opts->pzProgPath)) + continue; + + /* + * IF the file name we constructed is a directory, + * THEN append the Resource Configuration file name + * ELSE we must have the complete file name + */ + if (stat(f_name, &sb) != 0) + continue; /* bogus name - skip the home list entry */ + + if (S_ISDIR(sb.st_mode)) { + size_t len = strlen(f_name); + size_t nln = strlen(opts->pzRcName) + 1; + char * pz = f_name + len; + + if (len + 1 + nln >= sizeof(f_name)) + continue; + + if (pz[-1] != DIRCH) + *(pz++) = DIRCH; + memcpy(pz, opts->pzRcName, nln); + } + + file_preset(opts, f_name, inc); + + /* + * IF we are now to skip config files AND we are presetting, + * THEN change direction. We must go the other way. + */ + { + tOptDesc * od = opts->pOptDesc + opts->specOptIdx.save_opts + 1; + if (DISABLED_OPT(od) && PRESETTING(inc)) { + idx -= inc; /* go back and reprocess current file */ + inc = DIRECTION_PROCESS; + } + } + } /* twice for every path in the home list, ... */ + + opts->fOptSet = svfl; +} + +/*=export_func optionFileLoad + * + * what: Load the locatable config files, in order + * + * arg: + tOptions * + opts + program options descriptor + + * arg: + char const * + prog + program name + + * + * ret_type: int + * ret_desc: 0 -> SUCCESS, -1 -> FAILURE + * + * doc: + * + * This function looks in all the specified directories for a configuration + * file ("rc" file or "ini" file) and processes any found twice. The first + * time through, they are processed in reverse order (last file first). At + * that time, only "immediate action" configurables are processed. For + * example, if the last named file specifies not processing any more + * configuration files, then no more configuration files will be processed. + * Such an option in the @strong{first} named directory will have no effect. + * + * Once the immediate action configurables have been handled, then the + * directories are handled in normal, forward order. In that way, later + * config files can override the settings of earlier config files. + * + * See the AutoOpts documentation for a thorough discussion of the + * config file format. + * + * Configuration files not found or not decipherable are simply ignored. + * + * err: Returns the value, "-1" if the program options descriptor + * is out of date or indecipherable. Otherwise, the value "0" will + * always be returned. +=*/ +int +optionFileLoad(tOptions * opts, char const * prog) +{ + if (! SUCCESSFUL(validate_struct(opts, prog))) + return -1; + + /* + * The pointer to the program name is "const". However, the + * structure is in writable memory, so we coerce the address + * of this pointer to point to writable memory. + */ + { + char const ** pp = VOIDP(&(opts->pzProgName)); + *pp = prog; + } + + intern_file_load(opts); + return 0; +} + +/*=export_func optionLoadOpt + * private: + * + * what: Load an option rc/ini file + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + odesc + the descriptor for this arg + + * + * doc: + * Processes the options found in the file named with + * odesc->optArg.argString. +=*/ +void +optionLoadOpt(tOptions * opts, tOptDesc * odesc) +{ + struct stat sb; + + if (opts <= OPTPROC_EMIT_LIMIT) + return; + + /* + * IF the option is not being disabled, THEN load the file. There must + * be a file. (If it is being disabled, then the disablement processing + * already took place. It must be done to suppress preloading of ini/rc + * files.) + */ + if ( DISABLED_OPT(odesc) + || ((odesc->fOptState & OPTST_RESET) != 0)) + return; + + if (stat(odesc->optArg.argString, &sb) != 0) { + if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0) + return; + + fserr_exit(opts->pzProgName, "stat", odesc->optArg.argString); + /* NOT REACHED */ + } + + if (! S_ISREG(sb.st_mode)) { + if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0) + return; + errno = EINVAL; + fserr_exit(opts->pzProgName, "stat", odesc->optArg.argString); + /* NOT REACHED */ + } + + file_preset(opts, odesc->optArg.argString, DIRECTION_CALLED); +} + +/** + * Parse the various attributes of an XML-styled config file entry + * + * @returns NULL on failure, otherwise the scan point + */ +static char const * +parse_attrs(tOptions * opts, char const * txt, tOptionLoadMode * pMode, + tOptionValue * pType) +{ + size_t len = 0; + + for (;;) { + len = (size_t)(SPN_LOWER_CASE_CHARS(txt) - txt); + + /* + * The enumeration used in this switch is derived from this switch + * statement itself. The "find_option_xat_attribute_cmd" function + * will return XAT_CMD_MEMBERS for the "txt" string value + * "members", etc. + */ + switch (find_option_xat_attribute_cmd(txt, len)) { + case XAT_CMD_TYPE: + txt = parse_value(txt+len, pType); + break; + + case XAT_CMD_WORDS: + txt = parse_keyword(opts, txt+len, pType); + break; + + case XAT_CMD_MEMBERS: + txt = parse_set_mem(opts, txt+len, pType); + break; + + case XAT_CMD_COOKED: + txt += len; + if (! IS_END_XML_TOKEN_CHAR(*txt)) + goto invalid_kwd; + + *pMode = OPTION_LOAD_COOKED; + break; + + case XAT_CMD_UNCOOKED: + txt += len; + if (! IS_END_XML_TOKEN_CHAR(*txt)) + goto invalid_kwd; + + *pMode = OPTION_LOAD_UNCOOKED; + break; + + case XAT_CMD_KEEP: + txt += len; + if (! IS_END_XML_TOKEN_CHAR(*txt)) + goto invalid_kwd; + + *pMode = OPTION_LOAD_KEEP; + break; + + default: + case XAT_INVALID_CMD: + invalid_kwd: + pType->valType = OPARG_TYPE_NONE; + return skip_unkn(txt); + } + + if (txt == NULL) + return NULL; + txt = SPN_WHITESPACE_CHARS(txt); + switch (*txt) { + case '/': pType->valType = OPARG_TYPE_NONE; + /* FALLTHROUGH */ + case '>': return txt; + } + if (! IS_LOWER_CASE_CHAR(*txt)) + return NULL; + } +} + +/** + * "txt" points to the character after "words=". + * What should follow is a name of a keyword (enumeration) list. + * + * @param opts unused + * @param[in] txt keyword to skip over + * @param type unused value type + * @returns pointer after skipped text + */ +static char const * +parse_keyword(tOptions * opts, char const * txt, tOptionValue * typ) +{ + (void)opts; + (void)typ; + + return skip_unkn(txt); +} + +/** + * "txt" points to the character after "members=" + * What should follow is a name of a "set membership". + * A collection of bit flags. + * + * @param opts unused + * @param[in] txt keyword to skip over + * @param type unused value type + * @returns pointer after skipped text + */ +static char const * +parse_set_mem(tOptions * opts, char const * txt, tOptionValue * typ) +{ + (void)opts; + (void)typ; + + return skip_unkn(txt); +} + +/** + * parse the type. The keyword "type" was found, now figure out + * the type that follows the type. + * + * @param[in] txt points to the '=' character after the "type" keyword. + * @param[out] typ where to store the type found + * @returns the next byte after the type name + */ +static char const * +parse_value(char const * txt, tOptionValue * typ) +{ + size_t len = 0; + + if (*(txt++) != '=') + goto woops; + + len = (size_t)(SPN_OPTION_NAME_CHARS(txt) - txt); + + if ((len == 0) || (! IS_END_XML_TOKEN_CHAR(txt[len]))) { + woops: + typ->valType = OPARG_TYPE_NONE; + return skip_unkn(txt + len); + } + + /* + * The enumeration used in this switch is derived from this switch + * statement itself. The "find_option_value_type_cmd" function + * will return VTP_CMD_INTEGER for the "txt" string value + * "integer", etc. + */ + switch (find_option_value_type_cmd(txt, len)) { + default: + case VTP_INVALID_CMD: goto woops; + + case VTP_CMD_STRING: + typ->valType = OPARG_TYPE_STRING; + break; + + case VTP_CMD_INTEGER: + typ->valType = OPARG_TYPE_NUMERIC; + break; + + case VTP_CMD_BOOL: + case VTP_CMD_BOOLEAN: + typ->valType = OPARG_TYPE_BOOLEAN; + break; + + case VTP_CMD_KEYWORD: + typ->valType = OPARG_TYPE_ENUMERATION; + break; + + case VTP_CMD_SET: + case VTP_CMD_SET_MEMBERSHIP: + typ->valType = OPARG_TYPE_MEMBERSHIP; + break; + + case VTP_CMD_NESTED: + case VTP_CMD_HIERARCHY: + typ->valType = OPARG_TYPE_HIERARCHY; + } + + return txt + len; +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/configfile.c */ diff --git a/src/libopts/cook.c b/src/libopts/cook.c new file mode 100644 index 0000000..5240540 --- /dev/null +++ b/src/libopts/cook.c @@ -0,0 +1,320 @@ +/** + * \file cook.c + * + * This file contains the routines that deal with processing quoted strings + * into an internal format. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/*=export_func ao_string_cook_escape_char + * private: + * + * what: escape-process a string fragment + * arg: + char const * + pzScan + points to character after the escape + + * arg: + char * + pRes + Where to put the result byte + + * arg: + unsigned int + nl_ch + replacement char if scanned char is \n + + * + * ret-type: unsigned int + * ret-desc: The number of bytes consumed processing the escaped character. + * + * doc: + * + * This function converts "t" into "\t" and all your other favorite + * escapes, including numeric ones: hex and ocatal, too. + * The returned result tells the caller how far to advance the + * scan pointer (passed in). The default is to just pass through the + * escaped character and advance the scan by one. + * + * Some applications need to keep an escaped newline, others need to + * suppress it. This is accomplished by supplying a '\n' replacement + * character that is different from \n, if need be. For example, use + * 0x7F and never emit a 0x7F. + * + * err: @code{NULL} is returned if the string is mal-formed. +=*/ +unsigned int +ao_string_cook_escape_char(char const * pzIn, char * pRes, uint_t nl) +{ + unsigned int res = 1; + + switch (*pRes = *pzIn++) { + case NUL: /* NUL - end of input string */ + return 0; + case '\r': + if (*pzIn != NL) + return 1; + res++; + /* FALLTHROUGH */ + case NL: /* NL - emit newline */ + *pRes = (char)nl; + return res; + + case 'a': *pRes = '\a'; break; + case 'b': *pRes = '\b'; break; + case 'f': *pRes = '\f'; break; + case 'n': *pRes = NL; break; + case 'r': *pRes = '\r'; break; + case 't': *pRes = '\t'; break; + case 'v': *pRes = '\v'; break; + + case 'x': + case 'X': /* HEX Escape */ + if (IS_HEX_DIGIT_CHAR(*pzIn)) { + char z[4]; + unsigned int ct = 0; + + do { + z[ct] = pzIn[ct]; + if (++ct >= 2) + break; + } while (IS_HEX_DIGIT_CHAR(pzIn[ct])); + z[ct] = NUL; + *pRes = (char)strtoul(z, NULL, 16); + return ct + 1; + } + break; + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + { + /* + * IF the character copied was an octal digit, + * THEN set the output character to an octal value. + * The 3 octal digit result might exceed 0xFF, so check it. + */ + char z[4]; + unsigned long val; + unsigned int ct = 0; + + z[ct++] = *--pzIn; + while (IS_OCT_DIGIT_CHAR(pzIn[ct])) { + z[ct] = pzIn[ct]; + if (++ct >= 3) + break; + } + + z[ct] = NUL; + val = strtoul(z, NULL, 8); + if (val > 0xFF) + val = 0xFF; + *pRes = (char)val; + return ct; + } + + default: /* quoted character is result character */; + } + + return res; +} + +/** + * count newlines between start and end + */ +static char * +nl_count(char * start, char * end, int * lnct_p) +{ + while (start < end) { + if (*(start++) == NL) + (*lnct_p)++; + } + return end; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * A quoted string has been found. + * Find the end of it and compress any escape sequences. + */ +static bool +contiguous_quote(char ** pps, char * pq, int * lnct_p) +{ + char * ps = *pps + 1; + + for (;;) { + while (IS_WHITESPACE_CHAR(*ps)) + if (*(ps++) == NL) + (*lnct_p)++; + + /* + * IF the next character is a quote character, + * THEN we will concatenate the strings. + */ + switch (*ps) { + case '"': + case '\'': + *pq = *(ps++); /* assign new quote character and return */ + *pps = ps; + return true; + + case '/': + /* + * Allow for a comment embedded in the concatenated string. + */ + switch (ps[1]) { + default: + goto fail_return; + + case '/': + /* + * Skip to end of line + */ + ps = strchr(ps, NL); + if (ps == NULL) + goto fail_return; + break; + + case '*': + ps = nl_count(ps + 2, strstr(ps + 2, "*/"), lnct_p); + if (ps == NULL) + goto fail_return; + ps += 2; + } + continue; + + default: + /* + * The next non-whitespace character is not a quote. + * The series of quoted strings has come to an end. + */ + *pps = ps; + return false; + } + } + + fail_return: + *pps = NULL; + return false; +} + +/*=export_func ao_string_cook + * private: + * + * what: concatenate and escape-process strings + * arg: + char * + pzScan + The *MODIFIABLE* input buffer + + * arg: + int * + lnct_p + The (possibly NULL) pointer to a line count + + * + * ret-type: char * + * ret-desc: The address of the text following the processed strings. + * The return value is NULL if the strings are ill-formed. + * + * doc: + * + * A series of one or more quoted strings are concatenated together. + * If they are quoted with double quotes (@code{"}), then backslash + * escapes are processed per the C programming language. If they are + * single quote strings, then the backslashes are honored only when they + * precede another backslash or a single quote character. + * + * err: @code{NULL} is returned if the string(s) is/are mal-formed. +=*/ +char * +ao_string_cook(char * pzScan, int * lnct_p) +{ + int l = 0; + char q = *pzScan; + + /* + * It is a quoted string. Process the escape sequence characters + * (in the set "abfnrtv") and make sure we find a closing quote. + */ + char * pzD = pzScan++; + char * pzS = pzScan; + + if (lnct_p == NULL) + lnct_p = &l; + + for (;;) { + /* + * IF the next character is the quote character, THEN we may end the + * string. We end it unless the next non-blank character *after* the + * string happens to also be a quote. If it is, then we will change + * our quote character to the new quote character and continue + * condensing text. + */ + while (*pzS == q) { + *pzD = NUL; /* This is probably the end of the line */ + if (! contiguous_quote(&pzS, &q, lnct_p)) + return pzS; + } + + /* + * We are inside a quoted string. Copy text. + */ + switch (*(pzD++) = *(pzS++)) { + case NUL: + return NULL; + + case NL: + (*lnct_p)++; + break; + + case '\\': + /* + * IF we are escaping a new line, + * THEN drop both the escape and the newline from + * the result string. + */ + if (*pzS == NL) { + pzS++; + pzD--; + (*lnct_p)++; + } + + /* + * ELSE IF the quote character is '"' or '`', + * THEN we do the full escape character processing + */ + else if (q != '\'') { + unsigned int ct; + ct = ao_string_cook_escape_char(pzS, pzD-1, (uint_t)NL); + if (ct == 0) + return NULL; + + pzS += ct; + } /* if (q != '\'') */ + + /* + * OTHERWISE, we only process "\\", "\'" and "\#" sequences. + * The latter only to easily hide preprocessing directives. + */ + else switch (*pzS) { + case '\\': + case '\'': + case '#': + pzD[-1] = *pzS++; + } + } /* switch (*(pzD++) = *(pzS++)) */ + } /* for (;;) */ +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/cook.c */ diff --git a/src/libopts/enum.c b/src/libopts/enum.c new file mode 100644 index 0000000..7f92e0b --- /dev/null +++ b/src/libopts/enum.c @@ -0,0 +1,628 @@ + +/** + * \file enumeration.c + * + * Handle options with enumeration names and bit mask bit names + * for their arguments. + * + * @addtogroup autoopts + * @{ + */ +/* + * This routine will run run-on options through a pager so the + * user may examine, print or edit them at their leisure. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +static void +enum_err(tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, int name_ct) +{ + size_t max_len = 0; + size_t ttl_len = 0; + int ct_down = name_ct; + int hidden = 0; + + /* + * A real "pOpts" pointer means someone messed up. Give a real error. + */ + if (pOpts > OPTPROC_EMIT_LIMIT) + fprintf(option_usage_fp, pz_enum_err_fmt, pOpts->pzProgName, + pOD->optArg.argString, pOD->pz_Name); + + fprintf(option_usage_fp, zValidKeys, pOD->pz_Name); + + /* + * If the first name starts with this funny character, then we have + * a first value with an unspellable name. You cannot specify it. + * So, we don't list it either. + */ + if (**paz_names == 0x7F) { + paz_names++; + hidden = 1; + ct_down = --name_ct; + } + + /* + * Figure out the maximum length of any name, plus the total length + * of all the names. + */ + { + char const * const * paz = paz_names; + + do { + size_t len = strlen(*(paz++)) + 1; + if (len > max_len) + max_len = len; + ttl_len += len; + } while (--ct_down > 0); + + ct_down = name_ct; + } + + /* + * IF any one entry is about 1/2 line or longer, print one per line + */ + if (max_len > 35) { + do { + fprintf(option_usage_fp, ENUM_ERR_LINE, *(paz_names++)); + } while (--ct_down > 0); + } + + /* + * ELSE IF they all fit on one line, then do so. + */ + else if (ttl_len < 76) { + fputc(' ', option_usage_fp); + do { + fputc(' ', option_usage_fp); + fputs(*(paz_names++), option_usage_fp); + } while (--ct_down > 0); + fputc(NL, option_usage_fp); + } + + /* + * Otherwise, columnize the output + */ + else { + unsigned int ent_no = 0; + char fmt[16]; /* format for all-but-last entries on a line */ + + if (snprintf(fmt, 16, ENUM_ERR_WIDTH, (int)max_len) >= 16) + option_exits(EXIT_FAILURE); + max_len = 78 / max_len; /* max_len is now max entries on a line */ + fputs(TWO_SPACES_STR, option_usage_fp); + + /* + * Loop through all but the last entry + */ + ct_down = name_ct; + while (--ct_down > 0) { + if (++ent_no == max_len) { + /* + * Last entry on a line. Start next line, too. + */ + fprintf(option_usage_fp, NLSTR_SPACE_FMT, *(paz_names++)); + ent_no = 0; + } + + else + fprintf(option_usage_fp, fmt, *(paz_names++) ); + } + fprintf(option_usage_fp, NLSTR_FMT, *paz_names); + } + + if (pOpts > OPTPROC_EMIT_LIMIT) { + fprintf(option_usage_fp, zIntRange, hidden, name_ct - 1 + hidden); + + (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + } + + if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) { + fprintf(option_usage_fp, zLowerBits, name_ct); + fputs(zSetMemberSettings, option_usage_fp); + } else { + fprintf(option_usage_fp, zIntRange, hidden, name_ct - 1 + hidden); + } +} + +/** + * Convert a name or number into a binary number. + * "~0" and "-1" will be converted to the largest value in the enumeration. + * + * @param name the keyword name (number) to convert + * @param pOpts the program's option descriptor + * @param pOD the option descriptor for this option + * @param paz_names the list of keywords for this option + * @param name_ct the count of keywords + */ +static uintptr_t +find_name(char const * name, tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, unsigned int name_ct) +{ + /* + * Return the matching index as a pointer sized integer. + * The result gets stashed in a char * pointer. + */ + uintptr_t res = name_ct; + size_t len = strlen((char *)name); + uintptr_t idx; + + if (IS_DEC_DIGIT_CHAR(*name)) { + char * pz = VOIDP(name); + unsigned long val = strtoul(pz, &pz, 0); + if ((*pz == NUL) && (val < name_ct)) + return (uintptr_t)val; + pz_enum_err_fmt = znum_too_large; + option_usage_fp = stderr; + enum_err(pOpts, pOD, paz_names, (int)name_ct); + return name_ct; + } + + if (IS_INVERSION_CHAR(*name) && (name[2] == NUL)) { + if ( ((name[0] == '~') && (name[1] == '0')) + || ((name[0] == '-') && (name[1] == '1'))) + return (uintptr_t)(name_ct - 1); + goto oops; + } + + /* + * Look for an exact match, but remember any partial matches. + * Multiple partial matches means we have an ambiguous match. + */ + for (idx = 0; idx < name_ct; idx++) { + if (strncmp((char *)paz_names[idx], (char *)name, len) == 0) { + if (paz_names[idx][len] == NUL) + return idx; /* full match */ + + if (res == name_ct) + res = idx; /* save partial match */ + else + res = (uintptr_t)~0; /* may yet find full match */ + } + } + + if (res < name_ct) + return res; /* partial match */ + + oops: + + pz_enum_err_fmt = (res == name_ct) ? zNoKey : zambiguous_key; + option_usage_fp = stderr; + enum_err(pOpts, pOD, paz_names, (int)name_ct); + return name_ct; +} + + +/*=export_func optionKeywordName + * what: Convert between enumeration values and strings + * private: + * + * arg: tOptDesc *, pOD, enumeration option description + * arg: unsigned int, enum_val, the enumeration value to map + * + * ret_type: char const * + * ret_desc: the enumeration name from const memory + * + * doc: This converts an enumeration value into the matching string. +=*/ +char const * +optionKeywordName(tOptDesc * pOD, unsigned int enum_val) +{ + tOptDesc od = { 0 }; + od.optArg.argEnum = enum_val; + + (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, &od ); + return od.optArg.argString; +} + + +/*=export_func optionEnumerationVal + * what: Convert from a string to an enumeration value + * private: + * + * arg: tOptions *, pOpts, the program options descriptor + * arg: tOptDesc *, pOD, enumeration option description + * arg: char const * const *, paz_names, list of enumeration names + * arg: unsigned int, name_ct, number of names in list + * + * ret_type: uintptr_t + * ret_desc: the enumeration value + * + * doc: This converts the optArg.argString string from the option description + * into the index corresponding to an entry in the name list. + * This will match the generated enumeration value. + * Full matches are always accepted. Partial matches are accepted + * if there is only one partial match. +=*/ +uintptr_t +optionEnumerationVal(tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, unsigned int name_ct) +{ + uintptr_t res = 0UL; + + /* + * IF the program option descriptor pointer is invalid, + * then it is some sort of special request. + */ + switch ((uintptr_t)pOpts) { + case (uintptr_t)OPTPROC_EMIT_USAGE: + /* + * print the list of enumeration names. + */ + enum_err(pOpts, pOD, paz_names, (int)name_ct); + break; + + case (uintptr_t)OPTPROC_EMIT_SHELL: + { + unsigned int ix = (unsigned int)pOD->optArg.argEnum; + /* + * print the name string. + */ + if (ix >= name_ct) + printf(INVALID_FMT, ix); + else + fputs(paz_names[ ix ], stdout); + + break; + } + + case (uintptr_t)OPTPROC_RETURN_VALNAME: + { + unsigned int ix = (unsigned int)pOD->optArg.argEnum; + /* + * Replace the enumeration value with the name string. + */ + if (ix >= name_ct) + return (uintptr_t)INVALID_STR; + + pOD->optArg.argString = paz_names[ix]; + break; + } + + default: + if ((pOD->fOptState & OPTST_RESET) != 0) + break; + + res = find_name(pOD->optArg.argString, pOpts, pOD, paz_names, name_ct); + + if (pOD->fOptState & OPTST_ALLOC_ARG) { + AGFREE(pOD->optArg.argString); + pOD->fOptState &= ~OPTST_ALLOC_ARG; + pOD->optArg.argString = NULL; + } + } + + return res; +} + +static void +set_memb_shell(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names, + unsigned int name_ct) +{ + /* + * print the name string. + */ + unsigned int ix = 0; + uintptr_t bits = (uintptr_t)pOD->optCookie; + size_t len = 0; + + (void)pOpts; + bits &= ((uintptr_t)1 << (uintptr_t)name_ct) - (uintptr_t)1; + + while (bits != 0) { + if (bits & 1) { + if (len++ > 0) fputs(OR_STR, stdout); + fputs(paz_names[ix], stdout); + } + if (++ix >= name_ct) break; + bits >>= 1; + } +} + +static void +set_memb_names(tOptions * opts, tOptDesc * od, char const * const * nm_list, + unsigned int nm_ct) +{ + char * pz; + uintptr_t mask = (1UL << (uintptr_t)nm_ct) - 1UL; + uintptr_t bits = (uintptr_t)od->optCookie & mask; + unsigned int ix = 0; + size_t len = 1; + + /* + * Replace the enumeration value with the name string. + * First, determine the needed length, then allocate and fill in. + */ + while (bits != 0) { + if (bits & 1) + len += strlen(nm_list[ix]) + PLUS_STR_LEN + 1; + if (++ix >= nm_ct) break; + bits >>= 1; + } + + od->optArg.argString = pz = AGALOC(len, "enum"); + bits = (uintptr_t)od->optCookie & mask; + if (bits == 0) { + *pz = NUL; + return; + } + + for (ix = 0; ; ix++) { + size_t nln; + int doit = bits & 1; + + bits >>= 1; + if (doit == 0) + continue; + + nln = strlen(nm_list[ix]); + memcpy(pz, nm_list[ix], nln); + pz += nln; + if (bits == 0) + break; + memcpy(pz, PLUS_STR, PLUS_STR_LEN); + pz += PLUS_STR_LEN; + } + *pz = NUL; + (void)opts; +} + +/** + * Check membership start conditions. An equal character (@samp{=}) says to + * clear the result and not carry over any residual value. A carat + * (@samp{^}), which may follow the equal character, says to invert the + * result. The scanning pointer is advanced past these characters and any + * leading white space. Invalid sequences are indicated by setting the + * scanning pointer to NULL. + * + * @param od the set membership option description + * @param argp a pointer to the string scanning pointer + * @param invert a pointer to the boolean inversion indicator + * + * @returns either zero or the original value for the optCookie. + */ +static uintptr_t +check_membership_start(tOptDesc * od, char const ** argp, bool * invert) +{ + uintptr_t res = (uintptr_t)od->optCookie; + char const * arg = SPN_WHITESPACE_CHARS(od->optArg.argString); + if ((arg == NULL) || (*arg == NUL)) + goto member_start_fail; + + *invert = false; + + switch (*arg) { + case '=': + res = 0UL; + arg = SPN_WHITESPACE_CHARS(arg + 1); + switch (*arg) { + case '=': case ',': + goto member_start_fail; + case '^': + goto inversion; + default: + break; + } + break; + + case '^': + inversion: + *invert = true; + arg = SPN_WHITESPACE_CHARS(arg + 1); + if (*arg != ',') + break; + /* FALLTHROUGH */ + + case ',': + goto member_start_fail; + + default: + break; + } + + *argp = arg; + return res; + +member_start_fail: + *argp = NULL; + return 0UL; +} + +/** + * convert a name to a bit. Look up a name string to get a bit number + * and shift the value "1" left that number of bits. + * + * @param opts program options descriptor + * @param od the set membership option description + * @param pz address of the start of the bit name + * @param nm_list the list of names for this option + * @param nm_ct the number of entries in this list + * + * @returns 0UL on error, other an unsigned long with the correct bit set. + */ +static uintptr_t +find_member_bit(tOptions * opts, tOptDesc * od, char const * pz, int len, + char const * const * nm_list, unsigned int nm_ct) +{ + char nm_buf[ AO_NAME_SIZE ]; + + memcpy(nm_buf, pz, len); + nm_buf[len] = NUL; + + { + unsigned int shift_ct = (unsigned int) + find_name(nm_buf, opts, od, nm_list, nm_ct); + if (shift_ct >= nm_ct) + return 0UL; + + return 1UL << shift_ct; + } +} + +/*=export_func optionMemberList + * what: Get the list of members of a bit mask set + * + * arg: tOptDesc *, od, the set membership option description + * + * ret_type: char * + * ret_desc: the names of the set bits + * + * doc: This converts the OPT_VALUE_name mask value to a allocated string. + * It is the caller's responsibility to free the string. +=*/ +char * +optionMemberList(tOptDesc * od) +{ + uintptr_t sv = od->optArg.argIntptr; + char * res; + (*(od->pOptProc))(OPTPROC_RETURN_VALNAME, od); + res = VOIDP(od->optArg.argString); + od->optArg.argIntptr = sv; + return res; +} + +/*=export_func optionSetMembers + * what: Convert between bit flag values and strings + * private: + * + * arg: tOptions *, opts, the program options descriptor + * arg: tOptDesc *, od, the set membership option description + * arg: char const * const *, + * nm_list, list of enumeration names + * arg: unsigned int, nm_ct, number of names in list + * + * doc: This converts the optArg.argString string from the option description + * into the index corresponding to an entry in the name list. + * This will match the generated enumeration value. + * Full matches are always accepted. Partial matches are accepted + * if there is only one partial match. +=*/ +void +optionSetMembers(tOptions * opts, tOptDesc * od, + char const * const * nm_list, unsigned int nm_ct) +{ + /* + * IF the program option descriptor pointer is invalid, + * then it is some sort of special request. + */ + switch ((uintptr_t)opts) { + case (uintptr_t)OPTPROC_EMIT_USAGE: + enum_err(OPTPROC_EMIT_USAGE, od, nm_list, nm_ct); + return; + + case (uintptr_t)OPTPROC_EMIT_SHELL: + set_memb_shell(opts, od, nm_list, nm_ct); + return; + + case (uintptr_t)OPTPROC_RETURN_VALNAME: + set_memb_names(opts, od, nm_list, nm_ct); + return; + + default: + break; + } + + if ((od->fOptState & OPTST_RESET) != 0) + return; + + { + char const * arg; + bool invert; + uintptr_t res = check_membership_start(od, &arg, &invert); + if (arg == NULL) + goto fail_return; + + while (*arg != NUL) { + bool inv_val = false; + int len; + + switch (*arg) { + case ',': + arg = SPN_WHITESPACE_CHARS(arg+1); + if ((*arg == ',') || (*arg == '|')) + goto fail_return; + continue; + + case '-': + case '!': + inv_val = true; + /* FALLTHROUGH */ + + case '+': + case '|': + arg = SPN_WHITESPACE_CHARS(arg+1); + } + + len = (int)(BRK_SET_SEPARATOR_CHARS(arg) - arg); + if (len == 0) + break; + + if ((len == 3) && (strncmp(arg, zAll, 3) == 0)) { + if (inv_val) + res = 0; + else res = ~0UL; + } + else if ((len == 4) && (strncmp(arg, zNone, 4) == 0)) { + if (! inv_val) + res = 0; + } + else do { + char * pz; + uintptr_t bit = strtoul(arg, &pz, 0); + + if (pz != arg + len) { + bit = find_member_bit(opts, od, pz, len, nm_list, nm_ct); + if (bit == 0UL) + goto fail_return; + } + if (inv_val) + res &= ~bit; + else res |= bit; + } while (false); + + arg = SPN_WHITESPACE_CHARS(arg + len); + } + + if (invert) + res ^= ~0UL; + + if (nm_ct < (8 * sizeof(uintptr_t))) + res &= (1UL << nm_ct) - 1UL; + + od->optCookie = VOIDP(res); + } + return; + +fail_return: + od->optCookie = VOIDP(0); +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/enum.c */ diff --git a/src/libopts/env.c b/src/libopts/env.c new file mode 100644 index 0000000..16f0e95 --- /dev/null +++ b/src/libopts/env.c @@ -0,0 +1,261 @@ + +/** + * \file environment.c + * + * This file contains all of the routines that must be linked into + * an executable to use the generated option processing. The optional + * routines are in separately compiled modules so that they will not + * necessarily be linked in. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/* + * doPrognameEnv - check for preset values from the ${PROGNAME} + * environment variable. This is accomplished by parsing the text into + * tokens, temporarily replacing the arg vector and calling + * immediate_opts and/or regular_opts. + */ +static void +doPrognameEnv(tOptions * pOpts, teEnvPresetType type) +{ + char const * env_opts = getenv(pOpts->pzPROGNAME); + token_list_t * pTL; + int sv_argc; + proc_state_mask_t sv_flag; + char ** sv_argv; + + /* + * No such beast? Then bail now. + */ + if (env_opts == NULL) + return; + + /* + * Tokenize the string. If there's nothing of interest, we'll bail + * here immediately. + */ + pTL = ao_string_tokenize(env_opts); + if (pTL == NULL) + return; + + /* + * Substitute our $PROGNAME argument list for the real one + */ + sv_argc = (int)pOpts->origArgCt; + sv_argv = pOpts->origArgVect; + sv_flag = pOpts->fOptSet; + + /* + * We add a bogus pointer to the start of the list. The program name + * has already been pulled from "argv", so it won't get dereferenced. + * The option scanning code will skip the "program name" at the start + * of this list of tokens, so we accommodate this way .... + */ + { + uintptr_t v = (uintptr_t)(pTL->tkn_list); + pOpts->origArgVect = VOIDP(v - sizeof(char *)); + } + pOpts->origArgCt = (unsigned int)pTL->tkn_ct + 1; + pOpts->fOptSet &= ~OPTPROC_ERRSTOP; + + pOpts->curOptIdx = 1; + pOpts->pzCurOpt = NULL; + + switch (type) { + case ENV_IMM: + (void)immediate_opts(pOpts); + break; + + case ENV_ALL: + (void)immediate_opts(pOpts); + pOpts->curOptIdx = 1; + pOpts->pzCurOpt = NULL; + /* FALLTHROUGH */ + + case ENV_NON_IMM: + (void)regular_opts(pOpts); + } + + /* + * Free up the temporary arg vector and restore the original program args. + */ + free(pTL); + pOpts->origArgVect = sv_argv; + pOpts->origArgCt = (unsigned int)sv_argc; + pOpts->fOptSet = sv_flag; +} + +static void +do_env_opt(tOptState * os, char * env_name, + tOptions * pOpts, teEnvPresetType type) +{ + os->pzOptArg = getenv(env_name); + if (os->pzOptArg == NULL) + return; + + os->flags = OPTST_PRESET | OPTST_ALLOC_ARG | os->pOD->fOptState; + os->optType = TOPT_UNDEFINED; + + if ( (os->pOD->pz_DisablePfx != NULL) + && (streqvcmp(os->pzOptArg, os->pOD->pz_DisablePfx) == 0)) { + os->flags |= OPTST_DISABLED; + os->pzOptArg = NULL; + handle_opt(pOpts, os); + return; + } + + switch (type) { + case ENV_IMM: + /* + * Process only immediate actions + */ + if (DO_IMMEDIATELY(os->flags)) + break; + return; + + case ENV_NON_IMM: + /* + * Process only NON immediate actions + */ + if (DO_NORMALLY(os->flags) || DO_SECOND_TIME(os->flags)) + break; + return; + + default: /* process everything */ + break; + } + + /* + * Make sure the option value string is persistent and consistent. + * + * The interpretation of the option value depends + * on the type of value argument the option takes + */ + if (OPTST_GET_ARGTYPE(os->pOD->fOptState) == OPARG_TYPE_NONE) { + /* + * Ignore any value. + */ + os->pzOptArg = NULL; + + } else if (os->pzOptArg[0] == NUL) { + /* + * If the argument is the empty string and the argument is + * optional, then treat it as if the option was not specified. + */ + if ((os->pOD->fOptState & OPTST_ARG_OPTIONAL) == 0) + return; + os->pzOptArg = NULL; + + } else { + AGDUPSTR(os->pzOptArg, os->pzOptArg, "option argument"); + os->flags |= OPTST_ALLOC_ARG; + } + + handle_opt(pOpts, os); +} + +/* + * env_presets - check for preset values from the envrionment + * This routine should process in all, immediate or normal modes.... + */ +static void +env_presets(tOptions * pOpts, teEnvPresetType type) +{ + int ct; + tOptState st; + char * pzFlagName; + size_t spaceLeft; + char zEnvName[ AO_NAME_SIZE ]; + + /* + * Finally, see if we are to look at the environment + * variables for initial values. + */ + if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0) + return; + + doPrognameEnv(pOpts, type); + + ct = pOpts->presetOptCt; + st.pOD = pOpts->pOptDesc; + + pzFlagName = zEnvName + + snprintf(zEnvName, sizeof(zEnvName), "%s_", pOpts->pzPROGNAME); + spaceLeft = AO_NAME_SIZE - (unsigned long)(pzFlagName - zEnvName) - 1; + + for (;ct-- > 0; st.pOD++) { + size_t nln; + + /* + * If presetting is disallowed, then skip this entry + */ + if ( ((st.pOD->fOptState & OPTST_NO_INIT) != 0) + || (st.pOD->optEquivIndex != NO_EQUIVALENT) ) + continue; + + /* + * IF there is no such environment variable, + * THEN skip this entry, too. + */ + nln = strlen(st.pOD->pz_NAME) + 1; + if (nln <= spaceLeft) { + /* + * Set up the option state + */ + memcpy(pzFlagName, st.pOD->pz_NAME, nln); + do_env_opt(&st, zEnvName, pOpts, type); + } + } + + /* + * Special handling for ${PROGNAME_LOAD_OPTS} + */ + if ( (pOpts->specOptIdx.save_opts != NO_EQUIVALENT) + && (pOpts->specOptIdx.save_opts != 0)) { + size_t nln; + st.pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1; + + if (st.pOD->pz_NAME == NULL) + return; + + nln = strlen(st.pOD->pz_NAME) + 1; + + if (nln > spaceLeft) + return; + + memcpy(pzFlagName, st.pOD->pz_NAME, nln); + do_env_opt(&st, zEnvName, pOpts, type); + } +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/environment.c */ diff --git a/src/libopts/file.c b/src/libopts/file.c new file mode 100644 index 0000000..14efe8f --- /dev/null +++ b/src/libopts/file.c @@ -0,0 +1,201 @@ + +/** + * \file file.c + * + * Handle options that have file names for arguments. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/** + * Make sure the directory containing the subject file exists and that + * the file exists or does not exist, per the option requirements. + * + * @param ftype file existence type flags + * @param pOpts program option descriptor + * @param pOD the option descriptor + */ +static void +check_existence(teOptFileType ftype, tOptions * pOpts, tOptDesc * pOD) +{ + char const * fname = pOD->optArg.argString; + struct stat sb; + + errno = 0; + + switch (ftype & FTYPE_MODE_EXIST_MASK) { + case FTYPE_MODE_MUST_NOT_EXIST: + if ((stat(fname, &sb) == 0) || (errno != ENOENT)) { + if (errno == 0) + errno = EINVAL; + fserr_exit(pOpts->pzProgName, "stat", fname); + /* NOTREACHED */ + } + /* FALLTHROUGH */ + + default: + case FTYPE_MODE_MAY_EXIST: + { + char * p = strrchr(fname, DIRCH); + size_t l; + + if (p == NULL) + /* + * The file may or may not exist and its directory is ".". + * Assume that "." exists. + */ + break; + + l = (size_t)(p - fname); + p = AGALOC(l + 1, "fname"); + memcpy(p, fname, l); + p[l] = NUL; + + if ((stat(p, &sb) != 0) || (errno = EINVAL, ! S_ISDIR(sb.st_mode))) + fserr_exit(pOpts->pzProgName, "stat", p); + /* NOTREACHED */ + + AGFREE(p); + break; + } + + case FTYPE_MODE_MUST_EXIST: + if ( (stat(fname, &sb) != 0) + || (errno = EINVAL, ! S_ISREG(sb.st_mode)) ) + fserr_exit(pOpts->pzProgName, "stat", fname); + /* NOTREACHED */ + + break; + } +} + +/** + * Open the specified file with open(2) and save the FD. + * + * @param pOpts program option descriptor + * @param pOD the option descriptor + * @param mode the open mode (uses int flags value) + */ +static void +open_file_fd(tOptions * pOpts, tOptDesc * pOD, tuFileMode mode) +{ + int fd = open(pOD->optArg.argString, mode.file_flags); + if (fd < 0) + fserr_exit(pOpts->pzProgName, "open", pOD->optArg.argString); + /* NOTREACHED */ + + if ((pOD->fOptState & OPTST_ALLOC_ARG) != 0) + pOD->optCookie = VOIDP(pOD->optArg.argString); + else + AGDUPSTR(pOD->optCookie, pOD->optArg.argString, "file name"); + + pOD->optArg.argFd = fd; + pOD->fOptState &= ~OPTST_ALLOC_ARG; +} + +/** + * Open the specified file with open(2) and save the FD. + * + * @param pOpts program option descriptor + * @param pOD the option descriptor + * @param mode the open mode (uses "char *" mode value) + */ +static void +fopen_file_fp(tOptions * pOpts, tOptDesc * pOD, tuFileMode mode) +{ + FILE * fp = fopen(pOD->optArg.argString, mode.file_mode); + if (fp == NULL) + fserr_exit(pOpts->pzProgName, "fopen", pOD->optArg.argString); + /* NOTREACHED */ + + if ((pOD->fOptState & OPTST_ALLOC_ARG) != 0) + pOD->optCookie = VOIDP(pOD->optArg.argString); + else + AGDUPSTR(pOD->optCookie, pOD->optArg.argString, "file name"); + + pOD->optArg.argFp = fp; + pOD->fOptState &= ~OPTST_ALLOC_ARG; +} + +/*=export_func optionFileCheck + * private: + * + * what: Decipher a boolean value + * arg: + tOptions * + pOpts + program options descriptor + + * arg: + tOptDesc * + pOptDesc + the descriptor for this arg + + * arg: + teOptFileType + ftype + File handling type + + * arg: + tuFileMode + mode + file open mode (if needed) + + * + * doc: + * Make sure the named file conforms with the file type mode. + * The mode specifies if the file must exist, must not exist or may + * (or may not) exist. The mode may also specify opening the + * file: don't, open just the descriptor (fd), or open as a stream + * (FILE * pointer). +=*/ +void +optionFileCheck(tOptions * pOpts, tOptDesc * pOD, + teOptFileType ftype, tuFileMode mode) +{ + if (pOpts <= OPTPROC_EMIT_LIMIT) { + if (pOpts != OPTPROC_EMIT_USAGE) + return; + + switch (ftype & FTYPE_MODE_EXIST_MASK) { + case FTYPE_MODE_MUST_NOT_EXIST: + fputs(zFileCannotExist + tab_skip_ct, option_usage_fp); + break; + + case FTYPE_MODE_MUST_EXIST: + fputs(zFileMustExist + tab_skip_ct, option_usage_fp); + break; + } + return; + } + + if ((pOD->fOptState & OPTST_RESET) != 0) { + if (pOD->optCookie != NULL) + AGFREE(pOD->optCookie); + return; + } + + check_existence(ftype, pOpts, pOD); + + switch (ftype & FTYPE_MODE_OPEN_MASK) { + default: + case FTYPE_MODE_NO_OPEN: break; + case FTYPE_MODE_OPEN_FD: open_file_fd( pOpts, pOD, mode); break; + case FTYPE_MODE_FOPEN_FP: fopen_file_fp(pOpts, pOD, mode); break; + } +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/file.c */ diff --git a/src/libopts/find.c b/src/libopts/find.c new file mode 100644 index 0000000..03ae103 --- /dev/null +++ b/src/libopts/find.c @@ -0,0 +1,765 @@ +/** + * @file check.c + * + * @brief Hunt for options in the option descriptor list + * + * This file contains the routines that deal with processing quoted strings + * into an internal format. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/** + * find the name and name length we are looking for + */ +static int +parse_opt(char const ** nm_pp, char ** arg_pp, char * buf, size_t bufsz) +{ + int res = 0; + char const * p = *nm_pp; + *arg_pp = NULL; + + for (;;) { + switch (*(p++)) { + case NUL: return res; + + case '=': + memcpy(buf, *nm_pp, (size_t)res); + + buf[res] = NUL; + *nm_pp = buf; + *arg_pp = (char *)p; + return res; + + default: + if (++res >= (int)bufsz) + return -1; + } + } +} + +/** + * print out the options that match the given name. + * + * @param pOpts option data + * @param opt_name name of option to look for + */ +static void +opt_ambiguities(tOptions * opts, char const * name, int nm_len) +{ + char const * const hyph = + NAMED_OPTS(opts) ? "" : LONG_OPT_MARKER; + + tOptDesc * pOD = opts->pOptDesc; + int idx = 0; + + fputs(zambig_list_msg, stderr); + do { + if (pOD->pz_Name == NULL) + continue; /* doc option */ + + if (strneqvcmp(name, pOD->pz_Name, nm_len) == 0) + fprintf(stderr, zambig_file, hyph, pOD->pz_Name); + + else if ( (pOD->pz_DisableName != NULL) + && (strneqvcmp(name, pOD->pz_DisableName, nm_len) == 0) + ) + fprintf(stderr, zambig_file, hyph, pOD->pz_DisableName); + } while (pOD++, (++idx < opts->optCt)); +} + +/** + * Determine the number of options that match the name + * + * @param pOpts option data + * @param opt_name name of option to look for + * @param nm_len length of provided name + * @param index pointer to int for option index + * @param disable pointer to bool to mark disabled option + * @return count of options that match + */ +static int +opt_match_ct(tOptions * opts, char const * name, int nm_len, + int * ixp, bool * disable) +{ + int matchCt = 0; + int idx = 0; + int idxLim = opts->optCt; + tOptDesc * pOD = opts->pOptDesc; + + do { + /* + * If option disabled or a doc option, skip to next + */ + if (pOD->pz_Name == NULL) + continue; + + if ( SKIP_OPT(pOD) + && (pOD->fOptState != (OPTST_OMITTED | OPTST_NO_INIT))) + continue; + + if (strneqvcmp(name, pOD->pz_Name, nm_len) == 0) { + /* + * IF we have a complete match + * THEN it takes priority over any already located partial + */ + if (pOD->pz_Name[ nm_len ] == NUL) { + *ixp = idx; + return 1; + } + } + + /* + * IF there is a disable name + * *AND* the option name matches the disable name + * THEN ... + */ + else if ( (pOD->pz_DisableName != NULL) + && (strneqvcmp(name, pOD->pz_DisableName, nm_len) == 0) + ) { + *disable = true; + + /* + * IF we have a complete match + * THEN it takes priority over any already located partial + */ + if (pOD->pz_DisableName[ nm_len ] == NUL) { + *ixp = idx; + return 1; + } + } + + else + continue; /* does not match any option */ + + /* + * We found a full or partial match, either regular or disabling. + * Remember the index for later. + */ + *ixp = idx; + ++matchCt; + + } while (pOD++, (++idx < idxLim)); + + return matchCt; +} + +/** + * Set the option to the indicated option number. + * + * @param opts option data + * @param arg option argument (if glued to name) + * @param idx option index + * @param disable mark disabled option + * @param st state about current option + */ +static tSuccess +opt_set(tOptions * opts, char * arg, int idx, bool disable, tOptState * st) +{ + tOptDesc * pOD = opts->pOptDesc + idx; + + if (SKIP_OPT(pOD)) { + if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0) + return FAILURE; + + fprintf(stderr, zDisabledErr, opts->pzProgName, pOD->pz_Name); + if (pOD->pzText != NULL) + fprintf(stderr, SET_OFF_FMT, pOD->pzText); + fputc(NL, stderr); + (*opts->pUsageProc)(opts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + + /* + * IF we found a disablement name, + * THEN set the bit in the callers' flag word + */ + if (disable) + st->flags |= OPTST_DISABLED; + + st->pOD = pOD; + st->pzOptArg = arg; + st->optType = TOPT_LONG; + + return SUCCESS; +} + +/** + * An option was not found. Check for default option and set it + * if there is one. Otherwise, handle the error. + * + * @param opts option data + * @param name name of option to look for + * @param arg option argument + * @param st state about current option + * + * @return success status + */ +static tSuccess +opt_unknown(tOptions * opts, char const * name, char * arg, tOptState * st) +{ + /* + * IF there is no equal sign + * *AND* we are using named arguments + * *AND* there is a default named option, + * THEN return that option. + */ + if ( (arg == NULL) + && NAMED_OPTS(opts) + && (opts->specOptIdx.default_opt != NO_EQUIVALENT)) { + + st->pOD = opts->pOptDesc + opts->specOptIdx.default_opt; + st->pzOptArg = name; + st->optType = TOPT_DEFAULT; + return SUCCESS; + } + + if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) { + fprintf(stderr, zIllOptStr, opts->pzProgPath, name); + (*opts->pUsageProc)(opts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + + return FAILURE; +} + +/** + * Several options match the provided name. + * + * @param opts option data + * @param name name of option to look for + * @param match_ct number of matching options + * + * @return success status (always FAILURE, if it returns) + */ +static tSuccess +opt_ambiguous(tOptions * opts, char const * name, int match_ct) +{ + if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) { + fprintf(stderr, zambig_opt_fmt, opts->pzProgPath, name, match_ct); + if (match_ct <= 4) + opt_ambiguities(opts, name, (int)strlen(name)); + (*opts->pUsageProc)(opts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + return FAILURE; +} + +/*=export_func optionVendorOption + * private: + * + * what: Process a vendor option + * arg: + tOptions * + pOpts + program options descriptor + + * arg: + tOptDesc * + pOptDesc + the descriptor for this arg + + * + * doc: + * For POSIX specified utilities, the options are constrained to the options, + * @xref{config attributes, Program Configuration}. AutoOpts clients should + * never specify this directly. It gets referenced when the option + * definitions contain a "vendor-opt" attribute. +=*/ +void +optionVendorOption(tOptions * pOpts, tOptDesc * pOD) +{ + tOptState opt_st = OPTSTATE_INITIALIZER(PRESET); + char const * vopt_str = pOD->optArg.argString; + + if (pOpts <= OPTPROC_EMIT_LIMIT) + return; + + if ((pOD->fOptState & OPTST_RESET) != 0) + return; + + if ((pOD->fOptState & OPTPROC_IMMEDIATE) == 0) + opt_st.flags = OPTST_DEFINED; + + if ( ((pOpts->fOptSet & OPTPROC_VENDOR_OPT) == 0) + || ! SUCCESSFUL(opt_find_long(pOpts, vopt_str, &opt_st)) + || ! SUCCESSFUL(get_opt_arg(pOpts, &opt_st)) ) + { + fprintf(stderr, zIllVendOptStr, pOpts->pzProgName, vopt_str); + (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + + /* + * See if we are in immediate handling state. + */ + if (pOpts->fOptSet & OPTPROC_IMMEDIATE) { + /* + * See if the enclosed option is okay with that state. + */ + if (DO_IMMEDIATELY(opt_st.flags)) + (void)handle_opt(pOpts, &opt_st); + + } else { + /* + * non-immediate direction. + * See if the enclosed option is okay with that state. + */ + if (DO_NORMALLY(opt_st.flags) || DO_SECOND_TIME(opt_st.flags)) + (void)handle_opt(pOpts, &opt_st); + } +} + +/** + * Find the option descriptor by full name. + * + * @param opts option data + * @param opt_name name of option to look for + * @param state state about current option + * + * @return success status + */ +static tSuccess +opt_find_long(tOptions * opts, char const * opt_name, tOptState * state) +{ + char name_buf[128]; + char * opt_arg; + int nm_len = parse_opt(&opt_name, &opt_arg, name_buf, sizeof(name_buf)); + + int idx = 0; + bool disable = false; + int ct; + + if (nm_len <= 1) { + if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0) + return FAILURE; + + fprintf(stderr, zInvalOptName, opts->pzProgName, opt_name); + (*opts->pUsageProc)(opts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + + ct = opt_match_ct(opts, opt_name, nm_len, &idx, &disable); + + /* + * See if we found one match, no matches or multiple matches. + */ + switch (ct) { + case 1: return opt_set(opts, opt_arg, idx, disable, state); + case 0: return opt_unknown(opts, opt_name, opt_arg, state); + default: return opt_ambiguous(opts, opt_name, ct); + } +} + + +/** + * Find the short option descriptor for the current option + * + * @param pOpts option data + * @param optValue option flag character + * @param pOptState state about current option + */ +static tSuccess +opt_find_short(tOptions * pOpts, uint_t optValue, tOptState * pOptState) +{ + tOptDesc * pRes = pOpts->pOptDesc; + int ct = pOpts->optCt; + + /* + * Search the option list + */ + do { + if (optValue != pRes->optValue) + continue; + + if (SKIP_OPT(pRes)) { + if ( (pRes->fOptState == (OPTST_OMITTED | OPTST_NO_INIT)) + && (pRes->pz_Name != NULL)) { + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0) + return FAILURE; + + fprintf(stderr, zDisabledErr, pOpts->pzProgPath, pRes->pz_Name); + if (pRes->pzText != NULL) + fprintf(stderr, SET_OFF_FMT, pRes->pzText); + fputc(NL, stderr); + (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + goto short_opt_error; + } + + pOptState->pOD = pRes; + pOptState->optType = TOPT_SHORT; + return SUCCESS; + + } while (pRes++, --ct > 0); + + /* + * IF the character value is a digit + * AND there is a special number option ("-n") + * THEN the result is the "option" itself and the + * option is the specially marked "number" option. + */ + if ( IS_DEC_DIGIT_CHAR(optValue) + && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) { + pOptState->pOD = \ + pRes = pOpts->pOptDesc + pOpts->specOptIdx.number_option; + (pOpts->pzCurOpt)--; + pOptState->optType = TOPT_SHORT; + return SUCCESS; + } + + short_opt_error: + + /* + * IF we are to stop on errors (the default, actually) + * THEN call the usage procedure. + */ + if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) { + fprintf(stderr, zIllOptChr, pOpts->pzProgPath, optValue); + (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + _exit(EXIT_FAILURE); /* to be certain */ + } + + return FAILURE; +} + +/** + * Process option with a required argument. Long options can either have a + * separate command line argument, or an argument attached by the '=' + * character. Figure out which. + * + * @param[in,out] opts the program option descriptor + * @param[in,out] o_st the option processing state + * @returns SUCCESS or FAILURE + */ +static tSuccess +get_opt_arg_must(tOptions * opts, tOptState * o_st) +{ + switch (o_st->optType) { + case TOPT_SHORT: + /* + * See if an arg string follows the flag character + */ + if (*++(opts->pzCurOpt) == NUL) + opts->pzCurOpt = opts->origArgVect[ opts->curOptIdx++ ]; + o_st->pzOptArg = opts->pzCurOpt; + break; + + case TOPT_LONG: + /* + * See if an arg string has already been assigned (glued on + * with an `=' character) + */ + if (o_st->pzOptArg == NULL) + o_st->pzOptArg = opts->origArgVect[ opts->curOptIdx++ ]; + break; + + default: +#ifdef DEBUG + fputs("AutoOpts lib error: option type not selected\n", stderr); + option_exits(EXIT_FAILURE); +#endif + + case TOPT_DEFAULT: + /* + * The option was selected by default. The current token is + * the option argument. + */ + break; + } + + /* + * Make sure we did not overflow the argument list. + */ + if (opts->curOptIdx > opts->origArgCt) { + fprintf(stderr, zMisArg, opts->pzProgPath, o_st->pOD->pz_Name); + return FAILURE; + } + + opts->pzCurOpt = NULL; /* next time advance to next arg */ + return SUCCESS; +} + +/** + * Process an option with an optional argument. For short options, it looks + * at the character after the option character, or it consumes the next full + * argument. For long options, it looks for an '=' character attachment to + * the long option name before deciding to take the next command line + * argument. + * + * @param pOpts the option descriptor + * @param o_st a structure for managing the current processing state + * @returns SUCCESS or does not return + */ +static tSuccess +get_opt_arg_may(tOptions * pOpts, tOptState * o_st) +{ + /* + * An option argument is optional. + */ + switch (o_st->optType) { + case TOPT_SHORT: + if (*++pOpts->pzCurOpt != NUL) + o_st->pzOptArg = pOpts->pzCurOpt; + else { + char * pzLA = pOpts->origArgVect[ pOpts->curOptIdx ]; + + /* + * BECAUSE it is optional, we must make sure + * we did not find another flag and that there + * is such an argument. + */ + if ((pzLA == NULL) || (*pzLA == '-')) + o_st->pzOptArg = NULL; + else { + pOpts->curOptIdx++; /* argument found */ + o_st->pzOptArg = pzLA; + } + } + break; + + case TOPT_LONG: + /* + * Look for an argument if we don't already have one (glued on + * with a `=' character) *AND* we are not in named argument mode + */ + if ( (o_st->pzOptArg == NULL) + && (! NAMED_OPTS(pOpts))) { + char * pzLA = pOpts->origArgVect[ pOpts->curOptIdx ]; + + /* + * BECAUSE it is optional, we must make sure + * we did not find another flag and that there + * is such an argument. + */ + if ((pzLA == NULL) || (*pzLA == '-')) + o_st->pzOptArg = NULL; + else { + pOpts->curOptIdx++; /* argument found */ + o_st->pzOptArg = pzLA; + } + } + break; + + default: + case TOPT_DEFAULT: + ao_bug(zbad_default_msg); + } + + /* + * After an option with an optional argument, we will + * *always* start with the next option because if there + * were any characters following the option name/flag, + * they would be interpreted as the argument. + */ + pOpts->pzCurOpt = NULL; + return SUCCESS; +} + +/** + * Process option that does not have an argument. + * + * @param[in,out] opts the program option descriptor + * @param[in,out] o_st the option processing state + * @returns SUCCESS or FAILURE + */ +static tSuccess +get_opt_arg_none(tOptions * pOpts, tOptState * o_st) +{ + /* + * No option argument. Make sure next time around we find + * the correct option flag character for short options + */ + if (o_st->optType == TOPT_SHORT) + (pOpts->pzCurOpt)++; + + /* + * It is a long option. Make sure there was no ``=xxx'' argument + */ + else if (o_st->pzOptArg != NULL) { + fprintf(stderr, zNoArg, pOpts->pzProgPath, o_st->pOD->pz_Name); + return FAILURE; + } + + /* + * It is a long option. Advance to next command line argument. + */ + else + pOpts->pzCurOpt = NULL; + + return SUCCESS; +} + +/** + * Process option. Figure out whether or not to look for an option argument. + * + * @param[in,out] opts the program option descriptor + * @param[in,out] o_st the option processing state + * @returns SUCCESS or FAILURE + */ +static tSuccess +get_opt_arg(tOptions * opts, tOptState * o_st) +{ + o_st->flags |= (o_st->pOD->fOptState & OPTST_PERSISTENT_MASK); + + /* + * Disabled options and options specified to not have arguments + * are handled with the "none" procedure. Otherwise, check the + * optional flag and call either the "may" or "must" function. + */ + if ((o_st->flags & OPTST_DISABLED) != 0) + return get_opt_arg_none(opts, o_st); + + switch (OPTST_GET_ARGTYPE(o_st->flags)) { + case OPARG_TYPE_STATIC: + { + /* + * Propagate the static arg + */ + tSuccess res = get_opt_arg_none(opts, o_st); + o_st->pzOptArg = o_st->pOD->optArg.argString; + return res; + } + + case OPARG_TYPE_NONE: + return get_opt_arg_none(opts, o_st); + } + + if (o_st->flags & OPTST_ARG_OPTIONAL) + return get_opt_arg_may( opts, o_st); + + return get_opt_arg_must(opts, o_st); +} + +/** + * Find the option descriptor for the current option. + * + * @param[in,out] opts the program option descriptor + * @param[in,out] o_st the option processing state + * @returns SUCCESS or FAILURE + */ +static tSuccess +find_opt(tOptions * opts, tOptState * o_st) +{ + /* + * IF we are continuing a short option list (e.g. -xyz...) + * THEN continue a single flag option. + * OTHERWISE see if there is room to advance and then do so. + */ + if ((opts->pzCurOpt != NULL) && (*opts->pzCurOpt != NUL)) + return opt_find_short(opts, (uint8_t)*(opts->pzCurOpt), o_st); + + if (opts->curOptIdx >= opts->origArgCt) + return PROBLEM; /* NORMAL COMPLETION */ + + opts->pzCurOpt = opts->origArgVect[ opts->curOptIdx ]; + + /* + * IF all arguments must be named options, ... + */ + if (NAMED_OPTS(opts)) { + char * pz = opts->pzCurOpt; + int def; + tSuccess res; + uint16_t * def_opt; + + opts->curOptIdx++; + + if (*pz != '-') + return opt_find_long(opts, pz, o_st); + + /* + * The name is prefixed with one or more hyphens. Strip them off + * and disable the "default_opt" setting. Use heavy recasting to + * strip off the "const" quality of the "default_opt" field. + */ + while (*(++pz) == '-') ; + def_opt = VOIDP(&(opts->specOptIdx.default_opt)); + def = *def_opt; + *def_opt = NO_EQUIVALENT; + res = opt_find_long(opts, pz, o_st); + *def_opt = (uint16_t)def; + return res; + } + + /* + * Note the kind of flag/option marker + */ + if (*((opts->pzCurOpt)++) != '-') + return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */ + + /* + * Special hack for a hyphen by itself + */ + if (*(opts->pzCurOpt) == NUL) + return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */ + + /* + * The current argument is to be processed as an option argument + */ + opts->curOptIdx++; + + /* + * We have an option marker. + * Test the next character for long option indication + */ + if (opts->pzCurOpt[0] == '-') { + if (*++(opts->pzCurOpt) == NUL) + /* + * NORMAL COMPLETION - NOT this arg, but rest are operands + */ + return PROBLEM; + + /* + * We do not allow the hyphen to be used as a flag value. + * Therefore, if long options are not to be accepted, we punt. + */ + if ((opts->fOptSet & OPTPROC_LONGOPT) == 0) { + fprintf(stderr, zIllOptStr, opts->pzProgPath, opts->pzCurOpt-2); + return FAILURE; + } + + return opt_find_long(opts, opts->pzCurOpt, o_st); + } + + /* + * If short options are not allowed, then do long + * option processing. Otherwise the character must be a + * short (i.e. single character) option. + */ + if ((opts->fOptSet & OPTPROC_SHORTOPT) != 0) + return opt_find_short(opts, (uint8_t)*(opts->pzCurOpt), o_st); + + return opt_find_long(opts, opts->pzCurOpt, o_st); +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/find.c */ diff --git a/src/libopts/genshell.c b/src/libopts/genshell.c new file mode 100644 index 0000000..05182a6 --- /dev/null +++ b/src/libopts/genshell.c @@ -0,0 +1,848 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (genshell.c) + * + * It has been AutoGen-ed + * From the definitions genshell.def + * and the template file options + * + * Generated from AutoOpts 42:1:17 templates. + * + * AutoOpts is a copyrighted work. This source file is not encumbered + * by AutoOpts licensing, but is provided under the licensing terms chosen + * by the genshellopt author or copyright holder. AutoOpts is + * licensed under the terms of the LGPL. The redistributable library + * (``libopts'') is licensed under the terms of either the LGPL or, at the + * users discretion, the BSD license. See the AutoOpts and/or libopts sources + * for details. + * + * The genshellopt program is copyrighted and licensed + * under the following terms: + * + * Copyright (C) 1999-2018 Bruce Korb, all rights reserved. + * This is free software. It is licensed for use, modification and + * redistribution under the terms of the GNU Lesser General Public License, + * version 2 or later + * + * The genshellopt library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, see + * + */ + +#ifndef __doxygen__ +#define OPTION_CODE_COMPILE 1 +#include "genshell.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +extern FILE * option_usage_fp; +#define zCopyright (genshellopt_opt_strs+0) +#define zLicenseDescrip (genshellopt_opt_strs+285) + +extern tUsageProc genshelloptUsage; + +#ifndef NULL +# define NULL 0 +#endif + +/** + * static const strings for genshellopt options + */ +static char const genshellopt_opt_strs[1769] = +/* 0 */ "genshellopt 1\n" + "Copyright (C) 1999-2018 Bruce Korb, all rights reserved.\n" + "This is free software. It is licensed for use, modification and\n" + "redistribution under the terms of the GNU Lesser General Public License,\n" + "version 2 or later \n\0" +/* 285 */ "The genshellopt library is free software; you can redistribute it and/or\n" + "modify it under the terms of the GNU Library General Public License as\n" + "published by the Free Software Foundation; either version 2 of the License,\n" + "or (at your option) any later version.\n\n" + "This library is distributed in the hope that it will be useful, but WITHOUT\n" + "ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n" + "FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public\n" + "License for more details.\n\n" + "You should have received a copy of the GNU Library General Public License\n" + "along with this library; if not, see\n" + "\n\0" +/* 957 */ "Output Script File\0" +/* 976 */ "SCRIPT\0" +/* 983 */ "script\0" +/* 990 */ "Shell name (follows \"#!\" magic)\0" +/* 1022 */ "SHELL\0" +/* 1028 */ "no-shell\0" +/* 1037 */ "no\0" +/* 1040 */ "display extended usage information and exit\0" +/* 1084 */ "help\0" +/* 1089 */ "extended usage information passed thru pager\0" +/* 1134 */ "more-help\0" +/* 1144 */ "output version information and exit\0" +/* 1180 */ "version\0" +/* 1188 */ "GENSHELLOPT\0" +/* 1200 */ "genshellopt - Generate Shell Option Processing Script - Ver. 1\n" + "Usage: %s [ - [] | --[{=| }] ]...\n\0" +/* 1321 */ "autogen-users@lists.sourceforge.net\0" +/* 1357 */ "Note that 'shell' is only useful if the output file does not already exist.\n" + "If it does, then the shell name and optional first argument will be\n" + "extracted from the script file.\n\0" +/* 1534 */ "If the script file already exists and contains Automated Option Processing\n" + "text, the second line of the file through the ending tag will be replaced\n" + "by the newly generated text. The first '#!' line will be regenerated.\n\0" +/* 1755 */ "genshellopt 1"; + +/** + * script option description: + */ +/** Descriptive text for the script option */ +#define SCRIPT_DESC (genshellopt_opt_strs+957) +/** Upper-cased name for the script option */ +#define SCRIPT_NAME (genshellopt_opt_strs+976) +/** Name string for the script option */ +#define SCRIPT_name (genshellopt_opt_strs+983) +/** Compiled in flag settings for the script option */ +#define SCRIPT_FLAGS (OPTST_DISABLED \ + | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)) + +/** + * shell option description: + */ +/** Descriptive text for the shell option */ +#define SHELL_DESC (genshellopt_opt_strs+990) +/** Upper-cased name for the shell option */ +#define SHELL_NAME (genshellopt_opt_strs+1022) +/** disablement name for the shell option */ +#define NOT_SHELL_name (genshellopt_opt_strs+1028) +/** disablement prefix for the shell option */ +#define NOT_SHELL_PFX (genshellopt_opt_strs+1037) +/** Name string for the shell option */ +#define SHELL_name (NOT_SHELL_name + 3) +/** Compiled in flag settings for the shell option */ +#define SHELL_FLAGS (OPTST_INITENABLED \ + | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)) + +/* + * Help/More_Help/Version option descriptions: + */ +#define HELP_DESC (genshellopt_opt_strs+1040) +#define HELP_name (genshellopt_opt_strs+1084) +#ifdef HAVE_WORKING_FORK +#define MORE_HELP_DESC (genshellopt_opt_strs+1089) +#define MORE_HELP_name (genshellopt_opt_strs+1134) +#define MORE_HELP_FLAGS (OPTST_IMM | OPTST_NO_INIT) +#else +#define MORE_HELP_DESC HELP_DESC +#define MORE_HELP_name HELP_name +#define MORE_HELP_FLAGS (OPTST_OMITTED | OPTST_NO_INIT) +#endif +#ifdef NO_OPTIONAL_OPT_ARGS +# define VER_FLAGS (OPTST_IMM | OPTST_NO_INIT) +#else +# define VER_FLAGS (OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \ + OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT) +#endif +#define VER_DESC (genshellopt_opt_strs+1144) +#define VER_name (genshellopt_opt_strs+1180) +/** + * Declare option callback procedures + */ +extern tOptProc + optionBooleanVal, optionNestedVal, optionNumericVal, + optionPagedUsage, optionPrintVersion, optionResetOpt, + optionStackArg, optionTimeDate, optionTimeVal, + optionUnstackArg, optionVendorOption; +static tOptProc + doUsageOpt; +#define VER_PROC optionPrintVersion + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * Define the genshellopt Option Descriptions. + * This is an array of GENSHELL_OPTION_CT entries, one for each + * option that the genshellopt program responds to. + */ +static tOptDesc optDesc[GENSHELL_OPTION_CT] = { + { /* entry idx, value */ 0, VALUE_GENSHELL_OPT_SCRIPT, + /* equiv idx, value */ 0, VALUE_GENSHELL_OPT_SCRIPT, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ SCRIPT_FLAGS, 0, + /* last opt argumnt */ { NULL }, /* --script */ + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ NULL, + /* desc, NAME, name */ SCRIPT_DESC, SCRIPT_NAME, SCRIPT_name, + /* disablement strs */ NULL, NULL }, + + { /* entry idx, value */ 1, VALUE_GENSHELL_OPT_SHELL, + /* equiv idx, value */ 1, VALUE_GENSHELL_OPT_SHELL, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ SHELL_FLAGS, 0, + /* last opt argumnt */ { NULL }, /* --shell */ + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ NULL, + /* desc, NAME, name */ SHELL_DESC, SHELL_NAME, SHELL_name, + /* disablement strs */ NOT_SHELL_name, NOT_SHELL_PFX }, + + { /* entry idx, value */ INDEX_GENSHELL_OPT_VERSION, VALUE_GENSHELL_OPT_VERSION, + /* equiv idx value */ NO_EQUIVALENT, VALUE_GENSHELL_OPT_VERSION, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ VER_FLAGS, AOUSE_VERSION, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ VER_PROC, + /* desc, NAME, name */ VER_DESC, NULL, VER_name, + /* disablement strs */ NULL, NULL }, + + + + { /* entry idx, value */ INDEX_GENSHELL_OPT_HELP, VALUE_GENSHELL_OPT_HELP, + /* equiv idx value */ NO_EQUIVALENT, VALUE_GENSHELL_OPT_HELP, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ OPTST_IMM | OPTST_NO_INIT, AOUSE_HELP, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ doUsageOpt, + /* desc, NAME, name */ HELP_DESC, NULL, HELP_name, + /* disablement strs */ NULL, NULL }, + + { /* entry idx, value */ INDEX_GENSHELL_OPT_MORE_HELP, VALUE_GENSHELL_OPT_MORE_HELP, + /* equiv idx value */ NO_EQUIVALENT, VALUE_GENSHELL_OPT_MORE_HELP, + /* equivalenced to */ NO_EQUIVALENT, + /* min, max, act ct */ 0, 1, 0, + /* opt state flags */ MORE_HELP_FLAGS, AOUSE_MORE_HELP, + /* last opt argumnt */ { NULL }, + /* arg list/cookie */ NULL, + /* must/cannot opts */ NULL, NULL, + /* option proc */ optionPagedUsage, + /* desc, NAME, name */ MORE_HELP_DESC, NULL, MORE_HELP_name, + /* disablement strs */ NULL, NULL } +}; + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** Reference to the upper cased version of genshellopt. */ +#define zPROGNAME (genshellopt_opt_strs+1188) +/** Reference to the title line for genshellopt usage. */ +#define zUsageTitle (genshellopt_opt_strs+1200) +/** There is no genshellopt configuration file. */ +#define zRcName NULL +/** There are no directories to search for genshellopt config files. */ +#define apzHomeList NULL +/** The genshellopt program bug email address. */ +#define zBugsAddr (genshellopt_opt_strs+1321) +/** Clarification/explanation of what genshellopt does. */ +#define zExplain (genshellopt_opt_strs+1357) +/** Extra detail explaining what genshellopt does. */ +#define zDetail (genshellopt_opt_strs+1534) +/** The full version string for genshellopt. */ +#define zFullVersion (genshellopt_opt_strs+1755) +/* extracted from optcode.tlib near line 342 */ + +#if defined(ENABLE_NLS) +# define OPTPROC_BASE OPTPROC_TRANSLATE + static tOptionXlateProc translate_option_strings; +#else +# define OPTPROC_BASE OPTPROC_NONE +# define translate_option_strings NULL +#endif /* ENABLE_NLS */ + +#define genshellopt_full_usage (NULL) +#define genshellopt_short_usage (NULL) + +#endif /* not defined __doxygen__ */ + +/* + * Create the static procedure(s) declared above. + */ +/** + * The callout function that invokes the genshelloptUsage function. + * + * @param[in] opts the AutoOpts option description structure + * @param[in] od the descriptor for the "help" (usage) option. + * @noreturn + */ +static void +doUsageOpt(tOptions * opts, tOptDesc * od) +{ + int ex_code; + ex_code = GENSHELLOPT_EXIT_SUCCESS; + genshelloptUsage(&genshelloptOptions, ex_code); + /* NOTREACHED */ + exit(GENSHELLOPT_EXIT_FAILURE); + (void)opts; + (void)od; +} +/* extracted from optmain.tlib near line 1250 */ + +/** + * The directory containing the data associated with genshellopt. + */ +#ifndef PKGDATADIR +# define PKGDATADIR "" +#endif + +/** + * Information about the person or institution that packaged genshellopt + * for the current distribution. + */ +#ifndef WITH_PACKAGER +# define genshellopt_packager_info NULL +#else +/** Packager information for genshellopt. */ +static char const genshellopt_packager_info[] = + "Packaged by " WITH_PACKAGER + +# ifdef WITH_PACKAGER_VERSION + " ("WITH_PACKAGER_VERSION")" +# endif + +# ifdef WITH_PACKAGER_BUG_REPORTS + "\nReport genshellopt bugs to " WITH_PACKAGER_BUG_REPORTS +# endif + "\n"; +#endif +#ifndef __doxygen__ + +#endif /* __doxygen__ */ +/** + * The option definitions for genshellopt. The one structure that + * binds them all. + */ +tOptions genshelloptOptions = { + OPTIONS_STRUCT_VERSION, + 0, NULL, /* original argc + argv */ + ( OPTPROC_BASE + + OPTPROC_ERRSTOP + + OPTPROC_SHORTOPT + + OPTPROC_LONGOPT + + OPTPROC_NO_REQ_OPT + + OPTPROC_NEGATIONS + + OPTPROC_NO_ARGS ), + 0, NULL, /* current option index, current option */ + NULL, NULL, zPROGNAME, + zRcName, zCopyright, zLicenseDescrip, + zFullVersion, apzHomeList, zUsageTitle, + zExplain, zDetail, optDesc, + zBugsAddr, /* address to send bugs to */ + NULL, NULL, /* extensions/saved state */ + genshelloptUsage, /* usage procedure */ + translate_option_strings, /* translation procedure */ + /* + * Indexes to special options + */ + { INDEX_GENSHELL_OPT_MORE_HELP, /* more-help option index */ + NO_EQUIVALENT, /* save option index */ + NO_EQUIVALENT, /* '-#' option index */ + NO_EQUIVALENT /* index of default opt */ + }, + 5 /* full option count */, 2 /* user option count */, + genshellopt_full_usage, genshellopt_short_usage, + NULL, NULL, + PKGDATADIR, genshellopt_packager_info +}; + +#if ENABLE_NLS +/** + * This code is designed to translate translatable option text for the + * genshellopt program. These translations happen upon entry + * to optionProcess(). + */ +#include +#include +#include +#include +#ifdef HAVE_DCGETTEXT +# include +#endif +#include + +static char * AO_gettext(char const * pz); +static void coerce_it(void ** s); + +/** + * AutoGen specific wrapper function for gettext. It relies on the macro _() + * to convert from English to the target language, then strdup-duplicates the + * result string. It tries the "libopts" domain first, then whatever has been + * set via the \a textdomain(3) call. + * + * @param[in] pz the input text used as a lookup key. + * @returns the translated text (if there is one), + * or the original text (if not). + */ +static char * +AO_gettext(char const * pz) +{ + char * res; + if (pz == NULL) + return NULL; +#ifdef HAVE_DCGETTEXT + /* + * While processing the option_xlateable_txt data, try to use the + * "libopts" domain. Once we switch to the option descriptor data, + * do *not* use that domain. + */ + if (option_xlateable_txt.field_ct != 0) { + res = dgettext("libopts", pz); + if (res == pz) + res = (char *)VOIDP(_(pz)); + } else + res = (char *)VOIDP(_(pz)); +#else + res = (char *)VOIDP(_(pz)); +#endif + if (res == pz) + return res; + res = strdup(res); + if (res == NULL) { + fputs(_("No memory for duping translated strings\n"), stderr); + exit(GENSHELLOPT_EXIT_FAILURE); + } + return res; +} + +/** + * All the pointers we use are marked "* const", but they are stored in + * writable memory. Coerce the mutability and set the pointer. + */ +static void coerce_it(void ** s) { *s = AO_gettext(*s); +} + +/** + * Translate all the translatable strings in the genshelloptOptions + * structure defined above. This is done only once. + */ +static void +translate_option_strings(void) +{ + tOptions * const opts = &genshelloptOptions; + + /* + * Guard against re-translation. It won't work. The strings will have + * been changed by the first pass through this code. One shot only. + */ + if (option_xlateable_txt.field_ct != 0) { + /* + * Do the translations. The first pointer follows the field count + * field. The field count field is the size of a pointer. + */ + char ** ppz = (char**)VOIDP(&(option_xlateable_txt)); + int ix = option_xlateable_txt.field_ct; + + do { + ppz++; /* skip over field_ct */ + *ppz = AO_gettext(*ppz); + } while (--ix > 0); + /* prevent re-translation and disable "libopts" domain lookup */ + option_xlateable_txt.field_ct = 0; + + coerce_it(VOIDP(&(opts->pzCopyright))); + coerce_it(VOIDP(&(opts->pzCopyNotice))); + coerce_it(VOIDP(&(opts->pzFullVersion))); + coerce_it(VOIDP(&(opts->pzUsageTitle))); + coerce_it(VOIDP(&(opts->pzExplain))); + coerce_it(VOIDP(&(opts->pzDetail))); + { + tOptDesc * od = opts->pOptDesc; + for (ix = opts->optCt; ix > 0; ix--, od++) + coerce_it(VOIDP(&(od->pzText))); + } + } +} +#endif /* ENABLE_NLS */ + +#ifdef DO_NOT_COMPILE_THIS_CODE_IT_IS_FOR_GETTEXT +/** I18N function strictly for xgettext. Do not compile. */ +static void bogus_function(void) { + /* TRANSLATORS: + + The following dummy function was crated solely so that xgettext can + extract the correct strings. These strings are actually referenced + by a field name in the genshelloptOptions structure noted in the + comments below. The literal text is defined in genshellopt_opt_strs. + + NOTE: the strings below are segmented with respect to the source string + genshellopt_opt_strs. The strings above are handed off for translation + at run time a paragraph at a time. Consequently, they are presented here + for translation a paragraph at a time. + + ALSO: often the description for an option will reference another option + by name. These are set off with apostrophe quotes (I hope). Do not + translate option names. + */ + /* referenced via genshelloptOptions.pzCopyright */ + puts(_("genshellopt 1\n\ +Copyright (C) 1999-2018 Bruce Korb, all rights reserved.\n\ +This is free software. It is licensed for use, modification and\n\ +redistribution under the terms of the GNU Lesser General Public License,\n\ +version 2 or later \n")); + + /* referenced via genshelloptOptions.pzCopyNotice */ + puts(_("The genshellopt library is free software; you can redistribute it and/or\n\ +modify it under the terms of the GNU Library General Public License as\n\ +published by the Free Software Foundation; either version 2 of the License,\n\ +or (at your option) any later version.\n\n")); + puts(_("This library is distributed in the hope that it will be useful, but WITHOUT\n\ +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n\ +FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public\n\ +License for more details.\n\n")); + puts(_("You should have received a copy of the GNU Library General Public License\n\ +along with this library; if not, see\n\ +\n")); + + /* referenced via genshelloptOptions.pOptDesc->pzText */ + puts(_("Output Script File")); + + /* referenced via genshelloptOptions.pOptDesc->pzText */ + puts(_("Shell name (follows \"#!\" magic)")); + + /* referenced via genshelloptOptions.pOptDesc->pzText */ + puts(_("display extended usage information and exit")); + + /* referenced via genshelloptOptions.pOptDesc->pzText */ + puts(_("extended usage information passed thru pager")); + + /* referenced via genshelloptOptions.pOptDesc->pzText */ + puts(_("output version information and exit")); + + /* referenced via genshelloptOptions.pzUsageTitle */ + puts(_("genshellopt - Generate Shell Option Processing Script - Ver. 1\n\ +Usage: %s [ - [] | --[{=| }] ]...\n")); + + /* referenced via genshelloptOptions.pzExplain */ + puts(_("Note that 'shell' is only useful if the output file does not already exist.\n\ +If it does, then the shell name and optional first argument will be\n\ +extracted from the script file.\n")); + + /* referenced via genshelloptOptions.pzDetail */ + puts(_("If the script file already exists and contains Automated Option Processing\n\ +text, the second line of the file through the ending tag will be replaced\n\ +by the newly generated text. The first '#!' line will be regenerated.\n")); + + /* referenced via genshelloptOptions.pzFullVersion */ + puts(_("genshellopt 1")); + + /* referenced via genshelloptOptions.pzFullUsage */ + puts(_("<<>>")); + + /* referenced via genshelloptOptions.pzShortUsage */ + puts(_("<<>>")); + /* LIBOPTS-MESSAGES: */ +#line 67 "../autoopts.c" + puts(_("allocation of %d bytes failed\n")); +#line 89 "../autoopts.c" + puts(_("allocation of %d bytes failed\n")); +#line 48 "../init.c" + puts(_("AutoOpts function called without option descriptor\n")); +#line 81 "../init.c" + puts(_("\tThis exceeds the compiled library version: ")); +#line 79 "../init.c" + puts(_("Automated Options Processing Error!\n" + "\t%s called AutoOpts function with structure version %d:%d:%d.\n")); +#line 78 "../autoopts.c" + puts(_("realloc of %d bytes at 0x%p failed\n")); +#line 83 "../init.c" + puts(_("\tThis is less than the minimum library version: ")); +#line 121 "../version.c" + puts(_("Automated Options version %s\n" + "\tCopyright (C) 1999-2017 by Bruce Korb - all rights reserved\n")); +#line 49 "../makeshell.c" + puts(_("(AutoOpts bug): %s.\n")); +#line 90 "../reset.c" + puts(_("optionResetOpt() called, but reset-option not configured")); +#line 241 "../usage.c" + puts(_("could not locate the 'help' option")); +#line 330 "../autoopts.c" + puts(_("optionProcess() was called with invalid data")); +#line 697 "../usage.c" + puts(_("invalid argument type specified")); +#line 568 "../find.c" + puts(_("defaulted to option with optional arg")); +#line 76 "../alias.c" + puts(_("aliasing option is out of range.")); +#line 210 "../enum.c" + puts(_("%s error: the keyword '%s' is ambiguous for %s\n")); +#line 78 "../find.c" + puts(_(" The following options match:\n")); +#line 263 "../find.c" + puts(_("%s: ambiguous option name: %s (matches %d options)\n")); +#line 161 "../check.c" + puts(_("%s: Command line arguments required\n")); +#line 43 "../alias.c" + puts(_("%d %s%s options allowed\n")); +#line 56 "../makeshell.c" + puts(_("%s error %d (%s) calling %s for '%s'\n")); +#line 268 "../makeshell.c" + puts(_("interprocess pipe")); +#line 171 "../version.c" + puts(_("error: version option argument '%c' invalid. Use:\n" + "\t'v' - version only\n" + "\t'c' - version and copyright\n" + "\t'n' - version and full copyright notice\n")); +#line 58 "../check.c" + puts(_("%s error: the '%s' and '%s' options conflict\n")); +#line 187 "../find.c" + puts(_("%s: The '%s' option has been disabled.")); +#line 400 "../find.c" + puts(_("%s: The '%s' option has been disabled.")); +#line 38 "../alias.c" + puts(_("-equivalence")); +#line 439 "../find.c" + puts(_("%s: illegal option -- %c\n")); +#line 110 "../reset.c" + puts(_("%s: illegal option -- %c\n")); +#line 241 "../find.c" + puts(_("%s: illegal option -- %s\n")); +#line 740 "../find.c" + puts(_("%s: illegal option -- %s\n")); +#line 118 "../reset.c" + puts(_("%s: illegal option -- %s\n")); +#line 305 "../find.c" + puts(_("%s: unknown vendor extension option -- %s\n")); +#line 135 "../enum.c" + puts(_(" or an integer from %d through %d\n")); +#line 145 "../enum.c" + puts(_(" or an integer from %d through %d\n")); +#line 696 "../usage.c" + puts(_("%s error: invalid option descriptor for %s\n")); +#line 1030 "../usage.c" + puts(_("%s error: invalid option descriptor for %s\n")); +#line 355 "../find.c" + puts(_("%s: invalid option name: %s\n")); +#line 497 "../find.c" + puts(_("%s: The '%s' option requires an argument.\n")); +#line 150 "../autoopts.c" + puts(_("(AutoOpts bug): Equivalenced option '%s' was equivalenced to both\n" + "\t'%s' and '%s'.")); +#line 94 "../check.c" + puts(_("%s error: The %s option is required\n")); +#line 602 "../find.c" + puts(_("%s: The '%s' option cannot have an argument.\n")); +#line 151 "../check.c" + puts(_("%s: Command line arguments are not allowed.\n")); +#line 568 "../save.c" + puts(_("error %d (%s) creating %s\n")); +#line 210 "../enum.c" + puts(_("%s error: '%s' does not match any %s keywords.\n")); +#line 93 "../reset.c" + puts(_("%s error: The '%s' option requires an argument.\n")); +#line 122 "../save.c" + puts(_("error %d (%s) stat-ing %s\n")); +#line 175 "../save.c" + puts(_("error %d (%s) stat-ing %s\n")); +#line 143 "../restore.c" + puts(_("%s error: no saved option state\n")); +#line 225 "../autoopts.c" + puts(_("'%s' is not a command line option.\n")); +#line 113 "../time.c" + puts(_("%s error: '%s' is not a recognizable date/time.\n")); +#line 50 "../time.c" + puts(_("%s error: '%s' is not a recognizable time duration.\n")); +#line 92 "../check.c" + puts(_("%s error: The %s option must appear %d times.\n")); +#line 165 "../numeric.c" + puts(_("%s error: '%s' is not a recognizable number.\n")); +#line 176 "../enum.c" + puts(_("%s error: %s exceeds %s keyword count\n")); +#line 279 "../usage.c" + puts(_("Try '%s %s' for more information.\n")); +#line 45 "../alias.c" + puts(_("one %s%s option allowed\n")); +#line 170 "../makeshell.c" + puts(_("standard output")); +#line 905 "../makeshell.c" + puts(_("standard output")); +#line 223 "../usage.c" + puts(_("standard output")); +#line 364 "../usage.c" + puts(_("standard output")); +#line 574 "../usage.c" + puts(_("standard output")); +#line 178 "../version.c" + puts(_("standard output")); +#line 223 "../usage.c" + puts(_("standard error")); +#line 364 "../usage.c" + puts(_("standard error")); +#line 574 "../usage.c" + puts(_("standard error")); +#line 178 "../version.c" + puts(_("standard error")); +#line 170 "../makeshell.c" + puts(_("write")); +#line 905 "../makeshell.c" + puts(_("write")); +#line 222 "../usage.c" + puts(_("write")); +#line 363 "../usage.c" + puts(_("write")); +#line 573 "../usage.c" + puts(_("write")); +#line 177 "../version.c" + puts(_("write")); +#line 60 "../numeric.c" + puts(_("%s error: %s option value %ld is out of range.\n")); +#line 44 "../check.c" + puts(_("%s error: %s option requires the %s option\n")); +#line 121 "../save.c" + puts(_("%s warning: cannot save options - %s not regular file\n")); +#line 174 "../save.c" + puts(_("%s warning: cannot save options - %s not regular file\n")); +#line 193 "../save.c" + puts(_("%s warning: cannot save options - %s not regular file\n")); +#line 567 "../save.c" + puts(_("%s warning: cannot save options - %s not regular file\n")); + /* END-LIBOPTS-MESSAGES */ + + /* USAGE-TEXT: */ +#line 822 "../usage.c" + puts(_("\t\t\t\t- an alternate for '%s'\n")); +#line 1097 "../usage.c" + puts(_("Version, usage and configuration options:")); +#line 873 "../usage.c" + puts(_("\t\t\t\t- default option for unnamed options\n")); +#line 786 "../usage.c" + puts(_("\t\t\t\t- disabled as '--%s'\n")); +#line 1066 "../usage.c" + puts(_(" --- %-14s %s\n")); +#line 1064 "../usage.c" + puts(_("This option has been disabled")); +#line 813 "../usage.c" + puts(_("\t\t\t\t- enabled by default\n")); +#line 40 "../alias.c" + puts(_("%s error: only ")); +#line 1143 "../usage.c" + puts(_(" - examining environment variables named %s_*\n")); +#line 168 "../file.c" + puts(_("\t\t\t\t- file must not pre-exist\n")); +#line 172 "../file.c" + puts(_("\t\t\t\t- file must pre-exist\n")); +#line 329 "../usage.c" + puts(_("Options are specified by doubled hyphens and their name or by a single\n" + "hyphen and the flag character.\n")); +#line 882 "../makeshell.c" + puts(_("\n" + "= = = = = = = =\n\n" + "This incarnation of genshell will produce\n" + "a shell script to parse the options for %s:\n\n")); +#line 142 "../enum.c" + puts(_(" or an integer mask with any of the lower %d bits set\n")); +#line 846 "../usage.c" + puts(_("\t\t\t\t- is a set membership option\n")); +#line 867 "../usage.c" + puts(_("\t\t\t\t- must appear between %d and %d times\n")); +#line 331 "../usage.c" + puts(_("Options are specified by single or double hyphens and their name.\n")); +#line 853 "../usage.c" + puts(_("\t\t\t\t- may appear multiple times\n")); +#line 840 "../usage.c" + puts(_("\t\t\t\t- may not be preset\n")); +#line 1258 "../usage.c" + puts(_(" Arg Option-Name Description\n")); +#line 1194 "../usage.c" + puts(_(" Flg Arg Option-Name Description\n")); +#line 1252 "../usage.c" + puts(_(" Flg Arg Option-Name Description\n")); +#line 1253 "../usage.c" + puts(_(" %3s %s")); +#line 1259 "../usage.c" + puts(_(" %3s %s")); +#line 336 "../usage.c" + puts(_("The '-#' option may omit the hash char\n")); +#line 332 "../usage.c" + puts(_("All arguments are named options.\n")); +#line 920 "../usage.c" + puts(_(" - reading file %s")); +#line 358 "../usage.c" + puts(_("\n" + "Please send bug reports to: <%s>\n")); +#line 100 "../version.c" + puts(_("\n" + "Please send bug reports to: <%s>\n")); +#line 129 "../version.c" + puts(_("\n" + "Please send bug reports to: <%s>\n")); +#line 852 "../usage.c" + puts(_("\t\t\t\t- may NOT appear - preset only\n")); +#line 893 "../usage.c" + puts(_("\n" + "The following option preset mechanisms are supported:\n")); +#line 1141 "../usage.c" + puts(_("\n" + "The following option preset mechanisms are supported:\n")); +#line 631 "../usage.c" + puts(_("prohibits these options:\n")); +#line 626 "../usage.c" + puts(_("prohibits the option '%s'\n")); +#line 81 "../numeric.c" + puts(_("%s%ld to %ld")); +#line 79 "../numeric.c" + puts(_("%sgreater than or equal to %ld")); +#line 75 "../numeric.c" + puts(_("%s%ld exactly")); +#line 68 "../numeric.c" + puts(_("%sit must lie in one of the ranges:\n")); +#line 68 "../numeric.c" + puts(_("%sit must be in the range:\n")); +#line 88 "../numeric.c" + puts(_(", or\n")); +#line 66 "../numeric.c" + puts(_("%sis scalable with a suffix: k/K/m/M/g/G/t/T\n")); +#line 77 "../numeric.c" + puts(_("%sless than or equal to %ld")); +#line 339 "../usage.c" + puts(_("Operands and options may be intermixed. They will be reordered.\n")); +#line 601 "../usage.c" + puts(_("requires the option '%s'\n")); +#line 604 "../usage.c" + puts(_("requires these options:\n")); +#line 1270 "../usage.c" + puts(_(" Arg Option-Name Req? Description\n")); +#line 1264 "../usage.c" + puts(_(" Flg Arg Option-Name Req? Description\n")); +#line 143 "../enum.c" + puts(_("or you may use a numeric representation. Preceding these with a '!'\n" + "will clear the bits, specifying 'none' will clear all bits, and 'all'\n" + "will set them all. Multiple entries may be passed as an option\n" + "argument list.\n")); +#line 859 "../usage.c" + puts(_("\t\t\t\t- may appear up to %d times\n")); +#line 52 "../enum.c" + puts(_("The valid \"%s\" option keywords are:\n")); +#line 1101 "../usage.c" + puts(_("The next option supports vendor supported extra options:")); +#line 722 "../usage.c" + puts(_("These additional options are:")); + /* END-USAGE-TEXT */ +} +#endif /* uncompilable code */ +#ifdef __cplusplus +} +#endif +/* genshell.c ends here */ diff --git a/src/libopts/genshell.h b/src/libopts/genshell.h new file mode 100644 index 0000000..994af16 --- /dev/null +++ b/src/libopts/genshell.h @@ -0,0 +1,224 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (genshell.h) + * + * It has been AutoGen-ed + * From the definitions genshell.def + * and the template file options + * + * Generated from AutoOpts 42:1:17 templates. + * + * AutoOpts is a copyrighted work. This header file is not encumbered + * by AutoOpts licensing, but is provided under the licensing terms chosen + * by the genshellopt author or copyright holder. AutoOpts is + * licensed under the terms of the LGPL. The redistributable library + * (``libopts'') is licensed under the terms of either the LGPL or, at the + * users discretion, the BSD license. See the AutoOpts and/or libopts sources + * for details. + * + * The genshellopt program is copyrighted and licensed + * under the following terms: + * + * Copyright (C) 1999-2018 Bruce Korb, all rights reserved. + * This is free software. It is licensed for use, modification and + * redistribution under the terms of the GNU Lesser General Public License, + * version 2 or later + * + * The genshellopt library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, see + * + */ +/** + * This file contains the programmatic interface to the Automated + * Options generated for the genshellopt program. + * These macros are documented in the AutoGen info file in the + * "AutoOpts" chapter. Please refer to that doc for usage help. + */ +#ifndef AUTOOPTS_GENSHELL_H_GUARD +#define AUTOOPTS_GENSHELL_H_GUARD 1 +#include +#include +#include + +/** + * Ensure that the library used for compiling this generated header is at + * least as new as the version current when the header template was released + * (not counting patch version increments). Also ensure that the oldest + * tolerable version is at least as old as what was current when the header + * template was released. + */ +#define AO_TEMPLATE_VERSION 172033 +#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \ + || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION) +# error option template version mismatches autoopts/options.h header + Choke Me. +#endif + +#if GCC_VERSION > 40400 +#define NOT_REACHED __builtin_unreachable(); +#else +#define NOT_REACHED +#endif + +/** + * Enumeration of each option type for genshellopt + */ +typedef enum { + INDEX_GENSHELL_OPT_SCRIPT = 0, + INDEX_GENSHELL_OPT_SHELL = 1, + INDEX_GENSHELL_OPT_VERSION = 2, + INDEX_GENSHELL_OPT_HELP = 3, + INDEX_GENSHELL_OPT_MORE_HELP = 4 +} teGenshell_OptIndex; +/** count of all options for genshellopt */ +#define GENSHELL_OPTION_CT 5 +/** genshellopt version */ +#define GENSHELLOPT_VERSION "1" +/** Full genshellopt version text */ +#define GENSHELLOPT_FULL_VERSION "genshellopt 1" + +/** + * Interface defines for all options. Replace "n" with the UPPER_CASED + * option name (as in the teGenshell_OptIndex enumeration above). + * e.g. HAVE_GENSHELL_OPT(SCRIPT) + */ +#define GENSHELL_DESC(n) (genshelloptOptions.pOptDesc[INDEX_GENSHELL_OPT_## n]) +/** 'true' if an option has been specified in any way */ +#define HAVE_GENSHELL_OPT(n) (! UNUSED_OPT(& GENSHELL_DESC(n))) +/** The string argument to an option. The argument type must be \"string\". */ +#define GENSHELL_OPT_ARG(n) (GENSHELL_DESC(n).optArg.argString) +/** Mask the option state revealing how an option was specified. + * It will be one and only one of \a OPTST_SET, \a OPTST_PRESET, + * \a OPTST_DEFINED, \a OPTST_RESET or zero. + */ +#define STATE_GENSHELL_OPT(n) (GENSHELL_DESC(n).fOptState & OPTST_SET_MASK) +/** Count of option's occurrances *on the command line*. */ +#define COUNT_GENSHELL_OPT(n) (GENSHELL_DESC(n).optOccCt) +/** mask of \a OPTST_SET and \a OPTST_DEFINED. */ +#define ISSEL_GENSHELL_OPT(n) (SELECTED_OPT(&GENSHELL_DESC(n))) +/** 'true' if \a HAVE_OPT would yield 'false'. */ +#define ISUNUSED_GENSHELL_OPT(n) (UNUSED_OPT(& GENSHELL_DESC(n))) +/** 'true' if OPTST_DISABLED bit not set. */ +#define ENABLED_GENSHELL_OPT(n) (! DISABLED_OPT(& GENSHELL_DESC(n))) +/** number of stacked option arguments. + * Valid only for stacked option arguments. */ +#define STACKCT_GENSHELL_OPT(n) (((tArgList*)(GENSHELL_DESC(n).optCookie))->useCt) +/** stacked argument vector. + * Valid only for stacked option arguments. */ +#define STACKLST_GENSHELL_OPT(n) (((tArgList*)(GENSHELL_DESC(n).optCookie))->apzArgs) +/** Reset an option. */ +#define CLEAR_GENSHELL_OPT(n) STMTS( \ + GENSHELL_DESC(n).fOptState &= OPTST_PERSISTENT_MASK; \ + if ((GENSHELL_DESC(n).fOptState & OPTST_INITENABLED) == 0) \ + GENSHELL_DESC(n).fOptState |= OPTST_DISABLED; \ + GENSHELL_DESC(n).optCookie = NULL ) +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * Enumeration of genshellopt exit codes + */ +typedef enum { + GENSHELLOPT_EXIT_SUCCESS = 0, + GENSHELLOPT_EXIT_FAILURE = 1, + GENSHELLOPT_EXIT_USAGE_ERROR = 64, + GENSHELLOPT_EXIT_LIBOPTS_FAILURE = 70 +} genshellopt_exit_code_t; +/** + * Interface defines for specific options. + * @{ + */ +#define VALUE_GENSHELL_OPT_SCRIPT 'o' +#define VALUE_GENSHELL_OPT_SHELL 's' +/** option flag (value) for help-value option */ +#define VALUE_GENSHELL_OPT_HELP '?' +/** option flag (value) for more-help-value option */ +#define VALUE_GENSHELL_OPT_MORE_HELP '!' +/** option flag (value) for version-value option */ +#define VALUE_GENSHELL_OPT_VERSION 'v' +/* + * Interface defines not associated with particular options + */ +#define ERRSKIP_GENSHELL_OPTERR STMTS(genshelloptOptions.fOptSet &= ~OPTPROC_ERRSTOP) +#define ERRSTOP_GENSHELL_OPTERR STMTS(genshelloptOptions.fOptSet |= OPTPROC_ERRSTOP) +#define RESTART_GENSHELL_OPT(n) STMTS( \ + genshelloptOptions.curOptIdx = (n); \ + genshelloptOptions.pzCurOpt = NULL ) +#define START_GENSHELL_OPT RESTART_GENSHELL_OPT(1) +#define GENSHELL_USAGE(c) (*genshelloptOptions.pUsageProc)(&genshelloptOptions, c) + +#ifdef __cplusplus +extern "C" { +#endif +/* + * global exported definitions + */ +#define ch_t unsigned char +#define cc_t const unsigned char +#define cch_t char const + + +/* * * * * * + * + * Declare the genshellopt option descriptor. + */ +extern tOptions genshelloptOptions; + +#if defined(ENABLE_NLS) +# ifndef _ +# include +# ifndef HAVE_GETTEXT + extern char * gettext(char const *); +# else +# include +# endif + +# ifndef ATTRIBUTE_FORMAT_ARG +# define ATTRIBUTE_FORMAT_ARG(_a) +# endif + +static inline char* aoGetsText(char const* pz) ATTRIBUTE_FORMAT_ARG(1); +static inline char* aoGetsText(char const* pz) { + if (pz == NULL) return NULL; + return (char*)gettext(pz); +} +# define _(s) aoGetsText(s) +# endif /* _() */ + +# define OPT_NO_XLAT_CFG_NAMES STMTS(genshelloptOptions.fOptSet |= \ + OPTPROC_NXLAT_OPT_CFG;) +# define OPT_NO_XLAT_OPT_NAMES STMTS(genshelloptOptions.fOptSet |= \ + OPTPROC_NXLAT_OPT|OPTPROC_NXLAT_OPT_CFG;) + +# define OPT_XLAT_CFG_NAMES STMTS(genshelloptOptions.fOptSet &= \ + ~(OPTPROC_NXLAT_OPT|OPTPROC_NXLAT_OPT_CFG);) +# define OPT_XLAT_OPT_NAMES STMTS(genshelloptOptions.fOptSet &= \ + ~OPTPROC_NXLAT_OPT;) + +#else /* ENABLE_NLS */ +# define OPT_NO_XLAT_CFG_NAMES +# define OPT_NO_XLAT_OPT_NAMES + +# define OPT_XLAT_CFG_NAMES +# define OPT_XLAT_OPT_NAMES + +# ifndef _ +# define _(_s) _s +# endif +#endif /* ENABLE_NLS */ + + +#ifdef __cplusplus +} +#endif +#endif /* AUTOOPTS_GENSHELL_H_GUARD */ + +/* genshell.h ends here */ diff --git a/src/libopts/gettext.h b/src/libopts/gettext.h new file mode 100644 index 0000000..87ec819 --- /dev/null +++ b/src/libopts/gettext.h @@ -0,0 +1,294 @@ +/* Convenience header for conditional use of GNU . + Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2018 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1, 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License along + with this program; if not, see . */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option + or through "#define ENABLE NLS 0" before including this file. */ +#if defined ENABLE_NLS && ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +# include + +/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by + the gettext() and ngettext() macros. This is an alternative to calling + textdomain(), and is useful for libraries. */ +# ifdef DEFAULT_TEXT_DOMAIN +# undef gettext +# define gettext(Msgid) \ + dgettext (DEFAULT_TEXT_DOMAIN, Msgid) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) +# endif + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of a NOP. We don't include + as well because people using "gettext.h" will not include , + and also including would fail on SunOS 4, whereas + is OK. */ +#if defined(__sun) +# include +#endif + +/* Many header files from the libstdc++ coming with g++ 3.3 or newer include + , which chokes if dcgettext is defined as a macro. So include + it now, to make later inclusions of a NOP. */ +#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) +# include +# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H +# include +# endif +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +# undef gettext +# define gettext(Msgid) ((const char *) (Msgid)) +# undef dgettext +# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) +# undef dcgettext +# define dcgettext(Domainname, Msgid, Category) \ + ((void) (Category), dgettext (Domainname, Msgid)) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 \ + ? ((void) (Msgid2), (const char *) (Msgid1)) \ + : ((void) (Msgid1), (const char *) (Msgid2))) +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) +# undef textdomain +# define textdomain(Domainname) ((const char *) (Domainname)) +# undef bindtextdomain +# define bindtextdomain(Domainname, Dirname) \ + ((void) (Domainname), (const char *) (Dirname)) +# undef bind_textdomain_codeset +# define bind_textdomain_codeset(Domainname, Codeset) \ + ((void) (Domainname), (const char *) (Codeset)) + +#endif + +/* Prefer gnulib's setlocale override over libintl's setlocale override. */ +#ifdef GNULIB_defined_setlocale +# undef setlocale +# define setlocale rpl_setlocale +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +/* The separator between msgctxt and msgid in a .mo file. */ +#define GETTEXT_CONTEXT_GLUE "\004" + +/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a + MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be + short and rarely need to change. + The letter 'p' stands for 'particular' or 'special'. */ +#ifdef DEFAULT_TEXT_DOMAIN +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#else +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#endif +#define dpgettext(Domainname, Msgctxt, Msgid) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) +#ifdef DEFAULT_TEXT_DOMAIN +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#else +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#endif +#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +pgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + int category) +{ + const char *translation = dcgettext (domain, msg_ctxt_id, category); + if (translation == msg_ctxt_id) + return msgid; + else + return translation; +} + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +npgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + const char *translation = + dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); + if (translation == msg_ctxt_id || translation == msgid_plural) + return (n == 1 ? msgid : msgid_plural); + else + return translation; +} + +/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID + can be arbitrary expressions. But for string literals these macros are + less efficient than those above. */ + +#include + +#if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \ + /* || __STDC_VERSION__ == 199901L + || (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */ ) +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1 +#else +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0 +#endif + +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS +#include +#endif + +#define pgettext_expr(Msgctxt, Msgid) \ + dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) +#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ + dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + int found_translation; + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcgettext (domain, msg_ctxt_id, category); + found_translation = (translation != msg_ctxt_id); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (found_translation) + return translation; + } + return msgid; +} + +#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcnpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + int found_translation; + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); + found_translation = !(translation == msg_ctxt_id || translation == msgid_plural); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (found_translation) + return translation; + } + return (n == 1 ? msgid : msgid_plural); +} + +#endif /* _LIBGETTEXT_H */ diff --git a/src/libopts/init.c b/src/libopts/init.c new file mode 100644 index 0000000..b65e593 --- /dev/null +++ b/src/libopts/init.c @@ -0,0 +1,289 @@ +/** + * \file initialize.c + * + * initialize the libopts data structures. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/** + * Make sure the option descriptor is there and that we understand it. + * This should be called from any user entry point where one needs to + * worry about validity. (Some entry points are free to assume that + * the call is not the first to the library and, thus, that this has + * already been called.) + * + * Upon successful completion, pzProgName and pzProgPath are set. + * + * @param[in,out] opts program options descriptor + * @param[in] pname name of program, from argv[] + * @returns SUCCESS or FAILURE + */ +static tSuccess +validate_struct(tOptions * opts, char const * pname) +{ + if (opts == NULL) { + fputs(zno_opt_arg, stderr); + return FAILURE; + } + print_exit = ((opts->fOptSet & OPTPROC_SHELL_OUTPUT) != 0); + + /* + * IF the client has enabled translation and the translation procedure + * is available, then go do it. + */ + if ( ((opts->fOptSet & OPTPROC_TRANSLATE) != 0) + && (opts->pTransProc != NULL) + && (option_xlateable_txt.field_ct != 0) ) { + /* + * If option names are not to be translated at all, then do not do + * it for configuration parsing either. (That is the bit that really + * gets tested anyway.) + */ + if ((opts->fOptSet & OPTPROC_NO_XLAT_MASK) == OPTPROC_NXLAT_OPT) + opts->fOptSet |= OPTPROC_NXLAT_OPT_CFG; + opts->pTransProc(); + } + + /* + * IF the struct version is not the current, and also + * either too large (?!) or too small, + * THEN emit error message and fail-exit + */ + if ( ( opts->structVersion != OPTIONS_STRUCT_VERSION ) + && ( (opts->structVersion > OPTIONS_STRUCT_VERSION ) + || (opts->structVersion < OPTIONS_MINIMUM_VERSION ) + ) ) { + fprintf(stderr, zwrong_ver, pname, NUM_TO_VER(opts->structVersion)); + if (opts->structVersion > OPTIONS_STRUCT_VERSION ) + fputs(ztoo_new, stderr); + else + fputs(ztoo_old, stderr); + + fwrite(ao_ver_string, sizeof(ao_ver_string) - 1, 1, stderr); + return FAILURE; + } + + /* + * If the program name hasn't been set, then set the name and the path + * and the set of equivalent characters. + */ + if (opts->pzProgName == NULL) { + char const * pz = strrchr(pname, DIRCH); + char const ** pp = + (char const **)(void **)&(opts->pzProgName); + + if (pz != NULL) + *pp = pz+1; + else + *pp = pname; + + pz = pathfind(getenv("PATH"), (char *)pname, "rx"); + if (pz != NULL) + pname = VOIDP(pz); + + pp = (char const **)VOIDP(&(opts->pzProgPath)); + *pp = pname; + + /* + * when comparing long names, these are equivalent + */ + strequate(zSepChars); + } + + return SUCCESS; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * DO PRESETS + * + * The next several routines do the immediate action pass on the command + * line options, then the environment variables, then the config files in + * reverse order. Once done with that, the order is reversed and all + * the config files and environment variables are processed again, this + * time only processing the non-immediate action options. do_presets() + * will then return for optionProcess() to do the final pass on the command + * line arguments. + */ + +/** + * scan the command line for immediate action options. + * This is only called the first time through. + * While this procedure is active, the OPTPROC_IMMEDIATE is true. + * + * @param pOpts program options descriptor + * @returns SUCCESS or FAILURE + */ +static tSuccess +immediate_opts(tOptions * opts) +{ + tSuccess res; + + opts->fOptSet |= OPTPROC_IMMEDIATE; + opts->curOptIdx = 1; /* start by skipping program name */ + opts->pzCurOpt = NULL; + + /* + * Examine all the options from the start. We process any options that + * are marked for immediate processing. + */ + for (;;) { + tOptState opt_st = OPTSTATE_INITIALIZER(PRESET); + + res = next_opt(opts, &opt_st); + switch (res) { + case FAILURE: goto failed_option; + case PROBLEM: res = SUCCESS; goto leave; + case SUCCESS: break; + } + + /* + * IF this is an immediate-attribute option, then do it. + */ + if (! DO_IMMEDIATELY(opt_st.flags)) + continue; + + if (! SUCCESSFUL(handle_opt(opts, &opt_st))) + break; + } failed_option:; + + if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) + (*opts->pUsageProc)(opts, EXIT_FAILURE); + + leave: + + opts->fOptSet &= ~OPTPROC_IMMEDIATE; + return res; +} + +/** + * check for preset values from a config files or envrionment variables + * + * @param[in,out] opts the structure with the option names to check + */ +static tSuccess +do_presets(tOptions * opts) +{ + tOptDesc * od = NULL; + + if (! SUCCESSFUL(immediate_opts(opts))) + return FAILURE; + + /* + * IF this option set has a --save-opts option, then it also + * has a --load-opts option. See if a command line option has disabled + * option presetting. + */ + if ( (opts->specOptIdx.save_opts != NO_EQUIVALENT) + && (opts->specOptIdx.save_opts != 0)) { + od = opts->pOptDesc + opts->specOptIdx.save_opts + 1; + if (DISABLED_OPT(od)) + return SUCCESS; + } + + /* + * Until we return from this procedure, disable non-presettable opts + */ + opts->fOptSet |= OPTPROC_PRESETTING; + /* + * IF there are no config files, + * THEN do any environment presets and leave. + */ + if (opts->papzHomeList == NULL) { + env_presets(opts, ENV_ALL); + } + else { + env_presets(opts, ENV_IMM); + + /* + * Check to see if environment variables have disabled presetting. + */ + if ((od != NULL) && ! DISABLED_OPT(od)) + intern_file_load(opts); + + /* + * ${PROGRAM_LOAD_OPTS} value of "no" cannot disable other environment + * variable options. Only the loading of .rc files. + */ + env_presets(opts, ENV_NON_IMM); + } + opts->fOptSet &= ~OPTPROC_PRESETTING; + + return SUCCESS; +} + +/** + * AutoOpts initialization + * + * @param[in,out] opts the structure to initialize + * @param[in] a_ct program argument count + * @param[in] a_v program argument vector + */ +static bool +ao_initialize(tOptions * opts, int a_ct, char ** a_v) +{ + if ((opts->fOptSet & OPTPROC_INITDONE) != 0) + return true; + + opts->origArgCt = (unsigned int)a_ct; + opts->origArgVect = a_v; + opts->fOptSet |= OPTPROC_INITDONE; + + if (HAS_pzPkgDataDir(opts)) + program_pkgdatadir = opts->pzPkgDataDir; + + if (! SUCCESSFUL(do_presets(opts))) + return false; + + /* + * IF option name conversion was suppressed but it is not suppressed + * for the command line, then it's time to translate option names. + * Usage text will not get retranslated. + */ + if ( ((opts->fOptSet & OPTPROC_TRANSLATE) != 0) + && (opts->pTransProc != NULL) + && ((opts->fOptSet & OPTPROC_NO_XLAT_MASK) == OPTPROC_NXLAT_OPT_CFG) + ) { + opts->fOptSet &= ~OPTPROC_NXLAT_OPT_CFG; + (*opts->pTransProc)(); + } + + if ((opts->fOptSet & OPTPROC_REORDER) != 0) + optionSort(opts); + + opts->curOptIdx = 1; + opts->pzCurOpt = NULL; + return true; +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/initialize.c */ diff --git a/src/libopts/intprops.h b/src/libopts/intprops.h new file mode 100644 index 0000000..af456ff --- /dev/null +++ b/src/libopts/intprops.h @@ -0,0 +1,453 @@ +/* intprops.h -- properties of integer types + + Copyright (C) 2001-2018 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +/* Written by Paul Eggert. */ + +#ifndef _GL_INTPROPS_H +#define _GL_INTPROPS_H + +#include + +/* Return a value with the common real type of E and V and the value of V. */ +#define _GL_INT_CONVERT(e, v) (0 * (e) + (v)) + +/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see + . */ +#define _GL_INT_NEGATE_CONVERT(e, v) (0 * (e) - (v)) + +/* The extra casts in the following macros work around compiler bugs, + e.g., in Cray C 5.0.3.0. */ + +/* True if the arithmetic type T is an integer type. bool counts as + an integer. */ +#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1) + +/* True if the real type T is signed. */ +#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) + +/* Return 1 if the real expression E, after promotion, has a + signed or floating type. */ +#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0) + + +/* Minimum and maximum values for integer types and expressions. */ + +/* The width in bits of the integer type or expression T. + Padding bits are not supported; this is checked at compile-time below. */ +#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT) + +/* The maximum and minimum values for the integer type T. */ +#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t)) +#define TYPE_MAXIMUM(t) \ + ((t) (! TYPE_SIGNED (t) \ + ? (t) -1 \ + : ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1))) + +/* The maximum and minimum values for the type of the expression E, + after integer promotion. E should not have side effects. */ +#define _GL_INT_MINIMUM(e) \ + (EXPR_SIGNED (e) \ + ? ~ _GL_SIGNED_INT_MAXIMUM (e) \ + : _GL_INT_CONVERT (e, 0)) +#define _GL_INT_MAXIMUM(e) \ + (EXPR_SIGNED (e) \ + ? _GL_SIGNED_INT_MAXIMUM (e) \ + : _GL_INT_NEGATE_CONVERT (e, 1)) +#define _GL_SIGNED_INT_MAXIMUM(e) \ + (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH ((e) + 0) - 2)) - 1) * 2 + 1) + +/* Work around OpenVMS incompatibility with C99. */ +#if !defined LLONG_MAX && defined __INT64_MAX +# define LLONG_MAX __INT64_MAX +# define LLONG_MIN __INT64_MIN +#endif + +/* This include file assumes that signed types are two's complement without + padding bits; the above macros have undefined behavior otherwise. + If this is a problem for you, please let us know how to fix it for your host. + This assumption is tested by the intprops-tests module. */ + +/* Does the __typeof__ keyword work? This could be done by + 'configure', but for now it's easier to do it by hand. */ +#if (2 <= __GNUC__ \ + || (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \ + || (0x5110 <= __SUNPRO_C && !__STDC__)) +# define _GL_HAVE___TYPEOF__ 1 +#else +# define _GL_HAVE___TYPEOF__ 0 +#endif + +/* Return 1 if the integer type or expression T might be signed. Return 0 + if it is definitely unsigned. This macro does not evaluate its argument, + and expands to an integer constant expression. */ +#if _GL_HAVE___TYPEOF__ +# define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t)) +#else +# define _GL_SIGNED_TYPE_OR_EXPR(t) 1 +#endif + +/* Bound on length of the string representing an unsigned integer + value representable in B bits. log10 (2.0) < 146/485. The + smallest value of B where this bound is not tight is 2621. */ +#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485) + +/* Bound on length of the string representing an integer type or expression T. + Subtract 1 for the sign bit if T is signed, and then add 1 more for + a minus sign if needed. + + Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 0 when its argument is + signed, this macro may overestimate the true bound by one byte when + applied to unsigned types of size 2, 4, 16, ... bytes. */ +#define INT_STRLEN_BOUND(t) \ + (INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - _GL_SIGNED_TYPE_OR_EXPR (t)) \ + + _GL_SIGNED_TYPE_OR_EXPR (t)) + +/* Bound on buffer size needed to represent an integer type or expression T, + including the terminating null. */ +#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) + + +/* Range overflow checks. + + The INT__RANGE_OVERFLOW macros return 1 if the corresponding C + operators might not yield numerically correct answers due to + arithmetic overflow. They do not rely on undefined or + implementation-defined behavior. Their implementations are simple + and straightforward, but they are a bit harder to use than the + INT__OVERFLOW macros described below. + + Example usage: + + long int i = ...; + long int j = ...; + if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX)) + printf ("multiply would overflow"); + else + printf ("product is %ld", i * j); + + Restrictions on *_RANGE_OVERFLOW macros: + + These macros do not check for all possible numerical problems or + undefined or unspecified behavior: they do not check for division + by zero, for bad shift counts, or for shifting negative numbers. + + These macros may evaluate their arguments zero or multiple times, + so the arguments should not have side effects. The arithmetic + arguments (including the MIN and MAX arguments) must be of the same + integer type after the usual arithmetic conversions, and the type + must have minimum value MIN and maximum MAX. Unsigned types should + use a zero MIN of the proper type. + + These macros are tuned for constant MIN and MAX. For commutative + operations such as A + B, they are also tuned for constant B. */ + +/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_ADD_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? (a) < (min) - (b) \ + : (max) - (b) < (a)) + +/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? (max) + (b) < (a) \ + : (a) < (min) + (b)) + +/* Return 1 if - A would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_NEGATE_RANGE_OVERFLOW(a, min, max) \ + ((min) < 0 \ + ? (a) < - (max) \ + : 0 < (a)) + +/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Avoid && and || as they tickle + bugs in Sun C 5.11 2010/08/13 and other compilers; see + . */ +#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? ((a) < 0 \ + ? (a) < (max) / (b) \ + : (b) == -1 \ + ? 0 \ + : (min) / (b) < (a)) \ + : (b) == 0 \ + ? 0 \ + : ((a) < 0 \ + ? (a) < (min) / (b) \ + : (max) / (b) < (a))) + +/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Do not check for division by zero. */ +#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max) \ + ((min) < 0 && (b) == -1 && (a) < - (max)) + +/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Do not check for division by zero. + Mathematically, % should never overflow, but on x86-like hosts + INT_MIN % -1 traps, and the C standard permits this, so treat this + as an overflow too. */ +#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max) \ + INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max) + +/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Here, MIN and MAX are for A only, and B need + not be of the same type as the other arguments. The C standard says that + behavior is undefined for shifts unless 0 <= B < wordwidth, and that when + A is negative then A << B has undefined behavior and A >> B has + implementation-defined behavior, but do not check these other + restrictions. */ +#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max) \ + ((a) < 0 \ + ? (a) < (min) >> (b) \ + : (max) >> (b) < (a)) + +/* True if __builtin_add_overflow (A, B, P) works when P is non-null. */ +#if 5 <= __GNUC__ && !defined __ICC +# define _GL_HAS_BUILTIN_OVERFLOW 1 +#else +# define _GL_HAS_BUILTIN_OVERFLOW 0 +#endif + +/* True if __builtin_add_overflow_p (A, B, C) works. */ +#define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__) + +/* The _GL*_OVERFLOW macros have the same restrictions as the + *_RANGE_OVERFLOW macros, except that they do not assume that operands + (e.g., A and B) have the same type as MIN and MAX. Instead, they assume + that the result (e.g., A + B) has that type. */ +#if _GL_HAS_BUILTIN_OVERFLOW_P +# define _GL_ADD_OVERFLOW(a, b, min, max) \ + __builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0) +# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ + __builtin_sub_overflow_p (a, b, (__typeof__ ((a) - (b))) 0) +# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ + __builtin_mul_overflow_p (a, b, (__typeof__ ((a) * (b))) 0) +#else +# define _GL_ADD_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \ + : (a) < 0 ? (b) <= (a) + (b) \ + : (b) < 0 ? (a) <= (a) + (b) \ + : (a) + (b) < (b)) +# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \ + : (a) < 0 ? 1 \ + : (b) < 0 ? (a) - (b) <= (a) \ + : (a) < (b)) +# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ + (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \ + || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max)) +#endif +#define _GL_DIVIDE_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ + : (a) < 0 ? (b) <= (a) + (b) - 1 \ + : (b) < 0 && (a) + (b) <= (a)) +#define _GL_REMAINDER_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ + : (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b) \ + : (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max)) + +/* Return a nonzero value if A is a mathematical multiple of B, where + A is unsigned, B is negative, and MAX is the maximum value of A's + type. A's type must be the same as (A % B)'s type. Normally (A % + -B == 0) suffices, but things get tricky if -B would overflow. */ +#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max) \ + (((b) < -_GL_SIGNED_INT_MAXIMUM (b) \ + ? (_GL_SIGNED_INT_MAXIMUM (b) == (max) \ + ? (a) \ + : (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1)) \ + : (a) % - (b)) \ + == 0) + +/* Check for integer overflow, and report low order bits of answer. + + The INT__OVERFLOW macros return 1 if the corresponding C operators + might not yield numerically correct answers due to arithmetic overflow. + The INT__WRAPV macros also store the low-order bits of the answer. + These macros work correctly on all known practical hosts, and do not rely + on undefined behavior due to signed arithmetic overflow. + + Example usage, assuming A and B are long int: + + if (INT_MULTIPLY_OVERFLOW (a, b)) + printf ("result would overflow\n"); + else + printf ("result is %ld (no overflow)\n", a * b); + + Example usage with WRAPV flavor: + + long int result; + bool overflow = INT_MULTIPLY_WRAPV (a, b, &result); + printf ("result is %ld (%s)\n", result, + overflow ? "after overflow" : "no overflow"); + + Restrictions on these macros: + + These macros do not check for all possible numerical problems or + undefined or unspecified behavior: they do not check for division + by zero, for bad shift counts, or for shifting negative numbers. + + These macros may evaluate their arguments zero or multiple times, so the + arguments should not have side effects. + + The WRAPV macros are not constant expressions. They support only + +, binary -, and *. The result type must be signed. + + These macros are tuned for their last argument being a constant. + + Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B, + A % B, and A << B would overflow, respectively. */ + +#define INT_ADD_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW) +#define INT_SUBTRACT_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW) +#if _GL_HAS_BUILTIN_OVERFLOW_P +# define INT_NEGATE_OVERFLOW(a) INT_SUBTRACT_OVERFLOW (0, a) +#else +# define INT_NEGATE_OVERFLOW(a) \ + INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) +#endif +#define INT_MULTIPLY_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW) +#define INT_DIVIDE_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW) +#define INT_REMAINDER_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW) +#define INT_LEFT_SHIFT_OVERFLOW(a, b) \ + INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \ + _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) + +/* Return 1 if the expression A B would overflow, + where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test, + assuming MIN and MAX are the minimum and maximum for the result type. + Arguments should be free of side effects. */ +#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \ + op_result_overflow (a, b, \ + _GL_INT_MINIMUM (0 * (b) + (a)), \ + _GL_INT_MAXIMUM (0 * (b) + (a))) + +/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R. + Return 1 if the result overflows. See above for restrictions. */ +#define INT_ADD_WRAPV(a, b, r) \ + _GL_INT_OP_WRAPV (a, b, r, +, __builtin_add_overflow, INT_ADD_OVERFLOW) +#define INT_SUBTRACT_WRAPV(a, b, r) \ + _GL_INT_OP_WRAPV (a, b, r, -, __builtin_sub_overflow, INT_SUBTRACT_OVERFLOW) +#define INT_MULTIPLY_WRAPV(a, b, r) \ + _GL_INT_OP_WRAPV (a, b, r, *, __builtin_mul_overflow, INT_MULTIPLY_OVERFLOW) + +/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390. See: + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193 + https://llvm.org/bugs/show_bug.cgi?id=25390 + For now, assume all versions of GCC-like compilers generate bogus + warnings for _Generic. This matters only for older compilers that + lack __builtin_add_overflow. */ +#if __GNUC__ +# define _GL__GENERIC_BOGUS 1 +#else +# define _GL__GENERIC_BOGUS 0 +#endif + +/* Store the low-order bits of A B into *R, where OP specifies + the operation. BUILTIN is the builtin operation, and OVERFLOW the + overflow predicate. Return 1 if the result overflows. See above + for restrictions. */ +#if _GL_HAS_BUILTIN_OVERFLOW +# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) builtin (a, b, r) +#elif 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS +# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \ + (_Generic \ + (*(r), \ + signed char: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + signed char, SCHAR_MIN, SCHAR_MAX), \ + short int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + short int, SHRT_MIN, SHRT_MAX), \ + int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + int, INT_MIN, INT_MAX), \ + long int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ + long int, LONG_MIN, LONG_MAX), \ + long long int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ + long long int, LLONG_MIN, LLONG_MAX))) +#else +# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \ + (sizeof *(r) == sizeof (signed char) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + signed char, SCHAR_MIN, SCHAR_MAX) \ + : sizeof *(r) == sizeof (short int) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + short int, SHRT_MIN, SHRT_MAX) \ + : sizeof *(r) == sizeof (int) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + int, INT_MIN, INT_MAX) \ + : _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow)) +# ifdef LLONG_MAX +# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \ + (sizeof *(r) == sizeof (long int) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ + long int, LONG_MIN, LONG_MAX) \ + : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ + long long int, LLONG_MIN, LLONG_MAX)) +# else +# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ + long int, LONG_MIN, LONG_MAX) +# endif +#endif + +/* Store the low-order bits of A B into *R, where the operation + is given by OP. Use the unsigned type UT for calculation to avoid + overflow problems. *R's type is T, with extrema TMIN and TMAX. + T must be a signed integer type. Return 1 if the result overflows. */ +#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \ + (sizeof ((a) op (b)) < sizeof (t) \ + ? _GL_INT_OP_CALC1 ((t) (a), (t) (b), r, op, overflow, ut, t, tmin, tmax) \ + : _GL_INT_OP_CALC1 (a, b, r, op, overflow, ut, t, tmin, tmax)) +#define _GL_INT_OP_CALC1(a, b, r, op, overflow, ut, t, tmin, tmax) \ + ((overflow (a, b) \ + || (EXPR_SIGNED ((a) op (b)) && ((a) op (b)) < (tmin)) \ + || (tmax) < ((a) op (b))) \ + ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \ + : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0)) + +/* Return the low-order bits of A B, where the operation is given + by OP. Use the unsigned type UT for calculation to avoid undefined + behavior on signed integer overflow, and convert the result to type T. + UT is at least as wide as T and is no narrower than unsigned int, + T is two's complement, and there is no padding or trap representations. + Assume that converting UT to T yields the low-order bits, as is + done in all known two's-complement C compilers. E.g., see: + https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html + + According to the C standard, converting UT to T yields an + implementation-defined result or signal for values outside T's + range. However, code that works around this theoretical problem + runs afoul of a compiler bug in Oracle Studio 12.3 x86. See: + https://lists.gnu.org/r/bug-gnulib/2017-04/msg00049.html + As the compiler bug is real, don't try to work around the + theoretical problem. */ + +#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \ + ((t) ((ut) (a) op (ut) (b))) + +#endif /* _GL_INTPROPS_H */ diff --git a/src/libopts/libopts.c b/src/libopts/libopts.c new file mode 100644 index 0000000..457edc4 --- /dev/null +++ b/src/libopts/libopts.c @@ -0,0 +1,50 @@ +#define AUTOOPTS_INTERNAL 1 +#include "autoopts/project.h" + +#include "ao-strs.h" +static char const ao_ver_string[] = + "42:1:17\n"; +#include "autoopts/options.h" +#include "autoopts/usage-txt.h" +#include "genshell.h" +#include "option-xat-attribute.h" +#include "option-value-type.h" +#include "ao-strs.h" +#include "ag-char-map.h" +#include "save-flags.h" +#include "autoopts.h" +#include "proto.h" +#include "parse-duration.c" +#include "ao-strs.c" +#include "option-value-type.c" +#include "option-xat-attribute.c" +#include "save-flags.c" +#include "autoopts.c" +#include "alias.c" +#include "boolean.c" +#include "check.c" +#include "configfile.c" +#include "cook.c" +#include "enum.c" +#include "env.c" +#include "file.c" +#include "find.c" +#include "genshell.c" +#include "load.c" +#include "makeshell.c" +#include "nested.c" +#include "numeric.c" +#include "pgusage.c" +#include "putshell.c" +#include "reset.c" +#include "restore.c" +#include "save.c" +#include "sort.c" +#include "stack.c" +#include "streqvcmp.c" +#include "text_mmap.c" +#include "time.c" +#include "tokenize.c" +#include "usage.c" +#include "version.c" +#include "init.c" diff --git a/src/libopts/load.c b/src/libopts/load.c new file mode 100644 index 0000000..59d124e --- /dev/null +++ b/src/libopts/load.c @@ -0,0 +1,578 @@ + +/** + * \file load.c + * + * This file contains the routines that deal with processing text strings + * for options, either from a NUL-terminated string passed in or from an + * rc/ini file. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +static bool +get_realpath(char * buf, size_t b_sz) +{ +#if defined(HAVE_CANONICALIZE_FILE_NAME) + { + size_t name_len; + + char * pz = canonicalize_file_name(buf); + if (pz == NULL) + return false; + + name_len = strlen(pz); + if (name_len >= (size_t)b_sz) { + free(pz); + return false; + } + + memcpy(buf, pz, name_len + 1); + free(pz); + } + +#elif defined(HAVE_REALPATH) + { + size_t name_len; + char z[PATH_MAX+1]; + + if (realpath(buf, z) == NULL) + return false; + + name_len = strlen(z); + if (name_len >= b_sz) + return false; + + memcpy(buf, z, name_len + 1); + } +#endif + return true; +} + +/*=export_func optionMakePath + * private: + * + * what: translate and construct a path + * arg: + char * + p_buf + The result buffer + + * arg: + int + b_sz + The size of this buffer + + * arg: + char const * + fname + The input name + + * arg: + char const * + prg_path + The full path of the current program + + * + * ret-type: bool + * ret-desc: true if the name was handled, otherwise false. + * If the name does not start with ``$'', then it is handled + * simply by copying the input name to the output buffer and + * resolving the name with either + * @code{canonicalize_file_name(3GLIBC)} or @code{realpath(3C)}. + * + * doc: + * + * This routine will copy the @code{pzName} input name into the + * @code{pzBuf} output buffer, not exceeding @code{bufSize} bytes. If the + * first character of the input name is a @code{'$'} character, then there + * is special handling: + * @* + * @code{$$} is replaced with the directory name of the @code{pzProgPath}, + * searching @code{$PATH} if necessary. + * @* + * @code{$@} is replaced with the AutoGen package data installation directory + * (aka @code{pkgdatadir}). + * @* + * @code{$NAME} is replaced by the contents of the @code{NAME} environment + * variable. If not found, the search fails. + * + * Please note: both @code{$$} and @code{$NAME} must be at the start of the + * @code{pzName} string and must either be the entire string or be followed + * by the @code{'/'} (backslash on windows) character. + * + * err: @code{false} is returned if: + * @* + * @bullet{} The input name exceeds @code{bufSize} bytes. + * @* + * @bullet{} @code{$$}, @code{$@@} or @code{$NAME} is not the full string + * and the next character is not '/'. + * @* + * @bullet{} libopts was built without PKGDATADIR defined and @code{$@@} + * was specified. + * @* + * @bullet{} @code{NAME} is not a known environment variable + * @* + * @bullet{} @code{canonicalize_file_name} or @code{realpath} return + * errors (cannot resolve the resulting path). +=*/ +bool +optionMakePath(char * p_buf, int b_sz, char const * fname, char const * prg_path) +{ + { + size_t len = strlen(fname); + + if (((size_t)b_sz <= len) || (len == 0)) + return false; + } + + /* + * IF not an environment variable, just copy the data + */ + if (*fname != '$') { + char const * src = fname; + char * dst = p_buf; + int ct = b_sz; + + for (;;) { + if ( (*(dst++) = *(src++)) == NUL) + break; + if (--ct <= 0) + return false; + } + } + + /* + * IF the name starts with "$$", then it must be "$$" or + * it must start with "$$/". In either event, replace the "$$" + * with the path to the executable and append a "/" character. + */ + else switch (fname[1]) { + case NUL: + return false; + + case '$': + if (! add_prog_path(p_buf, b_sz, fname, prg_path)) + return false; + break; + + case '@': + if (program_pkgdatadir[0] == NUL) + return false; + + if (snprintf(p_buf, (size_t)b_sz, "%s%s", + program_pkgdatadir, fname + 2) >= b_sz) + return false; + break; + + default: + if (! add_env_val(p_buf, b_sz, fname)) + return false; + } + + return get_realpath(p_buf, b_sz); +} + +/** + * convert a leading "$$" into a path to the executable. + */ +static bool +add_prog_path(char * buf, int b_sz, char const * fname, char const * prg_path) +{ + char const * path; + char const * pz; + int skip = 2; + size_t fname_len; + size_t dir_len; //!< length of the directory portion of the path to the exe + + switch (fname[2]) { + case DIRCH: + skip = 3; + case NUL: + break; + default: + return false; + } + + /* + * See if the path is included in the program name. + * If it is, we're done. Otherwise, we have to hunt + * for the program using "pathfind". + */ + if (strchr(prg_path, DIRCH) != NULL) + path = prg_path; + else { + path = pathfind(getenv("PATH"), (char *)prg_path, "rx"); + + if (path == NULL) + return false; + } + + pz = strrchr(path, DIRCH); + + /* + * IF we cannot find a directory name separator, + * THEN we do not have a path name to our executable file. + */ + if (pz == NULL) + return false; + + fname += skip; + fname_len = strlen(fname) + 1; // + NUL byte + dir_len = (pz - path) + 1; // + dir sep character + + /* + * Concatenate the file name to the end of the executable path. + * The result may be either a file or a directory. + */ + if (dir_len + fname_len > (unsigned)b_sz) + return false; + + memcpy(buf, path, dir_len); + memcpy(buf + dir_len, fname, fname_len); + + /* + * If the "path" path was gotten from "pathfind()", then it was + * allocated and we need to deallocate it. + */ + if (path != prg_path) + AGFREE(path); + return true; +} + +/** + * Add an environment variable value. + */ +static bool +add_env_val(char * buf, int buf_sz, char const * name) +{ + char * dir_part = buf; + + for (;;) { + int ch = (int)*++name; + if (! IS_VALUE_NAME_CHAR(ch)) + break; + *(dir_part++) = (char)ch; + } + + if (dir_part == buf) + return false; + + *dir_part = NUL; + + dir_part = getenv(buf); + + /* + * Environment value not found -- skip the home list entry + */ + if (dir_part == NULL) + return false; + + { + size_t dir_len = strlen(dir_part); + size_t nm_len = strlen(name) + 1; + + if (dir_len + nm_len >= (unsigned)buf_sz) + return false; + memcpy(buf, dir_part, dir_len); + memcpy(buf + dir_len, name, nm_len); + } + + return true; +} + +/** + * Trim leading and trailing white space. + * If we are cooking the text and the text is quoted, then "cook" + * the string. To cook, the string must be quoted. + * + * @param[in,out] txt the input and output string + * @param[in] mode the handling mode (cooking method) + */ +static void +munge_str(char * txt, tOptionLoadMode mode) +{ + char * end; + + if (mode == OPTION_LOAD_KEEP) + return; + + if (IS_WHITESPACE_CHAR(*txt)) { + char * src = SPN_WHITESPACE_CHARS(txt+1); + size_t l = strlen(src) + 1; + memmove(txt, src, l); + end = txt + l - 1; + + } else + end = txt + strlen(txt); + + end = SPN_WHITESPACE_BACK(txt, end); + *end = NUL; + + if (mode == OPTION_LOAD_UNCOOKED) + return; + + switch (*txt) { + default: return; + case '"': + case '\'': break; + } + + switch (end[-1]) { + default: return; + case '"': + case '\'': break; + } + + (void)ao_string_cook(txt, NULL); +} + +static char * +assemble_arg_val(char * txt, tOptionLoadMode mode) +{ + char * end = strpbrk(txt, ARG_BREAK_STR); + int space_break; + + /* + * Not having an argument to a configurable name is okay. + */ + if (end == NULL) + return txt + strlen(txt); + + /* + * If we are keeping all whitespace, then the modevalue starts with the + * character that follows the end of the configurable name, regardless + * of which character caused it. + */ + if (mode == OPTION_LOAD_KEEP) { + *(end++) = NUL; + return end; + } + + /* + * If the name ended on a white space character, remember that + * because we'll have to skip over an immediately following ':' or '=' + * (and the white space following *that*). + */ + space_break = IS_WHITESPACE_CHAR(*end); + *(end++) = NUL; + + end = SPN_WHITESPACE_CHARS(end); + if (space_break && ((*end == ':') || (*end == '='))) + end = SPN_WHITESPACE_CHARS(end+1); + + return end; +} + +static char * +trim_quotes(char * arg) +{ + switch (*arg) { + case '"': + case '\'': + ao_string_cook(arg, NULL); + } + return arg; +} + +/** + * See if the option is to be processed in the current scan direction + * (-1 or +1). + */ +static bool +direction_ok(opt_state_mask_t f, int dir) +{ + if (dir == 0) + return true; + + switch (f & (OPTST_IMM|OPTST_DISABLE_IMM)) { + case 0: + /* + * The selected option has no immediate action. + * THEREFORE, if the direction is PRESETTING + * THEN we skip this option. + */ + if (PRESETTING(dir)) + return false; + break; + + case OPTST_IMM: + if (PRESETTING(dir)) { + /* + * We are in the presetting direction with an option we handle + * immediately for enablement, but normally for disablement. + * Therefore, skip if disabled. + */ + if ((f & OPTST_DISABLED) == 0) + return false; + } else { + /* + * We are in the processing direction with an option we handle + * immediately for enablement, but normally for disablement. + * Therefore, skip if NOT disabled. + */ + if ((f & OPTST_DISABLED) != 0) + return false; + } + break; + + case OPTST_DISABLE_IMM: + if (PRESETTING(dir)) { + /* + * We are in the presetting direction with an option we handle + * immediately for disablement, but normally for handling. + * Therefore, skip if NOT disabled. + */ + if ((f & OPTST_DISABLED) != 0) + return false; + } else { + /* + * We are in the processing direction with an option we handle + * immediately for disablement, but normally for handling. + * Therefore, skip if disabled. + */ + if ((f & OPTST_DISABLED) == 0) + return false; + } + break; + + case OPTST_IMM|OPTST_DISABLE_IMM: + /* + * The selected option is always for immediate action. + * THEREFORE, if the direction is PROCESSING + * THEN we skip this option. + */ + if (PROCESSING(dir)) + return false; + break; + } + return true; +} + +/** + * Load an option from a block of text. The text must start with the + * configurable/option name and be followed by its associated value. + * That value may be processed in any of several ways. See "tOptionLoadMode" + * in autoopts.h. + * + * @param[in,out] opts program options descriptor + * @param[in,out] opt_state option processing state + * @param[in,out] line source line with long option name in it + * @param[in] direction current processing direction (preset or not) + * @param[in] load_mode option loading mode (OPTION_LOAD_*) + */ +static void +load_opt_line(tOptions * opts, tOptState * opt_state, char * line, + tDirection direction, tOptionLoadMode load_mode ) +{ + /* + * When parsing a stored line, we only look at the characters after + * a hyphen. Long names must always be at least two characters and + * short options are always exactly one character long. + */ + line = SPN_LOAD_LINE_SKIP_CHARS(line); + + { + char * arg = assemble_arg_val(line, load_mode); + + if (IS_OPTION_NAME_CHAR(line[1])) { + + if (! SUCCESSFUL(opt_find_long(opts, line, opt_state))) + return; + + } else if (! SUCCESSFUL(opt_find_short(opts, *line, opt_state))) + return; + + if ((! CALLED(direction)) && (opt_state->flags & OPTST_NO_INIT)) + return; + + opt_state->pzOptArg = trim_quotes(arg); + } + + if (! direction_ok(opt_state->flags, direction)) + return; + + /* + * Fix up the args. + */ + if (OPTST_GET_ARGTYPE(opt_state->pOD->fOptState) == OPARG_TYPE_NONE) { + if (*opt_state->pzOptArg != NUL) + return; + opt_state->pzOptArg = NULL; + + } else if (opt_state->pOD->fOptState & OPTST_ARG_OPTIONAL) { + if (*opt_state->pzOptArg == NUL) + opt_state->pzOptArg = NULL; + else { + AGDUPSTR(opt_state->pzOptArg, opt_state->pzOptArg, "opt arg"); + opt_state->flags |= OPTST_ALLOC_ARG; + } + + } else { + if (*opt_state->pzOptArg == NUL) + opt_state->pzOptArg = zNil; + else { + AGDUPSTR(opt_state->pzOptArg, opt_state->pzOptArg, "opt arg"); + opt_state->flags |= OPTST_ALLOC_ARG; + } + } + + { + tOptionLoadMode sv = option_load_mode; + option_load_mode = load_mode; + handle_opt(opts, opt_state); + option_load_mode = sv; + } +} + +/*=export_func optionLoadLine + * + * what: process a string for an option name and value + * + * arg: tOptions *, opts, program options descriptor + * arg: char const *, line, NUL-terminated text + * + * doc: + * + * This is a client program callable routine for setting options from, for + * example, the contents of a file that they read in. Only one option may + * appear in the text. It will be treated as a normal (non-preset) option. + * + * When passed a pointer to the option struct and a string, it will find + * the option named by the first token on the string and set the option + * argument to the remainder of the string. The caller must NUL terminate + * the string. The caller need not skip over any introductory hyphens. + * Any embedded new lines will be included in the option + * argument. If the input looks like one or more quoted strings, then the + * input will be "cooked". The "cooking" is identical to the string + * formation used in AutoGen definition files (@pxref{basic expression}), + * except that you may not use backquotes. + * + * err: Invalid options are silently ignored. Invalid option arguments + * will cause a warning to print, but the function should return. +=*/ +void +optionLoadLine(tOptions * opts, char const * line) +{ + tOptState st = OPTSTATE_INITIALIZER(SET); + char * pz; + proc_state_mask_t sv_flags = opts->fOptSet; + opts->fOptSet &= ~OPTPROC_ERRSTOP; + AGDUPSTR(pz, line, "opt line"); + load_opt_line(opts, &st, pz, DIRECTION_CALLED, OPTION_LOAD_COOKED); + AGFREE(pz); + opts->fOptSet = sv_flags; +} +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/load.c */ diff --git a/src/libopts/makeshell.c b/src/libopts/makeshell.c new file mode 100644 index 0000000..10ed120 --- /dev/null +++ b/src/libopts/makeshell.c @@ -0,0 +1,918 @@ + +/** + * \file makeshell.c + * + * This module will interpret the options set in the tOptions + * structure and create a Bourne shell script capable of parsing them. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + + static inline unsigned char to_uchar (char ch) { return ch; } + +#define UPPER(_c) (toupper(to_uchar(_c))) +#define LOWER(_c) (tolower(to_uchar(_c))) + +noreturn static void +option_exits(int exit_code) +{ + if (print_exit) + printf("\nexit %d\n", exit_code); + exit(exit_code); +} + +noreturn static void +ao_bug(char const * msg) +{ + fprintf(stderr, zao_bug_msg, msg); + option_exits(EX_SOFTWARE); +} + +static void +fserr_warn(char const * prog, char const * op, char const * fname) +{ + fprintf(stderr, zfserr_fmt, prog, errno, strerror(errno), + op, fname); +} + +noreturn static void +fserr_exit(char const * prog, char const * op, char const * fname) +{ + fserr_warn(prog, op, fname); + option_exits(EXIT_FAILURE); +} + +/*=export_func optionParseShell + * private: + * + * what: Decipher a boolean value + * arg: + tOptions * + pOpts + program options descriptor + + * + * doc: + * Emit a shell script that will parse the command line options. +=*/ +void +optionParseShell(tOptions * opts) +{ + /* + * Check for our SHELL option now. + * IF the output file contains the "#!" magic marker, + * it will override anything we do here. + */ + if (HAVE_GENSHELL_OPT(SHELL)) + shell_prog = GENSHELL_OPT_ARG(SHELL); + + else if (! ENABLED_GENSHELL_OPT(SHELL)) + shell_prog = NULL; + + else if ((shell_prog = getenv("SHELL")), + shell_prog == NULL) + + shell_prog = POSIX_SHELL; + + /* + * Check for a specified output file + */ + if (HAVE_GENSHELL_OPT(SCRIPT)) + open_out(GENSHELL_OPT_ARG(SCRIPT), opts->pzProgName); + + emit_usage(opts); + emit_setup(opts); + + /* + * There are four modes of option processing. + */ + switch (opts->fOptSet & (OPTPROC_LONGOPT|OPTPROC_SHORTOPT)) { + case OPTPROC_LONGOPT: + fputs(LOOP_STR, stdout); + + fputs(LONG_OPT_MARK, stdout); + fputs(INIT_LOPT_STR, stdout); + emit_long(opts); + printf(LOPT_ARG_FMT, opts->pzPROGNAME); + fputs(END_OPT_SEL_STR, stdout); + + fputs(NOT_FOUND_STR, stdout); + break; + + case 0: + fputs(ONLY_OPTS_LOOP, stdout); + fputs(INIT_LOPT_STR, stdout); + emit_long(opts); + printf(LOPT_ARG_FMT, opts->pzPROGNAME); + break; + + case OPTPROC_SHORTOPT: + fputs(LOOP_STR, stdout); + + fputs(FLAG_OPT_MARK, stdout); + fputs(INIT_OPT_STR, stdout); + emit_flag(opts); + printf(OPT_ARG_FMT, opts->pzPROGNAME); + fputs(END_OPT_SEL_STR, stdout); + + fputs(NOT_FOUND_STR, stdout); + break; + + case OPTPROC_LONGOPT|OPTPROC_SHORTOPT: + fputs(LOOP_STR, stdout); + + fputs(LONG_OPT_MARK, stdout); + fputs(INIT_LOPT_STR, stdout); + emit_long(opts); + printf(LOPT_ARG_FMT, opts->pzPROGNAME); + fputs(END_OPT_SEL_STR, stdout); + + fputs(FLAG_OPT_MARK, stdout); + fputs(INIT_OPT_STR, stdout); + emit_flag(opts); + printf(OPT_ARG_FMT, opts->pzPROGNAME); + fputs(END_OPT_SEL_STR, stdout); + + fputs(NOT_FOUND_STR, stdout); + break; + } + + emit_wrapup(opts); + if ((script_trailer != NULL) && (*script_trailer != NUL)) + fputs(script_trailer, stdout); + else if (ENABLED_GENSHELL_OPT(SHELL)) + printf(SHOW_PROG_ENV, opts->pzPROGNAME); + +#ifdef HAVE_FCHMOD + fchmod(STDOUT_FILENO, 0755); +#endif + fclose(stdout); + + if (ferror(stdout)) + fserr_exit(opts->pzProgName, zwriting, zstdout_name); + + AGFREE(script_text); + script_leader = NULL; + script_trailer = NULL; + script_text = NULL; +} + +#ifdef HAVE_WORKING_FORK +/** + * Print the value of "var" to a file descriptor. + * The "fdin" is the read end of a pipe to a forked process that + * is writing usage text to it. We read that text in and re-emit + * to standard out, formatting it so that it is assigned to a + * shell variable. + * + * @param[in] prog The capitalized, c-variable-formatted program name + * @param[in] var a similarly formatted type name + * (LONGUSAGE, USAGE or VERSION) + * @param[in] fdin the input end of a pipe + */ +static void +emit_var_text(char const * prog, char const * var, int fdin) +{ + FILE * fp = fdopen(fdin, "r" FOPEN_BINARY_FLAG); + int nlct = 0; /* defer newlines and skip trailing ones */ + + printf(SET_TEXT_FMT, prog, var); + if (fp == NULL) + goto skip_text; + + for (;;) { + int ch = fgetc(fp); + switch (ch) { + + case NL: + nlct++; + break; + + case '\'': + while (nlct > 0) { + fputc(NL, stdout); + nlct--; + } + fputs(apostrophe, stdout); + break; + + case EOF: + goto done; + + default: + while (nlct > 0) { + fputc(NL, stdout); + nlct--; + } + fputc(ch, stdout); + break; + } + } done:; + + fclose(fp); + + skip_text: + + fputs(END_SET_TEXT, stdout); +} +#endif + +/** + * The purpose of this function is to assign "long usage", short usage + * and version information to a shell variable. Rather than wind our + * way through all the logic necessary to emit the text directly, we + * fork(), have our child process emit the text the normal way and + * capture the output in the parent process. + * + * @param[in] opts the program options + * @param[in] which what to print: long usage, usage or version + * @param[in] od for TT_VERSION, it is the version option + */ +static void +text_to_var(tOptions * opts, teTextTo which, tOptDesc * od) +{ +# define _TT_(n) static char const z ## n [] = #n; + TEXTTO_TABLE +# undef _TT_ +# define _TT_(n) z ## n , + static char const * ttnames[] = { TEXTTO_TABLE }; +# undef _TT_ + +#if ! defined(HAVE_WORKING_FORK) + printf(SET_NO_TEXT_FMT, opts->pzPROGNAME, ttnames[which]); +#else + int fdpair[2]; + + fflush(stdout); + fflush(stderr); + + if (pipe(fdpair) != 0) + fserr_exit(opts->pzProgName, "pipe", zinter_proc_pipe); + + switch (fork()) { + case -1: + fserr_exit(opts->pzProgName, "fork", opts->pzProgName); + /* NOTREACHED */ + + case 0: + /* + * Send both stderr and stdout to the pipe. No matter which + * descriptor is used, we capture the output on the read end. + */ + dup2(fdpair[1], STDERR_FILENO); + dup2(fdpair[1], STDOUT_FILENO); + close(fdpair[0]); + + switch (which) { + case TT_LONGUSAGE: + (*(opts->pUsageProc))(opts, EXIT_SUCCESS); + /* FALLTHROUGH */ /* NOTREACHED */ + + case TT_USAGE: + (*(opts->pUsageProc))(opts, EXIT_FAILURE); + /* FALLTHROUGH */ /* NOTREACHED */ + + case TT_VERSION: + if (od->fOptState & OPTST_ALLOC_ARG) { + AGFREE(od->optArg.argString); + od->fOptState &= ~OPTST_ALLOC_ARG; + } + od->optArg.argString = "c"; + optionPrintVersion(opts, od); + /* FALLTHROUGH */ /* NOTREACHED */ + + default: + option_exits(EXIT_FAILURE); + /* FALLTHROUGH */ /* NOTREACHED */ + } + /* FALLTHROUGH */ /* NOTREACHED */ + + default: + close(fdpair[1]); + } + + emit_var_text(opts->pzPROGNAME, ttnames[which], fdpair[0]); +#endif +} + +/** + * capture usage text in shell variables. + * + */ +static void +emit_usage(tOptions * opts) +{ + char tm_nm_buf[AO_NAME_SIZE]; + + /* + * First, switch stdout to the output file name. + * Then, change the program name to the one defined + * by the definitions (rather than the current + * executable name). Down case the upper cased name. + */ + if (script_leader != NULL) + fputs(script_leader, stdout); + + { + char const * out_nm; + + { + time_t c_tim = time(NULL); + struct tm * ptm = localtime(&c_tim); + strftime(tm_nm_buf, AO_NAME_SIZE, TIME_FMT, ptm ); + } + + if (HAVE_GENSHELL_OPT(SCRIPT)) + out_nm = GENSHELL_OPT_ARG(SCRIPT); + else out_nm = STDOUT; + + if ((script_leader == NULL) && (shell_prog != NULL)) + printf(SHELL_MAGIC, shell_prog); + + printf(PREAMBLE_FMT, START_MARK, out_nm, tm_nm_buf); + } + + printf(END_PRE_FMT, opts->pzPROGNAME); + + /* + * Get a copy of the original program name in lower case and + * fill in an approximation of the program name from it. + */ + { + char * pzPN = tm_nm_buf; + char const * pz = opts->pzPROGNAME; + char ** pp; + + /* Copy the program name into the time/name buffer */ + for (;;) { + if ((*pzPN++ = (char)tolower(*pz++)) == NUL) + break; + } + + pp = VOIDP(&(opts->pzProgPath)); + *pp = tm_nm_buf; + pp = VOIDP(&(opts->pzProgName)); + *pp = tm_nm_buf; + } + + text_to_var(opts, TT_LONGUSAGE, NULL); + text_to_var(opts, TT_USAGE, NULL); + + { + tOptDesc * pOptDesc = opts->pOptDesc; + int optionCt = opts->optCt; + + for (;;) { + if (pOptDesc->pOptProc == optionPrintVersion) { + text_to_var(opts, TT_VERSION, pOptDesc); + break; + } + + if (--optionCt <= 0) + break; + pOptDesc++; + } + } +} + +static void +emit_wrapup(tOptions * opts) +{ + tOptDesc * od = opts->pOptDesc; + int opt_ct = opts->presetOptCt; + char const * fmt; + + printf(FINISH_LOOP, opts->pzPROGNAME); + for (;opt_ct > 0; od++, --opt_ct) { + /* + * Options that are either usage documentation or are compiled out + * are not to be processed. + */ + if (SKIP_OPT(od) || (od->pz_NAME == NULL)) + continue; + + /* + * do not presence check if there is no minimum/must-set + */ + if ((od->optMinCt == 0) && ((od->fOptState & OPTST_MUST_SET) == 0)) + continue; + + if (od->optMaxCt > 1) + fmt = CHK_MIN_COUNT; + else fmt = CHK_ONE_REQUIRED; + + { + int min = (od->optMinCt == 0) ? 1 : od->optMinCt; + printf(fmt, opts->pzPROGNAME, od->pz_NAME, min); + } + } + fputs(END_MARK, stdout); +} + +static void +emit_setup(tOptions * opts) +{ + tOptDesc * od = opts->pOptDesc; + int opt_ct = opts->presetOptCt; + char const * fmt; + char const * def_val; + + for (;opt_ct > 0; od++, --opt_ct) { + char int_val_buf[32]; + + /* + * Options that are either usage documentation or are compiled out + * are not to be processed. + */ + if (SKIP_OPT(od) || (od->pz_NAME == NULL)) + continue; + + if (od->optMaxCt > 1) + fmt = MULTI_DEF_FMT; + else fmt = SGL_DEF_FMT; + + /* + * IF this is an enumeration/bitmask option, then convert the value + * to a string before printing the default value. + */ + switch (OPTST_GET_ARGTYPE(od->fOptState)) { + case OPARG_TYPE_ENUMERATION: + (*(od->pOptProc))(OPTPROC_EMIT_SHELL, od ); + def_val = od->optArg.argString; + break; + + /* + * Numeric and membership bit options are just printed as a number. + */ + case OPARG_TYPE_NUMERIC: + snprintf(int_val_buf, sizeof(int_val_buf), "%d", + (int)od->optArg.argInt); + def_val = int_val_buf; + break; + + case OPARG_TYPE_MEMBERSHIP: + snprintf(int_val_buf, sizeof(int_val_buf), "%lu", + (unsigned long)od->optArg.argIntptr); + def_val = int_val_buf; + break; + + case OPARG_TYPE_BOOLEAN: + def_val = (od->optArg.argBool) ? TRUE_STR : FALSE_STR; + break; + + default: + if (od->optArg.argString == NULL) { + if (fmt == SGL_DEF_FMT) + fmt = SGL_NO_DEF_FMT; + def_val = NULL; + } + else + def_val = od->optArg.argString; + } + + printf(fmt, opts->pzPROGNAME, od->pz_NAME, def_val); + } +} + +static void +emit_action(tOptions * opts, tOptDesc * od) +{ + if (od->pOptProc == optionPrintVersion) + printf(ECHO_N_EXIT, opts->pzPROGNAME, VER_STR); + + else if (od->pOptProc == optionPagedUsage) + printf(PAGE_USAGE_TEXT, opts->pzPROGNAME); + + else if (od->pOptProc == optionLoadOpt) { + printf(LVL3_CMD, NO_LOAD_WARN); + printf(LVL3_CMD, YES_NEED_OPT_ARG); + + } else if (od->pz_NAME == NULL) { + + if (od->pOptProc == NULL) { + printf(LVL3_CMD, NO_SAVE_OPTS); + printf(LVL3_CMD, OK_NEED_OPT_ARG); + } else + printf(ECHO_N_EXIT, opts->pzPROGNAME, LONG_USE_STR); + + } else { + if (od->optMaxCt == 1) + printf(SGL_ARG_FMT, opts->pzPROGNAME, od->pz_NAME); + else { + if ((unsigned)od->optMaxCt < NOLIMIT) + printf(CHK_MAX_COUNT, opts->pzPROGNAME, + od->pz_NAME, od->optMaxCt); + + printf(MULTI_ARG_FMT, opts->pzPROGNAME, od->pz_NAME); + } + + /* + * Fix up the args. + */ + if (OPTST_GET_ARGTYPE(od->fOptState) == OPARG_TYPE_NONE) { + printf(SET_MULTI_ARG, opts->pzPROGNAME, od->pz_NAME); + printf(LVL3_CMD, NO_ARG_NEEDED); + + } else if (od->fOptState & OPTST_ARG_OPTIONAL) { + printf(SET_MULTI_ARG, opts->pzPROGNAME, od->pz_NAME); + printf(LVL3_CMD, OK_NEED_OPT_ARG); + + } else { + printf(LVL3_CMD, YES_NEED_OPT_ARG); + } + } + fputs(zOptionEndSelect, stdout); +} + +static void +emit_inaction(tOptions * opts, tOptDesc * od) +{ + if (od->pOptProc == optionLoadOpt) { + printf(LVL3_CMD, NO_SUPPRESS_LOAD); + + } else if (od->optMaxCt == 1) + printf(NO_SGL_ARG_FMT, opts->pzPROGNAME, + od->pz_NAME, od->pz_DisablePfx); + else + printf(NO_MULTI_ARG_FMT, opts->pzPROGNAME, + od->pz_NAME, od->pz_DisablePfx); + + printf(LVL3_CMD, NO_ARG_NEEDED); + fputs(zOptionEndSelect, stdout); +} + +/** + * recognize flag options. These go at the end. + * At the end, emit code to handle options we don't recognize. + * + * @param[in] opts the program options + */ +static void +emit_flag(tOptions * opts) +{ + tOptDesc * od = opts->pOptDesc; + int opt_ct = opts->optCt; + + fputs(zOptionCase, stdout); + + for (;opt_ct > 0; od++, --opt_ct) { + + if (SKIP_OPT(od) || ! IS_GRAPHIC_CHAR(od->optValue)) + continue; + + printf(zOptionFlag, od->optValue); + emit_action(opts, od); + } + printf(UNK_OPT_FMT, FLAG_STR, opts->pzPROGNAME); +} + +/** + * Emit the match text for a long option. The passed in \a name may be + * either the enablement name or the disablement name. + * + * @param[in] name The current name to check. + * @param[in] cod current option descriptor + * @param[in] opts the program options + */ +static void +emit_match_expr(char const * name, tOptDesc * cod, tOptions * opts) +{ + char name_bf[32]; + unsigned int min_match_ct = 2; + unsigned int max_match_ct = strlen(name) - 1; + + if (max_match_ct >= sizeof(name_bf) - 1) + goto leave; + + { + tOptDesc * od = opts->pOptDesc; + int ct = opts->optCt; + + for (; ct-- > 0; od++) { + unsigned int match_ct = 0; + + /* + * Omit the current option, Doc opts and compiled out opts. + */ + if ((od == cod) || SKIP_OPT(od)) + continue; + + /* + * Check each character of the name case insensitively. + * They must not be the same. They cannot be, because it would + * not compile correctly if they were. + */ + while (UPPER(od->pz_Name[match_ct]) == UPPER(name[match_ct])) + match_ct++; + + if (match_ct > min_match_ct) + min_match_ct = match_ct; + + /* + * Check the disablement name, too. + */ + if (od->pz_DisableName == NULL) + continue; + + match_ct = 0; + while ( toupper(od->pz_DisableName[match_ct]) + == toupper(name[match_ct])) + match_ct++; + if (match_ct > min_match_ct) + min_match_ct = match_ct; + } + } + + /* + * Don't bother emitting partial matches if there is only one possible + * partial match. + */ + if (min_match_ct < max_match_ct) { + char * pz = name_bf + min_match_ct; + int nm_ix = min_match_ct; + + memcpy(name_bf, name, min_match_ct); + + for (;;) { + *pz = NUL; + printf(zOptionPartName, name_bf); + *pz++ = name[nm_ix++]; + if (name[nm_ix] == NUL) { + *pz = NUL; + break; + } + } + } + +leave: + printf(zOptionFullName, name); +} + +/** + * Emit GNU-standard long option handling code. + * + * @param[in] opts the program options + */ +static void +emit_long(tOptions * opts) +{ + tOptDesc * od = opts->pOptDesc; + int ct = opts->optCt; + + fputs(zOptionCase, stdout); + + /* + * do each option, ... + */ + do { + /* + * Documentation & compiled-out options + */ + if (SKIP_OPT(od)) + continue; + + emit_match_expr(od->pz_Name, od, opts); + emit_action(opts, od); + + /* + * Now, do the same thing for the disablement version of the option. + */ + if (od->pz_DisableName != NULL) { + emit_match_expr(od->pz_DisableName, od, opts); + emit_inaction(opts, od); + } + } while (od++, --ct > 0); + + printf(UNK_OPT_FMT, OPTION_STR, opts->pzPROGNAME); +} + +/** + * Load the previous shell script output file. We need to preserve any + * hand-edited additions outside of the START_MARK and END_MARKs. + * + * @param[in] fname the output file name + */ +static char * +load_old_output(char const * fname, char const * pname) +{ + /* + * IF we cannot stat the file, + * THEN assume we are creating a new file. + * Skip the loading of the old data. + */ + FILE * fp = fopen(fname, "r" FOPEN_BINARY_FLAG); + struct stat stbf; + char * text; + char * scan; + + if (fp == NULL) + return NULL; + + /* + * If we opened it, we should be able to stat it and it needs + * to be a regular file + */ + if ((fstat(fileno(fp), &stbf) != 0) || (! S_ISREG(stbf.st_mode))) + fserr_exit(pname, "fstat", fname); + + scan = text = AGALOC(stbf.st_size + 1, "f data"); + + /* + * Read in all the data as fast as our OS will let us. + */ + for (;;) { + size_t inct = fread(VOIDP(scan), 1, (size_t)stbf.st_size, fp); + if (inct == 0) + break; + + stbf.st_size -= (ssize_t)inct; + + if (stbf.st_size == 0) + break; + + scan += inct; + } + + *scan = NUL; + fclose(fp); + + return text; +} + +/** + * Open the specified output file. If it already exists, load its + * contents and save the non-generated (hand edited) portions. + * If a "start mark" is found, everything before it is preserved leader. + * If not, the entire thing is a trailer. Assuming the start is found, + * then everything after the end marker is the trailer. If the end + * mark is not found, the file is actually corrupt, but we take the + * remainder to be the trailer. + * + * @param[in] fname the output file name + */ +static void +open_out(char const * fname, char const * pname) +{ + + do { + char * txt = script_text = load_old_output(fname, pname); + char * scn; + + if (txt == NULL) + break; + + scn = strstr(txt, START_MARK); + if (scn == NULL) { + script_trailer = txt; + break; + } + + *(scn++) = NUL; + scn = strstr(scn, END_MARK); + if (scn == NULL) { + /* + * The file is corrupt. Set the trailer to be everything + * after the start mark. The user will need to fix it up. + */ + script_trailer = txt + strlen(txt) + START_MARK_LEN + 1; + break; + } + + /* + * Check to see if the data contains our marker. + * If it does, then we will skip over it + */ + script_trailer = scn + END_MARK_LEN; + script_leader = txt; + } while (false); + + if (freopen(fname, "w" FOPEN_BINARY_FLAG, stdout) != stdout) + fserr_exit(pname, "freopen", fname); +} + +/*=export_func genshelloptUsage + * private: + * what: The usage function for the genshellopt generated program + * + * arg: + tOptions * + opts + program options descriptor + + * arg: + int + exit_cd + usage text type to produce + + * + * doc: + * This function is used to create the usage strings for the option + * processing shell script code. Two child processes are spawned + * each emitting the usage text in either the short (error exit) + * style or the long style. The generated program will capture this + * and create shell script variables containing the two types of text. +=*/ +void +genshelloptUsage(tOptions * opts, int exit_cd) +{ +#if ! defined(HAVE_WORKING_FORK) + optionUsage(opts, exit_cd); +#else + /* + * IF not EXIT_SUCCESS, + * THEN emit the short form of usage. + */ + if (exit_cd != EXIT_SUCCESS) + optionUsage(opts, exit_cd); + fflush(stderr); + fflush(stdout); + if (ferror(stdout) || ferror(stderr)) + option_exits(EXIT_FAILURE); + + option_usage_fp = stdout; + + /* + * First, print our usage + */ + switch (fork()) { + case -1: + optionUsage(opts, EXIT_FAILURE); + /* FALLTHROUGH */ /* NOTREACHED */ + + case 0: + pagerState = PAGER_STATE_CHILD; + optionUsage(opts, EXIT_SUCCESS); + /* FALLTHROUGH */ /* NOTREACHED */ + + default: + { + int sts; + wait(&sts); + } + } + + /* + * Generate the pzProgName, since optionProcess() normally + * gets it from the command line + */ + { + char * pz; + char ** pp = VOIDP(&(optionParseShellOptions->pzProgName)); + AGDUPSTR(pz, optionParseShellOptions->pzPROGNAME, "prog name"); + *pp = pz; + while (*pz != NUL) { + *pz = (char)LOWER(*pz); + pz++; + } + } + + /* + * Separate the makeshell usage from the client usage + */ + fprintf(option_usage_fp, zGenshell, optionParseShellOptions->pzProgName); + fflush(option_usage_fp); + + /* + * Now, print the client usage. + */ + switch (fork()) { + case 0: + pagerState = PAGER_STATE_CHILD; + /*FALLTHROUGH*/ + case -1: + optionUsage(optionParseShellOptions, EXIT_FAILURE); + /* FALLTHROUGH */ /* NOTREACHED */ + + default: + { + int sts; + wait(&sts); + } + } + + fflush(stdout); + if (ferror(stdout)) + fserr_exit(opts->pzProgName, zwriting, zstdout_name); + + option_exits(EXIT_SUCCESS); +#endif +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/makeshell.c */ diff --git a/src/libopts/nested.c b/src/libopts/nested.c new file mode 100644 index 0000000..e760450 --- /dev/null +++ b/src/libopts/nested.c @@ -0,0 +1,905 @@ + +/** + * \file nested.c + * + * Handle options with arguments that contain nested values. + * + * @addtogroup autoopts + * @{ + */ +/* + * Automated Options Nested Values module. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +typedef struct { + int xml_ch; + int xml_len; + char xml_txt[8]; +} xml_xlate_t; + + static xml_xlate_t const xml_xlate[] = { + { '&', 4, "amp;" }, + { '<', 3, "lt;" }, + { '>', 3, "gt;" }, + { '"', 5, "quot;" }, + { '\'',5, "apos;" } +}; + +#ifndef ENOMSG +#define ENOMSG ENOENT +#endif + +/** + * Backslashes are used for line continuations. We keep the newline + * characters, but trim out the backslash: + */ +static void +remove_continuation(char * src) +{ + char * pzD; + + do { + while (*src == NL) src++; + pzD = strchr(src, NL); + if (pzD == NULL) + return; + + /* + * pzD has skipped at least one non-newline character and now + * points to a newline character. It now becomes the source and + * pzD goes to the previous character. + */ + src = pzD--; + if (*pzD != '\\') + pzD++; + } while (pzD == src); + + /* + * Start shifting text. + */ + for (;;) { + char ch = ((*pzD++) = *(src++)); + switch (ch) { + case NUL: return; + case '\\': + if (*src == NL) + --pzD; /* rewrite on next iteration */ + } + } +} + +/** + * Find the end of a quoted string, skipping escaped quote characters. + */ +static char const * +scan_q_str(char const * pzTxt) +{ + char q = *(pzTxt++); /* remember the type of quote */ + + for (;;) { + char ch = *(pzTxt++); + if (ch == NUL) + return pzTxt-1; + + if (ch == q) + return pzTxt; + + if (ch == '\\') { + ch = *(pzTxt++); + /* + * IF the next character is NUL, drop the backslash, too. + */ + if (ch == NUL) + return pzTxt - 2; + + /* + * IF the quote character or the escape character were escaped, + * then skip both, as long as the string does not end. + */ + if ((ch == q) || (ch == '\\')) { + if (*(pzTxt++) == NUL) + return pzTxt-1; + } + } + } +} + + +/** + * Associate a name with either a string or no value. + * + * @param[in,out] pp argument list to add to + * @param[in] name the name of the "suboption" + * @param[in] nm_len the length of the name + * @param[in] val the string value for the suboption + * @param[in] d_len the length of the value + * + * @returns the new value structure + */ +static tOptionValue * +add_string(void ** pp, char const * name, size_t nm_len, + char const * val, size_t d_len) +{ + tOptionValue * pNV; + size_t sz = nm_len + d_len + sizeof(*pNV); + + pNV = AGALOC(sz, "option name/str value pair"); + + if (val == NULL) { + pNV->valType = OPARG_TYPE_NONE; + pNV->pzName = pNV->v.strVal; + + } else { + pNV->valType = OPARG_TYPE_STRING; + if (d_len > 0) { + char const * src = val; + char * pzDst = pNV->v.strVal; + int ct = (int)d_len; + do { + int ch = *(src++) & 0xFF; + if (ch == NUL) goto data_copy_done; + if (ch == '&') + ch = get_special_char(&src, &ct); + *(pzDst++) = (char)ch; + } while (--ct > 0); + data_copy_done: + *pzDst = NUL; + + } else { + pNV->v.strVal[0] = NUL; + } + + pNV->pzName = pNV->v.strVal + d_len + 1; + } + + memcpy(pNV->pzName, name, nm_len); + pNV->pzName[ nm_len ] = NUL; + addArgListEntry(pp, pNV); + return pNV; +} + +/** + * Associate a name with a boolean value + * + * @param[in,out] pp argument list to add to + * @param[in] name the name of the "suboption" + * @param[in] nm_len the length of the name + * @param[in] val the boolean value for the suboption + * @param[in] d_len the length of the value + * + * @returns the new value structure + */ +static tOptionValue * +add_bool(void ** pp, char const * name, size_t nm_len, + char const * val, size_t d_len) +{ + size_t sz = nm_len + sizeof(tOptionValue) + 1; + tOptionValue * new_val = AGALOC(sz, "bool val"); + + /* + * Scan over whitespace is constrained by "d_len" + */ + while (IS_WHITESPACE_CHAR(*val) && (d_len > 0)) { + d_len--; val++; + } + + if (d_len == 0) + new_val->v.boolVal = 0; + + else if (IS_DEC_DIGIT_CHAR(*val)) + new_val->v.boolVal = (unsigned)atoi(val); + + else new_val->v.boolVal = ! IS_FALSE_TYPE_CHAR(*val); + + new_val->valType = OPARG_TYPE_BOOLEAN; + new_val->pzName = (char *)(new_val + 1); + memcpy(new_val->pzName, name, nm_len); + new_val->pzName[ nm_len ] = NUL; + addArgListEntry(pp, new_val); + return new_val; +} + +/** + * Associate a name with strtol() value, defaulting to zero. + * + * @param[in,out] pp argument list to add to + * @param[in] name the name of the "suboption" + * @param[in] nm_len the length of the name + * @param[in] val the numeric value for the suboption + * @param[in] d_len the length of the value + * + * @returns the new value structure + */ +static tOptionValue * +add_number(void ** pp, char const * name, size_t nm_len, + char const * val, size_t d_len) +{ + size_t sz = nm_len + sizeof(tOptionValue) + 1; + tOptionValue * new_val = AGALOC(sz, "int val"); + + /* + * Scan over whitespace is constrained by "d_len" + */ + while (IS_WHITESPACE_CHAR(*val) && (d_len > 0)) { + d_len--; val++; + } + if (d_len == 0) + new_val->v.longVal = 0; + else + new_val->v.longVal = strtol(val, 0, 0); + + new_val->valType = OPARG_TYPE_NUMERIC; + new_val->pzName = (char *)(new_val + 1); + memcpy(new_val->pzName, name, nm_len); + new_val->pzName[ nm_len ] = NUL; + addArgListEntry(pp, new_val); + return new_val; +} + +/** + * Associate a name with a nested/hierarchical value. + * + * @param[in,out] pp argument list to add to + * @param[in] name the name of the "suboption" + * @param[in] nm_len the length of the name + * @param[in] val the nested values for the suboption + * @param[in] d_len the length of the value + * + * @returns the new value structure + */ +static tOptionValue * +add_nested(void ** pp, char const * name, size_t nm_len, + char * val, size_t d_len) +{ + tOptionValue * new_val; + + if (d_len == 0) { + size_t sz = nm_len + sizeof(*new_val) + 1; + new_val = AGALOC(sz, "empty nest"); + new_val->v.nestVal = NULL; + new_val->valType = OPARG_TYPE_HIERARCHY; + new_val->pzName = (char *)(new_val + 1); + memcpy(new_val->pzName, name, nm_len); + new_val->pzName[ nm_len ] = NUL; + + } else { + new_val = optionLoadNested(val, name, nm_len); + } + + if (new_val != NULL) + addArgListEntry(pp, new_val); + + return new_val; +} + +/** + * We have an entry that starts with a name. Find the end of it, cook it + * (if called for) and create the name/value association. + */ +static char const * +scan_name(char const * name, tOptionValue * res) +{ + tOptionValue * new_val; + char const * pzScan = name+1; /* we know first char is a name char */ + char const * pzVal; + size_t nm_len = 1; + size_t d_len = 0; + + /* + * Scan over characters that name a value. These names may not end + * with a colon, but they may contain colons. + */ + pzScan = SPN_VALUE_NAME_CHARS(name + 1); + if (pzScan[-1] == ':') + pzScan--; + nm_len = (size_t)(pzScan - name); + + pzScan = SPN_HORIZ_WHITE_CHARS(pzScan); + + re_switch: + + switch (*pzScan) { + case '=': + case ':': + pzScan = SPN_HORIZ_WHITE_CHARS(pzScan + 1); + if ((*pzScan == '=') || (*pzScan == ':')) + goto default_char; + goto re_switch; + + case NL: + case ',': + pzScan++; + /* FALLTHROUGH */ + + case NUL: + add_string(&(res->v.nestVal), name, nm_len, NULL, (size_t)0); + break; + + case '"': + case '\'': + pzVal = pzScan; + pzScan = scan_q_str(pzScan); + d_len = (size_t)(pzScan - pzVal); + new_val = add_string(&(res->v.nestVal), name, nm_len, pzVal, + d_len); + if ((new_val != NULL) && (option_load_mode == OPTION_LOAD_COOKED)) + ao_string_cook(new_val->v.strVal, NULL); + break; + + default: + default_char: + /* + * We have found some strange text value. It ends with a newline + * or a comma. + */ + pzVal = pzScan; + for (;;) { + char ch = *(pzScan++); + switch (ch) { + case NUL: + pzScan--; + d_len = (size_t)(pzScan - pzVal); + goto string_done; + /* FALLTHROUGH */ + + case NL: + if ( (pzScan > pzVal + 2) + && (pzScan[-2] == '\\') + && (pzScan[ 0] != NUL)) + continue; + /* FALLTHROUGH */ + + case ',': + d_len = (size_t)(pzScan - pzVal) - 1; + string_done: + new_val = add_string(&(res->v.nestVal), name, nm_len, + pzVal, d_len); + if (new_val != NULL) + remove_continuation(new_val->v.strVal); + goto leave_scan_name; + } + } + break; + } leave_scan_name:; + + return pzScan; +} + +/** + * Some xml element that does not start with a name. + * The next character must be either '!' (introducing a comment), + * or '?' (introducing an XML meta-marker of some sort). + * We ignore these and indicate an error (NULL result) otherwise. + * + * @param[in] txt the text within an xml bracket + * @returns the address of the character after the closing marker, or NULL. + */ +static char const * +unnamed_xml(char const * txt) +{ + switch (*txt) { + default: + txt = NULL; + break; + + case '!': + txt = strstr(txt, "-->"); + if (txt != NULL) + txt += 3; + break; + + case '?': + txt = strchr(txt, '>'); + if (txt != NULL) + txt++; + break; + } + return txt; +} + +/** + * Scan off the xml element name, and the rest of the header, too. + * Set the value type to NONE if it ends with "/>". + * + * @param[in] name the first name character (alphabetic) + * @param[out] nm_len the length of the name + * @param[out] val set valType field to STRING or NONE. + * + * @returns the scan resumption point, or NULL on error + */ +static char const * +scan_xml_name(char const * name, size_t * nm_len, tOptionValue * val) +{ + char const * scan = SPN_VALUE_NAME_CHARS(name + 1); + *nm_len = (size_t)(scan - name); + if (*nm_len > 64) + return NULL; + val->valType = OPARG_TYPE_STRING; + + if (IS_WHITESPACE_CHAR(*scan)) { + /* + * There are attributes following the name. Parse 'em. + */ + scan = SPN_WHITESPACE_CHARS(scan); + scan = parse_attrs(NULL, scan, &option_load_mode, val); + if (scan == NULL) + return NULL; /* oops */ + } + + if (! IS_END_XML_TOKEN_CHAR(*scan)) + return NULL; /* oops */ + + if (*scan == '/') { + /* + * Single element XML entries get inserted as an empty string. + */ + if (*++scan != '>') + return NULL; + val->valType = OPARG_TYPE_NONE; + } + return scan+1; +} + +/** + * We've found a closing '>' without a preceding '/', thus we must search + * the text for '' where "name" is the name of the XML element. + * + * @param[in] name the start of the name in the element header + * @param[in] nm_len the length of that name + * @param[out] len the length of the value (string between header and + * the trailer/tail. + * @returns the character after the trailer, or NULL if not found. + */ +static char const * +find_end_xml(char const * src, size_t nm_len, char const * val, size_t * len) +{ + char z[72] = " 0); /* nm_len is known to be 64 or less */ + *(dst++) = '>'; + *dst = NUL; + + { + char const * res = strstr(val, z); + + if (res != NULL) { + char const * end = (option_load_mode != OPTION_LOAD_KEEP) + ? SPN_WHITESPACE_BACK(val, res) + : res; + *len = (size_t)(end - val); /* includes trailing white space */ + res = SPN_WHITESPACE_CHARS(res + (dst - z)); + } + return res; + } +} + +/** + * We've found a '<' character. We ignore this if it is a comment or a + * directive. If it is something else, then whatever it is we are looking + * at is bogus. Returning NULL stops processing. + * + * @param[in] xml_name the name of an xml bracket (usually) + * @param[in,out] res_val the option data derived from the XML element + * + * @returns the place to resume scanning input + */ +static char const * +scan_xml(char const * xml_name, tOptionValue * res_val) +{ + size_t nm_len, v_len; + char const * scan; + char const * val_str; + tOptionValue valu; + tOptionLoadMode save_mode = option_load_mode; + + if (! IS_VAR_FIRST_CHAR(*++xml_name)) + return unnamed_xml(xml_name); + + /* + * "scan_xml_name()" may change "option_load_mode". + */ + val_str = scan_xml_name(xml_name, &nm_len, &valu); + if (val_str == NULL) + goto bail_scan_xml; + + if (valu.valType == OPARG_TYPE_NONE) + scan = val_str; + else { + if (option_load_mode != OPTION_LOAD_KEEP) + val_str = SPN_WHITESPACE_CHARS(val_str); + scan = find_end_xml(xml_name, nm_len, val_str, &v_len); + if (scan == NULL) + goto bail_scan_xml; + } + + /* + * "scan" now points to where the scan is to resume after returning. + * It either points after "/>" at the end of the XML element header, + * or it points after the "" tail based on the name in the header. + */ + + switch (valu.valType) { + case OPARG_TYPE_NONE: + add_string(&(res_val->v.nestVal), xml_name, nm_len, NULL, 0); + break; + + case OPARG_TYPE_STRING: + { + tOptionValue * new_val = add_string( + &(res_val->v.nestVal), xml_name, nm_len, val_str, v_len); + + if (option_load_mode != OPTION_LOAD_KEEP) + munge_str(new_val->v.strVal, option_load_mode); + + break; + } + + case OPARG_TYPE_BOOLEAN: + add_bool(&(res_val->v.nestVal), xml_name, nm_len, val_str, v_len); + break; + + case OPARG_TYPE_NUMERIC: + add_number(&(res_val->v.nestVal), xml_name, nm_len, val_str, v_len); + break; + + case OPARG_TYPE_HIERARCHY: + { + char * pz = AGALOC(v_len+1, "h scan"); + memcpy(pz, val_str, v_len); + pz[v_len] = NUL; + add_nested(&(res_val->v.nestVal), xml_name, nm_len, pz, v_len); + AGFREE(pz); + break; + } + + case OPARG_TYPE_ENUMERATION: + case OPARG_TYPE_MEMBERSHIP: + default: + break; + } + + option_load_mode = save_mode; + return scan; + +bail_scan_xml: + option_load_mode = save_mode; + return NULL; +} + + +/** + * Deallocate a list of option arguments. This must have been gotten from + * a hierarchical option argument, not a stacked list of strings. It is + * an internal call, so it is not validated. The caller is responsible for + * knowing what they are doing. + */ +static void +unload_arg_list(tArgList * arg_list) +{ + int ct = arg_list->useCt; + char const ** pnew_val = arg_list->apzArgs; + + while (ct-- > 0) { + tOptionValue * new_val = (tOptionValue *)VOIDP(*(pnew_val++)); + if (new_val->valType == OPARG_TYPE_HIERARCHY) + unload_arg_list(new_val->v.nestVal); + AGFREE(new_val); + } + + AGFREE(arg_list); +} + +/*=export_func optionUnloadNested + * + * what: Deallocate the memory for a nested value + * arg: + tOptionValue const * + pOptVal + the hierarchical value + + * + * doc: + * A nested value needs to be deallocated. The pointer passed in should + * have been gotten from a call to @code{configFileLoad()} (See + * @pxref{libopts-configFileLoad}). +=*/ +void +optionUnloadNested(tOptionValue const * opt_val) +{ + if (opt_val == NULL) return; + if (opt_val->valType != OPARG_TYPE_HIERARCHY) { + errno = EINVAL; + return; + } + + unload_arg_list(opt_val->v.nestVal); + + AGFREE(opt_val); +} + +/** + * This is a _stable_ sort. The entries are sorted alphabetically, + * but within entries of the same name the ordering is unchanged. + * Typically, we also hope the input is sorted. + */ +static void +sort_list(tArgList * arg_list) +{ + int ix; + int lm = arg_list->useCt; + + /* + * This loop iterates "useCt" - 1 times. + */ + for (ix = 0; ++ix < lm;) { + int iy = ix-1; + tOptionValue * new_v = C(tOptionValue *, arg_list->apzArgs[ix]); + tOptionValue * old_v = C(tOptionValue *, arg_list->apzArgs[iy]); + + /* + * For as long as the new entry precedes the "old" entry, + * move the old pointer. Stop before trying to extract the + * "-1" entry. + */ + while (strcmp(old_v->pzName, new_v->pzName) > 0) { + arg_list->apzArgs[iy+1] = VOIDP(old_v); + old_v = (tOptionValue *)VOIDP(arg_list->apzArgs[--iy]); + if (iy < 0) + break; + } + + /* + * Always store the pointer. Sometimes it is redundant, + * but the redundancy is cheaper than a test and branch sequence. + */ + arg_list->apzArgs[iy+1] = VOIDP(new_v); + } +} + +/*= + * private: + * + * what: parse a hierarchical option argument + * arg: + char const * + pzTxt + the text to scan + + * arg: + char const * + pzName + the name for the text + + * arg: + size_t + nm_len + the length of "name" + + * + * ret_type: tOptionValue * + * ret_desc: An allocated, compound value structure + * + * doc: + * A block of text represents a series of values. It may be an + * entire configuration file, or it may be an argument to an + * option that takes a hierarchical value. + * + * If NULL is returned, errno will be set: + * @itemize @bullet + * @item + * @code{EINVAL} the input text was NULL. + * @item + * @code{ENOMEM} the storage structures could not be allocated + * @item + * @code{ENOMSG} no configuration values were found + * @end itemize +=*/ +static tOptionValue * +optionLoadNested(char const * text, char const * name, size_t nm_len) +{ + tOptionValue * res_val; + + /* + * Make sure we have some data and we have space to put what we find. + */ + if (text == NULL) { + errno = EINVAL; + return NULL; + } + text = SPN_WHITESPACE_CHARS(text); + if (*text == NUL) { + errno = ENOMSG; + return NULL; + } + res_val = AGALOC(sizeof(*res_val) + nm_len + 1, "nest args"); + res_val->valType = OPARG_TYPE_HIERARCHY; + res_val->pzName = (char *)(res_val + 1); + memcpy(res_val->pzName, name, nm_len); + res_val->pzName[nm_len] = NUL; + + { + tArgList * arg_list = AGALOC(sizeof(*arg_list), "nest arg l"); + + res_val->v.nestVal = arg_list; + arg_list->useCt = 0; + arg_list->allocCt = MIN_ARG_ALLOC_CT; + } + + /* + * Scan until we hit a NUL. + */ + do { + text = SPN_WHITESPACE_CHARS(text); + if (IS_VAR_FIRST_CHAR(*text)) + text = scan_name(text, res_val); + + else switch (*text) { + case NUL: + goto scan_done; + + case '<': + text = scan_xml(text, res_val); + if (text == NULL) + goto woops; + if (*text == ',') + text++; + break; + + case '#': + text = strchr(text, NL); + break; + + default: + goto woops; + } + } while (text != NULL); scan_done:; + + { + tArgList * al = res_val->v.nestVal; + if (al->useCt == 0) { + errno = ENOMSG; + goto woops; + } + if (al->useCt > 1) + sort_list(al); + } + + return res_val; + + woops: + AGFREE(res_val->v.nestVal); + AGFREE(res_val); + return NULL; +} + +/*=export_func optionNestedVal + * private: + * + * what: parse a hierarchical option argument + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + od + the descriptor for this arg + + * + * doc: + * Nested value was found on the command line +=*/ +void +optionNestedVal(tOptions * opts, tOptDesc * od) +{ + if (opts < OPTPROC_EMIT_LIMIT) + return; + + if (od->fOptState & OPTST_RESET) { + tArgList * arg_list = od->optCookie; + int ct; + char const ** av; + + if (arg_list == NULL) + return; + ct = arg_list->useCt; + av = arg_list->apzArgs; + + while (--ct >= 0) { + void * p = VOIDP(*(av++)); + optionUnloadNested((tOptionValue const *)p); + } + + AGFREE(od->optCookie); + + } else { + tOptionValue * opt_val = optionLoadNested( + od->optArg.argString, od->pz_Name, strlen(od->pz_Name)); + + if (opt_val != NULL) + addArgListEntry(&(od->optCookie), VOIDP(opt_val)); + } +} + +/** + * get_special_char + */ +static int +get_special_char(char const ** ppz, int * ct) +{ + char const * pz = *ppz; + + if (*ct < 3) + return '&'; + + if (*pz == '#') { + int base = 10; + int retch; + + pz++; + if (*pz == 'x') { + base = 16; + pz++; + } + retch = (int)strtoul(pz, (char **)&pz, base); + if (*pz != ';') + return '&'; + base = (int)(++pz - *ppz); + if (base > *ct) + return '&'; + + *ct -= base; + *ppz = pz; + return retch; + } + + { + int ctr = sizeof(xml_xlate) / sizeof(xml_xlate[0]); + xml_xlate_t const * xlatp = xml_xlate; + + for (;;) { + if ( (*ct >= xlatp->xml_len) + && (strncmp(pz, xlatp->xml_txt, (size_t)xlatp->xml_len) == 0)) { + *ppz += xlatp->xml_len; + *ct -= xlatp->xml_len; + return xlatp->xml_ch; + } + + if (--ctr <= 0) + break; + xlatp++; + } + } + return '&'; +} + +/** + * emit_special_char + */ +static void +emit_special_char(FILE * fp, int ch) +{ + int ctr = sizeof(xml_xlate) / sizeof(xml_xlate[0]); + xml_xlate_t const * xlatp = xml_xlate; + + putc('&', fp); + for (;;) { + if (ch == xlatp->xml_ch) { + fputs(xlatp->xml_txt, fp); + return; + } + if (--ctr <= 0) + break; + xlatp++; + } + fprintf(fp, XML_HEX_BYTE_FMT, (ch & 0xFF)); +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/nested.c */ diff --git a/src/libopts/numeric.c b/src/libopts/numeric.c new file mode 100644 index 0000000..bbb43cc --- /dev/null +++ b/src/libopts/numeric.c @@ -0,0 +1,180 @@ + +/** + * \file numeric.c + * + * Handle options with numeric (integer) arguments. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/*=export_func optionShowRange + * private: + * + * what: Show info about range constraints + * arg: + tOptions * + pOpts + program options descriptor + + * arg: + tOptDesc * + pOptDesc + the descriptor for this arg + + * arg: + void * + rng_table + the value range tables + + * arg: + int + rng_count + the number of entries + + * + * doc: + * Show information about a numeric option with range constraints. +=*/ +void +optionShowRange(tOptions * pOpts, tOptDesc * pOD, void * rng_table, int rng_ct) +{ + const struct {long const rmin, rmax;} * rng = rng_table; + + char const * pz_indent = zTabHyp + tab_skip_ct; + + /* + * The range is shown only for full usage requests and an error + * in this particular option. + */ + if (pOpts != OPTPROC_EMIT_USAGE) { + if (pOpts <= OPTPROC_EMIT_LIMIT) + return; + pz_indent = ONE_TAB_STR; + + fprintf(option_usage_fp, zRangeErr, pOpts->pzProgName, + pOD->pz_Name, pOD->optArg.argInt); + pz_indent = ""; + } + + if (pOD->fOptState & OPTST_SCALED_NUM) + fprintf(option_usage_fp, zRangeScaled, pz_indent); + + fprintf(option_usage_fp, (rng_ct > 1) ? zRangeLie : zRangeOnly, pz_indent); + pz_indent = (pOpts != OPTPROC_EMIT_USAGE) + ? ONE_TAB_STR + : (zTabSpace + tab_skip_ct); + + for (;;) { + if (rng->rmax == LONG_MIN) + fprintf(option_usage_fp, zRangeExact, pz_indent, rng->rmin); + else if (rng->rmin == LONG_MIN) + fprintf(option_usage_fp, zRangeUpto, pz_indent, rng->rmax); + else if (rng->rmax == LONG_MAX) + fprintf(option_usage_fp, zRangeAbove, pz_indent, rng->rmin); + else + fprintf(option_usage_fp, zRange, pz_indent, rng->rmin, + rng->rmax); + + if (--rng_ct <= 0) { + fputc(NL, option_usage_fp); + break; + } + fputs(zRangeOr, option_usage_fp); + rng++; + } + + if (pOpts > OPTPROC_EMIT_LIMIT) + pOpts->pUsageProc(pOpts, EXIT_FAILURE); +} + +/*=export_func optionNumericVal + * private: + * + * what: process an option with a numeric value. + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + od + the descriptor for this arg + + * + * doc: + * Decipher a numeric value. +=*/ +void +optionNumericVal(tOptions * opts, tOptDesc * od) +{ + char * pz; + long val; + + /* + * Guard against all the different ways this procedure might get invoked + * when there is no string argument provided. + */ + if (INQUERY_CALL(opts, od) || (od->optArg.argString == NULL)) + return; + + /* + * Numeric options may have a range associated with it. + * If it does, the usage procedure requests that it be + * emitted by passing a NULL od pointer. Also bail out + * if there is no option argument or if we are being reset. + */ + if ( (od == NULL) + || (od->optArg.argString == NULL) + || ((od->fOptState & OPTST_RESET) != 0) + || (opts <= OPTPROC_EMIT_LIMIT)) + return; + + errno = 0; + val = strtol(od->optArg.argString, &pz, 0); + if ((pz == od->optArg.argString) || (errno != 0)) + goto bad_number; + + if ((od->fOptState & OPTST_SCALED_NUM) != 0) + switch (*(pz++)) { + case NUL: pz--; break; + case 't': val *= 1000; /* FALLTHROUGH */ + case 'g': val *= 1000; /* FALLTHROUGH */ + case 'm': val *= 1000; /* FALLTHROUGH */ + case 'k': val *= 1000; break; + + case 'T': val *= 1024; /* FALLTHROUGH */ + case 'G': val *= 1024; /* FALLTHROUGH */ + case 'M': val *= 1024; /* FALLTHROUGH */ + case 'K': val *= 1024; break; + + default: goto bad_number; + } + + if (*pz != NUL) + goto bad_number; + + if (od->fOptState & OPTST_ALLOC_ARG) { + AGFREE(od->optArg.argString); + od->fOptState &= ~OPTST_ALLOC_ARG; + } + + od->optArg.argInt = val; + return; + + bad_number: + + fprintf( stderr, zNotNumber, opts->pzProgName, od->optArg.argString ); + if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) + (*(opts->pUsageProc))(opts, EXIT_FAILURE); + + errno = EINVAL; + od->optArg.argInt = ~0; +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/numeric.c */ diff --git a/src/libopts/option-value-type.c b/src/libopts/option-value-type.c new file mode 100644 index 0000000..2bc8642 --- /dev/null +++ b/src/libopts/option-value-type.c @@ -0,0 +1,156 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (stdin.c) + * + * It has been AutoGen-ed + * From the definitions stdin + * and the template file str2enum + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name ``Bruce Korb'' nor the name of any other + * contributor may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * str2enum IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "option-value-type.h" +/* ANSI-C code produced by gperf version 3.1 */ +/* Command-line: gperf option-value-type.gp */ +/* Computed positions: -k'1' */ + + + +# if 0 /* gperf build options: */ +// %struct-type +// %language=ANSI-C +// %includes +// %global-table +// %omit-struct-type +// %readonly-tables +// %compare-strncmp +// +// %define slot-name vtp_name +// %define hash-function-name option_value_type_hash +// %define lookup-function-name find_option_value_type_name +// %define word-array-name option_value_type_table +// %define initializer-suffix ,VTP_COUNT_CMD +// +# endif + +#include "option-value-type.h" +typedef struct { + char const * vtp_name; + option_value_type_enum_t vtp_id; +} option_value_type_map_t; +#include + +/* maximum key range = 15, duplicates = 0 */ + +static unsigned int +option_value_type_hash (register const char *str, register size_t len) +{ + static const unsigned char asso_values[] = + { + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 0, 18, + 18, 18, 18, 18, 0, 10, 18, 5, 18, 18, + 5, 18, 18, 18, 18, 0, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18 + }; + return len + asso_values[(unsigned char)str[0]]; +} + +static const option_value_type_map_t option_value_type_table[] = + { + {"",VTP_COUNT_CMD}, {"",VTP_COUNT_CMD}, + {"",VTP_COUNT_CMD}, + {"set", VTP_CMD_SET}, + {"bool", VTP_CMD_BOOL}, + {"",VTP_COUNT_CMD}, + {"string", VTP_CMD_STRING}, + {"boolean", VTP_CMD_BOOLEAN}, + {"",VTP_COUNT_CMD}, + {"hierarchy", VTP_CMD_HIERARCHY}, + {"",VTP_COUNT_CMD}, + {"nested", VTP_CMD_NESTED}, + {"keyword", VTP_CMD_KEYWORD}, + {"",VTP_COUNT_CMD}, + {"set-membership", VTP_CMD_SET_MEMBERSHIP}, + {"",VTP_COUNT_CMD}, {"",VTP_COUNT_CMD}, + {"integer", VTP_CMD_INTEGER} + }; + +static inline const option_value_type_map_t * +find_option_value_type_name (register const char *str, register size_t len) +{ + if (len <= 14 && len >= 3) + { + register unsigned int key = (int)option_value_type_hash (str, len); + + if (key <= 17) + { + register const char *s = option_value_type_table[key].vtp_name; + + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') + return &option_value_type_table[key]; + } + } + return 0; +} + +/** + * Convert a command (keyword) to a option_value_type_enum_t enumeration value. + * + * @param[in] str a string that should start with a known key word. + * @param[in] len the provided length of the keyword at \a str. + * @returns the enumeration value. + * If not found, that value is VTP_INVALID_CMD. + */ +option_value_type_enum_t +find_option_value_type_cmd(char const * str, size_t len) +{ + option_value_type_map_t const * map; + + map = find_option_value_type_name(str, (unsigned int)len); + return (map == NULL) ? VTP_INVALID_CMD : map->vtp_id; +} + +/* end of option-value-type.c */ diff --git a/src/libopts/option-value-type.h b/src/libopts/option-value-type.h new file mode 100644 index 0000000..cf6dcaa --- /dev/null +++ b/src/libopts/option-value-type.h @@ -0,0 +1,60 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (stdin.h) + * + * It has been AutoGen-ed + * From the definitions stdin + * and the template file str2enum + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name ``Bruce Korb'' nor the name of any other + * contributor may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * str2enum IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Command/Keyword Dispatcher + */ +#ifndef STR2ENUM_OPTION_VALUE_TYPE_H_GUARD +#define STR2ENUM_OPTION_VALUE_TYPE_H_GUARD 1 +#include +#ifndef MISSING_INTTYPES_H +# include +#endif + +typedef enum { + VTP_INVALID_CMD = 0, + VTP_CMD_STRING = 1, + VTP_CMD_INTEGER = 2, + VTP_CMD_BOOL = 3, + VTP_CMD_BOOLEAN = 4, + VTP_CMD_KEYWORD = 5, + VTP_CMD_SET = 6, + VTP_CMD_SET_MEMBERSHIP = 7, + VTP_CMD_NESTED = 8, + VTP_CMD_HIERARCHY = 9, + VTP_COUNT_CMD +} option_value_type_enum_t; + +extern option_value_type_enum_t +find_option_value_type_cmd(char const * str, size_t len); + +#endif /* STR2ENUM_OPTION_VALUE_TYPE_H_GUARD */ +/* end of option-value-type.h */ diff --git a/src/libopts/option-xat-attribute.c b/src/libopts/option-xat-attribute.c new file mode 100644 index 0000000..a34ab1b --- /dev/null +++ b/src/libopts/option-xat-attribute.c @@ -0,0 +1,148 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (stdin.c) + * + * It has been AutoGen-ed + * From the definitions stdin + * and the template file str2enum + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name ``Bruce Korb'' nor the name of any other + * contributor may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * str2enum IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "option-xat-attribute.h" +/* ANSI-C code produced by gperf version 3.1 */ +/* Command-line: gperf option-xat-attribute.gp */ +/* Computed positions: -k'1' */ + + + +# if 0 /* gperf build options: */ +// %struct-type +// %language=ANSI-C +// %includes +// %global-table +// %omit-struct-type +// %readonly-tables +// %compare-strncmp +// +// %define slot-name xat_name +// %define hash-function-name option_xat_attribute_hash +// %define lookup-function-name find_option_xat_attribute_name +// %define word-array-name option_xat_attribute_table +// %define initializer-suffix ,XAT_COUNT_CMD +// +# endif + +#include "option-xat-attribute.h" +typedef struct { + char const * xat_name; + option_xat_attribute_enum_t xat_id; +} option_xat_attribute_map_t; +#include + +/* maximum key range = 6, duplicates = 0 */ + +static unsigned int +option_xat_attribute_hash (register const char *str, register size_t len) +{ + static const unsigned char asso_values[] = + { + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10, 0, + 10,10,10,10,10,10,10, 5,10, 0, + 10,10,10,10,10,10, 0, 0,10, 0, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10 + }; + return len + asso_values[(unsigned char)str[0]]; +} + +static const option_xat_attribute_map_t option_xat_attribute_table[] = + { + {"",XAT_COUNT_CMD}, {"",XAT_COUNT_CMD}, + {"",XAT_COUNT_CMD}, {"",XAT_COUNT_CMD}, + {"type", XAT_CMD_TYPE}, + {"words", XAT_CMD_WORDS}, + {"cooked", XAT_CMD_COOKED}, + {"members", XAT_CMD_MEMBERS}, + {"uncooked", XAT_CMD_UNCOOKED}, + {"keep", XAT_CMD_KEEP} + }; + +static inline const option_xat_attribute_map_t * +find_option_xat_attribute_name (register const char *str, register size_t len) +{ + if (len <= 8 && len >= 4) + { + register unsigned int key = (int)option_xat_attribute_hash (str, len); + + if (key <= 9) + { + register const char *s = option_xat_attribute_table[key].xat_name; + + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') + return &option_xat_attribute_table[key]; + } + } + return 0; +} + +/** + * Convert a command (keyword) to a option_xat_attribute_enum_t enumeration value. + * + * @param[in] str a string that should start with a known key word. + * @param[in] len the provided length of the keyword at \a str. + * @returns the enumeration value. + * If not found, that value is XAT_INVALID_CMD. + */ +option_xat_attribute_enum_t +find_option_xat_attribute_cmd(char const * str, size_t len) +{ + option_xat_attribute_map_t const * map; + + map = find_option_xat_attribute_name(str, (unsigned int)len); + return (map == NULL) ? XAT_INVALID_CMD : map->xat_id; +} + +/* end of option-xat-attribute.c */ diff --git a/src/libopts/option-xat-attribute.h b/src/libopts/option-xat-attribute.h new file mode 100644 index 0000000..dde1617 --- /dev/null +++ b/src/libopts/option-xat-attribute.h @@ -0,0 +1,57 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (stdin.h) + * + * It has been AutoGen-ed + * From the definitions stdin + * and the template file str2enum + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name ``Bruce Korb'' nor the name of any other + * contributor may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * str2enum IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Command/Keyword Dispatcher + */ +#ifndef STR2ENUM_OPTION_XAT_ATTRIBUTE_H_GUARD +#define STR2ENUM_OPTION_XAT_ATTRIBUTE_H_GUARD 1 +#include +#ifndef MISSING_INTTYPES_H +# include +#endif + +typedef enum { + XAT_INVALID_CMD = 0, + XAT_CMD_TYPE = 1, + XAT_CMD_WORDS = 2, + XAT_CMD_MEMBERS = 3, + XAT_CMD_COOKED = 4, + XAT_CMD_UNCOOKED = 5, + XAT_CMD_KEEP = 6, + XAT_COUNT_CMD +} option_xat_attribute_enum_t; + +extern option_xat_attribute_enum_t +find_option_xat_attribute_cmd(char const * str, size_t len); + +#endif /* STR2ENUM_OPTION_XAT_ATTRIBUTE_H_GUARD */ +/* end of option-xat-attribute.h */ diff --git a/src/libopts/parse-duration.c b/src/libopts/parse-duration.c new file mode 100644 index 0000000..0f4a056 --- /dev/null +++ b/src/libopts/parse-duration.c @@ -0,0 +1,604 @@ +/* Parse a time duration and return a seconds count + Copyright (C) 2008-2018 Free Software Foundation, Inc. + Written by Bruce Korb , 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "parse-duration.h" + +#include +#include +#include +#include +#include +#include + +#include "intprops.h" + +#ifndef NUL +#define NUL '\0' +#endif + +#define cch_t char const + +typedef enum { + NOTHING_IS_DONE, + YEAR_IS_DONE, + MONTH_IS_DONE, + WEEK_IS_DONE, + DAY_IS_DONE, + HOUR_IS_DONE, + MINUTE_IS_DONE, + SECOND_IS_DONE +} whats_done_t; + +#define SEC_PER_MIN 60 +#define SEC_PER_HR (SEC_PER_MIN * 60) +#define SEC_PER_DAY (SEC_PER_HR * 24) +#define SEC_PER_WEEK (SEC_PER_DAY * 7) +#define SEC_PER_MONTH (SEC_PER_DAY * 30) +#define SEC_PER_YEAR (SEC_PER_DAY * 365) + +#undef MAX_DURATION +#define MAX_DURATION TYPE_MAXIMUM(time_t) + +/* Wrapper around strtoul that does not require a cast. */ +static unsigned long +str_const_to_ul (cch_t * str, cch_t ** ppz, int base) +{ + return strtoul (str, (char **)ppz, base); +} + +/* Wrapper around strtol that does not require a cast. */ +static long +str_const_to_l (cch_t * str, cch_t ** ppz, int base) +{ + return strtol (str, (char **)ppz, base); +} + +/* Returns BASE + VAL * SCALE, interpreting BASE = BAD_TIME + with errno set as an error situation, and returning BAD_TIME + with errno set in an error situation. */ +static time_t +scale_n_add (time_t base, time_t val, int scale) +{ + if (base == BAD_TIME) + { + if (errno == 0) + errno = EINVAL; + return BAD_TIME; + } + + if (val > MAX_DURATION / scale) + { + errno = ERANGE; + return BAD_TIME; + } + + val *= scale; + if (base > MAX_DURATION - val) + { + errno = ERANGE; + return BAD_TIME; + } + + return base + val; +} + +/* After a number HH has been parsed, parse subsequent :MM or :MM:SS. */ +static time_t +parse_hr_min_sec (time_t start, cch_t * pz) +{ + int lpct = 0; + + errno = 0; + + /* For as long as our scanner pointer points to a colon *AND* + we've not looped before, then keep looping. (two iterations max) */ + while ((*pz == ':') && (lpct++ <= 1)) + { + unsigned long v = str_const_to_ul (pz+1, &pz, 10); + + if (errno != 0) + return BAD_TIME; + + start = scale_n_add (v, start, 60); + + if (errno != 0) + return BAD_TIME; + } + + /* allow for trailing spaces */ + while (isspace ((unsigned char)*pz)) + pz++; + if (*pz != NUL) + { + errno = EINVAL; + return BAD_TIME; + } + + return start; +} + +/* Parses a value and returns BASE + value * SCALE, interpreting + BASE = BAD_TIME with errno set as an error situation, and returning + BAD_TIME with errno set in an error situation. */ +static time_t +parse_scaled_value (time_t base, cch_t ** ppz, cch_t * endp, int scale) +{ + cch_t * pz = *ppz; + time_t val; + + if (base == BAD_TIME) + return base; + + errno = 0; + val = str_const_to_ul (pz, &pz, 10); + if (errno != 0) + return BAD_TIME; + while (isspace ((unsigned char)*pz)) + pz++; + if (pz != endp) + { + errno = EINVAL; + return BAD_TIME; + } + + *ppz = pz; + return scale_n_add (base, val, scale); +} + +/* Parses the syntax YEAR-MONTH-DAY. + PS points into the string, after "YEAR", before "-MONTH-DAY". */ +static time_t +parse_year_month_day (cch_t * pz, cch_t * ps) +{ + time_t res = 0; + + res = parse_scaled_value (0, &pz, ps, SEC_PER_YEAR); + + pz++; /* over the first '-' */ + ps = strchr (pz, '-'); + if (ps == NULL) + { + errno = EINVAL; + return BAD_TIME; + } + res = parse_scaled_value (res, &pz, ps, SEC_PER_MONTH); + + pz++; /* over the second '-' */ + ps = pz + strlen (pz); + return parse_scaled_value (res, &pz, ps, SEC_PER_DAY); +} + +/* Parses the syntax YYYYMMDD. */ +static time_t +parse_yearmonthday (cch_t * in_pz) +{ + time_t res = 0; + char buf[8]; + cch_t * pz; + + if (strlen (in_pz) != 8) + { + errno = EINVAL; + return BAD_TIME; + } + + memcpy (buf, in_pz, 4); + buf[4] = NUL; + pz = buf; + res = parse_scaled_value (0, &pz, buf + 4, SEC_PER_YEAR); + + memcpy (buf, in_pz + 4, 2); + buf[2] = NUL; + pz = buf; + res = parse_scaled_value (res, &pz, buf + 2, SEC_PER_MONTH); + + memcpy (buf, in_pz + 6, 2); + buf[2] = NUL; + pz = buf; + return parse_scaled_value (res, &pz, buf + 2, SEC_PER_DAY); +} + +/* Parses the syntax yy Y mm M ww W dd D. */ +static time_t +parse_YMWD (cch_t * pz) +{ + time_t res = 0; + cch_t * ps = strchr (pz, 'Y'); + if (ps != NULL) + { + res = parse_scaled_value (0, &pz, ps, SEC_PER_YEAR); + pz++; + } + + ps = strchr (pz, 'M'); + if (ps != NULL) + { + res = parse_scaled_value (res, &pz, ps, SEC_PER_MONTH); + pz++; + } + + ps = strchr (pz, 'W'); + if (ps != NULL) + { + res = parse_scaled_value (res, &pz, ps, SEC_PER_WEEK); + pz++; + } + + ps = strchr (pz, 'D'); + if (ps != NULL) + { + res = parse_scaled_value (res, &pz, ps, SEC_PER_DAY); + pz++; + } + + while (isspace ((unsigned char)*pz)) + pz++; + if (*pz != NUL) + { + errno = EINVAL; + return BAD_TIME; + } + + return res; +} + +/* Parses the syntax HH:MM:SS. + PS points into the string, after "HH", before ":MM:SS". */ +static time_t +parse_hour_minute_second (cch_t * pz, cch_t * ps) +{ + time_t res = 0; + + res = parse_scaled_value (0, &pz, ps, SEC_PER_HR); + + pz++; + ps = strchr (pz, ':'); + if (ps == NULL) + { + errno = EINVAL; + return BAD_TIME; + } + + res = parse_scaled_value (res, &pz, ps, SEC_PER_MIN); + + pz++; + ps = pz + strlen (pz); + return parse_scaled_value (res, &pz, ps, 1); +} + +/* Parses the syntax HHMMSS. */ +static time_t +parse_hourminutesecond (cch_t * in_pz) +{ + time_t res = 0; + char buf[4]; + cch_t * pz; + + if (strlen (in_pz) != 6) + { + errno = EINVAL; + return BAD_TIME; + } + + memcpy (buf, in_pz, 2); + buf[2] = NUL; + pz = buf; + res = parse_scaled_value (0, &pz, buf + 2, SEC_PER_HR); + + memcpy (buf, in_pz + 2, 2); + buf[2] = NUL; + pz = buf; + res = parse_scaled_value (res, &pz, buf + 2, SEC_PER_MIN); + + memcpy (buf, in_pz + 4, 2); + buf[2] = NUL; + pz = buf; + return parse_scaled_value (res, &pz, buf + 2, 1); +} + +/* Parses the syntax hh H mm M ss S. */ +static time_t +parse_HMS (cch_t * pz) +{ + time_t res = 0; + cch_t * ps = strchr (pz, 'H'); + if (ps != NULL) + { + res = parse_scaled_value (0, &pz, ps, SEC_PER_HR); + pz++; + } + + ps = strchr (pz, 'M'); + if (ps != NULL) + { + res = parse_scaled_value (res, &pz, ps, SEC_PER_MIN); + pz++; + } + + ps = strchr (pz, 'S'); + if (ps != NULL) + { + res = parse_scaled_value (res, &pz, ps, 1); + pz++; + } + + while (isspace ((unsigned char)*pz)) + pz++; + if (*pz != NUL) + { + errno = EINVAL; + return BAD_TIME; + } + + return res; +} + +/* Parses a time (hours, minutes, seconds) specification in either syntax. */ +static time_t +parse_time (cch_t * pz) +{ + cch_t * ps; + time_t res = 0; + + /* + * Scan for a hyphen + */ + ps = strchr (pz, ':'); + if (ps != NULL) + { + res = parse_hour_minute_second (pz, ps); + } + + /* + * Try for a 'H', 'M' or 'S' suffix + */ + else if (ps = strpbrk (pz, "HMS"), + ps == NULL) + { + /* Its a YYYYMMDD format: */ + res = parse_hourminutesecond (pz); + } + + else + res = parse_HMS (pz); + + return res; +} + +/* Returns a substring of the given string, with spaces at the beginning and at + the end destructively removed, per SNOBOL. */ +static char * +trim (char * pz) +{ + /* trim leading white space */ + while (isspace ((unsigned char)*pz)) + pz++; + + /* trim trailing white space */ + { + char * pe = pz + strlen (pz); + while ((pe > pz) && isspace ((unsigned char)pe[-1])) + pe--; + *pe = NUL; + } + + return pz; +} + +/* + * Parse the year/months/days of a time period + */ +static time_t +parse_period (cch_t * in_pz) +{ + char * pT; + char * ps; + char * pz = strdup (in_pz); + void * fptr = pz; + time_t res = 0; + + if (pz == NULL) + { + errno = ENOMEM; + return BAD_TIME; + } + + pT = strchr (pz, 'T'); + if (pT != NULL) + { + *(pT++) = NUL; + pz = trim (pz); + pT = trim (pT); + } + + /* + * Scan for a hyphen + */ + ps = strchr (pz, '-'); + if (ps != NULL) + { + res = parse_year_month_day (pz, ps); + } + + /* + * Try for a 'Y', 'M' or 'D' suffix + */ + else if (ps = strpbrk (pz, "YMWD"), + ps == NULL) + { + /* Its a YYYYMMDD format: */ + res = parse_yearmonthday (pz); + } + + else + res = parse_YMWD (pz); + + if ((errno == 0) && (pT != NULL)) + { + time_t val = parse_time (pT); + res = scale_n_add (res, val, 1); + } + + free (fptr); + return res; +} + +static time_t +parse_non_iso8601 (cch_t * pz) +{ + whats_done_t whatd_we_do = NOTHING_IS_DONE; + + time_t res = 0; + + do { + time_t val; + + errno = 0; + val = str_const_to_l (pz, &pz, 10); + if (errno != 0) + goto bad_time; + + /* IF we find a colon, then we're going to have a seconds value. + We will not loop here any more. We cannot already have parsed + a minute value and if we've parsed an hour value, then the result + value has to be less than an hour. */ + if (*pz == ':') + { + if (whatd_we_do >= MINUTE_IS_DONE) + break; + + val = parse_hr_min_sec (val, pz); + + if ((whatd_we_do == HOUR_IS_DONE) && (val >= SEC_PER_HR)) + break; + + return scale_n_add (res, val, 1); + } + + { + unsigned int mult; + + /* Skip over white space following the number we just parsed. */ + while (isspace ((unsigned char)*pz)) + pz++; + + switch (*pz) + { + default: goto bad_time; + case NUL: + return scale_n_add (res, val, 1); + + case 'y': case 'Y': + if (whatd_we_do >= YEAR_IS_DONE) + goto bad_time; + mult = SEC_PER_YEAR; + whatd_we_do = YEAR_IS_DONE; + break; + + case 'M': + if (whatd_we_do >= MONTH_IS_DONE) + goto bad_time; + mult = SEC_PER_MONTH; + whatd_we_do = MONTH_IS_DONE; + break; + + case 'W': + if (whatd_we_do >= WEEK_IS_DONE) + goto bad_time; + mult = SEC_PER_WEEK; + whatd_we_do = WEEK_IS_DONE; + break; + + case 'd': case 'D': + if (whatd_we_do >= DAY_IS_DONE) + goto bad_time; + mult = SEC_PER_DAY; + whatd_we_do = DAY_IS_DONE; + break; + + case 'h': + if (whatd_we_do >= HOUR_IS_DONE) + goto bad_time; + mult = SEC_PER_HR; + whatd_we_do = HOUR_IS_DONE; + break; + + case 'm': + if (whatd_we_do >= MINUTE_IS_DONE) + goto bad_time; + mult = SEC_PER_MIN; + whatd_we_do = MINUTE_IS_DONE; + break; + + case 's': + mult = 1; + whatd_we_do = SECOND_IS_DONE; + break; + } + + res = scale_n_add (res, val, mult); + + pz++; + while (isspace ((unsigned char)*pz)) + pz++; + if (*pz == NUL) + return res; + + if (! isdigit ((unsigned char)*pz)) + break; + } + + } while (whatd_we_do < SECOND_IS_DONE); + + bad_time: + errno = EINVAL; + return BAD_TIME; +} + +time_t +parse_duration (char const * pz) +{ + while (isspace ((unsigned char)*pz)) + pz++; + + switch (*pz) + { + case 'P': + return parse_period (pz + 1); + + case 'T': + return parse_time (pz + 1); + + default: + if (isdigit ((unsigned char)*pz)) + return parse_non_iso8601 (pz); + + errno = EINVAL; + return BAD_TIME; + } +} + +/* + * Local Variables: + * mode: C + * c-file-style: "gnu" + * indent-tabs-mode: nil + * End: + * end of parse-duration.c */ diff --git a/src/libopts/parse-duration.h b/src/libopts/parse-duration.h new file mode 100644 index 0000000..9a7bcd5 --- /dev/null +++ b/src/libopts/parse-duration.h @@ -0,0 +1,90 @@ +/* Parse a time duration and return a seconds count + Copyright (C) 2008-2018 Free Software Foundation, Inc. + Written by Bruce Korb , 2008. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +/* + + Readers and users of this function are referred to the ISO-8601 + specification, with particular attention to "Durations". + + At the time of writing, this worked: + + https://en.wikipedia.org/wiki/ISO_8601#Durations + + The string must start with a 'P', 'T' or a digit. + + ==== if it is a digit + + the string may contain: NNN Y NNN M NNN W NNN d NNN h NNN m NNN s + This represents NNN years, NNN months, NNN weeks, NNN days, NNN hours, + NNN minutes and NNN seconds. + The embedded white space is optional. + These terms must appear in this order. + Case is significant: 'M' is months and 'm' is minutes. + The final "s" is optional. + All of the terms ("NNN" plus designator) are optional. + Minutes and seconds may optionally be represented as NNN:NNN. + Also, hours, minute and seconds may be represented as NNN:NNN:NNN. + There is no limitation on the value of any of the terms, except + that the final result must fit in a time_t value. + + ==== if it is a 'P' or 'T', please see ISO-8601 for a rigorous definition. + + The 'P' term may be followed by any of three formats: + yyyymmdd + yy-mm-dd + yy Y mm M ww W dd D + + or it may be empty and followed by a 'T'. The "yyyymmdd" must be eight + digits long. + + NOTE! Months are always 30 days and years are always 365 days long. + 5 years is always 1825 days, not 1826 or 1827 depending on leap year + considerations. 3 months is always 90 days. There is no consideration + for how many days are in the current, next or previous months. + + For the final format: + * Embedded white space is allowed, but it is optional. + * All of the terms are optional. Any or all-but-one may be omitted. + * The meanings are yy years, mm months, ww weeks and dd days. + * The terms must appear in this order. + + ==== The 'T' term may be followed by any of these formats: + + hhmmss + hh:mm:ss + hh H mm M ss S + + For the final format: + * Embedded white space is allowed, but it is optional. + * All of the terms are optional. Any or all-but-one may be omitted. + * The terms must appear in this order. + + */ +#ifndef GNULIB_PARSE_DURATION_H +#define GNULIB_PARSE_DURATION_H + +#include + +/* Return value when a valid duration cannot be parsed. */ +#define BAD_TIME ((time_t)~0) + +/* Parses the given string. If it has the syntax of a valid duration, + this duration is returned. Otherwise, the return value is BAD_TIME, + and errno is set to either EINVAL (bad syntax) or ERANGE (out of range). */ +extern time_t parse_duration (char const * in_pz); + +#endif /* GNULIB_PARSE_DURATION_H */ diff --git a/src/libopts/pgusage.c b/src/libopts/pgusage.c new file mode 100644 index 0000000..f895b3b --- /dev/null +++ b/src/libopts/pgusage.c @@ -0,0 +1,187 @@ + +/** + * \file pgusage.c + * + * Automated Options Paged Usage module. + * + * @addtogroup autoopts + * @{ + */ +/* + * This routine will run run-on options through a pager so the + * user may examine, print or edit them at their leisure. + * + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +#if defined(HAVE_WORKING_FORK) +static inline FILE * +open_tmp_usage(char ** buf) +{ + char * bf; + size_t bfsz; + + { + unsigned int my_pid = (unsigned int)getpid(); + char const * tmpdir = getenv(TMPDIR); + if (tmpdir == NULL) + tmpdir = tmp_dir; + bfsz = TMP_FILE_FMT_LEN + strlen(tmpdir) + 10; + bf = AGALOC(bfsz, "tmp fil"); + snprintf(bf, bfsz, TMP_FILE_FMT, tmpdir, my_pid); + } + + { + static mode_t const cmask = S_IRWXO | S_IRWXG; + mode_t svmsk = umask(cmask); + int fd = mkstemp(bf); + (void)umask(svmsk); + + if (fd < 0) { + AGFREE(bf); + return NULL; + } + *buf = bf; + return fdopen(fd, "w"); + } +} + +static inline char * +mk_pager_cmd(char const * fname) +{ + /* + * Page the file and remove it when done. For shell script processing, + * we must redirect the output to the current stderr, otherwise stdout. + */ + fclose(option_usage_fp); + option_usage_fp = NULL; + + { + char const * pager = (char const *)getenv(PAGER_NAME); + size_t bfsz; + char * res; + + /* + * Use the "more(1)" program if "PAGER" has not been defined + */ + if (pager == NULL) + pager = MORE_STR; + + bfsz = 2 * strlen(fname) + strlen(pager) + PAGE_USAGE_FMT_LEN; + res = AGALOC(bfsz, "more cmd"); + snprintf(res, bfsz, PAGE_USAGE_FMT, pager, fname); + AGFREE(fname); + return res; + } +} +#endif + +/*=export_func optionPagedUsage + * private: + * + * what: emit help text and pass through a pager program. + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + od + the descriptor for this arg + + * + * doc: + * Run the usage output through a pager. + * This is very handy if it is very long. + * This is disabled on platforms without a working fork() function. +=*/ +void +optionPagedUsage(tOptions * opts, tOptDesc * od) +{ +#if ! defined(HAVE_WORKING_FORK) + if ((od->fOptState & OPTST_RESET) != 0) + return; + + (*opts->pUsageProc)(opts, EXIT_SUCCESS); +#else + static bool sv_print_exit = false; + static char * fil_name = NULL; + + /* + * IF we are being called after the usage proc is done + * (and thus has called "exit(2)") + * THEN invoke the pager to page through the usage file we created. + */ + switch (pagerState) { + case PAGER_STATE_INITIAL: + { + if ((od->fOptState & OPTST_RESET) != 0) + return; + option_usage_fp = open_tmp_usage(&fil_name); + if (option_usage_fp == NULL) + (*opts->pUsageProc)(opts, EXIT_SUCCESS); + + pagerState = PAGER_STATE_READY; + sv_print_exit = print_exit; + + /* + * Set up so this routine gets called during the exit logic + */ + atexit((void(*)(void))optionPagedUsage); + + /* + * The usage procedure will now put the usage information into + * the temporary file we created above. Keep any shell commands + * out of the result. + */ + print_exit = false; + (*opts->pUsageProc)(opts, EXIT_SUCCESS); + + /* NOTREACHED */ + _exit(EXIT_FAILURE); + } + + case PAGER_STATE_READY: + fil_name = mk_pager_cmd(fil_name); + + if (sv_print_exit) { + fputs("\nexit 0\n", stdout); + fclose(stdout); + dup2(STDERR_FILENO, STDOUT_FILENO); + + } else { + fclose(stderr); + dup2(STDOUT_FILENO, STDERR_FILENO); + } + + ignore_val( system( fil_name)); + AGFREE(fil_name); + + case PAGER_STATE_CHILD: + /* + * This is a child process used in creating shell script usage. + */ + break; + } +#endif +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/pgusage.c */ diff --git a/src/libopts/proto.h b/src/libopts/proto.h new file mode 100644 index 0000000..437e81e --- /dev/null +++ b/src/libopts/proto.h @@ -0,0 +1,620 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * Prototypes for autoopts + * Generated Sun Aug 26 10:44:39 PDT 2018 + */ +#ifndef AUTOOPTS_PROTO_H_GUARD +#define AUTOOPTS_PROTO_H_GUARD 1 + + +/* + * Static declarations from alias.c + */ +static tSuccess +too_many_occurrences(tOptions * opts, tOptDesc * od); + +/* + * Static declarations from autoopts.c + */ +static void * +ao_malloc(size_t sz); + +static void * +ao_realloc(void *p, size_t sz); + +static char * +ao_strdup(char const *str); + +static tSuccess +handle_opt(tOptions * opts, tOptState * o_st); + +static tSuccess +next_opt(tOptions * opts, tOptState * o_st); + +static tSuccess +regular_opts(tOptions * opts); + +/* + * Static declarations from check.c + */ +static bool +has_conflict(tOptions * pOpts, tOptDesc * od); + +static bool +occurs_enough(tOptions * pOpts, tOptDesc * pOD); + +static bool +is_consistent(tOptions * pOpts); + +/* + * Static declarations from configfile.c + */ +static void +file_preset(tOptions * opts, char const * fname, int dir); + +static char * +handle_comment(char * txt); + +static char * +handle_cfg(tOptions * opts, tOptState * ost, char * txt, int dir); + +static char * +handle_directive(tOptions * opts, char * txt); + +static char * +aoflags_directive(tOptions * opts, char * txt); + +static char * +program_directive(tOptions * opts, char * txt); + +static char * +handle_section(tOptions * opts, char * txt); + +static int +parse_xml_encoding(char ** ppz); + +static char * +trim_xml_text(char * intxt, char const * pznm, tOptionLoadMode mode); + +static void +cook_xml_text(char * pzData); + +static char * +handle_struct(tOptions * opts, tOptState * ost, char * txt, int dir); + +static void +intern_file_load(tOptions * opts); + +static char const * +parse_attrs(tOptions * opts, char const * txt, tOptionLoadMode * pMode, + tOptionValue * pType); + +static char const * +parse_keyword(tOptions * opts, char const * txt, tOptionValue * typ); + +static char const * +parse_set_mem(tOptions * opts, char const * txt, tOptionValue * typ); + +static char const * +parse_value(char const * txt, tOptionValue * typ); + +/* + * Static declarations from cook.c + */ +static char * +nl_count(char * start, char * end, int * lnct_p); + +static bool +contiguous_quote(char ** pps, char * pq, int * lnct_p); + +/* + * Static declarations from enum.c + */ +static void +enum_err(tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, int name_ct); + +static uintptr_t +find_name(char const * name, tOptions * pOpts, tOptDesc * pOD, + char const * const * paz_names, unsigned int name_ct); + +static void +set_memb_shell(tOptions * pOpts, tOptDesc * pOD, char const * const * paz_names, + unsigned int name_ct); + +static void +set_memb_names(tOptions * opts, tOptDesc * od, char const * const * nm_list, + unsigned int nm_ct); + +static uintptr_t +check_membership_start(tOptDesc * od, char const ** argp, bool * invert); + +static uintptr_t +find_member_bit(tOptions * opts, tOptDesc * od, char const * pz, int len, + char const * const * nm_list, unsigned int nm_ct); + +/* + * Static declarations from env.c + */ +static void +doPrognameEnv(tOptions * pOpts, teEnvPresetType type); + +static void +do_env_opt(tOptState * os, char * env_name, + tOptions * pOpts, teEnvPresetType type); + +static void +env_presets(tOptions * pOpts, teEnvPresetType type); + +/* + * Static declarations from file.c + */ +static void +check_existence(teOptFileType ftype, tOptions * pOpts, tOptDesc * pOD); + +static void +open_file_fd(tOptions * pOpts, tOptDesc * pOD, tuFileMode mode); + +static void +fopen_file_fp(tOptions * pOpts, tOptDesc * pOD, tuFileMode mode); + +/* + * Static declarations from find.c + */ +static int +parse_opt(char const ** nm_pp, char ** arg_pp, char * buf, size_t bufsz); + +static void +opt_ambiguities(tOptions * opts, char const * name, int nm_len); + +static int +opt_match_ct(tOptions * opts, char const * name, int nm_len, + int * ixp, bool * disable); + +static tSuccess +opt_set(tOptions * opts, char * arg, int idx, bool disable, tOptState * st); + +static tSuccess +opt_unknown(tOptions * opts, char const * name, char * arg, tOptState * st); + +static tSuccess +opt_ambiguous(tOptions * opts, char const * name, int match_ct); + +static tSuccess +opt_find_long(tOptions * opts, char const * opt_name, tOptState * state); + +static tSuccess +opt_find_short(tOptions * pOpts, uint_t optValue, tOptState * pOptState); + +static tSuccess +get_opt_arg_must(tOptions * opts, tOptState * o_st); + +static tSuccess +get_opt_arg_may(tOptions * pOpts, tOptState * o_st); + +static tSuccess +get_opt_arg_none(tOptions * pOpts, tOptState * o_st); + +static tSuccess +get_opt_arg(tOptions * opts, tOptState * o_st); + +static tSuccess +find_opt(tOptions * opts, tOptState * o_st); + +/* + * Static declarations from init.c + */ +static tSuccess +validate_struct(tOptions * opts, char const * pname); + +static tSuccess +immediate_opts(tOptions * opts); + +static tSuccess +do_presets(tOptions * opts); + +static bool +ao_initialize(tOptions * opts, int a_ct, char ** a_v); + +/* + * Static declarations from load.c + */ +static bool +get_realpath(char * buf, size_t b_sz); + +static bool +add_prog_path(char * buf, int b_sz, char const * fname, char const * prg_path); + +static bool +add_env_val(char * buf, int buf_sz, char const * name); + +static void +munge_str(char * txt, tOptionLoadMode mode); + +static char * +assemble_arg_val(char * txt, tOptionLoadMode mode); + +static char * +trim_quotes(char * arg); + +static bool +direction_ok(opt_state_mask_t f, int dir); + +static void +load_opt_line(tOptions * opts, tOptState * opt_state, char * line, + tDirection direction, tOptionLoadMode load_mode ); + +/* + * Static declarations from makeshell.c + */ +noreturn static void +option_exits(int exit_code); + +noreturn static void +ao_bug(char const * msg); + +static void +fserr_warn(char const * prog, char const * op, char const * fname); + +noreturn static void +fserr_exit(char const * prog, char const * op, char const * fname); + +static void +emit_var_text(char const * prog, char const * var, int fdin); + +static void +text_to_var(tOptions * opts, teTextTo which, tOptDesc * od); + +static void +emit_usage(tOptions * opts); + +static void +emit_wrapup(tOptions * opts); + +static void +emit_setup(tOptions * opts); + +static void +emit_action(tOptions * opts, tOptDesc * od); + +static void +emit_inaction(tOptions * opts, tOptDesc * od); + +static void +emit_flag(tOptions * opts); + +static void +emit_match_expr(char const * name, tOptDesc * cod, tOptions * opts); + +static void +emit_long(tOptions * opts); + +static char * +load_old_output(char const * fname, char const * pname); + +static void +open_out(char const * fname, char const * pname); + +/* + * Static declarations from nested.c + */ +static void +remove_continuation(char * src); + +static char const * +scan_q_str(char const * pzTxt); + +static tOptionValue * +add_string(void ** pp, char const * name, size_t nm_len, + char const * val, size_t d_len); + +static tOptionValue * +add_bool(void ** pp, char const * name, size_t nm_len, + char const * val, size_t d_len); + +static tOptionValue * +add_number(void ** pp, char const * name, size_t nm_len, + char const * val, size_t d_len); + +static tOptionValue * +add_nested(void ** pp, char const * name, size_t nm_len, + char * val, size_t d_len); + +static char const * +scan_name(char const * name, tOptionValue * res); + +static char const * +unnamed_xml(char const * txt); + +static char const * +scan_xml_name(char const * name, size_t * nm_len, tOptionValue * val); + +static char const * +find_end_xml(char const * src, size_t nm_len, char const * val, size_t * len); + +static char const * +scan_xml(char const * xml_name, tOptionValue * res_val); + +static void +unload_arg_list(tArgList * arg_list); + +static void +sort_list(tArgList * arg_list); + +static tOptionValue * +optionLoadNested(char const * text, char const * name, size_t nm_len); + +static int +get_special_char(char const ** ppz, int * ct); + +static void +emit_special_char(FILE * fp, int ch); + +/* + * Static declarations from parse-duration.c + */ +static unsigned long +str_const_to_ul (cch_t * str, cch_t ** ppz, int base); + +static long +str_const_to_l (cch_t * str, cch_t ** ppz, int base); + +static time_t +scale_n_add (time_t base, time_t val, int scale); + +static time_t +parse_hr_min_sec (time_t start, cch_t * pz); + +static time_t +parse_scaled_value (time_t base, cch_t ** ppz, cch_t * endp, int scale); + +static time_t +parse_year_month_day (cch_t * pz, cch_t * ps); + +static time_t +parse_yearmonthday (cch_t * in_pz); + +static time_t +parse_YMWD (cch_t * pz); + +static time_t +parse_hour_minute_second (cch_t * pz, cch_t * ps); + +static time_t +parse_hourminutesecond (cch_t * in_pz); + +static time_t +parse_HMS (cch_t * pz); + +static time_t +parse_time (cch_t * pz); + +static char * +trim (char * pz); + +static time_t +parse_period (cch_t * in_pz); + +static time_t +parse_non_iso8601 (cch_t * pz); + +/* + * Static declarations from pgusage.c + */ +static inline FILE * +open_tmp_usage(char ** buf); + +static inline char * +mk_pager_cmd(char const * fname); + +/* + * Static declarations from putshell.c + */ +static size_t +string_size(char const * scan, size_t nl_len); + +static char const * +print_quoted_apostrophes(char const * str); + +static void +print_quot_str(char const * str); + +static void +print_enumeration(tOptions * pOpts, tOptDesc * pOD); + +static void +print_membership(tOptions * pOpts, tOptDesc * pOD); + +static void +print_stacked_arg(tOptions * pOpts, tOptDesc * pOD); + +static void +print_reordering(tOptions * opts); + +/* + * Static declarations from reset.c + */ +static void +optionReset(tOptions * pOpts, tOptDesc * pOD); + +static void +optionResetEverything(tOptions * pOpts); + +/* + * Static declarations from restore.c + */ +static void +fixupSavedOptionArgs(tOptions * pOpts); + +/* + * Static declarations from save.c + */ +static char const * +find_dir_name(tOptions * opts, int * p_free); + +static char const * +find_file_name(tOptions * opts, int * p_free_name); + +static void +prt_entry(FILE * fp, tOptDesc * od, char const * l_arg, save_flags_mask_t save_fl); + +static void +prt_value(FILE * fp, int depth, tOptDesc * od, tOptionValue const * ovp); + +static void +prt_string(FILE * fp, char const * name, char const * pz); + +static void +prt_val_list(FILE * fp, char const * name, tArgList * al); + +static void +prt_nested(FILE * fp, tOptDesc * od, save_flags_mask_t save_fl); + +static void +remove_settings(tOptions * opts, char const * fname); + +static FILE * +open_sv_file(tOptions * opts, save_flags_mask_t save_fl); + +static void +prt_no_arg_opt(FILE * fp, tOptDesc * vod, tOptDesc * pod, save_flags_mask_t save_fl); + +static void +prt_str_arg(FILE * fp, tOptDesc * od, save_flags_mask_t save_fl); + +static void +prt_enum_arg(FILE * fp, tOptDesc * od, save_flags_mask_t save_fl); + +static void +prt_set_arg(FILE * fp, tOptDesc * od, save_flags_mask_t save_fl); + +static void +prt_file_arg(FILE * fp, tOptDesc * od, tOptions * opts, save_flags_mask_t save_fl); + +/* + * Static declarations from sort.c + */ +static tSuccess +must_arg(tOptions * opts, char * arg_txt, tOptState * pOS, + char ** opt_txt, uint32_t * opt_idx); + +static tSuccess +maybe_arg(tOptions * opts, char * arg_txt, tOptState * pOS, + char ** opt_txt, uint32_t * opt_idx); + +static tSuccess +short_opt_ck(tOptions * opts, char * arg_txt, tOptState * pOS, + char ** opt_txt, uint32_t * opt_idx); + +static void +optionSort(tOptions * opts); + +/* + * Static declarations from stack.c + */ +static void +addArgListEntry(void ** ppAL, void * entry); + +/* + * Static declarations from text_mmap.c + */ +static void +load_text_file(tmap_info_t * mapinfo, char const * pzFile); + +static void +validate_mmap(char const * fname, int prot, int flags, tmap_info_t * mapinfo); + +static void +close_mmap_files(tmap_info_t * mi); + +/* + * Static declarations from tokenize.c + */ +static void +copy_cooked(ch_t ** ppDest, char const ** ppSrc); + +static void +copy_raw(ch_t ** ppDest, char const ** ppSrc); + +static token_list_t * +alloc_token_list(char const * str); + +/* + * Static declarations from usage.c + */ +static unsigned int +parse_usage_flags(ao_flag_names_t const * fnt, char const * txt); + +static void +set_usage_flags(tOptions * opts, char const * flg_txt); + +static inline bool +do_gnu_usage(tOptions * pOpts); + +static inline bool +skip_misuse_usage(tOptions * pOpts); + +static void +print_offer_usage(tOptions * opts); + +static void +print_usage_details(tOptions * opts, int exit_code); + +static void +print_one_paragraph(char const * text, bool plain, FILE * fp); + +static void +prt_conflicts(tOptions * opts, tOptDesc * od); + +static void +prt_one_vendor(tOptions * opts, tOptDesc * od, + arg_types_t * argtp, char const * usefmt); + +static void +prt_vendor_opts(tOptions * opts, char const * title); + +static void +prt_extd_usage(tOptions * opts, tOptDesc * od, char const * title); + +static void +prt_ini_list(char const * const * papz, char const * ini_file, + char const * path_nm); + +static void +prt_preamble(tOptions * opts, tOptDesc * od, arg_types_t * at); + +static void +prt_one_usage(tOptions * opts, tOptDesc * od, arg_types_t * at); + +static void +prt_opt_usage(tOptions * opts, int ex_code, char const * title); + +static void +prt_prog_detail(tOptions * opts); + +static int +setGnuOptFmts(tOptions * opts, char const ** ptxt); + +static int +setStdOptFmts(tOptions * opts, char const ** ptxt); + +/* + * Static declarations from version.c + */ +static void +emit_first_line( + FILE * fp, char const * alt1, char const * alt2, char const * alt3); + +static void +emit_simple_ver(tOptions * o, FILE * fp); + +static void +emit_copy_full(tOptions * o, FILE * fp); + +static void +emit_copy_note(tOptions * opts, FILE * fp); + +static void +print_ver(tOptions * opts, tOptDesc * od, FILE * fp, bool call_exit); + +#endif /* AUTOOPTS_PROTO_H_GUARD */ diff --git a/src/libopts/putshell.c b/src/libopts/putshell.c new file mode 100644 index 0000000..84463dd --- /dev/null +++ b/src/libopts/putshell.c @@ -0,0 +1,495 @@ + +/** + * \file putshell.c + * + * This module will interpret the options set in the tOptions + * structure and print them to standard out in a fashion that + * will allow them to be interpreted by the Bourne or Korn shells. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/** + * Count the number of bytes required to represent a string as a + * compilable string. + * + * @param[in] scan the text to be rewritten as a C program text string. + * @param[in] nl_len the number of bytes used for each embedded newline. + * + * @returns the count, including the terminating NUL byte. + */ +static size_t +string_size(char const * scan, size_t nl_len) +{ + /* + * Start by counting the start and end quotes, plus the NUL. + */ + size_t res_ln = 3; + + for (;;) { + char ch = *(scan++); + if ((ch >= ' ') && (ch <= '~')) { + + /* + * a backslash allowance for double quotes and baskslashes + */ + res_ln += ((ch == '"') || (ch == '\\')) ? 2 : 1; + } + + /* + * When not a normal character, then count the characters + * required to represent whatever it is. + */ + else switch (ch) { + case NUL: + return res_ln; + + case NL: + res_ln += nl_len; + break; + + case HT: + case BEL: + case BS: + case FF: + case CR: + case VT: + res_ln += 2; + break; + + default: + res_ln += 4; /* text len for \xNN */ + } + } +} + +/*=export_func optionQuoteString + * private: + * + * what: Print a string as quoted text suitable for a C compiler. + * arg: + char const * + text + a block of text to quote + + * arg: + char const * + nl + line splice text + + * + * ret_type: char const * + * ret_desc: the allocated input string as a quoted string + * + * doc: + * This is for internal use by autogen and autoopts. + * It takes an input string and produces text the C compiler can process + * to produce an exact copy of the original string. + * The caller must deallocate the result. Standard C strings and + * K&R strings are distinguished by the "nl" string. +=*/ +char const * +optionQuoteString(char const * text, char const * nl) +{ + size_t nl_len = strlen(nl); + size_t out_sz = string_size(text, nl_len); + char * out; + char * res = out = AGALOC(out_sz, "quot str"); + + *(out++) = '"'; + + for (;;) { + unsigned char ch = (unsigned char)*text; + if ((ch >= ' ') && (ch <= '~')) { + if ((ch == '"') || (ch == '\\')) + /* + * We must escape these characters in the output string + */ + *(out++) = '\\'; + *(out++) = (char)ch; + + } else switch (ch) { +# define add_esc_ch(_ch) { *(out++) = '\\'; *(out++) = (_ch); } + case BEL: add_esc_ch('a'); break; + case BS: add_esc_ch('b'); break; + case HT: add_esc_ch('t'); break; + case VT: add_esc_ch('v'); break; + case FF: add_esc_ch('f'); break; + case CR: add_esc_ch('r'); break; + + case LF: + /* + * Place contiguous new-lines on a single line. + * The current character is a NL, check the next one. + */ + while (*++text == NL) + add_esc_ch('n'); + + /* + * Insert a splice before starting next line + */ + if (*text != NUL) { + memcpy(out, nl, nl_len); + out += nl_len; + + continue; /* text is already at the next character */ + } + + add_esc_ch('n'); + /* FALLTHROUGH */ + + case NUL: + /* + * End of string. Terminate the quoted output. If necessary, + * deallocate the text string. Return the scan resumption point. + */ + *(out++) = '"'; + *(out++) = NUL; +#ifndef NDEBUG + if ((size_t)(out - res) > out_sz) { + fputs(misguess_len, stderr); + option_exits(EXIT_FAILURE); + } +#endif + return res; + + default: + /* + * sprintf is safe here, because we already computed + * the amount of space we will be using. Assertion is above. + */ + out += sprintf(out, MK_STR_OCT_FMT, ch); + } + + text++; +# undef add_esc_ch + } +} + +/** + * Print out escaped apostorophes. + * + * @param[in] str the apostrophies to print + */ +static char const * +print_quoted_apostrophes(char const * str) +{ + while (*str == APOSTROPHE) { + fputs(QUOT_APOS, stdout); + str++; + } + return str; +} + +/** + * Print a single quote (apostrophe quoted) string. + * Other than somersaults for apostrophes, nothing else needs quoting. + * + * @param[in] str the string to print + */ +static void +print_quot_str(char const * str) +{ + /* + * Handle empty strings to make the rest of the logic simpler. + */ + if ((str == NULL) || (*str == NUL)) { + fputs(EMPTY_ARG, stdout); + return; + } + + /* + * Emit any single quotes/apostrophes at the start of the string and + * bail if that is all we need to do. + */ + str = print_quoted_apostrophes(str); + if (*str == NUL) + return; + + /* + * Start the single quote string + */ + fputc(APOSTROPHE, stdout); + for (;;) { + char const * pz = strchr(str, APOSTROPHE); + if (pz == NULL) + break; + + /* + * Emit the string up to the single quote (apostrophe) we just found. + */ + (void)fwrite(str, (size_t)(pz - str), (size_t)1, stdout); + + /* + * Close the current string, emit the apostrophes and re-open the + * string (IFF there is more text to print). + */ + fputc(APOSTROPHE, stdout); + str = print_quoted_apostrophes(pz); + if (*str == NUL) + return; + + fputc(APOSTROPHE, stdout); + } + + /* + * If we broke out of the loop, we must still emit the remaining text + * and then close the single quote string. + */ + fputs(str, stdout); + fputc(APOSTROPHE, stdout); +} + +static void +print_enumeration(tOptions * pOpts, tOptDesc * pOD) +{ + uintptr_t e_val = pOD->optArg.argEnum; + printf(OPT_VAL_FMT, pOpts->pzPROGNAME, pOD->pz_NAME); + + /* + * Convert value to string, print that and restore numeric value. + */ + (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD); + printf(QUOT_ARG_FMT, pOD->optArg.argString); + if (pOD->fOptState & OPTST_ALLOC_ARG) + AGFREE(pOD->optArg.argString); + pOD->optArg.argEnum = e_val; + + printf(OPT_END_FMT, pOpts->pzPROGNAME, pOD->pz_NAME); +} + +static void +print_membership(tOptions * pOpts, tOptDesc * pOD) +{ + char const * svstr = pOD->optArg.argString; + char const * pz; + uintptr_t val = 1; + printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, + (int)(uintptr_t)(pOD->optCookie)); + pOD->optCookie = VOIDP(~0UL); + (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD); + + pz = pOD->optArg.argString; + while (*pz != NUL) { + printf("readonly %s_", pOD->pz_NAME); + pz = SPN_PLUS_N_SPACE_CHARS(pz); + + for (;;) { + int ch = *(pz++); + if (IS_LOWER_CASE_CHAR(ch)) fputc(toupper(ch), stdout); + else if (IS_UPPER_CASE_CHAR(ch)) fputc(ch, stdout); + else if (IS_PLUS_N_SPACE_CHAR(ch)) goto name_done; + else if (ch == NUL) { pz--; goto name_done; } + else fputc('_', stdout); + } name_done:; + printf(SHOW_VAL_FMT, (unsigned long)val); + val <<= 1; + } + + AGFREE(pOD->optArg.argString); + pOD->optArg.argString = svstr; +} + +static void +print_stacked_arg(tOptions * pOpts, tOptDesc * pOD) +{ + tArgList * pAL = (tArgList *)pOD->optCookie; + char const ** ppz = pAL->apzArgs; + int ct = pAL->useCt; + + printf(zOptCookieCt, pOpts->pzPROGNAME, pOD->pz_NAME, ct); + + while (--ct >= 0) { + printf(ARG_BY_NUM_FMT, pOpts->pzPROGNAME, pOD->pz_NAME, + pAL->useCt - ct); + print_quot_str(*(ppz++)); + printf(EXPORT_ARG_FMT, pOpts->pzPROGNAME, pOD->pz_NAME, + pAL->useCt - ct); + } +} + +/** + * emit the arguments as readily parsed text. + * The program options are set by emitting the shell "set" command. + * + * @param[in] opts the program options structure + */ +static void +print_reordering(tOptions * opts) +{ + unsigned int ix; + + fputs(set_dash, stdout); + + for (ix = opts->curOptIdx; + ix < opts->origArgCt; + ix++) { + fputc(' ', stdout); + print_quot_str(opts->origArgVect[ ix ]); + } + fputs(init_optct, stdout); +} + +/*=export_func optionPutShell + * what: write a portable shell script to parse options + * private: + * arg: tOptions *, pOpts, the program options descriptor + * doc: This routine will emit portable shell script text for parsing + * the options described in the option definitions. +=*/ +void +optionPutShell(tOptions * pOpts) +{ + int optIx = 0; + + printf(zOptCtFmt, pOpts->curOptIdx-1); + + do { + tOptDesc * pOD = pOpts->pOptDesc + optIx; + + if ((pOD->fOptState & OPTST_NO_OUTPUT_MASK) != 0) + continue; + + /* + * Equivalence classes are hard to deal with. Where the + * option data wind up kind of squishes around. For the purposes + * of emitting shell state, they are not recommended, but we'll + * do something. I guess we'll emit the equivalenced-to option + * at the point in time when the base option is found. + */ + if (pOD->optEquivIndex != NO_EQUIVALENT) + continue; /* equivalence to a different option */ + + /* + * Equivalenced to a different option. Process the current option + * as the equivalenced-to option. Keep the persistent state bits, + * but copy over the set-state bits. + */ + if (pOD->optActualIndex != optIx) { + tOptDesc * p = pOpts->pOptDesc + pOD->optActualIndex; + p->optArg = pOD->optArg; + p->fOptState &= OPTST_PERSISTENT_MASK; + p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT_MASK; + printf(zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME); + pOD = p; + } + + /* + * If the argument type is a set membership bitmask, then we always + * emit the thing. We do this because it will always have some sort + * of bitmask value and we need to emit the bit values. + */ + if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) { + print_membership(pOpts, pOD); + continue; + } + + /* + * IF the option was either specified or it wakes up enabled, + * then we will emit information. Otherwise, skip it. + * The idea is that if someone defines an option to initialize + * enabled, we should tell our shell script that it is enabled. + */ + if (UNUSED_OPT(pOD) && DISABLED_OPT(pOD)) + continue; + + /* + * Handle stacked arguments + */ + if ( (pOD->fOptState & OPTST_STACKED) + && (pOD->optCookie != NULL) ) { + print_stacked_arg(pOpts, pOD); + continue; + } + + /* + * If the argument has been disabled, + * Then set its value to the disablement string + */ + if ((pOD->fOptState & OPTST_DISABLED) != 0) { + printf(zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME, + (pOD->pz_DisablePfx != NULL) + ? pOD->pz_DisablePfx : "false"); + continue; + } + + /* + * If the argument type is numeric, the last arg pointer + * is really the VALUE of the string that was pointed to. + */ + if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC) { + printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, + (int)pOD->optArg.argInt); + continue; + } + + /* + * If the argument type is an enumeration, then it is much + * like a text value, except we call the callback function + * to emit the value corresponding to the "optArg" number. + */ + if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) { + print_enumeration(pOpts, pOD); + continue; + } + + /* + * If the argument type is numeric, the last arg pointer + * is really the VALUE of the string that was pointed to. + */ + if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN) { + printf(zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME, + (pOD->optArg.argBool == 0) ? "false" : "true"); + continue; + } + + /* + * IF the option has an empty value, + * THEN we set the argument to the occurrence count. + */ + if ( (pOD->optArg.argString == NULL) + || (pOD->optArg.argString[0] == NUL) ) { + + printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME, + pOD->optOccCt); + continue; + } + + /* + * This option has a text value + */ + printf(OPT_VAL_FMT, pOpts->pzPROGNAME, pOD->pz_NAME); + print_quot_str(pOD->optArg.argString); + printf(OPT_END_FMT, pOpts->pzPROGNAME, pOD->pz_NAME); + + } while (++optIx < pOpts->presetOptCt ); + + if ( ((pOpts->fOptSet & OPTPROC_REORDER) != 0) + && (pOpts->curOptIdx < pOpts->origArgCt)) + print_reordering(pOpts); + + fflush(stdout); +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/putshell.c */ diff --git a/src/libopts/reset.c b/src/libopts/reset.c new file mode 100644 index 0000000..f7b58e8 --- /dev/null +++ b/src/libopts/reset.c @@ -0,0 +1,141 @@ + +/** + * \file reset.c + * + * Reset the option state to the compiled state. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +static void +optionReset(tOptions * pOpts, tOptDesc * pOD) +{ + pOD->fOptState &= OPTST_PERSISTENT_MASK; + pOD->fOptState |= OPTST_RESET; + if (pOD->pOptProc != NULL) + pOD->pOptProc(pOpts, pOD); + pOD->optArg.argString = + pOpts->originalOptArgArray[ pOD->optIndex ].argString; + pOD->optCookie = pOpts->originalOptArgCookie[ pOD->optIndex ]; + pOD->fOptState &= OPTST_PERSISTENT_MASK; +} + + +static void +optionResetEverything(tOptions * pOpts) +{ + tOptDesc * pOD = pOpts->pOptDesc; + int ct = pOpts->presetOptCt; + + for (;;) { + optionReset(pOpts, pOD); + + if (--ct <= 0) + break; + pOD++; + } +} + + +/*=export_func optionResetOpt + * private: + * + * what: Reset the value of an option + * arg: + tOptions * + pOpts + program options descriptor + + * arg: + tOptDesc * + pOptDesc + the descriptor for this arg + + * + * doc: + * This code will cause another option to be reset to its initial state. + * For example, --reset=foo will cause the --foo option to be reset. +=*/ +void +optionResetOpt(tOptions * pOpts, tOptDesc * pOD) +{ + static bool reset_active = false; + + tOptState opt_state = OPTSTATE_INITIALIZER(DEFINED); + char const * pzArg = pOD->optArg.argString; + tSuccess succ; + + if (pOpts <= OPTPROC_EMIT_LIMIT) + return; + + if (reset_active) + return; + + if ( (! HAS_originalOptArgArray(pOpts)) + || (pOpts->originalOptArgCookie == NULL)) + ao_bug(zno_reset); + + if ((pzArg == NULL) || (*pzArg == NUL)) { + fprintf(stderr, zreset_arg, pOpts->pzProgName, pOD->pz_Name); + pOpts->pUsageProc(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + assert(0 == 1); + } + + reset_active = true; + + if (pzArg[1] == NUL) { + if (*pzArg == '*') { + optionResetEverything(pOpts); + reset_active = false; + return; + } + + succ = opt_find_short(pOpts, (uint8_t)*pzArg, &opt_state); + if (! SUCCESSFUL(succ)) { + fprintf(stderr, zIllOptChr, pOpts->pzProgPath, *pzArg); + pOpts->pUsageProc(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + assert(0 == 1); + } + } else { + succ = opt_find_long(pOpts, (char *)pzArg, &opt_state); + if (! SUCCESSFUL(succ)) { + fprintf(stderr, zIllOptStr, pOpts->pzProgPath, pzArg); + pOpts->pUsageProc(pOpts, EXIT_FAILURE); + /* NOTREACHED */ + assert(0 == 1); + } + } + + /* + * We've found the indicated option. Turn off all non-persistent + * flags because we're forcing the option back to its initialized state. + * Call any callout procedure to handle whatever it needs to. + * Finally, clear the reset flag, too. + */ + optionReset(pOpts, opt_state.pOD); + reset_active = false; +} +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/reset.c */ diff --git a/src/libopts/restore.c b/src/libopts/restore.c new file mode 100644 index 0000000..36ebbce --- /dev/null +++ b/src/libopts/restore.c @@ -0,0 +1,223 @@ + +/* + * \file restore.c + * + * This module's routines will save the current option state to memory + * and restore it. If saved prior to the initial optionProcess call, + * then the initial state will be restored. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/* + * optionFixupSavedOpts Really, it just wipes out option state for + * options that are troublesome to copy. viz., stacked strings and + * hierarcicaly valued option args. We do duplicate string args that + * have been marked as allocated though. + */ +static void +fixupSavedOptionArgs(tOptions * pOpts) +{ + tOptions * p = pOpts->pSavedState; + tOptDesc * pOD = pOpts->pOptDesc; + int ct = pOpts->optCt; + + /* + * Make sure that allocated stuff is only referenced in the + * archived copy of the data. + */ + for (; ct-- > 0; pOD++) { + switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { + case OPARG_TYPE_STRING: + if (pOD->fOptState & OPTST_STACKED) { + tOptDesc * q = p->pOptDesc + (pOD - pOpts->pOptDesc); + q->optCookie = NULL; + } + if (pOD->fOptState & OPTST_ALLOC_ARG) { + tOptDesc * q = p->pOptDesc + (pOD - pOpts->pOptDesc); + AGDUPSTR(q->optArg.argString, pOD->optArg.argString, "arg"); + } + break; + + case OPARG_TYPE_HIERARCHY: + { + tOptDesc * q = p->pOptDesc + (pOD - pOpts->pOptDesc); + q->optCookie = NULL; + } + } + } +} + +/*=export_func optionSaveState + * + * what: saves the option state to memory + * arg: tOptions *, pOpts, program options descriptor + * + * doc: + * + * This routine will allocate enough memory to save the current option + * processing state. If this routine has been called before, that memory + * will be reused. You may only save one copy of the option state. This + * routine may be called before optionProcess(3AO). If you do call it + * before the first call to optionProcess, then you may also change the + * contents of argc/argv after you call optionRestore(3AO) + * + * In fact, more strongly put: it is safest to only use this function + * before having processed any options. In particular, the saving and + * restoring of stacked string arguments and hierarchical values is + * disabled. The values are not saved. + * + * err: If it fails to allocate the memory, + * it will print a message to stderr and exit. + * Otherwise, it will always succeed. +=*/ +void +optionSaveState(tOptions * pOpts) +{ + tOptions * p = (tOptions *)pOpts->pSavedState; + + if (p == NULL) { + size_t sz = sizeof(*pOpts) + + ((size_t)pOpts->optCt * sizeof(tOptDesc)); + p = AGALOC(sz, "saved option state"); + + pOpts->pSavedState = p; + } + + memcpy(p, pOpts, sizeof(*p)); + memcpy(p + 1, pOpts->pOptDesc, (size_t)p->optCt * sizeof(tOptDesc)); + + fixupSavedOptionArgs(pOpts); +} + + +/*=export_func optionRestore + * + * what: restore option state from memory copy + * arg: tOptions *, pOpts, program options descriptor + * + * doc: Copy back the option state from saved memory. + * The allocated memory is left intact, so this routine can be + * called repeatedly without having to call optionSaveState again. + * If you are restoring a state that was saved before the first call + * to optionProcess(3AO), then you may change the contents of the + * argc/argv parameters to optionProcess. + * + * err: If you have not called @code{optionSaveState} before, a diagnostic is + * printed to @code{stderr} and exit is called. +=*/ +void +optionRestore(tOptions * pOpts) +{ + tOptions * p = (tOptions *)pOpts->pSavedState; + + if (p == NULL) { + char const * pzName = pOpts->pzProgName; + if (pzName == NULL) { + pzName = pOpts->pzPROGNAME; + if (pzName == NULL) + pzName = zNil; + } + fprintf(stderr, zNoState, pzName); + option_exits(EXIT_FAILURE); + } + + pOpts->pSavedState = NULL; + optionFree(pOpts); + + memcpy(pOpts, p, sizeof(*p)); + memcpy(pOpts->pOptDesc, p+1, (size_t)p->optCt * sizeof(tOptDesc)); + pOpts->pSavedState = p; + + fixupSavedOptionArgs(pOpts); +} + +/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ + +/*=export_func optionFree + * + * what: free allocated option processing memory + * arg: tOptions *, pOpts, program options descriptor + * + * doc: AutoOpts sometimes allocates memory and puts pointers to it in the + * option state structures. This routine deallocates all such memory. + * + * err: As long as memory has not been corrupted, + * this routine is always successful. +=*/ +void +optionFree(tOptions * pOpts) +{ + free_saved_state: + { + tOptDesc * p = pOpts->pOptDesc; + int ct = pOpts->optCt; + do { + if (p->fOptState & OPTST_ALLOC_ARG) { + AGFREE(p->optArg.argString); + p->optArg.argString = NULL; + p->fOptState &= ~OPTST_ALLOC_ARG; + } + + switch (OPTST_GET_ARGTYPE(p->fOptState)) { + case OPARG_TYPE_STRING: +#ifdef WITH_LIBREGEX + if ( (p->fOptState & OPTST_STACKED) + && (p->optCookie != NULL)) { + p->optArg.argString = ".*"; + optionUnstackArg(pOpts, p); + } +#else + /* leak memory */; +#endif + break; + + case OPARG_TYPE_HIERARCHY: + if (p->optCookie != NULL) + unload_arg_list(p->optCookie); + break; + } + + p->optCookie = NULL; + } while (p++, --ct > 0); + } + if (pOpts->pSavedState != NULL) { + tOptions * p = (tOptions *)pOpts->pSavedState; + memcpy(pOpts, p, sizeof(*p)); + memcpy(pOpts->pOptDesc, p+1, (size_t)p->optCt * sizeof(tOptDesc)); + AGFREE(pOpts->pSavedState); + pOpts->pSavedState = NULL; + goto free_saved_state; + } +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/restore.c */ diff --git a/src/libopts/save-flags.c b/src/libopts/save-flags.c new file mode 100644 index 0000000..d295170 --- /dev/null +++ b/src/libopts/save-flags.c @@ -0,0 +1,248 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (save-flags.c) + * + * It has been AutoGen-ed + * From the definitions /tmp/.ag-ufBbQe/save-flags.def + * and the template file str2enum + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name ``Bruce Korb'' nor the name of any other + * contributor may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * str2enum IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "save-flags.h" +#include +#ifndef MISSING_INTTYPES_H +# include +#endif + +typedef enum { + SVFL_BNM_DEFAULT = 0, + SVFL_BNM_USAGE = 1, + SVFL_BNM_UPDATE = 2, + SVFL_COUNT_BNM +} save_flags_enum_t; + +static save_flags_enum_t +find_save_flags_bnm(char const * str, size_t len); + + +#include +#include +#ifndef NUL +#define NUL '\0' +#endif + +/* ANSI-C code produced by gperf version 3.1 */ +/* Command-line: gperf save-flags.gp */ +/* Computed positions: -k'' */ + + +# if 0 /* gperf build options: */ +// %struct-type +// %language=ANSI-C +// %includes +// %global-table +// %omit-struct-type +// %readonly-tables +// %compare-strncmp +// +// %define slot-name svfl_name +// %define hash-function-name save_flags_hash +// %define lookup-function-name find_save_flags_name +// %define word-array-name save_flags_table +// %define initializer-suffix ,SVFL_COUNT_BNM +// +# endif + +#include "save-flags.h" +typedef struct { + char const * svfl_name; + save_flags_enum_t svfl_id; +} save_flags_map_t; +#include + +/* maximum key range = 3, duplicates = 0 */ + +static unsigned int +save_flags_hash (register const char *str, register size_t len) +{ + (void)str; + (void)len; + return len; +} + +static const save_flags_map_t save_flags_table[] = + { + {"",SVFL_COUNT_BNM}, {"",SVFL_COUNT_BNM}, + {"",SVFL_COUNT_BNM}, {"",SVFL_COUNT_BNM}, + {"",SVFL_COUNT_BNM}, + {"usage", SVFL_BNM_USAGE}, + {"update", SVFL_BNM_UPDATE}, + {"default", SVFL_BNM_DEFAULT} + }; + +static inline const save_flags_map_t * +find_save_flags_name (register const char *str, register size_t len) +{ + if (len <= 7 && len >= 5) + { + register unsigned int key = (int)save_flags_hash (str, len); + + if (key <= 7) + { + register const char *s = save_flags_table[key].svfl_name; + + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') + return &save_flags_table[key]; + } + } + return 0; +} + +/** + * Convert a command (keyword) to a save_flags_enum_t enumeration value. + * + * @param[in] str a string that should start with a known key word. + * @param[in] len the provided length of the keyword at \a str. + * @returns the enumeration value. + * If not found, that value is SVFL_COUNT_BNM. + */ +static save_flags_enum_t +find_save_flags_bnm(char const * str, size_t len) +{ + save_flags_map_t const * map; + + map = find_save_flags_name(str, (unsigned int)len); + if (map != NULL) + return map->svfl_id; + /* Check for a partial match */ + { + /* + * Indexes of valid save_flags_table entries in sorted order: + */ + static unsigned int const ix_map[] = { + 7, 6, 5 }; + save_flags_enum_t res = SVFL_COUNT_BNM; + static int const HI = (sizeof(ix_map) / sizeof(ix_map[0])) - 1; + int lo = 0; + int hi = HI; + int av; + int cmp; + + for (;;) { + av = (hi + lo) / 2; + map = save_flags_table + ix_map[av]; + cmp = strncmp(map->svfl_name, str, len); + if (cmp == 0) break; + if (cmp > 0) + hi = av - 1; + else lo = av + 1; + if (lo > hi) + return SVFL_COUNT_BNM; + } + res = map->svfl_id; + /* + * If we have an exact match, accept it. + */ + if (map->svfl_name[len] == NUL) + return res; + /* + * Check for a duplicate partial match (a partial match + * with a higher or lower index than "av". + */ + if (av < HI) { + map = save_flags_table + ix_map[av + 1]; + if (strncmp(map->svfl_name, str, len) == 0) + return SVFL_COUNT_BNM; + } + if (av > 0) { + map = save_flags_table + ix_map[av - 1]; + if (strncmp(map->svfl_name, str, len) == 0) + return SVFL_COUNT_BNM; + } + return res; + } +} + +/** + * Convert a string to a save_flags_mask_t mask. + * Bit names prefixed with a hyphen have the bit removed from the mask. + * If the string starts with a '-', '+' or '|' character, then + * the old value is used as a base, otherwise the result mask + * is initialized to zero. Separating bit names with '+' or '|' + * characters is optional. By default, the bits are "or"-ed into the + * result. + * + * @param[in] str string with a list of bit names + * @param[in] old previous value, used if \a str starts with a '+' or '-'. + * + * @returns an unsigned integer with the bits set. + */ +save_flags_mask_t +save_flags_str2mask(char const * str, save_flags_mask_t old) +{ + static char const white[] = ", \t\f"; + static char const name_chars[] = + "adefglpstu" + "ADEFGLPSTU"; + + save_flags_mask_t res = 0; + int have_data = 0; + + for (;;) { + save_flags_enum_t val; + unsigned int val_len; + unsigned int invert = 0; + + str += strspn(str, white); + switch (*str) { + case NUL: return res; + case '-': case '~': + invert = 1; + /* FALLTHROUGH */ + + case '+': case '|': + if (have_data == 0) + res = old; + + str += 1 + strspn(str + 1, white); + if (*str == NUL) + return 0; + } + + val_len = strspn(str, name_chars); + if (val_len == 0) + return 0; + val = find_save_flags_bnm(str, val_len); + if (val == SVFL_COUNT_BNM) + return 0; + if (invert) + res &= ~((save_flags_mask_t)1 << val); + else + res |= (save_flags_mask_t)1 << val; + have_data = 1; + str += val_len; + } +} +/* end of save-flags.c */ diff --git a/src/libopts/save-flags.h b/src/libopts/save-flags.h new file mode 100644 index 0000000..dcfe0c9 --- /dev/null +++ b/src/libopts/save-flags.h @@ -0,0 +1,68 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (save-flags.h) + * + * It has been AutoGen-ed + * From the definitions /tmp/.ag-ufBbQe/save-flags.def + * and the template file str2enum + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name ``Bruce Korb'' nor the name of any other + * contributor may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * str2enum IS PROVIDED BY Bruce Korb ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bruce Korb OR ANY OTHER CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Command/Keyword Dispatcher + */ +#ifndef STR2ENUM_SAVE_FLAGS_H_GUARD +#define STR2ENUM_SAVE_FLAGS_H_GUARD 1 +#include +#include + +/** integral type for holding save_flags masks */ +typedef uint32_t save_flags_mask_t; + +/** bits defined for save_flags_mask_t */ +/** include default values in commentary */ +#define SVFL_DEFAULT 0x0001U +/** include usage text in commentary */ +#define SVFL_USAGE 0x0002U +/** replace or append state */ +#define SVFL_UPDATE 0x0004U + +/** bits in USAGE_DEFAULT mask: + * usage default */ +#define SVFL_USAGE_DEFAULT_MASK 0x0003U + +/** all bits in save_flags_mask_t masks */ +#define SVFL_MASK_ALL 0x0007U + +/** no bits in save_flags_mask_t */ +#define SVFL_NONE 0x0000U + +/** buffer size needed to hold all bit names for save_flags_mask_t masks */ +#define MAX_SAVE_FLAGS_NAME_SIZE 21 + +extern save_flags_mask_t +save_flags_str2mask(char const * str, save_flags_mask_t old); + +#endif /* STR2ENUM_SAVE_FLAGS_H_GUARD */ +/* end of save-flags.h */ diff --git a/src/libopts/save.c b/src/libopts/save.c new file mode 100644 index 0000000..8b1fba9 --- /dev/null +++ b/src/libopts/save.c @@ -0,0 +1,916 @@ + +/* + * \file save.c + * + * This module's routines will take the currently set options and + * store them into an ".rc" file for re-interpretation the next + * time the invoking program is run. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ +#include "save-flags.h" + +/** + * find the config file directory name + * + * @param opts the options descriptor + * @param p_free tell caller if name was allocated or not + */ +static char const * +find_dir_name(tOptions * opts, int * p_free) +{ + char const * dir; + + if ( (opts->specOptIdx.save_opts == NO_EQUIVALENT) + || (opts->specOptIdx.save_opts == 0)) + return NULL; + + dir = opts->pOptDesc[ opts->specOptIdx.save_opts ].optArg.argString; + if ((dir != NULL) && (*dir != NUL)) { + char const * pz = strchr(dir, '>'); + if (pz == NULL) + return dir; + while (*(++pz) == '>') ; + pz += strspn(pz, " \t"); + dir = pz; + if (*dir != NUL) + return dir; + } + + if (opts->papzHomeList == NULL) + return NULL; + + /* + * This function only works if there is a directory where + * we can stash the RC (INI) file. + */ + for (int idx = 0;; idx++) { + char f_name[ AG_PATH_MAX+1 ]; + + dir = opts->papzHomeList[idx]; + + switch (*dir) { + case '$': + break; + case NUL: + continue; + default: + return dir; + } + if (optionMakePath(f_name, (int)sizeof(f_name), dir, opts->pzProgPath)) { + *p_free = true; + AGDUPSTR(dir, f_name, "homerc"); + return dir; + } + } + return NULL; +} + +/** + * Find the name of the save-the-options file + * + * @param opts the options descriptor + * @param p_free_name tell caller if name was allocated or not + */ +static char const * +find_file_name(tOptions * opts, int * p_free_name) +{ + struct stat stBuf; + int free_dir_name = 0; + + char const * res = find_dir_name(opts, &free_dir_name); + if (res == NULL) + return res; + + /* + * See if we can find the specified directory. We use a once-only loop + * structure so we can bail out early. + */ + if (stat(res, &stBuf) != 0) do { + char z[AG_PATH_MAX]; + char * dirchp; + + /* + * IF we could not, check to see if we got a full + * path to a file name that has not been created yet. + */ + if (errno != ENOENT) { + bogus_name: + fprintf(stderr, zsave_warn, opts->pzProgName, res); + fprintf(stderr, zNoStat, errno, strerror(errno), res); + if (free_dir_name) + AGFREE(res); + return NULL; + } + + /* + * Strip off the last component, stat the remaining string and + * that string must name a directory + */ + dirchp = strrchr(res, DIRCH); + if (dirchp == NULL) { + stBuf.st_mode = S_IFREG; + break; /* found directory -- viz., "." */ + } + + if ((size_t)(dirchp - res) >= sizeof(z)) + goto bogus_name; + + memcpy(z, res, (size_t)(dirchp - res)); + z[dirchp - res] = NUL; + + if ((stat(z, &stBuf) != 0) || ! S_ISDIR(stBuf.st_mode)) + goto bogus_name; + stBuf.st_mode = S_IFREG; /* file within this directory */ + } while (false); + + /* + * IF what we found was a directory, + * THEN tack on the config file name + */ + if (S_ISDIR(stBuf.st_mode)) { + + { + size_t sz = strlen(res) + strlen(opts->pzRcName) + 2; + char * pzPath = (char *)AGALOC(sz, "file name"); + if ( snprintf(pzPath, sz, "%s/%s", res, opts->pzRcName) + >= (int)sz) + option_exits(EXIT_FAILURE); + + if (free_dir_name) + AGFREE(res); + res = pzPath; + free_dir_name = 1; + } + + /* + * IF we cannot stat the object for any reason other than + * it does not exist, then we bail out + */ + if (stat(res, &stBuf) != 0) { + if (errno != ENOENT) { + fprintf(stderr, zsave_warn, opts->pzProgName, res); + fprintf(stderr, zNoStat, errno, strerror(errno), + res); + AGFREE(res); + return NULL; + } + + /* + * It does not exist yet, but it will be a regular file + */ + stBuf.st_mode = S_IFREG; + } + } + + /* + * Make sure that whatever we ultimately found, that it either is + * or will soon be a file. + */ + if (! S_ISREG(stBuf.st_mode)) { + fprintf(stderr, zsave_warn, opts->pzProgName, res); + if (free_dir_name) + AGFREE(res); + return NULL; + } + + /* + * Get rid of the old file + */ + *p_free_name = free_dir_name; + return res; +} + +/** + * print one option entry to the save file. + * + * @param[in] fp the file pointer for the save file + * @param[in] od the option descriptor to print + * @param[in] l_arg the last argument for the option + * @param[in] save_fl include usage in comments + */ +static void +prt_entry(FILE * fp, tOptDesc * od, char const * l_arg, save_flags_mask_t save_fl) +{ + int space_ct; + + if (save_fl & SVFL_USAGE) + fprintf(fp, ao_name_use_fmt, od->pz_Name, od->pzText); + if (UNUSED_OPT(od) && (save_fl & SVFL_DEFAULT)) + fputs(ao_default_use, fp); + + /* + * There is an argument. Pad the name so values line up. + * Not disabled *OR* this got equivalenced to another opt, + * then use current option name. + * Otherwise, there must be a disablement name. + */ + { + char const * pz = + (od->pz_DisableName == NULL) + ? od->pz_Name + : (DISABLED_OPT(od) + ? od->pz_DisableName + : ((od->optEquivIndex == NO_EQUIVALENT) + ? od->pz_Name : od->pz_DisableName) + ); + + space_ct = 17 - strlen(pz); + fputs(pz, fp); + } + + if ( (l_arg == NULL) + && (OPTST_GET_ARGTYPE(od->fOptState) != OPARG_TYPE_NUMERIC)) + goto end_entry; + + fputs(" = ", fp); + while (space_ct-- > 0) fputc(' ', fp); + + /* + * IF the option is numeric only, + * THEN the char pointer is really the number + */ + if (OPTST_GET_ARGTYPE(od->fOptState) == OPARG_TYPE_NUMERIC) + fprintf(fp, "%d", (int)(intptr_t)l_arg); + + else { + for (;;) { + char const * eol = strchr(l_arg, NL); + + /* + * IF this is the last line + * THEN bail and print it + */ + if (eol == NULL) + break; + + /* + * Print the continuation and the text from the current line + */ + (void)fwrite(l_arg, (size_t)(eol - l_arg), (size_t)1, fp); + l_arg = eol+1; /* advance the Last Arg pointer */ + fputs("\\\n", fp); + } + + /* + * Terminate the entry + */ + fputs(l_arg, fp); + } + +end_entry: + fputc(NL, fp); +} + +/** + * print an option's value + * + * @param[in] fp the file pointer for the save file + * @param[in] od the option descriptor to print + */ +static void +prt_value(FILE * fp, int depth, tOptDesc * od, tOptionValue const * ovp) +{ + while (--depth >= 0) + putc(' ', fp), putc(' ', fp); + + switch (ovp->valType) { + default: + case OPARG_TYPE_NONE: + fprintf(fp, NULL_ATR_FMT, ovp->pzName); + break; + + case OPARG_TYPE_STRING: + prt_string(fp, ovp->pzName, ovp->v.strVal); + break; + + case OPARG_TYPE_ENUMERATION: + case OPARG_TYPE_MEMBERSHIP: + if (od != NULL) { + uint32_t opt_state = od->fOptState; + uintptr_t val = od->optArg.argEnum; + char const * typ = (ovp->valType == OPARG_TYPE_ENUMERATION) + ? "keyword" : "set-membership"; + + fprintf(fp, TYPE_ATR_FMT, ovp->pzName, typ); + + /* + * This is a magic incantation that will convert the + * bit flag values back into a string suitable for printing. + */ + (*(od->pOptProc))(OPTPROC_RETURN_VALNAME, od ); + if (od->optArg.argString != NULL) { + fputs(od->optArg.argString, fp); + + if (ovp->valType != OPARG_TYPE_ENUMERATION) { + /* + * set membership strings get allocated + */ + AGFREE(od->optArg.argString); + } + } + + od->optArg.argEnum = val; + od->fOptState = opt_state; + fprintf(fp, END_XML_FMT, ovp->pzName); + break; + } + /* FALLTHROUGH */ + + case OPARG_TYPE_NUMERIC: + fprintf(fp, NUMB_ATR_FMT, ovp->pzName, ovp->v.longVal); + break; + + case OPARG_TYPE_BOOLEAN: + fprintf(fp, BOOL_ATR_FMT, ovp->pzName, + ovp->v.boolVal ? "true" : "false"); + break; + + case OPARG_TYPE_HIERARCHY: + prt_val_list(fp, ovp->pzName, ovp->v.nestVal); + break; + } +} + +/** + * Print a string value in XML format + * + * @param[in] fp the file pointer for the save file + */ +static void +prt_string(FILE * fp, char const * name, char const * pz) +{ + fprintf(fp, OPEN_XML_FMT, name); + for (;;) { + int ch = ((int)*(pz++)) & 0xFF; + + switch (ch) { + case NUL: goto string_done; + + case '&': + case '<': + case '>': +#if __GNUC__ >= 4 + case 1 ... (' ' - 1): + case ('~' + 1) ... 0xFF: +#endif + emit_special_char(fp, ch); + break; + + default: +#if __GNUC__ < 4 + if ( ((ch >= 1) && (ch <= (' ' - 1))) + || ((ch >= ('~' + 1)) && (ch <= 0xFF)) ) { + emit_special_char(fp, ch); + break; + } +#endif + putc(ch, fp); + } + } string_done:; + fprintf(fp, END_XML_FMT, name); +} + +/** + * Print an option that can have multiple values in XML format + * + * @param[in] fp file pointer + */ +static void +prt_val_list(FILE * fp, char const * name, tArgList * al) +{ + static int depth = 1; + + int sp_ct; + int opt_ct; + void ** opt_list; + + if (al == NULL) + return; + opt_ct = al->useCt; + opt_list = (void **)al->apzArgs; + + if (opt_ct <= 0) { + fprintf(fp, OPEN_CLOSE_FMT, name); + return; + } + + fprintf(fp, NESTED_OPT_FMT, name); + + depth++; + while (--opt_ct >= 0) { + tOptionValue const * ovp = *(opt_list++); + + prt_value(fp, depth, NULL, ovp); + } + depth--; + + for (sp_ct = depth; --sp_ct >= 0;) + putc(' ', fp), putc(' ', fp); + fprintf(fp, "\n", name); +} + +/** + * printed a nested/hierarchical value + * + * @param[in] fp file pointer + * @param[in] od option descriptor + * @param[in] save_fl include usage in comments + */ +static void +prt_nested(FILE * fp, tOptDesc * od, save_flags_mask_t save_fl) +{ + int opt_ct; + tArgList * al = od->optCookie; + void ** opt_list; + + if (save_fl & SVFL_USAGE) + fprintf(fp, ao_name_use_fmt, od->pz_Name, od->pzText); + + /* + * Never show a default value if a hierarchical value is empty. + */ + if (UNUSED_OPT(od) || (al == NULL)) + return; + + opt_ct = al->useCt; + opt_list = (void **)al->apzArgs; + + if (opt_ct <= 0) + return; + + do { + tOptionValue const * base = *(opt_list++); + tOptionValue const * ovp = optionGetValue(base, NULL); + + if (ovp == NULL) + continue; + + fprintf(fp, NESTED_OPT_FMT, od->pz_Name); + + do { + prt_value(fp, 1, od, ovp); + + } while (ovp = optionNextValue(base, ovp), + ovp != NULL); + + fprintf(fp, "\n", od->pz_Name); + } while (--opt_ct > 0); +} + +/** + * remove the current program settings + * + * @param[in] opts the program options structure + * @param[in] fname the save file name + */ +static void +remove_settings(tOptions * opts, char const * fname) +{ + size_t const name_len = strlen(opts->pzProgName); + tmap_info_t map_info; + char * text = text_mmap(fname, PROT_READ|PROT_WRITE, MAP_PRIVATE, &map_info); + char * scan = text; + + for (;;) { + char * next = scan = strstr(scan, zCfgProg); + if (scan == NULL) + goto leave; + + scan = SPN_WHITESPACE_CHARS(scan + zCfgProg_LEN); + if ( (strneqvcmp(scan, opts->pzProgName, (int)name_len) == 0) + && (IS_END_XML_TOKEN_CHAR(scan[name_len])) ) { + + scan = next; + break; + } + } + + /* + * If not NULL, "scan" points to the "pzProgName, fname); + fprintf(stderr, zNoCreat, errno, strerror(errno), fname); + if (free_name) + AGFREE(fname); + return fp; + } + + if (free_name) + AGFREE(fname); + } + + do { + struct stat sbuf; + if (fstat(fileno(fp), &sbuf) < 0) + break; + + if (sbuf.st_size > zPresetFile_LEN) { + /* non-zero size implies save_fl is non-zero */ + fprintf(fp, zFmtProg, opts->pzProgName); + return fp; + } + } while (false); + + /* + * We have a new file. Insert a header + */ + fputs("# ", fp); + { + char const * e = strchr(opts->pzUsageTitle, NL); + if (e++ != NULL) + fwrite(opts->pzUsageTitle, 1, e - opts->pzUsageTitle, fp); + } + + { + time_t cur_time = time(NULL); + char * time_str = ctime(&cur_time); + + fprintf(fp, zPresetFile, time_str); +#ifdef HAVE_ALLOCATED_CTIME + /* + * The return values for ctime(), localtime(), and gmtime() + * normally point to static data that is overwritten by each call. + * The test to detect allocated ctime, so we leak the memory. + */ + AGFREE(time_str); +#endif + } + if (save_fl != 0) + fprintf(fp, zFmtProg, opts->pzProgName); + return fp; +} + +/** + * print option without an arg + * + * @param[in] fp file pointer + * @param[in] vod value option descriptor + * @param[in] pod primary option descriptor + * @param[in] save_fl include usage in comments + */ +static void +prt_no_arg_opt(FILE * fp, tOptDesc * vod, tOptDesc * pod, save_flags_mask_t save_fl) +{ + /* + * The aliased to argument indicates whether or not the option + * is "disabled". However, the original option has the name + * string, so we get that there, not with "vod". + */ + char const * pznm = + (DISABLED_OPT(vod)) ? pod->pz_DisableName : pod->pz_Name; + /* + * If the option was disabled and the disablement name is NULL, + * then the disablement was caused by aliasing. + * Use the name as the string to emit. + */ + if (pznm == NULL) + pznm = pod->pz_Name; + + if (save_fl & SVFL_USAGE) + fprintf(fp, ao_name_use_fmt, pod->pz_Name, pod->pzText); + if (UNUSED_OPT(pod) && (save_fl & SVFL_DEFAULT)) + fputs(ao_default_use, fp); + + fprintf(fp, "%s\n", pznm); +} + +/** + * print the string valued argument(s). + * + * @param[in] fp file pointer + * @param[in] od value option descriptor + * @param[in] save_fl include usage in comments + */ +static void +prt_str_arg(FILE * fp, tOptDesc * od, save_flags_mask_t save_fl) +{ + if (UNUSED_OPT(od) || ((od->fOptState & OPTST_STACKED) == 0)) { + char const * arg = od->optArg.argString; + if (arg == NULL) + arg = "''"; + prt_entry(fp, od, arg, save_fl); + + } else { + tArgList * pAL = (tArgList *)od->optCookie; + int uct = pAL->useCt; + char const ** ppz = pAL->apzArgs; + + /* + * un-disable multiple copies of disabled options. + */ + if (uct > 1) + od->fOptState &= ~OPTST_DISABLED; + + while (uct-- > 0) { + prt_entry(fp, od, *(ppz++), save_fl); + save_fl &= ~SVFL_USAGE; + } + } +} + +/** + * print the string value of an enumeration. + * + * @param[in] fp the file pointer to write to + * @param[in] od the option descriptor with the enumerated value + * @param[in] save_fl include usage in comments + */ +static void +prt_enum_arg(FILE * fp, tOptDesc * od, save_flags_mask_t save_fl) +{ + uintptr_t val = od->optArg.argEnum; + + /* + * This is a magic incantation that will convert the + * bit flag values back into a string suitable for printing. + */ + (*(od->pOptProc))(OPTPROC_RETURN_VALNAME, od); + prt_entry(fp, od, VOIDP(od->optArg.argString), save_fl); + + od->optArg.argEnum = val; +} + +/** + * Print the bits set in a bit mask option. + * + * We call the option handling function with a magic value for + * the options pointer and it allocates and fills in the string. + * We print that with a call to prt_entry(). + * + * @param[in] fp the file pointer to write to + * @param[in] od the option descriptor with a bit mask value type + * @param[in] save_fl include usage in comments + */ +static void +prt_set_arg(FILE * fp, tOptDesc * od, save_flags_mask_t save_fl) +{ + char * list = optionMemberList(od); + size_t len = strlen(list); + char * buf = (char *)AGALOC(len + 3, "dir name"); + *buf= '='; + memcpy(buf+1, list, len + 1); + prt_entry(fp, od, buf, save_fl); + AGFREE(buf); + AGFREE(list); +} + +/** + * figure out what the option file name argument is. + * If one can be found, call prt_entry() to emit it. + * + * @param[in] fp the file pointer to write to. + * @param[in] od the option descriptor with a bit mask value type + * @param[in] opts the program options descriptor + * @param[in] save_fl include usage in comments + */ +static void +prt_file_arg(FILE * fp, tOptDesc * od, tOptions * opts, save_flags_mask_t save_fl) +{ + /* + * If the cookie is not NULL, then it has the file name, period. + * Otherwise, if we have a non-NULL string argument, then.... + */ + if (od->optCookie != NULL) + prt_entry(fp, od, od->optCookie, save_fl); + + else if (HAS_originalOptArgArray(opts)) { + char const * orig = + opts->originalOptArgArray[od->optIndex].argString; + + if (od->optArg.argString == orig) { + if (save_fl) + fprintf(fp, ao_name_use_fmt, od->pz_Name, od->pzText); + return; + } + + prt_entry(fp, od, od->optArg.argString, save_fl); + + } else if (save_fl) + fprintf(fp, ao_name_use_fmt, od->pz_Name, od->pzText); +} + +/*=export_func optionSaveFile + * + * what: saves the option state to a file + * + * arg: tOptions *, opts, program options descriptor + * + * doc: + * + * This routine will save the state of option processing to a file. The name + * of that file can be specified with the argument to the @code{--save-opts} + * option, or by appending the @code{rcfile} attribute to the last + * @code{homerc} attribute. If no @code{rcfile} attribute was specified, it + * will default to @code{.@i{programname}rc}. If you wish to specify another + * file, you should invoke the @code{SET_OPT_SAVE_OPTS(@i{filename})} macro. + * + * The recommend usage is as follows: + * @example + * optionProcess(&progOptions, argc, argv); + * if (i_want_a_non_standard_place_for_this) + * SET_OPT_SAVE_OPTS("myfilename"); + * optionSaveFile(&progOptions); + * @end example + * + * err: + * + * If no @code{homerc} file was specified, this routine will silently return + * and do nothing. If the output file cannot be created or updated, a message + * will be printed to @code{stderr} and the routine will return. +=*/ +void +optionSaveFile(tOptions * opts) +{ + tOptDesc * od; + int ct; + FILE * fp; + save_flags_mask_t save_flags = SVFL_NONE; + + do { + char * temp_str; + char const * dir = opts->pOptDesc[ opts->specOptIdx.save_opts ].optArg.argString; + size_t flen; + + if (dir == NULL) + break; + temp_str = strchr(dir, '>'); + if (temp_str == NULL) + break; + if (temp_str[1] == '>') + save_flags = SVFL_UPDATE; + flen = (temp_str - dir); + if (flen == 0) + break; + temp_str = AGALOC(flen + 1, "flag search str"); + memcpy(temp_str, dir, flen); + temp_str[flen] = NUL; + save_flags |= save_flags_str2mask(temp_str, SVFL_NONE); + AGFREE(temp_str); + } while (false); + + fp = open_sv_file(opts, save_flags & SVFL_UPDATE); + if (fp == NULL) + return; + + /* + * FOR each of the defined options, ... + */ + ct = opts->presetOptCt; + od = opts->pOptDesc; + do { + tOptDesc * vod; + + /* + * Equivalenced options get picked up when the equivalenced-to + * option is processed. And do not save options with any state + * bits in the DO_NOT_SAVE collection + * + * ** option cannot be preset + * #define OPTST_NO_INIT 0x0000100U + * ** disable from cmd line + * #define OPTST_NO_COMMAND 0x2000000U + * ** alias for other option + * #define OPTST_ALIAS 0x8000000U + */ + if ((od->fOptState & OPTST_DO_NOT_SAVE_MASK) != 0) + continue; + + if ( (od->optEquivIndex != NO_EQUIVALENT) + && (od->optEquivIndex != od->optIndex)) + continue; + + if (UNUSED_OPT(od) && ((save_flags & SVFL_USAGE_DEFAULT_MASK) == SVFL_NONE)) + continue; + + /* + * The option argument data are found at the equivalenced-to option, + * but the actual option argument type comes from the original + * option descriptor. Be careful! + */ + vod = ((od->fOptState & OPTST_EQUIVALENCE) != 0) + ? (opts->pOptDesc + od->optActualIndex) : od; + + switch (OPTST_GET_ARGTYPE(od->fOptState)) { + case OPARG_TYPE_NONE: + prt_no_arg_opt(fp, vod, od, save_flags); + break; + + case OPARG_TYPE_NUMERIC: + prt_entry(fp, vod, VOIDP(vod->optArg.argInt), save_flags); + break; + + case OPARG_TYPE_STRING: + prt_str_arg(fp, vod, save_flags); + break; + + case OPARG_TYPE_ENUMERATION: + prt_enum_arg(fp, vod, save_flags); + break; + + case OPARG_TYPE_MEMBERSHIP: + prt_set_arg(fp, vod, save_flags); + break; + + case OPARG_TYPE_BOOLEAN: + prt_entry(fp, vod, vod->optArg.argBool ? "true" : "false", save_flags); + break; + + case OPARG_TYPE_HIERARCHY: + prt_nested(fp, vod, save_flags); + break; + + case OPARG_TYPE_FILE: + prt_file_arg(fp, vod, opts, save_flags); + break; + + default: + break; /* cannot handle - skip it */ + } + } while (od++, (--ct > 0)); + + fclose(fp); +} +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/save.c */ diff --git a/src/libopts/sort.c b/src/libopts/sort.c new file mode 100644 index 0000000..b4bd5cb --- /dev/null +++ b/src/libopts/sort.c @@ -0,0 +1,326 @@ + +/* + * \file sort.c + * + * This module implements argument sorting. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/* + * "must_arg" and "maybe_arg" are really similar. The biggest + * difference is that "may" will consume the next argument only if it + * does not start with a hyphen and "must" will consume it, hyphen or not. + */ +static tSuccess +must_arg(tOptions * opts, char * arg_txt, tOptState * pOS, + char ** opt_txt, uint32_t * opt_idx) +{ + /* + * An option argument is required. Long options can either have + * a separate command line argument, or an argument attached by + * the '=' character. Figure out which. + */ + switch (pOS->optType) { + case TOPT_SHORT: + /* + * See if an arg string follows the flag character. If not, + * the next arg must be the option argument. + */ + if (*arg_txt != NUL) + return SUCCESS; + break; + + case TOPT_LONG: + /* + * See if an arg string has already been assigned (glued on + * with an `=' character). If not, the next is the opt arg. + */ + if (pOS->pzOptArg != NULL) + return SUCCESS; + break; + + default: + return FAILURE; + } + if (opts->curOptIdx >= opts->origArgCt) + return FAILURE; + + opt_txt[ (*opt_idx)++ ] = opts->origArgVect[ (opts->curOptIdx)++ ]; + return SUCCESS; +} + +static tSuccess +maybe_arg(tOptions * opts, char * arg_txt, tOptState * pOS, + char ** opt_txt, uint32_t * opt_idx) +{ + /* + * An option argument is optional. + */ + switch (pOS->optType) { + case TOPT_SHORT: + /* + * IF nothing is glued on after the current flag character, + * THEN see if there is another argument. If so and if it + * does *NOT* start with a hyphen, then it is the option arg. + */ + if (*arg_txt != NUL) + return SUCCESS; + break; + + case TOPT_LONG: + /* + * Look for an argument if we don't already have one (glued on + * with a `=' character) + */ + if (pOS->pzOptArg != NULL) + return SUCCESS; + break; + + default: + return FAILURE; + } + if (opts->curOptIdx >= opts->origArgCt) + return PROBLEM; + + arg_txt = opts->origArgVect[ opts->curOptIdx ]; + if (*arg_txt != '-') + opt_txt[ (*opt_idx)++ ] = opts->origArgVect[ (opts->curOptIdx)++ ]; + return SUCCESS; +} + +/* + * Process a string of short options glued together. If the last one + * does or may take an argument, the do the argument processing and leave. + */ +static tSuccess +short_opt_ck(tOptions * opts, char * arg_txt, tOptState * pOS, + char ** opt_txt, uint32_t * opt_idx) +{ + while (*arg_txt != NUL) { + if (FAILED(opt_find_short(opts, (uint8_t)*arg_txt, pOS))) + return FAILURE; + + /* + * See if we can have an arg. + */ + if (OPTST_GET_ARGTYPE(pOS->pOD->fOptState) == OPARG_TYPE_NONE) { + arg_txt++; + + } else if (pOS->pOD->fOptState & OPTST_ARG_OPTIONAL) { + /* + * Take an argument if it is not attached and it does not + * start with a hyphen. + */ + if (arg_txt[1] != NUL) + return SUCCESS; + + arg_txt = opts->origArgVect[ opts->curOptIdx ]; + if (*arg_txt != '-') + opt_txt[ (*opt_idx)++ ] = + opts->origArgVect[ (opts->curOptIdx)++ ]; + return SUCCESS; + + } else { + /* + * IF we need another argument, be sure it is there and + * take it. + */ + if (arg_txt[1] == NUL) { + if (opts->curOptIdx >= opts->origArgCt) + return FAILURE; + opt_txt[ (*opt_idx)++ ] = + opts->origArgVect[ (opts->curOptIdx)++ ]; + } + return SUCCESS; + } + } + return SUCCESS; +} + +/* + * If the program wants sorted options (separated operands and options), + * then this routine will to the trick. + */ +static void +optionSort(tOptions * opts) +{ + char ** opt_txt; + char ** ppzOpds; + uint32_t optsIdx = 0; + uint32_t opdsIdx = 0; + + tOptState os = OPTSTATE_INITIALIZER(DEFINED); + + /* + * Disable for POSIX conformance, or if there are no operands. + */ + if ( (getenv("POSIXLY_CORRECT") != NULL) + || NAMED_OPTS(opts)) + return; + + /* + * Make sure we can allocate two full-sized arg vectors. + */ + opt_txt = malloc(opts->origArgCt * sizeof(char *)); + if (opt_txt == NULL) + goto exit_no_mem; + + ppzOpds = malloc(opts->origArgCt * sizeof(char *)); + if (ppzOpds == NULL) { + free(opt_txt); + goto exit_no_mem; + } + + opts->curOptIdx = 1; + opts->pzCurOpt = NULL; + + /* + * Now, process all the options from our current position onward. + * (This allows interspersed options and arguments for the few + * non-standard programs that require it.) + */ + for (;;) { + char * arg_txt; + tSuccess res; + + /* + * If we're out of arguments, we're done. Join the option and + * operand lists into the original argument vector. + */ + if (opts->curOptIdx >= opts->origArgCt) { + errno = 0; + goto joinLists; + } + + arg_txt = opts->origArgVect[ opts->curOptIdx ]; + if (*arg_txt != '-') { + ppzOpds[ opdsIdx++ ] = opts->origArgVect[ (opts->curOptIdx)++ ]; + continue; + } + + switch (arg_txt[1]) { + case NUL: + /* + * A single hyphen is an operand. + */ + ppzOpds[ opdsIdx++ ] = opts->origArgVect[ (opts->curOptIdx)++ ]; + continue; + + case '-': + /* + * Two consecutive hypens. Put them on the options list and then + * _always_ force the remainder of the arguments to be operands. + */ + if (arg_txt[2] == NUL) { + opt_txt[ optsIdx++ ] = + opts->origArgVect[ (opts->curOptIdx)++ ]; + goto restOperands; + } + res = opt_find_long(opts, arg_txt+2, &os); + break; + + default: + /* + * If short options are not allowed, then do long + * option processing. Otherwise the character must be a + * short (i.e. single character) option. + */ + if ((opts->fOptSet & OPTPROC_SHORTOPT) == 0) { + res = opt_find_long(opts, arg_txt+1, &os); + } else { + res = opt_find_short(opts, (uint8_t)arg_txt[1], &os); + } + break; + } + if (FAILED(res)) { + errno = EINVAL; + goto freeTemps; + } + + /* + * We've found an option. Add the argument to the option list. + * Next, we have to see if we need to pull another argument to be + * used as the option argument. + */ + opt_txt[ optsIdx++ ] = opts->origArgVect[ (opts->curOptIdx)++ ]; + + if (OPTST_GET_ARGTYPE(os.pOD->fOptState) == OPARG_TYPE_NONE) { + /* + * No option argument. If we have a short option here, + * then scan for short options until we get to the end + * of the argument string. + */ + if ( (os.optType == TOPT_SHORT) + && FAILED(short_opt_ck(opts, arg_txt+2, &os, opt_txt, + &optsIdx)) ) { + errno = EINVAL; + goto freeTemps; + } + + } else if (os.pOD->fOptState & OPTST_ARG_OPTIONAL) { + switch (maybe_arg(opts, arg_txt+2, &os, opt_txt, &optsIdx)) { + case FAILURE: errno = EIO; goto freeTemps; + case PROBLEM: errno = 0; goto joinLists; + } + + } else { + switch (must_arg(opts, arg_txt+2, &os, opt_txt, &optsIdx)) { + case PROBLEM: + case FAILURE: errno = EIO; goto freeTemps; + } + } + } /* for (;;) */ + + restOperands: + while (opts->curOptIdx < opts->origArgCt) + ppzOpds[ opdsIdx++ ] = opts->origArgVect[ (opts->curOptIdx)++ ]; + + joinLists: + if (optsIdx > 0) + memcpy(opts->origArgVect + 1, opt_txt, + (size_t)optsIdx * sizeof(char *)); + if (opdsIdx > 0) + memcpy(opts->origArgVect + 1 + optsIdx, ppzOpds, + (size_t)opdsIdx * sizeof(char *)); + + freeTemps: + free(opt_txt); + free(ppzOpds); + return; + + exit_no_mem: + errno = ENOMEM; + return; +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/sort.c */ diff --git a/src/libopts/stack.c b/src/libopts/stack.c new file mode 100644 index 0000000..39a328a --- /dev/null +++ b/src/libopts/stack.c @@ -0,0 +1,267 @@ + +/** + * \file stack.c + * + * This is a special option processing routine that will save the + * argument to an option in a FIFO queue. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +#ifdef WITH_LIBREGEX +# include REGEX_HEADER +#endif + +/*=export_func optionUnstackArg + * private: + * + * what: Remove option args from a stack + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + od + the descriptor for this arg + + * + * doc: + * Invoked for options that are equivalenced to stacked options. +=*/ +void +optionUnstackArg(tOptions * opts, tOptDesc * od) +{ + tArgList * arg_list; + + if (INQUERY_CALL(opts, od)) + return; + + arg_list = (tArgList *)od->optCookie; + + /* + * IF we don't have any stacked options, + * THEN indicate that we don't have any of these options + */ + if (arg_list == NULL) { + od->fOptState &= OPTST_PERSISTENT_MASK; + if ((od->fOptState & OPTST_INITENABLED) == 0) + od->fOptState |= OPTST_DISABLED; + return; + } + +#ifdef WITH_LIBREGEX + { + regex_t re; + int i, ct, dIdx; + + if (regcomp(&re, od->optArg.argString, REG_NOSUB) != 0) + return; + + /* + * search the list for the entry(s) to remove. Entries that + * are removed are *not* copied into the result. The source + * index is incremented every time. The destination only when + * we are keeping a define. + */ + for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) { + char const * pzSrc = arg_list->apzArgs[ i ]; + char * pzEq = strchr(pzSrc, '='); + int res; + + + if (pzEq != NULL) + *pzEq = NUL; + + res = regexec(&re, pzSrc, (size_t)0, NULL, 0); + switch (res) { + case 0: + /* + * Remove this entry by reducing the in-use count + * and *not* putting the string pointer back into + * the list. + */ + AGFREE(pzSrc); + arg_list->useCt--; + break; + + default: + case REG_NOMATCH: + if (pzEq != NULL) + *pzEq = '='; + + /* + * IF we have dropped an entry + * THEN we have to move the current one. + */ + if (dIdx != i) + arg_list->apzArgs[ dIdx ] = pzSrc; + dIdx++; + } + } + + regfree(&re); + } +#else /* not WITH_LIBREGEX */ + { + int i, ct, dIdx; + + /* + * search the list for the entry(s) to remove. Entries that + * are removed are *not* copied into the result. The source + * index is incremented every time. The destination only when + * we are keeping a define. + */ + for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) { + const char * pzSrc = arg_list->apzArgs[ i ]; + char * pzEq = strchr(pzSrc, '='); + + if (pzEq != NULL) + *pzEq = NUL; + + if (strcmp(pzSrc, od->optArg.argString) == 0) { + /* + * Remove this entry by reducing the in-use count + * and *not* putting the string pointer back into + * the list. + */ + AGFREE(pzSrc); + arg_list->useCt--; + } else { + if (pzEq != NULL) + *pzEq = '='; + + /* + * IF we have dropped an entry + * THEN we have to move the current one. + */ + if (dIdx != i) + arg_list->apzArgs[ dIdx ] = pzSrc; + dIdx++; + } + } + } +#endif /* WITH_LIBREGEX */ + /* + * IF we have unstacked everything, + * THEN indicate that we don't have any of these options + */ + if (arg_list->useCt == 0) { + od->fOptState &= OPTST_PERSISTENT_MASK; + if ((od->fOptState & OPTST_INITENABLED) == 0) + od->fOptState |= OPTST_DISABLED; + AGFREE(arg_list); + od->optCookie = NULL; + } +} + + +/* + * Put an entry into an argument list. The first argument points to + * a pointer to the argument list structure. It gets passed around + * as an opaque address. + */ +static void +addArgListEntry(void ** ppAL, void * entry) +{ + tArgList * pAL = *(void **)ppAL; + + /* + * IF we have never allocated one of these, + * THEN allocate one now + */ + if (pAL == NULL) { + pAL = (tArgList *)AGALOC(sizeof(*pAL), "new option arg stack"); + if (pAL == NULL) + return; + pAL->useCt = 0; + pAL->allocCt = MIN_ARG_ALLOC_CT; + *ppAL = VOIDP(pAL); + } + + /* + * ELSE if we are out of room + * THEN make it bigger + */ + else if (pAL->useCt >= pAL->allocCt) { + size_t sz = sizeof(*pAL); + pAL->allocCt += INCR_ARG_ALLOC_CT; + + /* + * The base structure contains space for MIN_ARG_ALLOC_CT + * pointers. We subtract it off to find our augment size. + */ + sz += sizeof(char *) * ((size_t)pAL->allocCt - MIN_ARG_ALLOC_CT); + pAL = (tArgList *)AGREALOC(VOIDP(pAL), sz, "expanded opt arg stack"); + if (pAL == NULL) + return; + *ppAL = VOIDP(pAL); + } + + /* + * Insert the new argument into the list + */ + pAL->apzArgs[ (pAL->useCt)++ ] = entry; +} + + +/*=export_func optionStackArg + * private: + * + * what: put option args on a stack + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + od + the descriptor for this arg + + * + * doc: + * Keep an entry-ordered list of option arguments. +=*/ +void +optionStackArg(tOptions * opts, tOptDesc * od) +{ + char * pz; + + if (INQUERY_CALL(opts, od)) + return; + + if ((od->fOptState & OPTST_RESET) != 0) { + tArgList * arg_list = od->optCookie; + int ix; + if (arg_list == NULL) + return; + + ix = arg_list->useCt; + while (--ix >= 0) + AGFREE(arg_list->apzArgs[ix]); + AGFREE(arg_list); + + } else { + if (od->optArg.argString == NULL) + return; + + AGDUPSTR(pz, od->optArg.argString, "stack arg"); + addArgListEntry(&(od->optCookie), VOIDP(pz)); + } +} +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/stack.c */ diff --git a/src/libopts/stdnoreturn.in.h b/src/libopts/stdnoreturn.in.h new file mode 100644 index 0000000..bf46c08 --- /dev/null +++ b/src/libopts/stdnoreturn.in.h @@ -0,0 +1,60 @@ +/* A substitute for ISO C11 . + + Copyright 2012-2018 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1, 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, see . */ + +/* Written by Paul Eggert. */ + +#ifndef noreturn + +/* ISO C11 for platforms that lack it. + + References: + ISO C11 (latest free draft + ) + section 7.23 */ + +/* The definition of _Noreturn is copied here. */ + +#if 1200 <= _MSC_VER || defined __CYGWIN__ +/* On MSVC, standard include files contain declarations like + __declspec (noreturn) void abort (void); + "#define noreturn _Noreturn" would cause this declaration to be rewritten + to the invalid + __declspec (__declspec (noreturn)) void abort (void); + + Similarly, on Cygwin, standard include files contain declarations like + void __cdecl abort (void) __attribute__ ((noreturn)); + "#define noreturn _Noreturn" would cause this declaration to be rewritten + to the invalid + void __cdecl abort (void) __attribute__ ((__attribute__ ((__noreturn__)))); + + Instead, define noreturn to empty, so that such declarations are rewritten to + __declspec () void abort (void); + or + void __cdecl abort (void) __attribute__ (()); + respectively. This gives up on noreturn's advice to the compiler but at + least it is valid code. */ +# define noreturn /*empty*/ +#else +# define noreturn _Noreturn +#endif + +/* Did he ever return? + No he never returned + And his fate is still unlearn'd ... + -- Steiner J, Hawes BL. M.T.A. (1949) */ + +#endif /* noreturn */ diff --git a/src/libopts/streqvcmp.c b/src/libopts/streqvcmp.c new file mode 100644 index 0000000..53477d6 --- /dev/null +++ b/src/libopts/streqvcmp.c @@ -0,0 +1,284 @@ + +/** + * \file streqvcmp.c + * + * String Equivalence Comparison + * + * These routines allow any character to be mapped to any other + * character before comparison. In processing long option names, + * the characters "-", "_" and "^" all need to be equivalent + * (because they are treated so by different development environments). + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + * + * This array is designed for mapping upper and lower case letter + * together for a case independent comparison. The mappings are + * based upon ascii character sequences. + */ + static unsigned char charmap[] = { + NUL, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, '\a', + '\b', '\t', NL, '\v', '\f', '\r', 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + + ' ', '!', '"', '#', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + + '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '[', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', 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, +}; + + +/*=export_func strneqvcmp + * + * what: compare two strings with an equivalence mapping + * + * arg: + char const * + str1 + first string + + * arg: + char const * + str2 + second string + + * arg: + int + ct + compare length + + * + * ret_type: int + * ret_desc: the difference between two differing characters + * + * doc: + * + * Using a character mapping, two strings are compared for "equivalence". + * Each input character is mapped to a comparison character and the + * mapped-to characters are compared for the two NUL terminated input strings. + * The comparison is limited to @code{ct} bytes. + * This function name is mapped to option_strneqvcmp so as to not conflict + * with the POSIX name space. + * + * err: none checked. Caller responsible for seg faults. +=*/ +int +strneqvcmp(char const * s1, char const * s2, int ct) +{ + for (; ct > 0; --ct) { + unsigned char u1 = (unsigned char) *s1++; + unsigned char u2 = (unsigned char) *s2++; + int dif; + if (u1 == u2) { + if (u1 == NUL) + return 0; + continue; + } + + dif = charmap[ u1 ] - charmap[ u2 ]; + + if (dif != 0) + return dif; + + if (u1 == NUL) + return 0; + } + + return 0; +} + + +/*=export_func streqvcmp + * + * what: compare two strings with an equivalence mapping + * + * arg: + char const * + str1 + first string + + * arg: + char const * + str2 + second string + + * + * ret_type: int + * ret_desc: the difference between two differing characters + * + * doc: + * + * Using a character mapping, two strings are compared for "equivalence". + * Each input character is mapped to a comparison character and the + * mapped-to characters are compared for the two NUL terminated input strings. + * This function name is mapped to option_streqvcmp so as to not conflict + * with the POSIX name space. + * + * err: none checked. Caller responsible for seg faults. +=*/ +int +streqvcmp(char const * s1, char const * s2) +{ + for (;;) { + unsigned char u1 = (unsigned char) *s1++; + unsigned char u2 = (unsigned char) *s2++; + int dif; + if (u1 == u2) { + if (u1 == NUL) + return 0; + continue; + } + + dif = charmap[ u1 ] - charmap[ u2 ]; + + if (dif != 0) + return dif; + + if (u1 == NUL) + return 0; + } +} + + +/*=export_func streqvmap + * + * what: Set the character mappings for the streqv functions + * + * arg: + char + from + Input character + + * arg: + char + to + Mapped-to character + + * arg: + int + ct + compare length + + * + * doc: + * + * Set the character mapping. If the count (@code{ct}) is set to zero, then + * the map is cleared by setting all entries in the map to their index + * value. Otherwise, the "@code{From}" character is mapped to the "@code{To}" + * character. If @code{ct} is greater than 1, then @code{From} and @code{To} + * are incremented and the process repeated until @code{ct} entries have been + * set. For example, + * @example + * streqvmap('a', 'A', 26); + * @end example + * @noindent + * will alter the mapping so that all English lower case letters + * will map to upper case. + * + * This function name is mapped to option_streqvmap so as to not conflict + * with the POSIX name space. + * + * err: none. +=*/ +void +streqvmap(char from, char to, int ct) +{ + if (ct == 0) { + ct = sizeof(charmap) - 1; + do { + charmap[ct] = (unsigned char)ct; + } while (--ct >= 0); + } + + else { + unsigned int i_to = (int)to & 0xFF; + unsigned int i_from = (int)from & 0xFF; + + do { + charmap[i_from] = (unsigned char)i_to; + i_from++; + i_to++; + if ((i_from >= sizeof(charmap)) || (i_to >= sizeof(charmap))) + break; + } while (--ct > 0); + } +} + + +/*=export_func strequate + * + * what: map a list of characters to the same value + * + * arg: + char const * + ch_list + characters to equivalence + + * + * doc: + * + * Each character in the input string get mapped to the first character + * in the string. + * This function name is mapped to option_strequate so as to not conflict + * with the POSIX name space. + * + * err: none. +=*/ +void +strequate(char const * s) +{ + if ((s != NULL) && (*s != NUL)) { + unsigned char equiv = (unsigned char)*s; + while (*s != NUL) + charmap[(unsigned char)*(s++)] = equiv; + } +} + + +/*=export_func strtransform + * + * what: convert a string into its mapped-to value + * + * arg: + char * + dest + output string + + * arg: + char const * + src + input string + + * + * doc: + * + * Each character in the input string is mapped and the mapped-to + * character is put into the output. + * This function name is mapped to option_strtransform so as to not conflict + * with the POSIX name space. + * + * The source and destination may be the same. + * + * err: none. +=*/ +void +strtransform(char * d, char const * s) +{ + do { + *(d++) = (char)charmap[(unsigned char)*s]; + } while (*(s++) != NUL); +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/streqvcmp.c */ diff --git a/src/libopts/text_mmap.c b/src/libopts/text_mmap.c new file mode 100644 index 0000000..1109308 --- /dev/null +++ b/src/libopts/text_mmap.c @@ -0,0 +1,382 @@ +/** + * @file text_mmap.c + * + * Map a text file, ensuring the text always has an ending NUL byte. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ +#if defined(HAVE_MMAP) +# ifndef MAP_ANONYMOUS +# ifdef MAP_ANON +# define MAP_ANONYMOUS MAP_ANON +# endif +# endif + +# if ! defined(MAP_ANONYMOUS) && ! defined(HAVE_DEV_ZERO) + /* + * We must have either /dev/zero or anonymous mapping for + * this to work. + */ +# undef HAVE_MMAP + +# else +# ifdef _SC_PAGESIZE +# define GETPAGESIZE() sysconf(_SC_PAGESIZE) +# else +# define GETPAGESIZE() getpagesize() +# endif +# endif +#endif + +/* + * Some weird systems require that a specifically invalid FD number + * get passed in as an argument value. Which value is that? Well, + * as everybody knows, if open(2) fails, it returns -1, so that must + * be the value. :) + */ +#define AO_INVALID_FD -1 + +#define FILE_WRITABLE(_prt,_flg) \ + ( (_prt & PROT_WRITE) \ + && ((_flg & (MAP_SHARED|MAP_PRIVATE)) == MAP_SHARED)) +#define MAP_FAILED_PTR (VOIDP(MAP_FAILED)) + +/** + * Load the contents of a text file. There are two separate implementations, + * depending up on whether mmap(3) is available. + * + * If not available, malloc the file length plus one byte. Read it in + * and NUL terminate. + * + * If available, first check to see if the text file size is a multiple of a + * page size. If it is, map the file size plus an extra page from either + * anonymous memory or from /dev/zero. Then map the file text on top of the + * first pages of the anonymous/zero pages. Otherwise, just map the file + * because there will be NUL bytes provided at the end. + * + * @param mapinfo a structure holding everything we need to know + * about the mapping. + * + * @param pzFile name of the file, for error reporting. + */ +static void +load_text_file(tmap_info_t * mapinfo, char const * pzFile) +{ +#if ! defined(HAVE_MMAP) + mapinfo->txt_data = AGALOC(mapinfo->txt_size+1, "file text"); + if (mapinfo->txt_data == NULL) { + mapinfo->txt_errno = ENOMEM; + return; + } + + { + size_t sz = mapinfo->txt_size; + char * pz = mapinfo->txt_data; + + while (sz > 0) { + ssize_t rdct = read(mapinfo->txt_fd, pz, sz); + if (rdct <= 0) { + mapinfo->txt_errno = errno; + fserr_warn("libopts", "read", pzFile); + free(mapinfo->txt_data); + return; + } + + pz += rdct; + sz -= rdct; + } + + *pz = NUL; + } + + mapinfo->txt_errno = 0; + +#else /* HAVE mmap */ + size_t const pgsz = (size_t)GETPAGESIZE(); + void * map_addr = NULL; + + (void)pzFile; + + mapinfo->txt_full_size = (mapinfo->txt_size + pgsz) & ~(pgsz - 1); + if (mapinfo->txt_full_size == (mapinfo->txt_size + pgsz)) { + /* + * The text is a multiple of a page boundary. We must map an + * extra page so the text ends with a NUL. + */ +#if defined(MAP_ANONYMOUS) + map_addr = mmap(NULL, mapinfo->txt_full_size, PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE, AO_INVALID_FD, 0); +#else + mapinfo->txt_zero_fd = open("/dev/zero", O_RDONLY); + + if (mapinfo->txt_zero_fd == AO_INVALID_FD) { + mapinfo->txt_errno = errno; + return; + } + map_addr = mmap(NULL, mapinfo->txt_full_size, PROT_READ|PROT_WRITE, + MAP_PRIVATE, mapinfo->txt_zero_fd, 0); +#endif + if (map_addr == MAP_FAILED_PTR) { + mapinfo->txt_errno = errno; + return; + } + mapinfo->txt_flags |= MAP_FIXED; + } + + mapinfo->txt_data = + mmap(map_addr, mapinfo->txt_size, mapinfo->txt_prot, + mapinfo->txt_flags, mapinfo->txt_fd, 0); + + if (mapinfo->txt_data == MAP_FAILED_PTR) + mapinfo->txt_errno = errno; +#endif /* HAVE_MMAP */ +} + +/** + * Make sure all the parameters are correct: we have a file name that + * is a text file that we can read. + * + * @param fname the text file to map + * @param prot the memory protections requested (read/write/etc.) + * @param flags mmap flags + * @param mapinfo a structure holding everything we need to know + * about the mapping. + */ +static void +validate_mmap(char const * fname, int prot, int flags, tmap_info_t * mapinfo) +{ + memset(mapinfo, 0, sizeof(*mapinfo)); +#if defined(HAVE_MMAP) && ! defined(MAP_ANONYMOUS) + mapinfo->txt_zero_fd = AO_INVALID_FD; +#endif + mapinfo->txt_fd = AO_INVALID_FD; + mapinfo->txt_prot = prot; + mapinfo->txt_flags = flags; + + /* + * Map mmap flags and protections into open flags and do the open. + */ + { + /* + * See if we will be updating the file. If we can alter the memory + * and if we share the data and we are *not* copy-on-writing the data, + * then our updates will show in the file, so we must open with + * write access. + */ + int o_flag = +#ifdef _WIN32 + O_BINARY | +#endif + FILE_WRITABLE(prot, flags) ? O_RDWR : O_RDONLY; + + /* + * If you're not sharing the file and you are writing to it, + * then don't let anyone else have access to the file. + */ + if (((flags & MAP_SHARED) == 0) && (prot & PROT_WRITE)) + o_flag |= O_EXCL; + + mapinfo->txt_fd = open(fname, o_flag); + if (mapinfo->txt_fd < 0) { + mapinfo->txt_errno = errno; + mapinfo->txt_fd = AO_INVALID_FD; + return; + } + } + + /* + * Make sure we can stat the regular file. Save the file size. + */ + { + struct stat sb; + if (fstat(mapinfo->txt_fd, &sb) != 0) { + mapinfo->txt_errno = errno; + close(mapinfo->txt_fd); + return; + } + + if (! S_ISREG(sb.st_mode)) { + mapinfo->txt_errno = errno = EINVAL; + close(mapinfo->txt_fd); + return; + } + + mapinfo->txt_size = (size_t)sb.st_size; + } + + if (mapinfo->txt_fd == AO_INVALID_FD) + mapinfo->txt_errno = errno; +} + +/** + * Close any files opened by the mapping. + * + * @param mi a structure holding everything we need to know about the map. + */ +static void +close_mmap_files(tmap_info_t * mi) +{ + if (mi->txt_fd == AO_INVALID_FD) + return; + + close(mi->txt_fd); + mi->txt_fd = AO_INVALID_FD; + +#if defined(HAVE_MMAP) && ! defined(MAP_ANONYMOUS) + if (mi->txt_zero_fd == AO_INVALID_FD) + return; + + close(mi->txt_zero_fd); + mi->txt_zero_fd = AO_INVALID_FD; +#endif +} + +/*=export_func text_mmap + * private: + * + * what: map a text file with terminating NUL + * + * arg: char const *, pzFile, name of the file to map + * arg: int, prot, mmap protections (see mmap(2)) + * arg: int, flags, mmap flags (see mmap(2)) + * arg: tmap_info_t *, mapinfo, returned info about the mapping + * + * ret-type: void * + * ret-desc: The mmaped data address + * + * doc: + * + * This routine will mmap a file into memory ensuring that there is at least + * one @file{NUL} character following the file data. It will return the + * address where the file contents have been mapped into memory. If there is a + * problem, then it will return @code{MAP_FAILED} and set @code{errno} + * appropriately. + * + * The named file does not exist, @code{stat(2)} will set @code{errno} as it + * will. If the file is not a regular file, @code{errno} will be + * @code{EINVAL}. At that point, @code{open(2)} is attempted with the access + * bits set appropriately for the requested @code{mmap(2)} protections and flag + * bits. On failure, @code{errno} will be set according to the documentation + * for @code{open(2)}. If @code{mmap(2)} fails, @code{errno} will be set as + * that routine sets it. If @code{text_mmap} works to this point, a valid + * address will be returned, but there may still be ``issues''. + * + * If the file size is not an even multiple of the system page size, then + * @code{text_map} will return at this point and @code{errno} will be zero. + * Otherwise, an anonymous map is attempted. If not available, then an attempt + * is made to @code{mmap(2)} @file{/dev/zero}. If any of these fail, the + * address of the file's data is returned, bug @code{no} @file{NUL} characters + * are mapped after the end of the data. + * + * see: mmap(2), open(2), stat(2) + * + * err: Any error code issued by mmap(2), open(2), stat(2) is possible. + * Additionally, if the specified file is not a regular file, then + * errno will be set to @code{EINVAL}. + * + * example: + * #include + * tmap_info_t mi; + * int no_nul; + * void * data = text_mmap("file", PROT_WRITE, MAP_PRIVATE, &mi); + * if (data == MAP_FAILED) return; + * no_nul = (mi.txt_size == mi.txt_full_size); + * << use the data >> + * text_munmap(&mi); +=*/ +void * +text_mmap(char const * pzFile, int prot, int flags, tmap_info_t * mi) +{ + validate_mmap(pzFile, prot, flags, mi); + if (mi->txt_errno != 0) + return MAP_FAILED_PTR; + + load_text_file(mi, pzFile); + + if (mi->txt_errno == 0) + return mi->txt_data; + + close_mmap_files(mi); + + errno = mi->txt_errno; + mi->txt_data = MAP_FAILED_PTR; + return mi->txt_data; +} + + +/*=export_func text_munmap + * private: + * + * what: unmap the data mapped in by text_mmap + * + * arg: tmap_info_t *, mapinfo, info about the mapping + * + * ret-type: int + * ret-desc: -1 or 0. @code{errno} will have the error code. + * + * doc: + * + * This routine will unmap the data mapped in with @code{text_mmap} and close + * the associated file descriptors opened by that function. + * + * see: munmap(2), close(2) + * + * err: Any error code issued by munmap(2) or close(2) is possible. +=*/ +int +text_munmap(tmap_info_t * mi) +{ + errno = 0; + +#ifdef HAVE_MMAP + (void)munmap(mi->txt_data, mi->txt_full_size); + +#else // don't HAVE_MMAP + /* + * IF the memory is writable *AND* it is not private (copy-on-write) + * *AND* the memory is "sharable" (seen by other processes) + * THEN rewrite the data. Emulate mmap visibility. + */ + if ( FILE_WRITABLE(mi->txt_prot, mi->txt_flags) + && (lseek(mi->txt_fd, 0, SEEK_SET) >= 0) ) + write(mi->txt_fd, mi->txt_data, mi->txt_size); + + free(mi->txt_data); +#endif /* HAVE_MMAP */ + + mi->txt_errno = errno; + close_mmap_files(mi); + + return mi->txt_errno; +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/text_mmap.c */ diff --git a/src/libopts/time.c b/src/libopts/time.c new file mode 100644 index 0000000..debaa7a --- /dev/null +++ b/src/libopts/time.c @@ -0,0 +1,145 @@ + +/** + * \file time.c + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/*=export_func optionTimeVal + * private: + * + * what: process an option with a time duration. + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + od + the descriptor for this arg + + * + * doc: + * Decipher a time duration value. +=*/ +void +optionTimeVal(tOptions * opts, tOptDesc * od) +{ + time_t val; + + if (INQUERY_CALL(opts, od)) + return; + + val = parse_duration(od->optArg.argString); + if (val == BAD_TIME) { + fprintf(stderr, zNotDuration, opts->pzProgName, od->optArg.argString); + if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) + (*(opts->pUsageProc))(opts, EXIT_FAILURE); + } + + if (od->fOptState & OPTST_ALLOC_ARG) { + AGFREE(od->optArg.argString); + od->fOptState &= ~OPTST_ALLOC_ARG; + } + + od->optArg.argInt = (long)val; +} + +/*=export_func optionTimeDate + * private: + * + * what: process an option with a time and date. + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + od + the descriptor for this arg + + * + * doc: + * Decipher a time and date value. +=*/ +void +optionTimeDate(tOptions * opts, tOptDesc * od) +{ +#if defined(HAVE_GETDATE_R) && defined(HAVE_PUTENV) + if (INQUERY_CALL(opts, od)) + return; + + if ((! HAS_pzPkgDataDir(opts)) || (opts->pzPkgDataDir == NULL)) + goto default_action; + + /* + * Export the DATEMSK environment variable. getdate_r() uses it to + * find the file with the strptime formats. If we cannot find the file + * we need ($PKGDATADIR/datemsk), then fall back to just a time duration. + */ + { + static char * envptr = NULL; + + if (envptr == NULL) { + static char const fmt[] = "DATEMSK=%s/datemsk"; + size_t sz = sizeof(fmt) + strlen(opts->pzPkgDataDir); + envptr = AGALOC(sz, fmt); + if (snprintf(envptr, sz, fmt, opts->pzPkgDataDir) >= (int)sz) + option_exits(EXIT_FAILURE); + + putenv(envptr); + } + + if (access(envptr+8, R_OK) != 0) + goto default_action; + } + + /* + * Convert the date to a time since the epoch and stash it in a long int. + */ + { + struct tm stm; + time_t tm; + + if (getdate_r(od->optArg.argString, &stm) != 0) { + fprintf(stderr, zNotDate, opts->pzProgName, + od->optArg.argString); + if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) + (*(opts->pUsageProc))(opts, EXIT_FAILURE); + return; + } + + tm = mktime(&stm); + + if (od->fOptState & OPTST_ALLOC_ARG) { + AGFREE(od->optArg.argString); + od->fOptState &= ~OPTST_ALLOC_ARG; + } + + od->optArg.argInt = tm; + } + return; + + default_action: + +#endif + optionTimeVal(opts, od); + if (od->optArg.argInt != BAD_TIME) + od->optArg.argInt += (long)time(NULL); +} +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/time.c */ diff --git a/src/libopts/tokenize.c b/src/libopts/tokenize.c new file mode 100644 index 0000000..7489e3d --- /dev/null +++ b/src/libopts/tokenize.c @@ -0,0 +1,322 @@ +/** \file tokenize.c + * + * Tokenize a string, accommodating quoted strings. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file defines the string_tokenize interface + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +static void +copy_cooked(ch_t ** ppDest, char const ** ppSrc) +{ + ch_t * pDest = (ch_t *)*ppDest; + const ch_t * pSrc = (const ch_t *)(*ppSrc + 1); + + for (;;) { + ch_t ch = *(pSrc++); + switch (ch) { + case NUL: *ppSrc = NULL; return; + case '"': goto done; + case '\\': + pSrc += ao_string_cook_escape_char((char *)pSrc, (char *)&ch, 0x7F); + if (ch == 0x7F) + break; + /* FALLTHROUGH */ + + default: + *(pDest++) = ch; + } + } + + done: + *ppDest = (ch_t *)pDest; /* next spot for storing character */ + *ppSrc = (char const *)pSrc; /* char following closing quote */ +} + + +static void +copy_raw(ch_t ** ppDest, char const ** ppSrc) +{ + ch_t * pDest = *ppDest; + cc_t * pSrc = (cc_t *) (*ppSrc + 1); + + for (;;) { + ch_t ch = *(pSrc++); + switch (ch) { + case NUL: *ppSrc = NULL; return; + case '\'': goto done; + case '\\': + /* + * *Four* escapes are handled: newline removal, escape char + * quoting and apostrophe quoting + */ + switch (*pSrc) { + case NUL: *ppSrc = NULL; return; + case '\r': + if (*(++pSrc) == NL) + ++pSrc; + continue; + + case NL: + ++pSrc; + continue; + + case '\'': + ch = '\''; + /* FALLTHROUGH */ + + case '\\': + ++pSrc; + break; + } + /* FALLTHROUGH */ + + default: + *(pDest++) = ch; + } + } + + done: + *ppDest = pDest; /* next spot for storing character */ + *ppSrc = (char const *) pSrc; /* char following closing quote */ +} + +static token_list_t * +alloc_token_list(char const * str) +{ + token_list_t * res; + + int max_token_ct = 2; /* allow for trailing NULL pointer & NUL on string */ + + if (str == NULL) goto enoent_res; + + /* + * Trim leading white space. Use "ENOENT" and a NULL return to indicate + * an empty string was passed. + */ + str = SPN_WHITESPACE_CHARS(str); + if (*str == NUL) goto enoent_res; + + /* + * Take an approximate count of tokens. If no quoted strings are used, + * it will be accurate. If quoted strings are used, it will be a little + * high and we'll squander the space for a few extra pointers. + */ + { + char const * pz = str; + + do { + max_token_ct++; + pz = BRK_WHITESPACE_CHARS(pz+1); + pz = SPN_WHITESPACE_CHARS(pz); + } while (*pz != NUL); + + res = malloc(sizeof(*res) + (size_t)(pz - str) + + ((size_t)max_token_ct * sizeof(ch_t *))); + } + + if (res == NULL) + errno = ENOMEM; + else res->tkn_list[0] = (ch_t *)(res->tkn_list + (max_token_ct - 1)); + + return res; + + enoent_res: + + errno = ENOENT; + return NULL; +} + +/*=export_func ao_string_tokenize + * + * what: tokenize an input string + * + * arg: + char const * + string + string to be tokenized + + * + * ret_type: token_list_t * + * ret_desc: pointer to a structure that lists each token + * + * doc: + * + * This function will convert one input string into a list of strings. + * The list of strings is derived by separating the input based on + * white space separation. However, if the input contains either single + * or double quote characters, then the text after that character up to + * a matching quote will become the string in the list. + * + * The returned pointer should be deallocated with @code{free(3C)} when + * are done using the data. The data are placed in a single block of + * allocated memory. Do not deallocate individual token/strings. + * + * The structure pointed to will contain at least these two fields: + * @table @samp + * @item tkn_ct + * The number of tokens found in the input string. + * @item tok_list + * An array of @code{tkn_ct + 1} pointers to substring tokens, with + * the last pointer set to NULL. + * @end table + * + * There are two types of quoted strings: single quoted (@code{'}) and + * double quoted (@code{"}). Singly quoted strings are fairly raw in that + * escape characters (@code{\\}) are simply another character, except when + * preceding the following characters: + * @example + * @code{\\} double backslashes reduce to one + * @code{'} incorporates the single quote into the string + * @code{\n} suppresses both the backslash and newline character + * @end example + * + * Double quote strings are formed according to the rules of string + * constants in ANSI-C programs. + * + * example: + * @example + * #include + * int ix; + * token_list_t * ptl = ao_string_tokenize(some_string) + * for (ix = 0; ix < ptl->tkn_ct; ix++) + * do_something_with_tkn(ptl->tkn_list[ix]); + * free(ptl); + * @end example + * Note that everything is freed with the one call to @code{free(3C)}. + * + * err: + * NULL is returned and @code{errno} will be set to indicate the problem: + * @itemize @bullet + * @item + * @code{EINVAL} - There was an unterminated quoted string. + * @item + * @code{ENOENT} - The input string was empty. + * @item + * @code{ENOMEM} - There is not enough memory. + * @end itemize +=*/ +token_list_t * +ao_string_tokenize(char const * str) +{ + token_list_t * res = alloc_token_list(str); + ch_t * pzDest; + + /* + * Now copy each token into the output buffer. + */ + if (res == NULL) + return res; + + pzDest = (ch_t *)(res->tkn_list[0]); + res->tkn_ct = 0; + + do { + res->tkn_list[ res->tkn_ct++ ] = pzDest; + for (;;) { + int ch = (ch_t)*str; + if (IS_WHITESPACE_CHAR(ch)) { + found_white_space: + str = SPN_WHITESPACE_CHARS(str+1); + break; + } + + switch (ch) { + case '"': + copy_cooked(&pzDest, &str); + if (str == NULL) { + free(res); + errno = EINVAL; + return NULL; + } + if (IS_WHITESPACE_CHAR(*str)) + goto found_white_space; + break; + + case '\'': + copy_raw(&pzDest, &str); + if (str == NULL) { + free(res); + errno = EINVAL; + return NULL; + } + if (IS_WHITESPACE_CHAR(*str)) + goto found_white_space; + break; + + case NUL: + goto copy_done; + + default: + str++; + *(pzDest++) = (unsigned char)ch; + } + } copy_done:; + + /* + * NUL terminate the last token and see if we have any more tokens. + */ + *(pzDest++) = NUL; + } while (*str != NUL); + + res->tkn_list[ res->tkn_ct ] = NULL; + + return res; +} + +#ifdef TEST +#include +#include + +int +main(int argc, char ** argv) +{ + if (argc == 1) { + printf("USAGE: %s arg [ ... ]\n", *argv); + return 1; + } + while (--argc > 0) { + char * arg = *(++argv); + token_list_t * p = ao_string_tokenize(arg); + if (p == NULL) { + printf("Parsing string ``%s'' failed:\n\terrno %d (%s)\n", + arg, errno, strerror(errno)); + } else { + int ix = 0; + printf("Parsed string ``%s''\ninto %d tokens:\n", arg, p->tkn_ct); + do { + printf(" %3d: ``%s''\n", ix+1, p->tkn_list[ix]); + } while (++ix < p->tkn_ct); + free(p); + } + } + return 0; +} +#endif + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/tokenize.c */ diff --git a/src/libopts/usage.c b/src/libopts/usage.c new file mode 100644 index 0000000..8df3591 --- /dev/null +++ b/src/libopts/usage.c @@ -0,0 +1,1285 @@ + +/* + * \file usage.c + * + * This module implements the default usage procedure for + * Automated Options. It may be overridden, of course. + * + * @addtogroup autoopts + * @{ + */ +/* + * Sort options: + --start=END-[S]TATIC-FORWARD --patt='^/\*($|[^:])' \ + --out=xx.c key='^[a-zA-Z0-9_]+\(' --trail='^/\*:' \ + --spac=2 --input=usage.c + */ + +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +#define GRAPH_CH(_ch) \ + ((((unsigned)_ch) <= 0x7E) && (((unsigned)_ch) > ' ')) + +/** + * Parse the option usage flags string. Any parsing problems yield + * a zero (no flags set) result. This function is internal to + * set_usage_flags(). + * + * @param[in] fnt Flag Name Table - maps a name to a mask + * @param[in] txt the text to process. If NULL, then + * getenv("AUTOOPTS_USAGE") is used. + * @returns a bit mask indicating which \a fnt entries were found. + */ +static unsigned int +parse_usage_flags(ao_flag_names_t const * fnt, char const * txt) +{ + unsigned int res = 0; + + /* + * The text may be passed in. If not, use the environment variable. + */ + if (txt == NULL) { + txt = getenv("AUTOOPTS_USAGE"); + if (txt == NULL) + return 0; + } + + txt = SPN_WHITESPACE_CHARS(txt); + if (*txt == NUL) + return 0; + + /* + * search the string for table entries. We must understand everything + * we see in the string, or we give up on it. + */ + for (;;) { + int ix = 0; + + for (;;) { + if (strneqvcmp(txt, fnt[ix].fnm_name, (int)fnt[ix].fnm_len) == 0) + break; + if (++ix >= AOUF_COUNT) + return 0; + } + + /* + * Make sure we have a full match. Look for whitespace, + * a comma, or a NUL byte. + */ + if (! IS_END_LIST_ENTRY_CHAR(txt[fnt[ix].fnm_len])) + return 0; + + res |= 1U << ix; + txt = SPN_WHITESPACE_CHARS(txt + fnt[ix].fnm_len); + + switch (*txt) { + case NUL: + return res; + + case ',': + txt = SPN_WHITESPACE_CHARS(txt + 1); + /* Something must follow the comma */ + /* FALLTHROUGH */ + + default: + continue; + } + } +} + +/** + * Set option usage flags. Any parsing problems yield no changes to options. + * Three different bits may be fiddled: \a OPTPROC_GNUUSAGE, \a OPTPROC_MISUSE + * and \a OPTPROC_COMPUTE. + * + * @param[in] flg_txt text to parse. If NULL, then the AUTOOPTS_USAGE + * environment variable is parsed. + * @param[in,out] opts the program option descriptor + */ +static void +set_usage_flags(tOptions * opts, char const * flg_txt) +{ +# define _aof_(_n, _f) { sizeof(#_n)-1, _f, #_n }, + static ao_flag_names_t const fn_table[AOUF_COUNT] = { + AOFLAG_TABLE + }; +# undef _aof_ + + /* + * the flag word holds a bit for each selected table entry. + */ + unsigned int flg = parse_usage_flags(fn_table, flg_txt); + if (flg == 0) return; + + /* + * Ensure we do not have conflicting selections + */ + { + static unsigned int const form_mask = + AOUF_gnu | AOUF_autoopts; + static unsigned int const misuse_mask = + AOUF_no_misuse_usage | AOUF_misuse_usage; + if ( ((flg & form_mask) == form_mask) + || ((flg & misuse_mask) == misuse_mask) ) + return; + } + + /* + * Now fiddle the fOptSet bits, based on settings. + * The OPTPROC_LONGOPT bit is immutable, thus if it is set, + * then fnm points to a mask off mask. + */ + { + ao_flag_names_t const * fnm = fn_table; + for (;;) { + if ((flg & 1) != 0) { + if ((fnm->fnm_mask & OPTPROC_LONGOPT) != 0) + opts->fOptSet &= fnm->fnm_mask; + else opts->fOptSet |= fnm->fnm_mask; + } + flg >>= 1; + if (flg == 0) + break; + fnm++; + } + } +} + +/* + * Figure out if we should try to format usage text sort-of like + * the way many GNU programs do. + */ +static inline bool +do_gnu_usage(tOptions * pOpts) +{ + return (pOpts->fOptSet & OPTPROC_GNUUSAGE) ? true : false; +} + +/* + * Figure out if we should try to format usage text sort-of like + * the way many GNU programs do. + */ +static inline bool +skip_misuse_usage(tOptions * pOpts) +{ + return (pOpts->fOptSet & OPTPROC_MISUSE) ? true : false; +} + + +/*=export_func optionOnlyUsage + * + * what: Print usage text for just the options + * arg: + tOptions * + pOpts + program options descriptor + + * arg: + int + ex_code + exit code for calling exit(3) + + * + * doc: + * This routine will print only the usage for each option. + * This function may be used when the emitted usage must incorporate + * information not available to AutoOpts. +=*/ +void +optionOnlyUsage(tOptions * pOpts, int ex_code) +{ + char const * pOptTitle = NULL; + + set_usage_flags(pOpts, NULL); + if ((ex_code != EXIT_SUCCESS) && + skip_misuse_usage(pOpts)) + return; + + /* + * Determine which header and which option formatting strings to use + */ + if (do_gnu_usage(pOpts)) + (void)setGnuOptFmts(pOpts, &pOptTitle); + else + (void)setStdOptFmts(pOpts, &pOptTitle); + + prt_opt_usage(pOpts, ex_code, pOptTitle); + + fflush(option_usage_fp); + if (ferror(option_usage_fp) != 0) + fserr_exit(pOpts->pzProgName, zwriting, (option_usage_fp == stderr) + ? zstderr_name : zstdout_name); +} + +/** + * Print a message suggesting how to get help. + * + * @param[in] opts the program options + */ +static void +print_offer_usage(tOptions * opts) +{ + char help[24]; + + if (HAS_opt_usage_t(opts)) { + int ix = opts->presetOptCt; + tOptDesc * od = opts->pOptDesc + ix; + while (od->optUsage != AOUSE_HELP) { + if (++ix >= opts->optCt) + ao_bug(zmissing_help_msg); + od++; + } + switch (opts->fOptSet & (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)) { + case OPTPROC_SHORTOPT: + help[0] = '-'; + help[1] = od->optValue; + help[2] = NUL; + break; + + case OPTPROC_LONGOPT: + case (OPTPROC_LONGOPT | OPTPROC_SHORTOPT): + help[0] = help[1] = '-'; + strncpy(help + 2, od->pz_Name, 20); + break; + + case 0: + strncpy(help, od->pz_Name, 20); + break; + } + + } else { + switch (opts->fOptSet & (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)) { + case OPTPROC_SHORTOPT: + strcpy(help, "-h"); + break; + + case OPTPROC_LONGOPT: + case (OPTPROC_LONGOPT | OPTPROC_SHORTOPT): + strcpy(help, "--help"); + break; + + case 0: + strcpy(help, "help"); + break; + } + } + + fprintf(option_usage_fp, zoffer_usage_fmt, opts->pzProgName, help); +} + +/** + * Print information about each option. + * + * @param[in] opts the program options + * @param[in] exit_code whether or not there was a usage error reported. + * used to select full usage versus abbreviated. + */ +static void +print_usage_details(tOptions * opts, int exit_code) +{ + { + char const * pOptTitle = NULL; + int flen; + + /* + * Determine which header and which option formatting strings to use + */ + if (do_gnu_usage(opts)) { + flen = setGnuOptFmts(opts, &pOptTitle); + sprintf(line_fmt_buf, zFmtFmt, flen); + fputc(NL, option_usage_fp); + + } else { + flen = setStdOptFmts(opts, &pOptTitle); + sprintf(line_fmt_buf, zFmtFmt, flen); + + /* + * When we exit with EXIT_SUCCESS and the first option is a doc + * option, we do *NOT* want to emit the column headers. + * Otherwise, we do. + */ + if ( (exit_code != EXIT_SUCCESS) + || ((opts->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) ) + + fputs(pOptTitle, option_usage_fp); + } + + flen = 4 - ((flen + 15) / 8); + if (flen > 0) + tab_skip_ct = flen; + prt_opt_usage(opts, exit_code, pOptTitle); + } + + /* + * Describe the mechanics of denoting the options + */ + switch (opts->fOptSet & OPTPROC_L_N_S) { + case OPTPROC_L_N_S: fputs(zFlagOkay, option_usage_fp); break; + case OPTPROC_SHORTOPT: break; + case OPTPROC_LONGOPT: fputs(zNoFlags, option_usage_fp); break; + case 0: fputs(zOptsOnly, option_usage_fp); break; + } + + if ((opts->fOptSet & OPTPROC_NUM_OPT) != 0) + fputs(zNumberOpt, option_usage_fp); + + if ((opts->fOptSet & OPTPROC_REORDER) != 0) + fputs(zReorder, option_usage_fp); + + if (opts->pzExplain != NULL) + fputs(opts->pzExplain, option_usage_fp); + + /* + * IF the user is asking for help (thus exiting with SUCCESS), + * THEN see what additional information we can provide. + */ + if (exit_code == EXIT_SUCCESS) + prt_prog_detail(opts); + + /* + * Give bug notification preference to the packager information + */ + if (HAS_pzPkgDataDir(opts) && (opts->pzPackager != NULL)) + fputs(opts->pzPackager, option_usage_fp); + + else if (opts->pzBugAddr != NULL) + fprintf(option_usage_fp, zPlsSendBugs, opts->pzBugAddr); + + fflush(option_usage_fp); + + if (ferror(option_usage_fp) != 0) + fserr_exit(opts->pzProgName, zwriting, (option_usage_fp == stderr) + ? zstderr_name : zstdout_name); +} + +static void +print_one_paragraph(char const * text, bool plain, FILE * fp) +{ + if (plain) { +#ifdef ENABLE_NLS +#ifdef HAVE_LIBINTL_H +#ifdef DEBUG_ENABLED +#undef gettext +#endif + char * buf = dgettext("libopts", text); + if (buf == text) + text = gettext(text); +#endif /* HAVE_LIBINTL_H */ +#endif /* ENABLE_NLS */ + fputs(text, fp); + } + + else { + char const * t = optionQuoteString(text, LINE_SPLICE); + fprintf(fp, PUTS_FMT, t); + AGFREE(t); + } +} + +/*=export_func optionPrintParagraphs + * private: + * + * what: Print a paragraph of usage text + * arg: + char const * + text + a block of text that has bee i18n-ed + + * arg: + bool + plain + false -> wrap text in fputs() + + * arg: + FILE * + fp + the stream file pointer for output + + * + * doc: + * This procedure is called in two contexts: when a full or short usage text + * has been provided for display, and when autogen is assembling a list of + * translatable texts in the optmain.tlib template. In the former case, \a + * plain is set to \a true, otherwise \a false. + * + * Anything less than 256 characters in size is printed as a single unit. + * Otherwise, paragraphs are detected. A paragraph break is defined as just + * before a non-empty line preceded by two newlines or a line that starts + * with at least one space character but fewer than 8 space characters. + * Lines indented with tabs or more than 7 spaces are considered continuation + * lines. + * + * If 'plain' is true, we are emitting text for a user to see. So, if it is + * true and NLS is not enabled, then just write the whole thing at once. +=*/ +void +optionPrintParagraphs(char const * text, bool plain, FILE * fp) +{ + size_t len = strlen(text); + char * buf; +#ifndef ENABLE_NLS + if (plain || (len < 256)) +#else + if (len < 256) +#endif + { + print_one_paragraph(text, plain, fp); + return; + } + + AGDUPSTR(buf, text, "ppara"); + text = buf; + + for (;;) { + char * scan; + + if (len < 256) { + done: + print_one_paragraph(buf, plain, fp); + break; + } + scan = buf; + + try_longer: + scan = strchr(scan, NL); + if (scan == NULL) + goto done; + + if ((scan - buf) < 40) { + scan++; + goto try_longer; + } + + scan++; + if ((! isspace((int)*scan)) || (*scan == HT)) + /* + * line starts with tab or non-whitespace --> continuation + */ + goto try_longer; + + if (*scan == NL) { + /* + * Double newline -> paragraph break + * Include all newlines in current paragraph. + */ + while (*++scan == NL) /*continue*/; + + } else { + char * p = scan; + int sp_ct = 0; + + while (*p == ' ') { + if (++sp_ct >= 8) { + /* + * Too many spaces --> continuation line + */ + scan = p; + goto try_longer; + } + p++; + } + } + + /* + * "scan" points to the first character of a paragraph or the + * terminating NUL byte. + */ + { + char svch = *scan; + *scan = NUL; + print_one_paragraph(buf, plain, fp); + len -= scan - buf; + if (len <= 0) + break; + *scan = svch; + buf = scan; + } + } + AGFREE(text); +} + +/*=export_func optionUsage + * private: + * + * what: Print usage text + * arg: + tOptions * + opts + program options descriptor + + * arg: + int + exitCode + exit code for calling exit(3) + + * + * doc: + * This routine will print usage in both GNU-standard and AutoOpts-expanded + * formats. The descriptor specifies the default, but AUTOOPTS_USAGE will + * over-ride this, providing the value of it is set to either "gnu" or + * "autoopts". This routine will @strong{not} return. + * + * If "exitCode" is "AO_EXIT_REQ_USAGE" (normally 64), then output will to + * to stdout and the actual exit code will be "EXIT_SUCCESS". +=*/ +noreturn void +optionUsage(tOptions * opts, int usage_exit_code) +{ + int exit_code = (usage_exit_code == AO_EXIT_REQ_USAGE) + ? EXIT_SUCCESS : usage_exit_code; + + displayEnum = false; + set_usage_flags(opts, NULL); + + /* + * Paged usage will preset option_usage_fp to an output file. + * If it hasn't already been set, then set it to standard output + * on successful exit (help was requested), otherwise error out. + * + * Test the version before obtaining pzFullUsage or pzShortUsage. + * These fields do not exist before revision 30. + */ + { + char const * pz; + + if (exit_code == EXIT_SUCCESS) { + pz = (opts->structVersion >= 30 * 4096) + ? opts->pzFullUsage : NULL; + + if (option_usage_fp == NULL) + option_usage_fp = print_exit ? stderr : stdout; + + } else { + pz = (opts->structVersion >= 30 * 4096) + ? opts->pzShortUsage : NULL; + + if (option_usage_fp == NULL) + option_usage_fp = stderr; + } + + if (((opts->fOptSet & OPTPROC_COMPUTE) == 0) && (pz != NULL)) { + if ((opts->fOptSet & OPTPROC_TRANSLATE) != 0) + optionPrintParagraphs(pz, true, option_usage_fp); + else + fputs(pz, option_usage_fp); + goto flush_and_exit; + } + } + + fprintf(option_usage_fp, opts->pzUsageTitle, opts->pzProgName); + + if ((exit_code == EXIT_SUCCESS) || + (! skip_misuse_usage(opts))) + + print_usage_details(opts, usage_exit_code); + else + print_offer_usage(opts); + + flush_and_exit: + fflush(option_usage_fp); + if (ferror(option_usage_fp) != 0) + fserr_exit(opts->pzProgName, zwriting, (option_usage_fp == stdout) + ? zstdout_name : zstderr_name); + + option_exits(exit_code); +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * PER OPTION TYPE USAGE INFORMATION + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * print option conflicts. + * + * @param opts the program option descriptor + * @param od the option descriptor + */ +static void +prt_conflicts(tOptions * opts, tOptDesc * od) +{ + const int * opt_no; + fputs(zTabHyp + tab_skip_ct, option_usage_fp); + + /* + * REQUIRED: + */ + if (od->pOptMust != NULL) { + opt_no = od->pOptMust; + + if (opt_no[1] == NO_EQUIVALENT) { + fprintf(option_usage_fp, zReqOne, + opts->pOptDesc[*opt_no].pz_Name); + } else { + fputs(zReqThese, option_usage_fp); + for (;;) { + fprintf(option_usage_fp, zTabout + tab_skip_ct, + opts->pOptDesc[*opt_no].pz_Name); + if (*++opt_no == NO_EQUIVALENT) + break; + } + } + + if (od->pOptCant != NULL) + fputs(zTabHypAnd + tab_skip_ct, option_usage_fp); + } + + /* + * CONFLICTS: + */ + if (od->pOptCant == NULL) + return; + + opt_no = od->pOptCant; + + if (opt_no[1] == NO_EQUIVALENT) { + fprintf(option_usage_fp, zProhibOne, + opts->pOptDesc[*opt_no].pz_Name); + return; + } + + fputs(zProhib, option_usage_fp); + for (;;) { + fprintf(option_usage_fp, zTabout + tab_skip_ct, + opts->pOptDesc[*opt_no].pz_Name); + if (*++opt_no == NO_EQUIVALENT) + break; + } +} + +/** + * Print the usage information for a single vendor option. + * + * @param[in] opts the program option descriptor + * @param[in] od the option descriptor + * @param[in] argtp names of the option argument types + * @param[in] usefmt format for primary usage line + */ +static void +prt_one_vendor(tOptions * opts, tOptDesc * od, + arg_types_t * argtp, char const * usefmt) +{ + prt_preamble(opts, od, argtp); + + { + char z[ 80 ]; + char const * pzArgType; + + /* + * Determine the argument type string first on its usage, then, + * when the option argument is required, base the type string on the + * argument type. + */ + if (od->fOptState & OPTST_ARG_OPTIONAL) { + pzArgType = argtp->pzOpt; + + } else switch (OPTST_GET_ARGTYPE(od->fOptState)) { + case OPARG_TYPE_NONE: pzArgType = argtp->pzNo; break; + case OPARG_TYPE_ENUMERATION: pzArgType = argtp->pzKey; break; + case OPARG_TYPE_FILE: pzArgType = argtp->pzFile; break; + case OPARG_TYPE_MEMBERSHIP: pzArgType = argtp->pzKeyL; break; + case OPARG_TYPE_BOOLEAN: pzArgType = argtp->pzBool; break; + case OPARG_TYPE_NUMERIC: pzArgType = argtp->pzNum; break; + case OPARG_TYPE_HIERARCHY: pzArgType = argtp->pzNest; break; + case OPARG_TYPE_STRING: pzArgType = argtp->pzStr; break; + case OPARG_TYPE_TIME: pzArgType = argtp->pzTime; break; + default: goto bogus_desc; + } + + pzArgType = SPN_WHITESPACE_CHARS(pzArgType); + if (*pzArgType == NUL) + snprintf(z, sizeof(z), "%s", od->pz_Name); + else + snprintf(z, sizeof(z), "%s=%s", od->pz_Name, pzArgType); + fprintf(option_usage_fp, usefmt, z, od->pzText); + + switch (OPTST_GET_ARGTYPE(od->fOptState)) { + case OPARG_TYPE_ENUMERATION: + case OPARG_TYPE_MEMBERSHIP: + displayEnum = (od->pOptProc != NULL) ? true : displayEnum; + } + } + + return; + + bogus_desc: + fprintf(stderr, zbad_od, opts->pzProgName, od->pz_Name); + ao_bug(zbad_arg_type_msg); +} + +/** + * Print the long options processed with "-W". These options will be the + * ones that do *not* have flag characters. + * + * @param opts the program option descriptor + * @param title the title for the options + */ +static void +prt_vendor_opts(tOptions * opts, char const * title) +{ + static unsigned int const not_vended_mask = + OPTST_NO_USAGE_MASK | OPTST_DOCUMENT; + + static char const vfmtfmt[] = "%%-%us %%s\n"; + char vfmt[sizeof(vfmtfmt)]; + + /* + * Only handle client specified options. The "vendor option" follows + * "presetOptCt", so we won't loop/recurse indefinitely. + */ + int ct = opts->presetOptCt; + tOptDesc * od = opts->pOptDesc; + fprintf(option_usage_fp, zTabout + tab_skip_ct, zVendOptsAre); + + { + size_t nmlen = 0; + do { + size_t l; + if ( ((od->fOptState & not_vended_mask) != 0) + || GRAPH_CH(od->optValue)) + continue; + + l = strlen(od->pz_Name); + if (l > nmlen) nmlen = l; + } while (od++, (--ct > 0)); + + snprintf(vfmt, sizeof(vfmt), vfmtfmt, (unsigned int)nmlen + 4); + } + + if (tab_skip_ct > 0) + tab_skip_ct--; + + ct = opts->presetOptCt; + od = opts->pOptDesc; + + do { + if ( ((od->fOptState & not_vended_mask) != 0) + || GRAPH_CH(od->optValue)) + continue; + + prt_one_vendor(opts, od, &argTypes, vfmt); + prt_extd_usage(opts, od, title); + + } while (od++, (--ct > 0)); + + /* no need to restore "tab_skip_ct" - options are done now */ +} + +/** + * Print extended usage. Usage/help was requested. + * + * @param opts the program option descriptor + * @param od the option descriptor + * @param title the title for the options + */ +static void +prt_extd_usage(tOptions * opts, tOptDesc * od, char const * title) +{ + if ( ((opts->fOptSet & OPTPROC_VENDOR_OPT) != 0) + && (od->optActualValue == VENDOR_OPTION_VALUE)) { + prt_vendor_opts(opts, title); + return; + } + + /* + * IF there are option conflicts or dependencies, + * THEN print them here. + */ + if ((od->pOptMust != NULL) || (od->pOptCant != NULL)) + prt_conflicts(opts, od); + + /* + * IF there is a disablement string + * THEN print the disablement info + */ + if (od->pz_DisableName != NULL ) + fprintf(option_usage_fp, zDis + tab_skip_ct, od->pz_DisableName); + + /* + * Check for argument types that have callbacks with magical properties + */ + switch (OPTST_GET_ARGTYPE(od->fOptState)) { + case OPARG_TYPE_NUMERIC: + /* + * IF the numeric option has a special callback, + * THEN call it, requesting the range or other special info + */ + if ( (od->pOptProc != NULL) + && (od->pOptProc != optionNumericVal) ) { + (*(od->pOptProc))(OPTPROC_EMIT_USAGE, od); + } + break; + + case OPARG_TYPE_FILE: + (*(od->pOptProc))(OPTPROC_EMIT_USAGE, od); + break; + } + + /* + * IF the option defaults to being enabled, + * THEN print that out + */ + if (od->fOptState & OPTST_INITENABLED) + fputs(zEnab + tab_skip_ct, option_usage_fp); + + /* + * IF the option is in an equivalence class + * AND not the designated lead + * THEN print equivalence and leave it at that. + */ + if ( (od->optEquivIndex != NO_EQUIVALENT) + && (od->optEquivIndex != od->optActualIndex ) ) { + fprintf(option_usage_fp, zalt_opt + tab_skip_ct, + opts->pOptDesc[ od->optEquivIndex ].pz_Name); + return; + } + + /* + * IF this particular option can NOT be preset + * AND some form of presetting IS allowed, + * AND it is not an auto-managed option (e.g. --help, et al.) + * THEN advise that this option may not be preset. + */ + if ( ((od->fOptState & OPTST_NO_INIT) != 0) + && ( (opts->papzHomeList != NULL) + || (opts->pzPROGNAME != NULL) + ) + && (od->optIndex < opts->presetOptCt) + ) + + fputs(zNoPreset + tab_skip_ct, option_usage_fp); + + /* + * Print the appearance requirements. + */ + if (OPTST_GET_ARGTYPE(od->fOptState) == OPARG_TYPE_MEMBERSHIP) + fputs(zMembers + tab_skip_ct, option_usage_fp); + + else switch (od->optMinCt) { + case 1: + case 0: + switch (od->optMaxCt) { + case 0: fputs(zPreset + tab_skip_ct, option_usage_fp); break; + case NOLIMIT: fputs(zNoLim + tab_skip_ct, option_usage_fp); break; + case 1: break; + /* + * IF the max is more than one but limited, print "UP TO" message + */ + default: + fprintf(option_usage_fp, zUpTo + tab_skip_ct, od->optMaxCt); break; + } + break; + + default: + /* + * More than one is required. Print the range. + */ + fprintf(option_usage_fp, zMust + tab_skip_ct, + od->optMinCt, od->optMaxCt); + } + + if ( NAMED_OPTS(opts) + && (opts->specOptIdx.default_opt == od->optIndex)) + fputs(zDefaultOpt + tab_skip_ct, option_usage_fp); +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * Figure out where all the initialization files might live. This requires + * translating some environment variables and testing to see if a name is a + * directory or a file. It's squishy, but important to tell users how to + * find these files. + * + * @param[in] papz search path + * @param[out] ini_file an output buffer of AG_PATH_MAX+1 bytes + * @param[in] path_nm the name of the file we're hunting for + */ +static void +prt_ini_list(char const * const * papz, char const * ini_file, + char const * path_nm) +{ + char pth_buf[AG_PATH_MAX+1]; + + fputs(zPresetIntro, option_usage_fp); + + for (;;) { + char const * path = *(papz++); + char const * nm_buf = pth_buf; + + if (path == NULL) + break; + + /* + * Ignore any invalid paths + */ + if (! optionMakePath(pth_buf, (int)sizeof(pth_buf), path, path_nm)) + nm_buf = path; + + /* + * Expand paths that are relative to the executable or installation + * directories. Leave alone paths that use environment variables. + */ + else if ((*path == '$') + && ((path[1] == '$') || (path[1] == '@'))) + path = nm_buf; + + /* + * Print the name of the "homerc" file. If the "rcfile" name is + * not empty, we may or may not print that, too... + */ + fprintf(option_usage_fp, zPathFmt, path); + if (*ini_file != NUL) { + struct stat sb; + + /* + * IF the "homerc" file is a directory, + * then append the "rcfile" name. + */ + if ((stat(nm_buf, &sb) == 0) && S_ISDIR(sb.st_mode)) { + fputc(DIRCH, option_usage_fp); + fputs(ini_file, option_usage_fp); + } + } + + fputc(NL, option_usage_fp); + } +} + +/** + * Print the usage line preamble text + * + * @param opts the program option descriptor + * @param od the option descriptor + * @param at names of the option argument types + */ +static void +prt_preamble(tOptions * opts, tOptDesc * od, arg_types_t * at) +{ + /* + * Flag prefix: IF no flags at all, then omit it. If not printable + * (not allowed for this option), then blank, else print it. + * Follow it with a comma if we are doing GNU usage and long + * opts are to be printed too. + */ + if ((opts->fOptSet & OPTPROC_SHORTOPT) == 0) + fputs(at->pzSpc, option_usage_fp); + + else if (! GRAPH_CH(od->optValue)) { + if ( (opts->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) + == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) + fputc(' ', option_usage_fp); + fputs(at->pzNoF, option_usage_fp); + + } else { + fprintf(option_usage_fp, " -%c", od->optValue); + if ( (opts->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) + == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) + fputs(", ", option_usage_fp); + } +} + +/** + * Print the usage information for a single option. + * + * @param opts the program option descriptor + * @param od the option descriptor + * @param at names of the option argument types + */ +static void +prt_one_usage(tOptions * opts, tOptDesc * od, arg_types_t * at) +{ + prt_preamble(opts, od, at); + + { + char z[80]; + char const * atyp; + + /* + * Determine the argument type string first on its usage, then, + * when the option argument is required, base the type string on the + * argument type. + */ + if (od->fOptState & OPTST_ARG_OPTIONAL) { + atyp = at->pzOpt; + + } else switch (OPTST_GET_ARGTYPE(od->fOptState)) { + case OPARG_TYPE_NONE: atyp = at->pzNo; break; + case OPARG_TYPE_ENUMERATION: atyp = at->pzKey; break; + case OPARG_TYPE_FILE: atyp = at->pzFile; break; + case OPARG_TYPE_MEMBERSHIP: atyp = at->pzKeyL; break; + case OPARG_TYPE_BOOLEAN: atyp = at->pzBool; break; + case OPARG_TYPE_NUMERIC: atyp = at->pzNum; break; + case OPARG_TYPE_HIERARCHY: atyp = at->pzNest; break; + case OPARG_TYPE_STRING: atyp = at->pzStr; break; + case OPARG_TYPE_TIME: atyp = at->pzTime; break; + default: goto bogus_desc; + } + +#ifdef _WIN32 + if (at->pzOptFmt == zGnuOptFmt) + snprintf(z, sizeof(z), "--%s%s", od->pz_Name, atyp); + else if (at->pzOptFmt == zGnuOptFmt + 2) + snprintf(z, sizeof(z), "%s%s", od->pz_Name, atyp); + else +#endif + snprintf(z, sizeof(z), at->pzOptFmt, atyp, od->pz_Name, + (od->optMinCt != 0) ? at->pzReq : at->pzOpt); + + fprintf(option_usage_fp, line_fmt_buf, z, od->pzText); + + switch (OPTST_GET_ARGTYPE(od->fOptState)) { + case OPARG_TYPE_ENUMERATION: + case OPARG_TYPE_MEMBERSHIP: + displayEnum = (od->pOptProc != NULL) ? true : displayEnum; + } + } + + return; + + bogus_desc: + fprintf(stderr, zbad_od, opts->pzProgName, od->pz_Name); + option_exits(EX_SOFTWARE); +} + +/** + * Print out the usage information for just the options. + */ +static void +prt_opt_usage(tOptions * opts, int ex_code, char const * title) +{ + int ct = opts->optCt; + int optNo = 0; + tOptDesc * od = opts->pOptDesc; + int docCt = 0; + + do { + /* + * no usage --> disallowed on command line (OPTST_NO_COMMAND), or + * deprecated -- strongly discouraged (OPTST_DEPRECATED), or + * compiled out of current object code (OPTST_OMITTED) + */ + if ((od->fOptState & OPTST_NO_USAGE_MASK) != 0) { + + /* + * IF this is a compiled-out option + * *AND* usage was requested with "omitted-usage" + * *AND* this is NOT abbreviated usage + * THEN display this option. + */ + if ( (od->fOptState == (OPTST_OMITTED | OPTST_NO_INIT)) + && (od->pz_Name != NULL) + && (ex_code == EXIT_SUCCESS)) { + + char const * why_pz = + (od->pzText == NULL) ? zDisabledWhy : od->pzText; + prt_preamble(opts, od, &argTypes); + fprintf(option_usage_fp, zDisabledOpt, od->pz_Name, why_pz); + } + + continue; + } + + if ((od->fOptState & OPTST_DOCUMENT) != 0) { + if (ex_code == EXIT_SUCCESS) { + fprintf(option_usage_fp, argTypes.pzBrk, od->pzText, + title); + docCt++; + } + + continue; + } + + /* Skip name only options when we have a vendor option */ + if ( ((opts->fOptSet & OPTPROC_VENDOR_OPT) != 0) + && (! GRAPH_CH(od->optValue))) + continue; + + /* + * IF this is the first auto-opt maintained option + * *AND* we are doing a full help + * *AND* there are documentation options + * *AND* the last one was not a doc option, + * THEN document that the remaining options are not user opts + */ + if ((docCt > 0) && (ex_code == EXIT_SUCCESS)) { + if (opts->presetOptCt == optNo) { + if ((od[-1].fOptState & OPTST_DOCUMENT) == 0) + fprintf(option_usage_fp, argTypes.pzBrk, zAuto, title); + + } else if ((ct == 1) && + (opts->fOptSet & OPTPROC_VENDOR_OPT)) + fprintf(option_usage_fp, argTypes.pzBrk, zVendIntro, title); + } + + prt_one_usage(opts, od, &argTypes); + + /* + * IF we were invoked because of the --help option, + * THEN print all the extra info + */ + if (ex_code == EXIT_SUCCESS) + prt_extd_usage(opts, od, title); + + } while (od++, optNo++, (--ct > 0)); + + fputc(NL, option_usage_fp); +} + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/** + * Print program details. + * @param[in] opts the program option descriptor + */ +static void +prt_prog_detail(tOptions * opts) +{ + bool need_intro = (opts->papzHomeList == NULL); + + /* + * Display all the places we look for config files, if we have + * a list of directories to search. + */ + if (! need_intro) + prt_ini_list(opts->papzHomeList, opts->pzRcName, opts->pzProgPath); + + /* + * Let the user know about environment variable settings + */ + if ((opts->fOptSet & OPTPROC_ENVIRON) != 0) { + if (need_intro) + fputs(zPresetIntro, option_usage_fp); + + fprintf(option_usage_fp, zExamineFmt, opts->pzPROGNAME); + } + + /* + * IF we found an enumeration, + * THEN hunt for it again. Call the handler proc with a NULL + * option struct pointer. That tells it to display the keywords. + */ + if (displayEnum) { + int ct = opts->optCt; + int optNo = 0; + tOptDesc * od = opts->pOptDesc; + + fputc(NL, option_usage_fp); + fflush(option_usage_fp); + do { + switch (OPTST_GET_ARGTYPE(od->fOptState)) { + case OPARG_TYPE_ENUMERATION: + case OPARG_TYPE_MEMBERSHIP: + (*(od->pOptProc))(OPTPROC_EMIT_USAGE, od); + } + } while (od++, optNo++, (--ct > 0)); + } + + /* + * If there is a detail string, now is the time for that. + */ + if (opts->pzDetail != NULL) + fputs(opts->pzDetail, option_usage_fp); +} + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * OPTION LINE FORMATTING SETUP + * + * The "OptFmt" formats receive three arguments: + * 1. the type of the option's argument + * 2. the long name of the option + * 3. "YES" or "no ", depending on whether or not the option must appear + * on the command line. + * These formats are used immediately after the option flag (if used) has + * been printed. + * + * Set up the formatting for GNU-style output + */ +static int +setGnuOptFmts(tOptions * opts, char const ** ptxt) +{ + static char const zOneSpace[] = " "; + int flen = 22; + *ptxt = zNoRq_ShrtTtl; + + argTypes.pzStr = zGnuStrArg; + argTypes.pzReq = zOneSpace; + argTypes.pzNum = zGnuNumArg; + argTypes.pzKey = zGnuKeyArg; + argTypes.pzKeyL = zGnuKeyLArg; + argTypes.pzTime = zGnuTimeArg; + argTypes.pzFile = zGnuFileArg; + argTypes.pzBool = zGnuBoolArg; + argTypes.pzNest = zGnuNestArg; + argTypes.pzOpt = zGnuOptArg; + argTypes.pzNo = zOneSpace; + argTypes.pzBrk = zGnuBreak; + argTypes.pzNoF = zSixSpaces; + argTypes.pzSpc = zThreeSpaces; + + switch (opts->fOptSet & OPTPROC_L_N_S) { + case OPTPROC_L_N_S: argTypes.pzOptFmt = zGnuOptFmt; break; + case OPTPROC_LONGOPT: argTypes.pzOptFmt = zGnuOptFmt; break; + case 0: argTypes.pzOptFmt = zGnuOptFmt + 2; break; + case OPTPROC_SHORTOPT: + argTypes.pzOptFmt = zShrtGnuOptFmt; + zGnuStrArg[0] = zGnuNumArg[0] = zGnuKeyArg[0] = zGnuBoolArg[0] = ' '; + argTypes.pzOpt = " [arg]"; + flen = 8; + break; + } + + return flen; +} + + +/* + * Standard (AutoOpts normal) option line formatting + */ +static int +setStdOptFmts(tOptions * opts, char const ** ptxt) +{ + int flen = 0; + + argTypes.pzStr = zStdStrArg; + argTypes.pzReq = zStdReqArg; + argTypes.pzNum = zStdNumArg; + argTypes.pzKey = zStdKeyArg; + argTypes.pzKeyL = zStdKeyLArg; + argTypes.pzTime = zStdTimeArg; + argTypes.pzFile = zStdFileArg; + argTypes.pzBool = zStdBoolArg; + argTypes.pzNest = zStdNestArg; + argTypes.pzOpt = zStdOptArg; + argTypes.pzNo = zStdNoArg; + argTypes.pzBrk = zStdBreak; + argTypes.pzNoF = zFiveSpaces; + argTypes.pzSpc = zTwoSpaces; + + switch (opts->fOptSet & (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT)) { + case (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT): + *ptxt = zNoRq_ShrtTtl; + argTypes.pzOptFmt = zNrmOptFmt; + flen = 19; + break; + + case OPTPROC_NO_REQ_OPT: + *ptxt = zNoRq_NoShrtTtl; + argTypes.pzOptFmt = zNrmOptFmt; + flen = 19; + break; + + case OPTPROC_SHORTOPT: + *ptxt = zReq_ShrtTtl; + argTypes.pzOptFmt = zReqOptFmt; + flen = 24; + break; + + case 0: + *ptxt = zReq_NoShrtTtl; + argTypes.pzOptFmt = zReqOptFmt; + flen = 24; + } + + return flen; +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/usage.c */ diff --git a/src/libopts/version.c b/src/libopts/version.c new file mode 100644 index 0000000..cd46be3 --- /dev/null +++ b/src/libopts/version.c @@ -0,0 +1,240 @@ + +/** \file version.c + * + * This module implements the default usage procedure for + * Automated Options. It may be overridden, of course. + * + * @addtogroup autoopts + * @{ + */ +/* + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved + * + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. + * + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" + * + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" + * + * These files have the following sha256 sums: + * + * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 + * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 + * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd + */ + +/*=export_func optionVersion + * + * what: return the compiled AutoOpts version number + * ret_type: char const * + * ret_desc: the version string in constant memory + * doc: + * Returns the full version string compiled into the library. + * The returned string cannot be modified. +=*/ +char const * +optionVersion(void) +{ + static char const ver[] = OPTIONS_DOTTED_VERSION; + return ver; +} + +static void +emit_first_line( + FILE * fp, char const * alt1, char const * alt2, char const * alt3) +{ + char const * p = (alt1 != NULL) ? alt1 : ((alt2 != NULL) ? alt2 : alt3); + char const * e; + if (p == NULL) + return; + e = strchr(p, NL); + if (e == NULL) + fputs(p, fp); + else + fwrite(p, 1, (e - p), fp); + fputc(NL, fp); +} + +/** + * Select among various ways to emit version information. + * + * @param[in] o the option descriptor + * @param[in] fp the output stream + */ +static void +emit_simple_ver(tOptions * o, FILE * fp) +{ + emit_first_line(fp, o->pzFullVersion, o->pzCopyright, o->pzUsageTitle); +} + +/** + * print the version with a copyright notice. + * + * @param[in] o the option descriptor + * @param[in] fp the output stream + */ +static void +emit_copy_full(tOptions * o, FILE * fp) +{ + if (o->pzCopyright != NULL) + fputs(o->pzCopyright, fp); + + else if (o->pzFullVersion != NULL) + fputs(o->pzFullVersion, fp); + + else + emit_first_line(fp, o->pzUsageTitle, NULL, NULL); + + if (HAS_pzPkgDataDir(o) && (o->pzPackager != NULL)) { + fputc(NL, fp); + fputs(o->pzPackager, fp); + + } else if (o->pzBugAddr != NULL) { + fputc(NL, fp); + fprintf(fp, zPlsSendBugs, o->pzBugAddr); + } +} + +/** + * print the version and any copyright notice. + * The version with a full copyright and additional notes. + * + * @param[in] opts the option descriptor + * @param[in] fp the output stream + */ +static void +emit_copy_note(tOptions * opts, FILE * fp) +{ + if (opts->pzCopyright != NULL) + fputs(opts->pzCopyright, fp); + + if (opts->pzCopyNotice != NULL) + fputs(opts->pzCopyNotice, fp); + + fputc(NL, fp); + fprintf(fp, zao_ver_fmt, optionVersion()); + + if (HAS_pzPkgDataDir(opts) && (opts->pzPackager != NULL)) { + fputc(NL, fp); + fputs(opts->pzPackager, fp); + + } else if (opts->pzBugAddr != NULL) { + fputc(NL, fp); + fprintf(fp, zPlsSendBugs, opts->pzBugAddr); + } +} + +/** + * Handle the version printing. We must see how much information + * is being requested and select the correct printing routine. + */ +static void +print_ver(tOptions * opts, tOptDesc * od, FILE * fp, bool call_exit) +{ + char ch; + + if (opts <= OPTPROC_EMIT_LIMIT) + return; + + /* + * IF we have an argument for this option, use it + * Otherwise, default to version only or copyright note, + * depending on whether the layout is GNU standard form or not. + */ + if ( (od->fOptState & OPTST_ARG_OPTIONAL) + && (od->optArg.argString != NULL) + && (od->optArg.argString[0] != NUL)) + + ch = od->optArg.argString[0]; + + else if (OPTST_GET_ARGTYPE(od->fOptState) == OPARG_TYPE_STATIC) { + ch = od->optArg.argString[0]; + + } else { + set_usage_flags(opts, NULL); + ch = (opts->fOptSet & OPTPROC_GNUUSAGE) ? 'c' : 'v'; + } + + switch (ch) { + case NUL: /* arg provided, but empty */ + case 'v': case 'V': emit_simple_ver(opts, fp); break; + case 'c': case 'C': emit_copy_full( opts, fp); break; + case 'n': case 'N': emit_copy_note( opts, fp); break; + + default: + fprintf(stderr, zBadVerArg, ch); + option_exits(EXIT_FAILURE); + } + + fflush(fp); + if (ferror(fp)) + fserr_exit(opts->pzProgName, zwriting, + (fp == stdout) ? zstdout_name : zstderr_name); + + if (call_exit) + option_exits(EXIT_SUCCESS); +} + +/*=export_func optionPrintVersion + * + * what: Print the program version + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + od + the descriptor for this arg + + * + * doc: + * This routine will print the version to stdout. +=*/ +void +optionPrintVersion(tOptions * opts, tOptDesc * od) +{ + print_ver(opts, od, print_exit ? stderr : stdout, true); +} + +/*=export_func optionPrintVersionAndReturn + * + * what: Print the program version + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + od + the descriptor for this arg + + * + * doc: + * This routine will print the version to stdout and return + * instead of exiting. Please see the source for the + * @code{print_ver} funtion for details on selecting how + * verbose to be after this function returns. +=*/ +void +optionPrintVersionAndReturn(tOptions * opts, tOptDesc * od) +{ + print_ver(opts, od, print_exit ? stderr : stdout, false); +} + +/*=export_func optionVersionStderr + * private: + * + * what: Print the program version to stderr + * arg: + tOptions * + opts + program options descriptor + + * arg: + tOptDesc * + od + the descriptor for this arg + + * + * doc: + * This routine will print the version to stderr. +=*/ +void +optionVersionStderr(tOptions * opts, tOptDesc * od) +{ + print_ver(opts, od, stderr, true); +} + +/** @} + * + * Local Variables: + * mode: C + * c-file-style: "stroustrup" + * indent-tabs-mode: nil + * End: + * end of autoopts/version.c */ diff --git a/src/serv-args.def b/src/serv-args.def index a584085..996fbe3 100644 --- a/src/serv-args.def +++ b/src/serv-args.def @@ -51,7 +51,7 @@ flag = { flag = { name = maxearlydata; arg-type = number; - arg-range = "1->"; + arg-range = "1->4294967295"; descrip = "The maximum early data size to accept"; doc = ""; }; diff --git a/tests/Makefile.am b/tests/Makefile.am index 38d691f..11a083c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -522,8 +522,6 @@ endif dist_check_SCRIPTS += gnutls-cli-self-signed.sh gnutls-cli-invalid-crl.sh gnutls-cli-rawpk.sh -dist_check_SCRIPTS += dh-fips-approved.sh - if ENABLE_PKCS11 dist_check_SCRIPTS += p11-kit-trust.sh testpkcs11.sh certtool-pkcs11.sh diff --git a/tests/aead-cipher-vec.c b/tests/aead-cipher-vec.c index 6a30a35..fba9010 100644 --- a/tests/aead-cipher-vec.c +++ b/tests/aead-cipher-vec.c @@ -49,7 +49,6 @@ static void start(const char *name, int algo) giovec_t auth_iov[2]; uint8_t tag[64]; size_t tag_size = 0; - size_t i; key.data = key16; key.size = gnutls_cipher_get_key_size(algo); @@ -83,23 +82,21 @@ static void start(const char *name, int algo) if (ret < 0) fail("gnutls_cipher_init: %s\n", gnutls_strerror(ret)); - for (i = 0; i < 2; i++) { - ret = gnutls_aead_cipher_encryptv2(ch, - iv.data, iv.size, - auth_iov, 2, - iov, i + 1, - tag, &tag_size); - if (ret < 0) - fail("could not encrypt data: %s\n", gnutls_strerror(ret)); - - ret = gnutls_aead_cipher_decryptv2(ch, - iv.data, iv.size, - auth_iov, 2, - iov, i + 1, - tag, tag_size); - if (ret < 0) - fail("could not decrypt data: %s\n", gnutls_strerror(ret)); - } + ret = gnutls_aead_cipher_encryptv2(ch, + iv.data, iv.size, + auth_iov, 2, + iov, 3, + tag, &tag_size); + if (ret < 0) + fail("could not encrypt data: %s\n", gnutls_strerror(ret)); + + ret = gnutls_aead_cipher_decryptv2(ch, + iv.data, iv.size, + auth_iov, 2, + iov, 3, + tag, tag_size); + if (ret < 0) + fail("could not decrypt data: %s\n", gnutls_strerror(ret)); gnutls_aead_cipher_deinit(ch); } diff --git a/tests/client-sign-md5-rep.c b/tests/client-sign-md5-rep.c index b1ad46c..1c7877f 100644 --- a/tests/client-sign-md5-rep.c +++ b/tests/client-sign-md5-rep.c @@ -468,11 +468,6 @@ void doit(void) int sockets[2]; int err; - /* tls1_hello contains ServerKeyExchange with custom DH - * parameters */ - if (gnutls_fips140_mode_enabled()) - exit(77); - signal(SIGPIPE, SIG_IGN); err = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); diff --git a/tests/dh-fips-approved.sh b/tests/dh-fips-approved.sh deleted file mode 100755 index 136dd15..0000000 --- a/tests/dh-fips-approved.sh +++ /dev/null @@ -1,127 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2017 Nikos Mavrogiannopoulos -# -# Author: Nikos Mavrogiannopoulos -# -# This file is part of GnuTLS. -# -# GnuTLS 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. -# -# GnuTLS 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 Lesser General Public License -# along with this program. If not, see - -srcdir="${srcdir:-.}" -SERV="${SERV:-../src/gnutls-serv${EXEEXT}}" -CLI="${CLI:-../src/gnutls-cli${EXEEXT}}" -unset RETCODE - -if ! test -x "${SERV}"; then - exit 77 -fi - -if ! test -x "${CLI}"; then - exit 77 -fi - -if test "${WINDIR}" != ""; then - exit 77 -fi - -if ! test -z "${VALGRIND}"; then - VALGRIND="${LIBTOOL:-libtool} --mode=execute ${VALGRIND} --error-exitcode=15" -fi - - -SERV="${SERV} -q" - -. "${srcdir}/scripts/common.sh" - -KEY1=${srcdir}/../doc/credentials/x509/key-rsa.pem -CERT1=${srcdir}/../doc/credentials/x509/cert-rsa.pem -CA1=${srcdir}/../doc/credentials/x509/ca.pem - -ALLOWED_PARAMS=" -rfc3526-group-14-2048 -rfc3526-group-15-3072 -rfc3526-group-16-4096 -rfc3526-group-17-6144 -rfc3526-group-18-8192 -rfc7919-ffdhe2048 -rfc7919-ffdhe3072 -rfc7919-ffdhe4096 -rfc7919-ffdhe6144 -rfc7919-ffdhe8192 -" - -DISALLOWED_PARAMS=" -rfc2409-group-2-1024 -rfc3526-group-5-1536 -rfc5054-1024 -rfc5054-1536 -rfc5054-2048 -rfc5054-3072 -rfc5054-4096 -rfc5054-6144 -rfc5054-8192 -rfc5114-group-22-1024 -rfc5114-group-23-2048 -rfc5114-group-24-2048 -" - -OPTS="--priority=NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-RSA:+AES-128-GCM:-GROUP-ALL" - -for params in $ALLOWED_PARAMS; do - echo "Checking with approved DH params: $params" - - PARAMS=${srcdir}/../doc/credentials/dhparams/${params}.pem - - eval "${GETPORT}" - launch_server $$ ${OPTS} --x509keyfile ${KEY1} --x509certfile ${CERT1} --dhparams ${PARAMS} - PID=$! - wait_server ${PID} - - ${VALGRIND} "${CLI}" ${OPTS} -p "${PORT}" 127.0.0.1 --verify-hostname=localhost --x509cafile ${CA1} /dev/null || \ - fail ${PID} "handshake should have succeeded!" - - kill ${PID} - wait -done - -for params in $DISALLOWED_PARAMS; do - echo "Checking with non-approved DH params: $params" - - PARAMS=${srcdir}/../doc/credentials/dhparams/${params}.pem - - eval "${GETPORT}" - launch_server $$ ${OPTS} --x509keyfile ${KEY1} --x509certfile ${CERT1} --dhparams ${PARAMS} - PID=$! - wait_server ${PID} - - ${VALGRIND} "${CLI}" ${OPTS} -p "${PORT}" 127.0.0.1 --verify-hostname=localhost --x509cafile ${CA1} /dev/null - - RET=$? - - if test $RET -eq 0; then - if test "${GNUTLS_FORCE_FIPS_MODE}" = 1; then - fail ${PID} "handshake should have failed (FIPS mode 1)!" - fi - else - if test "${GNUTLS_FORCE_FIPS_MODE}" != 1; then - fail ${PID} "handshake should have succeeded (FIPS mode 0)!" - fi - fi - - kill ${PID} - wait -done - -exit 0 diff --git a/tests/system.prio b/tests/system.prio index 53baaf2..ef69f6a 100644 --- a/tests/system.prio +++ b/tests/system.prio @@ -1,4 +1,3 @@ HELLO1=NORMAL HELLO2=NORMAL:+AES-128-CBC HELLO3=NONE:+VERS-TLS-ALL:-VERS-SSL3.0:+AEAD:+SHA1:+SHA256:+SHA384:+ECDHE-RSA:+ECDHE-ECDSA:+RSA:+DHE-RSA:+DHE-DSS:+AES-256-GCM:+AES-256-CBC:+CAMELLIA-256-GCM:+CAMELLIA-256-CBC:+AES-128-GCM:+AES-128-CBC:+CAMELLIA-128-GCM:+CAMELLIA-128-CBC:+3DES-CBC:+SIGN-ALL:-SIGN-RSA-MD5:+CURVE-ALL:+COMP-NULL:%PROFILE_LOW -SYSTEM=NORMAL diff --git a/tests/utils.c b/tests/utils.c index 60cd79b..9186a17 100644 --- a/tests/utils.c +++ b/tests/utils.c @@ -50,41 +50,47 @@ int debug = 0; int error_count = 0; int break_on_error = 0; -/* doc/credentials/dhparams/rfc3526-group-14-2048.pem */ const char *pkcs3 = "-----BEGIN DH PARAMETERS-----\n" - "MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n" - "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n" - "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n" - "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n" - "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n" - "5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==\n" + "MIGGAoGAtkxw2jlsVCsrfLqxrN+IrF/3W8vVFvDzYbLmxi2GQv9s/PQGWP1d9i22\n" + "P2DprfcJknWt7KhCI1SaYseOQIIIAYP78CfyIpGScW/vS8khrw0rlQiyeCvQgF3O\n" + "GeGOEywcw+oQT4SmFOD7H0smJe2CNyjYpexBXQ/A0mbTF9QKm1cCAQU=\n" "-----END DH PARAMETERS-----\n"; -/* doc/credentials/dhparams/rfc7919-ffdhe2048.pem */ const char *pkcs3_2048 = "-----BEGIN DH PARAMETERS-----\n" - "MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n" - "+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n" - "87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n" - "YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n" - "7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n" - "ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==\n" - "-----END DH PARAMETERS-----\n"; + "MIICDgKCAQEAvVNCqM8M9ZoVYBKEkV2KN8ELHHJ75aTZiK9z6170iKSgbITkOxsd\n" + "aBCLzHZd7d6/2aNofUeuWdDGHm73d8v53ma2HRVCNESeC2LKsEDFG9FjjUeugvfl\n" + "zb85TLZwWT9Lb35Ddhdk7CtxoukjS0/JkCE+8RGzmk5+57N8tNffs4aSSHSe4+cw\n" + "i4wULDxiG2p052czAMP3YR5egWvMuiByhy0vKShiZmOy1/Os5r6E/GUF+298gDjG\n" + "OeaEUF9snrTcoBwB4yNjVSEbuAh5fMd5zFtz2+dzrk9TYZ44u4DQYkgToW05WcmC\n" + "+LG0bLAH6lrJR5OMgyheZEo6F20z/d2yyQKCAQEAtzcuTHW61SFQiDRouk6eD0Yx\n" + "0k1RJdaQdlRf6/Dcc6lEqnbezL90THzvxkBwfJ5jG1VZE7JlVCvLRkBtgb0/6SCf\n" + "MATfEKG2JMOnKsJxvidmKEp4uN32LketXRrrEBl7rS+HABEfKAzqx+J6trBaq25E\n" + "7FVJFsyoa8IL8N8YUWwhE2UuEfmiqQQaeoIUYC/xD2arMXn9N0W84Nyy2S9IL4ct\n" + "e3Azi1Wc8MMfpbxxDRxXCnM2uMkLYWs1lQmcUUX+Uygv3P8lgS+RJ1Pi3+BWMx0S\n" + "ocsZXqOr6dbEF1WOLObQRK7h/MZp80iVUyrBgX0MbVFN9M5i2u4KKTG95VKRtgIC\n" + "AQA=\n" "-----END DH PARAMETERS-----\n"; -/* doc/credentials/dhparams/rfc7919-ffdhe3072.pem */ const char *pkcs3_3072 = "-----BEGIN DH PARAMETERS-----\n" - "MIIBiAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n" - "+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n" - "87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n" - "YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n" - "7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n" - "ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3\n" - "7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32\n" - "nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu\n" - "N///////////AgEC\n" - "-----END DH PARAMETERS-----\n"; + "MIIDDgKCAYEAtRUay8nDgwE5dSVzW525wEu/d0vrFolvYJSevxg2myj5S+gr3Fgq\n" + "OGaZc4zrBxkxsELc7GuCqaXSOWL4yobT8N05yGbYWkWRPf4crRMx3P7/Gba9WsmH\n" + "BlL71uPf1IN9CanAlabkhV89RKiYaCpUI19+/sq+N2dO874ToBZCNhxZnTgRZ+po\n" + "Gdr6XWM0lQ8imIKSer0px3ZHI+/5gmyPry35tGpwlbyclJAg3wlTSdnqDcLxq7AF\n" + "OZ23PzC3ij7SFErOX9EFBdS2bjtU47O3OkPc9EIYMEv5nwnXICLHslwVifmURAjV\n" + "LfpObL8LYGN4Gac4tFxuDa0PMg0ES5ADugYBwdRFTAtCy5WOYXINzAAOrH9MommT\n" + "rMkELf7JOCaV2ktBsvTlrgMAXeyqbf2YSG6CGjj4QnUuqPybSgwPru7VlahsS2lo\n" + "qjutBPpgIxS53o97Wi3V5kQedKJiNuIDNnJMFNuTADAM+OYwClTH7ZSwTsxEgVpr\n" + "tMH+WnTI7KTJAoIBgQCrELwIUB4oNbf0x+fIpVndhDpl/WcFc/lDtmiRuym5gWbb\n" + "NPeI+1rdhnS2R3+nCJODFQTcPNMgIJuSu2EnDCSs5xJ2k08SAgSzyxEdjBpY7qJe\n" + "+lJPJ12zhcl0vgcvMhb/YgqVe2MKz0RvnYZPwHM/aJbjYjq/6OpK3fVw4M1ZccBK\n" + "QD4OHK8HOvGU7Wf6kRIcxUlfn15spMCIsrAZQBddWLmQgktsxJNUS+AnaPwTBoOv\n" + "nGCr1vzw8OS1DtS03VCmtqt3otXhJ3D2oCIG6ogxVAKfHR30KIfzZLBfmCjdzHmH\n" + "x4OwYTN1wy5juA438QtiDtcgK60ZqSzQO08ZklRncA/TkkyEH6kPn5KSh/hW9O3D\n" + "KZeAY/KF0/Bc1XNtqPEYFb7Vo3rbTsyjXkICN1Hk9S0OIKL42K7rWBepO9KuddSd\n" + "aXgH9staP0HXCyyW1VAyqo0TwcWDhE/R7IQQGGwGyd4rD0T+ySW/t09ox23O6X8J\n" + "FSp6mOVNcuvhB5U2gW8CAgEA\n" "-----END DH PARAMETERS-----\n"; void _fail(const char *format, ...) {