diff --git a/ChangeLog b/ChangeLog index e22fb960e7..d646af8472 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,29 @@ * stdlib/Makefile: Add rules to build and run tst-makecontext2. * stdlib/tst-makecontext2.c: New test. +008-01-08 Jakub Jelinek + + * iconv/loop.c (UPDATE_PARAMS): Define to empty statement if not + defined. + (REINIT_PARAMS): Likewise. Undefine before end of file. + (STANDARD_TO_LOOP_ERR_HANDLER): Use UPDATE_PARAMS before calling + transliteration hooks and REINIT_PARAMS afterwards. + * iconvdata/iso-2022-jp.c (BODY): Use a separate variable for + status. + (REINIT_PARAMS): Define. + * iconvdata/ibm1364.c (REINIT_PARAMS): Likewise. + * iconvdata/ibm930.c (REINIT_PARAMS): Likewise. + * iconvdata/ibm933.c (REINIT_PARAMS): Likewise. + * iconvdata/ibm935.c (REINIT_PARAMS): Likewise. + * iconvdata/ibm937.c (REINIT_PARAMS): Likewise. + * iconvdata/ibm939.c (REINIT_PARAMS): Likewise. + * iconvdata/iso-2022-cn.c (REINIT_PARAMS): Likewise. + * iconvdata/iso-2022-cn-ext.c (REINIT_PARAMS): Likewise. + * iconvdata/iso-2022-jp-3.c (REINIT_PARAMS): Likewise. + * iconvdata/iso-2022-kr.c (REINIT_PARAMS): Likewise. + * iconvdata/Makefile: Add rules to build and run tst-iconv7.c. + * iconvdata/tst-iconv7.c: New test. + 2008-01-07 Ulrich Drepper * libio/stdio.h (vscanf): Fix definition for loser compilers. diff --git a/iconv/loop.c b/iconv/loop.c index df8c8dce9f..da11bc209d 100644 --- a/iconv/loop.c +++ b/iconv/loop.c @@ -1,5 +1,5 @@ /* Conversion loop frame work. - Copyright (C) 1998-2002, 2003, 2005 Free Software Foundation, Inc. + Copyright (C) 1998-2002, 2003, 2005, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1998. @@ -174,6 +174,15 @@ # define EXTRA_LOOP_DECLS #endif +/* Allow using UPDATE_PARAMS in macros where #ifdef UPDATE_PARAMS test + isn't possible. */ +#ifndef UPDATE_PARAMS +# define UPDATE_PARAMS do { } while (0) +#endif +#ifndef REINIT_PARAMS +# define REINIT_PARAMS do { } while (0) +#endif + /* To make it easier for the writers of the modules, we define a macro to test whether we have to ignore errors. */ @@ -214,6 +223,10 @@ case we are not doing any error recovery outself. */ \ break; \ \ + /* If needed, flush any conversion state, so that __gconv_transliterate \ + starts with current shift state. */ \ + UPDATE_PARAMS; \ + \ /* First try the transliteration methods. */ \ for (trans = step_data->__trans; trans != NULL; trans = trans->__next) \ { \ @@ -223,6 +236,9 @@ if (result != __GCONV_ILLEGAL_INPUT) \ break; \ } \ + \ + REINIT_PARAMS; \ + \ /* If any of them recognized the input continue with the loop. */ \ if (result != __GCONV_ILLEGAL_INPUT) \ { \ @@ -319,9 +335,7 @@ FCTNAME (LOOPFCT) (struct __gconv_step *step, /* Update the pointers pointed to by the parameters. */ *inptrp = inptr; *outptrp = outptr; -#ifdef UPDATE_PARAMS UPDATE_PARAMS; -#endif return result; } @@ -492,6 +506,7 @@ gconv_btowc (struct __gconv_step *step, unsigned char c) #undef EXTRA_LOOP_DECLS #undef INIT_PARAMS #undef UPDATE_PARAMS +#undef REINIT_PARAMS #undef ONEBYTE_BODY #undef UNPACK_BYTES #undef CLEAR_STATE diff --git a/iconvdata/Makefile b/iconvdata/Makefile index 4ac5de30e5..1a46a64ccd 100644 --- a/iconvdata/Makefile +++ b/iconvdata/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1997-2004,2005,2006,2007 Free Software Foundation, Inc. +# Copyright (C) 1997-2004,2005,2006,2007,2008 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -67,7 +67,7 @@ include ../Makeconfig ifeq (yes,$(build-shared)) tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ - tst-iconv6 bug-iconv5 bug-iconv6 + tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 ifeq ($(have-thread-library),yes) tests += bug-iconv3 endif @@ -365,6 +365,8 @@ $(objpfx)tst-loading.out: $(objpfx)gconv-modules \ $(addprefix $(objpfx),$(modules.so)) $(objpfx)tst-iconv4.out: $(objpfx)gconv-modules \ $(addprefix $(objpfx),$(modules.so)) +$(objpfx)tst-iconv7.out: $(objpfx)gconv-modules \ + $(addprefix $(objpfx),$(modules.so)) $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \ $(addprefix $(objpfx),$(modules.so)) \ diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c index 1d46cf6dfb..6881341c43 100644 --- a/iconvdata/ibm1364.c +++ b/iconvdata/ibm1364.c @@ -1,5 +1,5 @@ /* Conversion from and to IBM1364. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Masahide Washizawa , 2005. @@ -387,6 +387,7 @@ enum #define LOOP_NEED_FLAGS #define EXTRA_LOOP_DECLS , int *curcsp #define INIT_PARAMS int curcs = *curcsp & ~7 +#define REINIT_PARAMS curcs = *curcsp & ~7 #define UPDATE_PARAMS *curcsp = curcs #include diff --git a/iconvdata/ibm930.c b/iconvdata/ibm930.c index f5e2cb1dd3..67d07918fb 100644 --- a/iconvdata/ibm930.c +++ b/iconvdata/ibm930.c @@ -1,5 +1,5 @@ /* Conversion from and to IBM930. - Copyright (C) 2000-2002 Free Software Foundation, Inc. + Copyright (C) 2000-2002, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Masahide Washizawa , 2000. @@ -277,6 +277,7 @@ enum #define LOOP_NEED_FLAGS #define EXTRA_LOOP_DECLS , int *curcsp #define INIT_PARAMS int curcs = *curcsp & ~7 +#define REINIT_PARAMS curcs = *curcsp & ~7 #define UPDATE_PARAMS *curcsp = curcs #include diff --git a/iconvdata/ibm933.c b/iconvdata/ibm933.c index 389028ebc4..db822eaab1 100644 --- a/iconvdata/ibm933.c +++ b/iconvdata/ibm933.c @@ -1,5 +1,5 @@ /* Conversion from and to IBM933. - Copyright (C) 2000-2002 Free Software Foundation, Inc. + Copyright (C) 2000-2002, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Masahide Washizawa , 2000. @@ -272,6 +272,7 @@ enum #define LOOP_NEED_FLAGS #define EXTRA_LOOP_DECLS , int *curcsp #define INIT_PARAMS int curcs = *curcsp & ~7 +#define REINIT_PARAMS curcs = *curcsp & ~7 #define UPDATE_PARAMS *curcsp = curcs #include diff --git a/iconvdata/ibm935.c b/iconvdata/ibm935.c index 647573945f..5b9af9ae82 100644 --- a/iconvdata/ibm935.c +++ b/iconvdata/ibm935.c @@ -1,5 +1,5 @@ /* Conversion from and to IBM935 - Copyright (C) 2000-2002 Free Software Foundation, Inc. + Copyright (C) 2000-2002, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Masahide Washizawa , 2000. @@ -272,6 +272,7 @@ enum #define LOOP_NEED_FLAGS #define EXTRA_LOOP_DECLS , int *curcsp #define INIT_PARAMS int curcs = *curcsp & ~7 +#define REINIT_PARAMS curcs = *curcsp & ~7 #define UPDATE_PARAMS *curcsp = curcs #include diff --git a/iconvdata/ibm937.c b/iconvdata/ibm937.c index 2d46115942..52f7aeaffc 100644 --- a/iconvdata/ibm937.c +++ b/iconvdata/ibm937.c @@ -1,5 +1,5 @@ /* Conversion from and to IBM937. - Copyright (C) 2000-2002 Free Software Foundation, Inc. + Copyright (C) 2000-2002, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Masahide Washizawa , 2000. @@ -272,6 +272,7 @@ enum #define LOOP_NEED_FLAGS #define EXTRA_LOOP_DECLS , int *curcsp #define INIT_PARAMS int curcs = *curcsp & ~7 +#define REINIT_PARAMS curcs = *curcsp & ~7 #define UPDATE_PARAMS *curcsp = curcs #include diff --git a/iconvdata/ibm939.c b/iconvdata/ibm939.c index 50b083f492..9f3a3632bf 100644 --- a/iconvdata/ibm939.c +++ b/iconvdata/ibm939.c @@ -1,5 +1,5 @@ /* Conversion to and from IBM939. - Copyright (C) 2000-2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2000-2002, 2005, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Masahide Washizawa , 2000. @@ -277,6 +277,7 @@ enum #define LOOP_NEED_FLAGS #define EXTRA_LOOP_DECLS , int *curcsp #define INIT_PARAMS int curcs = *curcsp & ~7 +#define REINIT_PARAMS curcs = *curcsp & ~7 #define UPDATE_PARAMS *curcsp = curcs #include diff --git a/iconvdata/iso-2022-cn-ext.c b/iconvdata/iso-2022-cn-ext.c index fd02d63592..3ffaf19881 100644 --- a/iconvdata/iso-2022-cn-ext.c +++ b/iconvdata/iso-2022-cn-ext.c @@ -1,5 +1,5 @@ /* Conversion module for ISO-2022-CN-EXT. - Copyright (C) 2000-2002, 2004, 2007 Free Software Foundation, Inc. + Copyright (C) 2000-2002, 2004, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2000. @@ -648,6 +648,12 @@ enum #define EXTRA_LOOP_DECLS , int *setp #define INIT_PARAMS int set = (*setp >> 3) & CURRENT_MASK; \ int ann = (*setp >> 3) & ~CURRENT_MASK +#define REINIT_PARAMS do \ + { \ + set = (*setp >> 3) & CURRENT_MASK; \ + ann = (*setp >> 3) & ~CURRENT_MASK; \ + } \ + while (0) #define UPDATE_PARAMS *setp = (set | ann) << 3 #define LOOP_NEED_FLAGS #include diff --git a/iconvdata/iso-2022-cn.c b/iconvdata/iso-2022-cn.c index 1613cf2329..7247dd2c4e 100644 --- a/iconvdata/iso-2022-cn.c +++ b/iconvdata/iso-2022-cn.c @@ -1,5 +1,5 @@ /* Conversion module for ISO-2022-CN. - Copyright (C) 1999, 2000-2002, 2007 Free Software Foundation, Inc. + Copyright (C) 1999, 2000-2002, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1999. @@ -393,6 +393,12 @@ enum #define EXTRA_LOOP_DECLS , int *setp #define INIT_PARAMS int set = *setp & CURRENT_SEL_MASK; \ int ann = *setp & CURRENT_ANN_MASK +#define REINIT_PARAMS do \ + { \ + set = *setp & CURRENT_SEL_MASK; \ + ann = *setp & CURRENT_ANN_MASK; \ + } \ + while (0) #define UPDATE_PARAMS *setp = set | ann #include diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c index bbccc2e965..7df8ea14ea 100644 --- a/iconvdata/iso-2022-jp-3.c +++ b/iconvdata/iso-2022-jp-3.c @@ -1,5 +1,6 @@ /* Conversion module for ISO-2022-JP-3. - Copyright (C) 1998-1999, 2000-2002, 2004 Free Software Foundation, Inc. + Copyright (C) 1998-1999, 2000-2002, 2004, 2008 + Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1998, and Bruno Haible , 2002. @@ -759,6 +760,12 @@ static const struct #define EXTRA_LOOP_DECLS , int *statep #define INIT_PARAMS int set = *statep & CURRENT_SEL_MASK; \ uint32_t lasttwo = *statep >> 6 +#define REINIT_PARAMS do \ + { \ + set = *statep & CURRENT_SEL_MASK; \ + lasttwo = *statep >> 6; \ + } \ + while (0) #define UPDATE_PARAMS *statep = set | (lasttwo << 6) #include diff --git a/iconvdata/iso-2022-jp.c b/iconvdata/iso-2022-jp.c index a9612e99ab..e14b79615b 100644 --- a/iconvdata/iso-2022-jp.c +++ b/iconvdata/iso-2022-jp.c @@ -715,8 +715,7 @@ static const cvlist_t conversion_lists[4] = list that depends on the current language tag. */ \ cvlist_t conversion_list; \ unsigned char buf[2]; \ - \ - result = __GCONV_ILLEGAL_INPUT; \ + int res = __GCONV_ILLEGAL_INPUT; \ \ if (var == iso2022jp2) \ conversion_list = conversion_lists[tag >> 8]; \ @@ -735,7 +734,7 @@ static const cvlist_t conversion_lists[4] = { \ if (__builtin_expect (outptr + 3 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = ESC; \ @@ -746,13 +745,13 @@ static const cvlist_t conversion_lists[4] = \ if (__builtin_expect (outptr + 3 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = ESC; \ *outptr++ = 'N'; \ *outptr++ = ch - 0x80; \ - result = __GCONV_OK; \ + res = __GCONV_OK; \ break; \ } \ \ @@ -774,7 +773,7 @@ static const cvlist_t conversion_lists[4] = if (__builtin_expect (outptr + 3 > outend, \ 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = ESC; \ @@ -785,13 +784,13 @@ static const cvlist_t conversion_lists[4] = \ if (__builtin_expect (outptr + 3 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = ESC; \ *outptr++ = 'N'; \ *outptr++ = res; \ - result = __GCONV_OK; \ + res = __GCONV_OK; \ break; \ } \ } \ @@ -810,7 +809,7 @@ static const cvlist_t conversion_lists[4] = { \ if (__builtin_expect (outptr + 3 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = ESC; \ @@ -821,11 +820,11 @@ static const cvlist_t conversion_lists[4] = \ if (__builtin_expect (outptr + 1 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = buf[0]; \ - result = __GCONV_OK; \ + res = __GCONV_OK; \ break; \ } \ \ @@ -837,7 +836,7 @@ static const cvlist_t conversion_lists[4] = { \ if (__builtin_expect (outptr + 3 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = ESC; \ @@ -848,12 +847,12 @@ static const cvlist_t conversion_lists[4] = \ if (__builtin_expect (outptr + 2 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = buf[0]; \ *outptr++ = buf[1]; \ - result = __GCONV_OK; \ + res = __GCONV_OK; \ break; \ } \ \ @@ -869,7 +868,7 @@ static const cvlist_t conversion_lists[4] = { \ if (__builtin_expect (outptr + 4 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = ESC; \ @@ -881,12 +880,12 @@ static const cvlist_t conversion_lists[4] = \ if (__builtin_expect (outptr + 2 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = buf[0]; \ *outptr++ = buf[1]; \ - result = __GCONV_OK; \ + res = __GCONV_OK; \ break; \ } \ \ @@ -903,7 +902,7 @@ static const cvlist_t conversion_lists[4] = { \ if (__builtin_expect (outptr + 3 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = ESC; \ @@ -914,12 +913,12 @@ static const cvlist_t conversion_lists[4] = \ if (__builtin_expect (outptr + 2 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = buf[0]; \ *outptr++ = buf[1]; \ - result = __GCONV_OK; \ + res = __GCONV_OK; \ break; \ } \ \ @@ -936,7 +935,7 @@ static const cvlist_t conversion_lists[4] = { \ if (__builtin_expect (outptr + 4 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = ESC; \ @@ -948,12 +947,12 @@ static const cvlist_t conversion_lists[4] = \ if (__builtin_expect (outptr + 2 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = buf[0]; \ *outptr++ = buf[1]; \ - result = __GCONV_OK; \ + res = __GCONV_OK; \ break; \ } \ \ @@ -972,7 +971,7 @@ static const cvlist_t conversion_lists[4] = { \ if (__builtin_expect (outptr + 3 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = ESC; \ @@ -983,11 +982,11 @@ static const cvlist_t conversion_lists[4] = \ if (__builtin_expect (outptr + 1 > outend, 0)) \ { \ - result = __GCONV_FULL_OUTPUT; \ + res = __GCONV_FULL_OUTPUT; \ break; \ } \ *outptr++ = buf[0] - 0x80; \ - result = __GCONV_OK; \ + res = __GCONV_OK; \ break; \ } \ \ @@ -996,13 +995,16 @@ static const cvlist_t conversion_lists[4] = default: \ abort (); \ } \ - while (result == __GCONV_ILLEGAL_INPUT \ + while (res == __GCONV_ILLEGAL_INPUT \ && (conversion_list = CVLIST_REST (conversion_list)) != 0);\ \ - if (result == __GCONV_FULL_OUTPUT) \ - break; \ + if (res == __GCONV_FULL_OUTPUT) \ + { \ + result = res; \ + break; \ + } \ \ - if (result == __GCONV_ILLEGAL_INPUT) \ + if (res == __GCONV_ILLEGAL_INPUT) \ { \ STANDARD_TO_LOOP_ERR_HANDLER (4); \ } \ @@ -1017,6 +1019,13 @@ static const cvlist_t conversion_lists[4] = #define INIT_PARAMS int set = *setp & CURRENT_SEL_MASK; \ int set2 = *setp & CURRENT_ASSIGN_MASK; \ int tag = *setp & CURRENT_TAG_MASK; +#define REINIT_PARAMS do \ + { \ + set = *setp & CURRENT_SEL_MASK; \ + set2 = *setp & CURRENT_ASSIGN_MASK; \ + tag = *setp & CURRENT_TAG_MASK; \ + } \ + while (0) #define UPDATE_PARAMS *setp = set | set2 | tag #include diff --git a/iconvdata/iso-2022-kr.c b/iconvdata/iso-2022-kr.c index 6439b0a469..556a33d449 100644 --- a/iconvdata/iso-2022-kr.c +++ b/iconvdata/iso-2022-kr.c @@ -1,5 +1,6 @@ /* Conversion module for ISO-2022-KR. - Copyright (C) 1998, 1999, 2000-2002, 2007 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2000-2002, 2007, 2008 + Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1998. @@ -261,6 +262,7 @@ enum #define LOOP_NEED_FLAGS #define EXTRA_LOOP_DECLS , int *setp #define INIT_PARAMS int set = *setp +#define REINIT_PARAMS set = *setp #define UPDATE_PARAMS *setp = set #include diff --git a/iconvdata/tst-iconv7.c b/iconvdata/tst-iconv7.c new file mode 100644 index 0000000000..a01e3d8425 --- /dev/null +++ b/iconvdata/tst-iconv7.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include + +static int +do_test (void) +{ + setlocale (LC_ALL, "de_DE.UTF-8"); + + iconv_t cd = iconv_open ("ISO-2022-JP//TRANSLIT", ""); + if (cd == (iconv_t) -1) + { + puts ("iconv_open failed"); + return 1; + } + + char instr1[] = "\xc2\xa3\xe2\x82\xac\n"; + const char expstr1[] = "\033$B!r\033(BEUR\n"; + char outstr[32]; + size_t inlen = sizeof (instr1); + size_t outlen = sizeof (outstr); + char *inptr = instr1; + char *outptr = outstr; + size_t r = iconv (cd, &inptr, &inlen, &outptr, &outlen); + if (r != 1 + || inlen != 0 + || outlen != sizeof (outstr) - sizeof (expstr1) + || memcmp (outstr, expstr1, sizeof (expstr1)) != 0) + { + puts ("wrong first conversion"); + return 1; + } + + char instr2[] = "\xe3\x88\xb1\n"; + const char expstr2[] = "(\033$B3t\033(B)\n"; + inlen = sizeof (instr2); + outlen = sizeof (outstr); + inptr = instr2; + outptr = outstr; + r = iconv (cd, &inptr, &inlen, &outptr, &outlen); + if (r != 1 + || inlen != 0 + || outlen != sizeof (outstr) - sizeof (expstr2) + || memcmp (outstr, expstr2, sizeof (expstr2)) != 0) + { + puts ("wrong second conversion"); + return 1; + } + + if (iconv_close (cd) != 0) + { + puts ("iconv_close failed"); + return 1; + } + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c"