bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / build / aplibtool.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <process.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <sys/types.h>
22 #include <dirent.h>
23
24 typedef char bool;
25 #define false 0
26 #define true (!false)
27
28 bool silent = false;
29 bool shared = false;
30 bool export_all = false;
31 enum mode_t { mCompile, mLink, mInstall };
32 enum output_type_t { otGeneral, otObject, otProgram, otStaticLibrary, otDynamicLibrary };
33
34 #ifdef __EMX__
35 #  define SHELL_CMD  "sh"
36 #  define CC         "gcc"
37 #  define GEN_EXPORTS "emxexp"
38 #  define DEF2IMPLIB_CMD "emximp"
39 #  define SHARE_SW   "-Zdll -Zmtd"
40 #  define USE_OMF true
41 #  define TRUNCATE_DLL_NAME
42 #  define DYNAMIC_LIB_EXT "dll"
43 #  define EXE_EXT ".exe"
44
45 #  if USE_OMF
46      /* OMF is the native format under OS/2 */
47 #    define STATIC_LIB_EXT "lib"
48 #    define OBJECT_EXT     "obj"
49 #    define LIBRARIAN      "emxomfar"
50 #  else
51      /* but the alternative, a.out, can fork() which is sometimes necessary */
52 #    define STATIC_LIB_EXT "a"
53 #    define OBJECT_EXT     "o"
54 #    define LIBRARIAN      "ar"
55 #  endif
56 #endif
57
58
59 typedef struct {
60     char *arglist[1024];
61     int num_args;
62     enum mode_t mode;
63     enum output_type_t output_type;
64     char *output_name;
65     char *stub_name;
66     char *tmp_dirs[1024];
67     int num_tmp_dirs;
68     char *obj_files[1024];
69     int num_obj_files;
70 } cmd_data_t;
71
72 void parse_args(int argc, char *argv[], cmd_data_t *cmd_data);
73 bool parse_long_opt(char *arg, cmd_data_t *cmd_data);
74 int parse_short_opt(char *arg, cmd_data_t *cmd_data);
75 bool parse_input_file_name(char *arg, cmd_data_t *cmd_data);
76 bool parse_output_file_name(char *arg, cmd_data_t *cmd_data);
77 void post_parse_fixup(cmd_data_t *cmd_data);
78 bool explode_static_lib(char *lib, cmd_data_t *cmd_data);
79 int execute_command(cmd_data_t *cmd_data);
80 char *shell_esc(const char *str);
81 void cleanup_tmp_dirs(cmd_data_t *cmd_data);
82 void generate_def_file(cmd_data_t *cmd_data);
83 char *nameof(char *fullpath);
84 char *truncate_dll_name(char *path);
85
86
87 int main(int argc, char *argv[])
88 {
89     int rc;
90     cmd_data_t cmd_data;
91
92     memset(&cmd_data, 0, sizeof(cmd_data));
93     cmd_data.mode = mCompile;
94     cmd_data.output_type = otGeneral;
95
96     parse_args(argc, argv, &cmd_data);
97     rc = execute_command(&cmd_data);
98
99     if (rc == 0 && cmd_data.stub_name) {
100         fopen(cmd_data.stub_name, "w");
101     }
102
103     cleanup_tmp_dirs(&cmd_data);
104     return rc;
105 }
106
107
108
109 void parse_args(int argc, char *argv[], cmd_data_t *cmd_data)
110 {
111     int a;
112     char *arg;
113     bool argused;
114
115     for (a=1; a < argc; a++) {
116         arg = argv[a];
117         argused = false;
118
119         if (arg[0] == '-') {
120             if (arg[1] == '-') {
121                 argused = parse_long_opt(arg + 2, cmd_data);
122             } else if (arg[1] == 'o' && a+1 < argc) {
123                 cmd_data->arglist[cmd_data->num_args++] = arg;
124                 arg = argv[++a];
125                 argused = parse_output_file_name(arg, cmd_data);
126             } else {
127                 int num_used = parse_short_opt(arg + 1, cmd_data);
128                 argused = num_used > 0;
129
130                 if (num_used > 1) {
131                     a += num_used - 1;
132                 }
133             }
134         } else {
135             argused = parse_input_file_name(arg, cmd_data);
136         }
137
138         if (!argused) {
139             cmd_data->arglist[cmd_data->num_args++] = arg;
140         }
141     }
142
143     post_parse_fixup(cmd_data);
144 }
145
146
147
148 bool parse_long_opt(char *arg, cmd_data_t *cmd_data)
149 {
150     char *equal_pos = strchr(arg, '=');
151     char var[50];
152     char value[500];
153
154     if (equal_pos) {
155         strncpy(var, arg, equal_pos - arg);
156         var[equal_pos - arg] = 0;
157         strcpy(value, equal_pos + 1);
158     } else {
159         strcpy(var, arg);
160     }
161
162     if (strcmp(var, "silent") == 0) {
163         silent = true;
164     } else if (strcmp(var, "mode") == 0) {
165         if (strcmp(value, "compile") == 0) {
166             cmd_data->mode = mCompile;
167             cmd_data->output_type = otObject;
168         }
169
170         if (strcmp(value, "link") == 0) {
171             cmd_data->mode = mLink;
172         }
173
174         if (strcmp(value, "install") == 0) {
175             cmd_data->mode = mInstall;
176         }
177     } else if (strcmp(var, "shared") == 0) {
178         shared = true;
179     } else if (strcmp(var, "export-all") == 0) {
180         export_all = true;
181     } else {
182         return false;
183     }
184
185     return true;
186 }
187
188
189
190 int parse_short_opt(char *arg, cmd_data_t *cmd_data)
191 {
192     if (strcmp(arg, "export-dynamic") == 0) {
193         return 1;
194     }
195
196     if (strcmp(arg, "module") == 0) {
197         return 1;
198     }
199
200     if (strcmp(arg, "Zexe") == 0) {
201         return 1;
202     }
203
204     if (strcmp(arg, "avoid-version") == 0) {
205         return 1;
206     }
207
208     if (strcmp(arg, "prefer-pic") == 0) {
209         return 1;
210     }
211
212     if (strcmp(arg, "prefer-non-pic") == 0) {
213         return 1;
214     }
215
216     if (strcmp(arg, "version-info") == 0 ) {
217         return 2;
218     }
219
220     return 0;
221 }
222
223
224
225 bool parse_input_file_name(char *arg, cmd_data_t *cmd_data)
226 {
227     char *ext = strrchr(arg, '.');
228     char *name = strrchr(arg, '/');
229     int pathlen;
230     char *newarg;
231
232     if (!ext) {
233         return false;
234     }
235
236     ext++;
237
238     if (name == NULL) {
239         name = strrchr(arg, '\\');
240
241         if (name == NULL) {
242             name = arg;
243         } else {
244             name++;
245         }
246     } else {
247         name++;
248     }
249
250     pathlen = name - arg;
251
252     if (strcmp(ext, "lo") == 0) {
253         newarg = (char *)malloc(strlen(arg) + 10);
254         strcpy(newarg, arg);
255         strcpy(newarg + (ext - arg), OBJECT_EXT);
256         cmd_data->arglist[cmd_data->num_args++] = newarg;
257         cmd_data->obj_files[cmd_data->num_obj_files++] = newarg;
258         return true;
259     }
260
261     if (strcmp(ext, "la") == 0) {
262         newarg = (char *)malloc(strlen(arg) + 10);
263         strcpy(newarg, arg);
264         newarg[pathlen] = 0;
265         strcat(newarg, ".libs/");
266
267         if (strncmp(name, "lib", 3) == 0) {
268             name += 3;
269         }
270
271         strcat(newarg, name);
272         ext = strrchr(newarg, '.') + 1;
273
274         if (shared && cmd_data->mode == mInstall) {
275           strcpy(ext, DYNAMIC_LIB_EXT);
276           newarg = truncate_dll_name(newarg);
277         } else {
278           strcpy(ext, STATIC_LIB_EXT);
279         }
280
281         cmd_data->arglist[cmd_data->num_args++] = newarg;
282         return true;
283     }
284
285     if (strcmp(ext, "c") == 0) {
286         if (cmd_data->stub_name == NULL) {
287             cmd_data->stub_name = (char *)malloc(strlen(arg) + 4);
288             strcpy(cmd_data->stub_name, arg);
289             strcpy(strrchr(cmd_data->stub_name, '.') + 1, "lo");
290         }
291     }
292
293     if (strcmp(name, CC) == 0 || strcmp(name, CC EXE_EXT) == 0) {
294         if (cmd_data->output_type == otGeneral) {
295             cmd_data->output_type = otObject;
296         }
297     }
298
299     return false;
300 }
301
302
303
304 bool parse_output_file_name(char *arg, cmd_data_t *cmd_data)
305 {
306     char *name = strrchr(arg, '/');
307     char *ext = strrchr(arg, '.');
308     char *newarg = NULL, *newext;
309     int pathlen;
310
311     if (name == NULL) {
312         name = strrchr(arg, '\\');
313
314         if (name == NULL) {
315             name = arg;
316         } else {
317             name++;
318         }
319     } else {
320         name++;
321     }
322
323     if (!ext) {
324         cmd_data->stub_name = arg;
325         cmd_data->output_type = otProgram;
326         newarg = (char *)malloc(strlen(arg) + 5);
327         strcpy(newarg, arg);
328         strcat(newarg, EXE_EXT);
329         cmd_data->arglist[cmd_data->num_args++] = newarg;
330         cmd_data->output_name = newarg;
331         return true;
332     }
333
334     ext++;
335     pathlen = name - arg;
336
337     if (strcmp(ext, "la") == 0) {
338         cmd_data->stub_name = arg;
339         cmd_data->output_type = shared ? otDynamicLibrary : otStaticLibrary;
340         newarg = (char *)malloc(strlen(arg) + 10);
341         mkdir(".libs", 0);
342         strcpy(newarg, ".libs/");
343
344         if (strncmp(arg, "lib", 3) == 0) {
345             arg += 3;
346         }
347
348         strcat(newarg, arg);
349         newext = strrchr(newarg, '.') + 1;
350         strcpy(newext, shared ? DYNAMIC_LIB_EXT : STATIC_LIB_EXT);
351
352 #ifdef TRUNCATE_DLL_NAME
353         if (shared) {
354           newarg = truncate_dll_name(newarg);
355         }
356 #endif
357
358         cmd_data->arglist[cmd_data->num_args++] = newarg;
359         cmd_data->output_name = newarg;
360         return true;
361     }
362
363     if (strcmp(ext, "lo") == 0) {
364         cmd_data->stub_name = arg;
365         cmd_data->output_type = otObject;
366         newarg = (char *)malloc(strlen(arg) + 2);
367         strcpy(newarg, arg);
368         ext = strrchr(newarg, '.') + 1;
369         strcpy(ext, OBJECT_EXT);
370         cmd_data->arglist[cmd_data->num_args++] = newarg;
371         cmd_data->output_name = newarg;
372         return true;
373     }
374
375     return false;
376 }
377
378
379
380 void post_parse_fixup(cmd_data_t *cmd_data)
381 {
382     int a;
383     char *arg;
384     char *ext;
385
386     if (cmd_data->output_type == otStaticLibrary && cmd_data->mode == mLink) {
387         /* We do a real hatchet job on the args when making a static library
388          * removing all compiler switches & any other cruft that ar won't like
389          * We also need to explode any libraries listed
390          */
391
392         for (a=0; a < cmd_data->num_args; a++) {
393             arg = cmd_data->arglist[a];
394
395             if (arg) {
396                 ext = strrchr(arg, '.');
397
398                 if (ext) {
399                     ext++;
400                 }
401
402                 if (arg[0] == '-') {
403                     cmd_data->arglist[a] = NULL;
404
405                     if (strcmp(arg, "-rpath") == 0 && a+1 < cmd_data->num_args) {
406                         cmd_data->arglist[a+1] = NULL;
407                     }
408
409                     if (strcmp(arg, "-R") == 0 && a+1 < cmd_data->num_args) {
410                         cmd_data->arglist[a+1] = NULL;
411                     }
412
413                     if (strcmp(arg, "-version-info") == 0 && a+1 < cmd_data->num_args) {
414                         cmd_data->arglist[a+1] = NULL;
415                     }
416
417                     if (strcmp(arg, "-Zstack") == 0 && a+1 < cmd_data->num_args) {
418                         cmd_data->arglist[a+1] = NULL;
419                     }
420
421                     if (strcmp(arg, "-o") == 0) {
422                         a++;
423                     }
424                 }
425
426                 if (strcmp(arg, CC) == 0 || strcmp(arg, CC EXE_EXT) == 0) {
427                     cmd_data->arglist[a] = LIBRARIAN " cr";
428                 }
429
430                 if (ext) {
431                     if (strcmp(ext, "h") == 0 || strcmp(ext, "c") == 0) {
432                         /* ignore source files, they don't belong in a library */
433                         cmd_data->arglist[a] = NULL;
434                     }
435
436                     if (strcmp(ext, STATIC_LIB_EXT) == 0) {
437                         cmd_data->arglist[a] = NULL;
438                         explode_static_lib(arg, cmd_data);
439                     }
440                 }
441             }
442         }
443     }
444
445     if (cmd_data->output_type == otDynamicLibrary) {
446         for (a=0; a < cmd_data->num_args; a++) {
447             arg = cmd_data->arglist[a];
448
449             if (arg) {
450                 if (strcmp(arg, "-rpath") == 0 && a+1 < cmd_data->num_args) {
451                     cmd_data->arglist[a] = NULL;
452                     cmd_data->arglist[a+1] = NULL;
453                 }
454             }
455         }
456
457         if (export_all) {
458             generate_def_file(cmd_data);
459         }
460     }
461
462 #if USE_OMF
463     if (cmd_data->output_type == otObject ||
464         cmd_data->output_type == otProgram ||
465         cmd_data->output_type == otDynamicLibrary) {
466         cmd_data->arglist[cmd_data->num_args++] = "-Zomf";
467     }
468 #endif
469
470     if (shared && (cmd_data->output_type == otObject || cmd_data->output_type == otDynamicLibrary)) {
471         cmd_data->arglist[cmd_data->num_args++] = SHARE_SW;
472     }
473 }
474
475
476
477 int execute_command(cmd_data_t *cmd_data)
478 {
479     int target = 0;
480     char *command;
481     int a, total_len = 0;
482     char *args[4];
483
484     for (a=0; a < cmd_data->num_args; a++) {
485         if (cmd_data->arglist[a]) {
486             total_len += strlen(cmd_data->arglist[a]) + 1;
487         }
488     }
489
490     command = (char *)malloc( total_len );
491     command[0] = 0;
492
493     for (a=0; a < cmd_data->num_args; a++) {
494         if (cmd_data->arglist[a]) {
495             strcat(command, cmd_data->arglist[a]);
496             strcat(command, " ");
497         }
498     }
499
500     command[strlen(command)-1] = 0;
501
502     if (!silent) {
503         puts(command);
504     }
505
506     cmd_data->num_args = target;
507     cmd_data->arglist[cmd_data->num_args] = NULL;
508     command = shell_esc(command);
509
510     args[0] = SHELL_CMD;
511     args[1] = "-c";
512     args[2] = command;
513     args[3] = NULL;
514     return spawnvp(P_WAIT, args[0], args);
515 }
516
517
518
519 char *shell_esc(const char *str)
520 {
521     char *cmd;
522     unsigned char *d;
523     const unsigned char *s;
524
525     cmd = (char *)malloc(2 * strlen(str) + 1);
526     d = (unsigned char *)cmd;
527     s = (const unsigned char *)str;
528
529     for (; *s; ++s) {
530         if (*s == '"' || *s == '\\') {
531             *d++ = '\\';
532         }
533         *d++ = *s;
534     }
535
536     *d = '\0';
537     return cmd;
538 }
539
540
541
542 bool explode_static_lib(char *lib, cmd_data_t *cmd_data)
543 {
544     char tmpdir[1024];
545     char savewd[1024];
546     char cmd[1024];
547     char *name;
548     DIR *dir;
549     struct dirent *entry;
550
551     strcpy(tmpdir, lib);
552     strcat(tmpdir, ".exploded");
553
554     mkdir(tmpdir, 0);
555     cmd_data->tmp_dirs[cmd_data->num_tmp_dirs++] = strdup(tmpdir);
556     getcwd(savewd, sizeof(savewd));
557
558     if (chdir(tmpdir) != 0)
559         return false;
560
561     strcpy(cmd, LIBRARIAN " x ");
562     name = strrchr(lib, '/');
563
564     if (name) {
565         name++;
566     } else {
567         name = lib;
568     }
569
570     strcat(cmd, "../");
571     strcat(cmd, name);
572     system(cmd);
573     chdir(savewd);
574     dir = opendir(tmpdir);
575
576     while ((entry = readdir(dir)) != NULL) {
577         if (entry->d_name[0] != '.') {
578             strcpy(cmd, tmpdir);
579             strcat(cmd, "/");
580             strcat(cmd, entry->d_name);
581             cmd_data->arglist[cmd_data->num_args++] = strdup(cmd);
582         }
583     }
584
585     closedir(dir);
586     return true;
587 }
588
589
590
591 void cleanup_tmp_dir(char *dirname)
592 {
593     DIR *dir;
594     struct dirent *entry;
595     char fullname[1024];
596
597     dir = opendir(dirname);
598
599     if (dir == NULL)
600         return;
601
602     while ((entry = readdir(dir)) != NULL) {
603         if (entry->d_name[0] != '.') {
604             strcpy(fullname, dirname);
605             strcat(fullname, "/");
606             strcat(fullname, entry->d_name);
607             remove(fullname);
608         }
609     }
610
611     rmdir(dirname);
612 }
613
614
615
616 void cleanup_tmp_dirs(cmd_data_t *cmd_data)
617 {
618     int d;
619
620     for (d=0; d < cmd_data->num_tmp_dirs; d++) {
621         cleanup_tmp_dir(cmd_data->tmp_dirs[d]);
622     }
623 }
624
625
626
627 void generate_def_file(cmd_data_t *cmd_data)
628 {
629     char def_file[1024];
630     char implib_file[1024];
631     char *ext;
632     FILE *hDef;
633     char *export_args[1024];
634     int num_export_args = 0;
635     char *cmd;
636     int cmd_size = 0;
637     int a;
638
639     if (cmd_data->output_name) {
640         strcpy(def_file, cmd_data->output_name);
641         strcat(def_file, ".def");
642         hDef = fopen(def_file, "w");
643
644         if (hDef != NULL) {
645             fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name));
646             fprintf(hDef, "DATA NONSHARED\n");
647             fprintf(hDef, "EXPORTS\n");
648             fclose(hDef);
649
650             for (a=0; a < cmd_data->num_obj_files; a++) {
651                 cmd_size += strlen(cmd_data->obj_files[a]) + 1;
652             }
653
654             cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
655             cmd = (char *)malloc(cmd_size);
656             strcpy(cmd, GEN_EXPORTS);
657
658             for (a=0; a < cmd_data->num_obj_files; a++) {
659                 strcat(cmd, " ");
660                 strcat(cmd, cmd_data->obj_files[a] );
661             }
662
663             strcat(cmd, ">>");
664             strcat(cmd, def_file);
665             puts(cmd);
666             export_args[num_export_args++] = SHELL_CMD;
667             export_args[num_export_args++] = "-c";
668             export_args[num_export_args++] = cmd;
669             export_args[num_export_args++] = NULL;
670             spawnvp(P_WAIT, export_args[0], export_args);
671             cmd_data->arglist[cmd_data->num_args++] = strdup(def_file);
672
673             /* Now make an import library for the dll */
674             num_export_args = 0;
675             export_args[num_export_args++] = DEF2IMPLIB_CMD;
676             export_args[num_export_args++] = "-o";
677
678             strcpy(implib_file, ".libs/");
679             strcat(implib_file, cmd_data->stub_name);
680             ext = strrchr(implib_file, '.');
681
682             if (ext)
683                 *ext = 0;
684
685             strcat(implib_file, ".");
686             strcat(implib_file, STATIC_LIB_EXT);
687
688             export_args[num_export_args++] = implib_file;
689             export_args[num_export_args++] = def_file;
690             export_args[num_export_args++] = NULL;
691             spawnvp(P_WAIT, export_args[0], export_args);
692         }
693     }
694 }
695
696
697
698 /* returns just a file's name without path or extension */
699 char *nameof(char *fullpath)
700 {
701     char buffer[1024];
702     char *ext;
703     char *name = strrchr(fullpath, '/');
704
705     if (name == NULL) {
706         name = strrchr(fullpath, '\\');
707     }
708
709     if (name == NULL) {
710         name = fullpath;
711     } else {
712         name++;
713     }
714
715     strcpy(buffer, name);
716     ext = strrchr(buffer, '.');
717
718     if (ext) {
719         *ext = 0;
720         return strdup(buffer);
721     }
722
723     return name;
724 }
725
726
727
728 char *truncate_dll_name(char *path)
729 {
730     /* Cut DLL name down to 8 characters after removing any mod_ prefix */
731     char *tmppath = strdup(path);
732     char *newname = strrchr(tmppath, '/') + 1;
733     char *ext = strrchr(tmppath, '.');
734     int len;
735
736     if (ext == NULL)
737         return tmppath;
738
739     len = ext - newname;
740
741     if (strncmp(newname, "mod_", 4) == 0) {
742         strcpy(newname, newname + 4);
743         len -= 4;
744     }
745
746     if (len > 8) {
747         strcpy(newname + 8, strchr(newname, '.'));
748     }
749
750     return tmppath;
751 }