�����JFIF��XX����������    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222�����"����4���������������������������� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������,�PG"Z_�4�˷����kjز�Z�,F+��_z�,�© �����zh6�٨�ic�fu������������������������������������#ډb���_�N��?�����������wQ���5-�~�I���8���������������������������������TK<5o�Iv-������������������k�_U_������������������������������~b�M��d��������Ӝ�U�Hh��?]��E�w��Q���k�{��_}qFW7HTՑ��Y��F�����?_�'ϔ��_�Ջt������������������������=||I �����6�έ"�����D���/[�k�9����Y�8������ds|\���Ҿp6�Ҵ���]��.����6���z<�v��@]�i%������������������������$j��~����g��J>��no����pM[me�i$[�����������s�o�ᘨ�˸ nɜG-�ĨU�ycP���3.DB�li�;���������������������hj���x����7Z^�N�h��������N3u{�:j�����x�힞��#M��&��jL P@��_���� P�������������������&��o8��������9������@Sz���6�t7#O�ߋ �����s}Yf�T������lmr����Z)'N��k�۞p�����w\�T���������������ȯ?�8`���O��i{wﭹW�[�r�� ��Q4F�׊������3m&L�=��h3�������z~��#����\�l :�F,j@�� ʱ�wQT����8�"kJO����6�֚l������������������}����R�>ډK���]��y����&����p�}b������;N�1�m�r$����|��7�>e�@���B�TM*-i�H��g�D�)� E�m�|�ؘbҗ�a���Ҿ����������������t4�����o���G��*oCN�rP���Q��@z,|?W[0���������:�n,j���WiE��W������$~/�hp\��?��{(�0���+�Y8rΟ�+����>S-S���������������VN;���}�s?.����� w��9��˟<���Mq4�Wv'������{)0�1mB����V����W[��������8�/<� �%���wT^�5���b��)iM� p�g�N�&ݝ������������VO~��q���u���9��� ����!��J27�����$����O-���! �:���%H��� ـ�������y�ΠM=t{!S�� �oK8�������t<����è��������:a��������[������ա�H���~��w��Qz`�p����o�^ ������Q��n����� �,uu�C��$ ^���,�������8�#��:�6��e�|~�����������!�3��3.�\0�����q��o�4`.|� ����y�Q�`~;�d�ׯ,��O�Zw�������`73�v�܋�<�����Ȏ�� ـ4k��5�K�a�u�=9Yd��$>x�A�&�� j0� ���vF��� Y���|�y��� ~�6�@c��1vOp��������Ig�����4��l�OD�����L����� R���c���j�_�uX�6��3?nk��Wy�f;^*B� ��@���~a�`��Eu�������+�����6�L��.ü>��}y���}_�O�6�͐�:�Yr���G�X��kG������l^w����������~㒶sy���Iu�!���� W ��X��N�7BV��O��!X�2����wvG�R�f�T#�����t�/?���%8�^�W�aT����G�cL�M���I��(J����1~�8�?aT ���]����AS�E��(��*E}� 2������#I/�׍qz��^t�̔���������b�Yz4x����t�){ OH�����+(E��A&�N�������XT��o��"�XC����'���)}�J�z�p� ����~5�}�^����+�6����w��c��Q�|�Lp�d�H��}�(�.|����k��c4^�����"�����Z?ȕ ��a<�������L�!0�39C� �Eu�����C�F�Ew�ç ;�n?�*o���B�8�bʝ���'#Rqf����M}7����]�������s2tcS{�\icTx;�\��7K���P������ʇ Z O-��~�������c>"��?��������P�����E��O�8��@�8��G��Q�g�a�Վ���󁶠��䧘��_%#r�>�����1�z�a���eb��qcP��ѵ��n���#L��� =��׀t� L�7�`�����V����A{�C:�g���e@�����w1 Xp�3�c3�ġ�������p��M"'-�@n4���fG���B3�DJ�8[Jo�ߐ���gK)ƛ��$���� �������8�3�����+���� �����6�ʻ���� ���S�kI�*KZlT _`�������?��K�����QK�d���������B`�s}�>���`������*�>��,*@J�d�oF*�����弝��O}�k��s��]��y�ߘ�������c1G�V���<=�7��7����6��q�PT��tXԀ�!9*4�4Tހ���3XΛex�46�������Y��D ����� ����BdemDa����\�_l,����G�/���֌7���Y�](�xTt^%�GE�����4�}bT����ڹ�����;��Y)���B�Q��u��>J/J ���⮶.�XԄ��j�ݳ������+E��d ���r�5�_D�����1 ���o�� �B�x�΢�#����<��W�����8���R6�@���g�M�.��� dr�D��>(otU��@�x=��~v���2� ӣ�d�oBd�����3�eO�6�㣷����������ݜ�6��6Y��Qz`����S��{���\P��~z m5{J/L��1������<�e�ͅPu���b�]�ϔ��������'�������f�b� Zpw��c`"��i���BD@:)ִ�:�]��h���v�E��w���T�l�������P����"Ju�}��وV ��J��G6��. J/�Qgl߭�e�����@�z�Zev2u����)]կ���������7x�������s�M�-<ɯ�c��r��v�����@��$�ޮ}lk���a����'����>x��O\�Z������Fu>������ck#��&:��`�$��ai�>2Δ����l���oF[h�������lE�ܺ�Π���k:)���`������� $[6�����9�����kOw�\|�����8}������ބ:��񶐕��������I�A1/���=�2[�,�!��.}gN#�u����b���� ~���������݊��}34q�����d�E��L��������c��$���"�[q�U�硬g^��%B ��z���r�p�������J�ru%v\h�����1Y�ne`������ǥ:g����pQM~�^��Xi� ��`S�:V2������9.�P���V������?B�k�� ��������AEvw%�_�9C�Q����wKekP�ؠ�\������;Io d�{ ߞo�c1eP�����\� `����E=���@K<�Y��������eڼ�J����w����{av�F�'�M�@��������������/J��+9p����|]���������Iw &`���8���&�M�hg���[�{�������Xj���%��Ӓ�������������������$��(�����ʹN�������<>�I���RY�����K2�NPlL�ɀ�)��&e��������B+ь����(������������������� � �JTx����_?EZ� }@���� 6�U���뙢ط�z��dWI��n` D����噥�[��uV��"�G&�����Ú����2�g�}&m���������������������?ċ���"����Om#�������������������������� ��{���������������������ON��"S�X���Ne��ysQ���@�������������Fn��Vg�����dX�~nj����������������������]J�<�K]:����FW���b�������62����������=��5f����JKw����bf�X������������������������55��~J �%^�������:�-�QIE��P��v�nZum� z � ~ə ���� ���ة����;�f��\v�������g�8�1��f2�������������������������4;�V���ǔ�)�������������������9���1\������������������������������c��v�/'Ƞ�w������������������$�4�R-��t����������������������������������� e�6�/�ġ �̕Ecy�J���u�B���<�W�ַ~�w[B1L۲�-JS΂�{���΃�������������������������������������������A��20�c#���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@���� 0!1@AP"#2Q`$3V�%45a6�FRUq����� ������^7ׅ,$n��������+��F�`��2X'��0vM��p�L=�������5��8������u�p~���.�`r�����\����O��,ư�0oS ��_�M�����l���4�kv\JSd���x���SW�<��Ae�IX����������$I���w�:S���y���›R��9�Q[���,�5�;�@]�%���u�@ *ro�lbI �� ��+���%m:�͇ZV�����u�̉����θau<�fc�.����{�4Ա� �Q����*�Sm��8\ujqs]{kN���)qO�y�_*dJ�b�7���yQqI&9�ԌK!�M}�R�;�������S�T���1���i[U�ɵz�]��U)V�S6���3$K{��ߊ<�(� E]Զ[ǼENg�����'�\?#)Dkf��J���o��v���'�%ƞ�&K�u��!��b�35LX�Ϸ��63$K�a�;�9>,R��W��3�3� d�JeTYE.Mϧ��-�o�j3+y��y^�c�������VO�9NV\nd�1 ��!͕_)a�v;����թ�M�lWR1��)El��P;��yوÏ�u 3�k�5Pr6<�⒲l�!˞*��u־�n�!�l:����UNW ��%��Chx8vL'��X�@��*��)���̮��ˍ��� ����D-M�+J�U�kvK����+�x8��cY������?�Ԡ��~3mo��|�u@[XeY�C�\Kp�x8�oC�C�&����N�~3-H���� ��MX�s�u<`���~"WL��$8ξ��3���a�)|:@�m�\���^�`�@ҷ)�5p+��6���p�%i)P M���ngc�����#0Aruz���RL+xSS?���ʮ}()#�t��mˇ!��0}}y����<�e� �-ή�Ԩ��X������ MF���ԙ~l L.3���}�V뽺�v������멬��Nl�)�2����^�Iq��a��M��qG��T�����c3#������3U�Ǎ���}��לS�|qa��ڃ�+���-��2�f����/��bz��ڐ�� �ݼ[2�ç����k�X�2�* �Z�d���J�G����M*9W���s{��w���T��x��y,�in�O�v��]���n����P�$��JB@=4�OTI�n��e�22a\����q�d���%�$��(���:���: /*�K[PR�fr\nڙdN���F�n�$�4��[�� U�zƶ����� �mʋ���,�ao�u 3�z� �x��Kn����\[��VFmbE;�_U��&V�Gg�]L�۪&#n%�$ɯ��dG���D�TI=�%+AB�Ru#��b4�1�»x�cs�YzڙJG��f��Il���d�eF'T� iA��T���uC�$����Y��H?����[!G`}���ͪ� �纤Hv\������j�Ex�K���!���OiƸ�Yj�+u-<���'q����uN�*�r\��+�]���<�wOZ.fp�ێ��,-*)V?j-kÊ#�`�r��dV����(�ݽBk�����G�ƛk�QmUڗe��Z���f}|����8�8��a���i��3'J�����~G_�^���d�8w������ R�`(�~�.��u���l�s+g�bv���W���lGc}��u���afE~1�Ue������Z�0�8�=e�� f@/�jqEKQQ�J���oN��J���W5~M>$6�Lt�;$ʳ{���^��6�{����v6���ķܰg�V�cnn �~z�x�«�,2�u�?cE+Ș�H؎�%�Za�)���X>uW�Tz�Nyo����s���FQƤ��$��*�&�LLXL)�1�" L��eO��ɟ�9=���:t��Z���c��Ž���Y?�ӭV�wv�~,Y��r�ۗ�|�y��GaF�����C�����.�+� ���v1���fήJ�����]�S��T��B��n5sW}y�$��~z�'�c ��8 ��� ,! �p��VN�S��N�N�q��y8z˱�A��4��*��'������2n<�s���^ǧ˭P�Jޮɏ�U�G�L�J�*#��<�V��t7�8����TĜ>��i}K%,���)[��z�21z ?�N�i�n1?T�I�R#��m-�����������������1����lA�`��fT5+��ܐ�c�q՝��ʐ��,���3�f2U�եmab��#ŠdQ�y>\��)�SLY����w#��.���ʑ�f��� ,"+�w�~�N�'�c�O�3F�������N<���)j��&��,-� �љ���֊�_�zS���TǦ����w�>��?�������n��U仆�V���e�����0���$�C�d���rP �m�׈e�Xm�Vu� �L��.�bֹ��� �[Դaզ���*��\y�8�Է:�Ez\�0�Kq�C b��̘��cө���Q��=0Y��s�N��S.����3.���O�o:���#���v7�[#߫ ��5�܎�L���Er4���9n��COWlG�^��0k�%<���ZB���aB_���������'=��{i�v�l�$�uC���mƎҝ{�c㱼�y]���W�i ��ߧc��m�H� m�"�"�����;Y�ߝ�Z�Ǔ�����:S#��|}�y�,/k�Ld� TA�(�AI$+I3��;Y*���Z��}|��ӧO��d�v��..#:n��f>�>���ȶI�TX��� 8��y����"d�R�|�)0���=���n4��6ⲑ�+��r<�O�܂~zh�z����7ܓ�HH�Ga롏���nCo�>������a ���~]���R���̲c?�6(�q�;5%� |�uj�~z8R�=X��I�V=�|{v�Gj\gc��q����z�؋%M�ߍ����1y��#��@f^���^�>N������#x#۹��6�Y~�?�dfPO��{��P�4��V��u1E1J �*|���%����JN��`eWu�zk M6���q t[�� ��g�G���v��WIG��u_ft����5�j�"�Y�:T��ɐ���*�;� e5���4����q$C��2d�}���� _S�L#m�Yp��O�.�C�;��c����Hi#֩%+) �Ӎ��ƲV���SYź��g |���tj��3�8���r|���V��1#;.SQ�A[���S������#���`n�+���$��$�I �P\[�@�s��(�ED�z���P��])8�G#��0B��[ى��X�II�q<��9�~[Z멜�Z�⊔IWU&A>�P~�#��dp<�?����7���c��'~���5 ��+$���lx@�M�dm��n<=e�dyX��?{�|Aef ,|n3�<~z�ƃ�uۧ�����P��Y,�ӥQ�*g�#먙R�\���;T��i,��[9Qi歉����c>]9�� ��"�c��P�� �Md?٥��If�ت�u��k��/����F��9�c*9��Ǎ:�ØF���z�n*�@|I�ށ9����N3{'��[�'ͬ�Ҳ4��#}��!�V� Fu��,�,mTIk���v C�7v���B�6k�T9��1�*l� '~��ƞF��lU��'�M ����][ΩũJ_�{�i�I�n��$����L�� j��O�dx�����kza۪��#�E��Cl����x˘�o�����V���ɞ�ljr��)�/,�߬h�L��#��^��L�ф�,íMƁe�̩�NB�L�����iL����q�}��(��q��6IçJ$�W�E$��:������=#����(�K�B����zђ <��K(�N�۫K�w��^O{!����)��H���>x�������lx�?>Պ�+�>�W���,Ly!_�D���Ō�l���Q�!�[ �S����J��1��Ɛ�Y}��b,+�Lo�x�ɓ)����=�y�oh�@�꥟/��I��ѭ=��P�y9��� �ۍYӘ�e+�p�Jnϱ?V\SO%�(�t� ���=?MR�[Ș�����d�/ ��n�l��B�7j� ��!�;ӥ�/�[-���A�>��dN�sLj ��,ɪv��=1c�.SQ�O3�U���ƀ�ܽ�E����������̻��9G�ϷD�7(�}��Ävӌ\��y�_0[w ���<΍>����a_��[0+�L��F.�޺��f�>oN�T����q;���y\��bՃ��y�jH�<|q-eɏ�_?_9+P���Hp$�����[ux�K w�Mw��N�ی'$Y2�=��q���KB��P��~�������Yul:�[<����F1�2�O���5=d����]Y�sw:���Ϯ���E��j,_Q��X��z`H1,#II ��d�wr��P˂@�ZJV����y$�\y�{}��^~���[:N����ߌ�U�������O��d�����ؾe��${p>G��3c���Ė�lʌ�� ת��[��`ϱ�-W����dg�I��ig2��� ��}s ��ؤ(%#sS@���~���3�X�nRG�~\jc3�v��ӍL��M[JB�T��s3}��j�Nʖ��W����;7���ç?=X�F=-�=����q�ߚ���#���='�c��7���ڑW�I(O+=:uxq�������������e2�zi+�kuG�R��������0�&e�n���iT^J����~\jy���p'dtG��s����O��3����9* �b#Ɋ�� p������[Bws�T�>d4�ۧs���nv�n���U���_�~,�v����ƜJ1��s�� �QIz���)�(lv8M���U=�;����56��G���s#�K���MP�=��LvyGd��}�VwWBF�'�à �?MH�U�g2�� ����!�p�7Q��j��ڴ����=��j�u��� Jn�A s���uM������e��Ɔ�Ҕ�!)�'��8Ϣ�ٔ���ޝ(��Vp���צ֖d=�IC�J�Ǡ{q������kԭ�߸���i��@K����u�|�p=..�*+����x�����z[Aqġ#s2a�Ɗ���RR�)*HRsi�~�a &f��M��P����-K�L@��Z��Xy�'x�{}��Zm+���:�)�) IJ�-i�u���� ���ܒH��'��L(7�y�GӜq���� j��� 6ߌg1�g�o���,kر���tY�?W,���p���e���f�OQS��!K�۟cҒA�|ս�j�>��=⬒��˧L[�� �߿2JaB~R��u�:��Q�] �0H~���]�7��Ƽ�I���(�}��cq '�ήET���q�?f�ab���ӥvr� �)o��-Q��_'����ᴎo��K������;��V���o��%���~OK ����*��b�f:���-ťIR��`B�5!RB@���ï�� �u �̯e\�_U�_������� g�ES��3��������QT��a�����x����U<~�c?�*�#]�MW,[8O�a�x��]�1bC|踤�P��lw5V%�)�{t�<��d��5���0i�XSU��m:��Z�┵�i�"��1�^B�-��P�hJ��&)O��*�D��c�W��vM��)����}���P��ܗ-q����\mmζZ-l@�}��a��E�6��F�@��&Sg@���ݚ�M����� ȹ 4����#p�\H����dYDo�H���"��\��..R�B�H�z_�/5˘����6��KhJR��P�mƶi�m���3��,#c�co��q�a)*P�t����R�m�k�7x�D�E�\Y�閣_X�<���~�)���c[[�BP����6�Yq���S��0����%_����;��Àv�~�| VS؇ ��'O0��F0��\���U�-�d@�����7�SJ*z��3n��y��P����O����������m�~�P�3|Y��ʉr#�C�<�G~�.,! ���bqx���h~0=��!ǫ�jy����l��O,�[B��~��|9��ٱ����Xly�#�i�B��g%�S��������tˋ���e���ې��\[d�t)��.+u�|1 ������#�~Oj����hS�%��i.�~X���I�H�m��0n���c�1uE�q��cF�RF�o���7� �O�ꮧ� ���ۛ{��ʛi5�rw?׌#Qn�TW��~?y$��m\�\o����%W� ?=>S�N@�� �Ʈ���R����N�)�r"C�:��:����� �����#��qb��Y�. �6[��2K����2u�Ǧ�HYR��Q�MV��� �G�$��Q+.>�����nNH��q�^��� ����q��mM��V��D�+�-�#*�U�̒ ���p욳��u:�������IB���m����PV@O���r[b= �� ��1U�E��_Nm�yKbN�O���U�}�the�`�|6֮P>�\2�P�V���I�D�i�P�O;�9�r�mAHG�W�S]��J*�_�G��+kP�2����Ka�Z���H�'K�x�W�MZ%�O�YD�Rc+o��?�q��Ghm��d�S�oh�\�D�|:W������UA�Qc yT�q��������~^�H��/��#p�CZ���T�I�1�ӏT����4��"�ČZ�����}��`w�#�*,ʹ�� ��0�i��課�Om�*�da��^gJ݅{���l�e9uF#T�ֲ��̲�ٞC"�q���ߍ ոޑ�o#�XZTp����@ o�8��(jd��xw�]�,f���`~��|,s��^����f�1���t��|��m�򸄭/ctr��5s��7�9Q�4�H1꠲BB@�l9@���C�����+�wp�xu�£Yc�9��?`@#�o�mH�s2��)�=��2�.�l����jg�9$�Y�S�%*L������R�Y������7Z���,*=�䷘$�������arm�o�ϰ���UW.|�r�uf����IGw�t����Zwo��~5 ��YյhO+=8fF�)�W�7�L9lM�̘·Y���֘YLf�큹�pRF���99.A �"wz��=E\Z���'a� 2��Ǚ�#;�'}�G���*��l��^"q��+2FQ� hj��kŦ��${���ޮ-�T�٭cf�|�3#~�RJ����t��$b�(R��(����r���dx� >U b�&9,>���%E\� Ά�e�$��'�q't��*�א���ެ�b��-|d���SB�O�O��$�R+�H�)�܎�K��1m`;�J�2�Y~9��O�g8=vqD`K[�F)k�[���1m޼c��n���]s�k�z$@��)!I �x՝"v��9=�ZA=`Ɠi �:�E��)`�7��vI��}d�YI�_ �o�:ob���o ���3Q��&D&�2=�� �Ά��;>�h����y.*ⅥS������Ӭ�+q&����j|UƧ�����}���J0��WW< ۋS�)jQR�j���Ư��rN)�Gű�4Ѷ(�S)Ǣ�8��i��W52���No˓� ۍ%�5brOn�L�;�n��\G����=�^U�dI���8$�&���h��'���+�(������cȁ߫k�l��S^���cƗjԌE�ꭔ��gF���Ȓ��@���}O���*;e�v�WV���YJ\�]X'5��ղ�k�F��b 6R�o՜m��i N�i�����>J����?��lPm�U��}>_Z&�KK��q�r��I�D�Չ~�q�3fL�:S�e>���E���-G���{L�6p�e,8��������QI��h��a�Xa��U�A'���ʂ���s�+טIjP�-��y�8ۈZ?J$��W�P� ��R�s�]��|�l(�ԓ��sƊi��o(��S0���Y� 8�T97.�����WiL��c�~�dxc�E|�2!�X�K�Ƙਫ਼�$((�6�~|d9u+�qd�^3�89��Y�6L�.I�����?���iI�q���9�)O/뚅����O���X��X�V��ZF[�یgQ�L��K1���RҖr@v�#��X�l��F���Нy�S�8�7�kF!A��sM���^rkp�jP�DyS$N���q���nxҍ!U�f�!eh�i�2�m����`�Y�I�9r�6� �TF���C}/�y�^���Η���5d�'��9A-��J��>{�_l+�`��A���[�'��յ�ϛ#w:݅�%��X�}�&�PSt�Q�"�-��\縵�/����$Ɨh�Xb�*�y��BS����;W�ջ_mc�����vt?2}1�;qS�d�d~u:2k5�2�R�~�z+|HE!)�Ǟl��7`��0�<�,�2*���Hl-��x�^����'_TV�gZA�'j� ^�2Ϊ��N7t�����?w�� �x1��f��Iz�C-Ȗ��K�^q�;���-W�DvT�7��8�Z�������� hK�(P:��Q- �8�n�Z���܃e貾�<�1�YT<�,�����"�6{�/ �?�͟��|1�:�#g��W�>$����d��J��d�B���=��jf[��%rE^��il:��B���x���Sּ�1հ��,�=��*�7 fcG��#q� �eh?��2�7�����,�!7x��6�n�LC�4x��},Geǝ�tC.��vS �F�43��zz\��;QYC,6����~;RYS/6���|2���5���v��T��i����������mlv��������&� �nRh^ejR�LG�f���? �ۉҬܦƩ��|��Ȱ����>3����!v��i�ʯ�>�v��オ�X3e���_1z�Kȗ\<������!�8���V��]��?b�k41�Re��T�q��mz��TiOʦ�Z��Xq���L������q"+���2ۨ��8}�&N7XU7Ap�d�X��~�׿��&4e�o�F��� �H�����O���č�c�� 懴�6���͉��+)��v;j��ݷ�� �UV�� i��� j���Y9GdÒJ1��詞�����V?h��l�����l�cGs�ځ�������y�Ac������\V3�? �� ܙg�>qH�S,�E�W�[�㺨�uch�⍸�O�}���a��>�q�6�n6�����N6�q��������N� ���! 1AQaq�0@����"2BRb�#Pr���3C`��Scst���$4D���%Td���� ?�����N����a��3��m���C���w��������xA�m�q�m����m������$����4n淿t'��C"w��zU=D�\R+w�p+Y�T�&�պ@��ƃ��3ޯ?�Aﶂ��aŘ���@-�����Q�=���9D��ռ�ѻ@��M�V��P��܅�G5�f�Y<�u=,EC)�<�Fy'�"�&�չ�X~f��l�KԆV��?�� �W�N����=(� �;���{�r����ٌ�Y���h{�١������jW����P���Tc�����X�K�r��}���w�R��%��?���E��m�� �Y�q|����\lEE4����r���}�lsI�Y������f�$�=�d�yO����p�����yBj8jU�o�/�S��?�U��*������ˍ�0�������u�q�m [�?f����a�� )Q�>����6#������� ?����0UQ����,IX���(6ڵ[�DI�MNލ�c&���υ�j\��X�R|,4��� j������T�hA�e��^���d���b<����n�� �즇�=!���3�^�`j�h�ȓr��jẕ�c�,ٞX����-����a�ﶔ���#�$��]w�O��Ӫ�1y%��L�Y<�wg#�ǝ�̗`�x�xa�t�w��»1���o7o5��>�m뭛C���Uƃߜ}�C���y1Xνm�F8�jI���]����H���ۺиE@I�i;r�8ӭ�����V�F�Շ| ��&?�3|x�B�MuS�Ge�=Ӕ�#BE5G������Y!z��_e��q�р/W>|-�Ci߇�t�1ޯќd�R3�u��g�=0 5��[?�#͏��q�cf���H��{ ?u�=?�?ǯ���}Z��z���hmΔ�BFTW�����<�q��(v� ��!��z���iW]*�J�V�z��gX֧A�q�&��/w���u�gYӘa���; �i=����g:��?2�dž6�ى�k�4�>�Pxs����}������G�9���3 ���)gG�R<>r h�$��'nc�h�P��Bj��J�ҧH� -��N1���N��?��~��}-q!=��_2hc�M��l�vY%UE�@|�v����M2�.Y[|y�"Eï��K�ZF,�ɯ?,q�?v�M 80jx�"�;�9vk�����+ ֧�� �ȺU��?�%�vcV��mA�6��Qg^M�����A}�3�nl� QRN�l8�kkn�'�����(��M�7m9و�q���%ޟ���*h$Zk"��$�9��: �?U8�Sl��,,|ɒ��xH(ѷ����Gn�/Q�4�P��G�%��Ա8�N��!� �&�7�;���eKM7�4��9R/%����l�c>�x;������>��C�:�����t��h?aKX�bhe�ᜋ^�$�Iհ �hr7%F$�E��Fd���t��5���+�(M6�t����Ü�UU|zW�=a�Ts�Tg������dqP�Q����b'�m���1{|Y����X�N��b �P~��F^F:����k6�"�j!�� �I�r�`��1&�-$�Bevk:y���#y�w��I0��x��=D�4��tU���P�ZH��ڠ底taP��6����b>�xa�����Q�#� WeF��ŮNj�p�J* mQ�N�����*I�-*�ȩ�F�g�3 �5��V�ʊ�ɮ�a��5F���O@{���NX��?����H�]3��1�Ri_u��������ѕ�� ����0��� F��~��:60�p�͈�S��qX#a�5>���`�o&+�<2�D����: �������ڝ�$�nP���*)�N�|y�Ej�F�5ټ�e���ihy�Z �>���k�bH�a�v��h�-#���!�Po=@k̆IEN��@��}Ll?j�O������߭�ʞ���Q|A07x���wt!xf���I2?Z��<ץ�T���cU�j��]���陎Ltl �}5�ϓ��$�,��O�mˊ�;�@O��jE��j(�ا,��LX���LO���Ц�90�O �.����a��nA���7������j4 ��W��_ٓ���zW�jcB������y՗+EM�)d���N�g6�y1_x��p�$Lv�:��9�"z��p���ʙ$��^��JԼ*�ϭ����o���=x�Lj�6�J��u82�A�H�3$�ٕ@�=Vv�]�'�qEz�;I˼��)��=��ɯ���x �/�W(V���p�����$ �m�������u�����񶤑Oqˎ�T����r��㠚x�sr�GC��byp�G��1ߠ�w e�8�$⿄����/�M{*}��W�]˷.�CK\�ުx���/$�WP�w���r� |i���&�}�{�X� �>��$-��l���?-z���g����lΆ���(F���h�vS*���b���߲ڡn,|)mrH[���a�3�ר�[1��3o_�U�3�TC�$��(�=�)0�kgP���� ��u�^=��4 �WYCҸ:��vQ�ר�X�à��tk�m,�t*��^�,�}D*�� �"(�I��9R����>`�`��[~Q]�#af��i6l��8���6�:,s�s�N6�j"�A4���IuQ��6E,�GnH��zS�HO�uk�5$�I�4��ؤ�Q9�@��C����wp��BGv[]�u�Ov����0I4���\��y�����Q�Ѹ��~>Z��8�T��a��q�ޣ;z��a���/��S��I:�ܫ_�|������>=Z����8:�S��U�I�J��"IY���8%b8���H��:�QO�6�;7�I�S��J��ҌAά3��>c���E+&jf$eC+�z�;��V����� �r���ʺ������my�e���aQ�f&��6�ND���.:��NT�vm�<- u���ǝ\MvZY�N�NT��-A�>jr!S��n�O 1�3�Ns�%�3D@���`������ܟ 1�^c<���� �a�ɽ�̲�Xë#�w�|y�cW�=�9I*H8�p�^(4���՗�k��arOcW�tO�\�ƍR��8����'�K���I�Q�����?5�>[�}��yU�ײ -h��=��% q�ThG�2�)���"ו3]�!kB��*p�FDl�A���,�eEi�H�f�Ps�����5�H:�Փ~�H�0Dت�D�I����h�F3�������c��2���E��9�H��5�zԑ�ʚ�i�X�=:m�xg�hd(�v����׊�9iS��O��d@0ڽ���:�p�5�h-��t�&���X�q�ӕ,��ie�|���7A�2���O%P��E��htj��Y1��w�Ѓ!����  ���� ࢽ��My�7�\�a�@�ţ�J ��4�Ȼ�F�@o�̒?4�wx��)��]�P��~�����u�����5�����7X ��9��^ܩ�U;Iꭆ 5 �������eK2�7(�{|��Y׎ �V��\"���Z�1� Z�����}��(�Ǝ"�1S���_�vE30>���p;� ΝD��%x�W�?W?v����o�^V�i�d��r[��/&>�~`�9Wh��y�;���R���� ;;ɮT��?����r$�g1�K����A��C��c��K��l:�'��3 c�ﳯ*"t8�~l��)���m��+U,z��`(��>yJ�?����h>��]��v��ЍG*�{`��;y]��I�T� ;c��NU�fo¾h���/$���|NS���1�S�"�H��V���T���4��uhǜ�]�v;���5�͠x��'C\�SBpl���h}�N����� A�Bx���%��ޭ�l��/����T��w�ʽ]D�=����K���ž�r㻠l4�S�O?=�k �M:� ��c�C�a�#ha���)�ѐxc�s���gP�iG���{+���x���Q���I= �� z��ԫ+ �8"�k�ñ�j=|����c ��y��CF��/���*9ж�h{ �?4�o� ��k�m�Q�N�x��;�Y��4膚�a�w?�6�>�e]�����Q�r�:����g�,i"�����ԩA��*M�<�G��b�if��l^M��5�� �Ҩ�{����6J��ZJ�����P�*�����Y���ݛu�_4�9�I8�7���������,^ToR���m4�H��?�N�S�ѕw��/S��甍�@�9H�S�T��t�ƻ���ʒU��*{Xs�@����f������֒Li�K{H�w^���������Ϥm�tq���s� ���ք��f:��o~s��g�r��ט� �S�ѱC�e]�x���a��) ���(b-$(�j>�7q�B?ӕ�F��hV25r[7 Y� }L�R��}����*sg+��x�r�2�U=�*'WS��ZDW]�WǞ�<��叓���{�$�9Ou4��y�90-�1�'*D`�c�^o?(�9��u���ݐ��'PI&� f�Jݮ�������:wS����jfP1F:X �H�9dԯ����˝[�_54 �}*;@�ܨ�� ð�yn�T���?�ןd�#���4rG�ͨ��H�1�|-#���Mr�S3��G�3�����)�.᧏3v�z֑��r����$G"�`j �1t��x0<Ɔ�Wh6�y�6��,œ�Ga��gA����y��b��)���h�D��ß�_�m��ü �gG;��e�v��ݝ�nQ� ��C����-�*��o���y�a��M��I�>�<���]obD��"�:���G�A��-\%LT�8���c�)��+y76���o�Q�#*{�(F�⽕�y����=���rW�\p���۩�c���A���^e6��K������ʐ�cVf5$�'->���ՉN"���F�"�UQ@�f��Gb~��#�&�M=��8�ט�JNu9��D��[̤�s�o�~������� G��9T�tW^g5y$b��Y'��س�Ǵ�=��U-2 #�MC�t(�i� �lj�@Q 5�̣i�*�O����s�x�K�f��}\��M{E�V�{�υ��Ƈ�����);�H����I��fe�Lȣr�2��>��W��I�Ȃ6������i��k�� �5�YOxȺ����>��Y�f5'��|��H+��98pj�n�.O�y�������jY��~��i�w'������l�;�s�2��Y��:'lg�ꥴ)o#'Sa�a�K��Z� �m��}�`169�n���"���x��I ��*+� }F<��cГ���F�P�������ֹ*�PqX�x۩��,� ��N�� �4<-����%����:��7����W���u�`����� $�?�I��&����o��o��`v�>��P��"��l���4��5'�Z�gE���8���?��[�X�7(��.Q�-��*���ތL@̲����v��.5���[��=�t\+�CNܛ��,g�SQnH����}*F�G16���&:�t��4ُ"A��̣��$�b �|����#rs��a�����T�� ]�<�j��B�S�('$�ɻ� �wP;�/�n��?�ݜ��x�F��yUn�~mL*-�������Xf�wd^�a�}��f�,=t�׵i�.2/wpN�Ep8�OР���•��R�FJ� 55TZ��T �ɭ�<��]��/�0�r�@�f��V��V����Nz�G��^���7hZi����k��3�,kN�e|�vg�1{9]_i��X5y7� 8e]�U����'�-2,���e"����]ot�I��Y_��n�(JҼ��1�O ]bXc���Nu�No��pS���Q_���_�?i�~�x h5d'�(qw52] ��'ޤ�q��o1�R!���`ywy�A4u���h<קy���\[~�4�\ X�Wt/� 6�����n�F�a8��f���z �3$�t(���q��q�x��^�XWeN'p<-v�!�{�(>ӽDP7��ո0�y)�e$ٕv�Ih'Q�EA�m*�H��RI��=:��� ���4牢) �%_iN�ݧ�l]� �Nt���G��H�L��� ɱ�g<���1V�,�J~�ٹ�"K��Q�� 9�HS�9�?@��k����r�;we݁�]I�!{ �@�G�[�"��`���J:�n]�{�cA�E����V��ʆ���#��U9�6����j�#Y�m\��q�e4h�B�7��C�������d<�?J����1g:ٳ���=Y���D�p�ц� ׈ǔ��1�]26؜oS�'��9�V�FVu�P�h�9�xc�oq�X��p�o�5��Ա5$�9W�V(�[Ak�aY錎qf;�'�[�|���b�6�Ck��)��#a#a˙��8���=äh�4��2��C��4tm^ �n'c����]GQ$[Wҿ��i���vN�{Fu ��1�gx��1┷���N�m��{j-,��x�� Ūm�ЧS�[�s���Gna���䑴�� x�p 8<������97�Q���ϴ�v�aϚG��Rt�Һ׈�f^\r��WH�JU�7Z���y)�vg=����n��4�_)y��D'y�6�]�c�5̪��\� �PF�k����&�c;��cq�$~T�7j ���nç]�<�g ":�to�t}�159�<�/�8������m�b�K#g'I'.W������6��I/��>v��\�MN��g���m�A�yQL�4u�Lj�j9��#44�t��l^�}L����n��R��!��t��±]��r��h6ٍ>�yҏ�N��fU�� ���� Fm@�8}�/u��jb9������he:A�y�ծw��GpΧh�5����l}�3p468��)U��d��c����;Us/�֔�YX�1�O2��uq�s��`hwg�r~�{ R��mhN��؎*q 42�*th��>�#���E����#��Hv�O����q�}������6�e��\�,Wk�#���X��b>��p}�դ��3���T5��†��6��[��@��P�y*n��|'f�֧>�lư΂�̺����SU�'*�q�p�_S�����M�� '��c�6������m�� ySʨ;M��r���Ƌ�m�Kxo,���Gm�P��A�G�:��i��w�9�}M(�^�V��$ǒ�ѽ�9���|���� �a����J�SQ�a���r�B;����}���ٻ֢�2�%U���c�#�g���N�a�ݕ�'�v�[�OY'��3L�3�;,p�]@�S��{ls��X�'���c�jw��k'a�.��}�}&�� �dP�*�bK=ɍ!����;3n�gΊU�ߴmt�'*{,=SzfD� A��ko~�G�aoq�_mi}#�m�������P�Xhύ�����mxǍ�΂���巿zf��Q���c���|kc�����?���W��Y�$���_Lv����l߶��c���`?����l�j�ݲˏ!V��6����U�Ђ(A���4y)H���p�Z_�x��>���e���R��$�/�`^'3qˏ�-&Q�=?��CFVR �D�fV�9��{�8g�������n�h�(P"��6�[�D���< E�����~0<@�`�G�6����Hг�cc�� �c�K.5��D��d�B���`?�XQ��2��ٿyqo&+�1^� DW�0�ꊩ���G�#��Q�nL3��c���������/��x ��1�1�[y�x�პCW��C�c�UĨ80�m�e�4.{�m��u���I=��f�����0QRls9���f���������9���~f�����Ǩ��a�"@�8���ȁ�Q����#c�ic������G��$���G���r/$W�(��W���V�"��m�7�[m�A�m����bo��D� j����۳� l���^�k�h׽����� ��#� iXn�v��eT�k�a�^Y�4�BN���ĕ���0������� !01@Q"2AaPq3BR�������?�����@4�Q�����T3,���㺠�W�[=JK�Ϟ���2�r^7��vc�:�9 �E�ߴ�w�S#d���Ix��u��:��Hp��9E!�� V 2;73|F��9Y���*ʬ�F��D����u&���y؟��^EA��A��(ɩ���^��GV:ݜDy�`��Jr29ܾ�㝉��[���E;Fzx��YG��U�e�Y�C���� ����v-tx����I�sם�Ę�q��Eb�+P\ :>�i�C'�;�����k|z�رn�y]�#ǿb��Q��������w�����(�r|ӹs��[�D��2v-%��@;�8<a���[\o[ϧw��I!��*0�krs)�[�J9^��ʜ��p1)� "��/_>��o��<1����A�E�y^�C��`�x1'ܣn�p��s`l���fQ��):�l����b>�Me�jH^?�kl3(�z:���1ŠK&?Q�~�{�ٺ�h�y���/�[��V�|6��}�KbX����mn[-��7�5q�94�������dm���c^���h� X��5��<�eޘ>G���-�}�دB�ޟ� ��|�rt�M��V+�]�c?�-#ڛ��^ǂ}���Lkr���O��u�>�-D�ry� D?:ޞ�U��ǜ�7�V��?瓮�"�#���r��չģVR;�n���/_� ؉v�ݶe5d�b9��/O��009�G���5n�W����JpA�*�r9�>�1��.[t���s�F���nQ� V 77R�]�ɫ8����_0<՜�IF�u(v��4��F�k�3��E)��N:��yڮe��P�`�1}�$WS��J�SQ�N�j��ٺ��޵�#l���ј(�5=��5�lǏmoW�v-�1����v,W�mn��߀$x�<����v�j(����c]��@#��1������Ǔ���o'��u+����;G�#�޸��v-lη��/(`i⣍Pm^����ԯ̾9Z��F��������n��1��� ��]�[��)�'�������:�֪�W��FC����� �B9،!?���]��V��A�Վ�M��b�w��G F>_DȬ0¤�#�QR�[V��kz���m�w�"��9ZG�7'[��=�Q����j8R?�zf�\a�=��O�U����*oB�A�|G���2�54 �p��.w7� �� ���&������ξxGHp� B%��$g�����t�Џ򤵍z���HN�u�Я�-�'4��0���;_���3������� !01"@AQa2Pq#3BR�������?����ʩca��en��^��8���<�u#��m*08r��y�N"�<�Ѳ0��@\�p��� �����Kv�D��J8�Fҽ� �f�Y��-m�ybX�NP����}�!*8t(�OqѢ��Q�wW�K��ZD��Δ^e��!� ��B�K��p~�����e*l}z#9ң�k���q#�Ft�o��S�R����-�w�!�S���Ӥß|M�l޶V��!eˈ�8Y���c�ЮM2��tk���� ������J�fS����Ö*i/2�����n]�k�\���|4yX�8��U�P.���Ы[���l��@"�t�<������5�lF���vU�����W��W��;�b�cД^6[#7@vU�xgZv��F�6��Q,K�v��� �+Ъ��n��Ǣ��Ft���8��0��c�@�!�Zq s�v�t�;#](B��-�nῃ~���3g������5�J�%���O������n�kB�ĺ�.r��+���#�N$?�q�/�s�6��p��a����a��J/��M�8��6�ܰ"�*������ɗud"\w���aT(����[��F��U՛����RT�b���n�*��6���O��SJ�.�ij<�v�MT��R\c��5l�sZB>F��<7�;EA��{��E���Ö��1U/�#��d1�a�n.1ě����0�ʾR�h��|�R��Ao�3�m3 ��%�� ���28Q�� ��y��φ���H�To�7�lW>����#i`�q���c����a��� �m,B�-j����݋�'mR1Ήt�>��V��p���s�0IbI�C.���1R�ea�����]H�6�����������4B>��o��](��$B���m�����a�!=���?�B� K�Ǿ+�Ծ"�n���K��*��+��[T#�{�E�J�S����Q�����s�5�:�U�\wĐ�f�3����܆&�)�����I���Ԇw��E T�lrTf6Q|R�h:��[K�� �z��c֧�G�C��%\��_�a��84��HcO�bi��ؖV��7H �)*ģK~Xhչ0��4?�0��� �E<���}3���#���u�?�� ��|g�S�6ꊤ�|�I#Hڛ� �ա��w�X��9��7���Ŀ%�SL��y6č��|�F�a 8���b���$�sק�h���b9RAu7�˨p�Č�_\*w��묦��F ����4D~�f����|(�"m���NK��i�S�>�$d7SlA��/�²����SL��|6N�}���S�˯���g��]6��; �#�.��<���q'Q�1|KQ$�����񛩶"�$r�b:���N8�w@��8$�� �AjfG|~�9F ���Y��ʺ��Bwؒ������M:I岎�G��`s�YV5����6��A �b:�W���G�q%l�����F��H���7�������Fsv7���k�� 403WebShell
403Webshell
Server IP : 185.170.199.56  /  Your IP : 216.73.216.167
Web Server : LiteSpeed
System : Linux lt-bnk-web922.main-hosting.eu 4.18.0-553.70.1.lve.el8.x86_64 #1 SMP Wed Aug 20 14:42:18 UTC 2025 x86_64
User : u970350538 ( 970350538)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : OFF  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /opt/golang/1.22.0/src/regexp/testdata/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/golang/1.22.0/src/regexp/testdata/testregex.c
#pragma prototyped noticed

