m4 adds extra space at top of file.

I have used m4 in the past to generate source code where aesthetics and space were of no consequence [ provided it worked ]. Now I am using it to generate script and program templates [ in an effort to improve the readability and general soundness of my scripts/programs ].

So here is an excerpt from my m4 file for producing a generic bash script:

dnl `$Id$'
define(`START_SCRIPT',`#!/bin/bash
#####################################
# File: $1
# Auth: $2
# Desc:
#
# TODO:
# BUGS:
# RCS: $Id$
#####################################
')

It outputs what you'd expect but tacks on 16 blank lines at the beginning of the file. I can use sed to remove these but I am thinking there is an m4 basic I am missing. I've looked through the docs and various tutorials. Maybe I have a buggy m4?

Thanks!

Bubnoff

Hi, I think you need to end your defines with dnl after the closing parentheses

This does help -- thanks. Where is this documented? I've been looking and haven't seen any examples where the defines were ended this way. I assume you mean:

define(`START_SCRIPT',`#!/bin/bash
#####################################
# File: $1
# Auth: $2
# Desc:
#
# TODO:
# BUGS:
# RCS: $Id$
#####################################
')dnl

Also, I still have 2 blank lines. Much less than what I had, but still producing blank lines.

What is the rule for this?

Thanks for your help!!!

Bub

Hi, I do not know where you can find it online.. FWIW, I checked my O'Reilly Sendmail book and it is in paragraph 19.1.2 (m4 and dnl).

1 Like

Thanks, I think I'm getting close -- down to one blank line.

I found references to this idiosyncrasy online.

Bub

define(`START_SCRIPT',`#!/bin/bash
#####################################
# File: $1
# Auth: $2
# Desc:
#
# TODO:
# BUGS:
# RCS: $Id$
#####################################
')dnl 
START_SCRIPT()dnl

Thanks for the replies. I tried adding dnl both in the macro and in the file and I still end up with one blank line at the top.

However, the resulting scripts work and if it really bothers me I can pull out a can o' sed on it.

What bothers me is the fact that there does not appear to be rhyme or reason for this behavior. Is m4 truly obsolete and no longer maintained? Other than sendmail is m4 worth the trouble verses using some bloated perl template script?

I hate to make a whing-fest out of a single blank line ...yet ...

Well, here's the pertinent parts for the curious. Maybe I've overlooked something else.

Sample use of macros:

include(`bash_macros.m4')
START_SCRIPT(`fake_script',`Automation Dept.')
GLOBALS()
SANITY_CHECKS()
FUNCTIONS()
MAIN()
END_SCRIPT()

Macros themselves:

define(`START_SCRIPT',#!/bin/bash
#####################################
# File: $1
# Auth: $2
# Desc:
#
# TODO:
# BUGS:
# RCS: $Id$
#####################################
)dnl
dnl
define(`LQ', `changequote(<,>)`dnl'
changequote`'')dnl
dnl
define(`RQ',`changequote(<,>)dnl`
'changequote`'')dnl
dnl
define(`GLOBALS',
#------------------------------------
# Globals
#------------------------------------
declare -rx SCRIPT=${0##*/}
SCRIPTNAME=${0%%.*}
FULLPATH=``$'0'
DATE=$`('date +%m-%d-%Y`)'
)dnl
dnl
define(`SANITY_CHECKS',
#------------------------------------
# Sanity Checks
#------------------------------------
if test -z "$BASH" ; then
    printf "$SCRIPT:$LINENO: Use BASH to run this script.\n" >&2
    exit 192
fi

# Test binaries
# Example:
# if test ! -x "$PRINT" ; then
#     printf "$SCRIPT:$LINENO: the command $PRINT is not available." >&2
#     exit 192
# fi

# Test file existence
# if test ! -e "$BKPLOG" ; then
#        RPT="File not found"
# else
#        RPT=$(/usr/bin/basename $BKPLOG)
# fi
)dnl
dnl
define(`FUNCTIONS',
#------------------------------------
# Functions
#------------------------------------
function func_usage ()
{
    echo ""
    echo "USAGE: "
    echo "    script_template.sh [-fh] <filename>"
    echo ""
    echo "OPTIONS:"
    echo "    -f  <filename>"
    echo "    -h  usage info"
    echo ""
    echo "EXAMPLE:"
    echo "    script_template.sh -f <filename>"
    echo ""
    exit $E_OPTERROR    # Exit and explain usage, if no argument(s) given.
}
)dnl
dnl
define(`MAIN',
#------------------------------------
# MAIN
#------------------------------------

# process args.
while getopts ":f:h" option
do
    case $option in
        f    `)' FILE=$OPTARG
             ;;
        h    `)' func_usage
               exit 0
             ;;
        *    `)' echo ""
               echo "Bad option."
               func_usage
    esac
done

shift $(($OPTIND - 1))
)dnl
dnl
define(`END_SCRIPT',
#---------------------------
# Cleanup
#---------------------------
exit 0
)dnl

A sample run:

m4 test.txt > new_script.sh

You will get a fairly textbook bash script template ...overkill for many tasks, but nice for larger stuff ...with a blank line at the top.

I am using m4 version 1.4.13 on Ubu 10.04.

Thanks for reading!

Bubnoff

try

include(`bash_macros.m4')
START_SCRIPT(`fake_script',`Automation Dept.')dnl
GLOBALS()
SANITY_CHECKS()
FUNCTIONS()
MAIN()
END_SCRIPT()
1 Like

[UPDATE - SOLVED - See updates at bottom.]

Thanks John, however, I still get the blank line on line one.
Here's the output ( excerpt of top ) via:

cat -n test.sh | head

Output:

 
     1  
     2  #!/bin/bash
     3  #####################################
     4  # File: fake_script
     5  # Auth: Automation Dept. 
     6  # Desc:
     7  #
     8  # TODO:
     9  # BUGS:
    10  # RCS: $Id$
    

As an aside:
This is part of a larger make script to generate various projects with different options/parameters ...otherwise I could simply copy a template. I hope to use the macros as I'd be passing in various options ...more flexibility, etc..

Thanks again for all your input!

Bubnoff

---------- Post updated at 04:01 PM ---------- Previous update was at 03:53 PM ----------

Eureka!!

John, your solution worked with one adjustment:

You suggested:

include(`shell_script.m4')
START_SCRIPT(`fake_script',`Automation Dept. - CR')dnl
GLOBALS()
SANITY_CHECKS()
FUNCTIONS()
MAIN()
END_SCRIPT()

The solution was:

include(`shell_script.m4')dnl
START_SCRIPT(`fake_script',`Automation Dept. - CR')
GLOBALS()
SANITY_CHECKS()
FUNCTIONS()
MAIN()
END_SCRIPT()

You probably were suggesting this but overlooked my include statement. Anyway, thanks ...you rock!!

Bubnoff