don't rewrite CPP_OPTION (pfile, obj_ext)
[fw/sdcc] / support / cpp2 / 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 #include "cpplib.h"
27 #include "cpphash.h"
28
29 /* Keep this structure local to this file, so clients don't find it
30    easy to start making assumptions.  */
31 struct deps
32 {
33   const char **targetv;
34   unsigned int ntargets;        /* number of slots actually occupied */
35   unsigned int targets_size;    /* amt of allocated space - in words */
36
37   const char **depv;
38   unsigned int ndeps;
39   unsigned int deps_size;
40 };
41
42 static const char *munge        PARAMS ((const char *));
43
44 /* Given a filename, quote characters in that filename which are
45    significant to Make.  Note that it's not possible to quote all such
46    characters - e.g. \n, %, *, ?, [, \ (in some contexts), and ~ are
47    not properly handled.  It isn't possible to get this right in any
48    current version of Make.  (??? Still true?  Old comment referred to
49    3.76.1.)  */
50    
51 static const char *
52 munge (filename)
53      const char *filename;
54 {
55   int len;
56   const char *p, *q;
57   char *dst, *buffer;
58
59   for (p = filename, len = 0; *p; p++, len++)
60     {
61       switch (*p)
62         {
63         case ' ':
64         case '\t':
65           /* GNU make uses a weird quoting scheme for white space.
66              A space or tab preceded by 2N+1 backslashes represents
67              N backslashes followed by space; a space or tab
68              preceded by 2N backslashes represents N backslashes at
69              the end of a file name; and backslashes in other
70              contexts should not be doubled.  */
71           for (q = p - 1; filename <= q && *q == '\\';  q--)
72             len++;
73           len++;
74           break;
75
76         case '$':
77           /* '$' is quoted by doubling it.  */
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 /* Public routines.  */
112
113 struct deps *
114 deps_init ()
115 {
116   struct deps *d = (struct deps *) xmalloc (sizeof (struct deps));
117
118   /* Allocate space for the vectors only if we need it.  */
119
120   d->targetv = 0;
121   d->depv = 0;
122
123   d->ntargets = 0;
124   d->targets_size = 0;
125   d->ndeps = 0;
126   d->deps_size = 0;
127
128   return d;
129 }
130
131 void
132 deps_free (d)
133      struct deps *d;
134 {
135   unsigned int i;
136
137   if (d->targetv)
138     {
139       for (i = 0; i < d->ntargets; i++)
140         free ((PTR) d->targetv[i]);
141       free (d->targetv);
142     }
143
144   if (d->depv)
145     {
146       for (i = 0; i < d->ndeps; i++)
147         free ((PTR) d->depv[i]);
148       free (d->depv);
149     }
150
151   free (d);
152 }
153
154 /* Adds a target T.  We make a copy, so it need not be a permanent
155    string.  QUOTE is true if the string should be quoted.  */
156 void
157 deps_add_target (d, t, quote)
158      struct deps *d;
159      const char *t;
160      int quote;
161 {
162   if (d->ntargets == d->targets_size)
163     {
164       d->targets_size = d->targets_size * 2 + 4;
165       d->targetv = (const char **) xrealloc (d->targetv,
166                              d->targets_size * sizeof (const char *));
167     }
168
169   if (quote)
170     t = munge (t);  /* Also makes permanent copy.  */
171   else
172     t = xstrdup (t);
173
174   d->targetv[d->ntargets++] = t;
175 }
176
177 /* Sets the default target if none has been given already.  An empty
178    string as the default target in interpreted as stdin.  The string
179    is quoted for MAKE.  */
180 void
181 deps_add_default_target (pfile, tgt)
182     cpp_reader *pfile;
183     const char *tgt;
184 {
185   /* Only if we have no targets.  */
186   if (pfile->deps->ntargets)
187     return;
188
189   if (tgt[0] == '\0')
190     deps_add_target (pfile->deps, "-", 1);
191   else
192     {
193 #ifndef TARGET_OBJECT_SUFFIX
194 # define TARGET_OBJECT_SUFFIX ".o"
195 #endif
196       char *start = lbasename (tgt);
197       char *o;
198       char *suffix;
199       const char *obj_ext;
200
201       if (NULL == CPP_OPTION (pfile, obj_ext))
202         obj_ext = TARGET_OBJECT_SUFFIX;
203       else if (CPP_OPTION (pfile, obj_ext)[0] != '.')
204         {
205           char *t = alloca (strlen (CPP_OPTION (pfile, obj_ext)) + 2);
206           t[0] = '.';
207           strcpy (&t[1], CPP_OPTION (pfile, obj_ext));
208           obj_ext = t;
209         }
210       else
211         obj_ext = CPP_OPTION (pfile, obj_ext);
212
213       o = (char *) alloca (strlen (start) + strlen (obj_ext) + 1);
214
215       strcpy (o, start);
216
217       suffix = strrchr (o, '.');
218       if (!suffix)
219         suffix = o + strlen (o);
220       strcpy (suffix, obj_ext);
221
222       deps_add_target (pfile->deps, o, 1);
223     }
224 }
225
226 void
227 deps_add_dep (d, t)
228      struct deps *d;
229      const char *t;
230 {
231   t = munge (t);  /* Also makes permanent copy.  */
232
233   if (d->ndeps == d->deps_size)
234     {
235       d->deps_size = d->deps_size * 2 + 8;
236       d->depv = (const char **)
237         xrealloc (d->depv, d->deps_size * sizeof (const char *));
238     }
239   d->depv[d->ndeps++] = t;
240 }
241
242 void
243 deps_write (d, fp, colmax)
244      const struct deps *d;
245      FILE *fp;
246      unsigned int colmax;
247 {
248   unsigned int size, i, column;
249
250   column = 0;
251   if (colmax && colmax < 34)
252     colmax = 34;
253
254   for (i = 0; i < d->ntargets; i++)
255     {
256       size = strlen (d->targetv[i]);
257       column += size;
258       if (colmax && column > colmax)
259         {
260           fputs (" \\\n ", fp);
261           column = 1 + size;
262         }
263       if (i)
264         {
265           putc (' ', fp);
266           column++;
267         }
268       fputs (d->targetv[i], fp);
269     }
270
271   putc (':', fp);
272   putc (' ', fp);
273   column += 2;
274
275   for (i = 0; i < d->ndeps; i++)
276     {
277       size = strlen (d->depv[i]);
278       column += size;
279       if (colmax && column > colmax)
280         {
281           fputs (" \\\n ", fp);
282           column = 1 + size;
283         }
284       if (i)
285         {
286           putc (' ', fp);
287           column++;
288         }
289       fputs (d->depv[i], fp);
290     }
291   putc ('\n', fp);
292 }
293   
294 void
295 deps_phony_targets (d, fp)
296      const struct deps *d;
297      FILE *fp;
298 {
299   unsigned int i;
300
301   for (i = 1; i < d->ndeps; i++)
302     {
303       putc ('\n', fp);
304       fputs (d->depv[i], fp);
305       putc (':', fp);
306       putc ('\n', fp);
307     }
308 }