Studying note of GCC-3.4.6 source (72)

5.1.2. C builtin macros

Below flag_undef is 0 by default, but it can be revised by option –undef, which if is nonzero, means do not predefine any system-specific or GCC-specific macros, but still predefine the standard predefined macros (i.e, macros defined in builtin_array).

 

295  void

296  c_cpp_builtins (cpp_reader *pfile)                                                       in c-cppbuiltin.c

297  {

298    /* -undef turns off target-specific built-ins.  */

299    if (flag_undef)

300      return;

301 

302    define__GNUC__ ();

5.1.2.1.    Macros of __GUNC__ family

In GCC, predefined macro __GNUC__ is always defined as the major version number of the compiler. For example, if the compiler version number is 3.4.6, this macro is defined as 3; while __GNUC_MINOR__, __GNUC_PATCHLEVEL__ are defined as 4 and 6 respectively. Further macro __GNUG__ is similar with __GNC__ but for C++. define__GNUC__ defines these macros from version_string which saves the version literal string.

 

252  static void

253  define__GNUC__ (void)                                                                     in c-cppbuiltin.c

254  {

255    /* The format of the version string, enforced below, is

256      ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)?  */

257    const char *q, *v = version_string;

258 

259    while (*v && ! ISDIGIT (*v))

260      v++;

261    if (!*v || (v > version_string && v[-1] != '-'))

262      abort ();

263 

264    q = v;

265    while (ISDIGIT (*v))

266      v++;

267    builtin_define_with_value_n ("__GNUC__", q, v - q);

268    if (c_dialect_cxx ())

269      builtin_define_with_value_n ("__GNUG__", q, v - q);

270 

271    if (*v != '.' || !ISDIGIT (v[1]))

272      abort ();

273    q = ++v;

274    while (ISDIGIT (*v))

275      v++;

276    builtin_define_with_value_n ("__GNUC_MINOR__", q, v - q);

277 

278    if (*v == '.')

279    {

280      if (!ISDIGIT (v[1]))

281        abort ();

282      q = ++v;

283      while (ISDIGIT (*v))

284        v++;

285      builtin_define_with_value_n ("__GNUC_PATCHLEVEL__", q, v - q);

286    }

287    else

288     builtin_define_with_value_n ("__GNUC_PATCHLEVEL__", "0", 1);

289 

290    if (*v && *v != ' ' && *v != '-')

291      abort ();

292  }

 

builtin_define_with_value_n will combine arguments macro and expansion to form definition pair and pass it to cpp_define.

 

492  static void

493  builtin_define_with_value_n (const char *macro, const char *expansion, size_t elen)

494  {

495    char *buf;

496    size_t mlen = strlen (macro);

497 

498    /* Space for an = and a NUL.  */

499    buf = alloca (mlen + elen + 2);

500    memcpy (buf, macro, mlen);

501    buf[mlen] = '=';

502    memcpy (buf + mlen + 1, expansion, elen);

503    buf[mlen + elen + 1] = '/0';

504 

505    cpp_define (parse_in, buf);

506  }

 

cpp_define also handles command line defined macros, which has form of m=val or m. For former ones, it needs be transformed into m val, and for rear ones, should be m 1. Then this regular form can be handled by run_directive which we have seen above.

 

1804 void

1805 cpp_define (cpp_reader *pfile, const char *str)                                             in cpplib.c

1806 {

1807   char *buf, *p;

1808   size_t count;

1809

1810   /* Copy the entire option so we can modify it.

1811     Change the first "=" in the string to a space. If there is none,

1812     tack " 1" on the end.  */

1813

1814   count = strlen (str);

1815   buf = alloca (count + 3);

1816   memcpy (buf, str, count);

1817

1818   p = strchr (str, '=');

1819   if (p)

1820     buf[p - str] = ' ';

1821   else

1822   {

1823     buf[count++] = ' ';

1824     buf[count++] = '1';

1825   }

1826   buf[count] = '/n';

1827

1828   run_directive (pfile, T_DEFINE, buf, count);

1829 }

5.1.2.2.    Macros in stddef.h

C++ defines some predefined macros in system header file stddef.h. They are size_t, ptrdiff_t, wchar, and wint. c_stddef_cpp_builtins helps to create the related objects for these macros.

 

c_cpp_builtins (continue)

 

304    /* For stddef.h. They require macros defined in c-common.c.  */

305    c_stddef_cpp_builtins ();

 

In below invocations, the second parameters, like SIZE_TYPE, are target related, and they are literal strings standing for specified type.

 

4249 void

4250 c_stddef_cpp_builtins(void)                                                                              in c-common.c

4251 {

4252   builtin_define_with_value ("__SIZE_TYPE__", SIZE_TYPE, 0);

4253   builtin_define_with_value ("__PTRDIFF_TYPE__", PTRDIFF_TYPE, 0);

4254   builtin_define_with_value ("__WCHAR_TYPE__", MODIFIED_WCHAR_TYPE, 0);

4255   builtin_define_with_value ("__WINT_TYPE__", WINT_TYPE, 0);

4256 }

 

See that builtin_define_with_value puts macro and expansion tegother into macro=expansion, however in cpp_define, we have seen, the expression will be transformed into macro expansion and run_directive is invoked.

 

470  void

471  builtin_define_with_value (const char *macro, const char *expansion, int is_str)

472  {

473    char *buf;

474    size_t mlen = strlen (macro);

475    size_t elen = strlen (expansion);

476    size_t extra = 2;  /* space for an = and a NUL */

477 

478    if (is_str)

479      extra += 2;  /* space for two quote marks */

480 

481    buf = alloca (mlen + elen + extra);

482    if (is_str)

483      sprintf (buf, "%s=/"%s/"", macro, expansion);

484    else

485      sprintf (buf, "%s=%s", macro, expansion);

486 

487    cpp_define (parse_in, buf);

488  }

 

Following are controlling macros, they describe the characteristics about the compiler, and the target machine.

5.1.2.3.    Control macros for language

The compiler needs some macros to describe the characteristics of the language. Then in our program, we can use them to select the matching definition, and make specific handling.

 

c_cpp_builtins (continue)

 

307    if (c_dialect_cxx ())

308    {

309      if (SUPPORTS_ONE_ONLY)

310        cpp_define (pfile, "__GXX_WEAK__=1");

311       else

312        cpp_define (pfile, "__GXX_WEAK__=0");

313      if (warn_deprecated)

314        cpp_define (pfile, "__DEPRECATED");

315    }

316    /* Note that we define this for C as well, so that we know if

317      __attribute__((cleanup)) will interface with EH.  */

318    if (flag_exceptions)

319      cpp_define (pfile, "__EXCEPTIONS");

320 

321    /* Represents the C++ ABI version, always defined so it can be used while

322      preprocessing C and assembler.  */

323    if (flag_abi_version == 0)

324      /* Use a very large value so that:

325 

326        #if __GXX_ABI_VERSION >= <value for version X>

327 

328        will work whether the user explicitly says "-fabi-version=x" or

329        "-fabi-version=0". Do not use INT_MAX because that will be

330        different from system to system.  */

331      builtin_define_with_int_value ("__GXX_ABI_VERSION", 999999);

332    else if (flag_abi_version == 1)

333      /* Due to an historical accident, this version had the value

334        "102".  */

335      builtin_define_with_int_value ("__GXX_ABI_VERSION", 102);

336    else

337      /* Newer versions have values 1002, 1003, ....  */

338      builtin_define_with_int_value ("__GXX_ABI_VERSION",

339                          1000 + flag_abi_version);

340 

341    /* libgcc needs to know this.  */

342    if (USING_SJLJ_EXCEPTIONS)

343      cpp_define (pfile, "__USING_SJLJ_EXCEPTIONS__");

5.1.2.4.    Macros for fundmental types characteristics

The characteristics of fundmental types can be gotten with below macros. They exist to make the standard header given numerical limits work correctly. Below TARGET_FLT_EVAL_METHOD is a C expression for the value for FLT_EVAL_METHOD in float.h, which stands for the  floating-point expression evaluation method, and its value,

if -1, indeterminate.

if 0, evaluate all operations and constants just to the range and precision of the type.

if 1, evaluate operations and constants of type float and double to the range and precision of the double type, evaluate long double operations and constants to the range and precision of the long double type.

if 2, evaluate all operations and constants to the range and precision of the long double type. For x86, the macro has below definition:

 

747  #define TARGET_FLT_EVAL_METHOD /                                                   in i386.h

748    (TARGET_MIX_SSE_I387 ? -1 : TARGET_SSE_MATH ? 0 : 2)

 

TARGET_MIX_SSE_I387 is set by option “-mfpmath=sse,387” which means utilize both the standard 387 floating point coprocessor and scalar floating point instructions present in the SSE instruction set, and results in indeterminate. And TARGET_SSE_MATH is set by “-mfpmath=sse” which just means using scalar floating point instructions present in the SSE instruction set. While by default, x86 uses 387 coprocessor, in which the temporary results are computed in 80bit precision instead of precision specified by the type resulting.

 

c_cpp_builtins (continue)

 

345    /* limits.h needs to know these.  */

346    builtin_define_type_max ("__SCHAR_MAX__", signed_char_type_node, 0);

347    builtin_define_type_max ("__SHRT_MAX__", short_integer_type_node, 0);

348    builtin_define_type_max ("__INT_MAX__", integer_type_node, 0);

349    builtin_define_type_max ("__LONG_MAX__", long_integer_type_node, 1);

350    builtin_define_type_max ("__LONG_LONG_MAX__", long_long_integer_type_node, 2);

351    builtin_define_type_max ("__WCHAR_MAX__", wchar_type_node, 0);

352 

353    builtin_define_type_precision ("__CHAR_BIT__", char_type_node);

354 

355    /* float.h needs to know these.  */

356 

357    builtin_define_with_int_value ("__FLT_EVAL_METHOD__",

358                              TARGET_FLT_EVAL_METHOD);

359 

360    builtin_define_float_constants ("FLT", "F", float_type_node);

361    builtin_define_float_constants ("DBL", "", double_type_node);

362    builtin_define_float_constants ("LDBL", "L", long_double_type_node);

363 

364    /* For use in assembly language.  */

365    builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0);

