OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libcpp/] [mkdeps.c] - Blame information for rev 768

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 730 jeremybenn
/* Dependency generator for Makefile fragments.
2
   Copyright (C) 2000, 2001, 2003, 2007, 2008, 2009
3
   Free Software Foundation, Inc.
4
   Contributed by Zack Weinberg, Mar 2000
5
 
6
This program is free software; you can redistribute it and/or modify it
7
under the terms of the GNU General Public License as published by the
8
Free Software Foundation; either version 3, or (at your option) any
9
later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; see the file COPYING3.  If not see
18
<http://www.gnu.org/licenses/>.
19
 
20
 In other words, you are welcome to use, share and improve this program.
21
 You are forbidden to forbid anyone else to use, share and improve
22
 what you give them.   Help stamp out software-hoarding!  */
23
 
24
#include "config.h"
25
#include "system.h"
26
#include "mkdeps.h"
27
 
28
/* Keep this structure local to this file, so clients don't find it
29
   easy to start making assumptions.  */
30
struct deps
31
{
32
  const char **targetv;
33
  unsigned int ntargets;        /* number of slots actually occupied */
34
  unsigned int targets_size;    /* amt of allocated space - in words */
35
 
36
  const char **depv;
37
  unsigned int ndeps;
38
  unsigned int deps_size;
39
 
40
  const char **vpathv;
41
  size_t *vpathlv;
42
  unsigned int nvpaths;
43
  unsigned int vpaths_size;
44
};
45
 
46
static const char *munge (const char *);
47
 
48
/* Given a filename, quote characters in that filename which are
49
   significant to Make.  Note that it's not possible to quote all such
50
   characters - e.g. \n, %, *, ?, [, \ (in some contexts), and ~ are
51
   not properly handled.  It isn't possible to get this right in any
52
   current version of Make.  (??? Still true?  Old comment referred to
53
   3.76.1.)  */
54
 
55
static const char *
56
munge (const char *filename)
57
{
58
  int len;
59
  const char *p, *q;
60
  char *dst, *buffer;
61
 
62
  for (p = filename, len = 0; *p; p++, len++)
63
    {
64
      switch (*p)
65
        {
66
        case ' ':
67
        case '\t':
68
          /* GNU make uses a weird quoting scheme for white space.
69
             A space or tab preceded by 2N+1 backslashes represents
70
             N backslashes followed by space; a space or tab
71
             preceded by 2N backslashes represents N backslashes at
72
             the end of a file name; and backslashes in other
73
             contexts should not be doubled.  */
74
          for (q = p - 1; filename <= q && *q == '\\';  q--)
75
            len++;
76
          len++;
77
          break;
78
 
79
        case '$':
80
          /* '$' is quoted by doubling it.  */
81
          len++;
82
          break;
83
 
84
        case '#':
85
          /* '#' is quoted with a backslash.  */
86
          len++;
87
          break;
88
        }
89
    }
90
 
91
  /* Now we know how big to make the buffer.  */
92
  buffer = XNEWVEC (char, len + 1);
93
 
94
  for (p = filename, dst = buffer; *p; p++, dst++)
95
    {
96
      switch (*p)
97
        {
98
        case ' ':
99
        case '\t':
100
          for (q = p - 1; filename <= q && *q == '\\';  q--)
101
            *dst++ = '\\';
102
          *dst++ = '\\';
103
          break;
104
 
105
        case '$':
106
          *dst++ = '$';
107
          break;
108
 
109
        case '#':
110
          *dst++ = '\\';
111
          break;
112
 
113
        default:
114
          /* nothing */;
115
        }
116
      *dst = *p;
117
    }
118
 
119
  *dst = '\0';
120
  return buffer;
121
}
122
 
123
/* If T begins with any of the partial pathnames listed in d->vpathv,
124
   then advance T to point beyond that pathname.  */
125
static const char *
126
apply_vpath (struct deps *d, const char *t)
127
{
128
  if (d->vpathv)
129
    {
130
      unsigned int i;
131
      for (i = 0; i < d->nvpaths; i++)
132
        {
133
          if (!filename_ncmp (d->vpathv[i], t, d->vpathlv[i]))
134
            {
135
              const char *p = t + d->vpathlv[i];
136
              if (!IS_DIR_SEPARATOR (*p))
137
                goto not_this_one;
138
 
139
              /* Do not simplify $(vpath)/../whatever.  ??? Might not
140
                 be necessary. */
141
              if (p[1] == '.' && p[2] == '.' && IS_DIR_SEPARATOR (p[3]))
142
                goto not_this_one;
143
 
144
              /* found a match */
145
              t = t + d->vpathlv[i] + 1;
146
              break;
147
            }
148
        not_this_one:;
149
        }
150
    }
151
 
152
  /* Remove leading ./ in any case.  */
153
  while (t[0] == '.' && IS_DIR_SEPARATOR (t[1]))
154
    {
155
      t += 2;
156
      /* If we removed a leading ./, then also remove any /s after the
157
         first.  */
158
      while (IS_DIR_SEPARATOR (t[0]))
159
        ++t;
160
    }
161
 
162
  return t;
163
}
164
 
