The R Project SVN R

Rev

Rev 81060 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 81060 Rev 81095
Line 1087... Line 1087...
1087
    jump_to_top_ex(FALSE, FALSE, TRUE, TRUE, TRUE);
1087
    jump_to_top_ex(FALSE, FALSE, TRUE, TRUE, TRUE);
1088
}
1088
}
1089
 
1089
 
1090
/* #define DEBUG_GETTEXT 1 */
1090
/* #define DEBUG_GETTEXT 1 */
1091
 
1091
 
-
 
1092
#ifdef DEBUG_GETTEXT
-
 
1093
# include <Print.h>
-
 
1094
# define GETT_PRINT(...) REprintf(__VA_ARGS__)
-
 
1095
#else
-
 
1096
# define GETT_PRINT(...) do {} while(0)
-
 
1097
#endif
1092
 
1098
 
1093
/* Called from do_gettext() and do_ngettext() */
1099
/* Called from do_gettext() and do_ngettext() */
1094
static char * determine_domain_gettext(SEXP domain_)
1100
static char * determine_domain_gettext(SEXP domain_, Rboolean up)
1095
{
1101
{
1096
    const char *domain = "";
1102
    const char *domain = "";
1097
    char *buf; // will be returned
1103
    char *buf; // will be returned
1098
 
1104
 
1099
    /* If cptr->cloenv is not R_GlobalEnv,
1105
    /* If TYPEOF(cptr->callfun) == CLOSXP (not .Primitive("eval")),
1100
     * ENCLOS(cptr->cloenv) is CLOENV(cptr->callfun) */
1106
     * ENCLOS(cptr->cloenv) is CLOENV(cptr->callfun) */
1101
    /* R_findParentContext(cptr, 1)->cloenv == cptr->sysparent */
1107
    /* R_findParentContext(cptr, 1)->cloenv == cptr->sysparent */
1102
    if(isNull(domain_)) {
1108
    if(isNull(domain_)) {
1103
	RCNTXT *cptr = R_findParentContext(R_GlobalContext, 1);
1109
	RCNTXT *cptr;
1104
	SEXP rho = cptr ? CLOENV(cptr->callfun) : R_EmptyEnv;
1110
	GETT_PRINT(">> determine_domain_gettext(), first rho=%s\n", EncodeEnvironment(rho));
1105
 
1111
 
1106
	/* stop() etc have internal call to .makeMessage */
1112
	/* stop() etc have internal call to .makeMessage */
1107
	/* gettextf calls gettext */
1113
	/* gettextf calls gettext */
-
 
1114
 
1108
	if (rho == R_BaseNamespace) {
1115
	SEXP rho = R_EmptyEnv;
-
 
1116
	if(R_GlobalContext->callflag & CTXT_FUNCTION) {
-
 
1117
	    if(up) {
1109
	    SEXP call = getCurrentCall(), cfn = CAR(call);
1118
		SEXP call = R_GlobalContext->call;
-
 
1119
		/* The call is of the form
-
 
1120
		   <symbol>(<symbol>, domain = domain [possible other argument]) */
-
 
1121
		rho =
-
 
1122
		    (isSymbol(CAR(call)) && (call = CDR(call)) != R_NilValue &&
1110
	    if (TYPEOF(cfn) == SYMSXP && !streql(CHAR(PRINTNAME(cfn)), "ngettext") &&
1123
		     TAG(call) == R_NilValue && isSymbol(CAR(call)) &&
1111
		TYPEOF(CADR(call)) == SYMSXP) {
1124
		     (call = CDR(call)) != R_NilValue &&
-
 
1125
		     isSymbol(TAG(call)) && streql(CHAR(PRINTNAME(TAG(call))), "domain") &&
-
 
1126
		     isSymbol(CAR(call)) && streql(CHAR(PRINTNAME(CAR(call))), "domain") &&
1112
		cptr = R_findParentContext(cptr, 1);
1127
		     (cptr = R_findParentContext(R_GlobalContext, 1)))
-
 
1128
		    ? cptr->sysparent
1113
		rho = cptr ? CLOENV(cptr->callfun) : R_EmptyEnv;
1129
		    : R_GlobalContext->sysparent;
1114
	    }
1130
	    }
-
 
1131
	    else
-
 
1132
		rho = R_GlobalContext->sysparent;
1115
	}
1133
	}
-
 
1134
	GETT_PRINT(" .. rho1_domain_ => rho=%s\n", EncodeEnvironment(rho));
1116
 
1135
 
1117
	SEXP ns = R_NilValue;
1136
	SEXP ns = R_NilValue;
-
 
1137
	int cnt = 0;
1118
	    while(rho != R_EmptyEnv) {
1138
	    while(rho != R_EmptyEnv) {
1119
		if (rho == R_GlobalEnv) break;
1139
		if (rho == R_GlobalEnv) break;
1120
		else if (R_IsNamespaceEnv(rho)) {
1140
		else if (R_IsNamespaceEnv(rho)) {
1121
		    ns = R_NamespaceEnvSpec(rho);
1141
		    ns = R_NamespaceEnvSpec(rho);
1122
		    break;
1142
		    break;
1123
		}
1143
		}
-
 
1144
		if(++cnt <= 5 || cnt > 99) { // diagnose "inf." loop
-
 
1145
		    GETT_PRINT("  cnt=%4d, rho=%s\n", cnt, EncodeEnvironment(rho));
-
 
1146
		    if(cnt > 111) break;
-
 
1147
		}
1124
		if(rho == ENCLOS(rho)) break; // *does* happen
1148
		if(rho == ENCLOS(rho)) break; // *did* happen; now keep for safety
1125
		rho = ENCLOS(rho);
1149
		rho = ENCLOS(rho);
1126
	    }
1150
	    }
1127
	if (!isNull(ns)) {
1151
	if (!isNull(ns)) {
1128
	    PROTECT(ns);
1152
	    PROTECT(ns);
1129
	    domain = translateChar(STRING_ELT(ns, 0));
1153
	    domain = translateChar(STRING_ELT(ns, 0));
1130
	    if (strlen(domain)) {
1154
	    if (strlen(domain)) {
1131
		size_t len = strlen(domain)+3;
1155
		size_t len = strlen(domain)+3;
1132
		buf = R_alloc(len, sizeof(char));
1156
		buf = R_alloc(len, sizeof(char));
1133
		Rsnprintf_mbcs(buf, len, "R-%s", domain);
1157
		Rsnprintf_mbcs(buf, len, "R-%s", domain);
1134
		UNPROTECT(1); /* ns */
1158
		UNPROTECT(1); /* ns */
1135
#ifdef DEBUG_GETTEXT
-
 
1136
		REprintf("Managed to determine 'domain' from environment as: '%s'\n", buf);
1159
		GETT_PRINT("Managed to determine 'domain' from environment as: '%s'\n", buf);
1137
#endif
-
 
1138
		return buf;
1160
		return buf;
1139
	    }
1161
	    }
1140
	    UNPROTECT(1); /* ns */ 
1162
	    UNPROTECT(1); /* ns */
1141
	}
1163
	}
1142
	return NULL;
1164
	return NULL;
1143
 
1165
 
1144
    } else if(isString(domain_)) {
1166
    } else if(isString(domain_)) {
1145
	domain = translateChar(STRING_ELT(domain_, 0));
1167
	domain = translateChar(STRING_ELT(domain_, 0));
1146
	if (!strlen(domain))
1168
	if (!strlen(domain))
1147
	    return NULL;
1169
	    return NULL;
1148
	buf = R_alloc(strlen(domain) + 1, sizeof(char));
1170
	buf = R_alloc(strlen(domain) + 1, sizeof(char));
1149
	strcpy(buf, domain);
1171
	strcpy(buf, domain);
1150
	return buf;
1172
	return buf;
1151
	
1173
 
1152
    } else if(isLogical(domain_) && LENGTH(domain_) == 1 && LOGICAL(domain_)[0] == NA_LOGICAL)
1174
    } else if(isLogical(domain_) && LENGTH(domain_) == 1 && LOGICAL(domain_)[0] == NA_LOGICAL)
1153
	return NULL;
1175
	return NULL;
1154
    else error(_("invalid '%s' value"), "domain");
1176
    else error(_("invalid '%s' value"), "domain");
1155
}
1177
}
1156
 
