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)18 fail (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)32 decode_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)42 is_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)56 scanwords (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()146 main ()
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