165
/* Public routines.  */
166
 
167
struct deps *
168
deps_init (void)
169
{
170
  return XCNEW (struct deps);
171
}
172
 
173
void
174
deps_free (struct deps *d)
175
{
176
  unsigned int i;
177
 
178
  if (d->targetv)
179
    {
180
      for (i = 0; i < d->ntargets; i++)
181
        free ((void *) d->targetv[i]);
182
      free (d->targetv);
183
    }
184
 
185
  if (d->depv)
186
    {
187
      for (i = 0; i < d->ndeps; i++)
188
        free ((void *) d->depv[i]);
189
      free (d->depv);
190
    }
191
 
192
  if (d->vpathv)
193
    {
194
      for (i = 0; i < d->nvpaths; i++)
195
        free ((void *) d->vpathv[i]);
196
      free (d->vpathv);
197
      free (d->vpathlv);
198
    }
199
 
200
  free (d);
201
}
202
 
203
/* Adds a target T.  We make a copy, so it need not be a permanent
204
   string.  QUOTE is true if the string should be quoted.  */
205
void
206
deps_add_target (struct deps *d, const char *t, int quote)
207
{
208
  if (d->ntargets == d->targets_size)
209
    {
210
      d->targets_size = d->targets_size * 2 + 4;
211
      d->targetv = XRESIZEVEC (const char *, d->targetv, d->targets_size);
212
    }
213
 
214
  t = apply_vpath (d, t);
215
  if (quote)
216
    t = munge (t);  /* Also makes permanent copy.  */
217
  else
218
    t = xstrdup (t);
219
 
220
  d->targetv[d->ntargets++] = t;
221
}
222
 
223
/* Sets the default target if none has been given already.  An empty
224
   string as the default target in interpreted as stdin.  The string
225
   is quoted for MAKE.  */
226
void
227
deps_add_default_target (struct deps *d, const char *tgt)
228
{
229
  /* Only if we have no targets.  */
230
  if (d->ntargets)
231
    return;
232
 
233
  if (tgt[0] == '\0')
234
    deps_add_target (d, "-", 1);
235
  else
236
    {
237
#ifndef TARGET_OBJECT_SUFFIX
238
# define TARGET_OBJECT_SUFFIX ".o"
239
#endif
240
      const char *start = lbasename (tgt);
241
      char *o = (char *) alloca (strlen (start)
242
                                 + strlen (TARGET_OBJECT_SUFFIX) + 1);
243
      char *suffix;
244
 
245
      strcpy (o, start);
246
 
247
      suffix = strrchr (o, '.');
248
      if (!suffix)
249
        suffix = o + strlen (o);
250
      strcpy (suffix, TARGET_OBJECT_SUFFIX);
251
 
252
      deps_add_target (d, o, 1);
253
    }
254
}
255
 
256
void
257
deps_add_dep (struct deps *d, const char *t)
258
{
259
  t = munge (apply_vpath (d, t));  /* Also makes permanent copy.  */
260
 
261
  if (d->ndeps == d->deps_size)
262
    {
263
      d->deps_size = d->deps_size * 2 + 8;
264
      d->depv = XRESIZEVEC (const char *, d->depv, d->deps_size);
265
    }
266
  d->depv[d->ndeps++] = t;
267
}
268
 
269
void
270
deps_add_vpath (struct deps *d, const char *vpath)
271
{
272
  const char *elem, *p;
273
  char *copy;
274
  size_t len;
275
 
276
  for (elem = vpath; *elem; elem = p)
277
    {
278
      for (p = elem; *p && *p != ':'; p++);
279
      len = p - elem;
280
      copy = XNEWVEC (char, len + 1);
281
      memcpy (copy, elem, len);
282
      copy[len] = '\0';
283
      if (*p == ':')
284
        p++;
285
 
286
      if (d->nvpaths == d->vpaths_size)
287
        {
288
          d->vpaths_size = d->vpaths_size * 2 + 8;
289
          d->vpathv = XRESIZEVEC (const char *, d->vpathv, d->vpaths_size);
290
          d->vpathlv = XRESIZEVEC (size_t, d->vpathlv, d->vpaths_size);
291
        }
292
      d->vpathv[d->nvpaths] = copy;
293
      d->vpathlv[d->nvpaths] = len;
294
      d->nvpaths++;
295
    }
296
}
297
 
