Studying note of GCC-3.4.6 source (76)

5.4. Header file included by -include

According to [6], header file included by –include option is included before any header file included in source file, but this header file should be handled after file specified by –macro being handled. If multiple ‘-include’ options are given, the files are included in the order they appear on the command line.

 

finish_options (continue)

 

1466   include_cursor = 0;

1467   push_command_line_include ();

1468 }

 

First at line 1466 abve, include_cursor is set as 0, means no –include option has been handled among delayed options. Note that in below, if we read in a header specified by an –include option, we return at line 1480, leaving unhandled –include options within deferred_opts.

 

1471   static void

1472   push_command_line_include (void)                                                          in c-opts.c

1473   {

1474     while (include_cursor < deferred_count)

1475     {

1476       struct deferred_opt *opt = &deferred_opts[include_cursor++];

1477  

1478       if (! cpp_opts->preprocessed && opt->code == OPT_include

1479           && cpp_push_include (parse_in, opt->arg))

1480         return;

1481     }

1482  

1483     if (include_cursor == deferred_count)

1484     {

1485       include_cursor++;

1486       /* -Wunused-macros should only warn about macros defined hereafter.  */

1487       cpp_opts->warn_unused_macros = warn_unused_macros;

1488       /* Restore the line map from <command line>.  */

1489       if (! cpp_opts->preprocessed)

1490         cpp_change_file (parse_in, LC_RENAME, main_input_filename);

1491  

1492       /* Set this here so the client can change the option if it wishes,

1493         and after stacking the main file so we don't trace the main file.  */

1494       cpp_get_line_maps (parse_in)->trace_includes

1495            = cpp_opts->print_include_names;

1496     }

1497   }

 

So how to realize include multiple header files included by –include option? The answer starts at cb_file_change. In cb_file_change, there is code as below:

 

1509     if (new_map == 0 || (new_map->reason == LC_LEAVE && MAIN_FILE_P (new_map)))

1510     push_command_line_include ();

 

And at line 1158 in c_common_post_options, cb_file_change is assigned to hook file_change in field cb of cpp_reader, which is invoked in _cpp_do_file_change. And before that, in the function, linemap_add is called to add an line_map into map list in cpp_reader to record the file change.

If it is the finish of file readin, for example, the header file included by –include option here, then _cpp_pop_buffer is called by _cpp_get_fresh_line. _cpp_pop_buffer has following definition.

 

1949   void

1950   _cpp_pop_buffer (cpp_reader *pfile)                                                        in cpplib.c

1951   {

1952     cpp_buffer *buffer = pfile->buffer;

1953     struct _cpp_file *inc = buffer->file;

1954     struct if_stack *ifs;

1955  

1956     /* Walk back up the conditional stack till we reach its level at

1957       entry to this file, issuing error messages.  */

1958     for (ifs = buffer->if_stack; ifs; ifs = ifs->next)

1959       cpp_error_with_line (pfile, CPP_DL_ERROR, ifs->line, 0,

1960                           "unterminated #%s", dtable[ifs->type].name);

1961  

1962     /* In case of a missing #endif.  */

1963     pfile->state.skipping = 0;

1964  

1965     /* _cpp_do_file_change expects pfile->buffer to be the new one.  */

1966     pfile->buffer = buffer->prev;

1967  

1968     free (buffer->notes);

1969  

1970     /* Free the buffer object now; we may want to push a new buffer

1971       in _cpp_push_next_include_file.  */

1972     obstack_free (&pfile->buffer_ob, buffer);

1973  

1974     if (inc)

1975     {

1976       _cpp_pop_file_buffer (pfile, inc);

1977  

1978       _cpp_do_file_change (pfile, LC_LEAVE, 0, 0, 0);

1979     }

1980   }

 

Above at line 1953, buffer->file is only set in _cpp_stack_file, to stand for the major readin buffer of the file, and other buffers added in during the file processing (for example, in do_pragma), are created upon obstack, neither setting field file, nor releasing manually.

So for our header file included by –include option, the created line_map meets condition at line 1509, causes push_command_line_include tries to include next header files. Note at line 1479, cpp_push_include invokes _cpp_stack_include (refers to Stack the file (exclude PCH file)). Cyclizing in this way, till all header files included by –include options are handled.

5.5. Prepare PCH file header

If given option –output-pch, the header file besides being compiled, PCH file (pre-compiled header file) will also be generated. In this option, the name of the PCH file is specified and saved in variable pch_file. Here pch_init will prepare the head for will being generated PCH file.

 

