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.
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.
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 }