298
void
299
deps_write (const struct deps *d, FILE *fp, unsigned int colmax)
300
{
301
  unsigned int size, i, column;
302
 
303
  column = 0;
304
  if (colmax && colmax < 34)
305
    colmax = 34;
306
 
307
  for (i = 0; i < d->ntargets; i++)
308
    {
309
      size = strlen (d->targetv[i]);
310
      column += size;
311
      if (i)
312
        {
313
          if (colmax && column > colmax)
314
            {
315
              fputs (" \\\n ", fp);
316
              column = 1 + size;
317
            }
318
          else
319
            {
320
              putc (' ', fp);
321
              column++;
322
            }
323
        }
324
      fputs (d->targetv[i], fp);
325
    }
326
 
327
  putc (':', fp);
328
  column++;
329
 
330
  for (i = 0; i < d->ndeps; i++)
331
    {
332
      size = strlen (d->depv[i]);
333
      column += size;
334
      if (colmax && column > colmax)
335
        {
336
          fputs (" \\\n ", fp);
337
          column = 1 + size;
338
        }
339
      else
340
        {
341
          putc (' ', fp);
342
          column++;
343
        }
344
      fputs (d->depv[i], fp);
345
    }
346
  putc ('\n', fp);
347
}
348
 
349
void
350
deps_phony_targets (const struct deps *d, FILE *fp)
351
{
352
  unsigned int i;
353
 
354
  for (i = 1; i < d->ndeps; i++)
355
    {
356
      putc ('\n', fp);
357
      fputs (d->depv[i], fp);
358
      putc (':', fp);
359
      putc ('\n', fp);
360
    }
361
}
362
 
363
/* Write out a deps buffer to a file, in a form that can be read back
364
   with deps_restore.  Returns nonzero on error, in which case the
365
   error number will be in errno.  */
366
 
367
int
368
deps_save (struct deps *deps, FILE *f)
369
{
370
  unsigned int i;
371
 
372
  /* The cppreader structure contains makefile dependences.  Write out this
373
     structure.  */
374
 
375
  /* The number of dependences.  */
376
  if (fwrite (&deps->ndeps, sizeof (deps->ndeps), 1, f) != 1)
377
      return -1;
378
  /* The length of each dependence followed by the string.  */
379
  for (i = 0; i < deps->ndeps; i++)
380
    {
381
      size_t num_to_write = strlen (deps->depv[i]);
382
      if (fwrite (&num_to_write, sizeof (size_t), 1, f) != 1)
383
          return -1;
384
      if (fwrite (deps->depv[i], num_to_write, 1, f) != 1)
385
          return -1;
386
    }
387
 
388
  return 0;
389
}
390
 
391
/* Read back dependency information written with deps_save into
392
   the deps buffer.  The third argument may be NULL, in which case
393
   the dependency information is just skipped, or it may be a filename,
394
   in which case that filename is skipped.  */
395
 
396
int
397
deps_restore (struct deps *deps, FILE *fd, const char *self)
398
{
399
  unsigned int i, count;
400
  size_t num_to_read;
401
  size_t buf_size = 512;
402
  char *buf = XNEWVEC (char, buf_size);
403
 
404
  /* Number of dependences.  */
405
  if (fread (&count, 1, sizeof (count), fd) != sizeof (count))
406
    return -1;
407
 
408
  /* The length of each dependence string, followed by the string.  */
409
  for (i = 0; i < count; i++)
410
    {
411
      /* Read in # bytes in string.  */
412
      if (fread (&num_to_read, 1, sizeof (size_t), fd) != sizeof (size_t))
413
        return -1;
414
      if (buf_size < num_to_read + 1)
415
        {
416
          buf_size = num_to_read + 1 + 127;
417
          buf = XRESIZEVEC (char, buf, buf_size);
418
        }
419
      if (fread (buf, 1, num_to_read, fd) != num_to_read)
420
        return -1;
421
      buf[num_to_read] = '\0';
422
 
423
      /* Generate makefile dependencies from .pch if -nopch-deps.  */
424
      if (self != NULL && filename_cmp (buf, self) != 0)
425
        deps_add_dep (deps, buf);
426
    }
427
 
428
  free (buf);
429
  return 0;
430
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.