中文编程
首发于中文编程

如何使GCC支持中文(utf-8)的变量名、函数名?

目前VS 和Clang都是支持utf-8的变量名、函数名,但 GCC不支持。

有人提意见,提了好几年了:UTF-8 support for identifier names in GCC

GCC并没有解决,但官方给了一个解决方案:FAQ - GCC Wiki

就是用这样一条脚本语句转换一下源文件

perl -pe 'BEGIN { binmode STDIN, ":utf8"; } s/(.)/ord($1) < 128 ? $1 : sprintf("\\U%08x", ord($1))/ge;'

这条语句的意思是将源文件按utf-8读取出来,大于128的unicode(不在ASCII里)都用16进制的\Uxxxxxxxx的格式替代。

这种格式叫UCN。

实际上gcc内部还是将UCN转换成utf-8字符串,再加到符号表。却不支持原生的UTF-8符号,这个就有点搞笑了。

虽然有人会说,C、C++的标准里没有对UTF-8符号的支持,GCC不支持UTF-8符号是符合标准的。但是GCC从来就不是死守标准的乖宝宝对吧,加了不少扩展了。为啥这个不能扩展一下呢?

官方不加,咱可以同人一下嘛!

下面就告诉大家,怎么在GCC里加UTF-8符号的支持。

在libcpp/lex.c 里

1.加一个函数

bool is_utf8_char(cppchar_t c) {
    if (c > 0x80) return true;
    else return false;
}

2.复制一份函数lex_identifier,命名为lex_utf8_identifier

if (! starts_ucn)
{
	while (ISIDNUM (*cur))
	{
		hash = HT_HASHSTEP (hash, *cur);
		cur++;
	}
	NORMALIZE_STATE_UPDATE_IDNUM (nst, *(cur - 1));
}

中ISIDNUM 改成 is_utf8_char:

if (! starts_ucn)
{
	while (is_utf8_char (*cur))
	{
		hash = HT_HASHSTEP (hash, *cur);
		cur++;
	}
	NORMALIZE_STATE_UPDATE_IDNUM (nst, *(cur - 1));
}


3.在函数 _cpp_lex_direct 中修改 switch 的 default

	default:
		create_literal (pfile, result, buffer->cur - 1, 1, CPP_OTHER);
		break;

改为:

	default:
		if (is_utf8_char(c))
		{
			struct normalize_state nst = INITIAL_NORMALIZE_STATE;
			result->type = CPP_NAME;
			result->val.node.node = lex_utf8_identifier(pfile, buffer->cur - 1, false,
				&nst, &result->val.node.spelling);
			warn_about_normalization(pfile, result, &nst);
		}
		else
		{
			create_literal (pfile, result, buffer->cur - 1, 1, CPP_OTHER);
		}
		break;


OK!完工了。make bootstrap && make install 吧。

你就可以愉快地使用 UTF-8 变量,函数了。

成品:

github.com/swizl/gcn/bl

文章被以下专栏收录

    在所有编程语言和领域中尝试编写中文代码,开发相关工具,总结经验,一致代码风格。包括中文命名,汉化现有语言,创造中文语法的编程语言等等。作为最熟悉的母语,用来编写代码会让代码更容易被自己和母语相同的其他开发者理解。基于英文的编程语言和框架中,使用中文命名有时有技术问题。希望这里为后人趟雷,填坑。多数现有API是英文的,这里也会对其中一些常用的进行汉化。当然,这里也会对基于中文的编程语言进行探讨。包括汉化基于英文的编程语言,以及创造新的编程语言。