Topic: A preprocessor feature we should have had 40 years ago


Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: Thu, 23 May 2013 19:18:54 CST
Raw View
This is going to the C and C++ lists because it is equally applicable to
both.

I've occasionally needed to use the preprocessor to repeat a piece of
code some variable number of times. What would be so hard about
implementing this?

     #repeat <identifier> <const-expression>
     ...
     #endrepeat

The expression would be evaluated, and the contents of the block would
be repeated that number of times, with the preprocessor identifier
taking values 0 through n-1. Even with a fixed count, this can be useful:

     const int squares[] = {
     #repeat I 101
         I * I,
     #endrepeat
     };

Less trivial usages would of course involve counts that are themselves
preprocessor symbols or expressions. The only way to do this now is to
nest a lot of #if statements, up to some maximum size one might need,
and explicitly write the contents of each iteration.

--

Ciao,           Paul D. DeRocco
Paul            mailto:pderocco@ix.netcom.com


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Eric Sosman <esosman@comcast-dot-net.invalid>
Date: Fri, 24 May 2013 15:19:09 -0700 (PDT)
Raw View
On 5/23/2013 9:18 PM, Paul D. DeRocco wrote:
>
>
> This is going to the C and C++ lists because it is equally applicable to
> both.
>
> I've occasionally needed to use the preprocessor to repeat a piece of
> code some variable number of times. What would be so hard about
> implementing this?
>
>      #repeat <identifier> <const-expression>
>      ...
>      #endrepeat


    If you want PL/I, you know where to find it.

    (FWIW: In three years of writing PL/I, I used the analogous
construct once -- and in retrospect, it was a bad idea.  YMMV.)

--
Eric Sosman
esosman@comcast-dot-net.invalid


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]




Author: jacob navia <jacob@spamsink.net>
Date: Sat, 25 May 2013 02:23:16 -0700 (PDT)
Raw View
Le 24/05/13 03:18, Paul D. DeRocco a    crit :
> the contents of the block would
> be repeated that number of times, with the preprocessor identifier
> taking values 0 through n-1. Even with a fixed count, this can be useful:
>
>      const int squares[] = {
>      #repeat I 101
>          I * I,
>      #endrepeat
>      };

I am thinking about a C program that:

1) opens a text file. Output is ON: lines are copied to a temporary file.

2) Scans all lines selecting those that start with the character string
"#repeat" followed by  space/tab. All lines are copied to the temporary
file.

3) When a repeat directive is detected, it reads an identifier and the
count. Output is OFF, i.e. lines are read without being copied into the
temporary file but appended to a temporary buffer.

4) Goes on scanning lines in replace mode, replacing all identifiers
that match the given one by a placeholder.

5) When it reaches the end repeat directive (that is searched for only
in replace mode) builds a loop of N iterations outputting the text found
within the directive. The place-holders are replaced by the textual form
of the integer counter.

5) Output is set to ON again and processing continues at step 2.

6) End of file is seen. Processing stops, file is closed and the
compiler is called to process the temporary file. This shouldn't happen
in replace mode.

Of course this is bare bones. More expensive versions accept an
increment count (that defaults to 1), a printf format string for the
counter (that defaults to "%d") and probably other stuff that will be
discovered with usage: parameters to the expansion (should spaces be
added between the replacement text or not? should new lines be honored
in the output or should the output be a single line? etc) or even other
useful directives not discovered yet.


This makes for a very simple C program, at most 500 or 1000 lines...

Remember RATFOR?

RATC exists, you have just proposed it (again).

jacob



--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]