108  void

109  pch_init (void)                                                                                          in c-pch.c

110   {

111     FILE *f;

112     struct c_pch_validity v;

113     void *target_validity;

114     static const char partial_pch[IDENT_LENGTH] = "gpcWrite";

115     unsigned int current_flags_info = 0;

116    

117     if (! pch_file)

118       return;

119  

120    if (flag_unit_at_a_time)

121      current_flags_info |= FLAG_UNIT_AT_A_TIME_SET;

122 

123    f = fopen (pch_file, "w+b");

124    if (f == NULL)

125      fatal_error ("can't create precompiled header %s: %m", pch_file);

126    pch_outfile = f;

127   

128    if (strlen (host_machine) > 255 || strlen (target_machine) > 255

129        || strlen (version_string) > 255)

130      abort ();

131   

132    v.host_machine_length = strlen (host_machine);

133    v.target_machine_length = strlen (target_machine);

134    v.version_length = strlen (version_string);

135    v.debug_info_type = write_symbols;

136    v.flags_info = current_flags_info;

137    v.pch_init = &pch_init;

138    target_validity = targetm.get_pch_validity (&v.target_data_length);

139   

140    if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1

141        || fwrite (&v, sizeof (v), 1, f) != 1

142        || fwrite (host_machine, v.host_machine_length, 1, f) != 1

143        || fwrite (target_machine, v.target_machine_length, 1, f) != 1

144        || fwrite (version_string, v.version_length, 1, f) != 1

145        || fwrite (target_validity, v.target_data_length, 1, f) != 1)

146      fatal_error ("can't write to %s: %m", pch_file);

147 

148    /* We need to be able to re-read the output.  */

149   /* The driver always provides a valid -o option.  */

150    if (asm_file_name == NULL

151        || strcmp (asm_file_name, "-") == 0)

152      fatal_error ("`%s' is not a valid output file", asm_file_name);

153   

154    asm_file_startpos = ftell (asm_out_file);

155   

156    /* Let the debugging format deal with the PCHness.  */

157    (*debug_hooks->handle_pch) (0);

158   

159    cpp_save_state (parse_in, f);

160  }

 

As we have seen, c_pch_validity describes the structure of PCH file, refers to figure pch file layout for detail. At line 138, hook get_pch_validity will generate target data for the PCH file. Here, this hook routes the invocation to default_get_pch_validity.

 

4069 void *

4070 default_get_pch_validity (size_t *len)                                                                in toplev.c

4071 {

4072 #ifdef TARGET_OPTIONS

4073   size_t i;

4074 #endif

4075   char *result, *r;

4076

4077   *len = sizeof (target_flags) + 2;

4078 #ifdef TARGET_OPTIONS

4079   for (i = 0; i < ARRAY_SIZE (target_options); i++)

4080   {

4081     *len += 1;

4082     if (*target_options[i].variable)

4083       *len += strlen (*target_options[i].variable);

4084   }

4085 #endif

4086

4087   result = r = xmalloc (*len);

4088   r[0] = flag_pic;

4089   r[1] = flag_pie;

4090   r += 2;

4091   memcpy (r, &target_flags, sizeof (target_flags));

4092   r += sizeof (target_flags);

4093

4094 #ifdef TARGET_OPTIONS

4095   for (i = 0; i < ARRAY_SIZE (target_options); i++)

4096   {

4097     const char *str = *target_options[i].variable;

4098     size_t l;

4099     if (! str)

4100       str = "";

4101     l = strlen (str) + 1;

4102     memcpy (r, str, l);

4103     r += l;

4104  }

4105 #endif

4106

4107   return result;

4108 }

 

The content of target_options can refer to section Initializing options related to target, while the layout of target data segment in PCH file can refer to figure Layout of target data of PCH file.

Below function saves the current definitions of the parse_in for dependency checking purposes. It executes before handling the first source file. At that time parse_in contains definitions added by finish_options (it includes builtin deifnitions and user definition via –D or -U option). Here argument f is the file handle opened for PCH file specified by –output-pch in pch_file.

 

192    int

193    cpp_save_state (cpp_reader *r, FILE *f)                                                    in cpppch.c

194    {

195     /* Save the list of non-void identifiers for the dependency checking.  */

196      r->savedstate = xmalloc (sizeof (struct cpp_savedstate));

197      r->savedstate->definedhash = htab_create (100, cpp_string_hash,

198                                         cpp_string_eq, NULL);

199      cpp_forall_identifiers (r, save_idents, r->savedstate);

200     

201      /* Write out the list of defined identifiers.  */

202      cpp_forall_identifiers (r, write_macdef, f);

203   

204      return 0;

205  }

 

