f49d6dda1bd6884b40df29c9ded8b7adb9c2a2fa
[fw/sdcc] / support / cpp / winnt / fixinc-nt.c
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
10 static char *concat();
11 static char *concat3();
12 static char *concat4();
13 static int onlyonedir;
14 static int atleastone;
15 static char *fixeddirs, *origdirs;
16
17 /* Convert all /'s to \'s */
18
19 char *
20 slash2slash (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
33 int
34 mkdirpath (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
60 char *
61 newname (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
80 int
81 doheader (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
128 int
129 dodir (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
173 int
174 main ()
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
229 static char *
230 concat (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
246 static char *
247 concat3 (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
255 static char *
256 concat4 (s1, s2, s3, s4)
257      char *s1, *s2, *s3, *s4;
258 {
259   return concat (concat (s1, s2), concat (s3, s4));
260 }