// Copyright 2017-2022 The MathJax Consortium // SPDX-License-Identifier: Apache-2.0 // Based on ParseUtil.addArgs and ParseUtil.substituteArgs (MathJax 3.2.2).
package tex import ( ) const maxMacroBuffer = 5120 // macroAddArgs preserves a control word at a source-splicing boundary. The // source regular expression is ASCII-only; Unicode case folding is not used. // Its size limit counts UTF-16 code units after the separator is inserted. func macroAddArgs(, string, int) (string, error) { := func( byte) bool { return >= 'a' && <= 'z' || >= 'A' && <= 'Z' } if len() != 0 && ([0]) { := len() for > 0 && ([-1]) { -- } if < len() { := for > 0 && [-1] == '\\' { -- } if (-)%2 == 1 { += " " } } } if len(utf16.Encode([]rune()))+len(utf16.Encode([]rune())) > { return "", texError("MaxBufferSize", "MathJax internal buffer size exceeded; is there a recursive macro call?") } return + , nil } // Macros and paired delimiters use ParseUtil.substituteArgs before replacing // their caller source. Environments retain their separate substitution path. func substituteMacroArguments( string, []string) (string, error) { return substituteMacroArgumentsWithLimit(, , maxMacroBuffer) } func substituteMacroArgumentsWithLimit( string, []string, int) (string, error) { var strings.Builder := "" for := 0; < len(); { := [] ++ switch { case '\\': .WriteByte() if < len() { , := utf8.DecodeRuneInString([:]) .WriteString([ : +]) += } case '#': if >= len() { return "", texError("IllegalMacroParam", "Illegal macro parameter reference") } = [] ++ if == '#' { .WriteByte() continue } if < '1' || > '9' || int(-'1') >= len() { return "", texError("IllegalMacroParam", "Illegal macro parameter reference") } var error , = macroAddArgs(, .String(), ) if != nil { return "", } , = macroAddArgs(, [-'1'], ) if != nil { return "", } .Reset() default: .WriteByte() } } return macroAddArgs(, .String(), ) }