Amazon Best VPN GoSearch

OnWorks 网站图标

gpp - 云端在线

通过 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器在 OnWorks 免费托管服务提供商中运行 gpp

这是命令 gpp,可以使用我们的多个免费在线工作站之一在 OnWorks 免费托管服务提供商中运行,例如 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器

程序:

您的姓名


GPP - 通用预处理器

概要


gpp [-{o|O} 输出文件] [-一世/包括/路径] [-D名称=值 ...]
[-z|+z] [-x] [-m] [-C|-T|-H|-X|-P|-U ... [-M ...]]
[-n|+n] [+c str1 str2] [+s str1 str2 c]
[-C str1] [--nostdinc] [--nocurinc]
[--curdirinclast] [--警告级别 n]
[--包含标记 STR] [ - 包括 文件]
[入档]

gpp --帮助

gpp --版本

商品描述


GPP 是一个通用的预处理器,具有可定制的语法,适用于广泛的
预处理任务。 它独立于任何编程语言,使其更加
比 cpp 更通用,而它的语法比 m4 更轻巧,更灵活。

GPP 的目标是所有常见的预处理任务,其中 cpp 不适合并且没有
需要非常复杂的功能。 为了能够同样有效地处理
多种语言的文本文件或源代码,GPP使用的语法完全
可定制。 注释和字符串的处理特别先进。

最初,GPP 只理解一组最小的内置宏,称为 元宏.
这些元宏允许定义 用户 以及一些基本的操作
形成预处理系统的核心,包括条件测试、算术
评估、通配符匹配(通配)和语法规范。 所有用户宏
定义是全球性的—— ,它们在明确删除之前一直有效; 元宏
无法重新定义。 对于每个用户宏定义,GPP 会跟踪相应的
语法规范,以便可以安全地调用宏,而不管任何后续
操作模式的改变。

除了宏之外,GPP 还理解注释和字符串,它们的语法和行为可以
广泛定制以适应任何特定目的。 内部注释和字符串是
相同的构造,因此适用于注释的所有内容也适用于字符串。

配置


GPP 识别以下命令行开关和选项。 请注意,-nostdinc,
2.1 版中的 -nocurinc、-curdirinclast、-warninglevel 和 -includemarker 选项以及
较早的已被弃用,不应使用。 改用“长选项”变体
(--nostdinc, 等等).

-h - 帮帮我
打印简短的帮助消息。

- 版
打印版本信息。

-o 输出文件
指定所有输出都应发送到的文件(默认情况下,所有内容都发送到
到标准输出)。

-O 输出文件
指定所有输出都应发送到的文件; 输出同时发送到
标准输出。

-I/包括/路径
指定路径 的#include 元宏将查找包含文件,如果它们
不在当前目录中。 默认是 / usr / include 如果没有 -I
选项被指定。 可以指定多个 -I 选项以查看多个
目录。

-D名称=值
定义用户宏 姓名 等于 VAL. 这严格等同于使用
这些因素包括原料奶的可用性以及达到必要粉末质量水平所需的工艺。 #定义 元宏,但可以从命令定义宏 -
线。 如果 VAL 引用参数或其他宏,它应该符合
在命令行上指定的模式的语法。 从 2.1 版开始,
命令行上允许宏参数命名。 语法如下:
-D(参数1,...)=定义. 参数以 C 风格的语法指定,
没有任何空格,但定义仍应符合
在命令行上指定的模式。

+z 将文本模式设置为 Unix 模式(LF 终止符)。 输入中的任何 CR 字符都是
系统地丢弃。 这是 Unix 系统下的默认设置。

-z 将文本模式设置为 DOS 模式(CR-LF 终止符)。 在这种模式下,所有 CR 字符都是
从输入中删除,并且所有输出 LF 字符都转换为 CR-LF。 这个
如果 GPP 是使用 WIN_NT 选项编译的,则为默认值。

-x 启用使用 #执行 元宏。 自从 #执行 包括输出
任意shell命令行,都可能造成潜在的安全威胁,因此
除非指定此选项,否则禁用。

-m 启用自动模式切换到 cpp 兼容模式,如果
包含的文件以“.h”或“.c”结尾。 这使得包含 C 头文件成为可能
文件只做很小的修改。

-n 防止在以下情况下从输入中删除换行符或空白字符
它们作为宏调用或注释的结束出现。 默认情况下,当换行符
或空白字符形成宏的结尾或作为一部分解析的注释
宏调用或注释,因此从输出中删除。 使用 -n 选项
如果它是空格或换行符,则保留输入流中的最后一个字符。
这在 cpp 和 Prolog 模式下激活。

+n -n 的反义词。 这是除 cpp 和 Prolog 之外的所有模式的默认设置。 笔记
必须放置 +n after -C 或 -P 以产生任何效果。

-U 参数1 ... 参数9
用户定义模式。 以下九个命令行参数被视为
分别是宏开始序列,宏结束序列
参数,参数开始序列,参数分隔符,参数结束
序列,用于参数平衡的堆叠字符列表,
要取消堆栈的字符,用于引用参数的字符串
数字,最后是引号字符(如果没有空字符串应该是
假如)。 这些设置适用于用户宏和元宏,除非
-M 选项用于定义元宏的其他设置。 请参阅有关部分
更多细节的语法规范。

-M 参数1 ... 参数7
元宏的用户定义模式规范。 该选项只能使用
与 -M 一起。 以下七个命令行参数被视为
分别是宏开始序列,宏结束序列
参数,参数开始序列,参数分隔符,参数结束
序列,用于参数平衡的堆叠字符列表,以及
要取消堆叠的字符。 请参阅下面的更多细节。

