#							-*- Autotest -*-

AT_BANNER([M4sugar.])

# Copyright (C) 2000, 2001, 2002, 2005, 2006 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.


# AT_CHECK_M4SUGAR_TEXT(CODE, STDOUT, STDERR)
# -------------------------------------------
# Check that m4sugar CODE expands to STDOUT and emits STDERR.
m4_define([AT_CHECK_M4SUGAR_TEXT],
[
AT_DATA_M4SUGAR([script.4s],
[[m4_init
m4_divert_push(0)[]dnl
]$1[[]dnl
m4_divert_pop(0)
]])

AT_CHECK_M4SUGAR([-o-],, [$2], [$3])
])# AT_CHECK_M4SUGAR_TEXT


# Order of the tests:
# - m4_warn
#
# - m4_require
# uses warn/error code.
#
# - m4_text_wrap

## --------- ##
## m4_warn.  ##
## --------- ##

AT_SETUP([m4@&t@_warn])

# m4_text_wrap is used to display the help strings.  Also, check that
# commas are not swallowed.  This can easily happen because of
# m4-listification.

# FIXME: For the time being we use -f to make sure we do issue the
# warnings.  But maybe autom4te should handle that by itself?

AT_DATA_M4SUGAR([script.4s],
[[m4_init
m4_defun([cross_warning],
[m4_warn([cross],  [cross])])

m4_divert([0])dnl
m4_warn([obsolete],  [obsolete])dnl
cross_warning[]dnl
m4_warn([syntax], [syntax])dnl
]])

AT_CHECK_M4SUGAR([-o-], 0, [],
[script.4s:8: warning: syntax
])

AT_CHECK_M4SUGAR([-o- -Wall -f], 0, [],
[script.4s:6: warning: obsolete
script.4s:7: warning: cross
script.4s:3: cross_warning is expanded from...
script.4s:7: the top level
script.4s:8: warning: syntax
])

AT_CHECK_M4SUGAR([-o- -Wnone,cross -f], 0, [],
[script.4s:7: warning: cross
script.4s:3: cross_warning is expanded from...
script.4s:7: the top level
])

AT_CHECK_M4SUGAR([-o- -Wnone,cross,error -f], 1, [],
[[script.4s:7: warning: cross
script.4s:3: cross_warning is expanded from...
script.4s:7: the top level
]])

AT_CLEANUP


## --------------------------- ##
## m4_require: error message.  ##
## --------------------------- ##

AT_SETUP([m4@&t@_require: error message])

AT_DATA_M4SUGAR([script.4s],
[[m4_defun([foo], [FOO])
m4_require([foo])
]])

AT_CHECK_M4SUGAR([], 1, [],
[[script.4s:2: error: m4@&t@_require(foo): cannot be used outside of an m4_defun'd macro
script.4s:2: the top level
autom4te: m4 failed with exit status: 1
]])
AT_CLEANUP


## ----------------------------------- ##
## m4_require: circular dependencies.  ##
## ----------------------------------- ##

AT_SETUP([m4@&t@_require: circular dependencies])

# m4_text_wrap is used to display the help strings.  Also, check that
# commas are not swallowed.  This can easily happen because of
# m4-listification.

AT_DATA_M4SUGAR([script.4s],
[[m4_defun([foo],
[m4_require([bar])])

m4_defun([bar],
[m4_require([foo])])

m4_defun([baz],
[m4_require([foo])])

m4_init
m4_divert([0])dnl
baz
]])

AT_CHECK_M4SUGAR([], 1, [],
[[script.4s:12: error: m4@&t@_require: circular dependency of foo
script.4s:5: bar is expanded from...
script.4s:2: foo is expanded from...
script.4s:8: baz is expanded from...
script.4s:12: the top level
autom4te: m4 failed with exit status: 1
]])
AT_CLEANUP


## -------------- ##
## m4_text_wrap.  ##
## -------------- ##

AT_SETUP([m4@&t@_text_wrap])

# m4_text_wrap is used to display the help strings.  Also, check that
# commas are not swallowed.  This can easily happen because of
# m4-listification.

