about summary refs log tree commit diff
path: root/src/libexpr
diff options
context:
space:
mode:
authorJörg Thalheim <joerg@thalheim.io>2017-07-30T11·27+0100
committerJörg Thalheim <joerg@thalheim.io>2017-07-30T11·32+0100
commit2fd8f8bb99a2832b3684878c020ba47322e79332 (patch)
tree65a667fbc746f4ff8efcaca3c0a58565985f26a5 /src/libexpr
parentc7654bc491d9ce7c1fbadecd7769418fa79a2060 (diff)
Replace Unicode quotes in user-facing strings by ASCII
Relevant RFC: NixOS/rfcs#4

$ ag -l | xargs sed -i -e "/\"/s/’/'/g;/\"/s/‘/'/g"
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/attr-path.cc14
-rw-r--r--src/libexpr/common-opts.cc4
-rw-r--r--src/libexpr/eval.cc34
-rw-r--r--src/libexpr/get-drvs.cc4
-rw-r--r--src/libexpr/json-to-value.cc6
-rw-r--r--src/libexpr/lexer.l8
-rw-r--r--src/libexpr/nixexpr.cc4
-rw-r--r--src/libexpr/nixexpr.hh2
-rw-r--r--src/libexpr/parser.y16
-rw-r--r--src/libexpr/primops.cc108
-rw-r--r--src/libexpr/primops/fetchgit.cc18
11 files changed, 109 insertions, 109 deletions
diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc
index 55379f94b1..b0f80db32a 100644
--- a/src/libexpr/attr-path.cc
+++ b/src/libexpr/attr-path.cc
@@ -19,7 +19,7 @@ static Strings parseAttrPath(const string & s)
             ++i;
             while (1) {
                 if (i == s.end())
-                    throw Error(format("missing closing quote in selection path ‘%1%’") % s);
+                    throw Error(format("missing closing quote in selection path '%1%'") % s);
                 if (*i == '"') break;
                 cur.push_back(*i++);
             }
@@ -38,7 +38,7 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
     Strings tokens = parseAttrPath(attrPath);
 
     Error attrError =
-        Error(format("attribute selection path ‘%1%’ does not match expression") % attrPath);
+        Error(format("attribute selection path '%1%' does not match expression") % attrPath);
 
     Value * v = &vIn;
 
@@ -62,15 +62,15 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
 
             if (v->type != tAttrs)
                 throw TypeError(
-                    format("the expression selected by the selection path ‘%1%’ should be a set but is %2%")
+                    format("the expression selected by the selection path '%1%' should be a set but is %2%")
                     % attrPath % showType(*v));
 
             if (attr.empty())
-                throw Error(format("empty attribute name in selection path ‘%1%’") % attrPath);
+                throw Error(format("empty attribute name in selection path '%1%'") % attrPath);
 
             Bindings::iterator a = v->attrs->find(state.symbols.create(attr));
             if (a == v->attrs->end())
-                throw Error(format("attribute ‘%1%’ in selection path ‘%2%’ not found") % attr % attrPath);
+                throw Error(format("attribute '%1%' in selection path '%2%' not found") % attr % attrPath);
             v = &*a->value;
         }
 
@@ -78,11 +78,11 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
 
             if (!v->isList())
                 throw TypeError(
-                    format("the expression selected by the selection path ‘%1%’ should be a list but is %2%")
+                    format("the expression selected by the selection path '%1%' should be a list but is %2%")
                     % attrPath % showType(*v));
 
             if (attrIndex >= v->listSize())
-                throw Error(format("list index %1% in selection path ‘%2%’ is out of range") % attrIndex % attrPath);
+                throw Error(format("list index %1% in selection path '%2%' is out of range") % attrIndex % attrPath);
 
             v = v->listElems()[attrIndex];
         }
diff --git a/src/libexpr/common-opts.cc b/src/libexpr/common-opts.cc
index 06d6ed87df..6b31961d34 100644
--- a/src/libexpr/common-opts.cc
+++ b/src/libexpr/common-opts.cc
@@ -13,7 +13,7 @@ bool parseAutoArgs(Strings::iterator & i,
     string arg = *i;
     if (arg != "--arg" && arg != "--argstr") return false;
 
-    UsageError error(format("‘%1%’ requires two arguments") % arg);
+    UsageError error(format("'%1%' requires two arguments") % arg);
 
     if (++i == argsEnd) throw error;
     string name = *i;
@@ -46,7 +46,7 @@ bool parseSearchPathArg(Strings::iterator & i,
     const Strings::iterator & argsEnd, Strings & searchPath)
 {
     if (*i != "-I") return false;
-    if (++i == argsEnd) throw UsageError("‘-I’ requires an argument");
+    if (++i == argsEnd) throw UsageError("'-I' requires an argument");
     searchPath.push_back(*i);
     return true;
 }
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index ca4c9a373a..78f6b00105 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -329,7 +329,7 @@ Path EvalState::checkSourcePath(const Path & path_)
     if (!restricted) return path_;
 
     /* Resolve symlinks. */
-    debug(format("checking access to ‘%s’") % path_);
+    debug(format("checking access to '%s'") % path_);
     Path path = canonPath(path_, true);
 
     for (auto & i : searchPath) {
@@ -351,7 +351,7 @@ Path EvalState::checkSourcePath(const Path & path_)
         return path;
 #endif
 
-    throw RestrictedPathError(format("access to path ‘%1%’ is forbidden in restricted mode") % path_);
+    throw RestrictedPathError(format("access to path '%1%' is forbidden in restricted mode") % path_);
 }
 
 
@@ -504,7 +504,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
             return j->value;
         }
         if (!env->prevWith)