(默认 模式)
默认模式是一个模糊的类似 cpp 的模式,但它不处理注释,并且
与 cpp 存在各种不兼容。 典型的元宏和用户宏
看起来像这样:

#定义xy
宏(参数,...)

这种模式相当于

-U "" "" "(" "," ")" "(" ")" "#" "\\"
-M "#" "\n" " " " " "\n" "(" ")"

-C cpp 兼容模式。 这是 GPP 行为最接近的模式
cpp的那个。 与默认模式不同,元宏扩展只发生在
行的开头,以及 C 注释和字符串被理解。 这种模式是
相当于

-n -U "" "" "(" "," ")" "(" ")" "#" ""
-M "\n#\w" "\n" " " " " "\n" "" ""
+c "/*" "*/" +c "//" "\n" +c "\\\n" ""
+s "\"" "\"" "\\" +s "'" "'" "\\"

-T 类似 TeX 的模式。 在这种模式下,典型的元宏和用户宏如下所示:

\定义{x}{y}
\宏{arg}{...}

不理解任何评论。 这种模式相当于

-U "\\" "" "{" "}{" "}" "{" "}" "#" "@"

-H 类似 HTML 的模式。 在这种模式下,典型的元宏和用户宏如下所示:

<#define x|y>
<#宏参数|...>

不理解任何评论。 这种模式相当于

-U "<#" ">" "\B" "|" ">" "<" ">" "#" "\\"

-X 类似 XHTML 的模式。 在这种模式下,典型的元宏和用户宏如下所示:

<#define x|y/>
<#宏参数|.../>

不理解任何评论。 这种模式相当于

-U "<#" "/>" "\B" "|" "/>" "<" ">" "#" "\\"

-P Prolog 兼容的类似 cpp 的模式。 此模式与cpp兼容模式不同
通过它对评论的处理,相当于

-n -U "" "" "(" "," ")" "(" ")" "#" ""
-M "\n#\w" "\n" " " " " "\n" "" ""
+ccss "\!o/*" "*/" +ccss "%" "\n" +ccii "\\\n" ""
+s "\"" "\"" "" +s "\!#'" "'" ""

+c str1 str2
指定注释。 任何未加引号的出现 str1 将被解释为
评论的开头。 直到第一次出现的所有输入 str2
被丢弃。 此选项可多次使用以指定不同类型的
注释分隔符。 可选参数 可以指定改变
评论的行为和, 例如, 把它变成一个字符串或在下面忽略它
某些情况,见下文。

-c str1
取消指定注释或字符串。 开始的注释/字符串规范
顺序是 str1 已移除。 这对于更改内置注释很有用
标准模式的规格—— 例如,cpp兼容模式。

+s str1 str2 c
指定字符串。 任何未加引号的出现 str1 将被解释为
字符串的开头。 直到第一次出现的所有输入 str2
原样输出,无需任何评估。 分隔符本身是输出。 如果 c
非空,它的第一个字符用作 字符串引用 字符 -- ,以
在紧接出现之前出现的字符 str2 阻止它
终止字符串。 可选参数 可以指定改变
字符串的行为和, 例如, 转成注释, 启用宏评估
在字符串内部,或在某些情况下忽略字符串规范
情况。 见下文。

-s str1
取消指定注释或字符串。 与 -c 相同。

- 包括 文件
流程 文件 before 入档

--nostdinc
不要在标准目录 /usr/include 中查找包含文件。

--诺库林
不要在当前目录中查找包含文件。

--curdirinclast
在当前目录中查找包含文件 after 指定的目录
-I 而不是在他们面前。

--警告级别 n
将警告级别设置为 n (0、1 或 2)。 默认值为 2(最详细)。

--包含标记 STR
不要跟丢 的#include 通过在输出流中插入标记来指示指令。 这
标记的格式由 STR,其中必须包含三个出现
人物 % (或等效地 ?)。 第一次出现被替换为该行
数字,第二个是文件名,第三个是 1、2 或空白。 当这
选项在默认、cpp 或 Prolog 模式下指定,GPP 尽力确保
通过插入空白,输出中的行号与输入中的行号相同
行代替定义或注释。

入档 指定 GPP 从中读取其输入的输入文件。 如果没有输入文件
指定,输入从标准输入读取。

句法 规格


宏调用的语法如下:它必须以字符序列开头
匹配 开始 序列 在当前模式中指定,紧随其后
通过宏的名称,它必须是一个有效的 识别码 -- , 一个字母序列,
数字或下划线(“_”)。 宏名称后必须跟一个 end
序列 如果宏没有参数,或者由一个由
论点 开始 序列. 各种参数然后由一个 论点
分离器, 宏以一个 end 序列.

在所有情况下,当前上下文的参数—— ,参数传递给
被评估的主体——可以通过使用 论点 参考 序列
后跟 1 到 9 之间的数字。或者,可以命名宏参数(请参阅
以下)。 此外,为了避免 GPP 语法和
输入文件,一个 报价 字符 提供。 引号字符可用于防止
将宏调用、注释或字符串解释为纯文本以外的任何内容。 报价单
字符“保护”下一个字符,并且在评估期间总是被移除。
两个连续的引号字符计算为一个单引号字符。

最后,为了便于正确的参数定界,某些字符可以“堆叠”
当它们出现在宏参数中时,使参数分隔符或宏结束序列
如果参数主体不平衡,则不会解析。 这允许嵌套宏调用
不使用引号。 如果需要不正确的平衡参数,请引用字符
应该在一些堆叠的字符前面添加以使其平衡。

