commit e1761573bf82cf198032e67021265bfc0a7c8320
parent 4fdb68a0804e6734cfb891a91909b85bcbecee49
Author: Frédéric Wang <fred.wang@free.fr>
Date: Fri, 22 Feb 2013 18:58:16 +0100
Translation of messages from jax/input/TeX/jax.js
Diffstat:
2 files changed, 255 insertions(+), 57 deletions(-)
diff --git a/unpacked/MathJax.js b/unpacked/MathJax.js
@@ -2646,6 +2646,100 @@ MathJax.Localization = {
}
},
+ Tex: {
+ isLoaded: true,
+ strings: {
+ ExtraCloseMissingOpen:
+ "Accolade fermante non attendue ou accolade ouvrante manquante",
+ MissingLeftExtraRight:
+ "Commande \\left manquante or ou commande \\right non attendue",
+ MissingScript:
+ "Argument en exposant ou en indice manquant",
+ ExtraLeftMissingRight:
+ "Commande \\left inattendue or ou commande \\right manquante",
+ Misplaced: "Mauvaise position pour la commande %1",
+ MissingOpenForScript:
+ "Accolade ouvrante manquante pour le script %1",
+ AmbiguousUseOf:
+ "Usage ambigu de la commande %1",
+ EnvBadEnd:
+ "\\begin{%1} s'est terminé par un \\end{%2}",
+ EnvMissingEnd:
+ "\\end{%1} manquant",
+ MissingBoxFor:
+ "Boite manquante pour la commande %1",
+ MissingCloseBrace:
+ "Accolade fermante manquante",
+ UndefinedControlSequence:
+ "Commande %1 non définie",
+ DoubleExponent:
+ "Double exposant: utilisez des accolades pour clarifier",
+ DoubleSubscripts:
+ "Double indice: utilisez des accolades pour clarifier",
+ DoubleExponentPrime:
+ "Un prime entraine un double exposant: utilisez"+
+ "des accolades pour clarifier",
+ CanUseHash:
+ "Vous ne pouvez pas utilisez le caractère #, indiquant un "+
+ "paramètre de macro, dans le mode mathématique",
+ MisplacedMiddle:
+ "La commande %1 doit être placée à l'intérieur d'une section"+
+ "\\left ... \right"
+ MisplacedLimits:
+ "La commande %1 n'est autorisée que sur les opérateurs",
+ MisplacedMoveRoot:
+ "La commande %1 n'est autorisée qu'à l'intérieur d'une racine",
+ MultipleMoveRoot:
+ "Commande %1 redondante",
+ MoveRootArg:
+ "L'argument de la commande %1 doit être un entier",
+ NotMathMLToken:
+ "L'élément %1 n'est pas un élément MathML élémentaire",
+ InvalidMathMLAttr:
+ "Attribut MathML non valide: %1",
+ UnknownAttrForElement:
+ "Attribut %1 inconnu pour l'élément %2",
+ MaxMacroSub1:
+ "Le nombre maximal de substitution de macro autorisé par MathJax a été dépassé. Il y a t'il un appel de macro récursif?",
+ MaxMacroSub2:
+ "Le nombre maximal de substitution de macro autorisé par MathJax a été dépassé. Il y a t'il un environnement LaTeX récursif?",
+ MissingArgFor:
+ "Argument manquant pour la commande %1",
+ ExtraAlignTab:
+ "Tabulation d'alignement non attendu pour le texte de la commande"+
+ "\\cases",
+ BracketMustBeDimension:
+ "L'argument entre crochets de la commande %1 doit être une"+
+ "dimension",
+ InvalidEnv:
+ "Nom d'environnement '%1' non valide",
+ UnknownEnv:
+ "Environnement '%1' inconnu",
+ ExtraClose:
+ "Accolade fermante non attendue",
+ ExtraCloseInBrackets:
+ "Accolade fermante non attendue avant le crochet fermant.",
+ MissingCloseBracket:
+ "Impossible de trouver le crochet fermant pour l'argument de la "+
+ "commande %1",
+ MissingOrUnrecognizedDelim:
+ "Délimiteur manquant ou non reconnu pour la commande %1",
+ MissingDimOrUnits:
+ "Dimension ou unité manquante pour la commande %1",
+ ExtraCloseBraceInUpTo:
+ "Accolade fermante non attendue avant la commande %1",
+ TokenNotFoundForCommand:
+ "Impossible de trouver la commande %1 pour la commande %2",
+ MathNotTerminated:
+ "Expression mathématique non terminée à l'intérieur de cette boite"+
+ " de texte",
+ IllegalMacroParam:
+ "Paramètre de référence de macro non autorisé",
+ MaxBufferSize:
+ "Taille maximale du tampon interne de MathJax dépassée. Il y a t'il un appel de macro récursif?"
+ }
+ },
+
MathML: {
isLoaded: true,
strings: {
diff --git a/unpacked/jax/input/TeX/jax.js b/unpacked/jax/input/TeX/jax.js
@@ -28,6 +28,11 @@
(function (TEX,HUB,AJAX) {
var MML, NBSP = "\u00A0";
+ var _ = function (id) {
+ return MathJax.Localization._.apply(MathJax.Localization,
+ [ ["TeX", id] ].concat([].slice.call(arguments,1)))
+ };
+
var STACK = MathJax.Object.Subclass({
Init: function (env,inner) {
this.global = {isInner: inner};
@@ -74,9 +79,14 @@
var STACKITEM = STACK.Item = MathJax.Object.Subclass({
type: "base",
- // Localization: should be updated when the language is changed
- closeError: _("closeError", "Extra close brace or missing open brace"),
- rightError: _("rightError", "Missing \\left or extra \\right"),
+ // Localization: should be updated when the language is changed
+ // This is used in TEX.Error(this[item.type+"Error"]) below, perhaps a if
+ // could just be used directly, or make the messageID contains close/right
+ // Add a note about the \\ syntax.
+ closeError: _("ExtraCloseMissingOpen",
+ "Extra close brace or missing open brace"),
+ rightError: _("MissingLeftExtraRight",
+ "Missing \\left or extra \\right"),
Init: function () {
if (this.isOpen) {this.env = {}}
this.data = [];
@@ -93,7 +103,7 @@
if (item.type === "over" && this.isOpen) {item.num = this.mmlData(false); this.data = []}
if (item.type === "cell" && this.isOpen) {
if (item.linebreak) {return false}
- TEX.Error("Misplaced "+item.name);
+ TEX.Error(_("Misplaced %1", "Misplaced ", item.name));
}
if (item.isClose && this[item.type+"Error"]) {TEX.Error(this[item.type+"Error"])}
if (!item.isNotStack) {return true}
@@ -124,7 +134,9 @@
STACKITEM.open = STACKITEM.Subclass({
type: "open", isOpen: true,
- stopError: "Extra open brace or missing close brace",
+ // Localization: should be updated when the language is changed
+ stopError: _("ExtraOpenMissingClose",
+ "Extra open brace or missing close brace"),
checkItem: function (item) {
if (item.type === "close") {
var mml = this.mmlData(); // this.mmlData(true,true); // force row
@@ -150,7 +162,9 @@
STACKITEM.subsup = STACKITEM.Subclass({
type: "subsup",
- stopError: "Missing superscript or subscript argument",
+ // Localization: should be updated when the language is changed
+ stopError: _("MissingScript",
+ "Missing superscript or subscript argument"),
checkItem: function (item) {
var script = ["","subscript","superscript"][this.position];
if (item.type === "open" || item.type === "left") {return true}
@@ -162,8 +176,10 @@
this.data[0].SetData(this.position,item.data[0]);
return STACKITEM.mml(this.data[0]);
}
- if (this.SUPER(arguments).checkItem.call(this,item))
- {TEX.Error("Missing open brace for "+script)}
+ if (this.SUPER(arguments).checkItem.call(this,item)) {
+ TEX.Error(_("MissingOpenForScript",
+ "Missing open brace for %1", script))
+ }
},
Pop: function () {}
});
@@ -171,7 +187,9 @@
STACKITEM.over = STACKITEM.Subclass({
type: "over", isClose: true, name: "\\over",
checkItem: function (item,stack) {
- if (item.type === "over") {TEX.Error("Ambiguous use of "+item.name)}
+ if (item.type === "over") {
+ TEX.Error(_("AmbiguousUseOf", "Ambiguous use of %1", item.name))
+ }
if (item.isClose) {
var mml = MML.mfrac(this.num,this.mmlData(false));
if (this.thickness != null) {mml.linethickness = this.thickness}
@@ -189,7 +207,9 @@
STACKITEM.left = STACKITEM.Subclass({
type: "left", isOpen: true, delim: '(',
- stopError: "Extra \\left or missing \\right",
+ // Localization: should be updated when the language is changed
+ // Add a note about the \\ syntax.
+ stopError: _("ExtraLeftMissingRight", "Extra \\left or missing \\right"),
checkItem: function (item) {
if (item.type === "right") {
var mml = MML.mfenced(this.data.length === 1 ? this.data[0] : MML.mrow.apply(MML,this.data));
@@ -207,12 +227,17 @@
type: "begin", isOpen: true,
checkItem: function (item) {
if (item.type === "end") {
- if (item.name !== this.name)
- {TEX.Error("\\begin{"+this.name+"} ended with \\end{"+item.name+"}")}
+ if (item.name !== this.name) {
+ TEX.Error(_("EnvBadEnd",
+ "\\begin{%1} ended with \\end{%2}",
+ this.name, item.name))
+ }
if (!this.end) {return STACKITEM.mml(this.mmlData())}
return this.parse[this.end].call(this.parse,this,this.data);
}
- if (item.type === "stop") {TEX.Error("Missing \\end{"+this.name+"}")}
+ if (item.type === "stop") {
+ TEX.Error(_("EnvMissingEnd", "Missing \\end{%1}", this.name))
+ }
return this.SUPER(arguments).checkItem.call(this,item);
}
});
@@ -233,7 +258,9 @@
STACKITEM.position = STACKITEM.Subclass({
type: "position",
checkItem: function (item) {
- if (item.isClose) {TEX.Error("Missing box for "+this.name)}
+ if (item.isClose) {
+ TEX.Error(_("MissingBoxFor", "Missing box for %1"))
+ }
if (item.isNotStack) {
var mml = item.mmlData();
switch (this.move) {
@@ -275,7 +302,7 @@
mml = STACKITEM.mml(mml);
if (this.requireClose) {
if (item.type === 'close') {return mml}
- TEX.Error("Missing close brace");
+ TEX.Error(_("MissingCloseBrace", "Missing close brace"));
}
return [mml,item];
}
@@ -1119,7 +1146,8 @@
// (overridden in noUndefined extension)
//
csUndefined: function (name) {
- TEX.Error("Undefined control sequence "+name);
+ TEX.Error(_("UndefinedControlSequence",
+ "Undefined control sequence %1", name));
},
/*
@@ -1164,7 +1192,10 @@
else {base = this.stack.Prev(); if (!base) {base = MML.mi("")}}
if (base.isEmbellishedWrapper) {base = base.data[0].data[0]}
if (base.type === "msubsup") {
- if (base.data[base.sup]) {TEX.Error("Double exponent: use braces to clarify")}
+ if (base.data[base.sup]) {
+ TEX.Error(_("DoubleExponent",
+ "Double exponent: use braces to clarify"))
+ }
position = base.sup;
} else if (base.movesupsub) {
if (base.type !== "munderover" || base.data[base.over]) {
@@ -1186,7 +1217,10 @@
else {base = this.stack.Prev(); if (!base) {base = MML.mi("")}}
if (base.isEmbellishedWrapper) {base = base.data[0].data[0]}
if (base.type === "msubsup") {
- if (base.data[base.sub]) {TEX.Error("Double subscripts: use braces to clarify")}
+ if (base.data[base.sub]) {
+ TEX.Error(_("DoubleSubscripts",
+ "Double subscripts: use braces to clarify"))
+ }
position = base.sub;
} else if (base.movesupsub) {
if (base.type !== "munderover" || base.data[base.under]) {
@@ -1203,8 +1237,10 @@
PRIME: "\u2032", SMARTQUOTE: "\u2019",
Prime: function (c) {
var base = this.stack.Prev(); if (!base) {base = MML.mi()}
- if (base.type === "msubsup" && base.data[base.sup])
- {TEX.Error("Prime causes double exponent: use braces to clarify")}
+ if (base.type === "msubsup" && base.data[base.sup]) {
+ TEX.Error(_("DoubleExponentPrime",
+ "Prime causes double exponent: use braces to clarify"))
+ }
var sup = ""; this.i--;
do {sup += this.PRIME; this.i++, c = this.GetNext()}
while (c === "'" || c === this.SMARTQUOTE);
@@ -1231,7 +1267,8 @@
* Handle hash marks outside of definitions
*/
Hash: function (c) {
- TEX.Error("You can't use 'macro parameter character #' in math mode");
+ TEX.Error(_("CanUseHash",
+ "You can't use 'macro parameter character #' in math mode"));
},
/*
@@ -1284,7 +1321,9 @@
Middle: function (name) {
var delim = this.GetDelimiter(name);
- if (this.stack.Top().type !== "left") {TEX.Error(name+" must be within \\left and \\right")}
+ if (this.stack.Top().type !== "left") {
+ TEX.Error(_("MisplacedMiddle",
+ "%1 must be within \\left and \\right", name)}
this.Push(MML.mo(delim).With({stretchy:true}));
},
@@ -1307,7 +1346,10 @@
},
Limits: function (name,limits) {
var op = this.stack.Prev("nopop");
- if (!op || op.texClass !== MML.TEXCLASS.OP) {TEX.Error(name+" is allowed only on operators")}
+ if (!op || op.texClass !== MML.TEXCLASS.OP) {
+ TEX.Error(_("MisplacedLimits",
+ "%1 is allowed only on operators", name))
+ }
op.movesupsub = (limits ? true : false);
op.movablelimits = false;
},
@@ -1356,10 +1398,18 @@
return n;
},
MoveRoot: function (name,id) {
- if (!this.stack.env.inRoot) TEX.Error(name+" can appear only within a root");
- if (this.stack.global[id]) TEX.Error("Multiple use of "+name);
+ if (!this.stack.env.inRoot) {
+ TEX.Error(_("BadMoveRoot", "%1 can appear only within a root"));
+ }
+ if (this.stack.global[id]) {
+ TEX.Error(_("MultipleMoveRoot",
+ "Multiple use of %1", name));
+ }
var n = this.GetArgument(name);
- if (!n.match(/-?[0-9]+/)) TEX.Error("The argument to "+name+" must be an integer");
+ if (!n.match(/-?[0-9]+/)) {
+ TEX.Error(_("MoveRootArg",
+ "The argument to %1 must be an integer", name));
+ }
n = (n/15)+"em";
if (n.substr(0,1) !== "-") {n = "+"+n}
this.stack.global[id] = n;
@@ -1414,12 +1464,21 @@
attr = this.GetBrackets(name,"").replace(/^\s+/,""),
data = this.GetArgument(name),
def = {attrNames:[]}, match;
- if (!MML[type] || !MML[type].prototype.isToken) {TEX.Error(type+" is not a token element")}
+ if (!MML[type] || !MML[type].prototype.isToken) {
+ TEX.Error(_("NotMathMLToken", "%1 is not a token element", type))
+ }
while (attr !== "") {
match = attr.match(/^([a-z]+)\s*=\s*('[^']*'|"[^"]*"|[^ ]*)\s*/i);
- if (!match) {TEX.Error("Invalid MathML attribute: "+attr)}
- if (!MML[type].prototype.defaults[match[1]] && !this.MmlTokenAllow[match[1]])
- {TEX.Error(match[1]+" is not a recognized attribute for "+type)}
+ if (!match) {
+ TEX.Error("InvalidMathMLAttr",
+ "Invalid MathML attribute: %1", attr)
+ }
+ if (!MML[type].prototype.defaults[match[1]] &&
+ !this.MmlTokenAllow[match[1]]) {
+ TEX.Error(_("UnknownAttrForElement",
+ "%1 is not a recognized attribute for %2",
+ match[1], type))
+ }
def[match[1]] = match[2].replace(/^(['"])(.*)\1$/,"$2");
def.attrNames.push(match[1]);
attr = attr.substr(match[0].length);
@@ -1565,12 +1624,17 @@
}
this.string = this.AddArgs(macro,this.string.slice(this.i));
this.i = 0;
- if (++this.macroCount > TEX.config.MAXMACROS)
- {TEX.Error("MathJax maximum macro substitution count exceeded; is there a recursive macro call?")}
+ if (++this.macroCount > TEX.config.MAXMACROS) {
+ TEX.Error(_("MaxMacroSub",
+ "MathJax maximum macro substitution count exceeded; is there a recursive macro call?"))
+ }
},
Matrix: function (name,open,close,align,spacing,vspacing,style,cases) {
- var c = this.GetNext(); if (c === "") {TEX.Error("Missing argument for "+name)}
+ var c = this.GetNext();
+ if (c === "") {
+ TEX.Error(_("MissingArgFor", "Missing argument for %1", name))
+ }
if (c === "{") {this.i++} else {this.string = c+"}"+this.string.slice(this.i+1); this.i = 0}
var array = STACKITEM.array().With({
requireClose: true,
@@ -1595,8 +1659,10 @@
var c = string.charAt(i);
if (c === "{") {braces++; i++}
else if (c === "}") {if (braces === 0) {m = 0} else {braces--; i++}}
- else if (c === "&" && braces === 0) {TEX.Error("Extra alignment tab in \\cases text")}
- else if (c === "\\") {
+ else if (c === "&" && braces === 0) {
+ TEX.Error(_("ExtraAlignTab",
+ "Extra alignment tab in \\cases text"))
+ } else if (c === "\\") {
if (string.substr(i).match(/^((\\cr)[^a-zA-Z]|\\\\)/)) {m = 0} else {i += 2}
} else {i++}
}
@@ -1616,8 +1682,11 @@
var n;
if (this.string.charAt(this.i) === "[") {
n = this.GetBrackets(name,"").replace(/ /g,"");
- if (n && !n.match(/^((-?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|mm|cm|in|pc))$/))
- {TEX.Error("Bracket argument to "+name+" must be a dimension")}
+ if (n &&
+ !n.match(/^((-?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|mm|cm|in|pc))$/)) {
+ TEX.Error(_("BracketMustBeDimension",
+ "Bracket argument to %1 must be a dimension", name))
+ }
}
this.Push(STACKITEM.cell().With({isCR: true, name: name, linebreak: true}));
var top = this.stack.Top();
@@ -1656,7 +1725,9 @@
HLine: function (name,style) {
if (style == null) {style = "solid"}
var top = this.stack.Top();
- if (!top.isa(STACKITEM.array) || top.data.length) {TEX.Error("Misplaced "+name)}
+ if (!top.isa(STACKITEM.array) || top.data.length) {
+ TEX.Error(_("Misplaced", "Misplaced %1", name))
+ }
if (top.table.length == 0) {
top.frame.push("top");
} else {
@@ -1674,10 +1745,19 @@
Begin: function (name) {
var env = this.GetArgument(name);
- if (env.match(/[^a-z*]/i)) {TEX.Error('Invalid environment name "'+env+'"')}
- var cmd = this.envFindName(env); if (!cmd) {TEX.Error('Unknown environment "'+env+'"')}
- if (++this.macroCount > TEX.config.MAXMACROS)
- {TEX.Error("MathJax maximum substitution count exceeded; is there a recursive latex environment?")}
+ if (env.match(/[^a-z*]/i)) {
+ TEX.Error(_("InvalidEnv",
+ "Invalid environment name '%1'", env))
+ }
+ var cmd = this.envFindName(env);
+ if (!cmd) {
+ TEX.Error(_("UnknownEnv",
+ "Unknown environment '%1'", env))
+ }
+ if (++this.macroCount > TEX.config.MAXMACROS) {
+ TEX.Error(_("MaxMacroSub2",
+ "MathJax maximum substitution count exceeded; is there a recursive latex environment?"))
+ }
if (!(cmd instanceof Array)) {cmd = [cmd]}
var mml = STACKITEM.begin().With({name: env, end: cmd[1], parse:this});
if (cmd[0] && this[cmd[0]]) {mml = this[cmd[0]].apply(this,[mml].concat(cmd.slice(2)))}
@@ -1787,10 +1867,15 @@
GetArgument: function (name,noneOK) {
switch (this.GetNext()) {
case "":
- if (!noneOK) {TEX.Error("Missing argument for "+name)}
+ if (!noneOK) {
+ TEX.Error(_("MissingArgFor", "Missing argument for %1", name))
+ }
return null;
case '}':
- if (!noneOK) {TEX.Error("Extra close brace or missing open brace")}
+ if (!noneOK) {
+ TEX.Error(_("ExtraCloseMissingOpen",
+ "Extra close brace or missing open brace"))
+ }
return null;
case '\\':
this.i++; return "\\"+this.GetCS();
@@ -1801,12 +1886,14 @@
case '\\': this.i++; break;
case '{': parens++; break;
case '}':
- if (parens == 0) {TEX.Error("Extra close brace")}
+ if (parens == 0) {
+ TEX.Error(_("ExtraClose", "Extra close brace"))
+ }
if (--parens == 0) {return this.string.slice(j,this.i-1)}
break;
}
}
- TEX.Error("Missing close brace");
+ TEX.Error(_("MissingCloseBrace", "Missing close brace"));
break;
}
return this.string.charAt(this.i++);
@@ -1823,14 +1910,19 @@
case '{': parens++; break;
case '\\': this.i++; break;
case '}':
- if (parens-- <= 0) {TEX.Error("Extra close brace while looking for ']'")}
+ if (parens-- <= 0) {
+ TEX.Error(_("ExtraCloseInBrackets",
+ "Extra close brace while looking for ']'"))
+ }
break;
case ']':
if (parens == 0) {return this.string.slice(j,this.i-1)}
break;
}
}
- TEX.Error("Couldn't find closing ']' for argument to "+name);
+ TEX.Error(
+ _("MissingCloseBracket",
+ "Couldn't find closing ']' for argument to %1", name));
},
/*
@@ -1843,7 +1935,8 @@
this.i++; if (c == "\\") {c += this.GetCS(name)}
if (TEXDEF.delimiter[c] != null) {return this.convertDelimiter(c)}
}
- TEX.Error("Missing or unrecognized delimiter for "+name);
+ TEX.Error(_("MissingOrUnrecognizedDelim",
+ "Missing or unrecognized delimiter for %1", name));
},
/*
@@ -1864,7 +1957,8 @@
return match[1].replace(/ /g,"");
}
}
- TEX.Error("Missing dimension or its units for "+name);
+ TEX.Error(_("MissingDimOrUnits",
+ "Missing dimension or its units for %1", name));
},
/*
@@ -1879,13 +1973,17 @@
case '\\': c += this.GetCS(); break;
case '{': parens++; break;
case '}':
- if (parens == 0) {TEX.Error("Extra close brace while looking for "+token)}
+ if (parens == 0) {
+ TEX.Error(_("ExtraCloseBraceInUpTo",
+ "Extra close brace while looking for %1", token))
+ }
parens--;
break;
}
if (parens == 0 && c == token) {return this.string.slice(j,k)}
}
- TEX.Error("Couldn't find "+token+" for "+name);
+ TEX.Error(_("TokenNotFoundForCommand",
+ "Couldn't find %1 for %2", token, name));
},
/*
@@ -1934,7 +2032,9 @@
}
}
}
- if (match !== '') {TEX.Error("Math not terminated in text box")}
+ if (match !== '') {
+ TEX.Error(_("MathNotTerminated", "Math not terminated in text box"))
+ }
if (k < text.length) {mml.push(this.InternalText(text.slice(k),def))}
return mml;
},
@@ -1954,8 +2054,10 @@
else if (c === '#') {
c = string.charAt(i++);
if (c === '#') {text += c} else {
- if (!c.match(/[1-9]/) || c > args.length)
- {TEX.Error("Illegal macro parameter reference")}
+ if (!c.match(/[1-9]/) || c > args.length) {
+ TEX.Error(_("IllegalMacroParam",
+ "Illegal macro parameter reference"))
+ }
newstring = this.AddArgs(this.AddArgs(newstring,text),args[c-1]);
text = '';
}
@@ -1970,8 +2072,10 @@
*/
AddArgs: function (s1,s2) {
if (s2.match(/^[a-z]/i) && s1.match(/(^|[^\\])(\\\\)*\\[a-z]+$/i)) {s1 += ' '}
- if (s1.length + s2.length > TEX.config.MAXBUFFER)
- {TEX.Error("MathJax internal buffer size exceeded; is there a recursive macro call?")}
+ if (s1.length + s2.length > TEX.config.MAXBUFFER) {
+ TEX.Error(_("MaxBufferSize",
+ "MathJax internal buffer size exceeded; is there a recursive macro call?"))
+ }
return s1+s2;
}