OSDN Git Service

* cpp.texi: Update for -MT.
[pf3gnuchains/gcc-fork.git] / gcc / mkdeps.c
1 /* Dependency generator for Makefile fragments.
2    Copyright (C) 2000, 2001 Free Software Foundation, Inc.
3    Contributed by Zack Weinberg, Mar 2000
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19  In other words, you are welcome to use, share and improve this program.
20  You are forbidden to forbid anyone else to use, share and improve
21  what you give them.   Help stamp out software-hoarding!  */
22
23 #include "config.h"
24 #include "system.h"
25 #include "mkdeps.h"
26
27 /* Keep this structure local to this file, so clients don't find it
28    easy to start making assumptions.  */
29 struct deps
30 {
31   const char **targetv;
32   unsigned int ntargets;        /* number of slots actually occupied */
33   unsigned int targets_size;    /* amt of allocated space - in words */
34
35   const char **depv;
36   unsigned int ndeps;
37   unsigned int deps_size;
38 };
39
40 static const char *munge        PARAMS ((const char *));
41 static const char *base_name    PARAMS ((const char *));
42
43 /* Given a filename, quote characters in that filename which are
44    significant to Make.  Note that it's not possible to quote all such
45    characters - e.g. \n, %, *, ?, [, \ (in some contexts), and ~ are
46    not properly handled.  It isn't possible to get this right in any
47    current version of Make.  (??? Still true?  Old comment referred to
48    3.76.1.)  */
49    
50 static const char *
51 munge (filename)
52      const char *filename;
53 {
54   int len;
55   const char *p, *q;
56   char *dst, *buffer;
57
58   for (p = filename, len = 0; *p; p++, len++)
59     {
60       switch (*p)
61         {
62         case ' ':
63         case '\t':
64           /* GNU make uses a weird quoting scheme for white space.
65              A space or tab preceded by 2N+1 backslashes represents
66              N backslashes followed by space; a space or tab
67              preceded by 2N backslashes represents N backslashes at
68              the end of a file name; and backslashes in other
69              contexts should not be doubled.  */
70           for (q = p - 1; filename <= q && *q == '\\';  q--)
71             len++;
72           len++;
73           break;
74
75         case '$':
76           /* '$' is quoted by doubling it. This can mishandle things
77              like "$(" but there's no easy fix.  */
78           len++;
79           break;
80         }
81     }
82
83   /* Now we know how big to make the buffer.  */
84   buffer = xmalloc (len + 1);
85
86   for (p = filename, dst = buffer; *p; p++, dst++)
87     {
88       switch (*p)
89         {
90         case ' ':
91         case '\t':
92           for (q = p - 1; filename <= q && *q == '\\';  q--)
93             *dst++ = '\\';
94           *dst++ = '\\';
95           break;
96
97         case '$':
98           *dst++ = '$';
99           break;
100
101         default:
102           /* nothing */;
103         }
104       *dst = *p;
105     }
106
107   *dst = '\0';
108   return buffer;
109 }
110
111 /* Given a pathname, calculate the non-directory part.  This always
112    knows how to handle Unix-style pathnames, and understands VMS and
113    DOS paths on those systems.  */
114
115 /* Find the base name of a (partial) pathname FNAME.
116    Returns a pointer into the string passed in.
117    Accepts Unix (/-separated) paths on all systems,
118    DOS and VMS paths on those systems.  */
119
120 static const char *
121 base_name (fname)
122      const char *fname;
123 {
124   const char *s = fname;
125   const char *p;
126 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
127   if (ISALPHA (s[0]) && s[1] == ':') s += 2;
128   if ((p = strrchr (s, '\\'))) s = p + 1;
129 #elif defined VMS
130   if ((p = strrchr (s, ':'))) s = p + 1; /* Skip device.  */
131   if ((p = strrchr (s, ']'))) s = p + 1; /* Skip directory.  */
132   if ((p = strrchr (s, '>'))) s = p + 1; /* Skip alternate (int'n'l) dir.  */
133 #endif
134   if ((p = strrchr (s, '/'))) s = p + 1;
135   return s;
136 }
137
138 /* Public routines.  */
139
140 struct deps *
141 deps_init ()
142 {
143   struct deps *d = (struct deps *) xmalloc (sizeof (struct deps));
144
145   /* Allocate space for the vectors now.  */
146
147   d->targetv = (const char **) xmalloc (2 * sizeof (const char *));
148   d->depv = (const char **) xmalloc (8 * sizeof (const char *));
149
150   d->ntargets = 0;
151   d->targets_size = 2;
152   d->ndeps = 0;
153   d->deps_size = 8;
154
155   return d;
156 }
157
158 void
159 deps_free (d)
160      struct deps *d;
161 {
162   unsigned int i;
163
164   for (i = 0; i < d->ntargets; i++)
165     free ((PTR) d->targetv[i]);
166
167   for (i = 0; i < d->ndeps; i++)
168     free ((PTR) d->depv[i]);
169
170   free (d->targetv);
171   free (d->depv);
172   free (d);
173 }
174
175 void
176 deps_add_target (d, t)
177      struct deps *d;
178      const char *t;
179 {
180   t = munge (t);  /* Also makes permanent copy.  */
181
182   if (d->ntargets == d->targets_size)
183     {
184       d->targets_size *= 2;
185       d->targetv = (const char **) xrealloc (d->targetv,
186                              d->targets_size * sizeof (const char *));
187     }
188
189   d->targetv[d->ntargets++] = t;
190 }
191
192 /* Sets the default target if none has been given already.  An empty
193    string as the default target in interpreted as stdin.  */
194 void
195 deps_add_default_target (d, tgt)
196      struct deps *d;
197      const char *tgt;
198 {
199   char *o, *suffix;
200
201   /* Only if we have no targets.  */
202   if (d->ntargets)
203     return;
204
205   if (tgt[0] == '\0')
206     deps_add_target (d, "-");
207   else
208     {
209       tgt = base_name (tgt);
210       o = (char *) alloca (strlen (tgt) + 8);
211
212       strcpy (o, tgt);
213       suffix = strrchr (o, '.');
214
215 #ifndef OBJECT_SUFFIX
216 # define OBJECT_SUFFIX ".o"
217 #endif
218
219       if (suffix)
220         strcpy (suffix, OBJECT_SUFFIX);
221       else
222         strcat (o, OBJECT_SUFFIX);
223       deps_add_target (d, o);
224     }
225 }
226
227 void
228 deps_add_dep (d, t)
229      struct deps *d;
230      const char *t;
231 {
232   t = munge (t);  /* Also makes permanent copy.  */
233
234   if (d->ndeps == d->deps_size)
235     {
236       d->deps_size *= 2;
237       d->depv = (const char **)
238         xrealloc (d->depv, d->deps_size * sizeof (const char *));
239     }
240   d->depv[d->ndeps++] = t;
241 }
242
243 void
244 deps_write (d, fp, colmax)
245      const struct deps *d;
246      FILE *fp;
247      unsigned int colmax;
248 {
249   unsigned int size, i, column;
250
251   column = 0;
252   if (colmax && colmax < 34)
253     colmax = 34;
254
255   for (i = 0; i < d->ntargets; i++)
256     {
257       size = strlen (d->targetv[i]);
258       column += size;
259       if (colmax && column > colmax)
260         {
261           fputs (" \\\n ", fp);
262           column = 1 + size;
263         }
264       if (i)
265         {
266           putc (' ', fp);
267           column++;
268         }
269       fputs (d->targetv[i], fp);
270     }
271
272   putc (':', fp);
273   putc (' ', fp);
274   column += 2;
275
276   for (i = 0; i < d->ndeps; i++)
277     {
278       size = strlen (d->depv[i]);
279       column += size;
280       if (colmax && column > colmax)
281         {
282           fputs (" \\\n ", fp);
283           column = 1 + size;
284         }
285       if (i)
286         {
287           putc (' ', fp);
288           column++;
289         }
290       fputs (d->depv[i], fp);
291     }
292   putc ('\n', fp);
293 }
294   
295 void
296 deps_dummy_targets (d, fp)
297      const struct deps *d;
298      FILE *fp;
299 {
300   unsigned int i;
301
302   for (i = 1; i < d->ndeps; i++)
303     {
304       fputs (d->depv[i], fp);
305       putc (':', fp);
306       putc ('\n', fp);
307     }
308 }