对于元宏和对于元宏,上述宏构造序列可以不同。
用户宏:例如,在 cpp 模式下就是这种情况。 请注意,由于元宏可以
最多只有两个参数,第二个参数的分隔规则有点

一个元宏。

除非选择标准操作模式之一,否则上述语法序列可以是
在命令行上指定,分别使用 -M 和 -U 选项作为元-
宏和用户宏,或通过 #模式 目标#模式 用户 荟萃
宏调用。 在这两种情况下,模式描述都由用户的九个参数组成
宏规范,即宏开始序列、短宏结束序列、
参数开始序列、参数分隔符、长宏结束序列、字符串
列出要堆叠的字符,列出要取消堆叠的字符的字符串,参数
引用序列,最后是引号字符。 如下所述,这些序列
应使用 C 字符串的语法提供; 它们必须以非字母数字开头
字符,并且在前五个字符串中可以使用特殊匹配序列(参见
以下)。 如果引号对应的参数为空字符串,则
参数的功能被禁用。 对于元宏规范,只有七个
参数,因为参数引用序列和引号字符与
用户宏语法。

注释/字符串的结构如下:它必须以一系列
匹配给定的字符 评论/字符串 开始 序列,并且总是在第一个结束
的发生 评论/字符串 end 序列, 除非它前面是奇数
的发生 字符串引用 字符 (如果已经指定了这样的字符)。 在
在某些情况下,可以指定注释/字符串以启用内部的宏评估
评论/字符串; 在这种情况下,如果为宏定义了引号字符,则它可以是
也用于防止注释/字符串结束,不同之处在于宏
引号字符总是从输出中删除,而字符串引号字符总是
输出。 另请注意,在某些情况下,注释/字符串规范可以是
禁用,在这种情况下,注释/字符串开始序列将被简单地忽略。 最后,它
可以指定一个 绳子 警告 字符 其存在于评论/字符串中
将导致 GPP 输出警告(这对于在 cpp 中定位未终止的字符串很有用
模式)。 请注意,输入文件不允许包含未终止的注释/字符串。