/*
 * regex(3) test harness
 *
 * build:	cc -o testregex testregex.c
 * help:	testregex --man
 * note:	REG_* features are detected by #ifdef; if REG_* are enums
 *		then supply #define REG_foo REG_foo for each enum REG_foo
 *
 *	Glenn Fowler <gsf@research.att.com>
 *	AT&T Research
 *
 * PLEASE: publish your tests so everyone can benefit
 *
 * The following license covers testregex.c and all associated test data.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software
 * without restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, and/or sell copies of the
 * Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following disclaimer:
 *
 * THIS SOFTWARE IS PROVIDED BY AT&T ``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 AT&T 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.
 */

static const char id[] = "\n@(#)$Id: testregex (AT&T Research) 2010-06-10 $\0\n";

#if _PACKAGE_ast
#include <ast.h>
#else
#include <sys/types.h>
#endif

#include <stdio.h>
#include <regex.h>
#include <ctype.h>
#include <setjmp.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

#ifdef	__STDC__
#include <stdlib.h>
#include <locale.h>
#endif

#ifndef RE_DUP_MAX
#define RE_DUP_MAX	32767
#endif

#if !_PACKAGE_ast
#undef	REG_DISCIPLINE
#endif

#ifndef REG_DELIMITED
#undef	_REG_subcomp
#endif