366    builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0);

367 

368   /* Misc.  */

369    builtin_define_with_value ("__VERSION__", version_string, 1);

370 

371   /* Definitions for LP64 model.  */

372    if (TYPE_PRECISION (long_integer_type_node) == 64

373        && POINTER_SIZE == 64

374        && TYPE_PRECISION (integer_type_node) == 32)

375    {

376      cpp_define (pfile, "_LP64");

377      cpp_define (pfile, "__LP64__");

378    }

 

In section Convert to real mode, we see that GCC supports IEEE floating point standard. Now GCC outputs the data of the IEEE floating point standard into predefined macros by builtin_define_float_constants. This function is quite simple, we skip it here.

At line 365, REGISTER_PREFIX is the macro expanding to a single token (not a string constant) which is the prefix applied to register names in assembly language for this target. You can use it to write assembly that is usable in multiple environments. For example, in the `m68k-aout' environment it expands to nothing, but in the `m68k-coff' environment it expands to a single `%'. While __USER_LABEL_PREFIX__ is the macro expanding to a single token which is the prefix applied to user labels (symbols visible to C code) in assembly. For example, in the `m68k-aout' environment it expands to an `_', but in the `m68k-coff' environment it expands to nothing.

5.1.2.5.    Control macros for compiler

This part of macros reveal some behavor of the compiler. And these macros cause certain GNU header files to provide optimized definitions, using macros or inline functions, of system library functions.

 

