Studying note of GCC-3.4.6 source (32)

4.1.3.1.2.            Read in file

Above at line 439, if the file has been found and opened successfully,  _cpp_find_file returns the corresponding _cpp_file object, and refered by pfile->main_file. So at this point, it can begin read in the file content.

 

cpp_read_main_file (continue)

 

473      _cpp_stack_file (pfile, pfile->main_file, false);

474   

475      /* For foo.i, read the original filename foo.c now, for the benefit

476        of the front ends.  */

477      if (CPP_OPTION (pfile, preprocessed))

478      {

479        read_original_filename (pfile);

480        if (!pfile->map)

481          return NULL;

482        fname = pfile->map->to_file;

483      }

484      return fname;

485    }

 

In below functions, parameter import is true, if the file is included by #import directive. About the #import directive, [6] gives out below explaination.

GNU CPP supports two more ways of indicating that a header file should be read only once. Neither one is as portable as a wrapper ‘#ifdef’, and we recommend you do not use them in new programs.

In the Objective-C language, there is a variant of ‘#include’ called ‘#import’ which includes a file, but does so at most once. If you use ‘#import’ instead of ‘#include’, then you don’t need the conditionals inside the header file to prevent multiple inclusion of the cntents. GCC premits the use of ‘#import’ in C and C++ as well as Objective-C. However, it is not in standard Cor C++ and should therefore not be used by portable programs.

‘#import’ is not a well designed feature. It requires the users of a header file to know that it should only be included once. It is much better for the header file’s implementor to write the file so that users don’t need to know this. Using a wrapper ‘#ifndef’ accomplishes this goal.

In the present implementation, a single use of ‘#import’ will prevent the file from ever being read again, by either ‘#import’ or ‘#include’. You should not rely on this; do not use both ‘#import’ and ‘#include’ to refer to the same header file.

Another way to prevent aheader file from being included more than once is with the ‘#pragma once’ directive. If ‘#pragm once’ is seen when scanning a header file, that file will never be read again, no matter what.

‘#pragma once’ does not have the problems that ‘#import’ does, but it is not recognize by all preprocessors, so you cannot rely on it in a portable program.

 

643    bool

644    _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import)                  in cppfiles.c

645    {

646      cpp_buffer *buffer;

647      int sysp;

648   

649      if (!should_stack_file (pfile, file, import))

640        return false;

 

Here, for file included by ‘#import’ directive, once_only, seen_once_only will be set at line 563 below in _cpp_mark_file_once_only, so next time the file read again, it will exit at line 556. Then at line 572 below, it checks if the file has a defined header guard.

 

549    static bool

550    should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import)                      in cppfiles.c