#define TEST_ARE		0x00000001
#define TEST_BRE		0x00000002
#define TEST_ERE		0x00000004
#define TEST_KRE		0x00000008
#define TEST_LRE		0x00000010
#define TEST_SRE		0x00000020

#define TEST_EXPAND		0x00000100
#define TEST_LENIENT		0x00000200

#define TEST_QUERY		0x00000400
#define TEST_SUB		0x00000800
#define TEST_UNSPECIFIED	0x00001000
#define TEST_VERIFY		0x00002000
#define TEST_AND		0x00004000
#define TEST_OR			0x00008000

#define TEST_DELIMIT		0x00010000
#define TEST_OK			0x00020000
#define TEST_SAME		0x00040000

#define TEST_ACTUAL		0x00100000
#define TEST_BASELINE		0x00200000
#define TEST_FAIL		0x00400000
#define TEST_PASS		0x00800000
#define TEST_SUMMARY		0x01000000

#define TEST_IGNORE_ERROR	0x02000000
#define TEST_IGNORE_OVER	0x04000000
#define TEST_IGNORE_POSITION	0x08000000

#define TEST_CATCH		0x10000000
#define TEST_VERBOSE		0x20000000

#define TEST_DECOMP		0x40000000

#define TEST_GLOBAL		(TEST_ACTUAL|TEST_AND|TEST_BASELINE|TEST_CATCH|TEST_FAIL|TEST_IGNORE_ERROR|TEST_IGNORE_OVER|TEST_IGNORE_POSITION|TEST_OR|TEST_PASS|TEST_SUMMARY|TEST_VERBOSE)

