/* $Id: pmk.c 1941 2006-12-08 17:08:28Z coudercd $ */
/*
* Copyright (c) 2003-2005 Damien Couderc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* - Neither the name of the copyright holder(s) nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* Credits for patches :
* - Pierre-Yves Ritschard
*/
#include <sys/stat.h>
/* include it first as if it was <sys/types.h> - this will avoid errors */
#include "compat/pmk_sys_types.h"
#include <errno.h>
#include <stdlib.h>
#include "compat/pmk_ctype.h"
#include "compat/pmk_libgen.h" /* basename, dirname */
#include "compat/pmk_stdio.h"
#include "compat/pmk_string.h" /* strlcpy */
#include "compat/pmk_unistd.h"
#include "autoconf.h"
#include "common.h"
#include "func.h"
#include "hash_tools.h"
#include "lang.h"
#include "pathtools.h"
#include "pmk.h"
#include "tags.h"
/*#define PMK_DEBUG 1*/
/*************
* variables *
***********************************************************************/
extern char *optarg;
extern int optind;
extern prskw kw_pmkfile[];
extern size_t nbkwpf;
int cur_line = 0;
/******************
* init functions *
***********************************************************************/
/******************
* pmkdata_init() *
***********************************************************************
DESCR
init pmkdata structure
IN
NONE
OUT
pmkdata structure
***********************************************************************/
pmkdata *pmkdata_init(void) {
pmkdata *ppd;
ppd = (pmkdata *) malloc(sizeof(pmkdata));
if (ppd == NULL)
return(NULL);
/* initialise global data hash table */
ppd->htab = hash_init(MAX_DATA_KEY);
if (ppd->htab == NULL) {
errorf("cannot initialize hash table for data.");
return(NULL);
}
ppd->labl = hash_init(MAX_LABEL_KEY);
if (ppd->labl == NULL) {
hash_destroy(ppd->htab);
errorf("cannot initialize hash table for labels.");
return(NULL);
}
if (init_compiler_data(&(ppd->comp_data), LANG_NUMBER) == false) {
hash_destroy(ppd->htab);
hash_destroy(ppd->labl);
errorf("cannot initialize compiler data structure.");
return(NULL);
}
/* init compiler detection flag */
ppd->sys_detect = false;
/* init autoconf file */
ppd->ac_file = NULL;
/* init template list */
ppd->tlist = NULL;
/* init default language */
ppd->lang = NULL;
/* init on demand */
ppd->cfgt = NULL;
return(ppd);
}
/**************
* init_var() *
***********************************************************************
DESCR
init variables
IN
pgd : global data structure
OUT
NONE
***********************************************************************/
bool init_var(pmkdata *pgd) {
char buf[TMP_BUF_LEN],
*pstr;
htable *pht;
pht = pgd->htab;
pstr = MK_VAR_CFLAGS;
if (get_make_var(pstr, buf, sizeof(buf)) == false) {
buf[0] = CHAR_EOS; /* empty string */
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", pstr, buf);
#endif
if (hash_update_dup(pht, pstr, buf) == HASH_ADD_FAIL) {
return(false);
}
pstr = MK_VAR_CXXFLAGS;
if (get_make_var(pstr, buf, sizeof(buf)) == false) {
buf[0] = CHAR_EOS; /* empty string */
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", pstr, buf);
#endif
if (hash_update_dup(pht, pstr, buf) == HASH_ADD_FAIL) {
return(false);
}
pstr = MK_VAR_CPPFLAGS;
if (get_make_var(pstr, buf, sizeof(buf)) == false) {
buf[0] = CHAR_EOS; /* empty string */
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", pstr, buf);
#endif
if (hash_update_dup(pht, pstr, buf) == HASH_ADD_FAIL) {
return(false);
}
pstr = MK_VAR_LDFLAGS;
if (get_make_var(pstr, buf, sizeof(buf)) == false) {
buf[0] = CHAR_EOS; /* empty string */
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", pstr, buf);
#endif
if (hash_update_dup(pht, pstr, buf) == HASH_ADD_FAIL) {
return(false);
}
pstr = MK_VAR_CLDFLAGS;
if (get_make_var(pstr, buf, sizeof(buf)) == false) {
buf[0] = CHAR_EOS; /* empty string */
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", pstr, buf);
#endif
if (hash_update_dup(pht, pstr, buf) == HASH_ADD_FAIL) {
return(false);
}
pstr = MK_VAR_CXXLDFLAGS;
if (get_make_var(pstr, buf, sizeof(buf)) == false) {
buf[0] = CHAR_EOS; /* empty string */
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", pstr, buf);
#endif
if (hash_update_dup(pht, pstr, buf) == HASH_ADD_FAIL) {
return(false);
}
pstr = MK_VAR_LIBS;
if (get_make_var(pstr, buf, sizeof(buf)) == false) {
buf[0] = CHAR_EOS; /* empty string */
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", pstr, buf);
#endif
if (hash_update_dup(pht, pstr, buf) == HASH_ADD_FAIL) {
return(false);
}
pstr = MK_VAR_DEBUG;
if (get_make_var(pstr, buf, sizeof(buf)) == false) {
buf[0] = CHAR_EOS; /* empty string */
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", pstr, buf);
#endif
if (hash_update_dup(pht, pstr, buf) == HASH_ADD_FAIL) {
return(false);
}
/* autoconf shit ? *//* XXX YES !!! => to move ! */
if (hash_update_dup(pht, "OBJEXT", "o") == HASH_ADD_FAIL) {
return(false);
}
pstr = hash_get(pht, PMKCONF_BIN_CC);
if (pstr != NULL) {
if (hash_update_dup(pht, "CC", pstr) == HASH_ADD_FAIL) {
return(false);
}
}
pstr = hash_get(pht, PMKCONF_BIN_CXX);
if (pstr != NULL) {
if (hash_update_dup(pht, "CXX", pstr) == HASH_ADD_FAIL) {
return(false);
}
}
pstr = hash_get(pht, PMKCONF_BIN_CPP);
if (pstr != NULL) {
if (hash_update_dup(pht, "CPP", pstr) == HASH_ADD_FAIL) {
return(false);
}
}
pstr = hash_get(pht, PMKCONF_BIN_INSTALL);
if (pstr != NULL) {
if (hash_update_dup(pht, "INSTALL", pstr) == HASH_ADD_FAIL) {
return(false);
}
}
pstr = hash_get(pht, PMKCONF_BIN_AR);
if (pstr != NULL) {
if (hash_update_dup(pht, "AR", pstr) == HASH_ADD_FAIL) {
return(false);
}
}
pstr = hash_get(pht, PMKCONF_BIN_RANLIB);
if (pstr != NULL) {
if (hash_update_dup(pht, "RANLIB", pstr) == HASH_ADD_FAIL) {
return(false);
}
}
pstr = hash_get(pht, PMKCONF_BIN_SH);
if (pstr != NULL) {
if (hash_update_dup(pht, "SHELL", pstr) == HASH_ADD_FAIL) {
return(false);
}
}
pstr = hash_get(pht, PMKCONF_BIN_STRIP);
if (pstr != NULL) {
if (hash_update_dup(pht, "STRIP", pstr) == HASH_ADD_FAIL) {
return(false);
}
}
pstr = hash_get(pht, PMKCONF_BIN_AWK);
if (pstr != NULL) {
if (hash_update_dup(pht, "AWK", pstr) == HASH_ADD_FAIL) {
return(false);
}
}
pstr = hash_get(pht, PMKCONF_BIN_EGREP);
if (pstr != NULL) {
if (hash_update_dup(pht, "EGREP", pstr) == HASH_ADD_FAIL) {
return(false);
}
}
/* shared lib support */
if (hash_update_dup(pht, MK_VAR_SL_BUILD, "") == HASH_ADD_FAIL) {
return(false);
}
if (hash_update_dup(pht, MK_VAR_SL_CLEAN, "") == HASH_ADD_FAIL) {
return(false);
}
if (hash_update_dup(pht, MK_VAR_SL_INST, "") == HASH_ADD_FAIL) {
return(false);
}
if (hash_update_dup(pht, MK_VAR_SL_DEINST, "") == HASH_ADD_FAIL) {
return(false);
}
/* set absolute paths */
if (hash_update_dup(pht, PMK_DIR_SRC_ROOT_ABS, pgd->srcdir) == HASH_ADD_FAIL) {
return(false);
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", PMK_DIR_SRC_ROOT_ABS, pgd->srcdir);
#endif
if (hash_update_dup(pht, PMK_DIR_BLD_ROOT_ABS, pgd->basedir) == HASH_ADD_FAIL) {
return(false);
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", PMK_DIR_BLD_ROOT_ABS, pgd->basedir);
#endif
return(true);
}
/**********************
* template functions *
***********************************************************************/
/***********************
* process_dyn_paths() *
***********************************************************************
DESCR
process dynamic paths
IN
pgd : global data structure
tmplpath : file to process
OUT
NONE
***********************************************************************/
bool process_dyn_paths(pmkdata *pgd, char *tmplpath) {
char *srcdir,
*basedir,
tpath[MAXPATHLEN];
pmkdyn_t *pdd;
pdd = &(pgd->dyndata);
srcdir = pgd->srcdir;
basedir = pgd->basedir;
/*
get template path
NOTE : we use strdup() to avoid problem with linux's dirname
*/
if (strlcpy_b(tpath, tmplpath, sizeof(tpath)) == false) {
errorf(PMK_ERR_OVRFLOW);
return(false);
}
/* save template filename */
if (strlcpy_b(pdd->tmpl_name, basename(tpath), sizeof(pdd->tmpl_name)) == false) {
errorf(PMK_ERR_OVRFLOW);
return(false);
}
/* set absolute path of template */
if (strlcpy_b(pdd->src_abs, dirname(tpath), sizeof(pdd->src_abs)) == false) {
errorf(PMK_ERR_OVRFLOW);
return(false);
}
/* compute relative path */
if (relpath(srcdir, pdd->src_abs, tpath) == false) {
errorf(PMK_ERR_OVRFLOW);
return(false);
}
/* compute builddir_abs with relative path */
if (abspath(basedir, tpath, pdd->bld_abs) == false) {
errorf(PMK_ERR_OVRFLOW);
return(false);
}
/* compute relative path to builddir root */
if (relpath(pdd->bld_abs, basedir, pdd->bld_root_rel) == false) {
errorf(PMK_ERR_OVRFLOW);
return(false);
}
/* set buildir_rel to '.', useful ? */
if (strlcpy_b(pdd->bld_rel, ".", sizeof(pdd->bld_rel)) == false) {
errorf(PMK_ERR_OVRFLOW);
return(false);
}
/* compute and set relative path from basedir to srcdir */
if (relpath(pdd->bld_abs, srcdir, pdd->src_root_rel) == false) {
errorf(PMK_ERR_OVRFLOW);
return(false);
}
/* compute and set relative path from template to builddir */
if (relpath(pdd->bld_abs, pdd->src_abs, pdd->src_rel) == false) {
errorf(PMK_ERR_OVRFLOW);
return(false);
}
return(true);
}
/*********************
* process_dyn_var() *
***********************************************************************
DESCR
set dynamic path variables
IN
pgd : global data structure
template : file to process
OUT
NONE
***********************************************************************/
bool process_dyn_var(pmkdata *pgd) {
htable *pht;
pmkdyn_t *pdd;
pht = pgd->htab;
pdd = &(pgd->dyndata);
if (hash_update_dup(pht, PMK_DIR_BLD_ROOT_REL, pdd->bld_root_rel) == HASH_ADD_FAIL) {
return(false);
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", PMK_DIR_BLD_ROOT_REL, pdd->bld_root_rel);
#endif
if (hash_update_dup(pht, PMK_DIR_BLD_ABS, pdd->bld_abs) == HASH_ADD_FAIL) {
return(false);
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", PMK_DIR_BLD_ABS, pdd->bld_abs);
#endif
if (hash_update_dup(pht, PMK_DIR_BLD_REL, pdd->bld_rel) == HASH_ADD_FAIL) {
return(false);
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", PMK_DIR_BLD_REL, pdd->bld_rel);
#endif
if (hash_update_dup(pht, PMK_DIR_SRC_ROOT_REL, pdd->src_root_rel) == HASH_ADD_FAIL) {
return(false);
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", PMK_DIR_SRC_ROOT_REL, pdd->src_root_rel);
#endif
if (hash_update_dup(pht, PMK_DIR_SRC_ABS, pdd->src_abs) == HASH_ADD_FAIL) {
return(false);
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", PMK_DIR_SRC_ABS, pdd->src_abs);
#endif
if (hash_update_dup(pht, PMK_DIR_SRC_REL, pdd->src_rel) == HASH_ADD_FAIL) {
return(false);
}
#ifdef PMK_DEBUG
debugf("%s = '%s'", PMK_DIR_SRC_REL, pdd->src_rel);
#endif
return(true);
}
/**********************
* process_template() *
***********************************************************************
DESCR
process the target file to replace tags
IN
target : path of the target file
pgd : global data structure
OUT
boolean
***********************************************************************/
bool process_template(pmkdata *pgd, char *template) {
FILE *tfp,
*gfp;
bool ac_flag;
char *gfname,
*pstr,
gfpath[MAXPATHLEN],
buf[TMP_BUF_LEN];
htable *pht;
pmkdyn_t *pdd;
prseng_t *ppe;
pht = pgd->htab;
pdd = &(pgd->dyndata);
/* create path if it does not exists */
if (makepath(pdd->bld_abs, S_IRWXU | S_IRWXG | S_IRWXO) == false) {
errorf("cannot build template generated file path '%s'.", pdd->bld_abs);
return(false);
}
/* generate full path for generated file */
gfname = gen_from_tmpl(pdd->tmpl_name);
if (abspath(pdd->bld_abs, gfname, gfpath) == false) {
errorf("failed to build absolute path from '%s' and '%s'", pdd->bld_abs, gfname);
return(false);
}
tfp = fopen(template, "r");
if (tfp == NULL) {
errorf("cannot open '%s' : %s.", template, strerror(errno));
return(false);
}
gfp = fopen(gfpath, "w");
if (gfp == NULL) {
fclose(tfp); /* close already opened tfp before leaving */
errorf("cannot open '%s' : %s.", gfpath, strerror(errno));
return(false);
}
if (process_dyn_var(pgd) == false) {
errorf("failed to process dynamic variables.");
return(false);
}
/* check if autoconf dynamic variables are needed */
if (pgd->ac_file == NULL) {
ac_flag = false;
} else {
ac_flag = true;
/* XXX should use directly path ? */
if (ac_process_dyn_var(pgd, template) == false) {
errorf("failed to process autoconf dynamic variables.");
return(false);
}
}
/* generate @configure_input@ tag */
/* XXX handle in pmkscan templates ? */
if (snprintf_b(buf, sizeof(buf), PMK_GENMSG, gfname, pdd->tmpl_name) == false) {
return(false);
}
if (hash_update_dup(pht, "configure_input", buf) == HASH_ADD_FAIL) {
return(false);
}
/* init prseng with template */
ppe = prseng_init(tfp, NULL);
if (ppe == NULL) {
errorf("parse engine init failed.");
return(false);
}
/* while end of template is not reached */
while (prseng_eof(ppe) == false) {
if (prseng_test_char(ppe, PMK_TAG_CHAR) == true) {
/* skip tag character */
if (prseng_next_char(ppe) == false) {
return(false);
}
/* get tag identifier */
if (prseng_get_idtf(ppe, buf, sizeof(buf), PMK_TAG_IDTF_STR) == true) {
/* if valid tag identifier */
if (prseng_test_char(ppe, PMK_TAG_CHAR) == true) {
/* skip end of tag character */
if (prseng_next_char(ppe) == false) {
return(false);
}
/* try to get tag content */
pstr = (char *) hash_get(pht, buf);
if (pstr != NULL) {
/* put data */
fprintf(gfp, "%s", pstr);
} else {
/* else no data, put back tag def */
fprintf(gfp, "%c%s%c", PMK_TAG_CHAR, buf, PMK_TAG_CHAR);
}
} else {
/* else not a valid tag identifier */
fprintf(gfp, "%c%s%c", PMK_TAG_CHAR, buf, prseng_get_char(ppe));
/* skip character */
if (prseng_next_char(ppe) == false) {
return(false);
}
}
} else {
/* else failed to get a tag identifier */
fprintf(gfp, "%c%s", PMK_TAG_CHAR, buf);
}
} else {
/* put character in generated file */
fputc(prseng_get_char(ppe), gfp);
/* next character */
if (prseng_next_char(ppe) == false) {
return(false);
}
}
}
fclose(gfp);
fclose(tfp);
pmk_log("Created '%s'.\n", gfpath);
if (ac_flag == true) {
/* clean autoconf dynamic variables */
ac_clean_dyn_var(pht);
}
hash_delete(pht, "configure_input");
return(true);
}
/*******************
* template_main() *
***********************************************************************
DESCR
main procedure for template management
IN
pgd : global data structure
OUT
boolean
***********************************************************************/
bool template_main(pmkdata *pgd) {
char *pstr,
buf[MAXPATHLEN];
dynary *da;
unsigned int i;
da = pgd->tlist;
if (da == NULL) {
errorf("no target given.");
exit(EXIT_FAILURE);
}
/* process each template */
for (i = 0 ; i < da_usize(da) ; i++) {
pstr = da_idx(da, i);
if (pstr != NULL) {
if (abspath(pgd->srcdir, pstr, buf) == false) {
errorf("failed to build absolute path of '%s'.", pstr);
return(false);
}
if (process_dyn_paths(pgd, buf) == false) {
errorf("failed to process dynamic paths for '%s'.", buf);
return(false);
}
if (process_template(pgd, buf) == false) {
/* failure while processing template */
errorf("failed to process template '%s'.", buf);
return(false);
}
}
}
/* process eventual autoconf style config file */
if (pgd->ac_file != NULL) {
pmk_log("\nProcess '%s' for autoconf compatibility.\n", pgd->ac_file);
if (ac_parse_config(pgd) == false) {
/* failure while processing autoconf file */
errorf("failed to process autoconf config file '%s'.", pgd->ac_file);
return(false);
}
}
return(true);
}
/***************************
* miscellaneous functions *
***********************************************************************/
/*****************
* process_cmd() *
***********************************************************************
DESCR
process the parsed command
IN
pdata : parsed data
pgd : global data structure
OUT
boolean
***********************************************************************/
bool process_cmd(prsdata *pdata, pmkdata *pgd) {
return(process_node(pdata->tree, pgd));
}
/*******************
* parse_cmdline() *
***********************************************************************
DESCR
process command line values
IN
val : array of defines
nbval : size of the array
pgd : global data structure
OUT
boolean (true on success)
***********************************************************************/
bool parse_cmdline(char **val, int nbval, pmkdata *pgd) {
bool rval = true;
char *pstr;
htable *ht;
int i;
prsopt opt;
/* don't init pscell */
ht = pgd->htab;
for (i = 0 ; (i < nbval) && (rval == true) ; i++) {
/* parse option */
rval = parse_clopt(val[i], &opt, PRS_PMKCONF_SEP);
if (rval == true) {
pstr = po_get_str(opt.value);
if (pstr == NULL) {
errorf("unable to get value for %s.", opt.key);
return(false);
}
/* no need to strdup */
if (hash_update(ht, opt.key, pstr) == HASH_ADD_FAIL) {
errorf("%s.", PRS_ERR_HASH);
rval = false;
}
}
}
return(rval);
}
/***********
* clean() *
***********************************************************************
DESCR
clean global data
IN
pgd : global data structure
OUT
NONE
***********************************************************************/
void clean(pmkdata *pgd) {
if (pgd->htab != NULL) {
hash_destroy(pgd->htab);
}
if (pgd->labl != NULL) {
hash_destroy(pgd->labl);
}
clean_compiler_data(&(pgd->comp_data));
if (pgd->cfgt != NULL) {
cfgtdata_destroy(pgd->cfgt);
}
if (pgd->tlist != NULL) {
da_destroy(pgd->tlist);
}
if (pgd->ac_file != NULL) {
free(pgd->ac_file);
}
if (pgd->lang != NULL) {
free(pgd->lang);
}
}
/*********************
* set_switch_list() *
***********************************************************************
DESCR
set or unset a switch
IN
swlst : list of switches to process
state : switch state to set (true or false)
OUT
boolean
***********************************************************************/
bool set_switch_list(pmkdata *pgd, char *swlst, bool state, int *ovrsw) {
char *pstr,
*ststr;
dynary *da;
if (state == true) {
ststr = BOOL_STRING_TRUE;
} else {
ststr = BOOL_STRING_FALSE;
}
da = str_to_dynary(swlst, CHAR_LIST_SEPARATOR);
if (da != NULL) {
do {
pstr = da_pop(da);
if (pstr != NULL) {
if (hash_update_dup(pgd->labl, pstr, ststr) == HASH_ADD_FAIL)
return(false);
*ovrsw++; /* increment number of overriden switches */
free(pstr);
}
} while (pstr != NULL);
da_destroy(da);
}
return(true);
}
/***********
* usage() *
***********************************************************************
DESCR
usage
IN
NONE
OUT
NONE
***********************************************************************/
void usage(void) {
fprintf(stderr, "usage: pmk [-vh] [-e list] [-d list] [-b path]\n");
fprintf(stderr, "\t[-f pmkfile] [-o ovrfile] [options]\n");
}
/**********
* main() *
***********************************************************************
DESCR
main loop
***********************************************************************/
int main(int argc, char *argv[]) {
FILE *fp;
bool go_exit = false,
pmkfile_set = false,
ovrfile_set = false,
basedir_set = false,
buildlog = false;
char *pstr,
*enable_sw = NULL,
*disable_sw = NULL,
buf[MAXPATHLEN];
int rval = 0,
nbpd,
nbcd,
ovrsw = 0,
chr;
pmkdata *pgd;
prsdata *pdata;
/* get current path */
if (getcwd(buf, sizeof(buf)) == NULL) {
errorf("unable to get current directory.");
exit(EXIT_FAILURE);
}
/* initialise global data hash table */
pgd = pmkdata_init();
if (pgd == NULL) {
exit(EXIT_FAILURE);
}
while (go_exit == false) {
chr = getopt(argc, argv, "b:d:e:f:hlo:v");
if (chr == -1) {
go_exit = true;
} else {
switch (chr) {
case 'b' :
/* XXX check if path is valid */
if (uabspath(buf, optarg, pgd->basedir) == false) {
errorf("cannot use basedir argument.");
exit(EXIT_FAILURE);
}
basedir_set = true;
break;
case 'e' :
/* enable switch(es) */
enable_sw = strdup(optarg);
if (enable_sw == NULL) {
errorf(ERRMSG_MEM);
exit(EXIT_FAILURE);
}
break;
case 'd' :
/* disable switch(es) */
disable_sw = strdup(optarg);
if (disable_sw == NULL) {
errorf(ERRMSG_MEM);
exit(EXIT_FAILURE);
}
break;
case 'f' :
/* pmk file path */
/* XXX check if path in optarg is valid */
if (uabspath(buf, optarg, pgd->pmkfile) == false) {
errorf("cannot use file argument.");
exit(EXIT_FAILURE);
}
/*
path of pmkfile is also the srcdir base
NOTE : we use strdup to avoid
problem with linux's dirname
*/
pstr = strdup(pgd->pmkfile);
if (pstr == NULL) {
free(pstr);
errorf(ERRMSG_MEM);
exit(EXIT_FAILURE);
}
if (strlcpy_b(pgd->srcdir, dirname(pstr),
sizeof(pgd->srcdir)) == false) {
free(pstr);
errorf(PMK_ERR_OVRFLOW);
exit(EXIT_FAILURE);
}
free(pstr);
pmkfile_set = true;
break;
case 'l' :
/* enable log of test build */
buildlog = true;
break;
case 'o' :
/* file path to override pmk.conf */
/* XXX check if path in optarg is valid */
if (uabspath(buf, optarg, pgd->ovrfile) == false) {
errorf("cannot use file argument.");
exit(EXIT_FAILURE);
}
ovrfile_set = true;
break;
case 'v' :
/* display version */
fprintf(stdout, "%s\n", PREMAKE_VERSION);
exit(EXIT_SUCCESS);
break;
case 'h' :
case '?' :
default :
usage();
exit(EXIT_FAILURE);
break;
}
}
}
argc = argc - optind;
argv = argv + optind;
/* set basedir if needed */
if (basedir_set == false) {
if (strlcpy_b(pgd->basedir, buf,
sizeof(pgd->basedir)) == false) {
errorf("failed to set 'basedir'.");
exit(EXIT_FAILURE);
}
}
/* set pmkfile and srcdir if needed */
if (pmkfile_set == false) {
if (strlcpy_b(pgd->srcdir, buf,
sizeof(pgd->srcdir)) == false) {
errorf("failed to set 'srcdir'.");
exit(EXIT_FAILURE);
}
abspath(pgd->srcdir, PREMAKE_FILENAME, pgd->pmkfile); /* should not fail */
}
if (buildlog == true) {
/* set build log name */
if (strlcpy_b(pgd->buildlog, PMK_BUILD_LOG,
sizeof(pgd->buildlog)) == false) {
errorf(PMK_ERR_BLDLOG);
exit(EXIT_FAILURE);
}
/* remove previous build log */
unlink(pgd->buildlog);
} else {
/* redirect build output to /dev/null */
if (strlcpy_b(pgd->buildlog, "/dev/null",
sizeof(pgd->buildlog)) == false) {
errorf(PMK_ERR_BLDLOG);
exit(EXIT_FAILURE);
}
}
/* init prsdata structure */
pdata = prsdata_init();
if (pdata == NULL) {
errorf("cannot intialize prsdata.");
exit(EXIT_FAILURE);
}
fp = fopen(PREMAKE_CONFIG_PATH, "r");
if (fp != NULL) {
if (parse_pmkconf(fp, pgd->htab, PRS_PMKCONF_SEP, process_opt) == false) {
/* parsing failed */
clean(pgd);
fclose(fp);
errorf(ERRMSG_PARSE, PREMAKE_CONFIG_PATH);
exit(EXIT_FAILURE);
}
fclose(fp);
nbpd = hash_nbkey(pgd->htab);
} else {
/* configuration file not found */
clean(pgd);
errorf(ERRMSG_PARSE " Run pmksetup(8).", PREMAKE_CONFIG_PATH);
exit(EXIT_FAILURE);
}
/* initialize some variables */
if (init_var(pgd) == false) {
/* hash error on variable initialization */
clean(pgd);
errorf("failed to do variable init.", PREMAKE_CONFIG_PATH);
exit(EXIT_FAILURE);
}
if (enable_sw != NULL) {
/* command line switches to enable */
if (set_switch_list(pgd, enable_sw, true, &ovrsw) == false) {
errorf("failed to set enabled switches.");
exit(EXIT_FAILURE);
}
}
if (disable_sw != NULL) {
/* command line switches to disable */
if (set_switch_list(pgd, disable_sw, false, &ovrsw) == false) {
errorf("failed to set disabled switches.");
exit(EXIT_FAILURE);
}
}
if (ovrfile_set == true) {
/* read override file */
fp = fopen(pgd->ovrfile, "r");
if (fp != NULL) {
if (parse_pmkconf(fp, pgd->htab, PRS_PMKCONF_SEP, process_opt) == false) {
/* parsing failed */
clean(pgd);
fclose(fp);
errorf(ERRMSG_PARSE, pgd->ovrfile);
exit(EXIT_FAILURE);
}
fclose(fp);
nbpd = hash_nbkey(pgd->htab);
} else {
/* configuration file not found */
clean(pgd);
errorf("cannot parse '%s' : %s.",
pgd->ovrfile, strerror(errno));
exit(EXIT_FAILURE);
}
}
if (argc != 0) {
/* parse optional arguments that override pmk.conf and override file */
if (parse_cmdline(argv, argc, pgd) == true) {
nbcd = argc;
} else {
clean(pgd);
errorf("incorrect optional arguments.");
exit(EXIT_FAILURE);
}
} else {
nbcd = 0;
}
/* open log file */
if (pmk_log_open(PMK_LOG) == false) {
clean(pgd);
errorf("while opening '%s'.", PMK_LOG);
exit(EXIT_FAILURE);
}
pmk_log("PMK version %s", PREMAKE_VERSION);
#ifdef DEBUG
pmk_log(" [SUB #%s] [SNAP #%s]", PREMAKE_SUBVER_PMK, PREMAKE_SNAP);
#endif
pmk_log("\n\n");
pmk_log("Loaded %d predefinined variables.\n", nbpd);
pmk_log("Loaded %d overridden switches.\n", ovrsw);
pmk_log("Loaded %d overridden variables.\n", nbcd);
pmk_log("Total : %d variables.\n\n", hash_nbkey(pgd->htab));
pmk_log("Parsing '%s'\n", pgd->pmkfile);
/* open pmk file */
fp = fopen(pgd->pmkfile, "r");
if (fp == NULL) {
clean(pgd);
errorf("failed to open '%s' : %s.", pgd->pmkfile, strerror(errno));
exit(EXIT_FAILURE);
}
if (parse_pmkfile(fp, pdata, kw_pmkfile, nbkwpf) == true) {
pmk_log("\nProcessing commands :\n");
if (process_cmd(pdata, pgd) == false) {
/* an error occured while parsing */
rval = 1;
} else {
pmk_log("\nProcess templates :\n");
if (template_main(pgd) == false) {
/* an error occured while processing templates */
rval = 1;
}
pmk_log("\nEnd of log\n");
}
} else {
errorf("failed to open '%s'.", pgd->pmkfile);
rval = 1;
}
fclose(fp);
/* flush and close files */
pmk_log_close();
/* clean global data */
clean(pgd);
return(rval);
}
/* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */
syntax highlighted by Code2HTML, v. 0.9.1