可以使用以下命令从输入文件中声明注释/字符串规范 #模式
评论 元宏调用(或等效的 #模式 绳子),在这种情况下 C 的数量
作为描述注释/字符串的参数给出的字符串可以介于
二和四:前两个参数(强制)是开始序列和结束
序列,并且可以利用特殊的匹配序列(见下文)。 他们可能不会
以字母数字字符开头。 第三个参数的第一个字符,如果有
一,用作字符串引号字符(使用空字符串禁用
功能),并且使用第四个参数的第一个字符(如果有)
作为字符串警告字符。 也可以从命令行给出规范,
在这种情况下,如果使用 +c 选项必须有两个参数,如果使用 +s 则必须有三个参数
选项。

注释/字符串的行为由三个字符的修饰符字符串指定,它
可以作为可选参数传递给 +c/+s 命令行选项或传递给
#模式 评论/#模式 绳子 元宏。 如果未指定修饰符字符串,则默认
注释的值为“ccc”,字符串的值为“sss”。 第一个字符对应
元宏调用中的行为(包括用户宏定义,因为它们来自内部
a #定义 元宏调用),第二个字符对应用户内部的行为-
宏参数,第三个字符对应任何宏之外的行为
称呼。 这些字符中的每一个都可以采用以下值:

i 禁用注释/字符串规范。

c 评论(既不评估也不输出)。

s 字符串(字符串及其定界符序列按原样输出)。

q 带引号的字符串(字符串按原样输出,没有分隔符序列)。

C 评估评论(评估宏,但丢弃输出)。

S 评估字符串(评估宏,输出分隔符)。

Q 评估的带引号的字符串(评估宏,不输出分隔符)。

重要说明:在另一个内部出现任何注释/字符串开始序列
注释/字符串始终被忽略,即使启用了宏评估。 换句话说,
注释/字符串不能嵌套。 特别是,`Q' 修饰符可以是一种方便的方式
定义暂时禁用所有注释和字符串规范的语法。

语法规范字符串应始终作为 C 字符串提供,无论它们是
作为参数给出 #模式 元宏调用或在 Unix shell 的命令行上。 如果
命令行参数是通过标准 Unix shell 之外的另一种方法给出的,然后
必须模拟 shell 行为—— , 周围的 "" 引号应该被删除,所有
出现的 `\\' 应该用一个反斜杠代替,类似的 `\"' 应该是
替换为 `"'。像 `\n' 这样的序列被 GPP 识别,应该保持原样。

可以使用与字符集的某些子集匹配的特殊序列。 他们是
形式`\x', 在哪里 x 是其中之一:

b 匹配任何一个或多个空格或制表符的序列(`\b' 等同于
` ')。

w 匹配零个或多个空格或制表符的任何序列。

B 匹配任何一个或多个空格、制表符或换行符的序列。

W 匹配零个或多个空格、制表符或换行符的任何序列。

a 一个字母字符(“a”到“z”,“A”到“Z”)。

A 一个字母字符,或一个空格、制表符或换行符。

# 一个数字(“0”到“9”)。

i 一个标识符字符。 匹配的字符集可以使用
#模式 字符集 id 命令。 默认设置匹配字母数字字符和
下划线(“a”到“z”,“A”到“Z”,“0”到“9”和“_”)。

t 一个制表符。

n 换行符。

o 一个操作符。 匹配的字符集可以使用
#模式 字符集 op 命令。 默认设置匹配中的所有字符
"+-*/\^<>=`~:.?@#&!%|",除了在 Prolog 模式中,其中 `!'、`%' 和 `|' 不是
匹配。

O 运算符字符或括号字符。 附加匹配的集合
与 `\o' 相比的字符可以使用 #模式 字符集 平价
命令。 默认设置是将“()[]{}”中的字符作为括号。

此外,除了“\w”和“\W”之外的所有这些匹配子集都可以通过插入一个
'! —— , 写成`\!x' 而不是 '\x'.

注意一个重要的显着特征 开始 序列: 当 a 的第一个字符
宏或注释/字符串开始序列是 ' ' 或上述特殊序列之一,它是
不被视为序列本身的一部分,而是用作上下文检查:对于
例如,以 '\n' 开头的开始序列仅匹配行首,但
匹配的换行符不被视为序列的一部分。 同样的开始
以 ' ' 开头的序列仅在存在某些空格时才匹配,但匹配
空格不被认为是开始序列的一部分,因此被发送到
输出。 如果在文件的开头执行上下文检查(或更一般地说
任何要评估的正文),结果与匹配换行符相同
(这使得 cpp 模式文件可以从元宏调用开始)。

2.1 版本中添加了两个特殊的语法规则。 首先,参数引用(#n) 不是
当它们在宏调用和定义之外时,评估时间更长。 然而,他们是
不再允许出现在对 a 的调用中(除非受引号字符保护)
定义的用户宏; 当前的行为(向后兼容)是默默地删除它们
如果发生这种情况,请从输入中获取。

其次,如果结束序列(对于宏或注释)由单个换行符组成
字符,如果定界规则导致在最终的上下文中进行评估
换行符不存在,GPP 默默地忽略丢失的换行符而不是生成
一个错误。 主要结果是元宏调用现在可以以简单的方式嵌套
在标准、cpp 和 Prolog 模式下。

评估 规则


输入被顺序读取并根据当前模式的规则进行解释。 全部
输入文本首先与指定的注释/字符串开始序列匹配
当前模式(除了那些被 'i' 修饰符禁用的模式),除非身体被
评估是注释/字符串的内容,其修饰符启用宏评估。
首先检查最近定义的注释/字符串规范。 重要的
注意:注释不能出现在宏的名称和它的参数之间(这样做
导致未定义的行为)。

然后将任何不是注释/字符串的内容与可能的元宏调用进行匹配,
如果这也失败了,则针对可能的用户宏调用。 所有剩余的文本都经过
用相关参数文本替换参数引用序列(空,除非
被评估的主体是用户宏的定义)和引号的删除
如果有字符。

请注意,元宏参数在任何评估之前传递给元宏
(尽管元宏可能会选择评估它们,请参阅下面的元宏描述)。
在的情况下 #模式 元宏,GPP 临时增加了注释/字符串规范
启用对 C 字符串(“...”)的识别并防止在其中进行任何评估,因此没有
被放入 C 字符串参数的字符的干扰 #模式
当前的语法是令人恐惧的。

另一方面,系统地评估用户宏的参数,然后
作为上下文参数传递给宏定义体,用它来评估
环境。 唯一的例外是当宏定义为空时,在这种情况下它的
不评估参数。 注意 GPP 暂时切换回模式
定义宏是为了对其进行评估,因此更改
定义宏和调用宏之间的操作模式。
相反,如果用户宏希望使用当前模式而不是当前模式
用于定义它需要以 #模式 恢复 调用并以一个结束 #模式
保存 呼叫。

可以使用命名参数定义用户宏(请参阅 #定义 说明如下)。 在那里面
情况下,当宏定义被评估时,每个命名参数都会导致一个
要创建的临时虚拟用户宏定义; 这样的宏只能被调用
不带参数,只返回相应参数的文本。

请注意,由于宏是在调用时而不是在调用时进行计算的
定义,任何调用递归宏的尝试都会导致未定义的行为,除非在
当宏使用时非常特殊的情况 #undef 在有限多次循环后擦除自身
迭代。

最后,当用户宏的定义不涉及任何
参数(既不是命名参数也不是参数引用序列)在一个
短用户宏结束序列为空的模式(例如、cpp 或 TeX 模式)。 在那里面
假设它是一个 别号 : 它的参数首先在当前评估
mode 像往常一样,但不是作为参数传递给宏定义(其中
会导致它们被丢弃)它们实际上被附加到宏定义中,
使用定义宏的模式的语法规则,以及结果文本
再次评估。 因此,重要的是要注意,在宏别名的情况下,
参数实际上在两种可能不同的模式下被评估两次。

元宏


这些宏始终是预定义的。 它们的实际调用顺序取决于当前
模式; 这里我们使用类似 cpp 的符号。

#定义 x y
这定义了用户宏 x as y. y 可以是任何有效的 GPP 输入,并且可以用于
示例参考其他宏。 x 必须是标识符 (,一系列
字母数字字符和“_”),除非指定了命名参数。 如果 x is
已定义,则覆盖先前的定义。 如果没有第二个参数是
给定, x 将被定义为一个不输出任何内容的宏。 两者都不 x 也不 y 旨在
评估; 宏定义只在被调用时被评估,而不是在被调用时
声明。

也可以在宏定义中命名参数:在这种情况下,
论点 x 应该是一个用户宏调用,其参数都是标识符。 这些
标识符在宏定义中作为用户宏可用; 这些
虚拟宏必须不带参数调用,并计算为相应的
宏参数。

#defeval x y
这类似于 #定义, 但第二个参数 y 被评估
立即地。 由于用户宏定义每次都会被评估
调用,这意味着宏 y 将经历 连续评价。 这
的用处 #defeval 相当重要,因为它是评估某事的唯一方法
不止一次,这可能需要强制评估元的参数
通常不执行任何评估的宏。 然而,由于所有的争论
在定义时评估的引用被理解为主体的参数
宏被定义而不是作为宏本身的参数,
通常必须使用引号字符来防止立即评估
参数引用。

#undef x
这将删除用户宏的任何现有定义 x.

#ifdef x
这开始了一个条件块。 仅当
识别码 x 被定义,直到任一 的#else 或者 #ENDIF 声明达成。
但是请注意,注释文本仍会被彻底扫描,因此其语法
必须有效。 拥有 的#else or #ENDIF 声明
结束条件块仅作为用户宏扩展的结果出现
而不是明确地在输入中。

#ifndef x
这开始了一个条件块。 仅当
识别码 x 没有定义。

#ifeq x y
这开始了一个条件块。 仅当
评估结果 xy 与字符串相同。 任何
比较时忽略前导或尾随空格。 注意在 cpp 模式下
任何未加引号的空白字符都被理解为第一个参数的结尾,
所以必须小心。

#ifneq x y
这开始了一个条件块。 仅当
评估结果 xy 不相同(甚至高达前导或
尾随空格)。

的#else 这会切换当前条件块的逻辑值。 接下来是
当且仅当前面的输入被注释掉时才进行评估。

#ENDIF 这结束了一个由 a 开始的条件块 #如果... 元宏。

的#include 文件
这会导致 GPP 打开指定的文件并评估其内容,插入
当前输出中的结果文本。 所有定义的用户宏仍然可用
在包含文件中,并且包含文件中定义的所有宏都将
在接下来的所有内容中都可用。 包含文件首先在
当前目录,然后,如果未找到,则在指定的目录之一中
-I 命令行选项(或 / usr / include 如果没有指定目录)。
请注意,出于兼容性原因,可以将文件名放在
"" 或 <>。

在各个目录中搜索包含文件的顺序是
受...的影响 -nostdinc, -诺库林-curdirinclast 命令行选项。

包含文件后,GPP 会立即保存当前操作模式的副本
进入模式堆栈,并在包含的末尾恢复操作模式
文件。 包含的文件可以通过以 #模式 恢复
调用并以 a 结尾 #模式 称呼。 此外,当 -m 命令行
指定选项,GPP会自动切换到cpp兼容模式
在包含名称以“.c”或“.h”结尾的文件时。

#执行 命令
这会导致 GPP 执行指定的命令行并包含其标准
在当前输出中输出。 请注意,出于安全原因,此元宏是
禁用,除非 -x 指定了命令行标志。 如果使用 #执行 是不是
允许,打印警告消息并且输出留空。 请注意,
指定的命令行在执行之前被评估,从而允许使用
命令行中的宏。 但是,命令的输出被逐字包括在内
并且不评价。 如果您需要评估输出,则必须使用 #defeval
(见上文)导致双重评估。

#评估 表达式
- #评估 元宏尝试评估 表达式 首先通过扩展宏(正常
GPP 评估),然后通过执行算术评估和/或通配符
匹配。 算术表达式的语法和运算符优先级是
与 C 中相同; 唯一缺少的运算符是 <<、>>、?: 和赋值
运营商。

POSIX 风格的通配符匹配('globbing')仅在 POSIX 上可用
可以使用 =~ 运算符调用。 简而言之,一个“?” 火柴
任何单个字符,“*”匹配任何字符串(包括空字符串),以及
'[...]' 匹配括号中的任一字符。 '[...]' 类是
当括号中的第一个字符是 '!' 时进行补码。 中的字符
'[...]' 类也可以使用 '-' 字符指定为一个范围 -- 例如,
'[FN]' 等价于 '[FGHIJKLMN]'。

如果无法为结果分配数值,则返回的文本只是
没有任何算术评估的宏展开的结果。 唯一的
此规则的例外是比较运算符 ==、!=、<、>、<= 和 >=
其中,如果一侧不计算为数字,则执行字符串比较
相反(忽略尾随和前导空格)。 此外,该 长度(...)
算术运算符返回其计算参数的字符长度。

在算术表达式中, 定义(...) 特殊用户宏也是
可用:它只接受一个参数,不计算,如果它返回 1
是用户宏的名称,否则为 0。

#如果 表达式
此元宏以与以下相同的方式调用算术/全局求值器
#评估 并将评估结果与字符串“0”进行比较以开始一个
条件块。 特别要注意的是逻辑值 表达式 永远是真的
当它不能被评估为一个数字时。

#elif 表达式
这个元宏可以用来避免嵌套 #如果 条件。 #如果 ... #elif ...
#ENDIF 相当于 #如果 ... 的#else #如果 ... #ENDIF #ENDIF.

#模式 关键词 ...
这个元宏控制 GPP 的操作模式。 请参阅下面的列表 #模式
命令。

#线 这个元宏计算当前输入文件的行号。

#文件 这个元宏计算当前输入文件的文件名,因为它出现
在命令行或参数中 的#include. 如果 GPP 正在读取其输入
从标准输入,然后 #文件 评估为“标准输入”。

#日期 fmt
此元宏计算为由格式化的当前日期和时间
指定格式字符串 fmt. 见章节 日期 AND 时间 转换 说明符
联络一位教师

#错误 味精
这个元宏会导致一条带有当前文件名和行号的错误消息,
和文字 味精, 打印到标准错误设备。 随后的
然后中止处理。

#警告 味精
这个元宏会导致一条带有当前文件名和行号的警告消息,
和文字 味精, 打印到标准错误设备。 随后的
然后恢复处理。

GPP 灵活性的关键是 #模式 元宏。 它的第一个参数始终是
可用关键字列表(见下文); 它的第二个参数总是一个序列
由空格分隔的单词。 除了可能的第一个,这些词中的每一个
始终是定界符或语法说明符,应作为 C 字符串分隔提供
通过双引号 (" ")。 部分中列出的各种特殊匹配序列
语法规范可用。 任何 #模式 命令在“...”的模式下被解析
被理解为 C 风格的字符串,所以在这些字符串中放入任何字符都是安全的
字符串。 还要注意第一个参数 #模式 (关键字)永远不会被评估,
而第二个参数被评估(当然除了 C 字符串的内容),
以便可以作为宏评估的结果获得语法规范。

可用 #模式 命令是:

#模式 保存 / #模式
将当前模式规范推入模式堆栈。

#模式 恢复 / #模式 流行的
模式堆栈中的弹出模式规范。

#模式 姓名
选择一种标准模式。 唯一的参数必须是以下之一: default
(默认模式); cpp, C (cpp 模式); tex, TeX (tex 模式); html、HTML(html模式);
xhtml、XHTML(xhtml 模式); prolog,Prolog(序言模式)。 模式名称必须是
直接给出,而不是作为 C 字符串。

#模式 用户 “s1” ... “s9”
指定用户宏语法。 9 个参数,都是 C 字符串,是模式
用户宏规范(请参阅 -U 命令行选项和有关
语法规范)。 元宏规范不受影响。

#模式 目标 {用户 | “s1” ... “s7”}
指定元宏语法。 要么唯一的论点是 用户 (不是字符串),和
用户宏模式规范被复制到元宏模式中
规范,或者必须有七个字符串参数,其意义是
与 -M 命令行选项相同(请参阅语法规范部分)。

#模式 报价 [“C”]
没有参数或 "" 作为参数,删除引号字符规范和
禁用引用功能。 使用一个字符串参数,第一个字符
的字符串被视为新的引号字符。 引号字符可以是
既不是字母数字也不是'_',也不能是特殊匹配序列之一。

#模式 评论 [XXX] “开始” “结尾” [“C” [“C”]]
添加注释规范。 可选的第一个参数由三个
未包含在 " " 中的字符可用于指定注释/字符串修饰符
(请参阅有关语法规范的部分)。 默认修饰符是 CCC。 第一
两个字符串参数分别用作注释开始和结束序列。 这
第三个字符串参数是可选的,可用于指定字符串引用
特点。 (如果它是“”,则功能被禁用。)第四个字符串
参数是可选的,可用于指定字符串分隔警告
特点。 (如果它是“”,则该功能被禁用。)

#模式 绳子 [XXX] “开始” “结尾” [“C” [“C”]]
添加字符串规范。 相同 #模式 评论 除了默认
修饰符是 SSS.

#模式 没有意见 / #模式 字符串 [“开始”]
不带参数,删除所有注释/字符串规范。 用一根绳子
参数,删除开始序列为
论据。

#模式 保存 { on | 折扣 | 1 | 0 }
相当于 -n 命令行开关。 如果论证是 on or 1, 任何换行符
或终止宏调用或注释/字符串的空白字符留在
用于进一步处理的输入流。 如果论证是 折扣 or 0 这个功能是
禁用。

#模式 字符集 { id | op | 平价 } “细绳”
指定用于匹配 \o、\O 和 \i 特殊字符集的字符集
序列。 第一个参数必须是 id (由\i 匹配的集合), op
设置匹配 \o) 或 平价 (除了由 \O 匹配的集合外,还与
\o)。 “细绳” 是一个 C 字符串,它列出了要放入集合中的所有字符。 它可能
仅包含特殊匹配序列 \a、\A、\b、\B 和 \#(其他
序列和否定序列是不允许的)。 当发现“-”时
在两个非特殊字符之间这会添加中间的所有字符(例如“AZ”
对应于所有大写字符)。 要在匹配集中有“-”,要么
将它放在第一个或最后一个位置或将其放在 \x 序列旁边。

日期 AND 时间 转换 说明符


放置在格式字符串中的普通字符被复制到而不进行转换。
转换说明符由“%”字符引入,并被替换如下:

%a 根据当前区域设置的缩写工作日名称。

%A 根据当前区域设置的完整工作日名称。

%b 根据当前语言环境的缩写月份名称。

%B 根据当前区域设置的完整月份名称。

%c 当前语言环境的首选日期和时间表示。

%d 以十进制数表示的月份中的第几天(范围为 01 到 31)。

%F 等效于 %Y-%m-%d(ISO 8601 日期格式)。

%H 使用 24 小时制的十进制数字小时(范围 00 到 23)。

%I 使用 12 小时制的十进制数字小时(范围 01 到 12)。

%j 以十进制数表示的一年中的第几天(范围 001 到 366)。

%m 以十进制数表示的月份(范围 01 到 12)。

%M 十进制数形式的分钟(范围 00 到 59)。

%p “AM”或“PM”根据给定的时间值,或相应的
当前语言环境的字符串。 中午被视为“下午”,午夜被视为“上午”。

%R 以 24 小时制表示的时间 (%H:%M)。

%S 第二个是十进制数(范围 00 到 61)。

%U 当前年份的周数为十进制数,范围为 00 到 53,
从第一个星期日开始作为第 01 周的第一天。

%w 以十进制表示的星期几,范围为 0 到 6,星期日为 0。

%W 当前年份的周数为十进制数,范围为 00 到 53,
从第一个星期一作为第 01 周的第一天开始。

%x 当前语言环境的首选日期表示形式,不带时间。

%X 不带日期的当前语言环境的首选时间表示。

%y 没有世纪的十进制数形式的年份(范围 00 到 99)。

%Y 以十进制数表示的年份,包括世纪。

%Z 时区或名称或缩写。

%% 文字“%”字符。

根据用于编译 GPP 的 C 编译器和库,可能会有更多的转换
可用的说明符。 请查阅编译器的文档以了解 时间() 功能。
但是请注意,上面未列出的任何转换说明符可能无法跨
GPP 的安装。

示例


这是标准或 cpp 模式下的一个基本不言自明的示例:

#define FOO 这是
#define BAR 一条消息。
#define 连接 #1 #2
连接(FOO,酒吧)
#ifeq (concat(foo,bar)) (foo 栏)
这是输出。
的#else
这不是输出。
#ENDIF

使用参数命名, CONCAT 宏也可以定义为

#define concat(x,y) xy

在 TeX 模式下并使用参数命名,相同的示例变为:

\define{FOO}{这是}
\define{BAR}{一条消息。}
\定义{\concat{x}{y}}{\x \y}
\concat{\FOO}{\BAR}
\ifeq{\concat{foo}{bar}}{foo bar}
这是输出。
\别的
这不是输出。
\万一

在 HTML 模式下,没有参数命名,类似:

<#define FOO|这是>
<#define BAR|一条消息。>
<#define concat|#1 #2>
<#concat <#FOO>|<#BAR>>
<#ifeq <#concat foo|bar>|foo bar>
这是输出。
<#else>
这不是输出。
<#endif>

以下示例(在标准模式下)说明了引号字符的使用:

#define FOO 这是\
多行定义。
#define BLAH(x) 我的论点是 x
布拉赫(乌尔夫)
\BLAH(乌尔夫)

请注意,多行定义在 cpp 和 Prolog 模式下也有效,尽管
没有引号字符,因为 '\' 后跟一个换行符然后被解释为
评论并丢弃。

在 cpp 模式下,C 字符串和注释是这样理解的,如
下面的例子:

#define BLAH foo
等等等等等等 */
'这是一个 /*string*/ !'

Prolog 模式和 cpp 模式的主要区别在于字符串的处理和
注释:在 Prolog 中,一个 '...' 字符串不能紧跟在一个数字之后,一个 /*...*/
注释不能在运算符字符之后立即开始。 此外,评论是
不会从输出中删除,除非它们出现在 #command 中。

cpp模式和默认模式的区别更深:在默认模式#commands
可以从任何地方开始,而在 cpp 模式下,它们必须在一行的开头; 默认的
mode 不知道注释和字符串,但有一个引号 ('\'),而 cpp
模式具有广泛的注释/字符串规范,但没有引号字符。 此外,该
元宏的参数需要在默认模式下正确加上括号,而没有这样的
检查是在 cpp 模式下进行的。

这使得在默认模式下比在 cpp 模式下更容易嵌套元宏调用。 为了
例如,考虑以下 HTML 模式输入,它测试
#执行 命令:

<#ifeq <#exec echo blah>|blah
> #exec 允许 <#else> #exec 不允许 <#endif>

没有等效的 cpp 模式,而在默认模式下,它可以很容易地翻译为

#ifeq (#exec 回声等等
)(废话
)
\#exec 允许
的#else
\#exec 不允许
#ENDIF

为了在 cpp 模式下嵌套元宏调用,需要修改模式
描述,或者通过改变元宏调用语法,或者更优雅地定义
一个无声字符串,并使用评估开头的上下文
字符串是换行符:

#mode string QQQ "$" "$"
#ifeq $#exec 回声等等
$$等等
$
\#exec 允许
的#else
\#exec 不允许
#ENDIF

但是请注意,注释/字符串不能嵌套($...$ 中的“...”会去
未被发现),所以需要小心在这样一个安静的环境中包含什么
评估字符串。 在本例中,2.1 版中引入的松散元宏嵌套
可以使用以下更简单的版本:

#ifeq 废话 #exec echo -n 废话
\#exec 允许
的#else
\#exec 不允许
#ENDIF

请记住,没有参数的宏实际上被理解为别名时
使用参数调用,如下例所示(默认或 cpp 模式):

#define DUP(x) xx
#define FOO 我说:DUP
FOO(废话)

的用处 #defeval 元宏在 HTML 模式下由以下示例显示:

<#define APPLY|<#defeval TEMP|<\##1 \#1>><#TEMP #2>>
<#define <#foo x>|<#x> 和 <#x>>
<#APPLY foo|BLAH>

之所以 #defeval 需要的是,因为一切都在一次通过中评估,
将导致所需的宏调用的输入需要由第一个生成
在第二次评估之前评估传递给 APPLY 的参数。

要在默认模式下翻译此示例,需要使用括号
将#defeval 调用嵌套在 APPLY 的定义中,但不需要这样做
输出括号。 最简单的解决方案是

#define 平衡(x) x
#define APPLY(f,v) 平衡(#defeval TEMP f
温度(v))
#define foo(x) x 和 x
应用(\foo,BLAH)