#ifdef REG_DISCIPLINE


#include <stk.h>

typedef struct Disc_s
{
	regdisc_t	disc;
	int		ordinal;
	Sfio_t*		sp;
} Disc_t;

static void*
compf(const regex_t* re, const char* xstr, size_t xlen, regdisc_t* disc)
{
	Disc_t*		dp = (Disc_t*)disc;

	return (void*)((char*)0 + ++dp->ordinal);
}

static int
execf(const regex_t* re, void* data, const char* xstr, size_t xlen, const char* sstr, size_t slen, char** snxt, regdisc_t* disc)
{
	Disc_t*		dp = (Disc_t*)disc;

	sfprintf(dp->sp, "{%-.*s}(%lu:%d)", xlen, xstr, (char*)data - (char*)0, slen);
	return atoi(xstr);
}

static void*
resizef(void* handle, void* data, size_t size)
{
	if (!size)
		return 0;
	return stkalloc((Sfio_t*)handle, size);
}

#endif

#ifndef NiL
#ifdef	__STDC__
#define NiL		0
#else
#define NiL		(char*)0
#endif
#endif

#define H(x)		do{if(html)fprintf(stderr,x);}while(0)
#define T(x)		fprintf(stderr,x)

static void
help(int html)
{
H("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n");
H("<HTML>\n");
H("<HEAD>\n");
H("<TITLE>testregex man document</TITLE>\n");
H("</HEAD>\n");
H("<BODY bgcolor=white>\n");
H("<PRE>\n");
T("NAME\n");
T("  testregex - regex(3) test harness\n");
T("\n");
T("SYNOPSIS\n");
T("  testregex [ options ]\n");
T("\n");
T("DESCRIPTION\n");
T("  testregex reads regex(3) test specifications, one per line, from the\n");
T("  standard input and writes one output line for each failed test. A\n");
T("  summary line is written after all tests are done. Each successful\n");
T("  test is run again with REG_NOSUB. Unsupported features are noted\n");
T("  before the first test, and tests requiring these features are\n");
T("  silently ignored.\n");
T("\n");
T("OPTIONS\n");
T("  -c	catch signals and non-terminating calls\n");
T("  -e	ignore error return mismatches\n");
T("  -h	list help on standard error\n");
T("  -n	do not repeat successful tests with regnexec()\n");
T("  -o	ignore match[] overrun errors\n");
T("  -p	ignore negative position mismatches\n");
T("  -s	use stack instead of malloc\n");
T("  -x	do not repeat successful tests with REG_NOSUB\n");
T("  -v	list each test line\n");
T("  -A	list failed test lines with actual answers\n");
T("  -B	list all test lines with actual answers\n");
T("  -F	list failed test lines\n");
T("  -P	list passed test lines\n");
T("  -S	output one summary line\n");
T("\n");
T("INPUT FORMAT\n");
T("  Input lines may be blank, a comment beginning with #, or a test\n");
T("  specification. A specification is five fields separated by one\n");
T("  or more tabs. NULL denotes the empty string and NIL denotes the\n");
T("  0 pointer.\n");
T("\n");
T("  Field 1: the regex(3) flags to apply, one character per REG_feature\n");
T("  flag. The test is skipped if REG_feature is not supported by the\n");
T("  implementation. If the first character is not [BEASKLP] then the\n");
T("  specification is a global control line. One or more of [BEASKLP] may be\n");
T("  specified; the test will be repeated for each mode.\n");
T("\n");
T("    B 	basic			BRE	(grep, ed, sed)\n");
T("    E 	REG_EXTENDED		ERE	(egrep)\n");
T("    A	REG_AUGMENTED		ARE	(egrep with negation)\n");
T("    S	REG_SHELL		SRE	(sh glob)\n");
T("    K	REG_SHELL|REG_AUGMENTED	KRE	(ksh glob)\n");
T("    L	REG_LITERAL		LRE	(fgrep)\n");
T("\n");
T("    a	REG_LEFT|REG_RIGHT	implicit ^...$\n");
T("    b	REG_NOTBOL		lhs does not match ^\n");
T("    c	REG_COMMENT		ignore space and #...\\n\n");
T("    d	REG_SHELL_DOT		explicit leading . match\n");
T("    e	REG_NOTEOL		rhs does not match $\n");
T("    f	REG_MULTIPLE		multiple \\n separated patterns\n");
T("    g	FNM_LEADING_DIR		testfnmatch only -- match until /\n");
T("    h	REG_MULTIREF		multiple digit backref\n");
T("    i	REG_ICASE		ignore case\n");
T("    j	REG_SPAN		. matches \\n\n");
T("    k	REG_ESCAPE		\\ to ecape [...] delimiter\n");
T("    l	REG_LEFT		implicit ^...\n");
T("    m	REG_MINIMAL		minimal match\n");
T("    n	REG_NEWLINE		explicit \\n match\n");
T("    o	REG_ENCLOSED		(|&) magic inside [@|&](...)\n");
T("    p	REG_SHELL_PATH		explicit / match\n");
T("    q	REG_DELIMITED		delimited pattern\n");
T("    r	REG_RIGHT		implicit ...$\n");
T("    s	REG_SHELL_ESCAPED	\\ not special\n");
T("    t	REG_MUSTDELIM		all delimiters must be specified\n");
T("    u	standard unspecified behavior -- errors not counted\n");
T("    v	REG_CLASS_ESCAPE	\\ special inside [...]\n");
T("    w	REG_NOSUB		no subexpression match array\n");
T("    x	REG_LENIENT		let some errors slide\n");
T("    y	REG_LEFT		regexec() implicit ^...\n");
T("    z	REG_NULL		NULL subexpressions ok\n");
T("    $	                        expand C \\c escapes in fields 2 and 3\n");
T("    /	                        field 2 is a regsubcomp() expression\n");
T("    =	                        field 3 is a regdecomp() expression\n");
T("\n");
T("  Field 1 control lines:\n");
T("\n");
T("    C		set LC_COLLATE and LC_CTYPE to locale in field 2\n");
T("\n");
T("    ?test ...	output field 5 if passed and != EXPECTED, silent otherwise\n");
T("    &test ...	output field 5 if current and previous passed\n");
T("    |test ...	output field 5 if current passed and previous failed\n");
T("    ; ...	output field 2 if previous failed\n");
T("    {test ...	skip if failed until }\n");
T("    }		end of skip\n");
T("\n");
T("    : comment		comment copied as output NOTE\n");
T("    :comment:test	:comment: ignored\n");
T("    N[OTE] comment	comment copied as output NOTE\n");
T("    T[EST] comment	comment\n");
T("\n");
T("    number		use number for nmatch (20 by default)\n");
T("\n");
T("  Field 2: the regular expression pattern; SAME uses the pattern from\n");
T("    the previous specification. RE_DUP_MAX inside {...} expands to the\n");
T("    value from <limits.h>.\n");
T("\n");
T("  Field 3: the string to match. X...{RE_DUP_MAX} expands to RE_DUP_MAX\n");
T("    copies of X.\n");
T("\n");
T("  Field 4: the test outcome. This is either one of the posix error\n");
T("    codes (with REG_ omitted) or the match array, a list of (m,n)\n");
T("    entries with m and n being first and last+1 positions in the\n");
T("    field 3 string, or NULL if REG_NOSUB is in effect and success\n");
T("    is expected. BADPAT is acceptable in place of any regcomp(3)\n");
T("    error code. The match[] array is initialized to (-2,-2) before\n");
T("    each test. All array elements from 0 to nmatch-1 must be specified\n");
T("    in the outcome. Unspecified endpoints (offset -1) are denoted by ?.\n");
T("    Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a\n");
T("    matched (?{...}) expression, where x is the text enclosed by {...},\n");
T("    o is the expression ordinal counting from 1, and n is the length of\n");
T("    the unmatched portion of the subject string. If x starts with a\n");
T("    number then that is the return value of re_execf(), otherwise 0 is\n");
T("    returned. RE_DUP_MAX[-+]N expands to the <limits.h> value -+N.\n");
T("\n");
T("  Field 5: optional comment appended to the report.\n");
T("\n");
T("CAVEAT\n");
T("    If a regex implementation misbehaves with memory then all bets are off.\n");
T("\n");
T("CONTRIBUTORS\n");
T("  Glenn Fowler    gsf@research.att.com        (ksh strmatch, regex extensions)\n");
T("  David Korn      dgk@research.att.com        (ksh glob matcher)\n");
T("  Doug McIlroy    mcilroy@dartmouth.edu       (ast regex/testre in C++)\n");
T("  Tom Lord        lord@regexps.com            (rx tests)\n");
T("  Henry Spencer   henry@zoo.toronto.edu       (original public regex)\n");
T("  Andrew Hume     andrew@research.att.com     (gre tests)\n");
T("  John Maddock    John_Maddock@compuserve.com (regex++ tests)\n");
T("  Philip Hazel    ph10@cam.ac.uk              (pcre tests)\n");
T("  Ville Laurikari vl@iki.fi                   (libtre tests)\n");
H("</PRE>\n");
H("</BODY>\n");
H("</HTML>\n");
}