AT_DATA_M4SUGAR([script.4s],
[[m4_divert([0])dnl
m4_text_wrap([Short string */], [   ], [/* ], 20)

m4_text_wrap([Much longer string */], [   ], [/* ], 20)

m4_text_wrap([Short doc.], [          ], [  --short ], 30)

m4_text_wrap([Short doc.], [          ], [  --too-wide], 30)

m4_text_wrap([Super long documentation.], [          ], [  --too-wide], 30)

m4_text_wrap([First, second  , third, [,quoted]])
]])

AT_DATA([expout],
[[/* Short string */

/* Much longer
   string */

  --short Short doc.

  --too-wide
          Short doc.

  --too-wide
          Super long
          documentation.

First, second , third, [,quoted]
]])

AT_CHECK_M4SUGAR([-o-], 0, [expout])

AT_CLEANUP

## ------------------------------ ##
## Standard regular expressions.  ##
## ------------------------------ ##

AT_SETUP([Standard regular expressions])

# AT_CHECK_M4RE(RE-NAME, TEXT, INTENT = `ok' | `')
# ------------------------------------------------
# Check whether RE-NAME (a macro whose definition is a regular expression)
# matches TEXT.  INTENT = `ok' if the match should succeed or else empty.
m4_define([AT_CHECK_M4RE],
[AT_CHECK_M4SUGAR_TEXT(
[[m4_bregexp([$2], ^m4_defn([$1])$, [ok])
]], [$3
])])

AT_CHECK_M4RE([m4_re_word], [ab9_c], [ok])
AT_CHECK_M4RE([m4_re_word], [_9abc], [ok])
AT_CHECK_M4RE([m4_re_word], [9ab_c])

AT_CHECK_M4RE([m4_re_string], [ab9_c], [ok])
AT_CHECK_M4RE([m4_re_string], [_9abc], [ok])
AT_CHECK_M4RE([m4_re_string], [9ab_c], [ok])
AT_CHECK_M4RE([m4_re_string], [9a@_c])

AT_CLEANUP

## ---------- ##
## M4 Loops.  ##
## ---------- ##

AT_SETUP([M4 loops])

AT_CHECK_M4SUGAR_TEXT([[dnl
m4_define([myvar], [outer value])dnl
m4_for([myvar], 1, 3, 1, [ myvar])
m4_for([myvar], 1, 3,  , [ myvar])
m4_for([myvar], 3, 1,-1, [ myvar])
m4_for([myvar], 3, 1,  , [ myvar])
m4_for([myvar], 1, 3, 2, [ myvar])
m4_for([myvar], 3, 1,-2, [ myvar])
m4_for([myvar],-1,-3,-2, [ myvar])
m4_for([myvar],-3,-1, 2, [ myvar])
dnl Make sure we recalculate the bounds correctly:
m4_for([myvar], 1, 3, 3, [ myvar])
m4_for([myvar], 1, 6, 3, [ myvar])
m4_for([myvar],22,-7,-5, [ myvar])
m4_for([myvar],-2,-7,-4, [ myvar])
m4_for([myvar],-7,-2, 4, [ myvar])
dnl Make sure we are not exposed to division truncation:
m4_for([myvar], 2, 5, 2, [ myvar])
m4_for([myvar],-5,-2, 2, [ myvar])
m4_for([myvar], 5, 2,-2, [ myvar])
m4_for([myvar],-2,-5,-2, [ myvar])
dnl Make sure we do not divide by zero:
m4_for([myvar], 1, 1,  , [ myvar])
m4_for([myvar], 1, 1,+2, [ myvar])
m4_for([myvar], 1, 1,-2, [ myvar])
dnl Make sure we do not loop endlessly
m4_for([myval], 1, 1, 0, [ myval])
dnl Make sure to properly parenthesize
m4_for([myvar], 3-5, -2+8, , [ myvar])
m4_for([myvar], -2+8, 3-5, , [ myvar])
m4_for([myvar], 8, 16, 3 * 2, [ myvar])
m4_for([myvar], 8, 16, -3 * -2, [ myvar])
m4_for([myvar], [2<<2], [2<<3], [-3 * (-2)], [ myvar])
m4_foreach([myvar], [[a], [b, c], [d], [e
],[f]], [ myvar|])
m4_foreach_w([myvar], [a  b c, d,e f
g], [ myvar|])
myvar
]],
[[ 1 2 3
 1 2 3
 3 2 1
 3 2 1
 1 3
 3 1
 -1 -3
 -3 -1
 1
 1 4
 22 17 12 7 2 -3
 -2 -6
 -7 -3
 2 4
 -5 -3
 5 3
 -2 -4
 1
 1
 1
 1
 -2 -1 0 1 2 3 4 5 6
 6 5 4 3 2 1 0 -1 -2
 8 14
 8 14
 8 14
 a| b, c| d| e
| f|
 a| b| c,| d,e| f| g|
outer value
]], [])

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
autom4te: m4 failed with exit status: 1
]])

AT_DATA_M4SUGAR([script.4s],
[[m4_init
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
autom4te: m4 failed with exit status: 1
]])

AT_DATA_M4SUGAR([script.4s],
[[m4_init
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
]])
AT_CLEANUP
