OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / mkdeps.c
1 /* Dependency generator for Makefile fragments.
2    Copyright (C) 2000 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 static const char *munge        PARAMS ((const char *));
28 static const char *base_name    PARAMS ((const char *));
29
30 #ifndef OBJECT_SUFFIX
31 # define OBJECT_SUFFIX ".o"
32 #endif
33
34 /* Given a filename, quote characters in that filename which are
35    significant to Make.  Note that it's not possible to quote all such
36    characters - e.g. \n, %, *, ?, [, \ (in some contexts), and ~ are
37    not properly handled.  It isn't possible to get this right in any
38    current version of Make.  (??? Still true?  Old comment referred to
39    3.76.1.)  */
40    
41 static const char *
42 munge (filename)
43      const char *filename;
44 {
45   int len;
46   const char *p, *q;
47   char *dst, *buffer;
48
49   for (p = filename, len = 0; *p; p++, len++)
50     {
51       switch (*p)
52         {
53         case ' ':
54         case '\t':
55           /* GNU make uses a weird quoting scheme for white space.
56              A space or tab preceded by 2N+1 backslashes represents
57              N backslashes followed by space; a space or tab
58              preceded by 2N backslashes represents N backslashes at
59              the end of a file name; and backslashes in other
60              contexts should not be doubled.  */
61           for (q = p - 1; filename <= q && *q == '\\';  q--)
62             len++;
63           len++;
64           break;
65
66         case '$':
67           /* '$' is quoted by doubling it. This can mishandle things
68              like "$(" but there's no easy fix.  */
69           len++;
70           break;
71         }
72     }
73
74   /* Now we know how big to make the buffer.  */
75   buffer = malloc (len + 1);
76
77   for (p = filename, dst = buffer; *p; p++, dst++)
78     {
79       switch (*p)
80         {
81         case ' ':
82         case '\t':
83           for (q = p - 1; filename <= q && *q == '\\';  q--)
84             *dst++ = '\\';
85           *dst++ = '\\';
86           break;
87
88         case '$':
89           *dst++ = '$';
90           break;
91
92         default:
93           /* nothing */;
94         }
95       *dst = *p;
96     }
97
98   *dst = '\0';
99   return buffer;
100 }
101
102 /* Given a pathname, calculate the non-directory part.  This always
103    knows how to handle Unix-style pathnames, and understands VMS and
104    DOS paths on those systems.  */
105
106 /* Find the base name of a (partial) pathname FNAME.
107    Returns a pointer into the string passed in.
108    Accepts Unix (/-separated) paths on all systems,
109    DOS and VMS paths on those systems.  */
110
111 static const char *
112 base_name (fname)
113      const char *fname;
114 {
115   const char *s = fname;
116   const char *p;
117 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
118   if (ISALPHA (s[0]) && s[1] == ':') s += 2;
119   if ((p = strrchr (s, '\\'))) s = p + 1;
120 #elif defined VMS
121   if ((p = strrchr (s, ':'))) s = p + 1; /* Skip device.  */
122   if ((p = strrchr (s, ']'))) s = p + 1; /* Skip directory.  */
123   if ((p = strrchr (s, '>'))) s = p + 1; /* Skip alternate (int'n'l) dir.  */
124 #endif
125   if ((p = strrchr (s, '/'))) s = p + 1;
126   return s;
127 }
128
129 /* Public routines.  */
130
131 struct deps *
132 deps_init ()
133 {
134   struct deps *d = (struct deps *) xmalloc (sizeof (struct deps));
135
136   /* Allocate space for the vectors now.  */
137
138   d->targetv = (const char **) xmalloc (2 * sizeof (const char *));
139   d->depv = (const char **) xmalloc (8 * sizeof (const char *));
140
141   d->ntargets = 0;
142   d->targets_size = 2;
143   d->ndeps = 0;
144   d->deps_size = 8;
145
146   return d;
147 }
148
149 void
150 deps_free (d)
151      struct deps *d;
152 {
153   unsigned int i;
154
155   for (i = 0; i < d->ntargets; i++)
156     free ((PTR) d->targetv[i]);
157
158   for (i = 0; i < d->ndeps; i++)
159     free ((PTR) d->depv[i]);
160
161   free (d->targetv);
162   free (d->depv);
163   free (d);
164 }
165
166 void
167 deps_add_target (d, t)
168      struct deps *d;
169      const char *t;
170 {
171   t = munge (t);  /* Also makes permanent copy.  */
172
173   if (d->ntargets == d->targets_size)
174     {
175       d->targets_size *= 2;
176       d->targetv = (const char **) xrealloc (d->targetv,
177                              d->targets_size * sizeof (const char *));
178     }
179
180   d->targetv[d->ntargets++] = t;
181 }
182
183 void
184 deps_calc_target (d, t)
185      struct deps *d;
186      const char *t;
187 {
188   char *o, *suffix;
189
190   t = base_name (t);
191   o = (char *) alloca (strlen (t) + 8);
192
193   strcpy (o, t);
194   suffix = strrchr (o, '.');
195   if (suffix)
196     strcpy (suffix, OBJECT_SUFFIX);
197   else
198     strcat (o, OBJECT_SUFFIX);
199
200   deps_add_target (d, o);
201 }
202
203 void
204 deps_add_dep (d, t)
205      struct deps *d;
206      const char *t;
207 {
208   t = munge (t);  /* Also makes permanent copy.  */
209
210   if (d->ndeps == d->deps_size)
211     {
212       d->deps_size *= 2;
213       d->depv = (const char **)
214         xrealloc (d->depv, d->deps_size * sizeof (const char *));
215     }
216   d->depv[d->ndeps++] = t;
217 }
218
219 void
220 deps_write (d, fp, colmax)
221      const struct deps *d;
222      FILE *fp;
223      unsigned int colmax;
224 {
225   unsigned int size, i, column;
226
227   column = 0;
228   if (colmax && colmax < 34)
229     colmax = 34;
230
231   for (i = 0; i < d->ntargets; i++)
232     {
233       size = strlen (d->targetv[i]);
234       column += size;
235       if (colmax && column > colmax)
236         {
237           fputs (" \\\n ", fp);
238           column = 1 + size;
239         }
240       if (i)
241         {
242           putc (' ', fp);
243           column++;
244         }
245       fputs (d->targetv[i], fp);
246     }
247
248   putc (':', fp);
249   putc (' ', fp);
250   column += 2;
251
252   for (i = 0; i < d->ndeps; i++)
253     {
254       size = strlen (d->depv[i]);
255       column += size;
256       if (colmax && column > colmax)
257         {
258           fputs (" \\\n ", fp);
259           column = 1 + size;
260         }
261       if (i)
262         {
263           putc (' ', fp);
264           column++;
265         }
266       fputs (d->depv[i], fp);
267     }
268   putc ('\n', fp);
269 }
270   
271 void
272 deps_dummy_targets (d, fp)
273      const struct deps *d;
274      FILE *fp;
275 {
276   unsigned int i;
277
278   for (i = 1; i < d->ndeps; i++)
279     {
280       fputs (d->depv[i], fp);
281       putc (':', fp);
282       putc ('\n', fp);
283     }
284 }