Shell [GNU - sed] sed command in makefile

I am having some trouble with sed on FreeBSD. I've been told that FreeBSD default sed is different than GNU sed and that I should try gsed.

I've tried gsed but it corrupts the transformation and later causes build issues. I have a Makefile.ac with this code.

The Makefile.in file code that handles this part is:
Code:
$(srcdir)/utsushi/tag.hpp $(srcdir)/lib/tag.cpp: $(srcdir)/lib/tag.xml \ $(srcdir)/lib/tag.xsl format=`echo $@ | sed 's|.*\.\([^.]*\)$$|\1|'`; \ sed -n \ -e "/^/{ /-->/d; s|^$$|//|p; s|^....|//|p; }' $< > $@; \ xsltproc --stringparam format $$format $(srcdir)/lib/tag.xsl $< >> $@ sed -i 's/SEC_N_("%1%")/"%1%"/' $@

I think that it could be a difference in shells but I am not sure.


Here's the commands that I am running:
Code:
xsltproc --verbose --stringparam format hpp ./lib/tag.xsl > _tags.hpp
creating dictionary for stylesheet
reusing dictionary from ./lib/tag.xsl for stylesheet
xsltParseStylesheetProcess : found stylesheet
xsltPrecomputeStylesheet: removing ignorable blank node
xsltParseTemplateContent: removing text
xsltCompilePattern : parsing 'tags'
xsltCompilePattern : parsed tags, default priority 0.000000
added pattern : 'tags' priority 0.000000
parsed 1 templates
Resolving attribute sets references
freeing dictionary from stylesheet

here's the tags.xsl file:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!--  tag.xsl :: converts XML tag data to other formats
      Copyright (C) 2012, 2015  SEIKO EPSON CORPORATION

      License: GPL-3.0+
      Author : EPSON AVASYS CORPORATION

      This file is part of the 'Utsushi' package.
      This package 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 3 of the License 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 ought to have received a copy of the GNU General Public License
      along with this package.  If not, see <http://www.gnu.org/licenses/>.
  -->

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="UTF-8"/>

  <xsl:template match="tags">

    <xsl:choose>

      <xsl:when test="$format='hpp'">
//  Automatically generated from lib/tag.xml using lib/tag.xsl.

#ifndef utsushi_tag_hpp_
#define utsushi_tag_hpp_

#include &lt;set&gt;

#include &lt;boost/operators.hpp&gt;

#include "key.hpp"
#include "string.hpp"

namespace utsushi {

struct tag
{
  //! Collect options and groups by the aspects they affect
  /*! A %tag::symbol is a string-like key that can be used to indicate
   *  which aspects are affected by an option or group.  An option may
   *  specify zero or more %tag symbols.
   *
   *  Similar to a descriptor, every %tag::symbol provides name() and
   *  text() accessors describing its purpose.  A user interface may
   *  use this information to provide a more human-oriented and mostly
   *  self-documenting view of tags.
   *
   *  \note  The UI is responsible for the translation of name() and
   *         text() as well as any formatting of the text().
   *
   *  \sa  descriptor::name(), descriptor::text()
   */
  class symbol
    : boost::totally_ordered&lt; symbol &gt;
  {
  public:
    symbol (const key&amp; key,
            const string&amp; name, const string&amp; text);

    //! \copybrief descriptor::name
    const string&amp; name () const;
    //! \copybrief descriptor::text
    const string&amp; text () const;

    bool operator== (const symbol&amp; ts) const;
    bool operator&lt; (const symbol&amp; ts) const;

    operator key () const;

  private:
    key key_;
    string name_;
    string text_;
  };

  static const symbol none;<xsl:for-each select="tag">
  static const symbol <xsl:value-of select="@key"/>;</xsl:for-each>
};

class tags
{
private:
  typedef std::set&lt; tag::symbol &gt; container_type;
  static container_type set_;
  static void initialize ();

public:
  typedef container_type::size_type size_type;
  typedef container_type::const_iterator const_iterator;

  static size_type count ();
  static const_iterator begin ();
  static const_iterator end ();
};

}       // namespace utsushi

#endif  /* utsushi_tag_hpp_ */
<xsl:text/>
      </xsl:when>

      <xsl:when test="$format='cpp'">
//  Automatically generated from tag.xml using tag.xsl.

#ifdef HAVE_CONFIG_H
#include &lt;config.h&gt;
#endif

#include "utsushi/i18n.hpp"
#include "utsushi/tag.hpp"

namespace utsushi {

tag::symbol::symbol (const key&amp; key,
                     const string&amp; name, const string&amp; text)
  : key_(key), name_(name), text_(text)
{}

const string&amp;
tag::symbol::name () const
{
  return name_;
}

const string&amp;
tag::symbol::text () const
{
  return text_;
}

bool
tag::symbol::operator== (const symbol&amp; ts) const
{
  return key_ == ts.key_;
}

bool
tag::symbol::operator&lt; (const tag::symbol&amp; ts) const
{
  return key_ &lt; ts.key_;
}

tag::symbol::operator key () const
{
  return key_;
}

<xsl:for-each select="tag">
const tag::symbol tag::<xsl:value-of select="@key"/> (
  "<xsl:number format="01"/>_<xsl:value-of select="@key"/>",
  SEC_N_("<xsl:value-of select="normalize-space(name)"/>"),
  CCB_N_("<xsl:value-of select="normalize-space(text)"/>")
);</xsl:for-each>

tags::container_type tags::set_;

void
tags::initialize ()
{
  container_type::iterator hint = set_.begin ();

<xsl:for-each select="tag">  hint = set_.insert (hint, tag::<xsl:value-of select="@key"/>);
</xsl:for-each>}

tags::size_type
tags::count ()
{
  if (set_.empty ())
    {
      initialize ();
    }
  return set_.size ();
}

tags::const_iterator
tags::begin ()
{
  if (set_.empty ())
    {
      initialize ();
    }
  return set_.begin ();
}

tags::const_iterator
tags::end ()
{
  if (set_.empty ())
    {
      initialize ();
    }
  return set_.end ();
}

}       // namespace utsushi
<xsl:text/>
      </xsl:when>

    </xsl:choose>

  </xsl:template>