如上所述,cpp 模式中最简单的版本依赖于定义一个无声评估
string 起到 BALANCE 宏的作用。

以下示例(默认或 cpp 模式)演示了算术计算:

#定义 x 4
答案是:
#eval x*x + 2*(16-x) + 1998%x

#如果已定义(x)&&!(3*x+5>17)
这应该是输出。
#ENDIF

最后,这里有一些涉及模式切换的示例。 下面的例子是
不言自明(以默认模式开始):

#模式推送
#define f(x) xx
#mode 标准 tex
\f{等等}
\mode{string}{"$" "$"}
\mode{comment}{"/*" "*/"}
$\f{urf}$ /* 等等 */
\define{FOO}{bar/* 等等 */}
\mode{弹出}
f($FOO$)

用户定义模式变得有用的一个很好的例子是本文档的 GPP 来源
(可通过 GPP 的源代码分发获得)。

另一个有趣的应用是选择性地强制对 C 字符串中的宏进行评估
在 cpp 模式下。 例如,考虑以下输入:

#define blah(x) “他说:x”
废话(富)

显然,人们想要参数 x 在字符串内展开。 有
解决这个问题的几种方法:

#模式推送
#mode nostring "\""
#define blah(x) “他说:x”
#mode 弹出

#mode 引用 "`"
#define blah(x) `"然后他说:x`"