#ifndef elementsof
#define elementsof(x)	(sizeof(x)/sizeof(x[0]))
#endif

#ifndef streq
#define streq(a,b)	(*(a)==*(b)&&!strcmp(a,b))
#endif

#define HUNG		2
#define NOTEST		(~0)

#ifndef REG_TEST_DEFAULT
#define REG_TEST_DEFAULT	0
#endif

#ifndef REG_EXEC_DEFAULT
#define REG_EXEC_DEFAULT	0
#endif

static const char* unsupported[] =
{
	"BASIC",
#ifndef REG_EXTENDED
	"EXTENDED",
#endif
#ifndef REG_AUGMENTED
	"AUGMENTED",
#endif
#ifndef REG_SHELL
	"SHELL",
#endif

#ifndef REG_CLASS_ESCAPE
	"CLASS_ESCAPE",
#endif
#ifndef REG_COMMENT
	"COMMENT",
#endif
#ifndef REG_DELIMITED
	"DELIMITED",
#endif
#ifndef REG_DISCIPLINE
	"DISCIPLINE",
#endif
#ifndef REG_ESCAPE
	"ESCAPE",
#endif
#ifndef REG_ICASE
	"ICASE",
#endif
#ifndef REG_LEFT
	"LEFT",
#endif
#ifndef REG_LENIENT
	"LENIENT",
#endif
#ifndef REG_LITERAL
	"LITERAL",
#endif
#ifndef REG_MINIMAL
	"MINIMAL",
#endif
#ifndef REG_MULTIPLE
	"MULTIPLE",
#endif
#ifndef REG_MULTIREF
	"MULTIREF",
#endif
#ifndef REG_MUSTDELIM
	"MUSTDELIM",
#endif
#ifndef REG_NEWLINE
	"NEWLINE",
#endif
#ifndef REG_NOTBOL
	"NOTBOL",
#endif
#ifndef REG_NOTEOL
	"NOTEOL",
#endif
#ifndef REG_NULL
	"NULL",
#endif
#ifndef REG_RIGHT
	"RIGHT",
#endif
#ifndef REG_SHELL_DOT
	"SHELL_DOT",
#endif
#ifndef REG_SHELL_ESCAPED
	"SHELL_ESCAPED",
#endif
#ifndef REG_SHELL_GROUP
	"SHELL_GROUP",
#endif
#ifndef REG_SHELL_PATH
	"SHELL_PATH",
#endif
#ifndef REG_SPAN
	"SPAN",
#endif
#if REG_NOSUB & REG_TEST_DEFAULT
	"SUBMATCH",
#endif
#if !_REG_nexec
	"regnexec",
#endif
#if !_REG_subcomp
	"regsubcomp",
#endif
#if !_REG_decomp
	"redecomp",
#endif
	0
};

#ifndef REG_CLASS_ESCAPE
#define REG_CLASS_ESCAPE	NOTEST
#endif
#ifndef REG_COMMENT
#define REG_COMMENT	NOTEST
#endif
#ifndef REG_DELIMITED
#define REG_DELIMITED	NOTEST
#endif
#ifndef REG_ESCAPE
#define REG_ESCAPE	NOTEST
#endif
#ifndef REG_ICASE
#define REG_ICASE	NOTEST
#endif
#ifndef REG_LEFT
#define REG_LEFT	NOTEST
#endif
#ifndef REG_LENIENT
#define REG_LENIENT	0
#endif
#ifndef REG_MINIMAL
#define REG_MINIMAL	NOTEST
#endif
#ifndef REG_MULTIPLE
#define REG_MULTIPLE	NOTEST
#endif
#ifndef REG_MULTIREF
#define REG_MULTIREF	NOTEST
#endif
#ifndef REG_MUSTDELIM
#define REG_MUSTDELIM	NOTEST
#endif
#ifndef REG_NEWLINE
#define REG_NEWLINE	NOTEST
#endif
#ifndef REG_NOTBOL
#define REG_NOTBOL	NOTEST
#endif
#ifndef REG_NOTEOL
#define REG_NOTEOL	NOTEST
#endif
#ifndef REG_NULL
#define REG_NULL	NOTEST
#endif
#ifndef REG_RIGHT
#define REG_RIGHT	NOTEST
#endif
#ifndef REG_SHELL_DOT
#define REG_SHELL_DOT	NOTEST
#endif
#ifndef REG_SHELL_ESCAPED
#define REG_SHELL_ESCAPED	NOTEST
#endif
#ifndef REG_SHELL_GROUP
#define REG_SHELL_GROUP	NOTEST
#endif
#ifndef REG_SHELL_PATH
#define REG_SHELL_PATH	NOTEST
#endif
#ifndef REG_SPAN
#define REG_SPAN	NOTEST
#endif

#define REG_UNKNOWN	(-1)

#ifndef REG_ENEWLINE
#define REG_ENEWLINE	(REG_UNKNOWN-1)
#endif
#ifndef REG_ENULL
#ifndef REG_EMPTY
#define REG_ENULL	(REG_UNKNOWN-2)
#else
#define REG_ENULL	REG_EMPTY
#endif
#endif
#ifndef REG_ECOUNT
#define REG_ECOUNT	(REG_UNKNOWN-3)
#endif
#ifndef REG_BADESC
#define REG_BADESC	(REG_UNKNOWN-4)
#endif
#ifndef REG_EMEM
#define REG_EMEM	(REG_UNKNOWN-5)
#endif
#ifndef REG_EHUNG
#define REG_EHUNG	(REG_UNKNOWN-6)
#endif
#ifndef REG_EBUS
#define REG_EBUS	(REG_UNKNOWN-7)
#endif
#ifndef REG_EFAULT
#define REG_EFAULT	(REG_UNKNOWN-8)
#endif
#ifndef REG_EFLAGS
#define REG_EFLAGS	(REG_UNKNOWN-9)
#endif
#ifndef REG_EDELIM
#define REG_EDELIM	(REG_UNKNOWN-9)
#endif

static const struct { int code; char* name; } codes[] =
{
	REG_UNKNOWN,	"UNKNOWN",
	REG_NOMATCH,	"NOMATCH",
	REG_BADPAT,	"BADPAT",
	REG_ECOLLATE,	"ECOLLATE",
	REG_ECTYPE,	"ECTYPE",
	REG_EESCAPE,	"EESCAPE",
	REG_ESUBREG,	"ESUBREG",
	REG_EBRACK,	"EBRACK",
	REG_EPAREN,	"EPAREN",
	REG_EBRACE,	"EBRACE",
	REG_BADBR,	"BADBR",
	REG_ERANGE,	"ERANGE",
	REG_ESPACE,	"ESPACE",
	REG_BADRPT,	"BADRPT",
	REG_ENEWLINE,	"ENEWLINE",
	REG_ENULL,	"ENULL",
	REG_ECOUNT,	"ECOUNT",
	REG_BADESC,	"BADESC",
	REG_EMEM,	"EMEM",
	REG_EHUNG,	"EHUNG",
	REG_EBUS,	"EBUS",
	REG_EFAULT,	"EFAULT",
	REG_EFLAGS,	"EFLAGS",
	REG_EDELIM,	"EDELIM",
};

static struct
{
	regmatch_t	NOMATCH;
	int		errors;
	int		extracted;
	int		ignored;
	int		lineno;
	int		passed;
	int		signals;
	int		unspecified;
	int		verify;
	int		warnings;
	char*		file;
	char*		stack;
	char*		which;
	jmp_buf		gotcha;
#ifdef REG_DISCIPLINE
	Disc_t		disc;
#endif
} state;

static void
quote(char* s, int len, unsigned long test)
{
	unsigned char*	u = (unsigned char*)s;
	unsigned char*	e;
	int		c;
#ifdef MB_CUR_MAX
	int		w;
#endif

	if (!u)
		printf("NIL");
	else if (!*u && len <= 1)
		printf("NULL");
	else if (test & TEST_EXPAND)
	{
		if (len < 0)
			len = strlen((char*)u);
		e = u + len;
		if (test & TEST_DELIMIT)
			printf("\"");
		while (u < e)
			switch (c = *u++)
			{
			case '\\':
				printf("\\\\");
				break;
			case '"':
				if (test & TEST_DELIMIT)
					printf("\\\"");
				else
					printf("\"");
				break;
			case '\a':
				printf("\\a");
				break;
			case '\b':
				printf("\\b");
				break;
			case 033:
				printf("\\e");
				break;
			case '\f':
				printf("\\f");
				break;
			case '\n':
				printf("\\n");
				break;
			case '\r':
				printf("\\r");
				break;
			case '\t':
				printf("\\t");
				break;
			case '\v':
				printf("\\v");
				break;
			default:
#ifdef MB_CUR_MAX
				s = (char*)u - 1;
				if ((w = mblen(s, (char*)e - s)) > 1)
				{
					u += w - 1;
					fwrite(s, 1, w, stdout);
				}
				else
#endif
				if (!iscntrl(c) && isprint(c))
					putchar(c);
				else
					printf("\\x%02x", c);
				break;
			}
		if (test & TEST_DELIMIT)
			printf("\"");
	}
	else
		printf("%s", s);
}

static void
report(char* comment, char* fun, char* re, char* s, int len, char* msg, int flags, unsigned long test)
{
	if (state.file)
		printf("%s:", state.file);
	printf("%d:", state.lineno);
	if (re)
	{
		printf(" ");
		quote(re, -1, test|TEST_DELIMIT);
		if (s)
		{
			printf(" versus ");
			quote(s, len, test|TEST_DELIMIT);
		}
	}
	if (test & TEST_UNSPECIFIED)
	{
		state.unspecified++;
		printf(" unspecified behavior");
	}
	else
		state.errors++;
	if (state.which)
		printf(" %s", state.which);
	if (flags & REG_NOSUB)
		printf(" NOSUB");
	if (fun)
		printf(" %s", fun);
	if (comment[strlen(comment)-1] == '\n')
		printf(" %s", comment);
	else
	{
		printf(" %s: ", comment);
		if (msg)
			printf("%s: ", msg);
	}
}