Struct cpp_savestate has following definition. Slot definedhash is the hash table to hold the name of definitions.

 

103    struct cpp_savedstate                                                                                in cpppch.c

104    {

105      /* A hash table of the defined identifiers.  */

106      htab_t definedhash;

107      /* The size of the definitions of those identifiers (the size of

108        'definedstrs').  */

109      size_t hashsize;

110       /* Number of definitions */

111       size_t n_defs;

112       /* Array of definitions. In cpp_write_pch_deps it is used for sorting.  */

113       cpp_hashnode **defs;

114       /* Space for the next definition. Definitions are null-terminated

115         strings.  */

116       unsigned char *definedstrs;

117     };

 

Routine cpp_forall_identifiers iterates the hash_table of parse_in which is the hash table for identifiers. As we have seen in previous section, the node of the hash table can be explained in two way, one into tree node, the other into cpp_hashnode which is passed as argument hn below. Note that last argument of htab_find_slot at line 134 is INSERT, it will add an empty node for absent identifier automatically.

 

122    static int

123    save_idents (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p)

124    {

125      struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p;

126     

127      if (hn->type != NT_VOID)

128      {

129        struct cpp_string news;

130        void **slot;

131   

132        news.len = NODE_LEN (hn);

133        news.text= NODE_NAME (hn);

134        slot = htab_find_slot (ss->definedhash, &news, INSERT);

135        if (*slot == NULL)

136        {

137          struct cpp_string *sp;

138          unsigned char *text;

139          

140          sp = xmalloc (sizeof (struct cpp_string));

141          *slot = sp;

142   

143          sp->len = NODE_LEN (hn);

144          sp->text = text = xmalloc (NODE_LEN (hn));

145          memcpy (text, NODE_NAME (hn), NODE_LEN (hn));

146        }

147      }

148   

149      return 1;

150    }

 

In first iteration, we get all names of the identifiers. In second iteration, we record all macro definitions. Note, as we are still under preprocessing, in the view of preprocessor, nodes are of three kinds: NT_VOID, NT_MACRO, and NT_ASSERTION.

 

48      static int

49      write_macdef (cpp_reader *pfile, cpp_hashnode *hn, void *file_p)                     in cpppch.c

50      {

51        FILE *f = (FILE *) file_p;

52        switch (hn->type)

53        {

54          case NT_VOID:

55            if (! (hn->flags & NODE_POISONED))

56              return 1;

57           

58          case NT_MACRO:

59            if ((hn->flags & NODE_BUILTIN))

60              return 1;

61     

62            {

63              struct macrodef_struct s;

64              const unsigned char *defn;

65     

66              s.name_length = NODE_LEN (hn);

67              s.flags = hn->flags & NODE_POISONED;

68     

69              if (hn->type == NT_MACRO)

70              {

71                defn = cpp_macro_definition (pfile, hn);

72                s.definition_length = ustrlen (defn);

73              }

74              else

75              {

76                defn = NODE_NAME (hn);

77                s.definition_length = s.name_length;

78              }

79          

80              if (fwrite (&s, sizeof (s), 1, f) != 1

81                 || fwrite (defn, 1, s.definition_length, f) != s.definition_length)

82              {

83                cpp_errno (pfile, CPP_DL_ERROR,

84                          "while writing precompiled header");

85                return 0;

86              }

87            }

88            return 1;

89           

90          case NT_ASSERTION:

91            /* Not currently implemented.  */

92            return 1;

93     

94          default:

95            abort ();

96        }

97      }

 

The macro definition is recorded in slot of cpp_macro within hashnode and field macro_buffer of cpp_reader. The content written into the PCH file is what we read from PCH file as section Read in macro defintions reveals.

 

1605   const unsigned char *

1606   cpp_macro_definition (cpp_reader *pfile, const cpp_hashnode *node)   in cppmacro.c

