From 759925d8160f9dc9dfbd480035bd8352203f2762 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 14 Nov 2011 15:15:44 +0000 Subject: [PATCH] interim commit while dropping dependence on printf in awk --- qse/include/qse/cmn/fmt.h | 27 ++++++--- qse/lib/awk/run.c | 64 +++++++++++++++++--- qse/lib/awk/tree.c | 1 + qse/lib/cmn/fmt.c | 121 +++++++++++++++++++++++++++++++++----- qse/samples/cmn/fmt01.c | 2 +- qse/samples/cmn/fmt02.c | 24 +++++++- 6 files changed, 203 insertions(+), 36 deletions(-) diff --git a/qse/include/qse/cmn/fmt.h b/qse/include/qse/cmn/fmt.h index 2cba0754..41bba3fd 100644 --- a/qse/include/qse/cmn/fmt.h +++ b/qse/include/qse/cmn/fmt.h @@ -38,20 +38,23 @@ enum qse_fmtintmax_flag_t QSE_FMTINTMAX_NOTRUNC = (0x100 << 0), /** Don't append a terminating null */ QSE_FMTINTMAX_NONULL = (0x100 << 1), + /** Produce no digit for a value of zero */ + QSE_FMTINTMAX_NOZERO = (0x100 << 2), /** Use uppercase letters for alphabetic digits */ - QSE_FMTINTMAX_UPPERCASE = (0x100 << 2), + QSE_FMTINTMAX_UPPERCASE = (0x100 << 3), /** Insert a plus sign for a positive integer including 0 */ - QSE_FMTINTMAX_PLUSSIGN = (0x100 << 3), + QSE_FMTINTMAX_PLUSSIGN = (0x100 << 4), /** Insert a space for a positive integer including 0 */ - QSE_FMTINTMAX_EMPTYSIGN = (0x100 << 4), + QSE_FMTINTMAX_EMPTYSIGN = (0x100 << 5), /** Fill the right part of the string */ - QSE_FMTINTMAX_FILLRIGHT = (0x100 << 5), + QSE_FMTINTMAX_FILLRIGHT = (0x100 << 6), /** Fill between the sign chacter and the digit part */ - QSE_FMTINTMAX_FILLCENTER = (0x100 << 6) + QSE_FMTINTMAX_FILLCENTER = (0x100 << 7) }; #define QSE_FMTINTMAX_NOTRUNC QSE_FMTINTMAX_NOTRUNC #define QSE_FMTINTMAX_NONULL QSE_FMTINTMAX_NONULL +#define QSE_FMTINTMAX_NOZERO QSE_FMTINTMAX_NOZERO #define QSE_FMTINTMAX_UPPERCASE QSE_FMTINTMAX_UPPERCASE #define QSE_FMTINTMAX_PLUSSIGN QSE_FMTINTMAX_PLUSSIGN #define QSE_FMTINTMAX_EMPTYSIGN QSE_FMTINTMAX_EMPTYSIGN @@ -60,6 +63,7 @@ enum qse_fmtintmax_flag_t #define QSE_FMTINTMAXTOMBS_NOTRUNC QSE_FMTINTMAX_NOTRUNC #define QSE_FMTINTMAXTOMBS_NONULL QSE_FMTINTMAX_NONULL +#define QSE_FMTINTMAXTOMBS_NOZERO QSE_FMTINTMAX_NOZERO #define QSE_FMTINTMAXTOMBS_UPPERCASE QSE_FMTINTMAX_UPPERCASE #define QSE_FMTINTMAXTOMBS_PLUSSIGN QSE_FMTINTMAX_PLUSSIGN #define QSE_FMTINTMAXTOMBS_EMPTYSIGN QSE_FMTINTMAX_EMPTYSIGN @@ -68,6 +72,7 @@ enum qse_fmtintmax_flag_t #define QSE_FMTINTMAXTOWCS_NOTRUNC QSE_FMTINTMAX_NOTRUNC #define QSE_FMTINTMAXTOWCS_NONULL QSE_FMTINTMAX_NONULL +#define QSE_FMTINTMAXTOWCS_NOZERO QSE_FMTINTMAX_NOZERO #define QSE_FMTINTMAXTOWCS_UPPERCASE QSE_FMTINTMAX_UPPERCASE #define QSE_FMTINTMAXTOWCS_PLUSSIGN QSE_FMTINTMAX_PLUSSIGN #define QSE_FMTINTMAXTOWCS_EMPTYSIGN QSE_FMTINTMAX_EMPTYSIGN @@ -122,6 +127,7 @@ int qse_fmtintmaxtombs ( int bufsize, /**< buffer size */ qse_intmax_t value, /**< integer to format */ int base_and_flags, /**< base ORed with flags */ + int precision, /**< precision */ qse_mchar_t fillchar, /**< fill character */ const qse_mchar_t* prefix /**< prefix */ ); @@ -170,6 +176,7 @@ int qse_fmtintmaxtowcs ( int bufsize, /**< buffer size */ qse_intmax_t value, /**< integer to format */ int base_and_flags, /**< base ORed with flags */ + int precision, /**< precision */ qse_wchar_t fillchar, /**< fill character */ const qse_wchar_t* prefix /**< prefix */ ); @@ -179,9 +186,9 @@ int qse_fmtintmaxtowcs ( * #QSE_CHAR_IS_MCHAR, and qse_fmtintmaxtowcs() if #QSE_CHAR_IS_WCHAR. */ #ifdef QSE_CHAR_IS_MCHAR -# define qse_fmtintmax(b,sz,v,bf,fc,pf) qse_fmtintmaxtombs(b,sz,v,bf,fc,pf) +# define qse_fmtintmax(b,sz,v,bf,pr,fc,pf) qse_fmtintmaxtombs(b,sz,v,bf,pr,fc,pf) #else -# define qse_fmtintmax(b,sz,v,bf,fc,pf) qse_fmtintmaxtowcs(b,sz,v,bf,fc,pf) +# define qse_fmtintmax(b,sz,v,bf,pr,fc,pf) qse_fmtintmaxtowcs(b,sz,v,bf,pr,fc,pf) #endif /** @@ -194,6 +201,7 @@ int qse_fmtuintmaxtombs ( int bufsize, /**< buffer size */ qse_uintmax_t value, /**< integer to format */ int base_and_flags, /**< base ORed with flags */ + int precision, /**< precision */ qse_mchar_t fillchar, /**< fill character */ const qse_mchar_t* prefix /**< prefix */ ); @@ -208,6 +216,7 @@ int qse_fmtuintmaxtowcs ( int bufsize, /**< buffer size */ qse_uintmax_t value, /**< integer to format */ int base_and_flags, /**< base ORed with flags */ + int precision, /**< precision */ qse_wchar_t fillchar, /**< fill character */ const qse_wchar_t* prefix /**< prefix */ ); @@ -217,9 +226,9 @@ int qse_fmtuintmaxtowcs ( * #QSE_CHAR_IS_MCHAR, and qse_fmtuintmaxtowcs() if #QSE_CHAR_IS_WCHAR. */ #ifdef QSE_CHAR_IS_MCHAR -# define qse_fmtuintmax(b,sz,v,bf,fc,pf) qse_fmtuintmaxtombs(b,sz,v,bf,fc,pf) +# define qse_fmtuintmax(b,sz,v,bf,pr,fc,pf) qse_fmtuintmaxtombs(b,sz,v,bf,pr,fc,pf) #else -# define qse_fmtuintmax(b,sz,v,bf,fc,pf) qse_fmtuintmaxtowcs(b,sz,v,bf,fc,pf) +# define qse_fmtuintmax(b,sz,v,bf,pr,fc,pf) qse_fmtuintmaxtowcs(b,sz,v,bf,pr,fc,pf) #endif #ifdef __cplusplus diff --git a/qse/lib/awk/run.c b/qse/lib/awk/run.c index 576db0c5..ac9537cf 100644 --- a/qse/lib/awk/run.c +++ b/qse/lib/awk/run.c @@ -6873,6 +6873,7 @@ wp_mod_main: rtx->format.tmp.len, wp[wp_idx], 10 | QSE_FMTINTMAX_NOTRUNC | QSE_FMTINTMAX_NONULL, + -1, QSE_T('\0'), QSE_NULL ); @@ -6968,18 +6969,30 @@ int fmt_uint = 0; qse_char_t fmt_fill = QSE_T('\0'); const qse_char_t* fmt_prefix = QSE_NULL; +// TODO: WP_WIDTH... + fmt_flags = QSE_FMTINTMAX_NOTRUNC | QSE_FMTINTMAX_NONULL; + if (l == 0 && wp[WP_PRECISION] == 0) { + /* A zero value with a precision of zero produces + * no character. */ + fmt_flags |= QSE_FMTINTMAX_NOZERO; } - fmt_flags = QSE_FMTINTMAX_NOTRUNC | QSE_FMTINTMAX_NONULL; - if (flags & FLAG_ZERO) + if ((flags & FLAG_ZERO) && + wp[WP_PRECISION] == -1 && + !(flag & FLAG_MINUS)) { + /* if precision is set or the minum flag is set, + the zero flag is not honored */ fmt_fill = QSE_T('0'); } else { - if (!(flags & FLAG_MINUS)) fmt_flags |= QSE_FMTINTMAX_FILLCENTER; +/* minus is left justificatin. +meaningful iif width is set */ + if (!(flags & FLAG_MINUS)) + fmt_flags |= QSE_FMTINTMAX_FILLCENTER; } switch (fmt[i]) @@ -6989,32 +7002,62 @@ const qse_char_t* fmt_prefix = QSE_NULL; case QSE_T('x'): fmt_flags |= 16; fmt_uint = 1; - if (l && (flags & FLAG_HASH)) fmt_prefix = QSE_T("0x"); + + if (l && (flags & FLAG_HASH)) + { + /* A nonzero value is prefixed with 0x */ + fmt_prefix = QSE_T("0x"); + } break; case QSE_T('o'): + fmt_flags &= ~QSE_FMTINTMAX_NOZERO; /* weird */ fmt_flags |= 8; fmt_uint = 1; - if (l && (flags & FLAG_HASH)) fmt_prefix = QSE_T("0"); + if (l && (flags & FLAG_HASH)) + { + /* The precision is increased + (only when necessary) + to force a zero as the first digit. */ + fmt_prefix = QSE_T("0"); + } break; default: fmt_flags |= 10; - if (flags & FLAG_PLUS) fmt_flags |= QSE_FMTINTMAX_PLUSSIGN; - if (flags & FLAG_SPACE) fmt_flags |= QSE_FMTINTMAX_EMPTYSIGN; + if (flags & FLAG_PLUS) + fmt_flags |= QSE_FMTINTMAX_PLUSSIGN; + if (flags & FLAG_SPACE) + fmt_flags |= QSE_FMTINTMAX_EMPTYSIGN; break; } -qse_printf (QSE_T("width=>%d precision=%d\n"), wp[0], wp[1]); do { if (fmt_uint) { + /* Explicit type-casting for 'l' from qse_long_t + * to qse_ulong_t is needed before passing it to + * qse_fmtuintmax(). + * + * Consider a value of -1 for example. + * -1 is a value with all bits set. + * If qse_long_t is 4 bytes and qse_uintmax_t + * is 8 bytes, the value is shown below for + * each type respectively . + * -1 - 0xFFFFFFFF (qse_long_t) + * -1 - 0xFFFFFFFFFFFFFFFF (qse_uintmax_t) + * + * Implicit typecasting of -1 from qse_long_t to + * to qse_uintmax_t results in 0xFFFFFFFFFFFFFFFF, + * though 0xFFFFFFF is expected in hexadecimal. + */ n = qse_fmtuintmax ( rtx->format.tmp.ptr, rtx->format.tmp.len, - l, + (qse_ulong_t)l, fmt_flags, + wp[WP_PRECISION], fmt_fill, fmt_prefix ); @@ -7026,6 +7069,7 @@ qse_printf (QSE_T("width=>%d precision=%d\n"), wp[0], wp[1]); rtx->format.tmp.len, l, fmt_flags, + wp[WP_PRECISION], fmt_fill, fmt_prefix ); @@ -7046,6 +7090,7 @@ qse_printf (QSE_T("width=>%d precision=%d\n"), wp[0], wp[1]); } #endif +#if 1 #if QSE_SIZEOF_LONG_LONG > 0 FMT_CHAR (QSE_T('l')); FMT_CHAR (QSE_T('l')); @@ -7093,6 +7138,7 @@ qse_printf (QSE_T("width=>%d precision=%d\n"), wp[0], wp[1]); while (1); OUT_STR (rtx->format.tmp.ptr, n); +#endif } else if (fmt[i] == QSE_T('e') || fmt[i] == QSE_T('E') || fmt[i] == QSE_T('g') || fmt[i] == QSE_T('G') || diff --git a/qse/lib/awk/tree.c b/qse/lib/awk/tree.c index 17692efb..159bf4e6 100644 --- a/qse/lib/awk/tree.c +++ b/qse/lib/awk/tree.c @@ -285,6 +285,7 @@ static int print_expr (qse_awk_t* awk, qse_awk_nde_t* nde) buf, QSE_COUNTOF(buf), ((qse_awk_nde_int_t*)nde)->val, 10, + -1, QSE_T('\0'), QSE_NULL ); diff --git a/qse/lib/cmn/fmt.c b/qse/lib/cmn/fmt.c index 89f35a3b..d3a26194 100644 --- a/qse/lib/cmn/fmt.c +++ b/qse/lib/cmn/fmt.c @@ -24,7 +24,7 @@ /* ==================== multibyte ===================================== */ static int fmt_unsigned_to_mbs ( qse_mchar_t* buf, int size, - qse_uintmax_t value, int base_and_flags, + qse_uintmax_t value, int base_and_flags, int prec, qse_mchar_t fillchar, qse_mchar_t signchar, const qse_mchar_t* prefix) { qse_mchar_t tmp[(QSE_SIZEOF(qse_uintmax_t) * 8)]; @@ -145,7 +145,7 @@ static int fmt_unsigned_to_mbs ( int qse_fmtintmaxtombs ( qse_mchar_t* buf, int size, - qse_intmax_t value, int base_and_flags, + qse_intmax_t value, int base_and_flags, int prec, qse_mchar_t fillchar, const qse_mchar_t* prefix) { qse_mchar_t signchar; @@ -172,12 +172,13 @@ int qse_fmtintmaxtombs ( absvalue = value; } - return fmt_unsigned_to_mbs (buf, size, absvalue, base_and_flags, fillchar, signchar, prefix); + return fmt_unsigned_to_mbs ( + buf, size, absvalue, base_and_flags, prec, fillchar, signchar, prefix); } int qse_fmtuintmaxtombs ( qse_mchar_t* buf, int size, - qse_uintmax_t value, int base_and_flags, + qse_uintmax_t value, int base_and_flags, int prec, qse_mchar_t fillchar, const qse_mchar_t* prefix) { qse_mchar_t signchar; @@ -196,7 +197,8 @@ int qse_fmtuintmaxtombs ( signchar = QSE_MT('\0'); } - return fmt_unsigned_to_mbs (buf, size, value, base_and_flags, fillchar, signchar, prefix); + return fmt_unsigned_to_mbs ( + buf, size, value, base_and_flags, prec, fillchar, signchar, prefix); } @@ -204,11 +206,11 @@ int qse_fmtuintmaxtombs ( static int fmt_unsigned_to_wcs ( qse_wchar_t* buf, int size, - qse_uintmax_t value, int base_and_flags, + qse_uintmax_t value, int base_and_flags, int prec, qse_wchar_t fillchar, qse_wchar_t signchar, const qse_wchar_t* prefix) { qse_wchar_t tmp[(QSE_SIZEOF(qse_uintmax_t) * 8)]; - int reslen, base, xsize, reqlen, pflen; + int reslen, base, xsize, reqlen, pflen, preczero; qse_wchar_t* p, * bp, * be; const qse_wchar_t* xbasestr; @@ -219,6 +221,15 @@ static int fmt_unsigned_to_wcs ( QSE_WT("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"): QSE_WT("0123456789abcdefghijklmnopqrstuvwxyz"); +/*if (prec == 0 && value == 0) */ +if ((base_and_flags & QSE_FMTINTMAXTOWCS_NOZERO) && value == 0) +{ + reslen = 0; + preczero = 0; + p = tmp; +} +else +{ /* store the resulting numeric string into 'tmp' first */ p = tmp; do @@ -230,14 +241,30 @@ static int fmt_unsigned_to_wcs ( /* reslen is the length of the resulting string without padding. */ reslen = (int)(p - tmp); + + /* precision specified the minum number of digits to produce. + * so if the precision is larger that the digits produced, + * reslen should be adjusted to precision */ + if (prec > reslen) + { + preczero = prec - reslen; + reslen = prec; + } + else + { + preczero = 0; + } +} + if (signchar) reslen++; /* increment reslen for the sign character */ if (prefix) { /* since the length can be truncated for different type sizes, * don't pass in a very long prefix. */ - pflen = (int)qse_wcslen(prefix); + pflen = (int)qse_wcslen(prefix); reslen += pflen; } + else pflen = 0; /* get the required buffer size for lossless formatting */ reqlen = (base_and_flags & QSE_FMTINTMAXTOWCS_NONULL)? reslen: (reslen + 1); @@ -248,6 +275,7 @@ static int fmt_unsigned_to_wcs ( return -reqlen; } + /* get the size to fill with fill characters */ xsize = (base_and_flags & QSE_FMTINTMAXTOWCS_NONULL)? size: (size - 1); bp = buf; be = buf + xsize; @@ -261,7 +289,22 @@ static int fmt_unsigned_to_wcs ( if (signchar && bp < be) *bp++ = signchar; /* copy prefix if necessary */ - if (prefix) while (*prefix && bp < be) *bp++ = *prefix++; + if (prefix) + { +/*if (preczero > 0 && pflen == 1 && prefix[0] == QSE_WT('0')) goto skip; */ +if (preczero <= 0 || pflen != 1 || prefix[0] != QSE_WT('0')) +{ + while (*prefix && bp < be) *bp++ = *prefix++; +} + } + + /* add 0s for precision */ + while (preczero > 0 && bp < be) + { + *bp++ = QSE_T('0'); + preczero--; + } + /* copy the numeric string to the destination buffer */ while (p > tmp && bp < be) *bp++ = *--p; @@ -285,7 +328,22 @@ static int fmt_unsigned_to_wcs ( } /* copy prefix if necessary */ - if (prefix) while (*prefix && bp < be) *bp++ = *prefix++; + if (prefix) + { +/*if (preczero > 0 && pflen == 1 && prefix[0] == QSE_WT('0')) goto skip; */ +if (preczero <= 0 || pflen != 1 || prefix[0] != QSE_WT('0')) +{ + while (*prefix && bp < be) *bp++ = *prefix++; +} + } + + /* add 0s for precision */ + while (preczero > 0 && bp < be) + { + *bp++ = QSE_T('0'); + preczero--; + } + /* copy the numeric string to the destination buffer */ while (p > tmp && bp < be) *bp++ = *--p; } @@ -302,7 +360,22 @@ static int fmt_unsigned_to_wcs ( if (signchar && bp < be) *bp++ = signchar; /* copy prefix if necessary */ - if (prefix) while (*prefix && bp < be) *bp++ = *prefix++; + if (prefix) + { +/*if (preczero > 0 && pflen == 1 && prefix[0] == QSE_WT('0')) goto skip; */ +if (preczero <= 0 || pflen != 1 || prefix[0] != QSE_WT('0')) +{ + while (*prefix && bp < be) *bp++ = *prefix++; +} + } + + /* add 0s for precision */ + while (preczero > 0 && bp < be) + { + *bp++ = QSE_T('0'); + preczero--; + } + /* copy the numeric string to the destination buffer */ while (p > tmp && bp < be) *bp++ = *--p; } @@ -313,7 +386,21 @@ static int fmt_unsigned_to_wcs ( if (signchar && bp < be) *bp++ = signchar; /* copy prefix if necessary */ - if (prefix) while (*prefix && bp < be) *bp++ = *prefix++; + if (prefix) + { +if (preczero <= 0 || pflen != 1 || prefix[0] != QSE_WT('0')) +{ + while (*prefix && bp < be) *bp++ = *prefix++; +} + } + + /* add 0s for precision */ + while (preczero > 0 && bp < be) + { + *bp++ = QSE_T('0'); + preczero--; + } + /* copy the numeric string to the destination buffer */ while (p > tmp && bp < be) *bp++ = *--p; } @@ -324,7 +411,7 @@ static int fmt_unsigned_to_wcs ( int qse_fmtintmaxtowcs ( qse_wchar_t* buf, int size, - qse_intmax_t value, int base_and_flags, + qse_intmax_t value, int base_and_flags, int prec, qse_wchar_t fillchar, const qse_wchar_t* prefix) { qse_wchar_t signchar; @@ -351,12 +438,13 @@ int qse_fmtintmaxtowcs ( absvalue = value; } - return fmt_unsigned_to_wcs (buf, size, absvalue, base_and_flags, fillchar, signchar, prefix); + return fmt_unsigned_to_wcs ( + buf, size, absvalue, base_and_flags, prec, fillchar, signchar, prefix); } int qse_fmtuintmaxtowcs ( qse_wchar_t* buf, int size, - qse_uintmax_t value, int base_and_flags, + qse_uintmax_t value, int base_and_flags, int prec, qse_wchar_t fillchar, const qse_wchar_t* prefix) { qse_wchar_t signchar; @@ -375,6 +463,7 @@ int qse_fmtuintmaxtowcs ( signchar = QSE_WT('\0'); } - return fmt_unsigned_to_wcs (buf, size, value, base_and_flags, fillchar, signchar, prefix); + return fmt_unsigned_to_wcs ( + buf, size, value, base_and_flags, prec, fillchar, signchar, prefix); } diff --git a/qse/samples/cmn/fmt01.c b/qse/samples/cmn/fmt01.c index eb7da95b..97f9f836 100644 --- a/qse/samples/cmn/fmt01.c +++ b/qse/samples/cmn/fmt01.c @@ -33,7 +33,7 @@ static int test_main (int argc, qse_char_t* argv[], qse_char_t* envp[]) { for (j = 0; j < QSE_COUNTOF(flags); j++) { - int n = qse_fmtuintmax (buf, QSE_COUNTOF(buf), num, bases[i] | flags[j], QSE_T('.'), prefix[i]); + int n = qse_fmtuintmax (buf, QSE_COUNTOF(buf), num, bases[i] | flags[j], -1, QSE_T('.'), prefix[i]); if (n <= -1) { qse_printf (QSE_T("%8X => [%4d:%04X] ERROR[%d]\n"), num, bases[i], flags[j], n); diff --git a/qse/samples/cmn/fmt02.c b/qse/samples/cmn/fmt02.c index 7eb98998..fcefff28 100644 --- a/qse/samples/cmn/fmt02.c +++ b/qse/samples/cmn/fmt02.c @@ -22,13 +22,35 @@ static int test_main (int argc, qse_char_t* argv[], qse_char_t* envp[]) */ + qse_printf (QSE_T("[PRECISION -1]\n")); for (k = 0; k < QSE_COUNTOF(nums) ; k++) { for (i = 0; i < QSE_COUNTOF(bases); i++) { for (j = 0; j < QSE_COUNTOF(flags); j++) { - int n = qse_fmtintmax (buf, QSE_COUNTOF(buf), nums[k], bases[i] | flags[j] | QSE_FMTINTMAX_NOTRUNC, QSE_T('.'), prefix[i]); + int n = qse_fmtintmax (buf, QSE_COUNTOF(buf), nums[k], bases[i] | flags[j] | QSE_FMTINTMAX_NOTRUNC, -1, QSE_T('.'), prefix[i]); + if (n <= -1) + { + qse_printf (QSE_T("%8d => [%4d:%04X] ERROR[%d]\n"), (int)nums[k], bases[i], flags[j], n); + } + else + { + qse_printf (QSE_T("%8d => [%4d:%04X] [%s]\n"), (int)nums[k], bases[i], flags[j], buf); + } + } + } + qse_printf (QSE_T("------------------------------\n")); + } + + qse_printf (QSE_T("[PRECISION 0]\n")); + for (k = 0; k < QSE_COUNTOF(nums) ; k++) + { + for (i = 0; i < QSE_COUNTOF(bases); i++) + { + for (j = 0; j < QSE_COUNTOF(flags); j++) + { + int n = qse_fmtintmax (buf, QSE_COUNTOF(buf), nums[k], bases[i] | flags[j] | QSE_FMTINTMAX_NOTRUNC | QSE_FMTINTMAX_NOZERO, 0, QSE_T('*'), prefix[i]); if (n <= -1) { qse_printf (QSE_T("%8d => [%4d:%04X] ERROR[%d]\n"), (int)nums[k], bases[i], flags[j], n);