1#include <stdlib.h>
2#include <string.h>
3#include <sys/stat.h>
4#include <dirent.h>
5#include <stdio.h>
6#include <io.h>
7#include <fcntl.h>
8#include <process.h>
9
10static char *concat();
11static char *concat3();
12static char *concat4();
13static int onlyonedir;
14static int atleastone;
15static char *fixeddirs, *origdirs;
16
17/* Convert all /'s to \'s */
18
19char *
20slash2slash (dirname)
21  char *dirname;
22{
23  int i;
24  for (i=0; dirname[i]; i++)
25    if (dirname [i] == '/')
26      dirname [i] = '\\';
27
28  return dirname;
29}
30
31/* Examine each directory component of a path and create the directory */
32
33int
34mkdirpath (dirpath)
35  char *dirpath;
36{
37  char *ndirpath = strdup (dirpath);
38  char *bp, *fp;
39
40  fp = bp = ndirpath;
41
42  while (bp)
43    {
44      bp = strchr (fp, '\\');
45      if (bp)
46        {
47          *bp = 0;
48          _mkdir (ndirpath);
49          *bp = '\\';
50          fp = ++bp;
51        }
52      else
53        _mkdir (ndirpath);
54    }
55}
56
57/* Construct a relative directory path from a given path by removing the
58   leading slash, if it exists and changing a drive letter from X: to X-. */
59
60char *
61newname (olddirname)
62  char *olddirname;
63{
64  char *newname = strdup (olddirname);
65
66  if ((strlen (newname) >= 2)
67      && (isalpha (newname[0]) && newname[1] == ':'))
68    newname [1] = '-';
69  else if ((strlen (newname) >= 1)
70           && (newname [0] == '/' || newname [0] == '\\'))
71    newname = &newname[1];
72
73  return newname;
74
75}
76
77/* Run the sed script on one header file.  If no modifications were made, then
78   delete the newly created file. */
79
80int
81doheader (oneheader, outheader, oldsize)
82  char *oneheader, *outheader;
83  int oldsize;
84{
85  char *newbuff, *oldbuff;
86  char *newheader = concat3 ("include", "\\", newname (outheader));
87  struct _stat newstatbuf;
88  int newdesc, olddesc;
89  int i;
90
91  system (concat4 ("sed -f fixinc-nt.sed ", oneheader, " > ", newheader));
92  _stat (newheader, &newstatbuf);
93  if (oldsize != newstatbuf.st_size)
94    {
95      atleastone = 1;
96      printf ("Fixing: %s\n", oneheader);
97      return 0;
98    }
99  oldbuff = malloc (oldsize);
100  newbuff = malloc (newstatbuf.st_size);
101  olddesc = open (oneheader, _O_RDONLY | _O_BINARY);
102  newdesc = open (newheader, _O_RDONLY | _O_BINARY);
103  read (olddesc, oldbuff, oldsize);
104  read (newdesc, newbuff, newstatbuf.st_size);
105  close (olddesc);
106  close (newdesc);
107  for (i=0; i<oldsize; i++)
108    {
109      if (oldbuff [i] != newbuff [i])
110        {
111          free (oldbuff);
112          free (newbuff);
113          atleastone = 1;
114          printf ("Fixing: %s\n", oneheader);
115          return 0;
116        }
117    }
118  free (oldbuff);
119  free (newbuff);
120  unlink (newheader);
121  return 0;
122
123}
124
125/* Examine the contents of a directory and call doheader () for a regular file
126   and recursively call dodir () for an enclosed directory. */
127
128int
129dodir (indir, outdir)
130  char *indir, *outdir;
131{
132  DIR *dir;
133  struct dirent *dire;
134  struct _stat statbuf;
135  char *intempbuf, *outtempbuf;
136
137  dir = opendir (indir);
138  if (!dir) return 0;
139
140  mkdirpath (concat3 ("include", "\\", newname (outdir)));
141  while ((dire = readdir (dir)))
142    {
143      if (dire->d_name[0] == '.')
144        continue;
145
146      intempbuf = slash2slash (concat3 (indir, "\\", dire->d_name));
147      outtempbuf = slash2slash (concat3 (outdir, "\\", dire->d_name));
148      _stat (intempbuf, &statbuf);
149
150      /* If directory ... */
151      if (statbuf.st_mode & _S_IFDIR)
152        dodir (intempbuf, outtempbuf);
153
154      /* If regular file ... */
155      if (statbuf.st_mode & _S_IFREG)
156        doheader (intempbuf, outtempbuf, statbuf.st_size);
157    }
158  closedir (dir);
159  return 0;
160}
161
162/* Retrieve the value of the Include environment variable, copy it into a
163   temporary and append a semi-colon for book-keeping purposes. Then call
164   dodir () for each complete directory that is named therein.  If there is
165   only one directory, then direct the output to use include\. as the
166   root instead of include/<directory path>, where <directory path> is a path
167   constructed from the path named in the Include environment variable.
168   I.e. if Include=C:\MSTOOLS\Include;D:\MSVC20\Include then the modified
169   header files will be in include\C-\MSTOOLS\Include and
170   include\D-\MSVC20\Include.  However if Include=C:\MSTOOLS\Include then the
171   modified files will be in include\. */
172
173int
174main ()
175{
176  char *fp, *bp, *foobar;
177  char *incvar = getenv ("Include");
178  int varlen = 0;
179  struct _stat statbuf;
180
181  if (incvar == NULL) return 0;
182
183  varlen = strlen (incvar);
184  foobar = (char *) malloc (varlen + 2);
185
186  strcpy (foobar, incvar);
187  foobar = slash2slash (foobar);
188  if (foobar [varlen-1] != ';') strcat (foobar, ";");
189  fp = bp = foobar;
190
191  if (strchr (fp, ';') == strrchr (fp, ';'))
192    onlyonedir = 1;
193  else
194    onlyonedir = 0;
195
196  fixeddirs = strdup(".\\include");
197  origdirs = strdup("");
198
199  while (bp)
200    {
201      bp = strchr (fp, ';');
202      if (bp)
203        {
204          *bp = 0;
205          _stat (fp, &statbuf);
206          if (statbuf.st_mode & _S_IFDIR)
207            {
208              atleastone = 0;
209              if (onlyonedir)
210                dodir (fp, ".");
211              else
212                dodir (fp, fp);
213              if (atleastone && !onlyonedir)
214                {
215                  origdirs = concat3 (origdirs, ";", fp);
216                  fixeddirs = concat3 (fixeddirs, ";",
217                    concat3 (".\\include", "\\", newname(fp)));
218                }
219            }
220          fp = ++bp;
221        }
222    }
223  printf ("set C_Include_Path=%s%s\n", fixeddirs, origdirs);
224  return 0;
225}
226
227/* Utility function that mallocs space and concatenates two strings. */
228
229static char *
230concat (s1, s2)
231     char *s1, *s2;
232{
233  int len1 = strlen (s1);
234  int len2 = strlen (s2);
235  char *result = malloc (len1 + len2 + 1);
236
237  strcpy (result, s1);
238  strcpy (result + len1, s2);
239  *(result + len1 + len2) = 0;
240
241  return result;
242}
243
244/* Utility function that concatenates three strings. */
245
246static char *
247concat3 (s1, s2, s3)
248     char *s1, *s2, *s3;
249{
250  return concat (concat (s1, s2), s3);
251}
252
253/* Utility function that concatenates four strings. */
254
255static char *
256concat4 (s1, s2, s3, s4)
257     char *s1, *s2, *s3, *s4;
258{
259  return concat (concat (s1, s2), concat (s3, s4));
260}
261