/* Copyright (C) 1994, Klaus Preschern. */ /* All rights reserved. */ /* See the file COPYRIGHT.KP for a full description. */ #include #include #include #include #define DEBUG 0 #define PATH_LEN 1024 #define QUAKE_LEN 1024 #define TARGET_LEN 1024 static char quake [] = "/ex32/usr/local/bin/quake"; static char template_dir [PATH_LEN] = "/ex32/usr/local/lib/m3/pkg/m3build/templates"; static char template [PATH_LEN] = "DOS"; static char build_dir [PATH_LEN] = "DOS"; static char start_dir [PATH_LEN] = "."; static char quake_args [QUAKE_LEN] = ""; static char targets [TARGET_LEN] = ""; static char src_ok [2] = "0"; static char use_overrides [2] = "0"; static char verbose [2] = "n"; static char base [PATH_LEN] = ""; static char parent [PATH_LEN] = ""; static char tmp [PATH_LEN] = ""; static char basetmp [PATH_LEN] = ""; static char package_dir [PATH_LEN] = ""; static char makefile [PATH_LEN] = ""; static char overrides [PATH_LEN] = ""; static char package [PATH_LEN] = ""; static char target [PATH_LEN] = ""; static int is_dir (char * name) { struct stat statbuf; #if DEBUG printf ("is_dir (%s)\n", name); #endif if (stat (name, &statbuf) < 0) { return 0; } return (statbuf.st_mode & __S_IFDIR); } static int readable (char * name) { /* we do not check for readability, just for existence */ struct stat statbuf; #if DEBUG printf ("readable (%s)\n", name); #endif return (!(stat (name, &statbuf) < 0)); } static char * dircat (char * dir1, char * dir2) { char tmp1 [PATH_LEN], tmp2 [PATH_LEN]; /* 'dir1' or 'dir2' could be 'tmp' */ strcpy (tmp1, dir1); strcpy (tmp2, dir2); strcat (tmp1, "/"); strcpy (tmp, tmp1); strcat (tmp, tmp2); #if DEBUG printf ("dircat (%s)\n", tmp); #endif return tmp; } static int skip_blanks (char * name, int i) { while ((name [i] == ' ') && (name [i] != '\0')) { i++; } return i; } static int getnext (char * part, char * components, int i) { int j = 0; i = skip_blanks (components, i); if (components [i] == '\0') { return -1; } while ((components [i] != ' ') && (components [i] != '\0')) { part [j++] = components [i++]; part [j] = '\0'; } return i; } static void print_usage (void) { printf ("usage: m3build [options] [targets]\n"); printf ("-b build with this template and in this directory (default=\'%s\')\n", build_dir); printf ("-T use templates in specified directory (default=\'%s\')\n", template_dir); printf ("-S build in 'src' directory\n"); printf ("-d start in this directory (default=\'%s\')\n", start_dir); printf ("-v verbose\n"); printf ("-h print this messsage\n"); printf ("- pass this argument to quake\n"); printf (" ... call quake with each target\n"); printf ("\n"); } /* * parse the command line */ static void parse_command_line (int argc, char ** argv) { int i = 1; while (i < argc) { if (strcmp (argv [i], "-b") == 0) { if (i++ >= argc) break; strcpy (build_dir, argv [i]); strcpy (template, argv [i]); } else if (strcmp (argv [i], "-T") == 0) { if (i++ >= argc) break; strcpy (template_dir, argv [i]); } else if (strcmp (argv [i], "-F") == 0) { if (i++ >= argc) break; strcat (quake_args, " "); strcat (quake_args, argv [i]); } else if (strcmp (argv [i], "-S") == 0) { strcpy (src_ok, "1"); } else if (strcmp (argv [i], "-O") == 0) { strcpy (use_overrides, "1"); } else if (strcmp (argv [i], "-d") == 0) { if (i++ >= argc) break; strcpy (start_dir, argv [i]); } else if (strcmp (argv [i], "-v") == 0) { strcpy (verbose, "y"); } else if (strcmp (argv [i], "-h") == 0) { print_usage (); exit (0); } else if (argv [i] [0] == '-') { /* quake args */ strcat (quake_args, " "); strcat (quake_args, argv [i]); } else { /* targets */ strcat (targets, " "); strcat (targets, argv [i]); } i++; } #if DEBUG printf (" --------------------------- \n"); for (i = 0; i < argc; i++) { printf ("argv [%d] = %s\n", i, argv [i]); } printf (" --------------------------- \n"); #endif } /* * get basename */ static char * basename (char * name) { int i, len; i = len = strlen (name); while ((--i >= 0) && (name [i] != '/') && (name [i] != '\\')) ; /* i could be (-1) */ strncpy (basetmp, &name [i+1], len - i + 1); #if DEBUG printf ("basename (%s) = %s\n", name, basetmp); #endif return basetmp; } /* * get to the initial directory */ static void goto_initial_directory (void) { chdir (start_dir); getcwd (start_dir, PATH_LEN); /* base=`basename "$start_dir"` */ strcpy (base, basename (start_dir)); chdir (".."); getcwd (parent, PATH_LEN); /* parent=`cd .. ; pwd` */ chdir (start_dir); #if DEBUG printf ("start_dir = %s, parent = %s, base = %s\n", start_dir, parent, base); #endif } /* * move to the directory with derived objects */ static void goto_dir_with_derived_objects (void) { if (strcmp (src_ok, "0") == 0) { /* if [ $src_ok = "0" ] */ if (strcmp (base, "src") == 0) { /* if [ $base = "src" ] */ printf ("m3build: use -S to build in the \'src\' directory\n"); exit (-1); } else if (strcmp (base, build_dir) == 0) { /* elif [ $base = $build_dir ] */ strcpy (package_dir, parent); } else if (is_dir (build_dir)) { /* elif [ -d "$build_dir" ] */ strcpy (package_dir, start_dir); printf ("--- building in %s ---\n", build_dir); chdir (build_dir); } else if (is_dir ("src") && readable (dircat (template_dir, template))) { /* elif [ -d src -a -r "$template_dir/$template" ] */ strcpy (package_dir, start_dir); printf ("mkdir %s\n", build_dir); mkdir (build_dir, 0); printf ("--- building in %s ---\n", build_dir); chdir (build_dir); } else { printf ("m3build: no build directory %s\n", build_dir); exit (-1); } } else { /* assume that we're in an immediate subdirectory of the package */ strcpy (package_dir, parent); strcpy (build_dir, base); } strcpy (package, basename (package_dir)); #if DEBUG printf ("package_dir = %s, build_dir = %s, package = %s\n", package_dir, build_dir, package); #endif } /* * check for a makefile */ static void check_for_makefile (void) { if (readable ("m3makefile")) { /* makefile="$package_dir/$build_dir/m3makefile" */ strcpy (makefile, dircat (package_dir, dircat (build_dir, "m3makefile"))); /* overrides="$package_dir/$build_dir/m3overrides" */ strcpy (overrides, dircat (package_dir, dircat (build_dir, "m3overrides"))); } else if (readable ("../src/m3makefile")) { /* makefile="$package_dir/src/m3makefile" */ strcpy (makefile, dircat (package_dir, "src/m3makefile")); /* overrides="$package_dir/src/m3overrides" */ strcpy (overrides, dircat (package_dir, "src/m3overrides")); } else { printf ("m3build: cannot locate an m3makefile\n"); exit (-1); } #if DEBUG printf ("makefile = %s, overrides = %s\n", makefile, overrides); #endif } /* * check for an overrides file */ static void check_for_overrides_file (void) { if (readable (overrides)) { if (strcmp (use_overrides, "0") != 0) { /* quake_args="$quake_args $overrides" */ strcat (quake_args, " "); strcat (quake_args, overrides); } else { printf ("m3build: ignoring %s\n", overrides); } } else { if (strcmp (use_overrides, "0") != 0) { printf ("m3build: missing %s\n", overrides); } } #if DEBUG printf ("quake_args = %s\n", quake_args); #endif } /* * did we get an explicit target? */ static void check_target (void) { if (strlen (targets) == 0) { strcpy (targets, "all"); } #if DEBUG printf ("targets = %s\n", targets); #endif } extern char ** environ; static int execute (char * quake, char * target, char * package_dir, char * package, char * build_dir, char * template_dir, char * quake_args, char * makefile) { /* quake -D_$target -DPACKAGE_DIR=$package_dir -DPACKAGE=$package * -DBUILD_DIR=$build_dir $template_dir/$template $quake_args $makefile */ char args [30] [PATH_LEN]; int i = 0, j = 0, status; char quake_arg [PATH_LEN]; char * argv [30]; strcpy (args [0], quake); argv [0] = &args [0][0]; strcpy (args [1], "-D_"); strcat (args [1], target); argv [1] = &args [1][0]; strcpy (args [2], "-DPACKAGE_DIR="); strcat (args [2], package_dir); argv [2] = &args [2][0]; strcpy (args [3], "-DPACKAGE="); strcat (args [3], package); argv [3] = &args [3][0]; strcpy (args [4], "-DBUILD_DIR="); strcat (args [4], build_dir); argv [4] = &args [4][0]; strcpy (args [5], template_dir); argv [5] = &args [5][0]; while ((i = getnext (quake_arg, quake_args, i)) > 0) { strcpy (args [6 + j], quake_arg); argv [6 + j] = &args [6 + j][0]; j++; } strcpy (args [6 + j], makefile); argv [6 + j] = &args [6 + j][0]; argv [6 + j + 1] = 0; #if DEBUG j = 0; printf ("-----------------------------\n"); while (argv [j]) { printf ("argv [%d] = %s\n", j, argv [j]); j++; } printf ("-----------------------------\n"); #endif if (vfork () == 0) { /* child */ if (execve (quake, argv, environ) < 0) { printf ("m3build: cannot execute %s\n", quake); exit (-1); } } /* parent */ wait (&status); return status; } /* * prepare for the worst... * * trap 'exit 1' 1 2 3 15 */ /* * finally, evaulate the makefile once for each target */ static void evaluate_makefile (void) { int i = 0; while ((i = getnext (target, targets, i)) > 0) { if (strcmp (verbose, "y") == 0) { printf ("%s -D_%s -DPACKAGE_DIR=%s -DPACKAGE=%s ", quake, target, package_dir, package); printf ("-DBUILD_DIR=%s %s/%s %s %s\n", build_dir, template_dir, template, quake_args, makefile); } /* quake -D_$target -DPACKAGE_DIR=$package_dir -DPACKAGE=$package * -DBUILD_DIR=$build_dir $template_dir/$template $quake_args $makefile */ if (execute (quake, target, package_dir, package, build_dir, dircat (template_dir, template), quake_args, makefile) < 0) { exit (-1); } } } int main (int argc, char ** argv, char ** envp) { parse_command_line (argc, argv); goto_initial_directory (); goto_dir_with_derived_objects (); check_for_makefile (); check_for_overrides_file (); check_target (); evaluate_makefile (); return 0; }