Author: Keith Thompson <kst-u@mib.org>
Date: Sat, 25 May 2013 02:24:09 -0700 (PDT)
Raw View
"Paul D. DeRocco" <pderocco@ix.netcom.com> writes:
> This is going to the C and C++ lists because it is equally applicable to
> both.
>
> I've occasionally needed to use the preprocessor to repeat a piece of
> code some variable number of times. What would be so hard about
> implementing this?
>
>      #repeat <identifier> <const-expression>
>      ...
>      #endrepeat
>
> The expression would be evaluated, and the contents of the block would
> be repeated that number of times, with the preprocessor identifier
> taking values 0 through n-1. Even with a fixed count, this can be useful:
>
>      const int squares[] = {
>      #repeat I 101
>          I * I,
>      #endrepeat
>      };
>
> Less trivial usages would of course involve counts that are themselves
> preprocessor symbols or expressions. The only way to do this now is to
> nest a lot of #if statements, up to some maximum size one might need,
> and explicitly write the contents of each iteration.

No, that's not the *only* way to do that.  You could write another
program that generates C source code from an input file in some well
defined format.  That format could even be standard C source with the
addition of a "#repeat" directive recognized by the program.  Make it
part of your build process, and voila, you have a #repeat directive.

In my opinion, the need to have simply repeated lines of code like
that is rare enough that it doesn't justify adding a new feature
to the preprocessor and to the language standard.

I wouldn't have *opposed* adding such a feature to the preprocessor
from the beginning, but I think adding it now would cause more
trouble than it's really worth, as new code that depends on it would
fail to compile on pre-C20XY compilers.  (Which is admittedly an
argument against adding *anything* to the language.)

--
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
     -- Antony Jay and Jonathan Lynn, "Yes Minister"


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]




Author: Rui Maciel <rui.maciel@googlemail.com>
Date: Sat, 25 May 2013 23:43:26 -0700 (PDT)
Raw View
Paul D. DeRocco wrote:

> This is going to the C and C++ lists because it is equally applicable to
> both.
>
> I've occasionally needed to use the preprocessor to repeat a piece of
> code some variable number of times. What would be so hard about
> implementing this?
>
> #repeat <identifier> <const-expression>
> ...
> #endrepeat
>
> The expression would be evaluated, and the contents of the block would
> be repeated that number of times, with the preprocessor identifier
> taking values 0 through n-1. Even with a fixed count, this can be useful:
>
> const int squares[] = {
> #repeat I 101
> I * I,
> #endrepeat
> };
>
> Less trivial usages would of course involve counts that are themselves
> preprocessor symbols or expressions. The only way to do this now is to
> nest a lot of #if statements, up to some maximum size one might need,
> and explicitly write the contents of each iteration.

What's wrong with using for() loops?  Compilers are able to unroll loops for
some time now.


Rui Maciel


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]




Author: "Kenneth \"Bessarion\" Boyd" <zaimoni@zaimoni.com>
Date: Sat, 25 May 2013 23:43:56 -0700 (PDT)
Raw View
On Saturday, May 25, 2013 4:24:09 AM UTC-5, Keith Thompson wrote:
> "Paul D. DeRocco" <pderocco@ix.netcom.com> writes:
>
> > This is going to the C and C++ lists because it is equally applicable to
>
> > both.
>
> >
>
> > I've occasionally needed to use the preprocessor to repeat a piece of
>
> > code some variable number of times. What would be so hard about
>
> > implementing this?
>
> >
>
> >      #repeat <identifier> <const-expression>
>
> >      ...
>
> >      #endrepeat
>
> >
>
> > The expression would be evaluated, and the contents of the block would
>
> > be repeated that number of times, with the preprocessor identifier
>
> > taking values 0 through n-1.

.....

> In my opinion, the need to have simply repeated lines of code like
>
> that is rare enough that it doesn't justify adding a new feature
>
> to the preprocessor and to the language standard.
>
>
>
> I wouldn't have *opposed* adding such a feature to the preprocessor
>
> from the beginning, but I think adding it now would cause more
>
> trouble than it's really worth, as new code that depends on it would
>
> fail to compile on pre-C20XY compilers.  (Which is admittedly an
>
> argument against adding *anything* to the language.)

