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-zA-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

ipslerrhisterr 使用同一套级别含义:

plev 含义 默认行为
1 note 打印信息,不停止。
2 warning 打印警告,不停止。
3 fatal 打印 fatal 信息;ipslerrlact_mode=.TRUE. 时停止,histerr 总是停止。

ipslerr 调用语义

位置:54-90 行。

ipslerr(plev, pcname, pstr1, pstr2, pstr3) 会:

  1. 如果 plev 在 1 到 3 之间,更新 ilv_curilv_max
  2. 向 logical unit n_l 写一行消息头,包含 note/warning/fatal 文本和调用例程名。
  3. 写三行解释字符串。
  4. 如果 plev==3lact_mode=.TRUE.,执行 STOP 'Fatal error from IOIPSL. See stdout for more details'

ioipsl_getincom.F90ipslerr(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, ...)

直接后果:

Mars 复现排查

现象 先查 解释
向量 key 读取结果和逗号写法有关 nocommacmpblank fallback 会把逗号变空格,并压缩连续空白。
logical key 大小写不同但都生效 strlowercase ASCII 大写会先转小写,再做 tru/y/fal/n 判断。
配置文件缺失但程序继续 ipslerr(2,...) warning 不停止,后续 key 可能落回默认值。
类型错误或内存扩容失败后停止 ipslerr(3,...) 默认 lact_mode=.TRUE.,fatal 会 STOP
错误信息不在 stdout ipslnlf 调用方可能改过输出 logical unit。

待确认

相关页面