1 /* { dg-do run } */ 2 3 extern void abort (void); 4 5 typedef int int32_t __attribute__ ((mode (SI))); 6 typedef int int64_t __attribute__ ((mode (DI))); 7 typedef __SIZE_TYPE__ size_t; 8 9 struct slice 10 { 11 unsigned char *data; 12 int64_t len; 13 int64_t cap; 14 }; 15 16 void fail (int32_t) __attribute__ ((noinline)); 17 void fail(int32_t c)18fail (int32_t c) 19 { 20 if (c != 0) 21 abort (); 22 } 23 24 struct decode_rune_ret 25 { 26 int32_t r; 27 int64_t width; 28 }; 29 30 struct decode_rune_ret decode_rune (struct slice) __attribute__ ((noinline)); 31 struct decode_rune_ret decode_rune(struct slice s)32decode_rune (struct slice s) 33 { 34 struct decode_rune_ret dr; 35 dr.r = s.data[0]; 36 dr.width = 1; 37 return dr; 38 } 39 40 _Bool is_space (int32_t) __attribute__ ((noinline)); 41 _Bool is_space(int32_t r)42is_space (int32_t r) 43 { 44 return r == ' '; 45 } 46 47 struct ret 48 { 49 int64_t advance; 50 struct slice token; 51 }; 52 53 struct ret scanwords (struct slice, _Bool) __attribute__ ((noinline)); 54 55 struct ret scanwords(struct slice data,_Bool ateof)56scanwords (struct slice data, _Bool ateof) 57 { 58 int64_t advance; 59 struct slice token; 60 int64_t start = 0; 61 { 62 int64_t width; 63 for (width = 0; start < data.len; start += width) 64 { 65 int32_t r = 0; 66 struct slice s; 67 if (start > data.cap || start < 0) 68 fail (3); 69 s.data = data.data + (size_t) start; 70 s.len = data.len - start; 71 s.cap = data.cap - start; 72 struct decode_rune_ret dr = decode_rune (s); 73 r = dr.r; 74 width = dr.width; 75 if (!is_space (r)) 76 break; 77 } 78 } 79 _Bool tmp = ateof; 80 if (tmp != 0) 81 goto L1; 82 else 83 goto L2; 84 L1: 85 tmp = data.len == 0; 86 L2: 87 if (tmp != 0) 88 goto L11; 89 else 90 goto L12; 91 L11: 92 { 93 struct ret r; 94 advance = 0; 95 token.data = 0; 96 token.len = 0; 97 token.cap = 0; 98 r.advance = advance; 99 r.token = token; 100 return r; 101 } 102 L12:; 103 int64_t width; 104 int64_t i; 105 for (width = 0, i = start; i < data.len; i += width) 106 { 107 int32_t r; 108 struct slice s; 109 if (i > data.cap || i < 0) 110 fail (3); 111 s.data = data.data + i; 112 s.len = data.len - i; 113 s.cap = data.cap - i; 114 struct decode_rune_ret dr = decode_rune (s); 115 r = dr.r; 116 width = dr.width; 117 if (is_space (r)) 118 { 119 if (i < start || i > data.cap || i < 0) 120 fail (3); 121 if (start > data.cap || start < 0) 122 fail (3); 123 struct ret r; 124 advance = i + width; 125 token.data = data.data + (size_t) start; 126 token.len = i - start; 127 token.cap = data.cap - start; 128 r.advance = advance; 129 r.token = token; 130 return r; 131 } 132 } 133 { 134 struct ret r; 135 advance = 0; 136 token.data = 0; 137 token.len = 0; 138 token.cap = 0; 139 r.advance = advance; 140 r.token = token; 141 return r; 142 } 143 } 144 145 int main()146main () 147 { 148 unsigned char buf[1000]; 149 struct slice s; 150 __builtin_memset (buf, 0, sizeof (buf)); 151 buf[0] = ' '; 152 buf[1] = 'a'; 153 buf[2] = ' '; 154 s.data = buf; 155 s.len = 3; 156 s.cap = sizeof (buf); 157 struct ret r; 158 r = scanwords (s, 1); 159 if (r.advance != 3 || r.token.data[0] != 'a' || r.token.len != 1) 160 abort (); 161 return 0; 162 } 163