Studying note of GCC-3.4.6 source (75)

5.3.1.3.    Builtin macro - handle pragma directive

The so-called builtin macro, defined by ISO C++ standards, includes: __TIME__, __DATE__, __FILE__, __BASE_FILE__, __LINE__, __INCLUDE_LEVEL__, _Pragma, and __STDC__ (see builtin_array), they are handled by builtin_macro.

 

249  static int

250  builtin_macro (cpp_reader *pfile, cpp_hashnode *node)                         in cppmacro.c

251  {

252    const uchar *buf;

253    size_t len;

254    char *nbuf;

255 

256    if (node->value.builtin == BT_PRAGMA)

257    {

258      /* Don't interpret _Pragma within directives. The standard is

259        not clear on this, but to me this makes most sense.  */

260      if (pfile->state.in_directive)

261        return 0;

262 

263      _cpp_do__Pragma (pfile);

264      return 1;

265    }

 

C99 introduces the _Pragma operator. This feature addresses a major problem with #pragma: being a directive, it cannot be produced as the result of macro expansion. _Pragma is an operator, much like sizeof or defined, and can be embedded in a macro.

Its syntax is _Pragma (STRING-LITERAL), where STRING-LITERAL can be either a normal or wide-character string literal. It is destringized, by replacing all // with a single / and all /" with a ". The result is then processed as if it had appeared as the right hand side of a #pragma directive. For example,

_Pragma ("GCC dependency /"parse.y/"")

has the same effect as #pragma GCC dependency "parse.y". The same effect could be achieved using macros, for example (we also take it as the example for following code reading)

#define DO_PRAGMA(x) _Pragma (#x)

DO_PRAGMA (GCC dependency "parse.y")

The standard is unclear on where a _Pragma operator can appear. The preprocessor does not accept it within a preprocessing conditional directive like #if. To be safe, you are probably best keeping it out of directives other than #define, and putting it on a line of its own.

 

1369 void

1370 _cpp_do__Pragma (cpp_reader *pfile)                                                               in cpplib.c

1371 {

1372   const cpp_token *string = get__Pragma_string (pfile);

1373

1374   if (string)

1375     destringize_and_run (pfile, &string->val.str);

1376   else

1377     cpp_error (pfile, CPP_DL_ERROR,

1378          "_Pragma takes a parenthesized string literal");

1379 }

 

As in above example, content of the _Pragma is literal string. Routine get__Pragma_string fetches this content.

 

1289 static const cpp_token *

1290 get__Pragma_string (cpp_reader *pfile)                                                             in cpplib.c

1291{

1292  const cpp_token *string;

1293

1294  if (get_token_no_padding (pfile)->type != CPP_OPEN_PAREN)

1295    return NULL;

1296

1297  string = get_token_no_padding (pfile);

1298  if (string->type != CPP_STRING && string->type != CPP_WSTRING)

1299    return NULL;

1300

1301  if (get_token_no_padding (pfile)->type != CPP_CLOSE_PAREN)

1302    return NULL;

1303

1304  return string;

1305}

 

The tokens in this statement are fetched by get_token_no_padding, it returns till non-padding token is fetched.

 

1276 static const cpp_token *

1277 get_token_no_padding (cpp_reader *pfile)                                                          in cpplib.c

1278 {

1279   for (;;)

1280   {

1281     const cpp_token *result = cpp_get_token (pfile);

1282     if (result->type != CPP_PADDING)

1283       return result;

1284   }

1285 }

 

The content of the literal string is what should following #pragma. Before executing the corresponding #pragma operator, the string need stringize to replace // with /, and /” with .

 

1309 static void

1310 destringize_and_run (cpp_reader *pfile, const cpp_string *in)                               n cpplib.c

1311 {

1312   const unsigned char *src, *limit;

1313   char *dest, *result;

1314

1315   dest = result = alloca (in->len - 1);

1316   src = in->text + 1 + (in->text[0] == 'L');

1317   limit = in->text + in->len - 1;

1318   while (src < limit)

1319   {

1320     /* We know there is a character following the backslash.  */

1321     if (*src == '//' && (src[1] == '//' || src[1] == '"'))

1322       src++;

1323     *dest++ = *src++;

1324   }

1325   *dest = '/n';

1326

1327   /* Ugh; an awful kludge. We are really not set up to be lexing

1328     tokens when in the middle of a macro expansion. Use a new

1329     context to force cpp_get_token to lex, and so skip_rest_of_line

1330     doesn't go beyond the end of the text. Also, remember the

1331     current lexing position so we can return to it later.

1332

1333     Something like line-at-a-time lexing should remove the need for

1334     this.  */

1335   {

1336     cpp_context *saved_context = pfile->context;

1337     cpp_token *saved_cur_token = pfile->cur_token;

1338     tokenrun *saved_cur_run = pfile->cur_run;

1339

1340     pfile->context = xnew (cpp_context);

1341     pfile->context->macro = 0;

1342     pfile->context->prev = 0;

1343     run_directive (pfile, T_PRAGMA, result, dest - result);

1344     free (pfile->context);

1345     pfile->context = saved_context;

1346     pfile->cur_token = saved_cur_token;

1347     pfile->cur_run = saved_cur_run;

1348     pfile->line--;

1349   }

1350

1351   /* See above comment. For the moment, we'd like

1352

1353       token1 _Pragma ("foo") token2

1354

1355     to be output as

1356

1357       token1

1358       # 7 "file.c"

1359       #pragma foo

1360       # 7 "file.c"

1361       token2

1362

1363     Getting the line markers is a little tricky.  */

1364   if (pfile->cb.line_change)

1365     pfile->cb.line_change (pfile, pfile->cur_token, false);

1366 }

 

Above at line 1343, in run_directive, this restored string is pushed into the readin buffer of cpp_reader by cpp_push_buffer. But in cpp_get_token, if current readin context isn’t the base context, it will read in token from the context instead from the readin buffer. To enforce to read in token from readin buffer, here forges a base context (prev at line 1342 is 0). At the same saves cur_token and cur_run for the base context. See that it means after running #pragma directive, its token would be reused by others.

 

1136 static void

1137 do_pragma (cpp_reader *pfile)                                                                           in cpplib.c

1138 {

1139   const struct pragma_entry *p = NULL;

1140   const cpp_token *token, *pragma_token = pfile->cur_token;

1141   unsigned int count = 1;

1142

1143   pfile->state.prevent_expansion++;

1144

1145   token = cpp_get_token (pfile);

1146   if (token->type == CPP_NAME)

1147   {

1148     p = lookup_pragma_entry (pfile->pragmas, token->val.node);

1149     if (p && p->is_nspace)

1150     {

1151       count = 2;

1152       token = cpp_get_token (pfile);

1153       if (token->type == CPP_NAME)

1154         p = lookup_pragma_entry (p->u.space, token->val.node);

1155       else

1156         p = NULL;

1157     }

1158   }

1159

1160   if (p)

1161   {

1162     /* Since the handler below doesn't get the line number, that it

1163       might need for diagnostics, make sure it has the right

1164       numbers in place.  */

1165     if (pfile->cb.line_change)

1166       (*pfile->cb.line_change) (pfile, pragma_token, false);

1167     (*p->u.handler) (pfile);

1168   }

1169   else if (pfile->cb.def_pragma)

1170   {

1171     _cpp_backup_tokens (pfile, count);

1172     pfile->cb.def_pragma (pfile, pfile->directive_line);

1173   }

1174

1175   pfile->state.prevent_expansion--;

1176 }

 

The system supports #pragma operators have been registered by cpp_register_pragma, and lookup_pragma_entry will return the entry for the registered operator. The registered handlers form a hierachical structure, for our example, cpp_get_token at line 1152 then gets token of dependency, which is registered under handler of GCC. Notice that when handling #pragma operators, no macro is allowed expanding by setting prevent_expansion nonzero at line 1143.

If the operator is not registered, hook def_pragma at line 1169 will be executed which will give out warning message. For our example, the operator is done by do_pragma_dependency.

5.3.1.3.1.            Handler of #pragma GCC dependency

When declaring #pragma GCC dependency parse.y in the file, it means the file depends upon parse.y, if parse.y is newer, the file need update.

 

1248 static void

1249 do_pragma_dependency (cpp_reader *pfile)                                                        in cpplib.c

1250 {

1251   const char *fname;

1252   int angle_brackets, ordering;

1253

1254   fname = parse_include (pfile, &angle_brackets);

1255   if (!fname)

1256     return;

1257

1258   ordering = _cpp_compare_file_date (pfile, fname, angle_brackets);

1259   if (ordering < 0)

1260     cpp_error (pfile, CPP_DL_WARNING, "cannot find source file %s", fname);

1261   else if (ordering > 0)

1262   {

1263     cpp_error (pfile, CPP_DL_WARNING,

1264              "current file is older than %s", fname);

1265     if (cpp_get_token (pfile)->type != CPP_EOF)

1266     {

1267       _cpp_backup_tokens (pfile, 1);

1268       do_diagnostic (pfile, CPP_DL_WARNING, 0);

1269     }

1270   }

1271

1272   free ((void *) fname);

1273 }

 

The filename appointed in the directive can be in form of <file>, which is regarded as system header file and will be searched under corresponding searching path. Routine parse_include helps to collect the name of the file and determine whether it is system ones.

 

634  static const char *

635  parse_include (cpp_reader *pfile, int *pangle_brackets)                                in cpplib.c

636  {

637    char *fname;

638    const cpp_token *header;

639 

640   /* Allow macro expansion.  */

641    header = get_token_no_padding (pfile);

642    if (header->type == CPP_STRING || header->type == CPP_HEADER_NAME)

643    {

644      fname = xmalloc (header->val.str.len - 1);

645      memcpy (fname, header->val.str.text + 1, header->val.str.len - 2);

646      fname[header->val.str.len - 2] = '/0';

647      *pangle_brackets = header->type == CPP_HEADER_NAME;

648    }

649    else if (header->type == CPP_LESS)

650    {

651      fname = glue_header_name (pfile);

652      *pangle_brackets = 1;

653    }

654    else

655    {

656      const unsigned char *dir;

657 

658      if (pfile->directive == &dtable[T_PRAGMA])

659        dir = U"pragma dependency";

660      else

661        dir = pfile->directive->name;

662      cpp_error(pfile, CPP_DL_ERROR, "#%s expects /"FILENAME/" or <FILENAME>",

663              dir);

664 

665      return NULL;

666    }

667 

668    check_eol (pfile);

669    return fname;

670  }

 

Clearly, only alphabet, ‘<’ and ‘>’ can appear within the filename, otherwise error message will be given out. After collecting information of the file name, _cpp_compare_file_date will search out the file according to the same searching rule for including file, and returns the result of timestamp comparison.

 

1023 int

1024 _cpp_compare_file_date (cpp_reader *pfile, const char *fname,                     in cppfiles.c

1025               int angle_brackets)

1026 {

1027   _cpp_file *file;

1028   struct cpp_dir *dir;

1029

1030   dir = search_path_head (pfile, fname, angle_brackets, IT_INCLUDE);

1031   if (!dir)

1032     return -1;

1033

1034   file = _cpp_find_file (pfile, fname, dir, false, angle_brackets);

1035   if (file->err_no)

1036     return -1;

1037

1038   if (file->fd != -1)

1039   {

1040     close (file->fd);

1041     file->fd = -1;

1042   }

1043

1044   return file->st.st_mtime > pfile->buffer->file->st.st_mtime;

1045 }

 

When finds out current file is older, the #pragma operator will give out a warning.

5.3.1.4.    Handle other builtin macros

If it is other builtin macro, following part of builtin_macro is executed.

 

builtin_macro (continue)

 

267    buf = _cpp_builtin_macro_text (pfile, node);

268    len = ustrlen (buf);

269    nbuf = alloca (len + 1);

270    memcpy (nbuf, buf, len);

271    nbuf[len]='/n';

272 

273    cpp_push_buffer (pfile, (uchar *) nbuf, len, /* from_stage3 */ true);

274    _cpp_clean_line (pfile);

275 

276    /* Set pfile->cur_token as required by _cpp_lex_direct.  */

277    pfile->cur_token = _cpp_temp_token (pfile);

278    push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);