551    {

552      _cpp_file *f;

553   

554      /* Skip once-only files.  */

555      if (file->once_only)

556        return false;

557   

558      /* We must mark the file once-only if #import now, before header

559        guard checks. Otherwise, undefining the header guard might

560        cause the file to be re-stacked.  */

561      if (import)

562      {

563        _cpp_mark_file_once_only (pfile, file);

564   

565        /* Don't stack files that have been stacked before.  */

566        if (file->stack_count)

567          return false;

568      }

569   

570      /* Skip if the file had a header guard and the macro is defined.

571        PCH relies on this appearing before the PCH handler below.  */

572      if (file->cmacro && file->cmacro->type == NT_MACRO)

573        return false;

574   

575      /* Handle PCH files immediately; don't stack them.  */

576      if (include_pch_p (file))

577      {

578        pfile->cb.read_pch (pfile, file->path, file->fd, file->pchname);

579        close (file->fd);

580        file->fd = -1;

581        return false;

582      }

4.1.3.1.2.1.      Case of PCH file

Above at line 576, include_pch_p checks the field pch of _cpp_file to see if the file is PCH (precompiled header), this field is set in pch_open_file if the PCH file is validate.

 

375    void

376    c_common_read_pch (cpp_reader *pfile, const char *name,                        in c-pch.c

377                   int fd, const char *orig_name ATTRIBUTE_UNUSED)

378    {

379      FILE *f;

380      struct c_pch_header h;

381      char *buf;

382      unsigned long written;

383      struct save_macro_data *smd;

384     

385      f = fdopen (fd, "rb");

386      if (f == NULL)

387      {

388        cpp_errno (pfile, CPP_DL_ERROR, "calling fdopen");

389        return;

390      }

391   

392      cpp_get_callbacks (parse_in)->valid_pch = NULL;

393   

394      if (fread (&h, sizeof (h), 1, f) != 1)

395      {

396        cpp_errno (pfile, CPP_DL_ERROR, "reading");

397        return;

398      }

399   

400      buf = xmalloc (16384);

401      for (written = 0; written < h.asm_size; )

402      {

403        long size = h.asm_size - written;

404        if (size > 16384)

405          size = 16384;

406        if (fread (buf, size, 1, f) != 1

407          || fwrite (buf, size, 1, asm_out_file) != 1)

408        cpp_errno (pfile, CPP_DL_ERROR, "reading");

409        written += size;

410      }

411       free (buf);

412   

413      cpp_prepare_state (pfile, &smd);

414   

415      gt_pch_restore (f);

416   

417      if (cpp_read_state (pfile, name, f, smd) != 0)

418        return;

419   

420      fclose (f);

421    }

 

Notice that here fd refers to the already opened validate PCH file, by fdopen at line 385 above, we will continue the reading at postion following target_data in the file. At that positon it should contains c_pch_header which only contains a field asm_size, and it indicates the size of the assemble code of the PCH file. It is written into asm_out_file.

If PCH file only contents assemble code, what is difference between it and library? And how can we use the data structures and functions defined in it? Thus, after the part of assemble code, PCH file also includes the content in form of intermediate tree, after reading in this part and merging into the tree of current compilation unit, PCH file acts exactly as normal header.

 

589    void

590    cpp_prepare_state (cpp_reader *r, struct save_macro_data **data)                in cpppch.c

591    {

592      struct save_macro_data *d = xmalloc (sizeof (struct save_macro_data));

593     

594      d->macros = NULL;

595      d->count = ARRAY_SIZE (d->macros->macs);

596      cpp_forall_identifiers (r, save_macros, d);

597      d->saved_pragmas = _cpp_save_pragma_names (r);

598      *data = d;

599    }

 

In cpp_reader, it contains field hash_table which is first initialized in _cpp_init_hashtable. In preprocessing stage, it works as hashtable for visible macros in the file. The instance of cpp_reader always stands for current handling file; now as we are handling PCH header file, we need to update the cpp_reader instance, first it needs save the macros seen so far for current file.

 

546    struct save_macro_item {                                                                          in cpppch.c

547      struct save_macro_item *next;

548      struct cpp_hashnode macs[64];

549    };

 

551    struct save_macro_data

552    {

553      struct save_macro_item *macros;

554      size_t count;

555      char **saved_pragmas;

556    };

 

Note line 595 in cpp_prepare_state, count is 64 for new created buffer.

 

112     void

113     cpp_forall_identifiers (cpp_reader *pfile, cpp_cb cb, void *v)                            in cpppch.c

114     {

115       /* We don't need a proxy since the hash table's identifier comes

116         first in cpp_hashnode.  */

117       ht_forall (pfile->hash_table, (ht_cb) cb, v);

118     }

 

209    void

210    ht_forall (hash_table *table, ht_cb cb, const void *v)                           in hashtable.c

211     {

212      hashnode *p, *limit;

213   

214      p = table->entries;

215      limit = p + table->nslots;

216      do

217        if (*p)

218        {

219          if ((*cb) (table->pfile, *p, v) == 0)

220            break;

221        }

222      while (++p < limit);

223    }

 

Below HT_STR and HT_LEN just access str and len field of ht_identifier of cpp_hashnode. Remember that ht_identifier is the major body of cpp_hashnode and the regular node in hashtable.

 

561    static int                                                                                                 in cpppch.c

562    save_macros (cpp_reader *r ATTRIBUTE_UNUSED, cpp_hashnode *h, void *data_p)

563    {

564      struct save_macro_data *data = (struct save_macro_data *)data_p;

565      if (h->type != NT_VOID

566          && (h->flags & NODE_BUILTIN) == 0)

567      {

568        cpp_hashnode *save;

569        if (data->count == ARRAY_SIZE (data->macros->macs))

570        {

571          struct save_macro_item *d = data->macros;

572          data->macros = xmalloc (sizeof (struct save_macro_item));

573          data->macros->next = d;

574          data->count = 0;

575        }

576        save = data->macros->macs + data->count;

577        data->count++;

578        memcpy (save, h, sizeof (struct cpp_hashnode));

579        HT_STR (&save->ident) = xmemdup (HT_STR (HT_NODE (save)),

580                                     HT_LEN (HT_NODE (save)),

581                                     HT_LEN (HT_NODE (save)) + 1);

582      }

583      return 1;

584    }

4.1.3.1.2.1.1.              #pragma directive in peprocessing

Following paragraphs are extracted from [6] about #pargma directive

The #pragma directive is the method specified by the C standard for providing additional information to the compiler, beyond what is conveyed in the language itself. Three forms of this directive (commonly known as pragmas) are specified by the 1999 C standard. A C compiler is free to attach any meaning it likes to other pragmas.

GCC has historically preferred to use extension to the syntax of the language, such as __attribute__, for this purpose. However, GCC does define a few pragmas of its own. These mostly have effects on the entire translation unit or souce file.

In GCC version 3, all GNU-defined, supported pragmas have been gvien a GCC prefix. This is in line with the STDC prefix on all pragmas defined by C9. For backward compatibility, pragmas which were recoginzed by previous versions are still recognized without the GCC prefix, but that usage is deprecated. Some older pragmas are deprecated in their entirety. They are not recognized with the GCC prefix.

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.

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

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

The pragmas are meaningful to the preprocessor are:

 

#pragma GCC dependency

#pragma GCC dependency allows you to check the relative dates of the current file and another file. If the other file is more recent than the current file, a warning is issued. This is useful if the current file is derived from the other file, and should be regenerated. The other file is searched for using the normal include search path. Optional trailing text can be used to give more information in the warning message.

#pragma GCC dependency “parse.y”

#pramga GCC dependency “/usr/include/time.h” rerun fuxincludes

 

#pragma GCC poison

Sometimes, there is an identifier that you want to remove completely from your program, and make sure that is never creeps back in. To enforce this, you can poison the identifier with this pragma. #pragma GCC poison is followed by a list of identifiers to poison. If any of those identifiers appears anywhere in the source after the directive, it is a hard error. For exmaple,

#pragma GCC poison printf sprintf fprintf

sprintf (some_string, “hello”);

Will produce an error.

If a poisoned identifier appears as part of the expansion of a macro which was defined before the identifier was poisoned, it will not cause an error. This lets you poison an identifier without worrying about system headers defining macros that use it. For example,

#define strrchr rindex

#pragma GCC poison rindex

strrchr (someth_string, ‘h’);

will not produce an error.

 

#pragma GCC system_header

This pragma takes no arguments. It causes the rest of the code in the current file to be treated as if it came from as system header.

 

1095 char **

1096 _cpp_save_pragma_names (cpp_reader *pfile)                                             in cpplib.c

1097 {

1098   int ct = count_registered_pragmas (pfile->pragmas);

1099   char **result = xnewvec (char *, ct);

1100   (void) save_registered_pragmas (pfile->pragmas, result);

1101   return result;

1102 }

 

1062 static int

1063 count_registered_pragmas (struct pragma_entry *pe)                                           in cpplib.c

1064 {

1065   int ct = 0;

1066   for (; pe != NULL; pe = pe->next)

1067   {

1068     if (pe->is_nspace)

1069       ct += count_registered_pragmas (pe->u.space);

1070     ct++;

1071   }

1072   return ct;

1073 }

 

1078 static char **

1079 save_registered_pragmas (struct pragma_entry *pe, char **sd)

1080 {

1081   for (; pe != NULL; pe = pe->next)

1082   {

1083     if (pe->is_nspace)

1084       sd = save_registered_pragmas (pe->u.space, sd);

1085       *sd++ = xmemdup (HT_STR (&pe->pragma->ident),

1086              HT_LEN (&pe->pragma->ident),

1087              HT_LEN (&pe->pragma->ident) + 1);

1088   }

1089   return sd;

1090 }

 

In above examples, GCC forms the space part in pe->u.space at line 1069, within which there are dependency, poison and system_header.  save_registered_paragmas, co-operated with count_registered_pragmas, saves this pragmas tree into the chain constructed with objects of save_macro_data.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值