1607   {

1608     unsigned int i, len;

1609     const cpp_macro *macro = node->value.macro;

1610     unsigned char *buffer;

1611  

1612     if (node->type != NT_MACRO || (node->flags & NODE_BUILTIN))

1613     {

1614       cpp_error (pfile, CPP_DL_ICE,

1615                "invalid hash type %d in cpp_macro_definition", node->type);

1616       return 0;

1617     }

1618  

1619     /* Calculate length.  */

1620     len = NODE_LEN (node) + 2;                     /* ' ' and NUL.  */

1621     if (macro->fun_like)

1622     {

1623       len += 4;             /* "()" plus possible final ".." of named

1624                        varargs (we have + 1 below).  */

1625       for (i = 0; i < macro->paramc; i++)

1626         len += NODE_LEN (macro->params[i]) + 1; /* "," */

1627     }

1628  

1629     /* This should match below where we fill in the buffer.  */

1630     if (CPP_OPTION (pfile, traditional))

1631       len += _cpp_replacement_text_len (macro);

1632     else

1633     {

1634       for (i = 0; i < macro->count; i++)

1635       {

1636         cpp_token *token = &macro->exp.tokens[i];

1637  

1638         if (token->type == CPP_MACRO_ARG)

1639           len += NODE_LEN (macro->params[token->val.arg_no - 1]);

1640         else

1641           len += cpp_token_len (token);

1642  

1643         if (token->flags & STRINGIFY_ARG)

1644           len++;                /* "#" */

1645         if (token->flags & PASTE_LEFT)

1646           len += 3;             /* " ##" */

1647         if (token->flags & PREV_WHITE)

1648           len++;              /* " " */

1649       }

1650     }

1651  

1652     if (len > pfile->macro_buffer_len)

1653     {

1654       pfile->macro_buffer = xrealloc (pfile->macro_buffer, len);

1655       pfile->macro_buffer_len = len;

1656     }

1657  

1658     /* Fill in the buffer. Start with the macro name.  */

1659     buffer = pfile->macro_buffer;

1660     memcpy (buffer, NODE_NAME (node), NODE_LEN (node));

1661     buffer += NODE_LEN (node);

1662  

1663     /* Parameter names.  */

1664     if (macro->fun_like)

1665     {

1666       *buffer++ = '(';

1667       for (i = 0; i < macro->paramc; i++)

1668       {

1669         cpp_hashnode *param = macro->params[i];

1670  

1671        if (param != pfile->spec_nodes.n__VA_ARGS__)

1672         {

1673           memcpy (buffer, NODE_NAME (param), NODE_LEN (param));

1674           buffer += NODE_LEN (param);

1675         }

1676  

1677         if (i + 1 < macro->paramc)

1678           /* Don't emit a space after the comma here; we're trying

1679             to emit a Dwarf-friendly definition, and the Dwarf spec

1680             forbids spaces in the argument list.  */

1681          *buffer++ = ',';

1682         else if (macro->variadic)

1683          *buffer++ = '.', *buffer++ = '.', *buffer++ = '.';

1684       }

1685       *buffer++ = ')';

1686     }

1687  

1688     /* The Dwarf spec requires a space after the macro name, even if the

1689       definition is the empty string.  */

1690     *buffer++ = ' ';

1691  

1692     if (CPP_OPTION (pfile, traditional))

1693       buffer = _cpp_copy_replacement_text (macro, buffer);

1694     else if (macro->count)

1695     /* Expansion tokens.  */

1696     {

1697       for (i = 0; i < macro->count; i++)

1698       {

1699         cpp_token *token = &macro->exp.tokens[i];

1700  

1701         if (token->flags & PREV_WHITE)

1702           *buffer++ = ' ';

1703         if (token->flags & STRINGIFY_ARG)

1704           *buffer++ = '#';

1705  

1706         if (token->type == CPP_MACRO_ARG)

1707         {

1708           memcpy (buffer,

1709                   NODE_NAME (macro->params[token->val.arg_no - 1]),

1710                   NODE_LEN (macro->params[token->val.arg_no - 1]));

1711           buffer += NODE_LEN (macro->params[token->val.arg_no - 1]);

1712         }

1713         else

1714           buffer = cpp_spell_token (pfile, token, buffer);

1715  

1716         if (token->flags & PASTE_LEFT)

1717         {

1718           *buffer++ = ' ';

1719           *buffer++ = '#';

1720           *buffer++ = '#';

1721           /* Next has PREV_WHITE; see _cpp_create_definition.  */

1722         }

1723       }

1724     }

1725  

1726     *buffer = '/0';

1727     return pfile->macro_buffer;

1728   }

 

The function just walks into the macro definition and first counts the size of buffer needed, then copy the whole definition in macro_buffer slot of cpp_reader, which when returns back write_macrodef is written into the PCH file.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值