Especially when this has already been implemented in the Boost
libraries, using a purely standard preprocessor.


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]




Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: Sat, 25 May 2013 23:44:39 -0700 (PDT)
Raw View
> On 5/25/2013 2:24 AM, Keith Thompson wrote:
>
>
> No, that's not the *only* way to do that.  You could write another
> program that generates C source code from an input file in some well
> defined format.  That format could even be standard C source with the
> addition of a "#repeat" directive recognized by the program.  Make it
> part of your build process, and voila, you have a #repeat directive.


Sure, but that's not doing it IN C/C++. And that requires a learning
curve if you want to figure out how to integrate it into Eclipse, or
Visual Studio, or Codewarrior, since normally one uses an IDE without
learning the ugly details about how its configured. And to give the
project to someone else, you have to provide the executable for that
extra tool, not just a project file and a bunch of source code.

> In my opinion, the need to have simply repeated lines of code like
> that is rare enough that it doesn't justify adding a new feature
> to the preprocessor and to the language standard.


I found I needed it recently, in order to build the descriptor tables
for a USB driver that I wanted to parameterize by the number of
endpoints. Since they had to be in flash, they had to be written as
constant tables. Then, in perusing the Atmel library, I discovered
that they, too, had come up against the same sort of thing, and had
used a big tree of #if blocks too.

> I wouldn't have *opposed* adding such a feature to the preprocessor
> from the beginning, but I think adding it now would cause more
> trouble than it's really worth, as new code that depends on it would
> fail to compile on pre-C20XY compilers.  (Which is admittedly an
> argument against adding *anything* to the language.)


It seems like the C++ community is generally open to useful additions
to the language, more so than the C community. Look at all the arcana
added since C++98. Furthermore, it seems like the GNU community is
even more open to extensions that go beyond what the standards
provide. Yet no one seems interested in the lowly preprocessor, even
though it hasn't been touched in decades. Besides, no new feature
"causes trouble" unless it introduces an incompatibility, which it
never should. If you don't use it, you don't notice it's there. I was
just hoping someone else would find this useful.

By the way, this particular extension could also be extended to
iterate through the characters of a string constant, something I've
needed to do a couple of times. Another trivial example:

    #define NAME "foobar" // e.g., in an include file

    const char name[] = NAME;
    const char ucase_name[] = {
        #repeat c NAME
        c < 'a' ? c : c <= 'z' ? c - 0x20 : c,
        #endrepeat
        0 };

In desktop environments, these issues don't generally come up, because
they all run entirely out of RAM, and expect to use extensive init
code anyway, so variable-sized tables can be built at runtime in
containers. In embedded environments, though, you often need to put
stuff in ROM, which these constructs would make a lot easier.

--

Ciao,           Paul D. DeRocco
Paul            mailto:pderocco@ix.netcom.com


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]




Author: Francis Glassborow <francis.glassborow@btinternet.com>
Date: Sun, 26 May 2013 08:52:59 CST
Raw View
On 26/05/2013 07:44, Paul D. DeRocco wrote:
>> On 5/25/2013 2:24 AM, Keith Thompson wrote:
> It seems like the C++ community is generally open to useful additions
> to the language, more so than the C community. Look at all the arcana
> added since C++98. Furthermore, it seems like the GNU community is
> even more open to extensions that go beyond what the standards
> provide. Yet no one seems interested in the lowly preprocessor, even
> though it hasn't been touched in decades. Besides, no new feature
> "causes trouble" unless it introduces an incompatibility, which it
> never should. If you don't use it, you don't notice it's there. I was
> just hoping someone else would find this useful.
>


I guess you do not realise how big a problem the pre-processor is to
C++, not least because it is completely 'ignorant' of such things as
namespaces. If a way could be found to remove it or at least seriously
reduce its use I think WG21 would grab the opportunity.  The
pre-processor does get used extensively but the cost is actually pretty
high in complexity and debugging costs.

New features cause trouble by adding more ways to go wrong. We should be
endeavouring to reduce dependence on the pre-processor rather than
adding to it.

BTW I suspect that constexpr from C++11 might solve problems such as
upper-casing a literal so that the result could be placed in ROM.

