123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755 |
- /* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <stdio.h>
- #include <process.h>
- #include <string.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <dirent.h>
- typedef char bool;
- #define false 0
- #define true (!false)
- bool silent = false;
- bool shared = false;
- bool export_all = false;
- enum mode_t { mCompile, mLink, mInstall };
- enum output_type_t { otGeneral, otObject, otProgram, otStaticLibrary, otDynamicLibrary };
- #ifdef __EMX__
- # define SHELL_CMD "sh"
- # define CC "gcc"
- # define GEN_EXPORTS "emxexp"
- # define DEF2IMPLIB_CMD "emximp"
- # define SHARE_SW "-Zdll -Zmtd"
- # define USE_OMF true
- # define TRUNCATE_DLL_NAME
- # define DYNAMIC_LIB_EXT "dll"
- # define EXE_EXT ".exe"
- # if USE_OMF
- /* OMF is the native format under OS/2 */
- # define STATIC_LIB_EXT "lib"
- # define OBJECT_EXT "obj"
- # define LIBRARIAN "emxomfar"
- # else
- /* but the alternative, a.out, can fork() which is sometimes necessary */
- # define STATIC_LIB_EXT "a"
- # define OBJECT_EXT "o"
- # define LIBRARIAN "ar"
- # endif
- #endif
- typedef struct {
- char *arglist[1024];
- int num_args;
- enum mode_t mode;
- enum output_type_t output_type;
- char *output_name;
- char *stub_name;
- char *tmp_dirs[1024];
- int num_tmp_dirs;
- char *obj_files[1024];
- int num_obj_files;
- } cmd_data_t;
- void parse_args(int argc, char *argv[], cmd_data_t *cmd_data);
- bool parse_long_opt(char *arg, cmd_data_t *cmd_data);
- int parse_short_opt(char *arg, cmd_data_t *cmd_data);
- bool parse_input_file_name(char *arg, cmd_data_t *cmd_data);
- bool parse_output_file_name(char *arg, cmd_data_t *cmd_data);
- void post_parse_fixup(cmd_data_t *cmd_data);
- bool explode_static_lib(char *lib, cmd_data_t *cmd_data);
- int execute_command(cmd_data_t *cmd_data);
- char *shell_esc(const char *str);
- void cleanup_tmp_dirs(cmd_data_t *cmd_data);
- void generate_def_file(cmd_data_t *cmd_data);
- char *nameof(char *fullpath);
- char *truncate_dll_name(char *path);
- int main(int argc, char *argv[])
- {
- int rc;
- cmd_data_t cmd_data;
- memset(&cmd_data, 0, sizeof(cmd_data));
- cmd_data.mode = mCompile;
- cmd_data.output_type = otGeneral;
- parse_args(argc, argv, &cmd_data);
- rc = execute_command(&cmd_data);
- if (rc == 0 && cmd_data.stub_name) {
- fopen(cmd_data.stub_name, "w");
- }
- cleanup_tmp_dirs(&cmd_data);
- return rc;
- }
- void parse_args(int argc, char *argv[], cmd_data_t *cmd_data)
- {
- int a;
- char *arg;
- bool argused;
- for (a=1; a < argc; a++) {
- arg = argv[a];
- argused = false;
- if (arg[0] == '-') {
- if (arg[1] == '-') {
- argused = parse_long_opt(arg + 2, cmd_data);
- } else if (arg[1] == 'o' && a+1 < argc) {
- cmd_data->arglist[cmd_data->num_args++] = arg;
- arg = argv[++a];
- argused = parse_output_file_name(arg, cmd_data);
- } else {
- int num_used = parse_short_opt(arg + 1, cmd_data);
- argused = num_used > 0;
- if (num_used > 1) {
- a += num_used - 1;
- }
- }
- } else {
- argused = parse_input_file_name(arg, cmd_data);
- }
- if (!argused) {
- cmd_data->arglist[cmd_data->num_args++] = arg;
- }
- }
- post_parse_fixup(cmd_data);
- }
- bool parse_long_opt(char *arg, cmd_data_t *cmd_data)
- {
- char *equal_pos = strchr(arg, '=');
- char var[50];
- char value[500];
- if (equal_pos) {
- strncpy(var, arg, equal_pos - arg);
- var[equal_pos - arg] = 0;
- strcpy(value, equal_pos + 1);
- } else {
- strcpy(var, arg);
- }
- if (strcmp(var, "silent") == 0) {
- silent = true;
- } else if (strcmp(var, "mode") == 0) {
- if (strcmp(value, "compile") == 0) {
- cmd_data->mode = mCompile;
- cmd_data->output_type = otObject;
- }
- if (strcmp(value, "link") == 0) {
- cmd_data->mode = mLink;
- }
- if (strcmp(value, "install") == 0) {
- cmd_data->mode = mInstall;
- }
- } else if (strcmp(var, "shared") == 0) {
- shared = true;
- } else if (strcmp(var, "export-all") == 0) {
- export_all = true;
- } else {
- return false;
- }
- return true;
- }
- int parse_short_opt(char *arg, cmd_data_t *cmd_data)
- {
- if (strcmp(arg, "export-dynamic") == 0) {
- return 1;
- }
- if (strcmp(arg, "module") == 0) {
- return 1;
- }
- if (strcmp(arg, "Zexe") == 0) {
- return 1;
- }
- if (strcmp(arg, "avoid-version") == 0) {
- return 1;
- }
- if (strcmp(arg, "prefer-pic") == 0) {
- return 1;
- }
- if (strcmp(arg, "prefer-non-pic") == 0) {
- return 1;
- }
- if (strcmp(arg, "version-info") == 0 ) {
- return 2;
- }
- if (strcmp(arg, "no-install") == 0) {
- return 1;
- }
- return 0;
- }
- bool parse_input_file_name(char *arg, cmd_data_t *cmd_data)
- {
- char *ext = strrchr(arg, '.');
- char *name = strrchr(arg, '/');
- int pathlen;
- char *newarg;
- if (!ext) {
- return false;
- }
- ext++;
- if (name == NULL) {
- name = strrchr(arg, '\\');
- if (name == NULL) {
- name = arg;
- } else {
- name++;
- }
- } else {
- name++;
- }
- pathlen = name - arg;
- if (strcmp(ext, "lo") == 0) {
- newarg = (char *)malloc(strlen(arg) + 10);
- strcpy(newarg, arg);
- strcpy(newarg + (ext - arg), OBJECT_EXT);
- cmd_data->arglist[cmd_data->num_args++] = newarg;
- cmd_data->obj_files[cmd_data->num_obj_files++] = newarg;
- return true;
- }
- if (strcmp(ext, "la") == 0) {
- newarg = (char *)malloc(strlen(arg) + 10);
- strcpy(newarg, arg);
- newarg[pathlen] = 0;
- strcat(newarg, ".libs/");
- if (strncmp(name, "lib", 3) == 0) {
- name += 3;
- }
- strcat(newarg, name);
- ext = strrchr(newarg, '.') + 1;
- if (shared && cmd_data->mode == mInstall) {
- strcpy(ext, DYNAMIC_LIB_EXT);
- newarg = truncate_dll_name(newarg);
- } else {
- strcpy(ext, STATIC_LIB_EXT);
- }
- cmd_data->arglist[cmd_data->num_args++] = newarg;
- return true;
- }
- if (strcmp(ext, "c") == 0) {
- if (cmd_data->stub_name == NULL) {
- cmd_data->stub_name = (char *)malloc(strlen(arg) + 4);
- strcpy(cmd_data->stub_name, arg);
- strcpy(strrchr(cmd_data->stub_name, '.') + 1, "lo");
- }
- }
- if (strcmp(name, CC) == 0 || strcmp(name, CC EXE_EXT) == 0) {
- if (cmd_data->output_type == otGeneral) {
- cmd_data->output_type = otObject;
- }
- }
- return false;
- }
- bool parse_output_file_name(char *arg, cmd_data_t *cmd_data)
- {
- char *name = strrchr(arg, '/');
- char *ext = strrchr(arg, '.');
- char *newarg = NULL, *newext;
- int pathlen;
- if (name == NULL) {
- name = strrchr(arg, '\\');
- if (name == NULL) {
- name = arg;
- } else {
- name++;
- }
- } else {
- name++;
- }
- if (!ext) {
- cmd_data->stub_name = arg;
- cmd_data->output_type = otProgram;
- newarg = (char *)malloc(strlen(arg) + 5);
- strcpy(newarg, arg);
- strcat(newarg, EXE_EXT);
- cmd_data->arglist[cmd_data->num_args++] = newarg;
- cmd_data->output_name = newarg;
- return true;
- }
- ext++;
- pathlen = name - arg;
- if (strcmp(ext, "la") == 0) {
- cmd_data->stub_name = arg;
- cmd_data->output_type = shared ? otDynamicLibrary : otStaticLibrary;
- newarg = (char *)malloc(strlen(arg) + 10);
- mkdir(".libs", 0);
- strcpy(newarg, ".libs/");
- if (strncmp(arg, "lib", 3) == 0) {
- arg += 3;
- }
- strcat(newarg, arg);
- newext = strrchr(newarg, '.') + 1;
- strcpy(newext, shared ? DYNAMIC_LIB_EXT : STATIC_LIB_EXT);
- #ifdef TRUNCATE_DLL_NAME
- if (shared) {
- newarg = truncate_dll_name(newarg);
- }
- #endif
- cmd_data->arglist[cmd_data->num_args++] = newarg;
- cmd_data->output_name = newarg;
- return true;
- }
- if (strcmp(ext, "lo") == 0) {
- cmd_data->stub_name = arg;
- cmd_data->output_type = otObject;
- newarg = (char *)malloc(strlen(arg) + 2);
- strcpy(newarg, arg);
- ext = strrchr(newarg, '.') + 1;
- strcpy(ext, OBJECT_EXT);
- cmd_data->arglist[cmd_data->num_args++] = newarg;
- cmd_data->output_name = newarg;
- return true;
- }
- return false;
- }
- void post_parse_fixup(cmd_data_t *cmd_data)
- {
- int a;
- char *arg;
- char *ext;
- if (cmd_data->output_type == otStaticLibrary && cmd_data->mode == mLink) {
- /* We do a real hatchet job on the args when making a static library
- * removing all compiler switches & any other cruft that ar won't like
- * We also need to explode any libraries listed
- */
- for (a=0; a < cmd_data->num_args; a++) {
- arg = cmd_data->arglist[a];
- if (arg) {
- ext = strrchr(arg, '.');
- if (ext) {
- ext++;
- }
- if (arg[0] == '-') {
- cmd_data->arglist[a] = NULL;
- if (strcmp(arg, "-rpath") == 0 && a+1 < cmd_data->num_args) {
- cmd_data->arglist[a+1] = NULL;
- }
- if (strcmp(arg, "-R") == 0 && a+1 < cmd_data->num_args) {
- cmd_data->arglist[a+1] = NULL;
- }
- if (strcmp(arg, "-version-info") == 0 && a+1 < cmd_data->num_args) {
- cmd_data->arglist[a+1] = NULL;
- }
- if (strcmp(arg, "-Zstack") == 0 && a+1 < cmd_data->num_args) {
- cmd_data->arglist[a+1] = NULL;
- }
- if (strcmp(arg, "-o") == 0) {
- a++;
- }
- }
- if (strcmp(arg, CC) == 0 || strcmp(arg, CC EXE_EXT) == 0) {
- cmd_data->arglist[a] = LIBRARIAN " cr";
- }
- if (ext) {
- if (strcmp(ext, "h") == 0 || strcmp(ext, "c") == 0) {
- /* ignore source files, they don't belong in a library */
- cmd_data->arglist[a] = NULL;
- }
- if (strcmp(ext, STATIC_LIB_EXT) == 0) {
- cmd_data->arglist[a] = NULL;
- explode_static_lib(arg, cmd_data);
- }
- }
- }
- }
- }
- if (cmd_data->output_type == otDynamicLibrary) {
- for (a=0; a < cmd_data->num_args; a++) {
- arg = cmd_data->arglist[a];
- if (arg) {
- if (strcmp(arg, "-rpath") == 0 && a+1 < cmd_data->num_args) {
- cmd_data->arglist[a] = NULL;
- cmd_data->arglist[a+1] = NULL;
- }
- }
- }
- if (export_all) {
- generate_def_file(cmd_data);
- }
- }
- #if USE_OMF
- if (cmd_data->output_type == otObject ||
- cmd_data->output_type == otProgram ||
- cmd_data->output_type == otDynamicLibrary) {
- cmd_data->arglist[cmd_data->num_args++] = "-Zomf";
- }
- #endif
- if (shared && (cmd_data->output_type == otObject || cmd_data->output_type == otDynamicLibrary)) {
- cmd_data->arglist[cmd_data->num_args++] = SHARE_SW;
- }
- }
- int execute_command(cmd_data_t *cmd_data)
- {
- int target = 0;
- char *command;
- int a, total_len = 0;
- char *args[4];
- for (a=0; a < cmd_data->num_args; a++) {
- if (cmd_data->arglist[a]) {
- total_len += strlen(cmd_data->arglist[a]) + 1;
- }
- }
- command = (char *)malloc( total_len );
- command[0] = 0;
- for (a=0; a < cmd_data->num_args; a++) {
- if (cmd_data->arglist[a]) {
- strcat(command, cmd_data->arglist[a]);
- strcat(command, " ");
- }
- }
- command[strlen(command)-1] = 0;
- if (!silent) {
- puts(command);
- }
- cmd_data->num_args = target;
- cmd_data->arglist[cmd_data->num_args] = NULL;
- command = shell_esc(command);
- args[0] = SHELL_CMD;
- args[1] = "-c";
- args[2] = command;
- args[3] = NULL;
- return spawnvp(P_WAIT, args[0], args);
- }
- char *shell_esc(const char *str)
- {
- char *cmd;
- unsigned char *d;
- const unsigned char *s;
- cmd = (char *)malloc(2 * strlen(str) + 1);
- d = (unsigned char *)cmd;
- s = (const unsigned char *)str;
- for (; *s; ++s) {
- if (*s == '"' || *s == '\\') {
- *d++ = '\\';
- }
- *d++ = *s;
- }
- *d = '\0';
- return cmd;
- }
- bool explode_static_lib(char *lib, cmd_data_t *cmd_data)
- {
- char tmpdir[1024];
- char savewd[1024];
- char cmd[1024];
- char *name;
- DIR *dir;
- struct dirent *entry;
- strcpy(tmpdir, lib);
- strcat(tmpdir, ".exploded");
- mkdir(tmpdir, 0);
- cmd_data->tmp_dirs[cmd_data->num_tmp_dirs++] = strdup(tmpdir);
- getcwd(savewd, sizeof(savewd));
- if (chdir(tmpdir) != 0)
- return false;
- strcpy(cmd, LIBRARIAN " x ");
- name = strrchr(lib, '/');
- if (name) {
- name++;
- } else {
- name = lib;
- }
- strcat(cmd, "../");
- strcat(cmd, name);
- system(cmd);
- chdir(savewd);
- dir = opendir(tmpdir);
- while ((entry = readdir(dir)) != NULL) {
- if (entry->d_name[0] != '.') {
- strcpy(cmd, tmpdir);
- strcat(cmd, "/");
- strcat(cmd, entry->d_name);
- cmd_data->arglist[cmd_data->num_args++] = strdup(cmd);
- }
- }
- closedir(dir);
- return true;
- }
- void cleanup_tmp_dir(char *dirname)
- {
- DIR *dir;
- struct dirent *entry;
- char fullname[1024];
- dir = opendir(dirname);
- if (dir == NULL)
- return;
- while ((entry = readdir(dir)) != NULL) {
- if (entry->d_name[0] != '.') {
- strcpy(fullname, dirname);
- strcat(fullname, "/");
- strcat(fullname, entry->d_name);
- remove(fullname);
- }
- }
- rmdir(dirname);
- }
- void cleanup_tmp_dirs(cmd_data_t *cmd_data)
- {
- int d;
- for (d=0; d < cmd_data->num_tmp_dirs; d++) {
- cleanup_tmp_dir(cmd_data->tmp_dirs[d]);
- }
- }
- void generate_def_file(cmd_data_t *cmd_data)
- {
- char def_file[1024];
- char implib_file[1024];
- char *ext;
- FILE *hDef;
- char *export_args[1024];
- int num_export_args = 0;
- char *cmd;
- int cmd_size = 0;
- int a;
- if (cmd_data->output_name) {
- strcpy(def_file, cmd_data->output_name);
- strcat(def_file, ".def");
- hDef = fopen(def_file, "w");
- if (hDef != NULL) {
- fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name));
- fprintf(hDef, "DATA NONSHARED\n");
- fprintf(hDef, "EXPORTS\n");
- fclose(hDef);
- for (a=0; a < cmd_data->num_obj_files; a++) {
- cmd_size += strlen(cmd_data->obj_files[a]) + 1;
- }
- cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
- cmd = (char *)malloc(cmd_size);
- strcpy(cmd, GEN_EXPORTS);
- for (a=0; a < cmd_data->num_obj_files; a++) {
- strcat(cmd, " ");
- strcat(cmd, cmd_data->obj_files[a] );
- }
- strcat(cmd, ">>");
- strcat(cmd, def_file);
- puts(cmd);
- export_args[num_export_args++] = SHELL_CMD;
- export_args[num_export_args++] = "-c";
- export_args[num_export_args++] = cmd;
- export_args[num_export_args++] = NULL;
- spawnvp(P_WAIT, export_args[0], export_args);
- cmd_data->arglist[cmd_data->num_args++] = strdup(def_file);
- /* Now make an import library for the dll */
- num_export_args = 0;
- export_args[num_export_args++] = DEF2IMPLIB_CMD;
- export_args[num_export_args++] = "-o";
- strcpy(implib_file, ".libs/");
- strcat(implib_file, cmd_data->stub_name);
- ext = strrchr(implib_file, '.');
- if (ext)
- *ext = 0;
- strcat(implib_file, ".");
- strcat(implib_file, STATIC_LIB_EXT);
- export_args[num_export_args++] = implib_file;
- export_args[num_export_args++] = def_file;
- export_args[num_export_args++] = NULL;
- spawnvp(P_WAIT, export_args[0], export_args);
- }
- }
- }
- /* returns just a file's name without path or extension */
- char *nameof(char *fullpath)
- {
- char buffer[1024];
- char *ext;
- char *name = strrchr(fullpath, '/');
- if (name == NULL) {
- name = strrchr(fullpath, '\\');
- }
- if (name == NULL) {
- name = fullpath;
- } else {
- name++;
- }
- strcpy(buffer, name);
- ext = strrchr(buffer, '.');
- if (ext) {
- *ext = 0;
- return strdup(buffer);
- }
- return name;
- }
- char *truncate_dll_name(char *path)
- {
- /* Cut DLL name down to 8 characters after removing any mod_ prefix */
- char *tmppath = strdup(path);
- char *newname = strrchr(tmppath, '/') + 1;
- char *ext = strrchr(tmppath, '.');
- int len;
- if (ext == NULL)
- return tmppath;
- len = ext - newname;
- if (strncmp(newname, "mod_", 4) == 0) {
- strcpy(newname, newname + 4);
- len -= 4;
- }
- if (len > 8) {
- strcpy(newname + 8, strchr(newname, '.'));
- }
- return tmppath;
- }
|