</xsl:stylesheet>

If there are anyone out there proficient with sed that can give me a hand with this.
 
First of all I wouldn't use | as a delimiter since it may be confused with the shell pipelines, maybe something neutral like + or = instead.
Also you have an unmatched double-quote and unescaped >.
The single-lined code above is not well readable, you already have backslashes for next lines, why not split them?
 
First of all I wouldn't use | as a delimiter since it may be confused with the shell pipelines, maybe something neutral like + or = instead.
Also you have an unmatched double-quote and unescaped >.
The single-lined code above is not well readable, you already have backslashes for next lines, why not split them?

Thanks for the feedback aragats but the code isn't mine. I'll try to post a cleaner sample, the code block changed the format.

The code block really messes this up. I'll upload the Makefile.ac as well as post an excerpt on a paste site: https://paste2.org/2pX8bUwF

I had to change the .am extension to .txt.

edit, running the make -dA command, the output stops at this:
Code:
Found './configure' as './configure'
./configure:@ = ./configure
./configure:@ = ./configure
./configure:* = ./configure
SuffFindDeps (./configure)
   No known suffix on ./configure. Using .NULL suffix
not adding suffix rules
./configure:@ = ./configure
./configure:* = ./configure
Searching for ./configure ...
   in '.'
./configure:@ = ./configure
./configure:* = configure
Examining ./lib/tag.xml...modified 19:03:29 Jun 09, 2017...up-to-date.
Examining ./lib/tag.xsl...modified 19:03:29 Jun 09, 2017...up-to-date.
Examining ./utsushi/tag.hpp...Wildcard expanding "./utsushi/tag.hpp"...Searching for ./utsushi/tag.hpp ...
   Trying subdirectories...
checking ./utsushi/tag.hpp ...
checking /usr/home/bcomputerguy/Downloads/Epson/ut/./utsushi/tag.hpp ...
   Checked . already, returning NULL
Found './utsushi/tag.hpp' as '(not found)'
non-existent...modified before source ./lib/tag.xml...out-of-date.
./utsushi/tag.hpp:> = ./lib/tag.xml
./utsushi/tag.hpp:? = ./lib/tag.xml
./utsushi/tag.hpp:> = ./lib/tag.xml ./lib/tag.xsl
./utsushi/tag.hpp:? = ./lib/tag.xml ./lib/tag.xsl
format=`echo ./utsushi/tag.hpp | sed 's|.*\.\([^.]*\)$|\1|'`;  sed -n  -e "/^<!--/s/\.xml ::/.$format --/"  -e '/^<!--/,/-->/{ /-->/d; s|^$|//|p; s|^....|//|p; }'  > ./utsushi/tag.hpp;  xsltproc --stringparam format $format ./lib/tag.xsl  >> ./utsushi/tag.hpp
Execute: 'format=`echo ./utsushi/tag.hpp | sed 's|.*\.\([^.]*\)$|\1|'`;  sed -n  -e "/^<!--/s/\.xml ::/.$format --/"  -e '/^<!--/,/-->/{ /-->/d; s|^$|//|p; s|^....|//|p; }'  > ./utsushi/tag.hpp;  xsltproc --stringparam format $format ./lib/tag.xsl  >> ./utsushi/tag.hpp'
Applying[.MAKE.EXPORTED] :O to "META_MODE"
Result[.MAKE.EXPORTED] of :O is "META_MODE"
Applying[.MAKE.EXPORTED] :u to "META_MODE"
Result[.MAKE.EXPORTED] of :u is "META_MODE"
+ echo ./utsushi/tag.hpp
+ sed 's|.*\.\([^.]*\)$|\1|'
+ format=hpp
+ sed -n -e '/^<!--/s/\.xml ::/.hpp --/' -e '/^<!--/,/-->/{ /-->/d; s|^$|//|p; s|^....|//|p; }'

I am not really good with sed AND it's regex. That's hard enough but I don't know if it's gnu type sed or the limited FreeBSD sed.
 

Attachments

  • Makefile.txt
    10.1 KB · Views: 382
FreeBSD sed(1) expects a parameter after the -i flag, so for sure the sed command which comes right after the last line of the output, which you informed by your last message, won't work.

So, you want to try first replacing sed -i 's/SEC_N_("%1%")/"%1%"/' $@ with sed -i "" -e 's/SEC_N_("%1%")/"%1%"/' $@ -- note the two double quotes following the -i flag and the additional -e flag.

Your second try might be to force FreeBSD sed utilizing the modern regular expression scheme by adding a -E flag on the command line of each sed command as the very first parameter.

If these measures do not help, then simply switch temporarily to using gsed:
pkg install gsed
mkdir -p ~/bin
ln -s /usr/local/bin/gsed ~/bin/sed
setenv PATH ~/bin:$PATH

Verify that the symlinked gsed is in your path:
which sed --> /USER/bin/sed

Then execute your make command once again, and this time it should utilize gsed by the way of the symlink that has been placed in the users bin directory. Note, after a logging out/in cycle, the system's sed will return being the default one.
 
Back
Top