c_cpp_builtins (continue)

 

380    /* Other target-independent built-ins determined by command-line

381      options.  */

382    if (optimize_size)

383      cpp_define (pfile, "__OPTIMIZE_SIZE__");

384    if (optimize)

385      cpp_define (pfile, "__OPTIMIZE__");

386 

387    if (fast_math_flags_set_p ())

388      cpp_define (pfile, "__FAST_MATH__");

389    if (flag_really_no_inline)

390      cpp_define (pfile, "__NO_INLINE__");

391    if (flag_signaling_nans)

392      cpp_define (pfile, "__SUPPORT_SNAN__");

393    if (flag_finite_math_only)

394      cpp_define (pfile, "__FINITE_MATH_ONLY__=1");

395    else

396      cpp_define (pfile, "__FINITE_MATH_ONLY__=0");

397 

398    if (flag_iso)

399      cpp_define (pfile, "__STRICT_ANSI__");

400 

401    if (!flag_signed_char)

402      cpp_define (pfile, "__CHAR_UNSIGNED__");

403 

404    if (c_dialect_cxx () && TREE_UNSIGNED (wchar_type_node))

405      cpp_define (pfile, "__WCHAR_UNSIGNED__");

406 

407    /* Make the choice of ObjC runtime visible to source code.  */

