Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

An example: code to list exports of a Windows DLL.

92 views
Skip to first unread message

Alf P. Steinbach

unread,
Aug 1, 2019, 9:36:34 PM8/1/19
to
This just-now-it-compiled-and-appeared-to-work code is for whoever needs
or desires a tool to list DLL exports (e.g. because of the large amount
of irrelevant output from MS `dumpbin`, or because one doesn't want to
install Visual Studio but instead just use MinGW g++), or those
interested in the internal structure of a Windows PE format executable.

For the latter, if it's still available on the web then one could do
worse than reading Matt Pietrek's two- or three part article series.

I once posted an exports listing program like this on Stack Overflow,
back then only for 32-bit DLLS, and as I recall then by loading the DLL
and using the pointers in the image directly as pointers. This code
instead reads the file. As I recall from the SO posting the function
names are stored internally with UTF-8 encoding, but the documentation
says ASCII, yet, on the third hand, the documentation of encodings used
in Windows is known to be wildly inaccurate & misleading. I've yet to
test that. But apparently the documentation of `GetProcAddr` (the
Windows way of getting a pointer to specified function in a loaded DLL)
now says ASCII, instead of previously Windows ANSI.

The $ things in the following code are macros from the specified
header-only library on GitHub. E.g. `$use_std` expands to a `using`
declaration that prepends `std::` to each specified name. If use of the
library is undesired then just manually expand the macro invocations.

The "winapi-header-wrappers" micro-library is not on GitHub or anywhere,
but they're just simple wrappers, mostly just ensuring that
`<windows.h>` is included, because MS headers are not self-sufficient.


------------------------------------------------------------------------
#include <cppx-core/all.hpp> // <url:
https://github.com/alf-p-steinbach/cppx-core>
#include <winapi-header-wrappers/windows-h.hpp> // Just a
<windows.h> wrapper with UNICODE defined.
#include <winapi-header-wrappers/shellapi-h.hpp> // CommandLineToArgvW

namespace win_util {
$use_std( exchange );
$use_cppx( Wide_c_str, Mutable_wide_c_str, hopefully, P_ );

class Command_line_args
{
P_<Mutable_wide_c_str> m_parts;
int m_n_parts;

Command_line_args( const Command_line_args& ) = delete;
auto operator=( const Command_line_args& ) ->
Command_line_args& = delete;

public:
auto count() const -> int { return
m_n_parts - 1; }
auto operator[]( const int i ) const -> Wide_c_str { return
m_parts[i + 1]; }
auto invocation() const -> Wide_c_str { return
m_parts[0]; }

Command_line_args():
m_parts( CommandLineToArgvW( GetCommandLine(), &m_n_parts ) )
{
hopefully( m_parts != nullptr )
or $fail( "CommandLineToArgvW failed" );
}

Command_line_args( Command_line_args&& other ):
m_parts( exchange( other.m_parts, nullptr ) ),
m_n_parts( exchange( other.m_n_parts, 0 ) )
{}

~Command_line_args()
{
if( m_parts != nullptr ) {
LocalFree( m_parts );
}
}
};

} // namespace win_util