1178
 
Line 1165... Line 1187...
1165
 
1187
 
1166
    if(isNull(string) || !n) return string;
1188
    if(isNull(string) || !n) return string;
1167
 
1189
 
1168
    if(!isString(string)) error(_("invalid '%s' value"), "string");
1190
    if(!isString(string)) error(_("invalid '%s' value"), "string");
1169
 
1191
 
1170
    char * domain = determine_domain_gettext(CAR(args));
1192
    char * domain = determine_domain_gettext(CAR(args), /*up*/TRUE);
1171
 
1193
 
1172
    if(domain && strlen(domain)) {
1194
    if(domain && strlen(domain)) {
1173
	SEXP ans = PROTECT(allocVector(STRSXP, n));
1195
	SEXP ans = PROTECT(allocVector(STRSXP, n));
1174
	for(int i = 0; i < n; i++) {
1196
	for(int i = 0; i < n; i++) {
1175
	    int ihead = 0, itail = 0;
1197
	    int ihead = 0, itail = 0;
Line 1203... Line 1225...
1203
		strcpy(tail, tmp+strlen(tmp)-itail);
1225
		strcpy(tail, tmp+strlen(tmp)-itail);
1204
		tmp[strlen(tmp)-itail] = '\0';
1226
		tmp[strlen(tmp)-itail] = '\0';
1205
	    }
1227
	    }
1206
 
1228
 
1207
	    if(strlen(tmp)) {
1229
	    if(strlen(tmp)) {
1208
#ifdef DEBUG_GETTEXT
-
 
1209
		REprintf("translating '%s' in domain '%s'\n", tmp, domain);
1230
		GETT_PRINT("translating '%s' in domain '%s'\n", tmp, domain);
1210
#endif
-
 
1211
		tr = dgettext(domain, tmp);
1231
		tr = dgettext(domain, tmp);
1212
 		R_CheckStack2(        strlen(tr) + ihead + itail + 1);
1232
 		R_CheckStack2(        strlen(tr) + ihead + itail + 1);
1213
		tmp = (char *) alloca(strlen(tr) + ihead + itail + 1);
1233
		tmp = (char *) alloca(strlen(tr) + ihead + itail + 1);
1214
		tmp[0] ='\0';
1234
		tmp[0] ='\0';
1215
		if(ihead > 0) strcat(tmp, head);
1235
		if(ihead > 0) strcat(tmp, head);
Line 1239... Line 1259...
1239
	error(_("'%s' must be a character string"), "msg1");
1259
	error(_("'%s' must be a character string"), "msg1");
1240
    if(!isString(msg2) || LENGTH(msg2) != 1)
1260
    if(!isString(msg2) || LENGTH(msg2) != 1)
1241
	error(_("'%s' must be a character string"), "msg2");
1261
	error(_("'%s' must be a character string"), "msg2");
1242
 
1262
 
1243
#ifdef ENABLE_NLS
1263
#ifdef ENABLE_NLS
1244
    char * domain = determine_domain_gettext(CADDDR(args));
1264
    char * domain = determine_domain_gettext(CADDDR(args), /*up*/FALSE);
1245
 
1265
 
1246
    if(domain && strlen(domain)) {
1266
    if(domain && strlen(domain)) {
1247
	/* libintl seems to malfunction if given a message of "" */
1267
	/* libintl seems to malfunction if given a message of "" */
1248
	if(length(STRING_ELT(msg1, 0))) {
1268
	if(length(STRING_ELT(msg1, 0))) {
1249
	    char *fmt = dngettext(domain,
1269
	    char *fmt = dngettext(domain,
Line 1270... Line 1290...
1270
    if(isNull(CADR(args))) {
1290
    if(isNull(CADR(args))) {
1271
	res = bindtextdomain(translateChar(STRING_ELT(CAR(args),0)), NULL);
1291
	res = bindtextdomain(translateChar(STRING_ELT(CAR(args),0)), NULL);
1272
    } else {
1292
    } else {
1273
	if(!isString(CADR(args)) || LENGTH(CADR(args)) != 1)
1293
	if(!isString(CADR(args)) || LENGTH(CADR(args)) != 1)
1274
	    error(_("invalid '%s' value"), "dirname");
1294
	    error(_("invalid '%s' value"), "dirname");
1275
	res = bindtextdomain(translateChar(STRING_ELT(CAR(args),0)),
1295
	res = bindtextdomain(translateChar(STRING_ELT(CAR (args),0)),
1276
			     translateChar(STRING_ELT(CADR(args),0)));
1296
			     translateChar(STRING_ELT(CADR(args),0)));
1277
    }
1297
    }
1278
    if(res) return mkString(res);
1298
    if(res) return mkString(res);
1279
    /* else this failed */
1299
    /* else this failed */
1280
#endif
1300
#endif