-            throwUndefinedVarError("undefined variable ‘%1%’ at %2%", var.name, var.pos);
+            throwUndefinedVarError("undefined variable '%1%' at %2%", var.name, var.pos);
         for (unsigned int l = env->prevWith; l; --l, env = env->up) ;
     }
 }
@@ -643,12 +643,12 @@ void EvalState::evalFile(const Path & path, Value & v)
         return;
     }
 
-    printTalkative("evaluating file ‘%1%’", path2);
+    printTalkative("evaluating file '%1%'", path2);
     Expr * e = parseExprFromFile(checkSourcePath(path2));
     try {
         eval(e, v);
     } catch (Error & e) {
-        addErrorPrefix(e, "while evaluating the file ‘%1%’:\n", path2);
+        addErrorPrefix(e, "while evaluating the file '%1%':\n", path2);
         throw;
     }
 
@@ -798,7 +798,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
         Symbol nameSym = state.symbols.create(nameVal.string.s);
         Bindings::iterator j = v.attrs->find(nameSym);
         if (j != v.attrs->end())
-            throwEvalError("dynamic attribute ‘%1%’ at %2% already defined at %3%", nameSym, i.pos, *j->pos);
+            throwEvalError("dynamic attribute '%1%' at %2% already defined at %3%", nameSym, i.pos, *j->pos);
 
         i.valueExpr->setName(nameSym);
         /* Keep sorted order so find can catch duplicates */
@@ -886,7 +886,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
             } else {
                 state.forceAttrs(*vAttrs, pos);
                 if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
-                    throwEvalError("attribute ‘%1%’ missing, at %2%", name, pos);
+                    throwEvalError("attribute '%1%' missing, at %2%", name, pos);
             }
             vAttrs = j->value;
             pos2 = j->pos;
@@ -897,7 +897,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
 
     } catch (Error & e) {
         if (pos2 && pos2->file != state.sDerivationNix)
-            addErrorPrefix(e, "while evaluating the attribute ‘%1%’ at %2%:\n",
+            addErrorPrefix(e, "while evaluating the attribute '%1%' at %2%:\n",
                 showAttrPath(state, env, attrPath), *pos2);
         throw;
     }
@@ -1039,7 +1039,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
         for (auto & i : lambda.formals->formals) {
             Bindings::iterator j = arg.attrs->find(i.name);
             if (j == arg.attrs->end()) {
-                if (!i.def) throwTypeError("%1% called without required argument ‘%2%’, at %3%",
+                if (!i.def) throwTypeError("%1% called without required argument '%2%', at %3%",
                     lambda, i.name, pos);
                 env2.values[displ++] = i.def->maybeThunk(*this, env2);
             } else {
@@ -1055,7 +1055,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
                user. */
             for (auto & i : *arg.attrs)
                 if (lambda.formals->argNames.find(i.name) == lambda.formals->argNames.end())
-                    throwTypeError("%1% called with unexpected argument ‘%2%’, at %3%", lambda, i.name, pos);
+                    throwTypeError("%1% called with unexpected argument '%2%', at %3%", lambda, i.name, pos);
             abort(); // can't happen
         }
     }
@@ -1113,7 +1113,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
         if (j != args.end())
             actualArgs->attrs->push_back(*j);
         else if (!i.def)
-            throwTypeError("cannot auto-call a function that has an argument without a default value (‘%1%’)", i.name);
+            throwTypeError("cannot auto-call a function that has an argument without a default value ('%1%')", i.name);
     }
 
     actualArgs->attrs->sort();
@@ -1342,7 +1342,7 @@ void EvalState::forceValueDeep(Value & v)
                 try {
                     recurse(*i.value);
                 } catch (Error & e) {
-                    addErrorPrefix(e, "while evaluating the attribute ‘%1%’ at %2%:\n", i.name, *i.pos);
+                    addErrorPrefix(e, "while evaluating the attribute '%1%' at %2%:\n", i.name, *i.pos);
                     throw;
                 }
         }
