# ,[$5],[$6],...,[$m]_m4_popdef([_m4_s])
# before calling m4_shift(_m4_s($@)).
m4_define([_m4_shiftn],
-[m4_define([_m4_s],
+[m4_if(m4_incr([$1]), [$#], [], [m4_define([_m4_s],
m4_pushdef([_m4_s])_m4_for([_m4_s], m4_eval([$1 + 2]), [$#], [1],
- [[,]m4_dquote([$]_m4_s)])[_m4_popdef([_m4_s])])m4_shift(_m4_s($@))])
+ [[,]m4_dquote([$]_m4_s)])[_m4_popdef([_m4_s])])m4_shift(_m4_s($@))])])
# m4_do(STRING, ...)
# ------------------
myvar
dnl only one side effect expansion, prior to visiting list elements
m4_foreach([i], [[1], [2], [3]m4_errprintn([hi])], [m4_errprintn(i)])dnl
+dnl shifting forms an important part of loops
+m4_shift3:m4_shift3(1,2,3):m4_shift3(1,2,3,4)
+m4_shiftn(3,1,2,3):m4_shiftn(3,1,2,3,4)
]],
[[ 1 2 3
1 2 3
| f|
a| b| c,| d,e| f| g|
outer value
+::4
+:4
]], [[hi
1
2
3
]])
+dnl bounds checking in m4_for
AT_DATA_M4SUGAR([script.4s],
[[m4_init
m4_divert([0])dnl
m4_for([myvar], 1, 3,-1, [ myvar])
]])
-
AT_CHECK_M4SUGAR([], 1, [],
[[script.4s:3: error: assert failed: -1 > 0
script.4s:3: the top level
m4_divert([0])dnl
m4_for([myvar], 1, 2, 0, [ myvar])
]])
-
AT_CHECK_M4SUGAR([], 1, [],
[[script.4s:3: error: assert failed: 0 > 0
script.4s:3: the top level
m4_divert([0])dnl
m4_for([myvar], 2, 1, 0, [ myvar])
]])
-
AT_CHECK_M4SUGAR([], 1, [],
[[script.4s:3: error: assert failed: 0 < 0
script.4s:3: the top level
autom4te: m4 failed with exit status: 1
]])
+dnl m4_shiftn also does bounds checking
+AT_DATA_M4SUGAR([script.4s],
+[[m4_init
+m4_divert([0])dnl
+m4_shiftn(3,1,2)
+]])
+AT_CHECK_M4SUGAR([], 1, [],
+[[script.4s:3: error: assert failed: 0 < 3 && 3 < 3
+script.4s:3: the top level
+autom4te: m4 failed with exit status: 1
+]])
+
AT_CLEANUP