Francis


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Peter <pcurran88@googlemail.com>
Date: Thu, 30 May 2013 19:40:45 CST
Raw View
On May 23, 8:20 pm, "Paul D. DeRocco" <pdero...@ix.netcom.com> wrote:
> This is going to the C and C++ lists because it is equally applicable to
> both.
>
> I've occasionally needed to use the preprocessor to repeat a piece of
> code some variable number of times. What would be so hard about
> implementing this?
>
>      #repeat <identifier> <const-expression>
>      ...
>      #endrepeat
>
> The expression would be evaluated, and the contents of the block would
> be repeated that number of times, with the preprocessor identifier
> taking values 0 through n-1. Even with a fixed count, this can be useful:
<snip>

Over many years, I have heard two main arguments against this kind of
feature.

The first is the "slippery slope" argument. Where do you stop? What
about a preprocessor-while statement? A preprocessor-for statement?
Arithmetic statements? A library of string functions? A library of
arithmetic functions? User-written preprocessor functions? Etc, etc.
Over the years I have had occasions where all of these would have been
useful. It would be very hard to draw a line, but all the imaginable
and useful features could result in a mess.

The second argument is, if you want that, you can create it. In many,
if not most, programming environments, it would be simple to insert a
customized preprocessor into the compilation sequence. You just have
to write it, and use it. There are in fact a few extended
preprocessors out there. I have had occasion to use tools like 'sed'
as a preprocessor.

The fact that such tools aren't widely used could be taken as a sign
that they aren't wanted, or as a sign that a non-standardized tool is
not going to catch on. If you believe the latter, you can get involved
with The Committee and try to make it happen.


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: Sat, 1 Jun 2013 02:04:58 CST
Raw View
> On 5/30/2013 6:40 PM, Peter wrote:
>
>
> Over many years, I have heard two main arguments against this kind of
> feature.
>
> The first is the "slippery slope" argument. Where do you stop? What
> about a preprocessor-while statement? A preprocessor-for statement?
> Arithmetic statements? A library of string functions? A library of
> arithmetic functions? User-written preprocessor functions? Etc, etc.
> Over the years I have had occasions where all of these would have been
> useful. It would be very hard to draw a line, but all the imaginable
> and useful features could result in a mess.


A simple 0 to n-1 count seems like a likely stopping point. (My more
fanciful string-to-char iterator is perhaps a bridge too far.) A
"while" construct doesn't make much sense, since there is nothing that
can change value in an unpredictable manner in the preprocessor, and
that therefore can't be boiled down to a simple count.

> The second argument is, if you want that, you can create it. In many,
> if not most, programming environments, it would be simple to insert a
> customized preprocessor into the compilation sequence. You just have
> to write it, and use it. There are in fact a few extended
> preprocessors out there. I have had occasion to use tools like 'sed'
> as a preprocessor.


That creates a barrier to distribution, because you can no longer just
ship some .cpp and .h files; you also have to ship either an
executable tool for whatever platform someone might wish to compile
the program with, or source for the executable tool; and then you have
to provide a customized makefile for the program that includes the
appropriate rule, which presumes the use of a particular make utility
since they're not standardized the way the language is.

Oh, well.

--

Ciao,           Paul D. DeRocco
Paul            mailto:pderocco@ix.netcom.com


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: ootiib@hot.ee
Date: Sat, 1 Jun 2013 14:53:31 CST
Raw View
On Saturday, 1 June 2013 10:10:03 UTC+3, Paul D. DeRocco  wrote:
> > On 5/30/2013 6:40 PM, Peter wrote:
> > The second argument is, if you want that, you can create it. In many,
> > if not most, programming environments, it would be simple to insert a
> > customized preprocessor into the compilation sequence. You just have
> > to write it, and use it. There are in fact a few extended
> > preprocessors out there. I have had occasion to use tools like 'sed'
> > as a preprocessor.
>
> That creates a barrier to distribution, because you can no longer just
> ship some .cpp and .h files; you also have to ship either an
> executable tool for whatever platform someone might wish to compile
> the program with, or source for the executable tool; and then you have
> to provide a customized makefile for the program that includes the
> appropriate rule, which presumes the use of a particular make utility
> since they're not standardized the way the language is.

