# # RUN: mkdir -p %t # # RUN: python %s --function=sscanf > %t/sscanftest.c # RUN: test.sh -p -t %t %t/sscanftest.c # # RUN: python %s --function=vsscanf > %t/vsscanftest.c # RUN: test.sh -p -t %t %t/vsscanftest.c # # # Generate a C program to test sscanf() or vsscanf(). # Str = 0 # string Int = 1 # integer Flt = 2 # float Dbl = 3 # double Ldb = 4 # long double Arr = 5 # array of bytes of given size Wst = 6 # wide character string Nsp = 7 # %n specifier (as int) basictests = \ [ # input format string return write [ 'abc ', '%s', 1, [ (Str, 'abc') ] ], [ ' abc', '%1[ ]', 1, [ (Str, ' ') ] ], [ ' abc', '%[] a]', 1, [ (Str, ' a') ] ], [ '\\n123', '%2d%1d', 2, [ (Int, '12'), (Int, '3') ] ], [ '%ab\\n ', '%%%s', 1, [ (Str, 'ab') ] ], [ '[][][]', '%[][]', 1, [ (Str, '[][][]') ] ], [ 'abcde', '%3[^ ]%s', 2, [ (Str, 'abc'), (Str, 'de') ] ], [ '123.4', '%i.%i', 2, [ (Int, '123'), (Int, '4') ] ], [ '123.4', '%Lf', 1, [ (Ldb, '123.4l') ] ], [ '6.6e-3', '%1Le', 1, [ (Ldb, '6.0l') ] ], [ '6.6e-3', '%7Le', 1, [ (Ldb, '6.6e-3l') ] ], [ '6.6e-3', '%lg', 1, [ (Dbl, '6.6e-3') ] ], [ 'yy x', '%3c', 1, [ (Arr, 'yy ') ] ], [ '-0x1.6p+2', '%Lf', 1, [ (Ldb, '-5.5l') ] ], [ '100ent', '%e', 0, [ ], ], [ '100e', '%e', 'EOF', [ ], ], [ '10010', '%*2i%o', 1, [ (Int, '8') ] ], [ ' \\na', '%[^a]', 1, [ (Str, ' \\n') ] ], [ '-6', '%f', 1, [ (Flt, '-6.f') ] ], [ ' ans', '%1s', 1, [ (Str, 'a') ] ], [ 'abcdefgh', '%[a-f]%[g-h]', 2, [ (Str, 'abcdef'), (Str, 'gh') ] ], [ '123.4', '%3ls', 1, [ (Wst, '123') ] ], [ 'str', '%ls', 1, [ (Wst, 'str') ] ], [ 'this', '%[nmop]', 0, [ ], ], [ '%', '%%%n', 0, [ (Nsp, '1') ], ], [ ' string', '%10s%n', 1, [ (Str, 'string'), (Nsp, '7') ] ], [ ' ', '%c%n%c', 2,[ (Arr, ' '), (Nsp, '1'), (Arr, ' ') ] ], [ 'i', '%n%ni', 0, [ (Nsp, '0'), (Nsp, '0') ] ], [ 'i', '%ni%n', 0, [ (Nsp, '0'), (Nsp, '1') ] ], [ 'abc 1', '%ls%n%d', 2, [ (Wst,'abc'), (Nsp,'3'), (Int,'1') ] ], [ '1234', '%2c%n', 1, [ (Arr, '12'), (Nsp, '2') ] ], [ 'xyzab', '%[x-z]%nab', 1, [ (Str, 'xyz'), (Nsp, '3') ] ], [ '456789', '%[4-7]%n%i', 2,[ (Str,'4567'), (Nsp,'4'), (Int,'89') ]], [ '456789', '%4i%n%i', 2,[ (Int,'4567'), (Nsp,'4'), (Int,'89') ]], ] quote = lambda s : '"' + s + '"' def build_test(n, input, fmt, rval, wrvals, function): strcount = 0 intcount = 0 fltcount = 0 dblcount = 0 ldbcount = 0 wstcount = 0 nspcount = 0 front = 'result = %s(%s, %s' % (function, quote(input), quote(fmt)) args = [] comparisons = [] for wrval in wrvals: valtype = wrval[0] compare = wrval[1] if valtype == Str: strcount += 1 args.append('s%i' % strcount) comparisons.append('strcmp(s%i, %s) == 0' % (strcount, quote(compare))) elif valtype == Int: intcount += 1 args.append('&i%i' % intcount) comparisons.append('i%i == %s' % (intcount, compare)) elif valtype == Flt: fltcount += 1 args.append('&f%i' % fltcount) comparisons.append('flteq(f%i, %s)' % (fltcount, compare)) elif valtype == Dbl: dblcount += 1 args.append('&d%i' % dblcount) comparisons.append('dbleq(d%i, %s)' % (dblcount, compare)) elif valtype == Ldb: ldbcount += 1 args.append('&ldb%i' % ldbcount) comparisons.append('ldbeq(ldb%i, %s)' % (ldbcount, compare)) elif valtype == Arr: size = len(compare) strcount += 1 args.append('s%i' % strcount) comparisons.append( 'memcmp((void *) s%i, (void *) %s, %i) == 0' % (strcount, quote(compare), size) ) elif valtype == Wst: wstcount += 1 args.append('w%i' % wstcount) comparisons.append('wcscmp(w%i, L%s) == 0' % (wstcount, quote(compare))) elif valtype == Nsp: nspcount += 1 args.append('&n%i' % nspcount) comparisons.append('n%i == %s' % (nspcount, compare)) args.append('(void *) buf') # Don't segfault bad implementations that write # one more argument than they should. if args != []: argv = ', ' + ', '.join(args) else: argv = '' command = front + argv + ');' tests = [command] for ctest in comparisons: tests.append( 'if (!(%s)) { fail = 1; puts("failure on test %s"); }' % (ctest, n) ) tests.append( 'if (result != %s) { fail = 1; puts("failure on test %s"); }' % (rval, n) ) return ' ' + '\n '.join(tests) top = \ '''#include #include #include #include #include int mysscanf(char *buf, const char *fmt, ...) { int result; va_list ap; va_start(ap, fmt); result = vsscanf(buf, fmt, ap); va_end(ap); return result; } /* Very crude floating point equality tests. */ int ldbeq(long double a, long double b) { return (a - b) < 0.00001l && (a - b) > -0.00001l; } int dbleq(double a, double b) { return (a - b) < 0.00001 && (a - b) > -0.00001; } int flteq(float a, float b) { return (a - b) < 0.00001f && (a - b) > -0.00001f; } int main(int argc, char *argv[]) { char buf[100]; char s1[100], s2[100], s3[100], s4[100], s5[100]; wchar_t w1[100], w2[100], w3[100], w4[100], w5[100]; int i1, i2, i3, i4, i5; int n1, n2, n3, n4, n5; long double ldb1, ldb2, ldb3, ldb4, ldb5; double d1, d2, d3, d4, d5; float f1, f2, f3, f4, f5; int fail, result; fail = 0; /* Begin tests. */ ''' bottom = \ ''' /* End tests. */ return fail; } ''' import cStringIO import optparse import sys if __name__ == '__main__': parser = optparse.OptionParser() parser.set_defaults(function='sscanf') parser.add_option('--function', dest='function', help='function to test: sscanf or vsscanf') (options, args) = parser.parse_args() if options.function == 'sscanf': function = 'sscanf' elif options.function == 'vsscanf': function = 'mysscanf' else: sys.stderr.write('specify either sscanf or vsscanf!\n') sys.exit(1) count = 0 output = cStringIO.StringIO() output.write(top) for basic_test in basictests: count += 1 input = basic_test[0] fmt = basic_test[1] rval = basic_test[2] wrvals = basic_test[3] result = build_test(count, input, fmt, rval, wrvals, function) output.write(result) output.write('\n\n') output.write(bottom) sys.stdout.write(output.getvalue()) output.close()