]>
git.ipfire.org Git - thirdparty/systemd.git/blob - ccdv.c
3 * Copyright (C) 2002-2003, by Mike Gleason, NcFTP Software.
6 * Licensed under the GNU Public License.
18 #define SETCOLOR_SUCCESS (gANSIEscapes ? "\033\1331;32m" : "")
19 #define SETCOLOR_FAILURE (gANSIEscapes ? "\033\1331;31m" : "")
20 #define SETCOLOR_WARNING (gANSIEscapes ? "\033\1331;33m" : "")
21 #define SETCOLOR_NORMAL (gANSIEscapes ? "\033\1330;39m" : "")
23 #define TEXT_BLOCK_SIZE 8192
26 #define TERMS "vt100:vt102:vt220:vt320:xterm:xterm-color:ansi:linux:scoterm:scoansi:dtterm:cons25:cygwin"
28 size_t gNBufUsed
= 0, gNBufAllocated
= 0;
31 char gAction
[200] = "";
32 char gTarget
[200] = "";
34 char gArLibraryTarget
[64] = "";
41 static void DumpFormattedOutput(void)
44 char spaces
[8 + 1] = " ";
51 for (cp
= gBuf
+ ((gDumpCmdArgs
== 0) ? strlen(gArgsStr
) : 0); ; cp
++) {
62 cp
= spaces
+ 8 - (8 - ((curcol
- INDENT
- 1) % 8));
65 for (i
= INDENT
; --i
>= 0; )
70 if (++curcol
== (gColumns
- 1)) {
73 } else if (*cp
== '\n')
77 } /* DumpFormattedOutput */
81 /* Difftime(), only for timeval structures. */
82 static void TimeValSubtract(struct timeval
*tdiff
, struct timeval
*t1
, struct timeval
*t0
)
84 tdiff
->tv_sec
= t1
->tv_sec
- t0
->tv_sec
;
85 tdiff
->tv_usec
= t1
->tv_usec
- t0
->tv_usec
;
86 if (tdiff
->tv_usec
< 0) {
88 tdiff
->tv_usec
+= 1000000;
90 } /* TimeValSubtract */
94 static void Wait(void)
100 pid2
= (int) waitpid(gCCPID
, &status
, 0);
101 } while (((pid2
>= 0) && (! WIFEXITED(status
))) || ((pid2
< 0) && (errno
== EINTR
)));
102 if (WIFEXITED(status
))
103 gExitStatus
= WEXITSTATUS(status
);
108 static int SlurpProgress(int fd
)
115 struct timeval now
, tnext
, tleft
;
118 const char *trail
= "/-\\|", *trailcp
;
121 snprintf(s1
, sizeof(s1
), "%s%s%s... ", gAction
, gTarget
[0] ? " " : "", gTarget
);
122 printf("\r%-70s%-9s", s1
, "");
125 gettimeofday(&now
, NULL
);
133 if (gNBufUsed
== (gNBufAllocated
- 1)) {
134 if ((newbuf
= (char *) realloc(gBuf
, gNBufAllocated
+ TEXT_BLOCK_SIZE
)) == NULL
) {
135 perror("ccdv: realloc");
138 gNBufAllocated
+= TEXT_BLOCK_SIZE
;
143 nready
= select(fd
+ 1, &ss
, NULL
, NULL
, &tleft
);
147 if (errno
!= EINTR
) {
148 perror("ccdv: select");
153 gettimeofday(&now
, NULL
);
154 if ((now
.tv_sec
> tnext
.tv_sec
) || ((now
.tv_sec
== tnext
.tv_sec
) && (now
.tv_usec
>= tnext
.tv_usec
))) {
159 printf("\r%-71s%c%-7s", s1
, *trailcp
, "");
161 if (*++trailcp
== '\0')
164 TimeValSubtract(&tleft
, &tnext
, &now
);
167 ntoread
= (gNBufAllocated
- gNBufUsed
- 1);
168 nread
= read(fd
, gBuf
+ gNBufUsed
, ntoread
);
172 perror("ccdv: read");
174 } else if (nread
== 0) {
178 gBuf
[gNBufUsed
] = '\0';
180 snprintf(s1
, sizeof(s1
), "%s%s%s: ", gAction
, gTarget
[0] ? " " : "", gTarget
);
182 if (gExitStatus
== 0) {
183 printf("\r%-70s", s1
);
184 printf("[%s%s%s]", ((gNBufUsed
- strlen(gArgsStr
)) < 4) ? SETCOLOR_SUCCESS
: SETCOLOR_WARNING
, "OK", SETCOLOR_NORMAL
);
185 printf("%-5s\n", " ");
187 printf("\r%-70s", s1
);
188 printf("[%s%s%s]", SETCOLOR_FAILURE
, "ERROR", SETCOLOR_NORMAL
);
189 printf("%-2s\n", " ");
190 gDumpCmdArgs
= 1; /* print cmd when there are errors */
194 } /* SlurpProgress */
198 static int SlurpAll(int fd
)
204 printf("%s%s%s.\n", gAction
, gTarget
[0] ? " " : "", gTarget
);
208 if (gNBufUsed
== (gNBufAllocated
- 1)) {
209 if ((newbuf
= (char *) realloc(gBuf
, gNBufAllocated
+ TEXT_BLOCK_SIZE
)) == NULL
) {
210 perror("ccdv: realloc");
213 gNBufAllocated
+= TEXT_BLOCK_SIZE
;
216 ntoread
= (gNBufAllocated
- gNBufUsed
- 1);
217 nread
= read(fd
, gBuf
+ gNBufUsed
, ntoread
);
221 perror("ccdv: read");
223 } else if (nread
== 0) {
227 gBuf
[gNBufUsed
] = '\0';
230 gDumpCmdArgs
= (gExitStatus
!= 0); /* print cmd when there are errors */
236 static const char *Basename(const char *path
)
239 cp
= strrchr(path
, '/');
247 static const char * Extension(const char *path
)
249 const char *cp
= path
;
250 cp
= strrchr(path
, '.');
253 // printf("Extension='%s'\n", cp);
259 static void Usage(void)
261 fprintf(stderr
, "Usage: ccdv /path/to/cc CFLAGS...\n\n");
262 fprintf(stderr
, "I wrote this to reduce the deluge Make output to make finding actual problems\n");
263 fprintf(stderr
, "easier. It is intended to be invoked from Makefiles, like this. Instead of:\n\n");
264 fprintf(stderr
, "\t.c.o:\n");
265 fprintf(stderr
, "\t\t$(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n");
266 fprintf(stderr
, "\nRewrite your rule so it looks like:\n\n");
267 fprintf(stderr
, "\t.c.o:\n");
268 fprintf(stderr
, "\t\t@ccdv $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\n");
269 fprintf(stderr
, "ccdv 1.1.0 is Free under the GNU Public License. Enjoy!\n");
270 fprintf(stderr
, " -- Mike Gleason, NcFTP Software <http://www.ncftp.com>\n");
276 int main(int argc
, char **argv
)
290 snprintf(gAction
, sizeof(gAction
), "Running %s", Basename(argv
[1]));
291 memset(gArgsStr
, 0, sizeof(gArgsStr
));
292 for (i
= 1; i
< argc
; i
++) {
293 // printf("argv[%d]='%s'\n", i, argv[i]);
294 quote
= (strchr(argv
[i
], ' ') != NULL
) ? "\"" : "";
295 snprintf(gArgsStr
+ strlen(gArgsStr
), sizeof(gArgsStr
) - strlen(gArgsStr
), "%s%s%s%s%s", (i
== 1) ? "" : " ", quote
, argv
[i
], quote
, (i
== (argc
- 1)) ? "\n" : "");
296 if ((strcmp(argv
[i
], "-o") == 0) && ((i
+ 1) < argc
)) {
297 if (strcasecmp(Extension(argv
[i
+ 1]), ".o") != 0) {
298 strcpy(gAction
, "Linking");
299 snprintf(gTarget
, sizeof(gTarget
), "%s", Basename(argv
[i
+ 1]));
301 } else if (strchr("-+", (int) argv
[i
][0]) != NULL
) {
303 } else if (strncasecmp(Extension(argv
[i
]), ".c", 2) == 0) {
305 snprintf(gTarget
, sizeof(gTarget
), "%s", Basename(argv
[i
]));
306 // printf("gTarget='%s'\n", gTarget);
307 } else if ((strncasecmp(Extension(argv
[i
]), ".h", 2) == 0) && (cc
== 0)) {
309 snprintf(gTarget
, sizeof(gTarget
), "%s", Basename(argv
[i
]));
310 } else if ((i
== 1) && (strcmp(Basename(argv
[i
]), "ar") == 0)) {
311 snprintf(gAr
, sizeof(gAr
), "%s", Basename(argv
[i
]));
312 } else if ((gArLibraryTarget
[0] == '\0') && (strcasecmp(Extension(argv
[i
]), ".a") == 0)) {
313 snprintf(gArLibraryTarget
, sizeof(gArLibraryTarget
), "%s", Basename(argv
[i
]));
316 if ((gAr
[0] != '\0') && (gArLibraryTarget
[0] != '\0')) {
317 strcpy(gAction
, "Creating library");
318 snprintf(gTarget
, sizeof(gTarget
), "%s", gArLibraryTarget
);
319 } else if (pch
> 0) {
320 strcpy(gAction
, "Precompiling");
322 strcpy(gAction
, "Compiling");
325 if (pipe(pipe1
) < 0) {
326 perror("ccdv: pipe");
331 devnull
= open("/dev/null", O_RDWR
, 00666);
332 if ((devnull
!= 0) && (dup2(devnull
, 0) == 0))
335 gCCPID
= (int) fork();
337 (void) close(pipe1
[0]);
338 (void) close(pipe1
[1]);
339 perror("ccdv: fork");
341 } else if (gCCPID
== 0) {
343 (void) close(pipe1
[0]); /* close read end */
344 if (pipe1
[1] != 1) { /* use write end on stdout */
345 (void) dup2(pipe1
[1], 1);
346 (void) close(pipe1
[1]);
348 (void) dup2(1, 2); /* use write end on stderr */
349 execvp(argv
[1], argv
+ 1);
355 (void) close(pipe1
[1]); /* close write end */
356 fd
= pipe1
[0]; /* use read end */
358 gColumns
= (getenv("COLUMNS") != NULL
) ? atoi(getenv("COLUMNS")) : 80;
359 gANSIEscapes
= (getenv("TERM") != NULL
) && (strstr(TERMS
, getenv("TERM")) != NULL
);
360 gBuf
= (char *) malloc(TEXT_BLOCK_SIZE
);
364 gNBufAllocated
= TEXT_BLOCK_SIZE
;
365 if (strlen(gArgsStr
) < (gNBufAllocated
- 1)) {
366 strcpy(gBuf
, gArgsStr
);
367 gNBufUsed
= strlen(gArgsStr
);
371 if (SlurpProgress(fd
) < 0)
374 if (SlurpAll(fd
) < 0)
377 DumpFormattedOutput();
381 gDumpCmdArgs
= 1; /* print cmd when there are errors */
382 DumpFormattedOutput();
383 while ((nread
= read(fd
, emerg
, (size_t) sizeof(emerg
))) > 0)
384 (void) write(2, emerg
, (size_t) nread
);