chiark / gitweb /
@@@ fltfmt wip
[mLib] / utils / control.3.in
1 .\" -*-nroff-*-
2 .\"
3 .\" Manual for control flow metaprogramming
4 .\"
5 .\" (c) 2023, 2024 Straylight/Edgeware
6 .\"
7 .
8 .\"----- Licensing notice ---------------------------------------------------
9 .\"
10 .\" This file is part of the mLib utilities library.
11 .\"
12 .\" mLib is free software: you can redistribute it and/or modify it under
13 .\" the terms of the GNU Library General Public License as published by
14 .\" the Free Software Foundation; either version 2 of the License, or (at
15 .\" your option) any later version.
16 .\"
17 .\" mLib is distributed in the hope that it will be useful, but WITHOUT
18 .\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 .\" FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
20 .\" License for more details.
21 .\"
22 .\" You should have received a copy of the GNU Library General Public
23 .\" License along with mLib.  If not, write to the Free Software
24 .\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25 .\" USA.
26 .
27 .\"--------------------------------------------------------------------------
28 .so ../defs.man \" @@@PRE@@@
29 .
30 .\"--------------------------------------------------------------------------
31 .TH control 3mLib "23 April 2023" "Straylight/Edgeware" "mLib utilities library"
32 .\" @MC_BEFORE
33 .\" @MC_AFTER
34 .\" @MC_WRAP
35 .\" @MC_FINALLY
36 .\" @MC_DOWHILE
37 .\" @MC_DECL
38 .\" @MC_LOOPELSE
39 .\" @MC_LOOPBETWEEN
40 .\" @MC_ALLOWELSE
41 .\" @MC_GOELSE
42 .\" @MC_TARGET
43 .\" @MC_GOTARGET
44 .\" @MC_ACT
45 .\" @MC_LABEL
46 .\" @MC_GOTO
47 .
48 .\"--------------------------------------------------------------------------
49 .SH NAME
50 control \- control structure metaprogramming
51 .
52 .\"--------------------------------------------------------------------------
53 .SH SYNOPSIS
54 .
55 .nf
56 .B "#include <mLib/control.h>"
57 .PP
58 .BI MC_BEFORE( tag ", " stmts ") " body
59 .BI MC_AFTER( tag ", " stmts ") " body
60 .BI MC_WRAP( tag ", " before_stmt ", " onend_stmt ", " onbreak_stmt ") " body
61 .BI MC_FINALLY( tag ", " cleanup ") " body
62 .BI MC_DOWHILE( tag ", " cond ") " body
63 .BI MC_DECL( tag ", " decl ") " body
64 .BI MC_LOOPELSE( tag ", " head ") " loop_body " \fR[\fBelse " else_body \fR]
65 .BI MC_LOOPBETWEEN( tag ", " setup ", " cond ", " step ") " loop_body " \fR[\fBelse " else_body \fR]
66 .PP
67 .BI MC_TARGET( tag ", " stmt ") " body
68 .BI MC_GOTARGET( tag );
69 .BI MC_ALLOWELSE( tag ") " main_body " \fR[\fBelse " else_body \fR]
70 .BI MC_GOELSE( tag );
71 .PP
72 .BI MC_ACT( stmt )
73 .BI MC_LABEL( tag )
74 .BI MC_GOTO( tag )
75 .fi
76 .
77 .\"--------------------------------------------------------------------------
78 .SH DESCRIPTION
79 .
80 The header file
81 .B <mLib/control.h>
82 defines a number of macros which are useful
83 when defining new control structures for C.
84 They are inspired by Simon Tatham's article
85 .IR "Metaprogramming custom control structures in C",
86 though these macros differ from Tatham's in a few respects.
87 .
88 .SS "Common features"
89 Each of these macros takes a
90 .I tag
91 argument.
92 A
93 .I tag
94 is lexically like an identifier,
95 except that it may begin with a digit,
96 so, for example, plain integers are acceptable tags.
97 Each use of an action macro by a user-level macro
98 must have a distinct
99 .IR tag .
100 If you're writing a new prefix action macro
101 written in terms of these existing actions,
102 your macro should receive a
103 .I tag
104 from its caller,
105 and pass this tag,
106 along with a distinctive component of its own,
107 down to any prefix actions that it calls;
108 the
109 .IR tag s
110 from each layer should be separated by a pair of underscores.
111 .PP
112 Some of these macros work by wrapping a loop around the
113 .I body
114 statement.
115 This interferes with the way that `free'
116 .B break
117 and
118 .B continue
119 statements within the
120 .I body
121 behave:
122 we say that these statements are
123 .I captured
124 by the macro.
125 A
126 .B break
127 or
128 .B continue
129 statement is
130 .I free
131 if it doesn't appear lexically within a loop or
132 (for
133 .B break)
134 .B switch
135 statement that is part of the
136 .IR body .
137 So
138 .VS
139 if (!x) break;
140 .VE
141 contains a free
142 .B break
143 statement,
144 while
145 .VS
146 .ta 2n
147 for (i = 0; i < n; i++)
148         if (interestingp(i)) break;
149 .VE
150 does not.
151 .PP
152 Some of these macros take special care
153 to give you control over what happens when a captured
154 .B break
155 is executed.
156 Alas, proper handling of
157 .B continue
158 doesn't seem possible.
159 Free
160 .B break
161 and
162 .B continue
163 statements
164 .I within
165 arguments to these macros are never captured.
166 .
167 .SS "Prefix action macros"
168 .B MC_BEFORE
169 macro is the simplest to understand.  Executing
170 .IP
171 .BI MC_BEFORE( tag ", " stmt ") " body
172 .PP
173 has the same effect as executing
174 .I stmt
175 followed by
176 .IR body ,
177 except that the whole thing is syntactically a single statement,
178 so, for example, it doesn't need to be enclosed in braces
179 to be the body of a
180 .B for
181 loop.
182 .B MC_BEFORE
183 does not capture free
184 .B break
185 or
186 .B continue
187 statements.
188 .PP
189 Executing
190 .IP
191 .BI MC_AFTER( tag ", " stmt ") " body
192 .PP
193 has
194 .I nearly
195 the same effect as executing
196 .I stmt
197 followed by
198 .IR body .
199 Again, the whole thing is syntactically a single statement.
200 However,
201 .B MC_AFTER
202 captures free
203 .B break
204 and
205 .B continue
206 statements within the
207 .IR body .
208 A free
209 .B break
210 or
211 .B continue
212 abruptly ends execution of the
213 .IR body ,
214 immediately transferring control to the
215 .IR stmt .
216 .PP
217 Executing
218 .IP
219 .BI MC_WRAP( tag ", " before ", " onend ", " onbreak ") " body
220 .PP
221 has
222 .I nearly
223 the same effect as executing
224 .IR before ,
225 .IR body ,
226 and then
227 .IR onend .
228 If the
229 .I body
230 executes a free
231 .B break
232 statement, then control abruptly continues with the
233 .I onbreak
234 statement, and
235 .I onend
236 is not executed.
237 Currently, if the
238 .I body
239 executes a free
240 .B continue
241 statement,
242 then control abruptly continues with the
243 .I onend
244 statement,
245 but this behaviour is a bug and may be fixed in the future.
246 .PP
247 Executing
248 .IP
249 .BI MC_FINALLY( tag ", " cleanup ") " body
250 .PP
251 has the same effect as executing
252 .I body
253 followed by
254 .IR cleanup ,
255 except that a free
256 .B break
257 statement within
258 .I body
259 will execute
260 .I cleanup
261 before propagating the
262 .B break
263 to the enclosing context.
264 A free
265 .B continue
266 statement currently causes control to continue abruptly with
267 .I cleanup
268 but this behaviour is a bug and may be fixed in the future.
269 The
270 .I cleanup
271 code is textually duplicated,
272 so there'll be some code bloat if this is very complex.
273 If it arranges to have private long-term state
274 then the two copies will not share this state,
275 so probably don't do this.
276 .PP
277 Executing
278 .IP
279 .BI MC_DOWHILE( tag ", " cond ") " body
280 .PP
281 has exactly the same effect as
282 .BI "do " body " while (" cond ); \fR,
283 the only difference being that the
284 .I body
285 appears in tail position rather than sandwiched in the middle.
286 .PP
287 Executing
288 .BI MC_DECL( tag ", " decl ") " body
289 has the same effect as
290 .BI "{ " decl "; " body " }" \fR,
291 except that free
292 .B break
293 and
294 .B continue
295 statements are captured.
296 Currently, a free
297 .B continue
298 statement will simply abruptly terminate execution of the
299 .IR body ,
300 while a free
301 .B break
302 statement abruptly
303 .I restarts
304 executing the
305 .I body
306 without leaving the scope of the
307 .IR decl ;
308 but these behaviours are bugs and may be fixed in the future.
309 .PP
310 The
311 .B MC_DECL
312 macro makes use of the fact that a
313 .B for
314 statement can introduce a declaration
315 into its body's scope in C99 and C++;
316 the macro is not available in C89.
317 .PP
318 Executing
319 .IP
320 .nf
321 .ta 2n
322 .BI MC_LOOPELSE( head ", " tag ") "
323 .I "    loop_body"
324 .RB [ else
325 .IR "   else_body" ]
326 .fi
327 .PP
328 results in Python-like loop behaviour.
329 The
330 .I head
331 must be a valid loop head with one of the forms
332 .IP
333 .nf
334 .BI "while (" cond ")"
335 .BI "for (" decl "; " cond "; " next_expr ")"
336 .BI "MC_DOWHILE(" tag ", " cond ")"
337 .fi
338 .PP
339 The resulting loop executes the same as
340 .IP
341 .nf
342 .ta 2n
343 .I head
344 .I "    loop_body"
345 .fi
346 .PP
347 If the loop ends abruptly, as a result of
348 .BR break ,
349 then control is passed to the statement following the loop
350 in the usual way.
351 However, if the loop completes naturally,
352 and the optional
353 .B else
354 clause is present,
355 then the
356 .I else_body
357 is executed.
358 A free
359 .B continue
360 statement within the
361 .I loop_body
362 behaves normally.
363 Free
364 .B break
365 and
366 .B continue
367 statements within the
368 .I else_body
369 are not captured.
370 .PP
371 Executing
372 .IP
373 .nf
374 .ta 2n
375 .BI MC_LOOPBETWEEN( tag ", " setup ", " cond ", " step ") "
376 .I "    loop-body"
377 .RB [ else
378 .IR "   else-body" ]
379 .fi
380 .PP
381 is similar to executing the
382 .B for
383 loop
384 .IP
385 .ta 2n
386 .nf
387 .BI "for (" setup "; " cond "; " step ") "
388 .I "    loop-body"
389 .fi
390 .PP
391 except that, once the
392 .I loop_body
393 has finished,
394 the
395 .I step
396 expression evaluated,
397 and the
398 .I cond
399 evaluated and determined to be nonzero,
400 the
401 .I else_body
402 (if any) is executed before re-entering the
403 .IR loop_body .
404 This makes it a useful place to insert
405 any kind of interstitial material,
406 e.g., printing commas between list items.
407 Note that by the time the
408 .I else_body
409 is executed,
410 the decision has already been made
411 that another iteration will be performed,
412 and, in particular, the
413 .I step
414 has occurred.  The
415 .I else_body
416 is therefore looking at the next item to be processed,
417 not the item that has just finished being processed.
418 The
419 .I cond
420 is textually duplicated,
421 so there'll be some code bloat if this is very complex.
422 If it somehow manages to have private long-term state
423 (e.g., as a result of declaring static variables
424 inside GCC statement expressions)
425 then the two copies will not share this state,
426 so probably don't do this.
427 .
428 .SS "Lower-level machinery"
429 Executing
430 .IP
431 .BI MC_TARGET( tag ", " stmt ") " body
432 .PP
433 has exactly the same effect as simply executing
434 .IR body .
435 Executing
436 .B MC_GOTARGET
437 immediately transfers control to
438 .IR stmt ,
439 with control continuing with the following statement,
440 skipping the
441 .IR body .
442 Free
443 .B break
444 or
445 .B continue
446 statements in
447 .I body
448 are not captured.
449 .PP
450 This is most commonly useful in loops
451 in order to arrange the correct behaviour of a free
452 .B break
453 within the loop body.
454 See the example below,
455 which shows the definition
456 of
457 .BR MC_LOOPELSE .
458 .PP
459 Executing
460 .IP
461 .nf
462 .ta 2n
463 .BI MC_ALLOWELSE( tag ") "
464 .I "    main_body"
465 .RB [ else
466 .IR "   else_body" ]
467 .fi
468 .PP
469 has exactly the same effect as just
470 .IR main_body .
471 Executing
472 .IP
473 .BI MC_GOELSE( tag );
474 .PP
475 transfers control immediately to
476 .I else_body
477 (if present);
478 control then naturally transfers to the following statement as usual.
479 Free
480 .B break
481 or
482 .B continue
483 statements in either of
484 .I main_body
485 or
486 .I else_body
487 are not captured.
488 .PP
489 Note that
490 .B MC_ALLOWELSE
491 works by secretly inserting an
492 .B if
493 statement head before the
494 .IR main_body ,
495 so things will likely to wrong if
496 .I main_body
497 is itself an
498 .B if
499 statement:
500 if
501 .I main_body
502 lacks an
503 .B else
504 clause,
505 then an
506 .B else
507 intended to match
508 .B MC_ALLOWELSE
509 will be mis-associated;
510 and even if
511 .I main_body
512 .I does
513 have an
514 .B else
515 clause,
516 the resulting program text is likely to provoke a compiler warning
517 about `dangling
518 .BR else '.
519 .PP
520 Using these tools,
521 it's relatively straightforward to define a macro like
522 .BR MC_LOOPELSE ,
523 described above:
524 .VS
525 .ta 4n 4n+\w'\fBMC_WRAP(tag##__body, 'u \n(.lu-\n(.iu-4n
526 #define MC_LOOPELSE(tag, head)                  \e
527         MC_TARGET(tag##__exit, { ; })           \e
528         MC_ALLOWELSE(tag##__else)               \e
529         MC_AFTER(tag##__after, { MC_GOELSE(tag##__else); })             \e
530         head            \e
531         MC_WRAP(tag##__body, { ; }, { ; },              \e
532                 { MC_GOTARGET(tag##__exit); })
533 .VE
534 The main `trick' for these control-flow macros is
535 .BR MC_ACT ,
536 which wraps up a statement as an
537 .IR action .
538 An action is a valid
539 .IR  "statement head" ,
540 like
541 .B if
542 or
543 .BR while :
544 i.e., it must be completed by following it with a
545 .I body
546 statement.
547 Executing
548 .IP
549 .BI MC_ACT( stmt ") " body
550 .PP
551 has the same effect as simply executing
552 .IR stmt ;
553 the
554 .I body
555 is usually ignored.
556 Note that
557 .B ;
558 is a valid statement which does nothing,
559 so
560 .BI MC_ACT( stmt );
561 is also a valid statement with the same effect as
562 .IR stmt .
563 The only way to cause
564 .I body
565 to be executed is to attach a label to it and transfer control using
566 .BR goto .
567 .PP
568 Executing
569 .IP
570 .BI MC_LABEL( tag ") " body
571 .PP
572 has the same effect as
573 .IR body .
574 Executing
575 .IP
576 .BI MC_GOTO( tag )
577 .PP
578 immediately transfers control to the
579 .IR body .
580 Note that
581 .B MC_GOTO
582 is syntactically an action,
583 i.e., it's wrapped in
584 .BR MC_ACT .
585 The
586 .IR tag s
587 here are scoped to the top-level source line,
588 like all
589 .IR tag s
590 in this macro package.
591 .PP
592 All of the control-flow macros in this package are mainly constructed from
593 .BR MC_ACT ,
594 .BR MC_LABEL ,
595 and
596 .BR MC_GOTO ,
597 sometimes with one or two other statement heads thrown into the mix.
598 For example,
599 .B MC_AFTER
600 is defined as
601 .VS
602 .ta 4n 28n 30n \n(.lu-\n(.iu-4n
603 #define MC_AFTER(tag, stmt)                     \e
604                 MC_GOTO(tag##__body)            \e
605         MC_LABEL(tag##__end)                    \e
606                 MC_ACT(stmt)            \e
607                 for (;;)                \e
608                         MC_GOTO(tag##__end)     \e
609         MC_LABEL(tag##__body)
610 .VE
611 (The unusual layout is conventional,
612 to make the overall structure of the code clear
613 despite visual interference from the labels.)
614 The
615 .I body
616 appears at the end,
617 labelled as
618 .IB tag __body \fR.
619 Control enters at the start,
620 and is immediately transferred to the
621 .I body ;
622 but the
623 .I body
624 is enclosed in a
625 .B for
626 loop, so when the
627 .I body
628 completes, the loop restarts,
629 transferring control to
630 .IB tag __end
631 and the
632 .IR stmt .
633 Since it is enclosed in
634 .BR MC_ACT ,
635 once
636 .I stmt
637 completes,
638 control transfers to the following statement.
639 .
640 .\"--------------------------------------------------------------------------
641 .SH "BUGS"
642 .
643 Some macros cause free
644 .B break
645 and/or
646 .B continue
647 statements to behave in unexpected ways.
648 .PP
649 It's rather hard to use
650 .B MC_ALLOWELSE
651 in practice without provoking
652 .RB `dangling- else '
653 warnings.
654 .PP
655 The need for tagging is ugly,
656 and the restriction on having two
657 user-facing control-flow macros on the same line is objectionable.
658 The latter could be avoided
659 by using nonstandard features such as GCC's
660 .B __COUNTER__
661 macro,
662 but adopting that would do programmers a disservice
663 by introducing a hazard for those
664 trying to port code to other compilers which lack any such feature.
665 .
666 .\"--------------------------------------------------------------------------
667 .SH "SEE ALSO"
668 .
669 .BR macros (3).
670 .BR mLib (3),
671 .PP
672 Simon Tatham,
673 .IR "Metaprogramming custom control structures in C",
674 .BR "https://www.chiark.greenend.org.uk/~sgtatham/mp/" .
675 .
676 .\"--------------------------------------------------------------------------
677 .SH "AUTHOR"
678 .
679 Mark Wooding, <mdw@distorted.org.uk>
680 .
681 .\"----- That's all, folks --------------------------------------------------