408    if (c_dialect_objc () && flag_next_runtime)

409      cpp_define (pfile, "__NEXT_RUNTIME__");

5.1.2.6.    Control macros for target

The C preprocessor normally predefines several macros that indicate what type of system and machine is in use. They are obviously different on each target supported by GCC. All system-specific predefined macros expand to the constant 1, so you can test them with either `#ifdef' or `#if'.

 

c_cpp_builtins (continue)

 

411    /* A straightforward target hook doesn't work, because of problems

412      linking that hook's body when part of non-C front ends.  */

413  # define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM)

414  # define preprocessing_trad_p() (cpp_get_options (pfile)->traditional)

415  # define builtin_define(TXT) cpp_define (pfile, TXT)

416  # define builtin_assert(TXT) cpp_assert (pfile, TXT)

417    TARGET_CPU_CPP_BUILTINS ();

418    TARGET_OS_CPP_BUILTINS ();

419    TARGET_OBJFMT_CPP_BUILTINS ();

420  }

 

The first series macros record information of CPU. Take x86 for example, if the target machine using PentiumPro chip, then TARGET_CPU_CPP_BUILTINS will define following macros. Note that builtin_define is defined as cpp_define.

 

548  #define TARGET_CPU_CPP_BUILTINS()  /                                                       in i386.h

549    do                                                        /

550    {                                                  /

         

654     else if (ix86_arch == PROCESSOR_PENTIUMPRO)          /

655     {                                                 /

656       builtin_define ("__i686");                        /

657       builtin_define ("__i686__");                           /

658       builtin_define ("__pentiumpro");                     /

659       builtin_define ("__pentiumpro__");                 /

660     }                                                 /

689    }                                                  /

690    while (0)

 

Following are macros describe language features related to target machine. We take Linux OS as the example. Linux support PIC (position independent code) which can be open or closed by GCC command line option, and defines __pic__ and __PIC__ (both have the same meaning) when GCC agrees. Note that to x86/Linux whether flag_pic is 1 (“small” pic) or 2 (“large” pic), there is no difference.

 

73    #define TARGET_OS_CPP_BUILTINS()           /                                                in linux.h

74      do                                          /

75      {                                    /

76        LINUX_TARGET_OS_CPP_BUILTINS();         /

77        if (flag_pic)                        /

78        {                                 /

79          builtin_define ("__PIC__");            /

80          builtin_define ("__pic__");              /

81        }                                 /

82      }                                    /

83      while (0)

 

Every target OS needs engrave its formal name with corresponding macros. For Linux, it does define below macros.

 

100  #define LINUX_TARGET_OS_CPP_BUILTINS()     /                                         in linux.h

101    do {                                              /

102      builtin_define ("__gnu_linux__");                     /

103      builtin_define_std ("linux");                      /

104      builtin_define_std ("unix");                       /

105      builtin_assert ("system=linux");                  /

106      builtin_assert ("system=unix");                          /

107      builtin_assert ("system=posix");                 /

108    } while (0)

 

Routine builtin_define_std is interesting and worthes a look. C/C++ requires that all system-specific macros be part of the "reserved namespace". All names begin with “__” or “_” and a capital letter, are reserved for the compiler and library to use as they wish. However, historically system-specific macros have had names with no special prefix; for instance, it is common to find `unix' defined on Unix systems. For all such macros, GCC provides a parallel macro with two underscores added at the beginning and the end. If `unix' is defined, `__unix__' will be defined too.

 