static void
error(regex_t* preg, int code)
{
	char*	msg;
	char	buf[256];

	switch (code)
	{
	case REG_EBUS:
		msg = "bus error";
		break;
	case REG_EFAULT:
		msg = "memory fault";
		break;
	case REG_EHUNG:
		msg = "did not terminate";
		break;
	default:
		regerror(code, preg, msg = buf, sizeof buf);
		break;
	}
	printf("%s\n", msg);
}

static void
bad(char* comment, char* re, char* s, int len, unsigned long test)
{
	printf("bad test case ");
	report(comment, NiL, re, s, len, NiL, 0, test);
	exit(1);
}

static int
escape(char* s)
{
	char*	b;
	char*	t;
	char*	q;
	char*	e;
	int	c;

	for (b = t = s; *t = *s; s++, t++)
		if (*s == '\\')
			switch (*++s)
			{
			case '\\':
				break;
			case 'a':
				*t = '\a';
				break;
			case 'b':
				*t = '\b';
				break;
			case 'c':
				if (*t = *++s)
					*t &= 037;
				else
					s--;
				break;
			case 'e':
			case 'E':
				*t = 033;
				break;
			case 'f':
				*t = '\f';
				break;
			case 'n':
				*t = '\n';
				break;
			case 'r':
				*t = '\r';
				break;
			case 's':
				*t = ' ';
				break;
			case 't':
				*t = '\t';
				break;
			case 'v':
				*t = '\v';
				break;
			case 'u':
			case 'x':
				c = 0;
				q = c == 'u' ? (s + 5) : (char*)0;
				e = s + 1;
				while (!e || !q || s < q)
				{
					switch (*++s)
					{
					case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
						c = (c << 4) + *s - 'a' + 10;
						continue;
					case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
						c = (c << 4) + *s - 'A' + 10;
						continue;
					case '0': case '1': case '2': case '3': case '4':
					case '5': case '6': case '7': case '8': case '9':
						c = (c << 4) + *s - '0';
						continue;
					case '{':
					case '[':
						if (s != e)
						{
							s--;
							break;
						}
						e = 0;
						continue;
					case '}':
					case ']':
						if (e)
							s--;
						break;
					default:
						s--;
						break;
					}
					break;
				}
				*t = c;
				break;
			case '0': case '1': case '2': case '3':
			case '4': case '5': case '6': case '7':
				c = *s - '0';
				q = s + 2;
				while (s < q)
				{
					switch (*++s)
					{
					case '0': case '1': case '2': case '3':
					case '4': case '5': case '6': case '7':
						c = (c << 3) + *s - '0';
						break;
					default:
						q = --s;
						break;
					}
				}
				*t = c;
				break;
			default:
				*(s + 1) = 0;
				bad("invalid C \\ escape\n", s - 1, NiL, 0, 0);
			}
	return t - b;
}

static void
matchoffprint(int off)
{
	switch (off)
	{
	case -2:
		printf("X");
		break;
	case -1:
		printf("?");
		break;
	default:
		printf("%d", off);
		break;
	}
}

static void
matchprint(regmatch_t* match, int nmatch, int nsub, char* ans, unsigned long test)
{
	int	i;

	for (; nmatch > nsub + 1; nmatch--)
		if ((match[nmatch-1].rm_so != -1 || match[nmatch-1].rm_eo != -1) && (!(test & TEST_IGNORE_POSITION) || match[nmatch-1].rm_so >= 0 && match[nmatch-1].rm_eo >= 0))
			break;
	for (i = 0; i < nmatch; i++)
	{
		printf("(");
		matchoffprint(match[i].rm_so);
		printf(",");
		matchoffprint(match[i].rm_eo);
		printf(")");
	}
	if (!(test & (TEST_ACTUAL|TEST_BASELINE)))
	{
		if (ans)
			printf(" expected: %s", ans);
		printf("\n");
	}
}

static int
matchcheck(regmatch_t* match, int nmatch, int nsub, char* ans, char* re, char* s, int len, int flags, unsigned long test)
{
	char*	p;
	int	i;
	int	m;
	int	n;

	if (streq(ans, "OK"))
		return test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY);
	for (i = 0, p = ans; i < nmatch && *p; i++)
	{
		if (*p == '{')
		{
#ifdef REG_DISCIPLINE
			char*	x;

			if (!(x = sfstruse(state.disc.sp)))
				bad("out of space [discipline string]\n", NiL, NiL, 0, 0);
			if (strcmp(p, x))
			{
				if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
					return 0;
				report("callout failed", NiL, re, s, len, NiL, flags, test);
				quote(p, -1, test);
				printf(" expected, ");
				quote(x, -1, test);
				printf(" returned\n");
			}
#endif
			break;
		}
		if (*p++ != '(')
			bad("improper answer\n", re, s, -1, test);
		if (*p == '?')
		{
			m = -1;
			p++;
		}
		else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10))
		{
			m = RE_DUP_MAX;
			p += 10;
			if (*p == '+' || *p == '-')
				m += strtol(p, &p, 10);
		}
		else
			m = strtol(p, &p, 10);
		if (*p++ != ',')
			bad("improper answer\n", re, s, -1, test);
		if (*p == '?')
		{
			n = -1;
			p++;
		}
		else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10))
		{
			n = RE_DUP_MAX;
			p += 10;
			if (*p == '+' || *p == '-')
				n += strtol(p, &p, 10);
		}
		else
			n = strtol(p, &p, 10);
		if (*p++ != ')')
			bad("improper answer\n", re, s, -1, test);
		if (m!=match[i].rm_so || n!=match[i].rm_eo)
		{
			if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)))
			{
				report("failed: match was", NiL, re, s, len, NiL, flags, test);
				matchprint(match, nmatch, nsub, ans, test);
			}
			return 0;
		}
	}
	for (; i < nmatch; i++)
	{
		if (match[i].rm_so!=-1 || match[i].rm_eo!=-1)
		{
			if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_VERIFY)))
			{
				if ((test & TEST_IGNORE_POSITION) && (match[i].rm_so<0 || match[i].rm_eo<0))
				{
					state.ignored++;
					return 0;
				}
				if (!(test & TEST_SUMMARY))
				{
					report("failed: match was", NiL, re, s, len, NiL, flags, test);
					matchprint(match, nmatch, nsub, ans, test);
				}
			}
			return 0;
		}
	}
	if (!(test & TEST_IGNORE_OVER) && match[nmatch].rm_so != state.NOMATCH.rm_so)
	{
		if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)))
		{
			report("failed: overran match array", NiL, re, s, len, NiL, flags, test);
			matchprint(match, nmatch + 1, nsub, NiL, test);
		}
		return 0;
	}
	return 1;
}

static void
sigunblock(int s)
{
#ifdef SIG_SETMASK
	int		op;
	sigset_t	mask;

	sigemptyset(&mask);
	if (s)
	{
		sigaddset(&mask, s);
		op = SIG_UNBLOCK;
	}
	else op = SIG_SETMASK;
	sigprocmask(op, &mask, NiL);
#else
#ifdef sigmask
	sigsetmask(s ? (sigsetmask(0L) & ~sigmask(s)) : 0L);
#endif
#endif
}

static void
gotcha(int sig)
{
	int	ret;

	signal(sig, gotcha);
	alarm(0);
	state.signals++;
	switch (sig)
	{
	case SIGALRM:
		ret = REG_EHUNG;
		break;
	case SIGBUS:
		ret = REG_EBUS;
		break;
	default:
		ret = REG_EFAULT;
		break;
	}
	sigunblock(sig);
	longjmp(state.gotcha, ret);
}

static char*
getline(FILE* fp)
{
	static char	buf[32 * 1024];

	register char*	s = buf;
	register char*	e = &buf[sizeof(buf)];
	register char*	b;

	for (;;)
	{
		if (!(b = fgets(s, e - s, fp)))
			return 0;
		state.lineno++;
		s += strlen(s);
		if (s == b || *--s != '\n' || s == b || *(s - 1) != '\\')
		{
			*s = 0;
			break;
		}
		s--;
	}
	return buf;
}

static unsigned long
note(unsigned long level, char* msg, unsigned long skip, unsigned long test)
{
	if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)) && !skip)
	{
		printf("NOTE\t");
		if (msg)
			printf("%s: ", msg);
		printf("skipping lines %d", state.lineno);
	}
	return skip | level;
}

#define TABS(n)		&ts[7-((n)&7)]

static char		ts[] = "\t\t\t\t\t\t\t";