namespace app {
$use_std(
cout, clog, endl, invoke, runtime_error, string, vector
);
$use_cppx(
hopefully, fail_, Is_zero,
Byte, fs_util::C_file, Size, Index, C_str,
fs_util::read, fs_util::read_, fs_util::read_sequence,
fs_util::read_sequence_,
fs_util::peek_,
is_in, P_, to_hex, up_to
);
namespace fs = std::filesystem;
using namespace cppx::basic_string_building; // operator<<,
operator""s

// A class to serve simple failure messages to the user, via
exceptions. These
// exceptions are thrown without origin info, and are presented as
just strings.
// Don't do this in any commercial code.
class Ui_exception:
public runtime_error
{ using runtime_error::runtime_error; };

using Uix = Ui_exception;

struct Pe32_types
{
using Optional_header = IMAGE_OPTIONAL_HEADER32;
static constexpr int address_width = 32;
};

struct Pe64_types
{
using Optional_header = IMAGE_OPTIONAL_HEADER64;
static constexpr int address_width = 64;
};

template< class Type >
auto from_bytes_( const P_<const Byte> p_first )
-> Type
{
Type result;
memcpy( &result, p_first, sizeof( Type ) );
return result;
}

template< class Type >
auto sequence_from_bytes_( const P_<const Byte> p_first, const Size n )
-> vector<Type>
{
vector<Type> result;
if( n <= 0 ) {
return result;
}

result.reserve( n );
for( const Index i: up_to( n ) ) {
result.push_back( from_bytes_<Type>( p_first + i*sizeof(
Type ) ) );
}
return result;
}

// When this function is called the file position is at start of
the optional header.
template< class Pe_types >
void list_exports(
const string& u8_path,
const C_file& f,
const IMAGE_FILE_HEADER& pe_header
)
{
cout << Pe_types::address_width << "-bit DLL." << endl;

using Optional_header = typename Pe_types::Optional_header;
const auto pe_header_opt = read_<Optional_header>( f );

hopefully( IMAGE_DIRECTORY_ENTRY_EXPORT <
pe_header_opt.NumberOfRvaAndSizes )
or fail_<Uix>( ""s << "No exports found in '" << u8_path <<
"'." );

const auto section_headers = invoke( [&]()
-> vector<IMAGE_SECTION_HEADER>
{
vector<IMAGE_SECTION_HEADER> headers;
for( int _: up_to( pe_header.NumberOfSections ) ) {
(void) _; headers.push_back(
read_<IMAGE_SECTION_HEADER>( f ) );
}
return headers;
} );

const auto& dir_info =
pe_header_opt.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

hopefully( dir_info.Size >= sizeof( IMAGE_EXPORT_DIRECTORY ) )
or fail_<Uix>( "Ungood file: claimed size of export dir
header is too small." );

const IMAGE_SECTION_HEADER& section = invoke( [&]()
{
const auto dir_addr = dir_info.VirtualAddress;
const auto beyond_dir_addr = dir_addr + dir_info.Size;

for( const auto& s: section_headers ) {
const auto s_addr = s.VirtualAddress;
const auto beyond_s_addr = s_addr + s.SizeOfRawData;

if( s_addr <= dir_addr and beyond_dir_addr <=
beyond_s_addr ) {
return s;
}
}
fail_<Uix>( "Ungood file: no section (fully) contains the
export table." );
} );

hopefully( section.SizeOfRawData > 0 )
or fail_<Uix>( "Ungood file: section with export table, is
of length zero." );

const auto addr_to_pos = section.PointerToRawData -
section.VirtualAddress;
const auto dir_position = dir_info.VirtualAddress +
addr_to_pos;
fseek( f, dir_position, SEEK_SET ) >> Is_zero()
or fail_<Uix>( "Ungood file: a seek to the exports table
section failed." );
const auto dir = read_<IMAGE_EXPORT_DIRECTORY>( f );

if( dir.NumberOfFunctions == 0 ) {
cout << "No functions are exported";
} else if( dir.NumberOfFunctions == 1 ) {
cout << "1 function is exported, at ordinal 0";
} else if( dir.NumberOfFunctions > 1 ) {
cout << dir.NumberOfFunctions << " functions are exported"
<< ", at ordinals 0 ... " << dir.NumberOfFunctions - 1;
}
cout << "." << endl;

if( dir.NumberOfFunctions == 0 ) {
return;
}

fseek( f, dir.AddressOfNames + addr_to_pos, SEEK_SET ) >> Is_zero()
or fail_<Uix>( "Ungood file: a seek to the name addresses
table failed." );
const vector<DWORD> name_positions = read_sequence_<DWORD>( f,
dir.NumberOfNames );

vector<string> names;
names.reserve( name_positions.size() );
for( const DWORD name_addr: name_positions ) {
string name;
int ch;
fseek( f, name_addr + addr_to_pos, SEEK_SET ) >> Is_zero()
or fail_<Uix>( "Ungood file: a seek to the an export
name failed." );
while( (ch = fgetc( f )) != EOF and ch != 0 ) {
name += char( ch );
}
names.push_back( name );
}

fseek( f, dir.AddressOfNameOrdinals + addr_to_pos, SEEK_SET )
>> Is_zero()
or fail_<Uix>( "Ungood file: a seek to the ordinals table
failed." );
const vector<WORD> ordinals = read_sequence_<WORD>( f,
dir.NumberOfNames );

cout << string( 72, '-' ) << endl;
for( const int i: up_to( dir.NumberOfNames ) ) {
cout << names[i] << " @" << ordinals[i] << endl;
}
}

void run()
{
const auto args = win_util::Command_line_args();
hopefully( args.count() == 1 )
or fail_<Uix>( "Specify one argument: the DLL filename or
path." );

const fs::path dll_path = args[0];
const string u8_path = cppx::fs_util::utf8_from( dll_path );

const auto f = C_file( tag::Read(), dll_path );

const auto dos_header = read_<IMAGE_DOS_HEADER >( f );
hopefully( dos_header.e_magic == IMAGE_DOS_SIGNATURE )
//0x5A4D, 'MZ' multichar.
or fail_<Uix>( ""s << "No MZ magic number at start of '" <<
u8_path << "'." );

fseek( f, dos_header.e_lfanew, SEEK_SET ) >> Is_zero()
or fail_<Uix>( "fseek to PE header failed" );

const auto pe_signature = read_<DWORD>( f );
hopefully( pe_signature == IMAGE_NT_SIGNATURE )
//0x4550, 'PE' multichar.
or fail_<Uix>( ""s << "No PE magic number in PE header of
'" << u8_path << "'." );

const auto pe_header = read_<IMAGE_FILE_HEADER>( f );
const auto image_kind_spec = peek_<WORD>( f );

switch( image_kind_spec ) {
case IMAGE_NT_OPTIONAL_HDR32_MAGIC: { // 0x10B
list_exports<Pe32_types>( u8_path, f, pe_header );
break;
}
case IMAGE_NT_OPTIONAL_HDR64_MAGIC: { // 0x20B
list_exports<Pe64_types>( u8_path, f, pe_header );
break;
}
default: { // E.g. 0x107 a.k.a.
IMAGE_ROM_OPTIONAL_HDR_MAGIC
fail_<Uix>( "Not a PE32 (32-bit) or PE32+ (64-bit)
file." );
}
};
}
} // namespace app

auto main() -> int
{
$use_std( exception, cerr, endl, clog, ios_base );
$use_cppx( monospaced_bullet_block, description_lines_from );

#ifdef NDEBUG
clog.setstate( ios_base::failbit ); // Suppress trace output.
#endif
try {
app::run();
return EXIT_SUCCESS;
} catch( const app::Ui_exception& x ) {
cerr << "!" << x.what() << endl;
} catch( const exception& x ) {
cerr << monospaced_bullet_block( description_lines_from( x ) )
<< endl;
}
return EXIT_FAILURE;
}
------------------------------------------------------------------------


Example output:


[P:\commands\list-exports]
> a "c:\windows\system32\user32.dll" | more
64-bit DLL.
1215 functions are exported, at ordinals 0 ... 1214.
------------------------------------------------------------------------
ActivateKeyboardLayout @3
AddClipboardFormatListener @4
AdjustWindowRect @5
AdjustWindowRectEx @6
AdjustWindowRectExForDpi @7
AlignRects @8
AllowForegroundActivation @9
AllowSetForegroundWindow @10
AnimateWindow @11
...


The missing ordinals, and there are many more later in the sequence, may
be undocumented functions exported by ordinal only.



Cheers!,

- Alf

Alf P. Steinbach

unread,
Aug 2, 2019, 5:22:55 AM8/2/19
to
I looked at the code again this morning and noticed a potential bug, of
using unsigned types:

On 02.08.2019 03:36, Alf P. Steinbach wrote:
>         const auto addr_to_pos      = section.PointerToRawData -
> section.VirtualAddress;
>         const auto dir_position     = dir_info.VirtualAddress +
> addr_to_pos;

This uses unsigned types (Microsoft's choice) limited to 32 bits. And
yes, the "pointer" and "virtual address" values in a DLL file are 32-bit
even for a 64-bit DLL. Again, that's Microsoft's decision.

But when e.g. `addr_to_pos` is added to an address value that's
represented with 64 bits (I don't think I do that, but /if/), then the
offset will not act as negative, if it's in that direction. To prevent
possible such mishaps the offset type above should be signed:

const INT32 addr_to_pos = section.PointerToRawData -
section.VirtualAddress;
const DWORD dir_position = dir_info.VirtualAddress +
addr_to_pos;

The lesson here is system independent: beware of unsigned arithmetic,
don't use unsigned types for /numbers/, even when the API that one
relates to, does that.


Cheers!,

- Alf

rick.c...@gmail.com

unread,
Aug 2, 2019, 5:33:59 AM8/2/19
to
On Thursday, August 1, 2019 at 9:36:34 PM UTC-4, Alf P. Steinbach wrote:
> This just-now-it-compiled-and-appeared-to-work code is for whoever needs
> or desires a tool to list DLL exports (e.g. because of the large amount
> of irrelevant output from MS `dumpbin`, or because one doesn't want to
> install Visual Studio but instead just use MinGW g++), or those
> interested in the internal structure of a Windows PE format executable.


If you do want to use Visual Studio and dumpbin, here's a great
tutorial video by a premiere WinDbg developer on DLLs:

CppCon 2017:
James McNellis
“Everything You Ever Wanted to Know about DLLs”

https://www.youtube.com/watch?v=JPQWQfDhICA&t=17m30s

--
Rick C. Hodgin

Alf P. Steinbach

unread,
Aug 2, 2019, 2:20:36 PM8/2/19
to
On 02.08.2019 03:36, Alf P. Steinbach wrote:
> This just-now-it-compiled-and-appeared-to-work code is for whoever needs
> or desires a tool to list DLL exports (e.g. because of the large amount
> of irrelevant output from MS `dumpbin`, or because one doesn't want to
> install Visual Studio but instead just use MinGW g++), or those
> interested in the internal structure of a Windows PE format executable.

[snip]

I added base adjustment of ordinals.

MS' `dumpbin` does that, GNU `objdump` doesn't but reports it elsewhere
in its listing.

The code is now on GitHub with the 2 microlibraries used as submodules,

<url: https://github.com/alf-p-steinbach/list-exports>

Cheers!,

- Alf

Chris M. Thomasson

unread,
Aug 2, 2019, 7:54:29 PM8/2/19
to
dumpbin is very nice. Btw, I am 99.999...% sure you are familiar with:

https://docs.microsoft.com/en-us/sysinternals

Always like this as well:

http://www.dependencywalker.com

;^)


Chris M. Thomasson

unread,
Aug 2, 2019, 10:10:05 PM8/2/19
to
On 8/2/2019 4:54 PM, Chris M. Thomasson wrote:
> On 8/2/2019 2:33 AM, rick.c...@gmail.com wrote:
>> On Thursday, August 1, 2019 at 9:36:34 PM UTC-4, Alf P. Steinbach wrote:
[...]
> Always like this as well:
>
> http://www.dependencywalker.com

Its been a while since I used this. Fun that it works on an Alpha.

Richard

unread,
Aug 19, 2019, 3:44:36 PM8/19/19
to
[Please do not mail me a copy of your followup]

"Alf P. Steinbach" <alf.p.stein...@gmail.com> spake the secret code
<qi042o$if8$1...@dont-email.me> thusly:

>The $ things in the following code are macros from the specified
>header-only library on GitHub.

Can you tell me where in the standard it allows for $ to be part of an
identifier?

I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Alf P. Steinbach

unread,
Aug 19, 2019, 8:12:48 PM8/19/19
to
On 19.08.2019 21:44, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> spake the secret code
> <qi042o$if8$1...@dont-email.me> thusly:
>
>> The $ things in the following code are macros from the specified
>> header-only library on GitHub.
>
> Can you tell me where in the standard it allows for $ to be part of an
> identifier?
>
> I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.

In the future you might risk that people think you're a total novice,
one who doesn't even know the basics of identifiers in C++.

Having called you out on that:

I've not yet heard of a practical problem with it with any compiler.
However, when Herb Sutter tried this naming scheme on some years after I
first did it, he got negative reactions from some people whose company
used a critical custom preprocessing step where `$` was significant, and
which was sufficiently simple-minded to be misled into doing the Wrong
Thing™. So he dropped the scheme, but I don't have to. :)

No sane person would e.g. rewrite `#pragma once` to more verbose and
ugly and error prone include guards with formally guaranteed behavior
just to get that formal guarantee, but if there is a problem with the
`$`s, like the aforementioned preprocessing, then you can replace these
macro names with their uppercase aliases. Less readable IMO. But YMMV.


Cheers & hth.,

- Alf

Keith Thompson

unread,
Aug 19, 2019, 9:32:09 PM8/19/19
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
> On 19.08.2019 21:44, Richard wrote:
>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> spake the secret code
>> <qi042o$if8$1...@dont-email.me> thusly:
>>
>>> The $ things in the following code are macros from the specified
>>> header-only library on GitHub.
>>
>> Can you tell me where in the standard it allows for $ to be part of an
>> identifier?
>>
>> I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.
>
> In the future you might risk that people think you're a total novice,
> one who doesn't even know the basics of identifiers in C++.

Then I'll risk the same thing. Can you explain where C++17 permits $
in identifiers (or where it permits compilers to permit it)?

Earlier editions of the standard, such as C++11, permitted "other
implementation-defined characters" in identifiers. This was dropped
after Defect Report #1963 pointed out that it was supposedly redundant.

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1963

In N4700 (a more recent C++17 draft), identifiers may contain the 52
upper and lower case letters, the 10 decimal digits, underscores, and
universal-character-names. Characters not in the basic source character
set are mapped to universal-character-names in translation phase 1, so $
will (probably) be mapped to \u0024 .

But universal-character-names in identifiers are only allowed by
designate characters in certain ranges (Table 2 in 5.10 [lex.name]), and
\u0024 is not in any of those ranges.

For example, this program prints "42" when I compile and run it with
g++, but clang++ rejects it (it warns about the '$' in an identifier
and says that "foo" is undeclared on the "std::cout << ..." line).
(I used "-std=c++17 -pedantic" for both.)

#include <iostream>
int main() {
const int foo$bar = 42;
std::cout << foo\u0024bar << "\n";
}

I believe that both foo$bar and foo\u0024bar violate a diagnosable rule
and therefore require a diagnostic from any conforming compiler (which
implies that gcc is non-conforming).

It's possible that it was intended to permit (but not require) support
for $ in identifiers, but that that was overlooked in the response to
Defect Report #1963. Perhaps 0024 should be added to Table 2?

Or perhaps I'm missing something (always a real possibility).

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

David Brown

unread,
Aug 20, 2019, 2:42:14 AM8/20/19
to
On 20/08/2019 03:31, Keith Thompson wrote:
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>> On 19.08.2019 21:44, Richard wrote:
>>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> spake the secret code
>>> <qi042o$if8$1...@dont-email.me> thusly:
>>>
>>>> The $ things in the following code are macros from the specified
>>>> header-only library on GitHub.
>>>
>>> Can you tell me where in the standard it allows for $ to be part of an
>>> identifier?
>>>
>>> I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.
>>
>> In the future you might risk that people think you're a total novice,
>> one who doesn't even know the basics of identifiers in C++.
>
> Then I'll risk the same thing. Can you explain where C++17 permits $
> in identifiers (or where it permits compilers to permit it)?
>

It doesn't.

> I believe that both foo$bar and foo\u0024bar violate a diagnosable rule
> and therefore require a diagnostic from any conforming compiler (which
> implies that gcc is non-conforming).
>

You get the warning with "-Wpedantic" and an appropriate "-std" C++
standard (and perhaps an appropriate version of gcc).

> Or perhaps I'm missing something (always a real possibility).
>

What you are missing is that $ is accepted in identifiers in many
compilers, and Alf simply does not care that it is not supported in the
standards as long as it is supported in the compilers he uses.

This is not an unreasonable attitude, if you like the kind of macro
libraries he has (I don't personally, but some people do) and he is
certainly not alone in it. But I think it would be a better to be much
clearer about it being non-standard.

Future directions of C++ are seriously considering adding $ for use in
metadata (metaclasses, introspection, etc.), which may break his library
or at least cause confusion.

And there are plenty of compilers that won't accept $ as an identifier
letter (such as gcc for the AVR - a perfectly valid, if small and
limited, C++ target), and others where it can cause trouble with
assemblers which use $ as a comment symbol (68k) or in register names
(many, including ARM).

As long as Alf's code is for his own use, and he only uses the compilers
/he/ chooses, with the compiler flags /he/ chooses, then he is of course
free to use $ in his identifiers. But he should not expect others to be
as happy with it.


Keith Thompson

unread,
Aug 20, 2019, 5:18:41 AM8/20/19
to
David Brown <david...@hesbynett.no> writes:
> On 20/08/2019 03:31, Keith Thompson wrote:
>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>>> On 19.08.2019 21:44, Richard wrote:
>>>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> spake the secret code
>>>> <qi042o$if8$1...@dont-email.me> thusly:
>>>>
>>>>> The $ things in the following code are macros from the specified
>>>>> header-only library on GitHub.
>>>>
>>>> Can you tell me where in the standard it allows for $ to be part of an
>>>> identifier?
>>>>
>>>> I'm looking at 5.10 in N4659 (Draft C++17) and don't see it.
>>>
>>> In the future you might risk that people think you're a total novice,
>>> one who doesn't even know the basics of identifiers in C++.
>>
>> Then I'll risk the same thing. Can you explain where C++17 permits $
>> in identifiers (or where it permits compilers to permit it)?
>
> It doesn't.
>
>> I believe that both foo$bar and foo\u0024bar violate a diagnosable rule
>> and therefore require a diagnostic from any conforming compiler (which
>> implies that gcc is non-conforming).
>
> You get the warning with "-Wpedantic" and an appropriate "-std" C++
> standard (and perhaps an appropriate version of gcc).

Can you demonstrate that? I haven't been able to do so, with several
versions of g++ (up to and including a bleeding-edge version I built
from source a week and a half ago). Here's the test case I used:

#include <iostream>
int main() {
const int foo$bar = 42;
std::cout << foo$bar << "\n";
}

compiled with "g++ -Wpedantic -std=c++17". No warning from any version
I have on my system.

>> Or perhaps I'm missing something (always a real possibility).
>
> What you are missing is that $ is accepted in identifiers in many
> compilers, and Alf simply does not care that it is not supported in the
> standards as long as it is supported in the compilers he uses.

Please don't assume that I missed it just because I didn't discuss it.

My post was about whether the C++ standard permits compilers to
permit $ in identifiers. (I presume we can all agree that compilers
aren't *required* to accept $ in identifiers.) C++11 clearly does
permit it, since it explicitly allows "other implementation-defined
characters" in identifiers. C++17 apparently does not, since it
dropped that wording (apparently in the belief that it was redundant,
but I don't believe it was).

[...]

Ian Collins

unread,
Aug 20, 2019, 6:22:14 AM8/20/19
to
Try clang:

$ clang++ -Wpedantic -std=c++17 /tmp/x.cc
/tmp/x.cc:3:18: warning: '$' in identifier
[-Wdollar-in-identifier-extension]
const int foo$bar = 42;
^
/tmp/x.cc:4:21: warning: '$' in identifier
[-Wdollar-in-identifier-extension]
std::cout << foo$bar << "\n";
^
2 warnings generated.
$ clang++ --version
clang version 8.0.1-svn363027-1~exp1~20190611211629.77 (branches/release_80)

--
Ian.

David Brown

unread,
Aug 20, 2019, 7:00:58 AM8/20/19
to
I was playing on <https://godbolt.org>, with just:

int a$ = 1;

"--std=c++03 -Wpedantic" gives a warning (testing with gcc trunk).
--std=c++11 and --std=c++17 do not. (C++98 also warns.)

It seems to be quite specific here.

clang warns on C++11 and C++17 as well as C++03.

So you can get a warning on some choices, but not others.

>>> Or perhaps I'm missing something (always a real possibility).
>>
>> What you are missing is that $ is accepted in identifiers in many
>> compilers, and Alf simply does not care that it is not supported in the
>> standards as long as it is supported in the compilers he uses.
>
> Please don't assume that I missed it just because I didn't discuss it.

Fair enough.

>
> My post was about whether the C++ standard permits compilers to
> permit $ in identifiers. (I presume we can all agree that compilers
> aren't *required* to accept $ in identifiers.) C++11 clearly does
> permit it, since it explicitly allows "other implementation-defined
> characters" in identifiers. C++17 apparently does not, since it
> dropped that wording (apparently in the belief that it was redundant,
> but I don't believe it was).
>

I have C11 and C++14 standards conveniently at hand, and both have
"other implementation-defined character" clauses.

If C++17 does not have that, would a $ in an identifier constitute
undefined behaviour (since it is not defined in the standard), and
therefore a compiler can support it, or would it constitute a syntax
error (requiring a diagnostic for conformity) ?

Frederick Gotham

unread,
Aug 20, 2019, 7:09:54 AM8/20/19
to

For the past 15 years or so, I've been using "Dependency Walker" for this on MS-Windows and it works great.

Keith Thompson

unread,
Aug 20, 2019, 5:21:19 PM8/20/19
to
Ian Collins <ian-...@hotmail.com> writes:
> On 20/08/2019 21:18, Keith Thompson wrote:
[...]
>> Can you demonstrate that? I haven't been able to do so, with several
>> versions of g++ (up to and including a bleeding-edge version I built
>> from source a week and a half ago). Here's the test case I used:
>>
>> #include <iostream>
>> int main() {
>> const int foo$bar = 42;
>> std::cout << foo$bar << "\n";
>> }
>>
>> compiled with "g++ -Wpedantic -std=c++17". No warning from any version
>> I have on my system.
>
> Try clang:
>
> $ clang++ -Wpedantic -std=c++17 /tmp/x.cc
> /tmp/x.cc:3:18: warning: '$' in identifier
> [-Wdollar-in-identifier-extension]
> const int foo$bar = 42;
> ^
> /tmp/x.cc:4:21: warning: '$' in identifier
> [-Wdollar-in-identifier-extension]
> std::cout << foo$bar << "\n";
> ^
> 2 warnings generated.
> $ clang++ --version
> clang version 8.0.1-svn363027-1~exp1~20190611211629.77 (branches/release_80)

Yes, I had already tried clang. It allows '$' in identifiers, but warns
about them in conforming mode, which agrees with my interpretation of
what the C++17 standard requires.

Keith Thompson

unread,
Aug 20, 2019, 5:59:54 PM8/20/19
to
All editions of the C++ standard allow universal-character-names in
identifiers, and all restrict them to ranges listed in a table (the
table does not include the code for '$').

C++11 (and apparently C++14) add the "other implementation-defined
characters" wording, which means that a compiler *may* permit '$' in
identifiers (and needn't warn about it). C++17 dropped it according to
the drafts I have.

As far as I can tell, no version of g++ warns about '$' in an identifier
with "-Wpedantic -std=c++17". My reading of the C++17 standard is that
such a warning is required, making g++ non-conforming.

It appears that gcc warns about '$' in identifiers with -std=c++98 and
-std=c++03, and does not warn with -std=c++11 or higher. It looks like
the gcc maintainers responded to the addition of "other
implementation-defined character" in C++11, but did not respond to its
removal in C++17.

clang supports '$' in identifiers as an extension, but always warns
about them with "-std=c++... -Wpedantic", which is conforming behavior
for all versions of the standard.

[...]

> I have C11 and C++14 standards conveniently at hand, and both have
> "other implementation-defined character" clauses.
>
> If C++17 does not have that, would a $ in an identifier constitute
> undefined behaviour (since it is not defined in the standard), and
> therefore a compiler can support it, or would it constitute a syntax
> error (requiring a diagnostic for conformity) ?

It would be a violation of a *diagnosable rule*, requiring at least a
warning. I don't think it's a syntax error, but there's no required
distinction between syntax errors and other kinds of diagnosable errors.

The rule it violates is in N4700 5.10 [lex.name] paragraph 1:

Each universal-character-name in an identifier shall designate a
character whose encoding in ISO 10646 falls into one of the ranges
specified in Table 2.

('$' is not in Table 2.) That wording in the C standard would imply
that the behavior is undefined (or that it's a "constraint violation",
if it's in an explicitly marked constraint) but C++ [intro.compliance]
says:

The set of diagnosable rules consists of all syntactic and
semantic rules in this document except for those rules containing
an explicit notation that “no diagnostic is required” or
which are described as resulting in “undefined behavior”.

The effect is the same: a diagnostic is required. (If the
implementation chooses to produce an executable after printing the
required diagnostic, I suppose the behavior is undefined by omission.)

Chris M. Thomasson

unread,
Aug 20, 2019, 8:25:03 PM8/20/19
to
On 8/20/2019 4:09 AM, Frederick Gotham wrote:
>
> For the past 15 years or so, I've been using "Dependency Walker" for this on MS-Windows and it works great.
>

Big time. Iirc, it was bundled up with Visual Studio a long time ago.

David Brown

unread,
Aug 21, 2019, 4:29:44 AM8/21/19
to
I wonder if the change in C++17 was with a view to future uses of $ for
other purposes in C++ (such as for metaclasses)? Has the status here
changed in C++20 ?
Thanks for filling out the details here.

Alf P. Steinbach

unread,
Aug 21, 2019, 5:14:25 AM8/21/19
to
Herb was thinking about that, at least as a for-the-moment temporary
scheme allowing exploration, but as mentioned he dropped it because at
least one company had $-based simple preprocessing.


>> It would be a violation of a *diagnosable rule*, requiring at least a
>> warning. I don't think it's a syntax error, but there's no required
>> distinction between syntax errors and other kinds of diagnosable errors.
>>
>> The rule it violates is in N4700 5.10 [lex.name] paragraph 1:
>>
>> Each universal-character-name in an identifier shall designate a
>> character whose encoding in ISO 10646 falls into one of the ranges
>> specified in Table 2.
>>
>> ('$' is not in Table 2.) That wording in the C standard would imply
>> that the behavior is undefined (or that it's a "constraint violation",
>> if it's in an explicitly marked constraint) but C++ [intro.compliance]
>> says:
>>
>> The set of diagnosable rules consists of all syntactic and
>> semantic rules in this document except for those rules containing
>> an explicit notation that “no diagnostic is required” or
>> which are described as resulting in “undefined behavior”.
>>
>> The effect is the same: a diagnostic is required. (If the
>> implementation chooses to produce an executable after printing the
>> required diagnostic, I suppose the behavior is undefined by omission.)

There's no need to print anything. /Not/ blinking the caps lock
indicator for a millisecond is a valid diagnostic. The standard doesn't
specify what a "diagnostic" or a "diagnostic message" is, that it should
involve text at all, or that it should be context-independent...

That may sound like a silly argument.

But it's exactly the same kind of argument as the quoted text that it
responds to: a literal formal interpretation of text that was meant to
be read with some common sense engaged. To the degree that that quoted
text is a valid argument, this caps lock non-blink argument is valid.

Of course, both are silly.

It doesn't make sense to assume that kind of absolute formal rigor in
the standard, and taking the standard's words literally proves that that
leads to totally absurd consequences.


> Thanks for filling out the details here.


Cheers!,

- Alf

Keith Thompson

unread,
Aug 21, 2019, 5:42:15 AM8/21/19
to
David Brown <david...@hesbynett.no> writes:
> On 20/08/2019 23:59, Keith Thompson wrote:
[...]
> I wonder if the change in C++17 was with a view to future uses of $ for
> other purposes in C++ (such as for metaclasses)? Has the status here
> changed in C++20 ?

I doubt it. The DR that led to the "other implementation-defined
characters" wording being dropped
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1963
doesn't specifically mention the '$' character. (It could apply equally
to '`' and '@', the other two printable ASCII characters that are
outside the basic source character set). It was removed because it was
thought that it wasn't needed.

As for C++20, there's a git repo for the C++ standard at
https://github.com/cplusplus/draft
The "other implementation-defined characters" wording was dropped in
commit fcde0c485c4, 2015-05-03, file source/lex.tex . There are no
changes to the syntax of "identifier" after that.

[...]

Keith Thompson

unread,
Aug 21, 2019, 5:56:08 AM8/21/19
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
> On 21.08.2019 10:29, David Brown wrote:
>> On 20/08/2019 23:59, Keith Thompson wrote:
[...]
>>> The effect is the same: a diagnostic is required. (If the
>>> implementation chooses to produce an executable after printing the
>>> required diagnostic, I suppose the behavior is undefined by omission.)
>
> There's no need to print anything. /Not/ blinking the caps lock
> indicator for a millisecond is a valid diagnostic. The standard doesn't
> specify what a "diagnostic" or a "diagnostic message" is, that it should
> involve text at all, or that it should be context-independent...
>
> That may sound like a silly argument.

Yes, it does.

The standard requires a diagnostic message for certain errors, and
defines a "diagnostic message" as "a message belonging to an
implementation-defined subset of the implementation’s output messages".
The phrase "implementation-defined" means the documentation has to
document it.

gcc's documentation, for example, says:

* 'How a diagnostic is identified (C90 3.7, C99 and C11 3.10, C90,
C99 and C11 5.1.1.3).'

Diagnostics consist of all the output sent to stderr by GCC.

That's for C, but the "C++ Implementation-Defined Behavior" says "Some
choices are documented in the corresponding document for the C
language."

So no, for gcc/g++ not blinking the caps lock is not a diagnostic.

> But it's exactly the same kind of argument as the quoted text that it
> responds to: a literal formal interpretation of text that was meant to
> be read with some common sense engaged. To the degree that that quoted
> text is a valid argument, this caps lock non-blink argument is valid.
>
> Of course, both are silly.
>
> It doesn't make sense to assume that kind of absolute formal rigor in
> the standard, and taking the standard's words literally proves that that
> leads to totally absurd consequences.

I prefer to assume that *the standard means what it says* whenever
possible.

In this particular case, I think that the wording of the current
standard, though it's unambiguous, has an unintended consequence.

Alf P. Steinbach

unread,
Aug 21, 2019, 6:30:30 AM8/21/19
to
I'm sorry, that's a simple fallacy.

That g++ doesn't do that now, has no bearing on what it /can/ do.

As far as the formal is concerned g++ can use the non-blinking caps lock
as a diagnostic.


>> But it's exactly the same kind of argument as the quoted text that it
>> responds to: a literal formal interpretation of text that was meant to
>> be read with some common sense engaged. To the degree that that quoted
>> text is a valid argument, this caps lock non-blink argument is valid.
>>
>> Of course, both are silly.
>>
>> It doesn't make sense to assume that kind of absolute formal rigor in
>> the standard, and taking the standard's words literally proves that that
>> leads to totally absurd consequences.
>
> I prefer to assume that *the standard means what it says* whenever
> possible.
>
> In this particular case, I think that the wording of the current
> standard, though it's unambiguous, has an unintended consequence.

Maybe.

For example, I remember `$` being used in the system API in the HP3000.
That's long ago, 1980s, but presumably use of `$` in system API function
names was part of the reasons why compilers supported it. And continue
to support it.

Also, Richard Smith's DR that you linked to (thank you) simply neglects
to consider the matter, and is worded as if he were unaware.

* * *

I think this one is just as ill-conceived as his UTF-8 character literal
limited to ASCII. My impression is that since C++14 there is a stronger
slant towards really marginal benefit for compiler writers, while
ignoring the far more significant negative consequences for practical
programming, education and knowledge sharing. But it's nothing I can
prove, I have no statistics.


Cheers!,

- Alf

David Brown

unread,
Aug 21, 2019, 8:22:35 AM8/21/19
to
On 21/08/2019 12:30, Alf P. Steinbach wrote:
> On 21.08.2019 11:55, Keith Thompson wrote:

>> In this particular case, I think that the wording of the current
>> standard, though it's unambiguous, has an unintended consequence.
>
> Maybe.
>
> For example, I remember `$` being used in the system API in the HP3000.
> That's long ago, 1980s, but presumably use of `$` in system API function
> names was part of the reasons why compilers supported it. And continue
> to support it.
>

It is not at all unreasonable for compiler implementations to support $
in identifiers in system functions or other "internal" uses, without it
being usable for other cases. A compiler could view it as part of its
reserved namespace, like __identifiers. But once they do that, it's
usually easier to allow it in ordinary code than add extra checking to
detect and diagnose it.

I've seen many assemblers that use $ for different reasons - to indicate
local labels, for register names, for hexadecimal numbers, for comments.
It's awkward for compilers to accept $ identifiers when working with
such lower-level tools - it means some sort of name mangling.

Keith Thompson

unread,
Aug 21, 2019, 3:41:35 PM8/21/19
to
No, that's what the documentation says.

> That g++ doesn't do that now, has no bearing on what it /can/ do.

How is that relevant?

The language standard requires each implementation to document what a
"diagnostic" is. The gcc/g++ documentation clearly documents what a
"diagnostic" is, in a way that clearly excludes "non-blinking caps
lock".

A future version could change that, but I'd be willing to bet that it
won't.

By accepting identifiers with "$" without a diagnostic in what is
intended to be a conforming mode, g++ is violating the requirements of
the C++ standard. If you disagree, what exactly is your argument?

> As far as the formal is concerned g++ can use the non-blinking caps lock
> as a diagnostic.

The "formal" what?

Yes, the standard permits an implementation to use a non-blinking caps
lock as a diagnostic -- if and only if its documentation defines
"diagnostic" in a way that's consistent with that. No implementation
does so or is likely to do so in the future.

I thought your argument was based on "common sense".

Here's an idea. I'll just assume that, at some point in the future, you
might change your argument and agree with me. Problem solved.

[...]

> For example, I remember `$` being used in the system API in the HP3000.
> That's long ago, 1980s, but presumably use of `$` in system API function
> names was part of the reasons why compilers supported it. And continue
> to support it.

OpenVMS uses $ in identifiers (and C and C++ compilers for OpenVMS have
to allow for that). Which is why, in my opinion, the standard *should*
allow compilers to accept $ in identifiers.

[...]

Alf P. Steinbach

unread,
Aug 21, 2019, 9:38:29 PM8/21/19
to
The above responds to what was a coherent /reductio ad absurdum/
argument, now lost in refocusing on and possibly misinterpreting one of
the shattered pieces of it.

As pointed out by you up-thread it's not the case that accepting the `$`
requires a diagnostic in all versions of the standard. g++ is simply not
fully up to date regarding C++17 in this respect. But then few
compilers, if any, are standard-conforming by default: one needs to
cajole them into conformance by applying the relevant set of options.


>> As far as the formal is concerned g++ can use the non-blinking caps lock
>> as a diagnostic.
>
> The "formal" what?
>
> Yes, the standard permits an implementation to use a non-blinking caps
> lock as a diagnostic -- if and only if its documentation defines
> "diagnostic" in a way that's consistent with that. No implementation
> does so or is likely to do so in the future.
>
> I thought your argument was based on "common sense".

Yep.


> Here's an idea. I'll just assume that, at some point in the future, you
> might change your argument and agree with me. Problem solved.
>
> [...]
>
>> For example, I remember `$` being used in the system API in the HP3000.
>> That's long ago, 1980s, but presumably use of `$` in system API function
>> names was part of the reasons why compilers supported it. And continue
>> to support it.
>
> OpenVMS uses $ in identifiers (and C and C++ compilers for OpenVMS have
> to allow for that). Which is why, in my opinion, the standard *should*
> allow compilers to accept $ in identifiers.
>
> [...]

Yes, I should have written MPE/IV, the OS we used on the HP3000. Sorry.

It's possible that all this is tied to the attempt to remove `$` in
ASCII, as I recall instigated by Russia or France, a political thing. I
mean, tied by the baffling decision to not include `$` in the C++ basic
execution character set.

For the new ASCII that I don't remember the name of, we got the (hark)
universal currency symbol `¤` as a replacement for `$`. Nobody uses
that. It's meaningless except as a political statement, but it's there
on my keyboard, taking up one key combination.


Cheers!,

- Alf

Keith Thompson

unread,
Aug 21, 2019, 10:24:52 PM8/21/19
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
> On 21.08.2019 21:41, Keith Thompson wrote:
[...]
>> By accepting identifiers with "$" without a diagnostic in what is
>> intended to be a conforming mode, g++ is violating the requirements of
>> the C++ standard. If you disagree, what exactly is your argument?
>
> The above responds to what was a coherent /reductio ad absurdum/
> argument, now lost in refocusing on and possibly misinterpreting one of
> the shattered pieces of it.

I still can't make any sense of what you've written so far in this
thread. Perhaps I'll stop trying.

> As pointed out by you up-thread it's not the case that accepting the `$`
> requires a diagnostic in all versions of the standard. g++ is simply not
> fully up to date regarding C++17 in this respect. But then few
> compilers, if any, are standard-conforming by default: one needs to
> cajole them into conformance by applying the relevant set of options.

As I said, I did apply the relevant set of options.

C++17 does not permit '$' in identifiers, and requires a diagnostic
for any program that attempts to use a '$' in an identifier.
Earlier editions of the standard do permit implementations to support
'$' in identifiers. gcc's lack of a diagnostic in conforming mode
"gcc -std=c++17 -Wpedantic" makes it non-conforming. If you agree
with that, I don't know what we're arguing about. If you don't,
I have yet to see an explanation.

I've also suggested that the committee probably did not intend to
make a significant change in this area.

[...]

> It's possible that all this is tied to the attempt to remove `$` in
> ASCII, as I recall instigated by Russia or France, a political thing. I
> mean, tied by the baffling decision to not include `$` in the C++ basic
> execution character set.

I've never heard of any attempt to remove '$' from ASCII, which I
believe has not changed since 1967. Do you have a citation for that?

'$' is not in the source or execution basic character set, a decision
that was made a long time ago. Apparently '$' is not supported in
all versions of EBCDIC, or at least doesn't have a consistent code
(see the Wikipedia article). And there are no tokens in C or C++
that required $ (or @ or `, the only three printable ASCII characters
not in the C or C++ basic character set).

> For the new ASCII that I don't remember the name of, we got the (hark)
> universal currency symbol `¤` as a replacement for `$`. Nobody uses
> that. It's meaningless except as a political statement, but it's there
> on my keyboard, taking up one key combination.

There is no "new ASCII". ASCII is a 7-bit character set. '¤' is part
of Unicode (and Latin-1). Unicode calls it "CURRENCY SIGN". It's not a
replacement for '$' (DOLLAR SIGN), which still exists in ASCII, Latin-1,
and Unicode. (DOLLAR SIGN is 0x24. CURRENCY SIGN is 0xA4.) If there's
a political issue, it's not one that interests me unless it's relevant
to C++.

James Kuyper

unread,
Aug 21, 2019, 11:21:32 PM8/21/19
to
On 8/21/19 10:24 PM, Keith Thompson wrote:
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
...
>> It's possible that all this is tied to the attempt to remove `$` in
>> ASCII, as I recall instigated by Russia or France, a political thing. I
>> mean, tied by the baffling decision to not include `$` in the C++ basic
>> execution character set.
>
> I've never heard of any attempt to remove '$' from ASCII, which I
> believe has not changed since 1967. Do you have a citation for that?
>
> '$' is not in the source or execution basic character set, a decision
> that was made a long time ago.

To be more precise, that decision predates the C++ standard, which
inherited it from the C standard. It had already been made by the time
C89 was approved. K&R did not allow '$' in identifiers, and didn't use
it anywhere in the C grammar, but didn't say anything about whether an
implementation was required to accept such characters if they appeared
in header names, comments, character constants, or string literals. The
decision to not include $ in either the source or execution basic
character sets was presumably made at the same time that it was decided
that the standard should specify those sets.

Alf P. Steinbach

unread,
Aug 22, 2019, 12:01:49 AM8/22/19
to
On 22.08.2019 04:24, Keith Thompson wrote:
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>> On 21.08.2019 21:41, Keith Thompson wrote:
>
> [...]
>
>> It's possible that all this is tied to the attempt to remove `$` in
>> ASCII, as I recall instigated by Russia or France, a political thing. I
>> mean, tied by the baffling decision to not include `$` in the C++ basic
>> execution character set.
>
> I've never heard of any attempt to remove '$' from ASCII, which I
> believe has not changed since 1967. Do you have a citation for that?

Wikipedia's article on `¤` mentions that the replacement was formally
proposed by Italy.

It cites an article on the web, written by an unknown *nix administrator
in the 1990s, but with easily checkable facts:

<url: http://czyborra.com/charsets/iso646.html>
[quote]
ASCII and its national variants were declared international standard ISO
646 in 1972. Back then, the socialist countries managed to substitute
the international currency sign ¤ for ASCII's capitalist dollar sign $
in the the first international reference version ISO-646-IRV but this
was revised in 1991 and now ISO-646-IRV is a synonym for ISO-646-US or
US-ASCII as it is used in the core Internet protocols.
[/quote]

I guess this is where I remembered Russia from.

Or some other source discussing the same history. It was all political.

The 1991 6th edition of that standard confirms in its annex C the above
claim that the new ASCII, ISO-646 (note: the codes of Unicode are
ISO-10646), "was revised" back to its former `$`-glory:

[quote]
3) In the G0 set of the IRV the character DOLLAR SIGN replaces the
character CURRENCY SIGN in position 2/4.
Otherwise this G0 set is unchanged.
[quote]


> '$' is not in the source or execution basic character set, a decision
> that was made a long time ago. Apparently '$' is not supported in
> all versions of EBCDIC, or at least doesn't have a consistent code
> (see the Wikipedia article). And there are no tokens in C or C++
> that required $ (or @ or `, the only three printable ASCII characters
> not in the C or C++ basic character set).
>
>> For the new ASCII that I don't remember the name of, we got the (hark)
>> universal currency symbol `¤` as a replacement for `$`. Nobody uses
>> that. It's meaningless except as a political statement, but it's there
>> on my keyboard, taking up one key combination.
>
> There is no "new ASCII".

I'm sorry, that's just wrong, although that statement is literally true
by using the word "is" instead of "never was".


> ASCII is a 7-bit character set. '¤' is part
> of Unicode (and Latin-1). Unicode calls it "CURRENCY SIGN". It's not a
> replacement for '$' (DOLLAR SIGN), which still exists in ASCII, Latin-1,
> and Unicode. (DOLLAR SIGN is 0x24. CURRENCY SIGN is 0xA4.)

Yes, it's back in place. Since 1991. Apparently the international
currency sign idiocy was adopted in 1972, but even Wikipedia contradicts
itself on this matter, so I'm not 100% sure when it started.


> If there's
> a political issue, it's not one that interests me unless it's relevant
> to C++.

I think it's quite possibly relevant to the original decision to not
include `$`.

A mistaken political correctness stance where `$` was seen as just too
Western-ish, as a kind of discrimination.


Cheers!,

- Alf

James Kuyper

unread,
Aug 22, 2019, 12:26:50 AM8/22/19
to
On 8/22/19 12:01 AM, Alf P. Steinbach wrote:
> On 22.08.2019 04:24, Keith Thompson wrote:
>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
...
>>> For the new ASCII that I don't remember the name of, we got the (hark)
>>> universal currency symbol `¤` as a replacement for `$`. Nobody uses
>>> that. It's meaningless except as a political statement, but it's there
>>> on my keyboard, taking up one key combination.
>>
>> There is no "new ASCII".
>
> I'm sorry, that's just wrong, although that statement is literally true
> by using the word "is" instead of "never was".

ASCII was first standardized as ASA X3.4-1963, and was revised in 1965,
1967, 1968, 1977, and 6 different versions came out in 1986
<https://en.wikipedia.org/wiki/ASCII#History>. So you're right - there
has been a "new ASCII" - a total of 10 of them, in fact. However, that
was all a long time ago, and every one of those versions included $.
What you're referring to is an early version of ISO/IEC 646, which was
based on ASCII and was ASCII's successor, but is not, itself, ASCII.

Alf P. Steinbach

unread,
Aug 22, 2019, 1:54:31 AM8/22/19
to
On 22.08.2019 06:26, James Kuyper wrote:
> On 8/22/19 12:01 AM, Alf P. Steinbach wrote:
>> On 22.08.2019 04:24, Keith Thompson wrote:
>>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
> ...
>>>> For the new ASCII that I don't remember the name of, we got the (hark)
>>>> universal currency symbol `¤` as a replacement for `$`. Nobody uses
>>>> that. It's meaningless except as a political statement, but it's there
>>>> on my keyboard, taking up one key combination.
>>>
>>> There is no "new ASCII".
>>
>> I'm sorry, that's just wrong, although that statement is literally true
>> by using the word "is" instead of "never was".
>
> ASCII was first standardized as ASA X3.4-1963, and was revised in 1965,
> 1967, 1968, 1977, and 6 different versions came out in 1986
> <https://en.wikipedia.org/wiki/ASCII#History>. So you're right - there
> has been a "new ASCII" - a total of 10 of them, in fact.

You're talking about the US national variant of ISO-646.

That's a meaningless interpretation of what I wrote.

What the fuck could I have meant when I wrote "the new ASCII that I
don't remember the name of"? Could it be that I didn't remember the name
ASCII that I mentioned in that very sentence? Yes, that must surely have
been what I meant.

But wait, that's already clarified up-thread, in the parts you snipped:
it was ISO 646, the international, ISO version of ASCII.

Removing significant context and introducing one's own apparent context
instead, is not like debate or clarification.

That's instead a common trolling technique.


> However, that
> was all a long time ago, and every one of those versions included $.

Yes, and as you well know that's irrelevant to anything in this thread.

Perhaps there were reasons that caused you to not see as relevant the
stuff that you snipped, but a debate or clarification can't be your goal
because you can't be unaware of the facts: you're presenting some.

The stuff that you snipped included reference to ISO 646, the
international version of ASCII, which from (apparently) 1972 to
(verified) 1991 had the `$` replaced with an unusable international
currency symbol `¤`.


> What you're referring to is an early version of ISO/IEC 646, which was
> based on ASCII and was ASCII's successor, but is not, itself, ASCII.

Yes, and again, as you well know that's irrelevant to anything.

Not sure if I should plink you, you're not usually trolling this way,

- Alf

James Kuyper

unread,
Aug 22, 2019, 9:08:40 AM8/22/19
to
On 8/22/19 1:54 AM, Alf P. Steinbach wrote:
> On 22.08.2019 06:26, James Kuyper wrote:
>> On 8/22/19 12:01 AM, Alf P. Steinbach wrote:
>>> On 22.08.2019 04:24, Keith Thompson wrote:
>>>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>> ...
>>>>> For the new ASCII that I don't remember the name of, we got the (hark)
>>>>> universal currency symbol `¤` as a replacement for `$`. Nobody uses
>>>>> that. It's meaningless except as a political statement, but it's there
>>>>> on my keyboard, taking up one key combination.
>>>>
>>>> There is no "new ASCII".
>>>
>>> I'm sorry, that's just wrong, although that statement is literally true
>>> by using the word "is" instead of "never was".
>>
>> ASCII was first standardized as ASA X3.4-1963, and was revised in 1965,
>> 1967, 1968, 1977, and 6 different versions came out in 1986
>> <https://en.wikipedia.org/wiki/ASCII#History>. So you're right - there
>> has been a "new ASCII" - a total of 10 of them, in fact.
>
> You're talking about the US national variant of ISO-646.

No, ASCII and ISO-646 have been developed cooperatively, and there is a
US national variant of ISO-646 that is identical in content to one of
the versions of ASCII, but that doesn't make ASCII a national variant of
ISO-646.

> That's a meaningless interpretation of what I wrote.
>
> What the fuck could I have meant when I wrote "the new ASCII that I
> don't remember the name of"? Could it be that I didn't remember the name
> ASCII that I mentioned in that very sentence?

No, each version of ASCII had it's own name, such as
ASA X3/4-1963 and ANSI-INCITS 4-1986. It was quite clear, since you
describe it as having replaced the dollar sign with the currency symbol,
that the only thing you could have been referring to was ISO 646 IRV.
However, given your usual sloppiness of thought, I assumed that you
actually meant what you said - that you were under the impression that
ISO 646 IRV was the name of a "... new [version of] ASCII ..." but that
you couldn't remember the name of that particular version.

I'm glad to hear that this was only sloppy wording on your part, and
that you're actually aware that it's a different standard, issued by an
international standards organization, rather than a merely national one.

Scott Lurndal

unread,
Aug 22, 2019, 9:17:14 AM8/22/19
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>On 21.08.2019 21:41, Keith Thompson wrote:
>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

>>> For example, I remember `$` being used in the system API in the HP3000.
>>> That's long ago, 1980s, but presumably use of `$` in system API function
>>> names was part of the reasons why compilers supported it. And continue
>>> to support it.
>>
>> OpenVMS uses $ in identifiers (and C and C++ compilers for OpenVMS have
>> to allow for that). Which is why, in my opinion, the standard *should*
>> allow compilers to accept $ in identifiers.
>>
>> [...]
>
>Yes, I should have written MPE/IV, the OS we used on the HP3000. Sorry.

Which HP3000 language allowed '$' in identifiers? On most HP3000
compilers the $ was used in column 1 to introduce compiler control
commands, for example in SPL/3000:

$TITLE "SON OF OVERLORD (SOO)"
$CONTROL USLINIT,NOWARN,MAP,CODE
$CONTROL SEGMENT=SOO
BEGIN ...

SPL did allow apostrophes in identifiers:

INTEGER PRIORITY, XDS'SUB, MAXPCB', MODE;

The engineers that designed the HP3000 were mostly ex-burroughs
engineers, which is where the use of $ as a compiler control
originated.

>
>It's possible that all this is tied to the attempt to remove `$` in
>ASCII, as I recall instigated by Russia or France, a political thing.

C'est what?

> I
>mean, tied by the baffling decision to not include `$` in the C++ basic
>execution character set.

Maybe because the '$' symbol was often substited with a national
symbol (e.g. the british pound symbol); it wasn't a fixed glyph
worldwide.

David Brown

unread,
Aug 22, 2019, 10:07:20 AM8/22/19
to
It was the # symbol that was replaced by £ in the GB version of ISO-646,
and on British keyboards. The $ sign remained. (Also ~ was replaced by
an overbar ‾, but I've no idea why.)

The $ symbol was kept in most, but not all, ISO-646 character sets. It
was more common to replace characters like # { } [ ] | and ~ , all of
which are still there in C (but have trigraphs).

On a related topic, what is the rationale behind the choice of
characters allowed in universal character identifiers? There seems to
be a vague attempt to allow "letters" but not "symbols". Surely
allowing symbols like ¤ £ and § would be ideal for the kind of thing Alf
has in his library - characters that would not conflict with anything
else, stand out clearly, and can by typed easily on many keyboard
layouts (even with Windows).

Perhaps € would be a good choice - it is in the list of allowed Unicode
identifier characters.



Alf P. Steinbach

unread,
Aug 22, 2019, 1:37:58 PM8/22/19
to
"It's" is spelled "its".

That's pretty sloppy spelling from you.


> [snip]
> However, given your usual sloppiness of thought,

You don't say.


> I assumed that you
> actually meant what you said - that you were under the impression that
> ISO 646 IRV was the name of a "... new [version of] ASCII ..." but that
> you couldn't remember the name of that particular version.

That explanation does not address the precision of snipping all mention
of ISO 646 in the text your replied to, which appeared to be designed to
mislead.

Not addressing your snipping of significant context is a sloppiness of
deception, an art that you don't quite master.


> I'm glad to hear that this was only sloppy wording on your part,

And that's associative, like an associative mind. It's true that the
wording was intentionally imprecise. It communicated exactly what I
meant to say, notwithstanding your unconvincing attempt to put it in a
different context, remove all mention of what it meant, and so on.


> and
> that you're actually aware that it's a different standard, issued by an
> international standards organization, rather than a merely national one.

You didn't learn that now.

You snipped those parts of the quoted text, remember.

To do that snipping you had to recognize what it was about, which you
now pretend to have understood, which means you are now conveying an
incorrect impression that you /know/ is incorrect, which there is a word
for.


Cheers!,

- Alf
0 new messages