#mode string QQQ "$$" "$$"
#define blah(x) $$"然后他说:x"$$

第一种方法很自然,但存在冗长和不便
中和字符串语义,以便在
字符串,或出现 '/*',不采取进一步措施是不可能的
扭曲。

第二种方法稍微更有效,因为引用的本地存在
字符可以更轻松地控制评估什么和不评估什么,但具有
缺点是有时无法找到合理的引号字符
必须显着改变源文件或将其包含在一个 #模式 推/弹出
构造。 例如,字符串中任何出现的 '/*' 都必须被引用。

最后一个方法演示了在上下文中评估字符串的效率
选择性评估:由于注释/字符串不能嵌套,任何出现的 '"' 或
'$$' 中的 '/*' 以纯文本形式输出,正如在字符串中所预期的那样,并且仅
宏评估已启用。 还要注意的是,在选择一个
字符串分隔符比在引号字符中选择。

从 2.1 版开始,元宏调用可以在默认情况下更有效地嵌套,cpp
和序言模式。 这使得制作元宏的用户版本变得容易,或者
增加一个计数器:

#定义 myeval #eval #1

#定义 x 1
#defeval x #eval x+1

⁠高级课程 示例


以下是一些使用 GPP 的高级构造示例。 他们往往很尴尬
并且应该被视为 GPP 局限性的证据。