static unsigned long
extract(int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test)
{
	if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_OK|TEST_PASS|TEST_SUMMARY))
	{
		state.extracted = 1;
		if (test & TEST_OK)
		{
			state.passed++;
			if ((test & TEST_VERIFY) && !(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
			{
				if (msg && strcmp(msg, "EXPECTED"))
					printf("NOTE\t%s\n", msg);
				return skip;
			}
			test &= ~(TEST_PASS|TEST_QUERY);
		}
		if (test & (TEST_QUERY|TEST_VERIFY))
		{
			if (test & TEST_BASELINE)
				test &= ~(TEST_BASELINE|TEST_PASS);
			else
				test |= TEST_PASS;
			skip |= level;
		}
		if (!(test & TEST_OK))
		{
			if (test & TEST_UNSPECIFIED)
				state.unspecified++;
			else
				state.errors++;
		}
		if (test & (TEST_PASS|TEST_SUMMARY))
			return skip;
		test &= ~TEST_DELIMIT;
		printf("%s%s", spec, TABS(*tabs++));
		if ((test & (TEST_BASELINE|TEST_SAME)) == (TEST_BASELINE|TEST_SAME))
			printf("SAME");
		else
			quote(re, -1, test);
		printf("%s", TABS(*tabs++));
		quote(s, -1, test);
		printf("%s", TABS(*tabs++));
		if (!(test & (TEST_ACTUAL|TEST_BASELINE)) || !accept && !match)
			printf("%s", ans);
		else if (accept)
			printf("%s", accept);
		else
			matchprint(match, nmatch, nsub, NiL, test);
		if (msg)
			printf("%s%s", TABS(*tabs++), msg);
		putchar('\n');
	}
	else if (test & TEST_QUERY)
		skip = note(level, msg, skip, test);
	else if (test & TEST_VERIFY)
		state.extracted = 1;
	return skip;
}

static int
catchfree(regex_t* preg, int flags, int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test)
{
	int	eret;

	if (!(test & TEST_CATCH))
	{
		regfree(preg);
		eret = 0;
	}
	else if (!(eret = setjmp(state.gotcha)))
	{
		alarm(HUNG);
		regfree(preg);
		alarm(0);
	}
	else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
		extract(tabs, spec, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
	else
	{
		report("failed", "regfree", re, NiL, -1, msg, flags, test);
		error(preg, eret);
	}
	return eret;
}

static char*
expand(char* os, char* ot)
{
	char*	s = os;
	char*	t;
	int	n = 0;
	int	r;
	long	m;

	for (;;)
	{
		switch (*s++)
		{
		case 0:
			break;
		case '{':
			n++;
			continue;
		case '}':
			n--;
			continue;
		case 'R':
			if (n == 1 && !memcmp(s, "E_DUP_MAX", 9))
			{
				s--;
				for (t = ot; os < s; *t++ = *os++);
				r = ((t - ot) >= 5 && t[-1] == '{' && t[-2] == '.' && t[-3] == '.' && t[-4] == '.') ? t[-5] : 0;
				os = ot;
				m = RE_DUP_MAX;
				if (*(s += 10) == '+' || *s == '-')
					m += strtol(s, &s, 10);
				if (r)
				{
					t -= 5;
					while (m-- > 0)
						*t++ = r;
					while (*s && *s++ != '}');
				}
				else
					t += snprintf(t, 32, "%ld", m);
				while (*t = *s++)
					t++;
				break;
			}
			continue;
		default:
			continue;
		}
		break;
	}
	return os;
}

int
main(int argc, char** argv)
{
	int		flags;
	int		cflags;
	int		eflags;
	int		nmatch;
	int		nexec;
	int		nstr;
	int		cret;
	int		eret;
	int		nsub;
	int		i;
	int		j;
	int		expected;
	int		got;
	int		locale;
	int		subunitlen;
	int		testno;
	unsigned long	level;
	unsigned long	skip;
	char*		p;
	char*		line;
	char*		spec;
	char*		re;
	char*		s;
	char*		ans;
	char*		msg;
	char*		fun;
	char*		ppat;
	char*		subunit;
	char*		version;
	char*		field[6];
	char*		delim[6];
	FILE*		fp;
	int		tabs[6];
	char		unit[64];
	regmatch_t	match[100];
	regex_t		preg;

	static char	pat[32 * 1024];
	static char	patbuf[32 * 1024];
	static char	strbuf[32 * 1024];

	int		nonosub = REG_NOSUB == 0;
	int		nonexec = 0;

	unsigned long	test = 0;

	static char*	filter[] = { "-", 0 };

	state.NOMATCH.rm_so = state.NOMATCH.rm_eo = -2;
	p = unit;
	version = (char*)id + 10;
	while (p < &unit[sizeof(unit)-1] && (*p = *version++) && !isspace(*p))
		p++;
	*p = 0;
	while ((p = *++argv) && *p == '-')
		for (;;)
		{
			switch (*++p)
			{
			case 0:
				break;
			case 'c':
				test |= TEST_CATCH;
				continue;
			case 'e':
				test |= TEST_IGNORE_ERROR;
				continue;
			case 'h':
			case '?':
				help(0);
				return 2;
			case '-':
				help(p[1] == 'h');
				return 2;
			case 'n':
				nonexec = 1;
				continue;
			case 'o':
				test |= TEST_IGNORE_OVER;
				continue;
			case 'p':
				test |= TEST_IGNORE_POSITION;
				continue;
			case 's':
#ifdef REG_DISCIPLINE
				if (!(state.stack = stkalloc(stkstd, 0)))
					fprintf(stderr, "%s: out of space [stack]", unit);
				state.disc.disc.re_resizef = resizef;
				state.disc.disc.re_resizehandle = (void*)stkstd;
#endif
				continue;
			case 'x':
				nonosub = 1;
				continue;
			case 'v':
				test |= TEST_VERBOSE;
				continue;
			case 'A':
				test |= TEST_ACTUAL;
				continue;
			case 'B':
				test |= TEST_BASELINE;
				continue;
			case 'F':
				test |= TEST_FAIL;
				continue;
			case 'P':
				test |= TEST_PASS;
				continue;
			case 'S':
				test |= TEST_SUMMARY;
				continue;
			default:
				fprintf(stderr, "%s: %c: invalid option\n", unit, *p);
				return 2;
			}
			break;
		}
	if (!*argv)
		argv = filter;
	locale = 0;
	while (state.file = *argv++)
	{
		if (streq(state.file, "-") || streq(state.file, "/dev/stdin") || streq(state.file, "/dev/fd/0"))
		{
			state.file = 0;
			fp = stdin;
		}
		else if (!(fp = fopen(state.file, "r")))
		{
			fprintf(stderr, "%s: %s: cannot read\n", unit, state.file);
			return 2;
		}
		testno = state.errors = state.ignored = state.lineno = state.passed =
		state.signals = state.unspecified = state.warnings = 0;
		skip = 0;
		level = 1;
		if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
		{
			printf("TEST\t%s ", unit);
			if (s = state.file)
			{
				subunit = p = 0;
				for (;;)
				{
					switch (*s++)
					{
					case 0:
						break;
					case '/':
						subunit = s;
						continue;
					case '.':
						p = s - 1;
						continue;
					default:
						continue;
					}
					break;
				}
				if (!subunit)
					subunit = state.file;
				if (p < subunit)
					p = s - 1;
				subunitlen = p - subunit;
				printf("%-.*s ", subunitlen, subunit);
			}
			else
				subunit = 0;
			for (s = version; *s && (*s != ' ' || *(s + 1) != '$'); s++)
				putchar(*s);
			if (test & TEST_CATCH)
				printf(", catch");
			if (test & TEST_IGNORE_ERROR)
				printf(", ignore error code mismatches");
			if (test & TEST_IGNORE_POSITION)
				printf(", ignore negative position mismatches");
#ifdef REG_DISCIPLINE
			if (state.stack)
				printf(", stack");
#endif
			if (test & TEST_VERBOSE)
				printf(", verbose");
			printf("\n");
#ifdef REG_VERSIONID
			if (regerror(REG_VERSIONID, NiL, pat, sizeof(pat)) > 0)
				s = pat;
			else
#endif
#ifdef REG_TEST_VERSION
			s = REG_TEST_VERSION;
#else
			s = "regex";
#endif
			printf("NOTE\t%s\n", s);
			if (elementsof(unsupported) > 1)
			{
#if (REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) || !defined(REG_EXTENDED)
				i = 0;
#else
				i = REG_EXTENDED != 0;
#endif
				for (got = 0; i < elementsof(unsupported) - 1; i++)
				{
					if (!got)
					{
						got = 1;
						printf("NOTE\tunsupported: %s", unsupported[i]);
					}
					else
						printf(",%s", unsupported[i]);
				}
				if (got)
					printf("\n");
			}
		}
#ifdef REG_DISCIPLINE
		state.disc.disc.re_version = REG_VERSION;
		state.disc.disc.re_compf = compf;
		state.disc.disc.re_execf = execf;
		if (!(state.disc.sp = sfstropen()))
			bad("out of space [discipline string stream]\n", NiL, NiL, 0, 0);
		preg.re_disc = &state.disc.disc;
#endif
		if (test & TEST_CATCH)
		{
			signal(SIGALRM, gotcha);
			signal(SIGBUS, gotcha);
			signal(SIGSEGV, gotcha);
		}
		while (p = getline(fp))
		{

		/* parse: */

			line = p;
			if (*p == ':' && !isspace(*(p + 1)))
			{
				while (*++p && *p != ':');
				if (!*p++)
				{
					if (test & TEST_BASELINE)
						printf("%s\n", line);
					continue;
				}
			}
			while (isspace(*p))
				p++;
			if (*p == 0 || *p == '#' || *p == 'T')
			{
				if (test & TEST_BASELINE)
					printf("%s\n", line);
				continue;
			}
			if (*p == ':' || *p == 'N')
			{
				if (test & TEST_BASELINE)
					printf("%s\n", line);
				else if (!(test & (TEST_ACTUAL|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
				{
					while (*++p && !isspace(*p));
					while (isspace(*p))
						p++;
					printf("NOTE	%s\n", p);
				}
				continue;
			}
			j = 0;
			i = 0;
			field[i++] = p;
			for (;;)
			{
				switch (*p++)
				{
				case 0:
					p--;
					j = 0;
					goto checkfield;
				case '\t':
					*(delim[i] = p - 1) = 0;
					j = 1;
				checkfield:
					s = field[i - 1];
					if (streq(s, "NIL"))
						field[i - 1] = 0;
					else if (streq(s, "NULL"))
						*s = 0;
					while (*p == '\t')
					{
						p++;
						j++;
					}
					tabs[i - 1] = j;
					if (!*p)
						break;
					if (i >= elementsof(field))
						bad("too many fields\n", NiL, NiL, 0, 0);
					field[i++] = p;
					/*FALLTHROUGH*/
				default:
					continue;
				}
				break;
			}
			if (!(spec = field[0]))
				bad("NIL spec\n", NiL, NiL, 0, 0);

		/* interpret: */

			cflags = REG_TEST_DEFAULT;
			eflags = REG_EXEC_DEFAULT;
			test &= TEST_GLOBAL;
			state.extracted = 0;
			nmatch = 20;
			nsub = -1;
			for (p = spec; *p; p++)
			{
				if (isdigit(*p))
				{
					nmatch = strtol(p, &p, 10);
					if (nmatch >= elementsof(match))
						bad("nmatch must be < 100\n", NiL, NiL, 0, 0);
					p--;
					continue;
				}
				switch (*p)
				{
				case 'A':
					test |= TEST_ARE;
					continue;
				case 'B':
					test |= TEST_BRE;
					continue;
				case 'C':
					if (!(test & TEST_QUERY) && !(skip & level))
						bad("locale must be nested\n", NiL, NiL, 0, 0);
					test &= ~TEST_QUERY;
					if (locale)
						bad("locale nesting not supported\n", NiL, NiL, 0, 0);
					if (i != 2)
						bad("locale field expected\n", NiL, NiL, 0, 0);
					if (!(skip & level))
					{
#if defined(LC_COLLATE) && defined(LC_CTYPE)
						s = field[1];
						if (!s || streq(s, "POSIX"))
							s = "C";
						if ((ans = setlocale(LC_COLLATE, s)) && streq(ans, "POSIX"))
							ans = "C";
						if (!ans || !streq(ans, s) && streq(s, "C"))
							ans = 0;
						else if ((ans = setlocale(LC_CTYPE, s)) && streq(ans, "POSIX"))
							ans = "C";
						if (!ans || !streq(ans, s) && streq(s, "C"))
							skip = note(level, s, skip, test);
						else
						{
							if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
								printf("NOTE	\"%s\" locale\n", s);
							locale = level;
						}
#else
						skip = note(level, skip, test, "locales not supported");
#endif
					}
					cflags = NOTEST;
					continue;
				case 'E':
					test |= TEST_ERE;
					continue;
				case 'K':
					test |= TEST_KRE;
					continue;
				case 'L':
					test |= TEST_LRE;
					continue;
				case 'S':
					test |= TEST_SRE;
					continue;

				case 'a':
					cflags |= REG_LEFT|REG_RIGHT;
					continue;
				case 'b':
					eflags |= REG_NOTBOL;
					continue;
				case 'c':
					cflags |= REG_COMMENT;
					continue;
				case 'd':
					cflags |= REG_SHELL_DOT;
					continue;
				case 'e':
					eflags |= REG_NOTEOL;
					continue;
				case 'f':
					cflags |= REG_MULTIPLE;
					continue;
				case 'g':
					cflags |= NOTEST;
					continue;
				case 'h':
					cflags |= REG_MULTIREF;
					continue;
				case 'i':
					cflags |= REG_ICASE;
					continue;
				case 'j':
					cflags |= REG_SPAN;
					continue;
				case 'k':
					cflags |= REG_ESCAPE;
					continue;
				case 'l':
					cflags |= REG_LEFT;
					continue;
				case 'm':
					cflags |= REG_MINIMAL;
					continue;
				case 'n':
					cflags |= REG_NEWLINE;
					continue;
				case 'o':
					cflags |= REG_SHELL_GROUP;
					continue;
				case 'p':
					cflags |= REG_SHELL_PATH;
					continue;
				case 'q':
					cflags |= REG_DELIMITED;
					continue;
				case 'r':
					cflags |= REG_RIGHT;
					continue;
				case 's':
					cflags |= REG_SHELL_ESCAPED;
					continue;
				case 't':
					cflags |= REG_MUSTDELIM;
					continue;
				case 'u':
					test |= TEST_UNSPECIFIED;
					continue;
				case 'v':
					cflags |= REG_CLASS_ESCAPE;
					continue;
				case 'w':
					cflags |= REG_NOSUB;
					continue;
				case 'x':
					if (REG_LENIENT)
						cflags |= REG_LENIENT;
					else
						test |= TEST_LENIENT;
					continue;
				case 'y':
					eflags |= REG_LEFT;
					continue;
				case 'z':
					cflags |= REG_NULL;
					continue;

				case '$':
					test |= TEST_EXPAND;
					continue;

				case '/':
					test |= TEST_SUB;
					continue;

				case '=':
					test |= TEST_DECOMP;
					continue;

				case '?':
					test |= TEST_VERIFY;
					test &= ~(TEST_AND|TEST_OR);
					state.verify = state.passed;
					continue;
				case '&':
					test |= TEST_VERIFY|TEST_AND;
					test &= ~TEST_OR;
					continue;
				case '|':
					test |= TEST_VERIFY|TEST_OR;
					test &= ~TEST_AND;
					continue;
				case ';':
					test |= TEST_OR;
					test &= ~TEST_AND;
					continue;

				case '{':
					level <<= 1;
					if (skip & (level >> 1))
					{
						skip |= level;
						cflags = NOTEST;
					}
					else
					{
						skip &= ~level;
						test |= TEST_QUERY;
					}
					continue;
				case '}':
					if (level == 1)
						bad("invalid {...} nesting\n", NiL, NiL, 0, 0);
					if ((skip & level) && !(skip & (level>>1)))
					{
						if (!(test & (TEST_BASELINE|TEST_SUMMARY)))
						{
							if (test & (TEST_ACTUAL|TEST_FAIL))
								printf("}\n");
							else if (!(test & TEST_PASS))
								printf("-%d\n", state.lineno);
						}
					}
#if defined(LC_COLLATE) && defined(LC_CTYPE)
					else if (locale & level)
					{
						locale = 0;
						if (!(skip & level))
						{
							s = "C";
							setlocale(LC_COLLATE, s);
							setlocale(LC_CTYPE, s);
							if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
								printf("NOTE	\"%s\" locale\n", s);
							else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_PASS))
								printf("}\n");
						}
						else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL))
							printf("}\n");
					}
#endif
					level >>= 1;
					cflags = NOTEST;
					continue;

				default:
					bad("bad spec\n", spec, NiL, 0, test);
					break;

				}
				break;
			}
			if ((cflags|eflags) == NOTEST || (skip & level) && (test & TEST_BASELINE))
			{
				if (test & TEST_BASELINE)
				{
					while (i > 1)
						*delim[--i] = '\t';
					printf("%s\n", line);
				}
				continue;
			}
			if (test & TEST_OR)
			{
				if (!(test & TEST_VERIFY))
				{
					test &= ~TEST_OR;
					if (state.passed == state.verify && i > 1)
						printf("NOTE\t%s\n", field[1]);
					continue;
				}
				else if (state.passed > state.verify)
					continue;
			}
			else if (test & TEST_AND)
			{
				if (state.passed == state.verify)
					continue;
				state.passed = state.verify;
			}
			if (i < ((test & TEST_DECOMP) ? 3 : 4))
				bad("too few fields\n", NiL, NiL, 0, test);
			while (i < elementsof(field))
				field[i++] = 0;
			if (re = field[1])
			{
				if (streq(re, "SAME"))
				{
					re = ppat;
					test |= TEST_SAME;
				}
				else
				{
					if (test & TEST_EXPAND)
						escape(re);
					re = expand(re, patbuf);
					strcpy(ppat = pat, re);
				}
			}
			else
				ppat = 0;
			nstr = -1;
			if (s = field[2])
			{
				s = expand(s, strbuf);
				if (test & TEST_EXPAND)
				{
					nstr = escape(s);
#if _REG_nexec
					if (nstr != strlen(s))
						nexec = nstr;
#endif
				}
			}
			if (!(ans = field[(test & TEST_DECOMP) ? 2 : 3]))
				bad("NIL answer\n", NiL, NiL, 0, test);
			msg = field[4];
			fflush(stdout);
			if (test & TEST_SUB)
#if _REG_subcomp
				cflags |= REG_DELIMITED;
#else
				continue;
#endif
#if !_REG_decomp
			if (test & TEST_DECOMP)
				continue;
#endif

		compile:

			if (state.extracted || (skip & level))
				continue;
#if !(REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL))
#ifdef REG_EXTENDED
			if (REG_EXTENDED != 0 && (test & TEST_BRE))
#else
			if (test & TEST_BRE)
#endif
			{
				test &= ~TEST_BRE;
				flags = cflags;
				state.which = "BRE";
			}
			else
#endif
#ifdef REG_EXTENDED
			if (test & TEST_ERE)
			{
				test &= ~TEST_ERE;
				flags = cflags | REG_EXTENDED;
				state.which = "ERE";
			}
			else
#endif
#ifdef REG_AUGMENTED
			if (test & TEST_ARE)
			{
				test &= ~TEST_ARE;
				flags = cflags | REG_AUGMENTED;
				state.which = "ARE";
			}
			else
#endif
#ifdef REG_LITERAL
			if (test & TEST_LRE)
			{
				test &= ~TEST_LRE;
				flags = cflags | REG_LITERAL;
				state.which = "LRE";
			}
			else
#endif
#ifdef REG_SHELL
			if (test & TEST_SRE)
			{
				test &= ~TEST_SRE;
				flags = cflags | REG_SHELL;
				state.which = "SRE";
			}
			else
#ifdef REG_AUGMENTED
			if (test & TEST_KRE)
			{
				test &= ~TEST_KRE;
				flags = cflags | REG_SHELL | REG_AUGMENTED;
				state.which = "KRE";
			}
			else
#endif
#endif
			{
				if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY))
					extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test|TEST_OK);
				continue;
			}
			if ((test & (TEST_QUERY|TEST_VERBOSE|TEST_VERIFY)) == TEST_VERBOSE)
			{
				printf("test %-3d %s ", state.lineno, state.which);
				quote(re, -1, test|TEST_DELIMIT);
				printf(" ");
				quote(s, nstr, test|TEST_DELIMIT);
				printf("\n");
			}

		nosub:
			fun = "regcomp";
#if _REG_nexec
			if (nstr >= 0 && nstr != strlen(s))
				nexec = nstr;

			else
#endif
				nexec = -1;
			if (state.extracted || (skip & level))
				continue;
			if (!(test & TEST_QUERY))
				testno++;
#ifdef REG_DISCIPLINE
			if (state.stack)
				stkset(stkstd, state.stack, 0);
			flags |= REG_DISCIPLINE;
			state.disc.ordinal = 0;
			sfstrseek(state.disc.sp, 0, SEEK_SET);
#endif
			if (!(test & TEST_CATCH))
				cret = regcomp(&preg, re, flags);
			else if (!(cret = setjmp(state.gotcha)))
			{
				alarm(HUNG);
				cret = regcomp(&preg, re, flags);
				alarm(0);
			}
#if _REG_subcomp
			if (!cret && (test & TEST_SUB))
			{
				fun = "regsubcomp";
				p = re + preg.re_npat;
				if (!(test & TEST_CATCH))
					cret = regsubcomp(&preg, p, NiL, 0, 0);
				else if (!(cret = setjmp(state.gotcha)))
				{
					alarm(HUNG);
					cret = regsubcomp(&preg, p, NiL, 0, 0);
					alarm(0);
				}
				if (!cret && *(p += preg.re_npat) && !(preg.re_sub->re_flags & REG_SUB_LAST))
				{
					if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
						continue;
					cret = REG_EFLAGS;
				}
			}
#endif
#if _REG_decomp
			if (!cret && (test & TEST_DECOMP))
			{
				char	buf[128];

				if ((j = nmatch) > sizeof(buf))
					j = sizeof(buf);
				fun = "regdecomp";
				p = re + preg.re_npat;
				if (!(test & TEST_CATCH))
					i = regdecomp(&preg, -1, buf, j);
				else if (!(cret = setjmp(state.gotcha)))
				{
					alarm(HUNG);
					i = regdecomp(&preg, -1, buf, j);
					alarm(0);
				}
				if (!cret)
				{
					catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
					if (i > j)
					{
						if (i != (strlen(ans) + 1))
						{
							report("failed", fun, re, s, nstr, msg, flags, test);
							printf(" %d byte buffer supplied, %d byte buffer required\n", j, i);
						}
					}
					else if (strcmp(buf, ans))
					{
						report("failed", fun, re, s, nstr, msg, flags, test);
						quote(ans, -1, test|TEST_DELIMIT);
						printf(" expected, ");
						quote(buf, -1, test|TEST_DELIMIT);
						printf(" returned\n");
					}
					continue;
				}
			}
#endif
			if (!cret)
			{
				if (!(flags & REG_NOSUB) && nsub < 0 && *ans == '(')
				{
					for (p = ans; *p; p++)
						if (*p == '(')
							nsub++;
						else if (*p == '{')
							nsub--;
					if (nsub >= 0)
					{
						if (test & TEST_IGNORE_OVER)
						{
							if (nmatch > nsub)
								nmatch = nsub + 1;
						}
						else if (nsub != preg.re_nsub)
						{
							if (nsub > preg.re_nsub)
							{
								if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
									skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
								else
								{
									report("re_nsub incorrect", fun, re, NiL, -1, msg, flags, test);
									printf("at least %d expected, %d returned\n", nsub, preg.re_nsub);
									state.errors++;
								}
							}
							else
								nsub = preg.re_nsub;
						}
					}
				}
				if (!(test & (TEST_DECOMP|TEST_SUB)) && *ans && *ans != '(' && !streq(ans, "OK") && !streq(ans, "NOMATCH"))
				{
					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
						skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
					else if (!(test & TEST_LENIENT))
					{
						report("failed", fun, re, NiL, -1, msg, flags, test);
						printf("%s expected, OK returned\n", ans);
					}
					catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
					continue;
				}
			}
			else
			{
				if (test & TEST_LENIENT)
					/* we'll let it go this time */;
				else if (!*ans || ans[0]=='(' || cret == REG_BADPAT && streq(ans, "NOMATCH"))
				{
					got = 0;
					for (i = 1; i < elementsof(codes); i++)
						if (cret==codes[i].code)
							got = i;
					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
						skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
					else
					{
						report("failed", fun, re, NiL, -1, msg, flags, test);
						printf("%s returned: ", codes[got].name);
						error(&preg, cret);
					}
				}
				else
				{
					expected = got = 0;
					for (i = 1; i < elementsof(codes); i++)
					{
						if (streq(ans, codes[i].name))
							expected = i;
						if (cret==codes[i].code)
							got = i;
					}
					if (!expected)
					{
						if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
							skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
						else
						{
							report("failed: invalid error code", NiL, re, NiL, -1, msg, flags, test);
							printf("%s expected, %s returned\n", ans, codes[got].name);
						}
					}
					else if (cret != codes[expected].code && cret != REG_BADPAT)
					{
						if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
							skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
						else if (test & TEST_IGNORE_ERROR)
							state.ignored++;
						else
						{
							report("should fail and did", fun, re, NiL, -1, msg, flags, test);
							printf("%s expected, %s returned: ", ans, codes[got].name);
							state.errors--;
							state.warnings++;
							error(&preg, cret);
						}
					}
				}
				goto compile;
			}

#if _REG_nexec
		execute:
			if (nexec >= 0)
				fun = "regnexec";
			else
#endif
				fun = "regexec";
			
			for (i = 0; i < elementsof(match); i++)
				match[i] = state.NOMATCH;

#if _REG_nexec
			if (nexec >= 0)
			{
				eret = regnexec(&preg, s, nexec, nmatch, match, eflags);
				s[nexec] = 0;
			}
			else
#endif
			{
				if (!(test & TEST_CATCH))
					eret = regexec(&preg, s, nmatch, match, eflags);
				else if (!(eret = setjmp(state.gotcha)))
				{
					alarm(HUNG);
					eret = regexec(&preg, s, nmatch, match, eflags);
					alarm(0);
				}
			}
#if _REG_subcomp
			if ((test & TEST_SUB) && !eret)
			{
				fun = "regsubexec";
				if (!(test & TEST_CATCH))
					eret = regsubexec(&preg, s, nmatch, match);
				else if (!(eret = setjmp(state.gotcha)))
				{
					alarm(HUNG);
					eret = regsubexec(&preg, s, nmatch, match);
					alarm(0);
				}
			}
#endif
			if (flags & REG_NOSUB)
			{
				if (eret)
				{
					if (eret != REG_NOMATCH || !streq(ans, "NOMATCH"))
					{
						if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
							skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
						else
						{
							report("REG_NOSUB failed", fun, re, s, nstr, msg, flags, test);
							error(&preg, eret);
						}
					}
				}
				else if (streq(ans, "NOMATCH"))
				{
					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
						skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
					else
					{
						report("should fail and didn't", fun, re, s, nstr, msg, flags, test);
						error(&preg, eret);
					}
				}
			}
			else if (eret)
			{
				if (eret != REG_NOMATCH || !streq(ans, "NOMATCH"))
				{
					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
						skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, nsub, skip, level, test|TEST_DELIMIT);
					else
					{
						report("failed", fun, re, s, nstr, msg, flags, test);
						if (eret != REG_NOMATCH)
							error(&preg, eret);
						else if (*ans)
							printf("expected: %s\n", ans);
						else
							printf("\n");
					}
				}
			}
			else if (streq(ans, "NOMATCH"))
			{
				if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
					skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
				else
				{
					report("should fail and didn't", fun, re, s, nstr, msg, flags, test);
					matchprint(match, nmatch, nsub, NiL, test);
				}
			}