431  void

432  builtin_define_std (const char *macro)                                                 in c-cppbuiltin.c

433  {

434    size_t len = strlen (macro);

435    char *buff = alloca (len + 5);

436    char *p = buff + 2;

437    char *q = p + len;

438 

439   /* prepend __ (or maybe just _) if in user's namespace.  */

440    memcpy (p, macro, len + 1);

441    if (!( *p == '_' && (p[1] == '_' || ISUPPER (p[1]))))

442    {

443      if (*p != '_')

444        *--p = '_';

445      if (p[1] != '_')

446        *--p = '_';

447    }

448    cpp_define (parse_in, p);

449 

450    /* If it was in user's namespace...  */

451    if (p != buff + 2)

452    {

453      /* Define the macro with leading and following __.  */

454      if (q[-1] != '_')

455        *q++ = '_';

456      if (q[-2] != '_')

457        *q++ = '_';

458      *q = '/0';

459      cpp_define (parse_in, p);

460 

461      /* Finally, define the original macro if permitted.  */

462      if (!flag_iso)

463        cpp_define (parse_in, macro);

464    }

465  }

 

Besides defining macros about the target OS, we also need prepare the answer for the possible assertions in system header files. In [13] the detail of assertion is given below:

"Assertions" are a deprecated alternative to macros in writing conditionals to test what sort of computer or system the compiled program will run on. Assertions are usually predefined, but you can define them with preprocessing directives or command-line options.

Assertions were intended to provide a more systematic way to describe the compiler's target system. However, in practice they are just as unpredictable as the system-specific predefined macros. In addition, they are not part of any standard, and only a few compilers support them. Therefore, the use of assertions is *less* portable than the use of system-specific predefined macros. We recommend you do not use them at all.

An assertion looks like this:

#PREDICATE (ANSWER)

PREDICATE must be a single identifier. ANSWER can be any sequence of tokens; all characters are significant except for leading and trailing whitespace, and differences in internal whitespace sequences are ignored. (This is similar to the rules governing macro redefinition.) Thus, `(x + y)' is different from `(x+y)' but equivalent to `( x + y )'. Parentheses do not nest inside an answer.

To test an assertion, you write it in an `#if'. For example, this conditional succeeds if either `vax' or `ns16000' has been asserted as an answer for `machine'.

#if #machine (vax) || #machine (ns16000)

You can test whether _any_ answer is asserted for a predicate by omitting the answer in the conditional:

#if #machine

Assertions are made with the `#assert' directive. Its sole argument is the assertion to make, without the leading `#' that identifies assertions in conditionals.

#assert PREDICATE (ANSWER)

You may make several assertions with the same predicate and different answers. Subsequent assertions do not override previous ones for the same predicate. All the answers for any given predicate are simultaneously true.

Assertions can be canceled with the `#unassert' directive. It has the same syntax as `#assert'. In that form it cancels only the answer which was specified on the `#unassert' line; other answers for that predicate remain true. You can cancel an entire predicate by leaving out the answer:

#unassert PREDICATE