第一个例子是一个递归宏。 主要问题是(由于 GPP 评估
一切)递归宏必须非常小心递归的方式
终止以避免未定义的行为(大多数情况下 GPP 只会崩溃)。
特别是,依靠 #if/#else/#endif 构造结束递归是不可能的
并导致无限循环,因为 GPP 即使在
条件块的未评估分支。 一个安全的方法是,例如
如下(我们以 TeX 模式为例):

\define{倒计时}{
\如果{#1}
#1 ...
\define{循环}{\倒计时}
\别的
完成。
\define{循环}{}
\万一
\循环{\评估{#1-1}}
}
\倒计时{10}

另一个例子,在 cpp 模式下:

#mode string QQQ "$" "$"
#define 三角形(x,y) y \
$#if 长度(y)
$#define iter$ $#endif
$ iter(x,*y)
三角形(20)

以下是(不幸的是非常弱)实现功能性的尝试
GPP 中的抽象(在标准模式下)。 理解这个例子以及为什么它不能被制作
留给好奇读者的练习要简单得多。

#mode 字符串 "`" "`" "\\"
#定义ASIS(x) x
#define SILENT(x) ASIS()
#define EVAL(x,f,v) 沉默(
#mode string QQQ "`" "`" "\\"
#defeval TEMP0 x
#defeval TEMP1 (
\#define \TEMP2(TEMP0) f
)
温度1
)温度 2(v)
#define LAMBDA(x,f,v) 沉默(
#ifneq (v) ()
#define TEMP3(a,b,c) EVAL(a,b,c)
的#else
#定义 TEMP3(a,b,c) \LAMBDA(a,b)
#ENDIF
)TEMP3(x,f,v)
#define EVALAMBDA(x,y) 静音(
#defeval TEMP4 x
#defeval TEMP5 是
)
#define APPLY(f,v) 沉默(
#defeval TEMP6 ASIS(\EVA)f
温度6
)EVAL(TEMP4,TEMP5,v)

这会产生以下结果:

拉姆达(z,z+z)
=> LAMBDA(z,z+z)

拉姆达(z,z+z,2)
=> 2+2

#define f LAMBDA(y,y*y)
f
=> LAMBDA(y,y*y)

应用(f,等等)
=> 废话*废话

应用(LAMBDA(t,tt),(tt))
=> (tt) (tt)

LAMBDA(x,应用(f,(x+x)),urf)
=> (urf+urf)*(urf+urf)

应用(应用(LAMBDA(x,LAMBDA(y,x*y)),foo),bar)
=> foo*bar

#define 测试 LAMBDA(y,`#ifeq y urf
y 是 urf#else
y 不是 urf#endif
`)
应用(测试,urf)
=> urf 就是 urf

应用(测试,富)
=> foo 不是 urf

使用 onworks.net 服务在线使用 gpp


免费服务器和工作站

下载 Windows 和 Linux 应用程序

Linux 命令

Ad




×
广告
❤️在这里购物、预订或购买——免费,有助于保持服务免费。