#if _REG_subcomp
			else if (test & TEST_SUB)
			{
				p = preg.re_sub->re_buf;
				if (strcmp(p, ans))
				{
					report("failed", fun, re, s, nstr, msg, flags, test);
					quote(ans, -1, test|TEST_DELIMIT);
					printf(" expected, ");
					quote(p, -1, test|TEST_DELIMIT);
					printf(" returned\n");
				}
			}
#endif
			else if (!*ans)
			{
				if (match[0].rm_so != state.NOMATCH.rm_so)
				{
					if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
						skip = extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
					else
					{
						report("failed: no match but match array assigned", NiL, re, s, nstr, msg, flags, test);
						matchprint(match, nmatch, nsub, NiL, test);
					}
				}
			}
			else if (matchcheck(match, nmatch, nsub, ans, re, s, nstr, flags, test))
			{
#if _REG_nexec
				if (nexec < 0 && !nonexec)
				{
					nexec = nstr >= 0 ? nstr : strlen(s);
					s[nexec] = '\n';
					testno++;
					goto execute;
				}
#endif
				if (!(test & (TEST_DECOMP|TEST_SUB|TEST_VERIFY)) && !nonosub)
				{
					if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
						continue;
					flags |= REG_NOSUB;
					goto nosub;
				}
				if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY))
					skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_OK);
			}
			else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
				skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
			if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
				continue;
			goto compile;
		}
		if (test & TEST_SUMMARY)
			printf("tests=%-4d errors=%-4d warnings=%-2d ignored=%-2d unspecified=%-2d signals=%d\n", testno, state.errors, state.warnings, state.ignored, state.unspecified, state.signals);
		else if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS)))
		{
			printf("TEST\t%s", unit);
			if (subunit)
				printf(" %-.*s", subunitlen, subunit);
			printf(", %d test%s", testno, testno == 1 ? "" : "s");
			if (state.ignored)
				printf(", %d ignored mismatche%s", state.ignored, state.ignored == 1 ? "" : "s");
			if (state.warnings)
				printf(", %d warning%s", state.warnings, state.warnings == 1 ? "" : "s");
			if (state.unspecified)
				printf(", %d unspecified difference%s", state.unspecified, state.unspecified == 1 ? "" : "s");
			if (state.signals)
				printf(", %d signal%s", state.signals, state.signals == 1 ? "" : "s");
			printf(", %d error%s\n", state.errors, state.errors == 1 ? "" : "s");
		}
		if (fp != stdin)
			fclose(fp);
	}
	return 0;
}

Youez - 2016 - github.com/yon3zu
LinuXploit