What software is distributed as only "some .cpp and .h files"? The
work that you describe is always done anyway regardless if there
is some custom code generator or preprocessor in tool-chain or not.


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kuyper <jameskuyper@verizon.net>
Date: Tue, 4 Jun 2013 10:41:59 CST
Raw View
On 06/01/2013 04:04 AM, Paul D. DeRocco wrote:
...
> the program with, or source for the executable tool; and then you have
> to provide a customized makefile for the program that includes the
> appropriate rule, which presumes the use of a particular make utility
> since they're not standardized the way the language is.

Some make utilities are standardized; POSIX make, for instance. Of
course, that won't do you much good if your target platform doesn't
conform to POSIX, but it's not the absence of a standard that's the
problem; it's the fact that many systems haven't adopted it.


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: espie@lain.home (Marc Espie)
Date: Wed, 5 Jun 2013 23:12:48 -0700 (PDT)
Raw View
In article <51ACB83B.9080903@verizon.net>,
James Kuyper  <jameskuyper@verizon.net> wrote:
>
>On 06/01/2013 04:04 AM, Paul D. DeRocco wrote:
>...
>> the program with, or source for the executable tool; and then you have
>> to provide a customized makefile for the program that includes the
>> appropriate rule, which presumes the use of a particular make utility
>> since they're not standardized the way the language is.
>
>Some make utilities are standardized; POSIX make, for instance. Of
>course, that won't do you much good if your target platform doesn't
>conform to POSIX, but it's not the absence of a standard that's the
>problem; it's the fact that many systems haven't adopted it.

make is probably *the* example tool that's standardized in such a fuzzy
way as to be interpreted any which way.

POSIX talks about parallel makes, but does not define all that much.

POSIX talks about % being "reserved", but does not describe the corresponding
suffix rules.

A lot of fairly common, and almost universal extensions, are not standardized,
the most prominent being VPATH and .PHONY...

I suspect there are almost no posix-compliant makes out there. Not fully.
They all come with some extensions, and they all forego some part of the
current POSIX standard.


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]




Author: James Kuyper <jameskuyper@verizon.net>
Date: Thu, 6 Jun 2013 09:20:26 -0700 (PDT)
Raw View
On 06/06/2013 02:12 AM, Marc Espie wrote:
> In article <51ACB83B.9080903@verizon.net>,
> James Kuyper  <jameskuyper@verizon.net> wrote:
>>
>> On 06/01/2013 04:04 AM, Paul D. DeRocco wrote:
>> ...
>>> the program with, or source for the executable tool; and then you have
>>> to provide a customized makefile for the program that includes the
>>> appropriate rule, which presumes the use of a particular make utility
>>> since they're not standardized the way the language is.
>>
>> Some make utilities are standardized; POSIX make, for instance. Of
>> course, that won't do you much good if your target platform doesn't
>> conform to POSIX, but it's not the absence of a standard that's the
>> problem; it's the fact that many systems haven't adopted it.
>
> make is probably *the* example tool that's standardized in such a fuzzy
> way as to be interpreted any which way.
>
> POSIX talks about parallel makes, but does not define all that much.
>
> POSIX talks about % being "reserved", but does not describe the corresponding
> suffix rules.
>
> A lot of fairly common, and almost universal extensions, are not standardized,
> the most prominent being VPATH and .PHONY...
>
> I suspect there are almost no posix-compliant makes out there. Not fully.
> They all come with some extensions, and they all forego some part of the
> current POSIX standard.

GNU make has many extensions, but extensions can be done in a conforming
way - I know this is true for the C standard; I think it's true for
POSIX, too. The GNU Make Manual claims, without qualification, that "GNU
make conforms to section 6.2 of IEEE Standard 1003.2-1992 (POSIX.2)." Do
you know for certain that this is not the case? If so, could you
identify the nature of the non-conformance?
--
James Kuyper


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]