diff --git a/qmake/project.cpp b/qmake/project.cpp index de010faeb8..24ea3a0257 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -78,7 +78,7 @@ QT_BEGIN_NAMESPACE //expand functions enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST, - E_SPRINTF, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, + E_SPRINTF, E_FORMAT_NUMBER, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION, E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_ESCAPE_EXPAND, E_UPPER, E_LOWER, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE, E_REPLACE, E_SIZE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS, @@ -97,6 +97,7 @@ QHash qmake_expandFunctions() qmake_expand_functions->insert("eval", E_EVAL); qmake_expand_functions->insert("list", E_LIST); qmake_expand_functions->insert("sprintf", E_SPRINTF); + qmake_expand_functions->insert("format_number", E_FORMAT_NUMBER); qmake_expand_functions->insert("join", E_JOIN); qmake_expand_functions->insert("split", E_SPLIT); qmake_expand_functions->insert("basename", E_BASENAME); @@ -2190,6 +2191,79 @@ QMakeProject::doProjectExpand(QString func, QList args_list, ret = split_value_list(tmp); } break; } + case E_FORMAT_NUMBER: + if (args.count() > 2) { + fprintf(stderr, "%s:%d: format_number(number[, options...]) requires one or two arguments.\n", + parser.file.toLatin1().constData(), parser.line_no); + } else { + int ibase = 10; + int obase = 10; + int width = 0; + bool zeropad = false; + bool leftalign = false; + enum { DefaultSign, PadSign, AlwaysSign } sign = DefaultSign; + if (args.count() >= 2) { + foreach (const QString &opt, split_value_list(args.at(1))) { + if (opt.startsWith(QLatin1String("ibase="))) { + ibase = opt.mid(6).toInt(); + } else if (opt.startsWith(QLatin1String("obase="))) { + obase = opt.mid(6).toInt(); + } else if (opt.startsWith(QLatin1String("width="))) { + width = opt.mid(6).toInt(); + } else if (opt == QLatin1String("zeropad")) { + zeropad = true; + } else if (opt == QLatin1String("padsign")) { + sign = PadSign; + } else if (opt == QLatin1String("alwayssign")) { + sign = AlwaysSign; + } else if (opt == QLatin1String("leftalign")) { + leftalign = true; + } else { + fprintf(stderr, "%s:%d: format_number(): invalid format option %s.\n", + parser.file.toLatin1().constData(), parser.line_no, + opt.toLatin1().constData()); + goto formfail; + } + } + } + if (args.at(0).contains(QLatin1Char('.'))) { + fprintf(stderr, "%s:%d: format_number(): floats are currently not supported.\n", + parser.file.toLatin1().constData(), parser.line_no); + break; + } + bool ok; + qlonglong num = args.at(0).toLongLong(&ok, ibase); + if (!ok) { + fprintf(stderr, "%s:%d: format_number(): malformed number %s for base %d.\n", + parser.file.toLatin1().constData(), parser.line_no, + args.at(0).toLatin1().constData(), ibase); + break; + } + QString outstr; + if (num < 0) { + num = -num; + outstr = QLatin1Char('-'); + } else if (sign == AlwaysSign) { + outstr = QLatin1Char('+'); + } else if (sign == PadSign) { + outstr = QLatin1Char(' '); + } + QString numstr = QString::number(num, obase); + int space = width - outstr.length() - numstr.length(); + if (space <= 0) { + outstr += numstr; + } else if (leftalign) { + outstr += numstr + QString(space, QLatin1Char(' ')); + } else if (zeropad) { + outstr += QString(space, QLatin1Char('0')) + numstr; + } else { + outstr.prepend(QString(space, QLatin1Char(' '))); + outstr += numstr; + } + ret += outstr; + } + formfail: + break; case E_JOIN: { if(args.count() < 1 || args.count() > 4) { fprintf(stderr, "%s:%d: join(var, glue, before, after) requires four" diff --git a/tests/auto/tools/qmake/testdata/functions/functions.pro b/tests/auto/tools/qmake/testdata/functions/functions.pro index 0b70b24158..2972128948 100644 --- a/tests/auto/tools/qmake/testdata/functions/functions.pro +++ b/tests/auto/tools/qmake/testdata/functions/functions.pro @@ -113,3 +113,17 @@ out = "easy \"less easy\" sca\$\${LITERAL_HASH}ry crazy\$\$escape_expand(\\\\t\\ testReplace($$val_escape(in), $$out, "val_escape") testReplace($$shadowed($$PWD/something), $$OUT_PWD/something, "shadowed") + +#format_number +spc = " " +testReplace($$format_number(13), 13, "simple number format") +testReplace($$format_number(-13), -13, "negative number format") +testReplace($$format_number(13, ibase=16), 19, "hex input number format") +testReplace($$format_number(13, obase=16), d, "hex output number format") +testReplace($$format_number(13, width=5), " $$spc 13", "right aligned number format") +testReplace($$format_number(13, width=5 leftalign), "13 $$spc ", "left aligned number format") +testReplace($$format_number(13, width=5 zeropad), "00013", "zero-padded number format") +testReplace($$format_number(13, width=5 alwayssign), "$$spc +13", "always signed number format") +testReplace($$format_number(13, width=5 alwayssign zeropad), "+0013", "zero-padded always signed number format") +testReplace($$format_number(13, width=5 padsign), " $$spc 13", "sign-padded number format") +testReplace($$format_number(13, width=5 padsign zeropad), " 0013", "zero-padded sign-padded number format")