Studying note of GCC-3.4.6 source (30)

4.1.3. Read in source file

As now cpp_reader is ready, it is time to read in source files. Below, macro input_line accesses line field of global variable input_location which records the current file name and current handling line number.

 

c_common_post_option (continue)

 

1162   saved_lineno = input_line;

1163   input_line = 0;

1164

1165   /* If an error has occurred in cpplib, note it so we fail

1166     immediately.  */

1167   errorcount += cpp_errors (parse_in);

1168

1169   *pfilename = this_input_filename

1170     = cpp_read_main_file (parse_in, in_fnames[0]);

1171   /* Don't do any compilation or preprocessing if there is no input file.  */

1172   if (this_input_filename == NULL)

1173   {

1174     errorcount++;

1175     return false;

1176   }

1177

1178   if (flag_working_directory

1179       && flag_preprocess_only && ! flag_no_line_commands)

1180     pp_dir_change (parse_in, get_src_pwd ());

1181

1182   return flag_preprocess_only;

1183 }

 

 

Note that in_fnames[0] above holds the first input file in command line (see line 453 in handle_options). It will be the source file (or one of ).

 

456    const char *

457    cpp_read_main_file (cpp_reader *pfile, const char *fname)                         in cppinit.c

458    {

459      if (CPP_OPTION (pfile, deps.style) != DEPS_NONE)

460      {

461        if (!pfile->deps)

462          pfile->deps = deps_init ();

463   

464        /* Set the default target (if there is none already).  */

465        deps_add_default_target (pfile->deps, fname);

466      }

 

First, if applies –M(M), or –M(M)D, or environment variable DEPENDENCIES_OUTPUT to ask compiler to generate dependency rule for make program, it needs collect target usable by make. Below at line 181, if the target is “-“, it means output to stdout; and for other target, propriate suffix will be appended to the target file if not specified.

 

173    void

174    deps_add_default_target (struct deps *d, const char *tgt)                                    in mkdeps.c

175    {

176      /* Only if we have no targets.  */

177      if (d->ntargets)

178        return;

179   

180      if (tgt[0] == '/0')

181        deps_add_target (d, "-", 1);

182      else

183      {

184    #ifndef TARGET_OBJECT_SUFFIX

185    # define TARGET_OBJECT_SUFFIX ".o"

186    #endif

187        const char *start = lbasename (tgt);

188        char *o = alloca (strlen (start) + strlen (TARGET_OBJECT_SUFFIX) + 1);

189        char *suffix;

190   

191        strcpy (o, start);

192   

193        suffix = strrchr (o, '.');

194        if (!suffix)

195          suffix = o + strlen (o);

196        strcpy (suffix, TARGET_OBJECT_SUFFIX);

197   

198        deps_add_target (d, o, 1);

199      }

200    }

 

Other 2 switches that can generate make dependency rule are –MT and –MQ, which are processed by handle_deferred_opts, and in it the invoked cpp_add_dependency_target, and then deps_add_target, both argument quote is 1 if –MQ in use, otherwise is 0. But here, quote is always 1.

 

152    void

153    deps_add_target (struct deps *d, const char *t, int quote)                                    in mkdeps.c

154    {

155      if (d->ntargets == d->targets_size)

156      {

157        d->targets_size = d->targets_size * 2 + 4;

158        d->targetv = xrealloc (d->targetv,

159                            d->targets_size * sizeof (const char *));

160      }

161   

162      if (quote)

163        t = munge (t);  /* Also makes permanent copy.  */

164      else

165        t = xstrdup (t);

166   

167      d->targetv[d->ntargets++] = t;

168    }

 

munge saves target name into GCC expected form. The major issue is replacing every single ‘/’ with ‘//’, and single ‘$’ with ‘$$’.

 

49      static const char *

50      munge (const char *filename)                                                                   in mkdeps.c

51      {

52        int len;

53        const char *p, *q;

54        char *dst, *buffer;

55     

56        for (p = filename, len = 0; *p; p++, len++)

57        {

58          switch (*p)

59          {

60            case ' ':

61            case '/t':

62              /* GNU make uses a weird quoting scheme for white space.

63                A space or tab preceded by 2N+1 backslashes represents

64                N backslashes followed by space; a space or tab

65                preceded by 2N backslashes represents N backslashes at

66                the end of a file name; and backslashes in other

67                contexts should not be doubled.  */

68              for (q = p - 1; filename <= q && *q == '//';  q--)

69                len++;

70              len++;

71              break;

72     

73            case '$':

74              /* '$' is quoted by doubling it.  */

75              len++;

76              break;

77          }

78        }

79     

80        /* Now we know how big to make the buffer.  */

81        buffer = xmalloc (len + 1);

82     

83        for (p = filename, dst = buffer; *p; p++, dst++)

84        {

85          switch (*p)

86          {

87            case ' ':

88            case '/t':

89              for (q = p - 1; filename <= q && *q == '//';  q--)

90                *dst++ = '//';

91              *dst++ = '//';

92              break;

93     

94            case '$':

95              *dst++ = '$';

96              break;

97     

98            default:

99              /* nothing */;

100        }

101        *dst = *p;

102      }

103   

104      *dst = '/0';

105      return buffer;

106    }

 

Always keep in mind, among switches that producing make dependency rule, except -M(M)D, other swith implies a –E option which is added by GCC’s shell.

4.1.3.1.    Find and read in the file

 

cpp_read_main_file (continue)

 

468    pfile->main_file

469      = _cpp_find_file (pfile, fname, &pfile->no_search_path, false, 0);

470    if (_cpp_find_failed (pfile->main_file))

471      return NULL;

 

In cpp_reader, there are three search paths – bracket_include for header files included by angle bracket (< >), quote_include for header files included by quote (“”), no_search_path for absolute paths. Notice that in Handling Options Related To Including Chain, bracket_include and quote_include have been setup and linked tegother. Now we are not handling header files, so use no_search_path as search path here (it is “”).

 

362  _cpp_file *

363  _cpp_find_file (cpp_reader *pfile, const char *fname,                                   in cppfiles.c

364               cpp_dir *start_dir, bool fake, int angle_brackets)

365  {

366    struct file_hash_entry *entry, **hash_slot;

367    _cpp_file*file;

368    bool invalid_pch = false;

369 

370    /* Ensure we get no confusion between cached files and directories.  */

371    if (start_dir == NULL)

372      cpp_error (pfile, CPP_DL_ICE, "NULL directory in find_file");

373 

374    hash_slot = (struct file_hash_entry **)

375      htab_find_slot_with_hash (pfile->file_hash, fname,

376                             htab_hash_string (fname),

377                             INSERT);

378 

379    /* First check the cache before we resort to memory allocation.  */

380    entry = search_cache (*hash_slot, start_dir);

381    if (entry)

382      return entry->u.file;

383 

384    file = make_cpp_file (pfile, start_dir, fname);

 

All files have been found will be recorded by a hashtable (file_hash field of cpp_reader) to make later visit as quick as possible. The element the hashtable is type file_hash_entry as following.

 

145  struct file_hash_entry                                                                                  in cppfiles.c

146  {

147    struct file_hash_entry *next;

148    cpp_dir *start_dir;

149    union

150    {

151      _cpp_file *file;

152      cpp_dir *dir;

153    } u;

154  };

 

And opened source files are recorded by structure _cpp_file in below.

 

57    struct _cpp_file                                                                                          in cppfiles.c

58    {

59      /* Filename as given to #include or command line switch.  */

60      const char *name;

61   

62      /* The full path used to find the file.  */

63      const char *path;

64   

65      /* The full path of the pch file.  */

66      const char *pchname;

67   

68      /* The file's path with the basename stripped. NULL if it hasn't

69        been calculated yet.  */

70      const char *dir_name;

71   

72      /* Chain through all files.  */

73      struct _cpp_file *next_file;

74   

75     /* The contents of NAME after calling read_file().  */

76      const uchar *buffer;

77   

78      /* The macro, if any, preventing re-inclusion.  */

79      const cpp_hashnode *cmacro;

80   

81      /* The directory in the search path where FILE was found. Used for

82        #include_next and determining whether a header is a system

83        header.  */

84      cpp_dir *dir;

85   

86     /* As filled in by stat(2) for the file.  */

87      struct stat st;

88   

89      /* File descriptor. Invalid if -1, otherwise open.  */

90      int fd;

91   

92      /* Zero if this file was successfully opened and stat()-ed,

93        otherwise errno obtained from failure.  */

94      int err_no;

95   

96      /* Number of times the file has been stacked for preprocessing.  */

97      unsigned short stack_count;

98   

99      /* If opened with #import or contains #pragma once.  */

100    bool once_only;

101 

102   /* If read() failed before.  */

103    bool dont_read;

104 

105   /* If this file is the main file.  */

106    bool main_file;

107 

108    /* If BUFFER above contains the true contents of the file.  */

109    bool buffer_valid;

110 

111    /* 0: file not known to be a PCH.

112      1: file is a PCH (on return from find_include_file).

113      2: file is not and never will be a valid precompiled header.

114      3: file is always a valid precompiled header.  */

115    uchar pch;

116  };

 

Here if start_dir is no_search_path (its content is””), means the cached file is a source file. If the cached file is a header file, start_dir should be the containing directory. At the invocation, head is a chain constructed by files of the same name in different directories, which has the name we are looking for.

 

788  static struct file_hash_entry *

789  search_cache (struct file_hash_entry *head, const cpp_dir *start_dir)              in cppfiles.c

790  {

791    while (head && head->start_dir != start_dir)

792      head = head->next;

793 

794    return head;

795  }

 

If the file hasn’t been cached with hashtable, it needs create an object of _cpp_file for the file by make_cpp_file as we are trying to find then open and cache it.

 

798  static _cpp_file *

799  make_cpp_file (cpp_reader *pfile, cpp_dir *dir, const char *fname)                      in cppfiles.c

800  {

801    _cpp_file *file;

802 

803    file = xcalloc (1, sizeof (_cpp_file));

804    file->main_file = !pfile->buffer;

805    file->fd = -1;

806    file->dir = dir;

807    file->name = xstrdup (fname);

808 

809    return file;

810  }

 

After the instance of _cpp_file is ready for the file interested, the file will be checked if it exists under specified path. If not exists, related search paths will be tried till the file is found or no more path left. See that when using no_search_path as the search path, once no file is found under specified directory, gives out error message immediately. While bracket_include or quote_include, set according to system or command line or environment variable, ususally contains several ordered diretories.

 

_cpp_find_file (continue)

 

386   /* Try each path in the include chain.  */

387    for (; !fake ;)

388    {

389      if (find_file_in_dir (pfile, file, &invalid_pch))

390        break;

391 

392      file->dir = file->dir->next;

393      if (file->dir == NULL)

394      {

395        open_file_failed (pfile, file, angle_brackets);

396        if (invalid_pch)

397        {

398          cpp_error (pfile, CPP_DL_ERROR,

399                  "one or more PCH files were found, but they were invalid");

400         if (!cpp_get_options (pfile)->warn_invalid_pch)

401            cpp_error (pfile, CPP_DL_ERROR,

402                   "use -Winvalid-pch for more information");

403        }

404        break;

405      }

406 

407      /* Only check the cache for the starting location (done above)

408        and the quote and bracket chain heads because there are no

409        other possible starting points for searches.  */

410      if (file->dir != pfile->bracket_include

411         && file->dir != pfile->quote_include)

412        continue;

413 

414      entry = search_cache (*hash_slot, file->dir);

415      if (entry)

416        break;

417    }

 

Below at line 319, remap is set for system only supporting short filename such as dos, which needs remap_filename to map the filename. Otherwise at line 322, append_file_to_dir creates the abosule path by appending filename to the direcoty path, note that maybe no file exists with the created path.

 

314  static bool

315  find_file_in_dir (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)          in cppfiles.c

316  {

317    char *path;

318 

319    if (CPP_OPTION (pfile, remap) && (path = remap_filename (pfile, file)))

320      ;

321    else

322      path = append_file_to_dir (file->name, file->dir);

323 

324    file->path = path;

325    if (pch_open_file (pfile, file, invalid_pch))

326      return true;

327 

328    if (open_file (file))

329      return true;

330 

331    if (file->err_no != ENOENT)

332    {

333      open_file_failed (pfile, file, 0);

334      return true;

335    }

336 

337    free (path);

338    file->path = file->name;

339    return false;

340  }

 

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