@@ -1434,10 +1434,10 @@ string EvalState::forceStringNoCtx(Value & v, const Pos & pos)
     string s = forceString(v, pos);
     if (v.string.context) {
         if (pos)
-            throwEvalError("the string ‘%1%’ is not allowed to refer to a store path (such as ‘%2%’), at %3%",
+            throwEvalError("the string '%1%' is not allowed to refer to a store path (such as '%2%'), at %3%",
                 v.string.s, v.string.context[0], pos);
         else
-            throwEvalError("the string ‘%1%’ is not allowed to refer to a store path (such as ‘%2%’)",
+            throwEvalError("the string '%1%' is not allowed to refer to a store path (such as '%2%')",
                 v.string.s, v.string.context[0]);
     }
     return s;
@@ -1519,7 +1519,7 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context,
 string EvalState::copyPathToStore(PathSet & context, const Path & path)
 {
     if (nix::isDerivation(path))
-        throwEvalError("file names are not allowed to end in ‘%1%’", drvExtension);
+        throwEvalError("file names are not allowed to end in '%1%'", drvExtension);
 
     Path dstPath;
     if (srcToStore[path] != "")
@@ -1529,7 +1529,7 @@ string EvalState::copyPathToStore(PathSet & context, const Path & path)
             ? store->computeStorePathForPath(checkSourcePath(path)).first
             : store->addToStore(baseNameOf(path), checkSourcePath(path), true, htSHA256, defaultPathFilter, repair);
         srcToStore[path] = dstPath;
-        printMsg(lvlChatty, format("copied source ‘%1%’ -> ‘%2%’")
+        printMsg(lvlChatty, format("copied source '%1%' -> '%2%'")
             % path % dstPath);
     }
 
@@ -1542,7 +1542,7 @@ Path EvalState::coerceToPath(const Pos & pos, Value & v, PathSet & context)
 {
     string path = coerceToString(pos, v, context, false, false);
     if (path == "" || path[0] != '/')
-        throwEvalError("string ‘%1%’ doesn't represent an absolute path, at %2%", path, pos);
+        throwEvalError("string '%1%' doesn't represent an absolute path, at %2%", path, pos);
     return path;
 }
 
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index 66689e3e88..d5bc42352a 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -89,7 +89,7 @@ DrvInfo::Outputs DrvInfo::queryOutputs(bool onlyOutputsToInstall)
     /* Check for `meta.outputsToInstall` and return `outputs` reduced to that. */
     const Value * outTI = queryMeta("outputsToInstall");
     if (!outTI) return outputs;
-    const auto errMsg = Error("this derivation has bad ‘meta.outputsToInstall’");
+    const auto errMsg = Error("this derivation has bad 'meta.outputsToInstall'");
         /* ^ this shows during `nix-env -i` right under the bad derivation */
     if (!outTI->isList()) throw errMsg;
     Outputs result;
@@ -310,7 +310,7 @@ static void getDerivations(EvalState & state, Value & vIn,
            bound to the attribute with the "lower" name should take
            precedence). */
         for (auto & i : v.attrs->lexicographicOrder()) {
-            debug("evaluating attribute ‘%1%’", i->name);
+            debug("evaluating attribute '%1%'", i->name);
             if (!std::regex_match(std::string(i->name), attrRegex))
                 continue;
             string pathPrefix2 = addToPath(pathPrefix, i->name);
diff --git a/src/libexpr/json-to-value.cc b/src/libexpr/json-to-value.cc
index c189cdef35..9380de3a66 100644
--- a/src/libexpr/json-to-value.cc
+++ b/src/libexpr/json-to-value.cc
@@ -57,7 +57,7 @@ static void parseJSON(EvalState & state, const char * & s, Value & v)
             values.push_back(v2);
             skipWhitespace(s);
             if (*s == ']') break;
-            if (*s != ',') throw JSONParseError("expected ‘,’ or ‘]’ after JSON array element");
+            if (*s != ',') throw JSONParseError("expected ',' or ']' after JSON array element");
             s++;
         }
         s++;
@@ -74,14 +74,14 @@ static void parseJSON(EvalState & state, const char * & s, Value & v)
             if (attrs.empty() && *s == '}') break;
             string name = parseJSONString(s);
             skipWhitespace(s);
-            if (*s != ':') throw JSONParseError("expected ‘:’ in JSON object");
+            if (*s != ':') throw JSONParseError("expected ':' in JSON object");
             s++;
             Value * v2 = state.allocValue();
             parseJSON(state, s, *v2);
             attrs[state.symbols.create(name)] = v2;
             skipWhitespace(s);
             if (*s == '}') break;
-            if (*s != ',') throw JSONParseError("expected ‘,’ or ‘}’ after JSON member");
+            if (*s != ',') throw JSONParseError("expected ',' or '}' after JSON member");
             s++;
         }
         state.mkAttrs(v, attrs.size());
diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l
index 40ca772580..28a0a6a878 100644
--- a/src/libexpr/lexer.l
+++ b/src/libexpr/lexer.l
@@ -124,13 +124,13 @@ or          { return OR_KW; }
 {INT}       { errno = 0;
               yylval->n = strtol(yytext, 0, 10);
               if (errno != 0)
-                  throw ParseError(format("invalid integer ‘%1%’") % yytext);
+                  throw ParseError(format("invalid integer '%1%'") % yytext);
               return INT;
             }
 {FLOAT}     { errno = 0;
               yylval->nf = strtod(yytext, 0);
               if (errno != 0)
-                  throw ParseError(format("invalid float ‘%1%’") % yytext);
+                  throw ParseError(format("invalid float '%1%'") % yytext);
               return FLOAT;
             }
 
@@ -191,12 +191,12 @@ or          { return OR_KW; }
 <INITIAL,INSIDE_DOLLAR_CURLY>{
 
 {PATH}      { if (yytext[yyleng-1] == '/')
-                  throw ParseError("path ‘%s’ has a trailing slash", yytext);
+                  throw ParseError("path '%s' has a trailing slash", yytext);
               yylval->path = strdup(yytext);
               return PATH;
             }
 {HPATH}     { if (yytext[yyleng-1] == '/')
-                  throw ParseError("path ‘%s’ has a trailing slash", yytext);
+                  throw ParseError("path '%s' has a trailing slash", yytext);
               yylval->path = strdup(yytext);
               return HPATH;
             }
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index b2c9f0528c..7b0a127cd4 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -267,7 +267,7 @@ void ExprVar::bindVars(const StaticEnv & env)
     /* Otherwise, the variable must be obtained from the nearest
        enclosing `with'.  If there is no `with', then we can issue an
        "undefined variable" error now. */
-    if (withLevel == -1) throw UndefinedVarError(format("undefined variable ‘%1%’ at %2%") % name % pos);
+    if (withLevel == -1) throw UndefinedVarError(format("undefined variable '%1%' at %2%") % name % pos);
 
     fromWith = true;
     this->level = withLevel;
@@ -419,7 +419,7 @@ void ExprLambda::setName(Symbol & name)
 
 string ExprLambda::showNamePos() const
 {
-    return (format("%1% at %2%") % (name.set() ? "‘" + (string) name + "’" : "anonymous function") % pos).str();
+    return (format("%1% at %2%") % (name.set() ? "'" + (string) name + "'" : "anonymous function") % pos).str();
 }
 
 
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index d2ca09b3a5..30be79bb57 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -235,7 +235,7 @@ struct ExprLambda : Expr
         : pos(pos), arg(arg), matchAttrs(matchAttrs), formals(formals), body(body)
     {
         if (!arg.empty() && formals && formals->argNames.find(arg) != formals->argNames.end())
-            throw ParseError(format("duplicate formal function argument ‘%1%’ at %2%")
+            throw ParseError(format("duplicate formal function argument '%1%' at %2%")
                 % arg % pos);
     };
     void setName(Symbol & name);
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index ca3d057451..669312bb7c 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -65,14 +65,14 @@ namespace nix {
 
 static void dupAttr(const AttrPath & attrPath, const Pos & pos, const Pos & prevPos)
 {
-    throw ParseError(format("attribute ‘%1%’ at %2% already defined at %3%")
+    throw ParseError(format("attribute '%1%' at %2% already defined at %3%")
         % showAttrPath(attrPath) % pos % prevPos);
 }
 
 
 static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos)
 {
-    throw ParseError(format("attribute ‘%1%’ at %2% already defined at %3%")
+    throw ParseError(format("attribute '%1%' at %2% already defined at %3%")
         % attr % pos % prevPos);
 }
 
@@ -121,7 +121,7 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
 static void addFormal(const Pos & pos, Formals * formals, const Formal & formal)
 {
     if (formals->argNames.find(formal.name) != formals->argNames.end())
-        throw ParseError(format("duplicate formal function argument ‘%1%’ at %2%")
+        throw ParseError(format("duplicate formal function argument '%1%' at %2%")
             % formal.name % pos);
     formals->formals.push_front(formal);
     formals->argNames.insert(formal.name);
@@ -564,7 +564,7 @@ Path resolveExprPath(Path path)
     struct stat st;
     while (true) {
         if (lstat(path.c_str(), &st))
-            throw SysError(format("getting status of ‘%1%’") % path);
+            throw SysError(format("getting status of '%1%'") % path);
         if (!S_ISLNK(st.st_mode)) break;
         path = absPath(readLink(path), dirOf(path));
     }
@@ -649,7 +649,7 @@ Path EvalState::findFile(SearchPath & searchPath, const string & path, const Pos
         if (pathExists(res)) return canonPath(res);
     }
     format f = format(
-        "file ‘%1%’ was not found in the Nix search path (add it using $NIX_PATH or -I)"
+        "file '%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)"
         + string(pos ? ", at %2%" : ""));
     f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
     throw ThrownError(f % path % pos);
@@ -671,7 +671,7 @@ std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathEl
             else
                 res = { true, getDownloader()->downloadCached(store, elem.second, true) };
         } catch (DownloadError & e) {
-            printError(format("warning: Nix search path entry ‘%1%’ cannot be downloaded, ignoring") % elem.second);
+            printError(format("warning: Nix search path entry '%1%' cannot be downloaded, ignoring") % elem.second);
             res = { false, "" };
         }
     } else {
@@ -679,12 +679,12 @@ std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathEl
         if (pathExists(path))
             res = { true, path };
         else {
-            printError(format("warning: Nix search path entry ‘%1%’ does not exist, ignoring") % elem.second);
+            printError(format("warning: Nix search path entry '%1%' does not exist, ignoring") % elem.second);
             res = { false, "" };
         }
     }
 
-    debug(format("resolved search path element ‘%s’ to ‘%s’") % elem.second % res.second);
+    debug(format("resolved search path element '%s' to '%s'") % elem.second % res.second);
 
     searchPathResolved[elem.second] = res;
     return res;
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 78d73e1f55..4e51e8ff25 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -44,7 +44,7 @@ std::pair<string, string> decodeContext(const string & s)
 
 
 InvalidPathError::InvalidPathError(const Path & path) :
-    EvalError(format("path ‘%1%’ is not valid") % path), path(path) {}
+    EvalError(format("path '%1%' is not valid") % path), path(path) {}
 
 void EvalState::realiseContext(const PathSet & context)
 {
@@ -60,7 +60,7 @@ void EvalState::realiseContext(const PathSet & context)
     }
     if (!drvs.empty()) {
         if (!settings.enableImportFromDerivation)
-            throw EvalError(format("attempted to realize ‘%1%’ during evaluation but 'allow-import-from-derivation' is false") % *(drvs.begin()));
+            throw EvalError(format("attempted to realize '%1%' during evaluation but 'allow-import-from-derivation' is false") % *(drvs.begin()));
         /* For performance, prefetch all substitute info. */
         PathSet willBuild, willSubstitute, unknown;
         unsigned long long downloadSize, narSize;
@@ -80,7 +80,7 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
     try {
         state.realiseContext(context);
     } catch (InvalidPathError & e) {
-        throw EvalError(format("cannot import ‘%1%’, since path ‘%2%’ is not valid, at %3%")
+        throw EvalError(format("cannot import '%1%', since path '%2%' is not valid, at %3%")
             % path % e.path % pos);
     }
 
@@ -127,7 +127,7 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
                 env->values[displ++] = attr.value;
             }
 
-            printTalkative("evaluating file ‘%1%’", path);
+            printTalkative("evaluating file '%1%'", path);
             Expr * e = state.parseExprFromFile(resolveExprPath(path), staticEnv);
 
             e->eval(state, *env, v);
@@ -149,7 +149,7 @@ static void prim_importNative(EvalState & state, const Pos & pos, Value * * args
     try {
         state.realiseContext(context);
     } catch (InvalidPathError & e) {
-        throw EvalError(format("cannot import ‘%1%’, since path ‘%2%’ is not valid, at %3%")
+        throw EvalError(format("cannot import '%1%', since path '%2%' is not valid, at %3%")
             % path % e.path % pos);
     }
 
@@ -159,16 +159,16 @@ static void prim_importNative(EvalState & state, const Pos & pos, Value * * args
 
     void *handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
     if (!handle)
-        throw EvalError(format("could not open ‘%1%’: %2%") % path % dlerror());
+        throw EvalError(format("could not open '%1%': %2%") % path % dlerror());
 
     dlerror();
     ValueInitializer func = (ValueInitializer) dlsym(handle, sym.c_str());
     if(!func) {
         char *message = dlerror();
         if (message)
-            throw EvalError(format("could not load symbol ‘%1%’ from ‘%2%’: %3%") % sym % path % message);
+            throw EvalError(format("could not load symbol '%1%' from '%2%': %3%") % sym % path % message);
         else
-            throw EvalError(format("symbol ‘%1%’ from ‘%2%’ resolved to NULL when a function pointer was expected")
+            throw EvalError(format("symbol '%1%' from '%2%' resolved to NULL when a function pointer was expected")
                     % sym % path);
     }
 
@@ -196,7 +196,7 @@ static void prim_exec(EvalState & state, const Pos & pos, Value * * args, Value
     try {
         state.realiseContext(context);
     } catch (InvalidPathError & e) {
-        throw EvalError(format("cannot execute ‘%1%’, since path ‘%2%’ is not valid, at %3%")
+        throw EvalError(format("cannot execute '%1%', since path '%2%' is not valid, at %3%")
             % program % e.path % pos);
     }
 
@@ -205,13 +205,13 @@ static void prim_exec(EvalState & state, const Pos & pos, Value * * args, Value
     try {
         parsed = state.parseExprFromString(output, pos.file);
     } catch (Error & e) {
-        e.addPrefix(format("While parsing the output from ‘%1%’, at %2%\n") % program % pos);
+        e.addPrefix(format("While parsing the output from '%1%', at %2%\n") % program % pos);
         throw;
     }
     try {
         state.eval(parsed, v);
     } catch (Error & e) {
-        e.addPrefix(format("While evaluating the output from ‘%1%’, at %2%\n") % program % pos);
+        e.addPrefix(format("While evaluating the output from '%1%', at %2%\n") % program % pos);
         throw;
     }
 }
@@ -332,7 +332,7 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar
     Bindings::iterator startSet =
         args[0]->attrs->find(state.symbols.create("startSet"));
     if (startSet == args[0]->attrs->end())
-        throw EvalError(format("attribute ‘startSet’ required, at %1%") % pos);
+        throw EvalError(format("attribute 'startSet' required, at %1%") % pos);
     state.forceList(*startSet->value, pos);
 
     ValueList workSet;
@@ -343,7 +343,7 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar
     Bindings::iterator op =
         args[0]->attrs->find(state.symbols.create("operator"));
     if (op == args[0]->attrs->end())
-        throw EvalError(format("attribute ‘operator’ required, at %1%") % pos);
+        throw EvalError(format("attribute 'operator' required, at %1%") % pos);
     state.forceValue(*op->value);
 
     /* Construct the closure by applying the operator to element of
@@ -362,7 +362,7 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar
         Bindings::iterator key =
             e->attrs->find(state.symbols.create("key"));
         if (key == e->attrs->end())
-            throw EvalError(format("attribute ‘key’ required, at %1%") % pos);
+            throw EvalError(format("attribute 'key' required, at %1%") % pos);
         state.forceValue(*key->value);
 
         if (doneKeys.find(key->value) != doneKeys.end()) continue;
@@ -393,7 +393,7 @@ static void prim_abort(EvalState & state, const Pos & pos, Value * * args, Value
 {
     PathSet context;
     string s = state.coerceToString(pos, *args[0], context);
-    throw Abort(format("evaluation aborted with the following error message: ‘%1%’") % s);
+    throw Abort(format("evaluation aborted with the following error message: '%1%'") % s);
 }
 
 
@@ -502,13 +502,13 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
     /* Figure out the name first (for stack backtraces). */
     Bindings::iterator attr = args[0]->attrs->find(state.sName);
     if (attr == args[0]->attrs->end())
-        throw EvalError(format("required attribute ‘name’ missing, at %1%") % pos);
+        throw EvalError(format("required attribute 'name' missing, at %1%") % pos);
     string drvName;
     Pos & posDrvName(*attr->pos);
     try {
         drvName = state.forceStringNoCtx(*attr->value, pos);
     } catch (Error & e) {
-        e.addPrefix(format("while evaluating the derivation attribute ‘name’ at %1%:\n") % posDrvName);
+        e.addPrefix(format("while evaluating the derivation attribute 'name' at %1%:\n") % posDrvName);
         throw;
     }
 
@@ -540,26 +540,26 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
     for (auto & i : args[0]->attrs->lexicographicOrder()) {
         if (i->name == state.sIgnoreNulls) continue;
         string key = i->name;
-        vomit("processing attribute ‘%1%’", key);
+        vomit("processing attribute '%1%'", key);
 
         auto handleHashMode = [&](const std::string & s) {
             if (s == "recursive") outputHashRecursive = true;
             else if (s == "flat") outputHashRecursive = false;
-            else throw EvalError("invalid value ‘%s’ for ‘outputHashMode’ attribute, at %s", s, posDrvName);
+            else throw EvalError("invalid value '%s' for 'outputHashMode' attribute, at %s", s, posDrvName);
         };
 
         auto handleOutputs = [&](const Strings & ss) {
             outputs.clear();
             for (auto & j : ss) {
                 if (outputs.find(j) != outputs.end())
-                    throw EvalError(format("duplicate derivation output ‘%1%’, at %2%") % j % posDrvName);
+                    throw EvalError(format("duplicate derivation output '%1%', at %2%") % j % posDrvName);
                 /* !!! Check whether j is a valid attribute
                    name. */
                 /* Derivations cannot be named ‘drv’, because
                    then we'd have an attribute ‘drvPath’ in
                    the resulting set. */
                 if (j == "drv")
-                    throw EvalError(format("invalid derivation output name ‘drv’, at %1%") % posDrvName);
+                    throw EvalError(format("invalid derivation output name 'drv', at %1%") % posDrvName);
                 outputs.insert(j);
             }
             if (outputs.empty())
@@ -622,7 +622,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
                     else if (i->name == state.sSystem) drv.platform = s;
                     else if (i->name == state.sName) {
                         drvName = s;
-                        printMsg(lvlVomit, format("derivation name is ‘%1%’") % drvName);
+                        printMsg(lvlVomit, format("derivation name is '%1%'") % drvName);
                     }
                     else if (key == "outputHash") outputHash = s;
                     else if (key == "outputHashAlgo") outputHashAlgo = s;
@@ -634,7 +634,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
             }
 
         } catch (Error & e) {
-            e.addPrefix(format("while evaluating the attribute ‘%1%’ of the derivation ‘%2%’ at %3%:\n")
+            e.addPrefix(format("while evaluating the attribute '%1%' of the derivation '%2%' at %3%:\n")
                 % key % drvName % posDrvName);
             throw;
         }
@@ -690,14 +690,14 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
 
     /* Do we have all required attributes? */
     if (drv.builder == "")
-        throw EvalError(format("required attribute ‘builder’ missing, at %1%") % posDrvName);
+        throw EvalError(format("required attribute 'builder' missing, at %1%") % posDrvName);
     if (drv.platform == "")
-        throw EvalError(format("required attribute ‘system’ missing, at %1%") % posDrvName);
+        throw EvalError(format("required attribute 'system' missing, at %1%") % posDrvName);
 
     /* Check whether the derivation name is valid. */
     checkStoreName(drvName);
     if (isDerivation(drvName))
-        throw EvalError(format("derivation names are not allowed to end in ‘%1%’, at %2%")
+        throw EvalError(format("derivation names are not allowed to end in '%1%', at %2%")
             % drvExtension % posDrvName);
 
     if (outputHash) {
@@ -707,7 +707,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
 
         HashType ht = parseHashType(outputHashAlgo);
         if (ht == htUnknown)
-            throw EvalError(format("unknown hash algorithm ‘%1%’, at %2%") % outputHashAlgo % posDrvName);
+            throw EvalError(format("unknown hash algorithm '%1%', at %2%") % outputHashAlgo % posDrvName);
         Hash h(*outputHash, ht);
         outputHash = h.to_string(Base16, false);
         if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo;
@@ -743,7 +743,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
     /* Write the resulting term into the Nix store directory. */
     Path drvPath = writeDerivation(state.store, drv, drvName, state.repair);
 
-    printMsg(lvlChatty, format("instantiated ‘%1%’ -> ‘%2%’")
+    printMsg(lvlChatty, format("instantiated '%1%' -> '%2%'")
         % drvName % drvPath);
 
     /* Optimisation, but required in read-only mode! because in that
@@ -763,7 +763,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
 
 /* Return a placeholder string for the specified output that will be
    substituted by the corresponding output path at build time. For
-   example, ‘placeholder "out"’ returns the string
+   example, 'placeholder "out"' returns the string
    /1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9. At build
    time, any occurence of this string in an derivation attribute will
    be replaced with the concrete path in the Nix store of the output
@@ -805,7 +805,7 @@ static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, V
        e.g. nix-push does the right thing. */
     if (!state.store->isStorePath(path)) path = canonPath(path, true);
     if (!state.store->isInStore(path))
-        throw EvalError(format("path ‘%1%’ is not in the Nix store, at %2%") % path % pos);
+        throw EvalError(format("path '%1%' is not in the Nix store, at %2%") % path % pos);
     Path path2 = state.store->toStorePath(path);
     if (!settings.readOnlyMode)
         state.store->ensurePath(path2);
@@ -819,7 +819,7 @@ static void prim_pathExists(EvalState & state, const Pos & pos, Value * * args,
     PathSet context;
     Path path = state.coerceToPath(pos, *args[0], context);
     if (!context.empty())
-        throw EvalError(format("string ‘%1%’ cannot refer to other paths, at %2%") % path % pos);
+        throw EvalError(format("string '%1%' cannot refer to other paths, at %2%") % path % pos);
     try {
         mkBool(v, pathExists(state.checkSourcePath(path)));
     } catch (SysError & e) {
@@ -860,18 +860,18 @@ static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Va
     try {
         state.realiseContext(context);
     } catch (InvalidPathError & e) {
-        throw EvalError(format("cannot read ‘%1%’, since path ‘%2%’ is not valid, at %3%")
+        throw EvalError(format("cannot read '%1%', since path '%2%' is not valid, at %3%")
             % path % e.path % pos);
     }
     string s = readFile(state.checkSourcePath(path));
     if (s.find((char) 0) != string::npos)
-        throw Error(format("the contents of the file ‘%1%’ cannot be represented as a Nix string") % path);
+        throw Error(format("the contents of the file '%1%' cannot be represented as a Nix string") % path);
     mkString(v, s.c_str());
 }
 
 
 /* Find a file in the Nix search path. Used to implement <x> paths,
-   which are desugared to ‘findFile __nixPath "x"’. */
+   which are desugared to 'findFile __nixPath "x"'. */
 static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
     state.forceList(*args[0], pos);
@@ -889,7 +889,7 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
 
         i = v2.attrs->find(state.symbols.create("path"));
         if (i == v2.attrs->end())
-            throw EvalError(format("attribute ‘path’ missing, at %1%") % pos);
+            throw EvalError(format("attribute 'path' missing, at %1%") % pos);
 
         PathSet context;
         string path = state.coerceToString(pos, *i->value, context, false, false);
@@ -897,7 +897,7 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
         try {
             state.realiseContext(context);
         } catch (InvalidPathError & e) {
-            throw EvalError(format("cannot find ‘%1%’, since path ‘%2%’ is not valid, at %3%")
+            throw EvalError(format("cannot find '%1%', since path '%2%' is not valid, at %3%")
                 % path % e.path % pos);
         }
 
@@ -917,7 +917,7 @@ static void prim_readDir(EvalState & state, const Pos & pos, Value * * args, Val
     try {
         state.realiseContext(ctx);
     } catch (InvalidPathError & e) {
-        throw EvalError(format("cannot read ‘%1%’, since path ‘%2%’ is not valid, at %3%")
+        throw EvalError(format("cannot read '%1%', since path '%2%' is not valid, at %3%")
             % path % e.path % pos);
     }
 
@@ -991,7 +991,7 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu
         if (isDerivation(path)) {
             /* See prim_unsafeDiscardOutputDependency. */
             if (path.at(0) != '~')
-                throw EvalError(format("in ‘toFile’: the file ‘%1%’ cannot refer to derivation outputs, at %2%") % name % pos);
+                throw EvalError(format("in 'toFile': the file '%1%' cannot refer to derivation outputs, at %2%") % name % pos);
             path = string(path, 1);
         }
         refs.insert(path);
@@ -1024,7 +1024,7 @@ struct FilterFromExpr : PathFilter
     {
         struct stat st;
         if (lstat(path.c_str(), &st))
-            throw SysError(format("getting attributes of path ‘%1%’") % path);
+            throw SysError(format("getting attributes of path '%1%'") % path);
 
         /* Call the filter function.  The first argument is the path,
            the second is a string indicating the type of the file. */
@@ -1054,11 +1054,11 @@ static void prim_filterSource(EvalState & state, const Pos & pos, Value * * args
     PathSet context;
     Path path = state.coerceToPath(pos, *args[1], context);
     if (!context.empty())
-        throw EvalError(format("string ‘%1%’ cannot refer to other paths, at %2%") % path % pos);
+        throw EvalError(format("string '%1%' cannot refer to other paths, at %2%") % path % pos);
 
     state.forceValue(*args[0]);
     if (args[0]->type != tLambda)
-        throw TypeError(format("first argument in call to ‘filterSource’ is not a function but %1%, at %2%") % showType(*args[0]) % pos);
+        throw TypeError(format("first argument in call to 'filterSource' is not a function but %1%, at %2%") % showType(*args[0]) % pos);
 
     FilterFromExpr filter(state, *args[0], pos);
 
@@ -1119,7 +1119,7 @@ void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v)
     // !!! Should we create a symbol here or just do a lookup?
     Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr));
     if (i == args[1]->attrs->end())
-        throw EvalError(format("attribute ‘%1%’ missing, at %2%") % attr % pos);
+        throw EvalError(format("attribute '%1%' missing, at %2%") % attr % pos);
     // !!! add to stack trace?
     if (state.countCalls && i->pos) state.attrSelects[*i->pos]++;
     state.forceValue(*i->value);
@@ -1199,14 +1199,14 @@ static void prim_listToAttrs(EvalState & state, const Pos & pos, Value * * args,
 
         Bindings::iterator j = v2.attrs->find(state.sName);
         if (j == v2.attrs->end())
-            throw TypeError(format("‘name’ attribute missing in a call to ‘listToAttrs’, at %1%") % pos);
+            throw TypeError(format("'name' attribute missing in a call to 'listToAttrs', at %1%") % pos);
         string name = state.forceStringNoCtx(*j->value, pos);
 
         Symbol sym = state.symbols.create(name);
         if (seen.find(sym) == seen.end()) {
             Bindings::iterator j2 = v2.attrs->find(state.symbols.create(state.sValue));
             if (j2 == v2.attrs->end())
-                throw TypeError(format("‘value’ attribute missing in a call to ‘listToAttrs’, at %1%") % pos);
+                throw TypeError(format("'value' attribute missing in a call to 'listToAttrs', at %1%") % pos);
 
             v.attrs->push_back(Attr(sym, j2->value, j2->pos));
             seen.insert(sym);
@@ -1281,7 +1281,7 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args
 {
     state.forceValue(*args[0]);
     if (args[0]->type != tLambda)
-        throw TypeError(format("‘functionArgs’ requires a function, at %1%") % pos);
+        throw TypeError(format("'functionArgs' requires a function, at %1%") % pos);
 
     if (!args[0]->lambda.fun->matchAttrs) {
         state.mkAttrs(v, 0);
@@ -1340,7 +1340,7 @@ static void prim_tail(EvalState & state, const Pos & pos, Value * * args, Value
 {
     state.forceList(*args[0], pos);
     if (args[0]->listSize() == 0)
-        throw Error(format("‘tail’ called on an empty list, at %1%") % pos);
+        throw Error(format("'tail' called on an empty list, at %1%") % pos);
     state.mkList(v, args[0]->listSize() - 1);
     for (unsigned int n = 0; n < v.listSize(); ++n)
         v.listElems()[n] = args[0]->listElems()[n + 1];
@@ -1649,7 +1649,7 @@ static void prim_substring(EvalState & state, const Pos & pos, Value * * args, V
     PathSet context;
     string s = state.coerceToString(pos, *args[2], context);
 
-    if (start < 0) throw EvalError(format("negative start position in ‘substring’, at %1%") % pos);
+    if (start < 0) throw EvalError(format("negative start position in 'substring', at %1%") % pos);
 
     mkString(v, (unsigned int) start >= s.size() ? "" : string(s, start, len), context);
 }
@@ -1696,7 +1696,7 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args,
     string type = state.forceStringNoCtx(*args[0], pos);
     HashType ht = parseHashType(type);
     if (ht == htUnknown)
-      throw Error(format("unknown hash type ‘%1%’, at %2%") % type % pos);
+      throw Error(format("unknown hash type '%1%', at %2%") % type % pos);
 
     PathSet context; // discarded
     string s = state.forceString(*args[1], context, pos);
@@ -1737,9 +1737,9 @@ static void prim_match(EvalState & state, const Pos & pos, Value * * args, Value
     } catch (std::regex_error &e) {
         if (e.code() == std::regex_constants::error_space) {
           // limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
-          throw EvalError("memory limit exceeded by regular expression ‘%s’, at %s", re, pos);
+          throw EvalError("memory limit exceeded by regular expression '%s', at %s", re, pos);
         } else {
-          throw EvalError("invalid regular expression ‘%s’, at %s", re, pos);
+          throw EvalError("invalid regular expression '%s', at %s", re, pos);
         }
     }
 }
@@ -1770,7 +1770,7 @@ static void prim_replaceStrings(EvalState & state, const Pos & pos, Value * * ar
     state.forceList(*args[0], pos);
     state.forceList(*args[1], pos);
     if (args[0]->listSize() != args[1]->listSize())
-        throw EvalError(format("‘from’ and ‘to’ arguments to ‘replaceStrings’ have different lengths, at %1%") % pos);
+        throw EvalError(format("'from' and 'to' arguments to 'replaceStrings' have different lengths, at %1%") % pos);
 
     vector<string> from;
     from.reserve(args[0]->listSize());
@@ -1861,17 +1861,17 @@ void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
             else if (n == "name")
                 name = state.forceStringNoCtx(*attr.value, *attr.pos);
             else
-                throw EvalError(format("unsupported argument ‘%1%’ to ‘%2%’, at %3%") % attr.name % who % attr.pos);
+                throw EvalError(format("unsupported argument '%1%' to '%2%', at %3%") % attr.name % who % attr.pos);
         }
 
         if (url.empty())
-            throw EvalError(format("‘url’ argument required, at %1%") % pos);
+            throw EvalError(format("'url' argument required, at %1%") % pos);
 
     } else
         url = state.forceStringNoCtx(*args[0], pos);
 
     if (state.restricted && !expectedHash)
-        throw Error(format("‘%1%’ is not allowed in restricted mode") % who);
+        throw Error(format("'%1%' is not allowed in restricted mode") % who);
 
     Path res = getDownloader()->downloadCached(state.store, url, unpack, name, expectedHash);
     mkString(v, res, PathSet({res}));
diff --git a/src/libexpr/primops/fetchgit.cc b/src/libexpr/primops/fetchgit.cc
index 1e01a452b7..e16c823537 100644
--- a/src/libexpr/primops/fetchgit.cc
+++ b/src/libexpr/primops/fetchgit.cc
@@ -14,18 +14,18 @@ Path exportGit(ref<Store> store, const std::string & uri,
     const std::string & ref, const std::string & rev)
 {
     if (!isUri(uri))
-        throw EvalError(format("‘%s’ is not a valid URI") % uri);
+        throw EvalError(format("'%s' is not a valid URI") % uri);
 
     if (rev != "") {
         std::regex revRegex("^[0-9a-fA-F]{40}$");
         if (!std::regex_match(rev, revRegex))
-            throw Error("invalid Git revision ‘%s’", rev);
+            throw Error("invalid Git revision '%s'", rev);
     }
 
     // FIXME: too restrictive, but better safe than sorry.
     std::regex refRegex("^[0-9a-zA-Z][0-9a-zA-Z.-]+$");
     if (!std::regex_match(ref, refRegex))
-        throw Error("invalid Git ref ‘%s’", ref);
+        throw Error("invalid Git ref '%s'", ref);
 
     Path cacheDir = getCacheDir() + "/nix/git";
 
@@ -34,7 +34,7 @@ Path exportGit(ref<Store> store, const std::string & uri,
         runProgram("git", true, { "init", "--bare", cacheDir });
     }
 
-    //Activity act(*logger, lvlInfo, format("fetching Git repository ‘%s’") % uri);
+    //Activity act(*logger, lvlInfo, format("fetching Git repository '%s'") % uri);
 
     std::string localRef = hashString(htSHA256, fmt("%s-%s", uri, ref)).to_string(Base32, false);
 
@@ -62,10 +62,10 @@ Path exportGit(ref<Store> store, const std::string & uri,
     std::string commitHash =
         rev != "" ? rev : chomp(readFile(localRefFile));
 
-    printTalkative("using revision %s of repo ‘%s’", uri, commitHash);
+    printTalkative("using revision %s of repo '%s'", uri, commitHash);
 
     Path storeLink = cacheDir + "/" + commitHash + ".link";
-    PathLocks storeLinkLock({storeLink}, fmt("waiting for lock on ‘%1%’...", storeLink));
+    PathLocks storeLinkLock({storeLink}, fmt("waiting for lock on '%1%'...", storeLink));
 
     if (pathExists(storeLink)) {
         auto storePath = readLink(storeLink);
@@ -94,7 +94,7 @@ Path exportGit(ref<Store> store, const std::string & uri,
 static void prim_fetchgit(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
     // FIXME: cut&paste from fetch().
-    if (state.restricted) throw Error("‘fetchgit’ is not allowed in restricted mode");
+    if (state.restricted) throw Error("'fetchgit' is not allowed in restricted mode");
 
     std::string url;
     std::string ref = "master";
@@ -118,11 +118,11 @@ static void prim_fetchgit(EvalState & state, const Pos & pos, Value * * args, Va
             else if (name == "rev")
                 rev = state.forceStringNoCtx(*attr.value, *attr.pos);
             else
-                throw EvalError("unsupported argument ‘%s’ to ‘fetchgit’, at %s", attr.name, *attr.pos);
+                throw EvalError("unsupported argument '%s' to 'fetchgit', at %s", attr.name, *attr.pos);
         }
 
         if (url.empty())
-            throw EvalError(format("‘url’ argument required, at %1%") % pos);
+            throw EvalError(format("'url' argument required, at %1%") % pos);
 
     } else
         url = state.forceStringNoCtx(*args[0], pos);