123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- /* depend.c - Handle dependency tracking.
- Copyright (C) 1997-2022 Free Software Foundation, Inc.
- This file is part of GAS, the GNU Assembler.
- GAS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- GAS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GAS; see the file COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
- 02110-1301, USA. */
- #include "as.h"
- #include "filenames.h"
- /* The file to write to, or NULL if no dependencies being kept. */
- static char * dep_file = NULL;
- struct dependency
- {
- char * file;
- struct dependency * next;
- };
- /* All the files we depend on. */
- static struct dependency * dep_chain = NULL;
- /* Current column in output file. */
- static int column = 0;
- static int quote_string_for_make (FILE *, const char *);
- static void wrap_output (FILE *, const char *, int);
- /* Number of columns allowable. */
- #define MAX_COLUMNS 72
- /* Start saving dependencies, to be written to FILENAME. If this is
- never called, then dependency tracking is simply skipped. */
- void
- start_dependencies (char *filename)
- {
- dep_file = filename;
- }
- /* Noticed a new filename, so try to register it. */
- void
- register_dependency (const char *filename)
- {
- struct dependency *dep;
- if (dep_file == NULL)
- return;
- for (dep = dep_chain; dep != NULL; dep = dep->next)
- {
- if (!filename_cmp (filename, dep->file))
- return;
- }
- dep = XNEW (struct dependency);
- dep->file = xstrdup (filename);
- dep->next = dep_chain;
- dep_chain = dep;
- }
- /* Quote a file name the way `make' wants it, and print it to FILE.
- If FILE is NULL, do no printing, but return the length of the
- quoted string.
- This code is taken from gcc with only minor changes. */
- static int
- quote_string_for_make (FILE *file, const char *src)
- {
- const char *p = src;
- int i = 0;
- for (;;)
- {
- char c = *p++;
- switch (c)
- {
- case '\0':
- case ' ':
- case '\t':
- {
- /* GNU make uses a weird quoting scheme for white space.
- A space or tab preceded by 2N+1 backslashes represents
- N backslashes followed by space; a space or tab
- preceded by 2N backslashes represents N backslashes at
- the end of a file name; and backslashes in other
- contexts should not be doubled. */
- const char *q;
- for (q = p - 1; src < q && q[-1] == '\\'; q--)
- {
- if (file)
- putc ('\\', file);
- i++;
- }
- }
- if (!c)
- return i;
- if (file)
- putc ('\\', file);
- i++;
- goto ordinary_char;
- case '$':
- if (file)
- putc (c, file);
- i++;
- /* Fall through. */
- /* This can mishandle things like "$(" but there's no easy fix. */
- default:
- ordinary_char:
- /* This can mishandle characters in the string "\0\n%*?[\\~";
- exactly which chars are mishandled depends on the `make' version.
- We know of no portable solution for this;
- even GNU make 3.76.1 doesn't solve the problem entirely.
- (Also, '\0' is mishandled due to our calling conventions.) */
- if (file)
- putc (c, file);
- i++;
- break;
- }
- }
- }
- /* Append some output to the file, keeping track of columns and doing
- wrapping as necessary. */
- static void
- wrap_output (FILE *f, const char *string, int spacer)
- {
- int len = quote_string_for_make (NULL, string);
- if (len == 0)
- return;
- if (column
- && (MAX_COLUMNS
- - 1 /* spacer */
- - 2 /* ` \' */
- < column + len))
- {
- fprintf (f, " \\\n ");
- column = 0;
- if (spacer == ' ')
- spacer = '\0';
- }
- if (spacer == ' ')
- {
- putc (spacer, f);
- ++column;
- }
- quote_string_for_make (f, string);
- column += len;
- if (spacer == ':')
- {
- putc (spacer, f);
- ++column;
- }
- }
- /* Print dependency file. */
- void
- print_dependencies (void)
- {
- FILE *f;
- struct dependency *dep;
- if (dep_file == NULL)
- return;
- f = fopen (dep_file, FOPEN_WT);
- if (f == NULL)
- {
- as_warn (_("can't open `%s' for writing"), dep_file);
- return;
- }
- column = 0;
- wrap_output (f, out_file_name, ':');
- for (dep = dep_chain; dep != NULL; dep = dep->next)
- wrap_output (f, dep->file, ' ');
- putc ('\n', f);
- if (fclose (f))
- as_warn (_("can't close `%s'"), dep_file);
- }
|