IOIPSL 本地字符串和错误支撑
源码基线:LMDZ.COMMON-6.3\LMDZ.COMMON。 Mars 运行参与度:条件经过。Mars 编译不使用外部 IOIPSL getin、或 COMMON fallback ioipsl_getincom 被动力/物理配置读取调用时,本页两个本地 IOIPSL helper 参与 .def 文本清洗、logical 字符串识别和错误报告。若构建链接外部 IOIPSL,本页仍是接口兼容边界。
源码范围
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\misc\ioipsl_stringop.F90
LMDZ.COMMON-6.3\LMDZ.COMMON\libf\misc\ioipsl_errioipsl.F90
两个文件都是从 IOIPSL v2_1_8 抽出的本地实现。ioipsl_getincom.F90 直接使用:
USE ioipsl_errioipsl, ONLY : ipslerr
USE ioipsl_stringop, ONLY : nocomma, cmpblank, strlowercase因此,本页关注它们在 fallback getin 中实际承担的职责,而不是把 IOIPSL 通用 API 写成 Mars 主路径承诺。
模块和符号清单
| 文件 | 行数 | 模块 | 公开/可用符号 | getincom 直接调用 |
|---|---|---|---|---|
ioipsl_stringop.F90 |
243 | ioipsl_stringop |
cmpblank, cntpos, findpos, find_str, nocomma, strlowercase, struppercase, gensig, find_sig |
nocomma, cmpblank, strlowercase |
ioipsl_errioipsl.F90 |
219 | ioipsl_errioipsl |
ipslnlf, ipslerr, ipslerr_act, ipslerr_inq, histerr, ipsldbg |
ipslerr |
ioipsl_stringop 没有显式 PRIVATE,因此模块过程默认可见。ioipsl_errioipsl 显式 PRIVATE,只公开上表列出的 6 个接口。
ioipsl_stringop 逻辑
cmpblank(str):压缩连续空白
位置:21-41 行。
输入输出同一个字符串 str。例程先取 LEN_TRIM(str),然后从左到右扫描。如果发现连续两个空格,就把后半段整体左移一位,并把有效长度减 1;否则扫描位置加 1。
效果是把连续空格压成一个空格,但不主动 ADJUSTL,也不删除单个分隔空格。
在 fallback getin 中,getin_readdef 对 value 文本调用它:
raw value -> nocomma -> cmpblank -> getin_decrypt
这一步决定 a, b c 会先变成 a b c,再压成 a b c,使后续多值拆分按单空格工作。
nocomma(str):逗号转空格
位置:117-131 行。
逐字符扫描 LEN_TRIM(str) 范围,遇到 , 就替换为空格。它不理解引号和转义,只做字符替换。
Mars .def 配置里如果写 key = 1,2,3,fallback 读入后会把逗号转成空格,再由 getin_decrypt 拆成向量项。这个行为解释了为什么逗号和空格在许多 getin 向量值中等价。
strlowercase(str):ASCII 小写化
位置:133-148 行。
逐字符取得 IACHAR,只把 ASCII A-Z 转成 a-z。非 ASCII 字符、数字和符号保持原样。
ioipsl_getincom.F90 在 logical 解析处调用它:先将候选 value 小写化,再搜索 "tru"/"y" 或 "fal"/"n"。因此 TRUE, True, yes, No 等大小写形式都能被识别;但这不是完整自然语言解析,只是源码中的子串检测规则。
其他 string helper
| 符号 | 位置 | 算法 | 当前 Mars fallback getin 用途 |
|---|---|---|---|
cntpos(c_c,l_c,c_r,l_r) |
43-68 | 用 INDEX 循环统计子串出现次数。 |
当前 ioipsl_getincom.F90 未直接调用。 |
findpos(c_c,l_c,c_r,l_r) |
70-84 | INDEX 查首次位置,没找到返回 -1。 |
当前 ioipsl_getincom.F90 未直接调用。 |
find_str(str_tab,str,pos) |
86-115 | 线性扫描字符串数组,TRIM 后相等则返回位置。 |
当前 ioipsl_getincom.F90 未直接调用。 |
struppercase(str) |
150-165 | ASCII a-z 转 A-Z。 |
当前 ioipsl_getincom.F90 未直接调用。 |
gensig(str,sig) |
167-185 | 对前 30 个字符做 prime-weighted IACHAR 加权和。 |
当前 ioipsl_getincom.F90 未直接调用。 |
find_sig(...) |
187-240 | 先按签名差值筛候选,再用完整字符串长度和包含关系确认。 | 当前 ioipsl_getincom.F90 未直接调用。 |
gensig/find_sig 源码注释明确签名不是唯一值,所以命中签名后还要验证原字符串。若后续 主页面追踪旧 IOIPSL 表查找性能,可以引用这一点;当前 Mars getincom 主线不依赖它。
ioipsl_errioipsl 状态和错误级别
模块保存 4 个全局状态:
| 状态 | 初值 | 含义 |
|---|---|---|
n_l |
6 |
ipslerr 输出 logical unit,默认 stdout。 |
ilv_cur |
0 |
最近一次有效错误级别。 |
ilv_max |
0 |
自最近一次 ipslerr_act 后见过的最高错误级别。 |
ioipsl_debug |
.FALSE. |
debug 开关,供 ipsldbg 查询和设置。 |
lact_mode |
.TRUE. |
fatal 错误是否立即 STOP。 |
ipslerr 和 histerr 使用同一套级别含义:
plev |
含义 | 默认行为 |
|---|---|---|
| 1 | note | 打印信息,不停止。 |
| 2 | warning | 打印警告,不停止。 |
| 3 | fatal | 打印 fatal 信息;ipslerr 在 lact_mode=.TRUE. 时停止,histerr 总是停止。 |
ipslerr 调用语义
位置:54-90 行。
ipslerr(plev, pcname, pstr1, pstr2, pstr3) 会:
- 如果
plev在 1 到 3 之间,更新ilv_cur和ilv_max。 - 向 logical unit
n_l写一行消息头,包含 note/warning/fatal 文本和调用例程名。 - 写三行解释字符串。
- 如果
plev==3且lact_mode=.TRUE.,执行STOP 'Fatal error from IOIPSL. See stdout for more details'。
ioipsl_getincom.F90 用 ipslerr(2,...) 表示可继续的 .def 文件缺失或部分默认警告;用 ipslerr(3,...) 表示类型不匹配、读值失败、内存分配失败、未知数据类型等必须终止的错误。
其他错误接口
| 符号 | 位置 | 作用 | 复现意义 |
|---|---|---|---|
ipslnlf(new_number, old_number) |
25-52 | 查询或修改 ipslerr 输出 logical unit。 |
若调用方改过 n_l,错误信息不一定在 stdout。 |
ipslerr_act(new_mode, old_mode) |
92-124 | 查询或修改 fatal action,并重置 ilv_cur/ilv_max。 |
可让 ipslerr(3,...) 继续运行,但默认会停止。 |
ipslerr_inq(current_level, maximum_level) |
126-151 | 查询当前和最高错误级别。 | 用于错误状态汇总。 |
histerr(plev, ...) |
153-186 | 直接向 * 输出 IOIPSL history 风格错误。 |
plev==3 总是 STOP,不受 lact_mode 控制。 |
ipsldbg(new_status, old_status) |
188-216 | 查询或修改 ioipsl_debug。 |
当前 fallback getin 主线未直接使用 debug 状态。 |
fallback getin 中的实际数据流
getin_readdef reads one line
-> split key = value
-> nocomma(value)
-> cmpblank(value)
-> getin_decrypt(value)
-> typed parsing
-> on warning/fatal: ipslerr(level, routine, msg1, msg2, msg3)
logical get_fil
-> strlowercase(candidate)
-> search tru/y/fal/n
-> on malformed value: ipslerr(3, ...)
直接后果:
- 逗号和多空格在未加引号的 value 中被标准化为单空格分隔。
- logical 解析大小写不敏感,但只基于源码中的
"tru","y","fal","n"字符串搜索。 - fatal 错误默认直接停止运行,所以 Mars 配置复现时不要只看调用方默认值,还要检查错误级别和
lact_mode。 - warning 级别不会停止,缺失 include 文件可能只留下 warning,并让后续 key 使用默认值。
Mars 复现排查
| 现象 | 先查 | 解释 |
|---|---|---|
| 向量 key 读取结果和逗号写法有关 | nocomma 与 cmpblank |
fallback 会把逗号变空格,并压缩连续空白。 |
| logical key 大小写不同但都生效 | strlowercase |
ASCII 大写会先转小写,再做 tru/y/fal/n 判断。 |
| 配置文件缺失但程序继续 | ipslerr(2,...) |
warning 不停止,后续 key 可能落回默认值。 |
| 类型错误或内存扩容失败后停止 | ipslerr(3,...) |
默认 lact_mode=.TRUE.,fatal 会 STOP。 |
| 错误信息不在 stdout | ipslnlf |
调用方可能改过输出 logical unit。 |
待确认
ipslerr_act(.FALSE.)在当前 Mars 标准运行链是否有实际调用,源码搜索未发现 COMMONlibf中除定义外的调用。gensig/find_sig在 当前 COMMONlibf中除定义外未被检索到活动调用;本页按未参与 Mars fallback 主链处理。