In either form, if no such assertion has been made, `#unassert' has no effect.

 

1854 void

1855 cpp_assert (cpp_reader *pfile, const char *str)                                              in cpplib.c

1856 {

1857   handle_assertion (pfile, str, T_ASSERT);

1858 }

 

In [10], the documented usage of assertion is #assert PRED=ANS. Then handle_assertion helps to converse the form into #assert PRED(ANS).

 

1868 static void

1869 handle_assertion (cpp_reader *pfile, const char *str, int type)                        in cpplib.c

1870 {

1871   size_t count = strlen (str);

1872   const char *p = strchr (str, '=');

1873

1874   /* Copy the entire option so we can modify it. Change the first

1875     "=" in the string to a '(', and tack a ')' on the end.  */

1876   char *buf = alloca (count + 2);

1877

1878   memcpy (buf, str, count);

1879   if (p)

1880   {

1881     buf[p - str] = '(';

1882     buf[count++] = ')';

1883   }

1884   buf[count] = '/n';

1885   str = buf;

1886

1887   run_directive (pfile, type, str, count);

1888 }

 

The registered handle for assertion is do_assert which is invoked by run_directive.

 

1733 static void

1734 do_assert (cpp_reader *pfile)                                                                             in cpplib.c

1735 {

1736   struct answer *new_answer;

1737   cpp_hashnode *node;

1738

1739   node = parse_assertion (pfile, &new_answer, T_ASSERT);

1740   if (node)

1741   {

1742     /* Place the new answer in the answer list. First check there

1743       is not a duplicate.  */

1744     new_answer->next = 0;

1745     if (node->type == NT_ASSERTION)

1746     {

1747       if (*find_answer (node, new_answer))

1748       {

1749         cpp_error (pfile, CPP_DL_WARNING, "/"%s/" re-asserted",

1750                  NODE_NAME (node) + 1);

1751         return;

1752       }

1753       new_answer->next = node->value.answers;

1754     }

1755

1756     node->type = NT_ASSERTION;

1757     node->value.answers = new_answer;

1758     BUFF_FRONT (pfile->a_buff) += (sizeof (struct answer)

1759                                  + (new_answer->count - 1)

1760                                    * sizeof (cpp_token));

1761     check_eol (pfile);

1762   }

1763 }

 

As part of cpp_hashnode, answer has following definition. Below the slot first is designed as variable length array, in which records tokens for the answer.

 

29    struct answer                                                                                             in cpplib.c

30    {

31      struct answer *next;

32      unsigned int count;

33      cpp_token first[1];

34    };

 

Notice that tokens in answer can’t be expanded further like macro. As it acts different from macro, and also handled by preprocessor, the system needs a way to tell it out from macro. So GCC appends heading ‘#’ in assertion’s name.

 

1651 static cpp_hashnode *

1652 parse_assertion (cpp_reader *pfile, struct answer **answerp, int type)            in cpplib.c

1653 {

1654   cpp_hashnode *result = 0;

1655   const cpp_token *predicate;

1656

1657  /* We don't expand predicates or answers.  */

1658   pfile->state.prevent_expansion++;

1659

1660   *answerp = 0;

1661   predicate = cpp_get_token (pfile);

1662   if (predicate->type == CPP_EOF)

1663     cpp_error (pfile, CPP_DL_ERROR, "assertion without predicate");

1664   else if (predicate->type != CPP_NAME)

1665     cpp_error (pfile, CPP_DL_ERROR, "predicate must be an identifier");

1666   else if (parse_answer (pfile, answerp, type) == 0)

1667   {

1668     unsigned int len = NODE_LEN (predicate->val.node);

1669     unsigned char *sym = alloca (len + 1);

1670

1671     /* Prefix '#' to get it out of macro namespace.  */

1672     sym[0] = '#';

1673     memcpy (sym + 1, NODE_NAME (predicate->val.node), len);

1674     result = cpp_lookup (pfile, sym, len + 1);

1675   }

1676

1677   pfile->state.prevent_expansion--;

1678   return result;

1679 }

 

The answer is extracted by parse_answer. This function is quite simple, and similar with those extracting macro defintion.

 

1575 static int

1576 parse_answer (cpp_reader *pfile, struct answer **answerp, int type)                             in cpplib.c

1577 {

1578   const cpp_token *paren;

1579   struct answer *answer;

1580   unsigned int acount;

1581

1582   /* In a conditional, it is legal to not have an open paren. We

1583     should save the following token in this case.  */

1584   paren = cpp_get_token (pfile);

1585

1586   /* If not a paren, see if we're OK.  */

1587   if (paren->type != CPP_OPEN_PAREN)

1588   {

1589     /* In a conditional no answer is a test for any answer. It

1590       could be followed by any token.  */

1591     if (type == T_IF)

1592     {

1593       _cpp_backup_tokens (pfile, 1);

1594       return 0;

1595     }

1596

1597     /* #unassert with no answer is valid - it removes all answers.  */

1598     if (type == T_UNASSERT && paren->type == CPP_EOF)

1599       return 0;

1600

1601     cpp_error (pfile, CPP_DL_ERROR, "missing '(' after predicate");

1602     return 1;

1603   }

1604

1605   for (acount = 0;; acount++)

1606   {

1607     size_t room_needed;

1608     const cpp_token *token = cpp_get_token (pfile);

1609     cpp_token *dest;

1610

1611     if (token->type == CPP_CLOSE_PAREN)

1612       break;

1613

1614     if (token->type == CPP_EOF)

1615     {

1616       cpp_error (pfile, CPP_DL_ERROR, "missing ')' to complete answer");

1617       return 1;

1618     }

1619

1620     /* struct answer includes the space for one token.  */

1621     room_needed = (sizeof (struct answer) + acount * sizeof (cpp_token));

1622

1623     if (BUFF_ROOM (pfile->a_buff) < room_needed)

1624       _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (struct answer));

1625

1626     dest = &((struct answer *) BUFF_FRONT (pfile->a_buff))->first[acount];

1627     *dest = *token;

1628

1629     /* Drop whitespace at start, for answer equivalence purposes.  */

1630     if (acount == 0)

1631       dest->flags &= ~PREV_WHITE;

1632   }

1633

1634   if (acount == 0)

1635   {

1636     cpp_error (pfile, CPP_DL_ERROR, "predicate's answer is empty");

1637     return 1;

1638   }

1639

1640   answer = (struct answer *) BUFF_FRONT (pfile->a_buff);

1641   answer->count = acount;

1642   answer->next = NULL;

1643   *answerp = answer;

1644

1645   return 0;

1646 }

 

find_answer is designed to find if specified answer of candidate has been added in node. Note that as answer contains tokens, the equivalence should be checked by _cpp_equiv_tokens one by one. Answer can’t be re-inserted.

 

1683 static struct answer **

1684 find_answer (cpp_hashnode *node, const struct answer *candidate)                       in cpplib.c

1685 {

1686   unsigned int i;

1687   struct answer **result;

1688

1689   for (result = &node->value.answers; *result; result = &(*result)->next)

1690   {

1691    struct answer *answer = *result;

1692

1693    if (answer->count == candidate->count)

1694    {

1695      for (i = 0; i < answer->count; i++)

1696        if (! _cpp_equiv_tokens (&answer->first[i], &candidate->first[i]))

1697          break;

1698

1699      if (i == answer->count)

1700        break;

1701    }

1702  }

1703

1704  return result;

1705}

 

At last, TARGET_OBJFMT_CPP_BUILTINS creates macro definitions relate to object format. For x86/Linux target, the object format is elf by default:

 

24    #define TARGET_OBJFMT_CPP_BUILTINS()          /                                 in elfso.h

25      do                                          /

26      {                                     /

27           builtin_define ("__ELF__");         /

28      }                                     /

29      while (0)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
for Policy and Practice, 2018, 17(2): 179-195. In this article, Victor Wang Chen Neo examines the implementation of school-based curriculum development (SBCD) in Singapore. SBCD is a process where schools are given greater autonomy to develop and implement their own curriculum, rather than following a standardized national curriculum. The author begins by providing an overview of the history of curriculum development in Singapore, and how the shift towards SBCD came about. He then presents the findings of a study that he conducted, which involved interviews with school leaders who had implemented SBCD in their schools. The author identifies several factors that influenced the successful implementation of SBCD in these schools. These include strong leadership, a clear vision and direction for the school, and a focus on student learning and development. The author also highlights the importance of teacher training and support, as well as collaboration and communication among all stakeholders involved in the curriculum development process. However, the author also notes some challenges that schools face when implementing SBCD. These include a lack of resources, such as time and funding, as well as the need to balance autonomy with accountability to ensure that the curriculum developed meets national standards. Overall, the author suggests that SBCD has the potential to improve the quality of education in Singapore by allowing schools to tailor their curriculum to the needs and interests of their students. However, he also calls for continued support and guidance from the government to ensure that schools are able to implement SBCD effectively.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值