279    if (pfile->buffer->cur != pfile->buffer->rlimit)

280      cpp_error (pfile, CPP_DL_ICE, "invalid built-in macro /"%s/"",

281               NODE_NAME (node));

282    _cpp_pop_buffer (pfile);

283 

284    return 1;

285  }

 

All these builtin macros are informational. Section Do file change describes details about file including chain built with struct line_map. Among them, __BASE_FILE__ expands to the name of the main input file.

 

116   const uchar *

117   _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)               in cppmacro.c

118   {

119     const uchar *result = NULL;

120    unsigned int number = 1;

121 

122    switch (node->value.builtin)

123    {

124      default:

125        cpp_error (pfile, CPP_DL_ICE, "invalid built-in macro /"%s/"",

126         NODE_NAME (node));

127        break;

128 

129      case BT_FILE:

130      case BT_BASE_FILE:

131      {

132        unsigned int len;

133        const char *name;

134        uchar *buf;

135        const struct line_map *map = pfile->map;

136 

137        if (node->value.builtin == BT_BASE_FILE)

138          while (!MAIN_FILE_P (map))

139            map = INCLUDED_FROM (&pfile->line_maps, map);

140 

141        name = map->to_file;

142        len = strlen (name);

143        buf = _cpp_unaligned_alloc (pfile, len * 4 + 3);

144        result = buf;

145        *buf = '"';

146        buf = cpp_quote_string (buf + 1, (const unsigned char *) name, len);

147        *buf++ = '"';

148        *buf = '/0';

149        }

150        break;

151 

152      case BT_INCLUDE_LEVEL:

153        /* The line map depth counts the primary source as level 1, but

154          historically __INCLUDE_DEPTH__ has called the primary source

155          level 0.  */

156        number = pfile->line_maps.depth - 1;

157        break;

158 

159      case BT_SPECLINE:

160        /* If __LINE__ is embedded in a macro, it must expand to the

161          line of the macro's invocation, not its definition.

162          Otherwise things like assert() will not work properly.  */

163        if (CPP_OPTION (pfile, traditional))

164          number = pfile->line;

165        else

166          number = pfile->cur_token[-1].line;

167        number = SOURCE_LINE (pfile->map, number);

168        break;

169 

170        /* __STDC__ has the value 1 under normal circumstances.

171          However, if (a) we are in a system header, (b) the option

172          stdc_0_in_system_headers is true (set by target config), and

173          (c) we are not in strictly conforming mode, then it has the

174          value 0.  */

175      case BT_STDC:

176      {

177        if (CPP_IN_SYSTEM_HEADER (pfile)

178            && CPP_OPTION (pfile, stdc_0_in_system_headers)

179            && !CPP_OPTION (pfile,std))

180          number = 0;

181        else

182          number = 1;

183      }

184      break;

185 

186      case BT_DATE:

187      case BT_TIME:

188        if (pfile->date == NULL)

189        {

190          /* Allocate __DATE__ and __TIME__ strings from permanent

191            storage. We only do this once, and don't generate them

192            at init time, because time() and localtime() are very

193            slow on some systems.  */

194          time_t tt;

195          struct tm *tb = NULL;

196 

197          /* (time_t) -1 is a legitimate value for "number of seconds

198            since the Epoch", so we have to do a little dance to

199            distinguish that from a genuine error.  */

200          errno = 0;

201          tt = time(NULL);

202          if (tt != (time_t)-1 || errno == 0)

203            tb = localtime (&tt);

204 

205          if (tb)

206          {

207            pfile->date = _cpp_unaligned_alloc (pfile,

208                                          sizeof ("/"Oct 11 1347/""));

209            sprintf ((char *) pfile->date, "/"%s %2d %4d/"",

210                  monthnames[tb->tm_mon], tb->tm_mday,

211                   tb->tm_year + 1900);

212 

213            pfile->time = _cpp_unaligned_alloc (pfile,

214                                          sizeof ("/"12:34:56/""));

215            sprintf ((char *) pfile->time, "/"%02d:%02d:%02d/"",

216                   tb->tm_hour, tb->tm_min, tb->tm_sec);

217          }

218          else

219          {

220            cpp_errno (pfile, CPP_DL_WARNING,

221                     "could not determine date and time");

222        

223            pfile->date = U"/"??? ?? ????/"";

224            pfile->time = U"/"??:??:??/"";

225          }

226        }

227 

228      if (node->value.builtin == BT_DATE)

229        result = pfile->date;

230      else

231        result = pfile->time;

232      break;

233    }

234 

235    if (result == NULL)

236    {

237      /* 21 bytes holds all NUL-terminated unsigned 64-bit numbers.  */

238      result = _cpp_unaligned_alloc (pfile, 21);

239      sprintf ((char *) result, "%u", number);

240    }

241 

242    return result;     

243  }

 

你可能感兴趣的:(Studying note of GCC-3.4.6 source (75))