pmk-0.10.4004075500017500000000000000000001077177766400112175ustar00mipswheelpmk-0.10.4/doc004075500017500000000000000000001077177765600117655ustar00mipswheelpmk-0.10.4/doc/tutorial.txt010064400017500000000000000375231011344077400144310ustar00mipswheel----------------------------------------------------------------------- Pre Make Kit tutorial file Document revision: $Id: tutorial.txt 1161 2004-08-26 20:03:08Z xsa $ ----------------------------------------------------------------------- PMK tutorial 1) Introduction ------------ As make is using a makefile, the pmk binary is using a pmkfile. This file contains a set of commands that perform checks of source dependencies. Following to that, template files are processed to generate a final file after tags substitutions. In addition to this tutorial, we highly recommend to read the pmkfile(5) manpage. 2) The settings ------------ The first command you will find in a pmkfile is named SETTINGS. Its function is to define global settings. To begin we are going to use only one template for the makefile. See the following example: SETTINGS { TARGET = ("Makefile.in") } The TARGET option is taking a list as value. The list is delimited by parenthesis. As you can see Makefile.in will be the template name. 3) Defining some variables ----------------------- It can be useful to define some basic variables such as package name and version. For this, we will use the DEFINE command as following: DEFINE { PACKAGE = "hello" VERSION = "0.1" } If the target(s) file(s) contain(s) the @PACKAGE@ and @VERSION@ tags then they will be replaced by the variables values. 4) First check ----------- Lets say that we have a hello.c file that needs the string header. For that, we use the CHECK_HEADER command like following: CHECK_HEADER(header_string) { NAME = "string.h" } The NAME option contains the header to check. The string into brackets is the label of the command. If the check succeeds, this label is set as true else it is set as false. We'll see later how to use this label state into conditional command or as dependency with the DEPEND option. Now let's see what our actual pmkfile contains. First we create the template with the following commands: echo "PACKAGE=@PACKAGE@" > Makefile.in echo "VERSION=@VERSION@" >> Makefile.in You can now type 'pmk'. The resulting output should look like this: __[OUTPUT]____________________________________________________[BEGIN]__ Processing commands : * Parsing settings Collecting targets : Added 'Makefile.in'. Total 1 target(s) added. * Parsing define defined 'PACKAGE' variable. defined 'VERSION' variable. * Checking header [header_string] Use C language with CC compiler. Store compiler flags in 'CFLAGS'. Found header 'string.h' : yes. Process templates : Created '/home/mips/tmp/Makefile'. __[OUTPUT]______________________________________________________[END]__ And the generated Makefile should look like: __[FILE]______________________________________________________[BEGIN]__ PACKAGE=hello VERSION=0.1 __[FILE]________________________________________________________[END]__ 5) Using external libraries ------------------------ Our hello program also needs the curses library. To check if this library is present we will use the following command: CHECK_LIB(lib_curses) { NAME = "curses" } Which gives as result: __[OUTPUT]____________________________________________________[BEGIN]__ * Checking library [lib_curses] Use C language with CC compiler. Store library flags in 'LIBS'. Found library 'curses' : yes. __[OUTPUT]______________________________________________________[END]__ We could also check for a specific function in the library: CHECK_LIB(lib_curses) { NAME = "curses" FUNCTION = "getwin" } So you'll get the following: __[OUTPUT]____________________________________________________[BEGIN]__ * Checking library [lib_curses] Use C language with CC compiler. Store library flags in 'LIBS'. Found function 'getwin' in 'curses' : yes. __[OUTPUT]______________________________________________________[END]__ The linker flags are automatically set in the default LIBS variable. We'll see later how to use an alternate variable. 6) Playing with pkg-config support ------------------------------- Let's say that our package has the gtkhello.c source that builds a gtk version of our hello program. That said, we need to check if gtk is present on the system. We have two possibilities to do that: first by using pkg-config or the second one by checking the library. We are going to learn how to check gtk via pkgconfig support: CHECK_PKG_CONFIG(pc_gtk) { NAME = "gtk+" } If gtk is present you should get the following output when running pmk: __[OUTPUT]____________________________________________________[BEGIN]__ * Checking pkg-config module [pc_gtk] Found package 'gtk+' : yes. Stored compiler flags in 'CFLAGS'. Stored library flags in 'LIBS'. __[OUTPUT]______________________________________________________[END]__ We could also check for a minimal version of gtk needed by the program. For example we could look for at least 1.2 version of gtk: CHECK_PKG_CONFIG(pc_gtk) { NAME = "gtk+" VERSION = "1.2" } And the related output: __[OUTPUT]____________________________________________________[BEGIN]__ * Checking pkg-config module [pc_gtk] Found package 'gtk+' : yes. Found version >= 1.2 : yes (1.2.10). Stored compiler flags in 'CFLAGS'. Stored library flags in 'LIBS'. __[OUTPUT]______________________________________________________[END]__ As you can see the compiler and linker flags are automatically stored in the default CFLAGS and LIBS variables. You can provide alternate variables with the CFLAGS and LIBS options like following: CHECK_PKG_CONFIG(pc_gtk) { NAME = "gtk+" VERSION = "1.2" CFLAGS = "GTK_CFLAGS" LIBS = "GTK_LIBS" } And you'll get: __[OUTPUT]____________________________________________________[BEGIN]__ * Checking pkg-config module [pc_gtk] Found package 'gtk+' : yes. Found version >= 1.2 : yes (1.2.10). Stored compiler flags in 'GTK_CFLAGS'. Stored library flags in 'GTK_LIBS'. __[OUTPUT]______________________________________________________[END]__ Notice that the storage variables have changed in the output. 7) Using switches -------------- Now we are able to detect gtk we could use a switch to specify if we want the gtk version or not. For this we will use the SWITCHES command and add it between SETTINGS AND DEFINE: SWITCHES { build_gtk_version = FALSE } By default we don't want the gtk version to be build so it's set to FALSE. A switch can be modified by using -e (enable) and -d (disable) options, see pmk(1). For example we could use the following to enable the build of the gtk program: pmk -e build_gtk_version We are going to see the two methods of using switchs. First using the DEPEND option: CHECK_PKG_CONFIG(pc_gtk) { NAME = "gtk+" DEPEND = ("build_gtk_version") VERSION = "1.2" CFLAGS = "GTK_CFLAGS" LIBS = "GTK_LIBS" } As you can see we added 'build_gtk_version' in the dependency list of the DEPEND option. A dependency can be a command label or a switch. If all the dependencies in the list are true then the command is executed. Else if the test is required pmk fill fail like this: __[OUTPUT]____________________________________________________[BEGIN]__ * Checking pkg-config module [pc_gtk] Required 'build_gtk_version' dependency failed. __[OUTPUT]______________________________________________________[END]__ Another method to use switches is the IF conditional command. This will look like the following: IF(build_gtk_version) { CHECK_PKG_CONFIG(pc_gtk) { NAME = "gtk+" VERSION = "1.2" CFLAGS = "GTK_CFLAGS" LIBS = "GTK_LIBS" } } Of course you can put as many commands as you want into the body. The ouput looks like the following: __[OUTPUT]____________________________________________________[BEGIN]__ < Begin of condition [build_gtk_version] * Checking pkg-config module [pc_gtk] Found package 'gtk+' : yes. Found version >= 1.2 : yes (1.2.10). Stored compiler flags in 'GTK_CFLAGS'. Stored library flags in 'GTK_LIBS'. > End of condition [build_gtk_version] __[OUTPUT]______________________________________________________[END]__ It's also possible to negate a value by appending a '!' above the dependency like this: IF(!build_gtk_version) { [commands] } or like this: DEPEND = ("!build_gtk_version") 8) Checking types -------------- As an example we will check for the ISO C99 boolean type: _Bool. See the following: CHECK_TYPE(type_bool_isoc) { NAME = "_Bool" } As my compiler is not fully ISO C99 compliant i get an error: __[OUTPUT]____________________________________________________[BEGIN]__ * Checking type [type_bool_isoc] Use C language with CC compiler. Found type '_Bool' : no. Error : failed to find type '_Bool'. __[OUTPUT]______________________________________________________[END]__ This test could be useful to detect compilers that are ISO C99 compliant. For those which are not we could include an external definition of this type. That said, pmk is exiting with an error by default if a check fails. To avoid this we'll use the REQUIRED option: CHECK_TYPE(type_bool_isoc) { REQUIRED = FALSE NAME = "_Bool" } And it gives the following: __[OUTPUT]____________________________________________________[BEGIN]__ * Checking type [type_bool_isoc] Use C language with CC compiler. Found type '_Bool' : no. __[OUTPUT]______________________________________________________[END]__ Now let's see how to use this test. First we must create an header that will contains the tags. Here is isoc_compat.h.in: __[FILE]______________________________________________________[BEGIN]__ /* ISO C compatibility header */ /* _Bool type */ @DEF___BOOL@ __[FILE]________________________________________________________[END]__ Now add this file in the target list: SETTINGS { TARGET = ("Makefile.in","isoc_compat.h.in") } The definition tag is easy to build, it's "DEF__" followed by the string of the type in uppercase: _Bool gives _BOOL. Now see the result: __[OUTPUT]____________________________________________________[BEGIN]__ * Checking type [type_bool_isoc] Use C language with CC compiler. Found type '_Bool' : no. Process templates : Created '/home/mips/tmp/pmk_tutor/Makefile'. Created '/home/mips/tmp/pmk_tutor/isoc_compat.h'. End of log __[OUTPUT]______________________________________________________[END]__ And the isoc_compat.h file: __[FILE]______________________________________________________[BEGIN]__ /* ISO C compatibility header */ /* _Bool type */ #undef HAVE__BOOL __[FILE]________________________________________________________[END]__ The @DEF___BOOL@ has been replaced by "#undef HAVE__BOOL". Now we can add the code to include the definition of _Bool type if it does not exist. __[FILE]______________________________________________________[BEGIN]__ /* ISO C compatibility header */ /* _Bool type */ @DEF___BOOL@ #ifndef HAVE__BOOL typedef unsigned char _Bool; #endif __[FILE]________________________________________________________[END]__ Which results in the following on my system: __[FILE]______________________________________________________[BEGIN]__ /* ISO C compatibility header */ /* _Bool type */ #undef HAVE__BOOL #ifndef HAVE__BOOL typedef unsigned char _Bool; #endif __[FILE]________________________________________________________[END]__ Mission succeeded ! 9) Looking for a binary ? ---------------------- Easy ! Need to know if strip program is available ? Use the following: CHECK_BINARY(bin_strip) { NAME = "strip" VARIABLE = "STRIP_PATH" } and add the tag in the Makefile.in template: __[FILE]______________________________________________________[BEGIN]__ PACKAGE=@PACKAGE@ VERSION=@VERSION@ STRIP_PATH=@STRIP_PATH@ __[FILE]________________________________________________________[END]__ Now run pmk: __[OUTPUT]____________________________________________________[BEGIN]__ * Checking binary [bin_strip] Found binary 'strip' : yes. __[OUTPUT]______________________________________________________[END]__ And look at Makefile: __[FILE]______________________________________________________[BEGIN]__ PACKAGE=hello VERSION=0.1 STRIP_PATH=/usr/bin/strip __[FILE]________________________________________________________[END]__ Well we got it :) 10) Checking a variable ------------------- As an example we'll take the case of a program that will run only on 'little endian' byte ordered CPUs. For that matter we'll check the HW_BYTEORDER variable set by pmksetup: CHECK_VARIABLE(var_endian) { NAME = "HW_BYTEORDER" VALUE = "LITTLE_ENDIAN" } On big-endian machines the check will fail with an error: __[OUTPUT]____________________________________________________[BEGIN]__ * Checking variable [var_endian] Found variable 'HW_BYTEORDER' : yes. Variable match value 'LITTLE_ENDIAN' : no. Error : variable value does not match ('LITTLE_ENDIAN' != 'BIG_ENDIAN'). __[OUTPUT]______________________________________________________[END]__ 11) Shared library support ---------------------- The first step is to detect the compiler used. We do that with the DETECT option of the SETTINGS command: SETTINGS { TARGET = ("Makefile.in","isoc_compat.h.in") DETECT = ("CC") } In this example we detect the C compiler but we could have detected the C++ compiler by using DETECT=("CXX"). You can also detect both compilers with DETECT=("CC","CXX"). The output should look almost like the following: __[OUTPUT]____________________________________________________[BEGIN]__ * Parsing settings Collecting targets : Added 'Makefile.in'. Added 'isoc_compat.h.in'. Total 2 target(s) added. Detecting compilers : Gathering data for compiler detection. Detecting 'CC' : GNU gcc (version 295). Setting SLCFLAGS to '-fPIC' Setting SLLDFLAGS to '-shared' __[OUTPUT]______________________________________________________[END]__ In this example the compiler used is gcc (version 2.95). As you can see the shared library flags (-fpic and -shared) are set in the reserved variables. Now we're going to see how to build the name of the shared library using the BUILD_SHLIB_NAME command: BUILD_SHLIB_NAME { NAME = "hello" MAJOR = "2" MINOR = "1" VERSION_NONE = "LIBNAME" VERSION_MAJ = "LIBNAME_MAJ" VERSION_FULL = "LIBNAME_FULL" } This will give the following output: __[OUTPUT]____________________________________________________[BEGIN]__ * Building shared library name Shared library support : yes. Setting LIBNAME to 'libhello.so' Setting LIBNAME_FULL to 'libhello.so.2.1' Setting LIBNAME_MAJ to 'libhello.so.2' __[OUTPUT]______________________________________________________[END]__ To use all this stuff we could use a template of makefile like following: __[FILE]______________________________________________________[BEGIN]__ PACKAGE=@PACKAGE@ VERSION=@VERSION@ STRIP_PATH=@STRIP_PATH@ CFLAGS=@CFLAGS@ LIBS=@LIBS@ SLCFLAGS=@SLCFLAGS@ SLLDFLAGS=@SLLDFLAGS@ LIBNAME=@LIBNAME@ LIBNAME_MAJ=@LIBNAME_MAJ@ LIBNAME_FULL=@LIBNAME_FULL@ libhello.o: $(CC) $(CFLAGS) $(SLCFLAGS) -c libhello.c $(LIBNAME): libhello.o $(CC) $(SLLDFLAGS) -o $@ libhello.o cp $(LIBNAME) $(LIBNAME_MAJ) cp $(LIBNAME) $(LIBNAME_FULL) __[FILE]________________________________________________________[END]__ And after running pmk we should obtain a makefile like this one: __[FILE]______________________________________________________[BEGIN]__ PACKAGE=hello VERSION=0.1 STRIP_PATH=/usr/bin/strip CFLAGS=-O2 -I/usr/include LIBS=-lcurses SLCFLAGS=-fPIC SLLDFLAGS=-shared LIBNAME=libhello.so LIBNAME_MAJ=libhello.so.2 LIBNAME_FULL=libhello.so.2.1 libhello.o: $(CC) $(CFLAGS) $(SLCFLAGS) -c libhello.c $(LIBNAME): libhello.o $(CC) $(SLLDFLAGS) -o $@ libhello.o cp $(LIBNAME) $(LIBNAME_MAJ) cp $(LIBNAME) $(LIBNAME_FULL) __[FILE]________________________________________________________[END]__ TO BE CONTINUED ... pmk-0.10.4/doc/sl_specs.txt010064400017500000000000000027601001271233600143660ustar00mipswheel----------------------------------------------------------------------- Pre Make Kit shared library support specifications file Document revision: $Id: sl_specs.txt 997 2004-02-12 14:59:42Z mipsator $ ----------------------------------------------------------------------- pmkcomp data: ADD_SYSTEM { NAME = "MySystem" SL_EXT = "shared library extension" SL_VERSION = "$SL_MAJOR.$SL_MINOR" SL_LIBNAME = "lib$SL_NAME$SL_EXT" SL_LIBNAME_VMAJ = "$SL_LIBNAME.$SL_MAJOR" SL_LIBNAME_VFULL = "$SL_LIBNAME.$SL_VERSION" } pmkfile command: BUILD_SHLIB_NAME(?) { NAME = "library name" MAJOR = "major version" MINOR = "minor version" VERSION_NONE = "storage variable" } example: (pmkcomp.dat) ADD_SYSTEM { NAME = "Darwin" SL_EXT = ".dylib" SL_VERSION = "$SL_MAJOR.$SL_MINOR" SL_LIBNAME = "lib$SL_NAME$SL_EXT" SL_LIBNAME_VMAJ = "lib$SL_NAME.$SL_MAJOR$SL_EXT" SL_LIBNAME_VFULL = "lib$SL_NAME.$SL_VERSION$SL_EXT" SLLDFLAGS_gcc = "-dynamiclib" } ADD_SYSTEM { NAME = "OpenBSD" SL_EXT = ".so" SL_VERSION = "$SL_MAJOR.$SL_MINOR" SL_LIBNAME = "lib$SL_NAME$SL_EXT" SL_LIBNAME_VMAJ = "$SL_LIBNAME.$SL_MAJOR" SL_LIBNAME_VFULL = "$SL_LIBNAME.$SL_VERSION" } (pmkfile) DEFINE { LIBPMK_NAME = "pmk" LIBPMK_MAJ = "1" LIBPMK_MIN = "2" } [...] BUILD_SHLIB_NAME(?) { NAME = "$LIBPMK_NAME" MAJOR = "$LIBPMK_MAJ" MINOR = "$LIBPMK_MIN" VERSION_NONE = "LIBNAME" VERSION_FULL = "LIBNAMEV" } (makefile template) LIBNAME= @LIBNAME@ LIBNAMEV= @LIBNAMEV@ (created makefile) LIBNAME= libpmk.so LIBNAMEV= libpmk.so.1.2 pmk-0.10.4/doc/style.txt010064400017500000000000000046641024136140200137160ustar00mipswheel----------------------------------------------------------------------- Pre Make Kit coding style file Document revision: # $Id: style.txt 1410 2005-05-14 11:37:38Z mipsator $ ----------------------------------------------------------------------- RECOMMENDED CODING STYLE FOR PMK -------------------------------- 1) Comments Comments in the code are GREATLY appreciated. /* simple in-code comment */ /* Recommended multiline comment. Other formats are allowed. */ The following is our "standard" fonction header that every new function should have : /******************* * function_name() * *********************************************************************** DESCR The description of the function processus IN arg1 : brief description of the named argument arg2 : same as above ... OUT description of what is returned ***********************************************************************/ 2) Includes #include #include "local_after.h" Each group of include can be sorted in alphabetical order. 3) Prototypes Use of tab indenting is recommended. Extra space to line up functions could be nice. void first_proc(void *); char *second_proc(char, int); int third_proc(char *); 4) Structures It uses the same specs as above, see the following example: struct mystruct { char *first_field; int second_field; double third_field; }; 5) Variables Always the same format: FILE *first_var; int second_var; char third_var[NB_CHAR], *fourth_var; Variables could be sorted by type in alphabetical order. You can also group them by letter case with uppercase first. 6) Keywords Keywords should be followed by a space instead of functions. 7) Functions Function must be declared on one line with type, function name, arguments and open brace as the following : int first_proc(char *arg_one, int arg_two) { Variables declared in functions respect the same rules defined in the fifth section. 8) Error messages When using the errorf() function, the format should look like the following: errorf("error message starting with a lowercase."); or errorf("error message %s : %s.", var, strerror(errno)); You should always use strerror(errno) when possible. Note that error messages always end with a dot (.) and start with a lowercase. 9) Exit statements - exit(EXIT_FAILURE) and exit(EXIT_SUCCESS) should be used respectively instead of exit(1) and exit(0). pmk-0.10.4/functool.c010064400017500000000000000365611051201023000132350ustar00mipswheel/* $Id: functool.c 1904 2006-10-07 20:39:52Z 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. * */ #include #include #include #include #include #include "compat/pmk_ctype.h" #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "compat/pmk_unistd.h" #include "common.h" #include "dynarray.h" #include "functool.h" #include "premake.h" #include "tags.h" /*#define FC_DEBUG 1*/ /******************** * check_bool_str() * *********************************************************************** DESCR check boolean string IN str : string to check OUT boolean NOTE strncmp checks only on a length of 6 because lenght of "true" is 5 and "false" is 6 chr. If str is longer we don't need to check as we are sure that the result is false. ***********************************************************************/ bool check_bool_str(char *str) { if (strncmp(str, BOOL_STRING_TRUE, 6) == 0) { return(true); } else { return(false); } } /***************** * invert_bool() * *********************************************************************** DESCR invert bool value IN value : input boolean value OUT negation of value ***********************************************************************/ bool invert_bool(bool value) { if (value == true) { return(false); } else { return(true); } } /***************** * bool_to_str() * *********************************************************************** DESCR convert boolean into string IN value : boolean value to convert to string OUT returns the string ***********************************************************************/ char *bool_to_str(bool value) { static char bstr[6]; if (value == true) { snprintf(bstr, sizeof(bstr), BOOL_STRING_TRUE); /* no check */ } else { snprintf(bstr, sizeof(bstr), BOOL_STRING_FALSE); /* no check */ } return(bstr); } /*********************** * get_file_dir_path() * *********************************************************************** DESCR get directory of given filename in given path list IN filename : name of the file to look for path : string of the list of path storage : storage for resulting directory size : size of storage OUT returns true if filename is found in one of the list's path ***********************************************************************/ bool get_file_dir_path(char *filename, char *path, char *storage, int size) { bool rval = false; dynary *bplst; /* fill dynary with path */ bplst= str_to_dynary(path, PATH_STR_DELIMITER); if (bplst == NULL) { errorf("failed to put a path into a dynamic array."); return(false); } /* try to locate cfgtool */ if (find_file_dir(bplst, filename, storage, size) == true) { rval = true; } else { rval = false; } da_destroy(bplst); return(rval); } /****************** * find_pattern() * *********************************************************************** DESCR find a file pattern in the given list of path IN da : dynary that contains list of path pattern : pattern to find pbuf : buffer to store directory if matching bsize : buffer size OUT returns true if pattern is found in one of the list of path ***********************************************************************/ bool find_pattern(dynary *da, char *pattern, char *pbuf, int bsize) { struct dirent *de; DIR *dp; bool found; char *path; size_t i, rsize; found = false; rsize = sizeof(de->d_name); for (i = 0 ; (i < da_usize(da)) && (found == false) ; i++) { path = da_idx(da, i); dp = opendir(path); if (dp == NULL) { /* can't open directory */ continue; } while ((de = readdir(dp)) != NULL) { /* check with pattern */ if (fnmatch(pattern, de->d_name, 0) == 0) { /* file match with pattern */ if (strlcpy_b(pbuf, path, bsize) == true) { /* pbuf set */ found = true; } break; } } closedir(dp); } return(found); } /**************** * record_def() * *********************************************************************** DESCR record data definition tag (DEF__*) IN ht : hash table to store the definition name : data name status : status of data OUT boolean ***********************************************************************/ bool record_def(htable *ht, char *name, bool status) { char *def_str, *have_str, def_val[MAX_HASH_VALUE_LEN]; def_str = gen_basic_tag_def(name); have_str = gen_ac_tag_name(name); if (status == true) { if (snprintf_b(def_val, sizeof(def_val), "#define %s 1", have_str) == false) return(false); } else { if (snprintf_b(def_val, sizeof(def_val), "#undef %s", have_str) == false) return(false); } #ifdef FC_DEBUG debugf("record_def() : def_val = '%s'", def_val); #endif /* pmk style define ID (DEF__*) */ if (hash_update_dup(ht, def_str, def_val) == HASH_ADD_FAIL) return(false); #ifdef FC_DEBUG debugf("record_def() : recorded '%s' with '%s'", def_str, def_val); #endif return(true); } /********************* * record_def_data() * *********************************************************************** DESCR record definition data (DEF__* and HAVE_*) IN ht : hash table to store the definition name : tag name value : tag value OUT boolean ***********************************************************************/ bool record_def_data(htable *ht, char *name, char *value) { char *def_str, *have_str, def_val[MAX_HASH_VALUE_LEN]; def_str = gen_basic_tag_def(name); have_str = gen_ac_tag_name(name); if (value != NULL) { /* common variable tag HAVE_* */ if (hash_update_dup(ht, have_str, value) == HASH_ADD_FAIL) return(false); #ifdef FC_DEBUG debugf("record_def_data() : recorded '%s' with '%s'", have_str, value); #endif if (snprintf_b(def_val, sizeof(def_val), "#define %s %s", have_str, value) == false) return(false); } else { if (snprintf_b(def_val, sizeof(def_val), "#undef %s", have_str) == false) return(false); } #ifdef FC_DEBUG debugf("record_def_data() : def_val = '%s'", def_val); #endif /* pmk style define ID (DEF__*) */ if (hash_update_dup(ht, def_str, def_val) == HASH_ADD_FAIL) return(false); #ifdef FC_DEBUG debugf("record_def_data() : recorded '%s' with '%s'", def_str, def_val); #endif return(true); } /******************** * record_def_adv() * *********************************************************************** DESCR XXX IN XXX OUT boolean ***********************************************************************/ bool record_def_adv(htable *ht, int type, char *ctn, char *ctt, char *msc, char *val) { char *tag_def, *tag_name, buf[MAX_HASH_VALUE_LEN]; tag_def = gen_tag_def(type, ctn, ctt, msc); tag_name = gen_tag_name(type, ctn, ctt, msc); if (val == NULL) { /* if value is NULL then undefine tag */ if (snprintf_b(buf, sizeof(buf), "#undef %s", tag_name) == false) { return(false); } } else { /* else value is not NULL so define tag with value */ if (snprintf_b(buf, sizeof(buf), "#define %s %s", tag_name, val) == false) { return(false); } /* record tag */ if (hash_update_dup(ht, tag_name, val) == HASH_ADD_FAIL) { return(false); } } /* record tag define */ if (hash_update_dup(ht, tag_def, buf) == HASH_ADD_FAIL) { return(false); } return(true); } /********************** * process_def_list() * *********************************************************************** DESCR process list of defines IN ht : storage hash table da : list of defines OUT boolean ***********************************************************************/ bool process_def_list(htable *ht, dynary *da, bool define) { char *name, *value; int i, n; if (define == true) { value = "1"; } else { value = NULL; } /* process additional defines */ if (da != NULL) { n = da_usize(da); for (i = 0 ; i < n ; i++) { name = da_idx(da, i); pmk_log("\tProcessing additional define '%s': ", name); if (record_def_data(ht, name, value) == false) { return(false); } pmk_log("ok.\n"); } } return(true); } /*************** * label_set() * *********************************************************************** DESCR set label IN ht : label hash table name : label name status : label status OUT boolean ***********************************************************************/ bool label_set(htable *lht, char *name, bool status) { if (hash_update_dup(lht, name, bool_to_str(status)) == HASH_ADD_FAIL) return(false); return(true); } /***************** * label_check() * *********************************************************************** DESCR check label IN ht : label hash table name : label name OUT boolean ***********************************************************************/ bool label_check(htable *lht, char *name) { bool neg = false, rval; char *p; if (*name == '!') { name++; neg = true; } p = (char *)hash_get(lht, name); if (p == NULL) return(false); rval = check_bool_str(p); if (neg == true) { rval = invert_bool(rval); } return(rval); } /****************** * depend_check() * *********************************************************************** DESCR check dependencies IN ht : label hash table deplst : string that contain the list of label dependencies OUT boolean ***********************************************************************/ bool depend_check(htable *lht, pmkdata *gd) { bool rval = true; char *fdep; dynary *da; pmkobj *po; unsigned int i; po = hash_get(lht, KW_OPT_DEPEND); if (po == NULL) { /* no dependencies, check is true */ return(true); } da = po_get_list(po); if (da == NULL) { /* DEPEND is not a list */ strlcpy(gd->errmsg, "Syntax error in DEPEND !", sizeof(gd->errmsg)); /* no check */ return(false); } /* check labels one by one */ for (i = 0 ; (i < da_usize(da)) && (rval == true) ; i++) { fdep = da_idx(da, i); if (label_check(gd->labl, fdep) == false) { rval = false; snprintf(gd->errmsg, sizeof(gd->errmsg), "Required '%s' dependency failed.", fdep); /* no check */ } } hash_delete(lht, KW_OPT_DEPEND); /* not really useful but save memory */ return(rval); } /******************* * require_check() * *********************************************************************** DESCR check the required flag IN ht : hash table of the command options OUT returns a boolean ***********************************************************************/ bool require_check(htable *pht) { pmkobj *req; req = hash_get(pht, KW_OPT_REQUIRED); if (req == NULL) { /* by default REQUIRED is true if not specified */ return(true); } if (po_get_type(req) != PO_BOOL) { return(false); } return(po_get_bool(req)); } /****************** * get_lang_str() * *********************************************************************** DESCR provide data on language used IN pht : hash table that should contain LANG pgd : global data structure OUT language string or NULL if language cannot be determined ***********************************************************************/ char *get_lang_str(htable *pht, pmkdata *pgd) { char *lang; /* check first if language has been provided locally */ lang = (char *)po_get_data(hash_get(pht, KW_OPT_LANG)); if (lang == NULL) { /* get global lang (could be NULL */ lang = pgd->lang; } return(lang); } /********************* * check_cfgt_data() * *********************************************************************** DESCR check if config tool data is loaded and try to load it if not done IN pgd : global data structure OUT boolean ***********************************************************************/ bool check_cfgt_data(pmkdata *pgd) { if (pgd->cfgt == NULL) { pgd->cfgt = parse_cfgt_file(); if (pgd->cfgt == NULL) { return(false); } } return(true); } /********************** * process_required() * *********************************************************************** DESCR process the required flag on failure IN pgd : global data structure pcmd : command data structure required : required flag key : optional define to record (not processed if NULL) value : optional value to record (see key) OUT boolean ***********************************************************************/ bool process_required(pmkdata *pgd, pmkcmd *pcmd, bool required, char *key, char *value) { if (key != NULL) { /* record definition */ record_def_data(pgd->htab, key, value); } /* set label value */ label_set(pgd->labl, pcmd->label, false); /* if required is false then we can continue (true) else stop (false) */ return(invert_bool(required)); } /***************************** * obsolete_string_to_list() * *********************************************************************** DESCR check if an option has an obsolete type of PO_STRING and replace it by PO_LIST type data. Display a warning if data has obosolete type. IN ht : options hash table opt : option name OUT NONE NOTE : OBSOLETE, to remove later when useless ***********************************************************************/ bool obsolete_string_to_list(htable *ht, char *opt) { char *pstr; dynary *da; pmkobj *po; /*debugf("opt = '%s'", opt);*/ po = hash_get(ht, opt); if (po == NULL) { return(false); } if (po_get_type(po) == PO_STRING) { /* pstr should not be NULL */ pstr = po_get_str(po); pmk_log("\tWARNING: providing a quoted string to the option '%s' is obsolete.\n", opt); pmk_log("\t\tCompatibility will be removed in future releases.\n"); da = da_init(); if (da == NULL) { errorf("unable to initialise dynary."); return(false); } if (da_push(da, strdup(pstr)) == false) { errorf("unable to add '%s' in function list.", pstr); return(false); } po = po_mk_list(da); hash_update(ht, opt, po); } return(true); } /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/hash.h010064400017500000000000000103351040066543300123440ustar00mipswheel/* $Id: hash.h 1541 2006-02-27 21:11:55Z mipsator $ */ /* * 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. * */ /************* * constants * ***********************************************************************/ #ifndef _PMK_HASH_H_ #define _PMK_HASH_H_ #include "compat/pmk_stdbool.h" #ifndef MAX_HASH_KEY_LEN # define MAX_HASH_KEY_LEN 256 #endif #ifndef MAX_HASH_VALUE_LEN # define MAX_HASH_VALUE_LEN 512 #endif #define HASH_ADD_FAIL 0 /* addition or appending failed */ #define HASH_ADD_OKAY 1 /* first add */ #define HASH_ADD_COLL 2 /* collision, key chained */ #define HASH_ADD_UPDT 3 /* key already exists, change value */ #define HASH_ADD_APPD 4 /* value appended */ /* error messages */ #define HASH_ERR_UPDT "Hash table update failed." #define HASH_ERR_UPDT_ARG "Failed to update hash table key '%s'." /********************************** * type and structure definitions * ***********************************************************************/ typedef struct s_hcell { char key[MAX_HASH_KEY_LEN]; void *value; struct s_hcell *next; } hcell; typedef struct { hcell *first, *last; } hnode; typedef struct { bool autogrow; size_t count, size; void *(*dupobj)(void *), (*freeobj)(void *), *(*appdobj)(void *, void *, void *); hnode *nodetab; /* array of hnode */ } htable; typedef struct { char key[MAX_HASH_KEY_LEN]; void *value; } hpair; typedef struct { size_t nkey; char **keys; } hkeys; /*********************** * function prototypes * ***********************************************************************/ unsigned int hash_compute(char *, size_t); htable *hash_init(size_t); htable *hash_init_adv(size_t, void *(*)(void *), void (*)(void *), void *(*)(void *, void *, void *)); bool hash_resize(htable *, size_t); void hash_set_grow(htable *); size_t hash_destroy(htable *); unsigned int hash_add(htable *, char *, void *); unsigned int hash_update(htable *, char *, void *); unsigned int hash_update_dup(htable *, char *, void *); unsigned int hash_add_cell(hnode *, hcell *); bool hash_add_array(htable *, hpair *, size_t); bool hash_add_array_adv(htable *, hpair *, size_t, void *(*)(void *)); unsigned int hash_append(htable *, char *, void *, void *); void hash_delete(htable *, char *); void *hash_extract(htable *, char *); void *hash_get(htable *, char *); size_t hash_merge(htable *, htable *); size_t hash_nbkey(htable *); hkeys *hash_keys(htable *); hkeys *hash_keys_sorted(htable *); void hash_free_hcell(htable *, hcell *); void hash_free_hkeys(hkeys *); void *hash_str_append(void *, void *, void *); #endif /* _PMK_HASH_H_ */ /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/pmkcfg.sh010075500017500000000000000273471062626154600131000ustar00mipswheel#!/bin/sh # $Id: pmkcfg.sh 1994 2007-05-27 10:54:30Z coudercd $ # Copyright (c) 2003-2004 Damien Couderc # Copyright (c) 2004 Martin Reindl # 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. # # automatically detect and use posix shell # if test "$1" != "autodetected"; then printf "Autodetecting POSIX shell\n" posix_sh="/usr/bin/posix/sh" if test ! -x $posix_sh; then posix_sh="/usr/xpg4/bin/sh" if test ! -x "$posix_sh"; then posix_sh="/bin/sh" fi fi printf "Using %s %s %s\n\n" "$posix_sh" "$0" "$*" $posix_sh $0 "autodetected" "$@" exit $? else # skip "autodetected" shift fi ########### # defines # ######################################################################## usermode=0 privsep_user="nobody" if [ -z "$PREFIX" ]; then prefix="/usr/local" else prefix=$PREFIX fi if [ -z "$SYSCONFDIR" ]; then sysdir="/etc" else sysdir=$SYSCONFDIR fi sconf="$sysdir/pmk" um_prfx='$(HOME)' testbin="./cfgtest" testfile="$testbin.c" testmake="./maketest.mk" testmkvar="./test_mkvar" testobj="$testbin.o" temporary="./pmkcfg.tmp" tmpl_list="Makefile.pmk compat/config.h.pmk tests/Makefile.pmk" ############# # functions # ######################################################################## # display usage usage() { echo "\ usage: $0 [-hup] -h usage -p path prefix override -u set usermode -U privilege separation user (default: nobody) " } # remove template suffix # result in filename variable get_file_name() { basedir=`dirname $1` case $1 in *.in) sfx=".in";; *.pmk) sfx=".pmk";; esac basename=`basename $1 $sfx` filename="$basedir/$basename" } # create new files from templates process_tmpl_list () { newlist="" for f in $*; do get_file_name $f newlist="$newlist $filename" cp $f $filename done } get_make_var() { mkvar="$1" printf "Getting '%s' value : " "$mkvar" cat > $testmake << EOF all: @printf "%s\n" "\$($mkvar)" > $testmkvar EOF make -f $testmake >/dev/null 2>&1 rslt=`cat $testmkvar` rm $testmake $testmkvar printf "'%s'\n" "$rslt" # mkf_sed "$mkvar" "$rslt" make_var_value=$rslt } check_binary() { binary="$1" tname=`echo "$binary" | tr [a-z] [A-Z] | tr . _` tval="" printf "Checking binary '%s' : " "$binary" plst=`echo $PATH | sed "s/:/ /g"` r=1 for d in $plst; do if test -x "$d/$binary"; then tval="$d/$binary" r=0 break fi done if test "$r" -eq 0; then printf "yes\n" mkf_sed "$tname" "$tval" else printf "no\n" fi return $r } check_header() { header="$1" printf "Checking header '%s' : " "$header" cat > $testfile < #include <$header> int main() { return(0); } EOF if $CC -o $testbin $testfile >/dev/null 2>&1; then sed_define "def" "$header" printf "yes\n" r=0 else sed_define "udef" "$header" printf "no\n" r=1 fi rm -f $testfile $testbin return $r } check_header_function() { include="$1" function="$2" printf "Checking function '%s' in header '%s' : " "$function" "$include" cat > $testfile < #include <$include> void (*pmk_funcp)() = $function; int main() { return(0); } EOF if $CC -o $testobj -c $testfile >/dev/null 2>&1; then sed_define "def" "$function" printf "yes\n" r=0 else sed_define "udef" "$function" printf "no\n" r=1 fi rm -f $testfile $testobj return $r } check_lib_function() { lib="$1" function="$2" printf "Checking function '%s' in library 'l%s' : " "$function" "$lib" cat > $testfile < int $function(); int main() { printf("%p", $function); return(0); } EOF if $CC -o $testobj $testfile -l$lib >/dev/null 2>&1; then sed_define "def" "$function" printf "yes\n" r=0 else sed_define "udef" "$function" printf "no\n" r=1 fi rm -f $testfile $testobj return $r } check_type() { type="$1" printf "Checking type '%s' : " "$type" cat > $testfile < int main() { if (($type *) 0) return(0); if (sizeof($type)) return(0); return(0); } EOF if $CC -o $testbin $testfile >/dev/null 2>&1; then sed_define "def" "$type" printf "yes\n" r=0 else sed_define "udef" "$type" printf "no\n" r=1 fi rm -f $testfile $testbin return $r } check_type_header() { type="$1" header="$2" printf "Checking type '%s' in header '%s' : " "$type" "$header" cat > $testfile < #include <$header> int main() { if (($type *) 0) return(0); if (sizeof($type)) return(0); return(0); } EOF if $CC -o $testbin $testfile >/dev/null 2>&1; then sed_define "def" "$type" printf "yes\n" r=0 else sed_define "udef" "$type" printf "no\n" r=1 fi rm -f $testfile $testbin return $r } sed_define() { sed_uc=`echo "$2" | tr [a-z] [A-Z] | tr . _ | tr " " _` case $1 in def) sed_str="#define HAVE_$sed_uc 1";; udef) sed_str="#undef HAVE_$sed_uc";; esac sed_tag="@DEF__$sed_uc@" for f in $file_list; do cp $f $temporary cat $temporary | sed "s/$sed_tag/$sed_str/" > $f rm -f $temporary done } mkf_sed() { sed_var="$1" sed_val="$2" #printf "DEBUG: replace @%s@ by %s\n" "$sed_var" "$sed_val" for f in $file_list; do cp $f $temporary cat $temporary | sed "s,@$sed_var@,$sed_val," > $f rm -f $temporary done } ######## # init # ######################################################################## # parse options while getopts "hp:uU:" arg; do case $arg in h) usage exit 1 ;; p) printf "Setting prefix to '%s'\n" "$OPTARG" base="$OPTARG" ;; u) usermode=1 ;; U) printf "Setting privsep user tp '%s'\n" "$OPTARG" privsep_user="$OPTARG" ;; esac done shift `expr $OPTIND - 1` # init templates process_tmpl_list "$tmpl_list" file_list=$newlist if [ $usermode = 1 ]; then echo 'USERMODE ON.' mkf_sed 'USERMODE' '-DPMK_USERMODE' if [ -z "$base" ]; then mkf_sed 'PREFIX' "$um_prfx" else mkf_sed 'PREFIX' "$base" fi mkf_sed 'CONFDIR' '$(HOME)/.pmk' mkf_sed 'SBINDIR' '$(PREFIX)/bin' mkf_sed 'DATADIR' '$(CONFDIR)' else echo "USERMODE OFF." mkf_sed 'USERMODE' '' if [ -z "$base" ]; then mkf_sed 'PREFIX' "$prefix" else mkf_sed 'PREFIX' "$base" fi mkf_sed 'CONFDIR' '$(SYSCONFDIR)/pmk' mkf_sed 'SBINDIR' '$(PREFIX)/sbin' mkf_sed 'DATADIR' '$(PREFIX)/share/$(PREMAKE)' fi mkf_sed 'BINDIR' '$(PREFIX)/bin' mkf_sed 'MANDIR' '$(PREFIX)/man' mkf_sed 'MAN1DIR' '$(MANDIR)/man1' mkf_sed 'MAN5DIR' '$(MANDIR)/man5' mkf_sed 'MAN8DIR' '$(MANDIR)/man8' mkf_sed 'SYSCONFDIR' "$sysdir" mkf_sed 'PRIVSEP_USER' "$privsep_user" mkf_sed 'PACKAGE' "pmk" mkf_sed 'VERSION' "0.9.3" mkf_sed 'INSTALL' './pmkinstall' ############# # get flags # ######################################################################## # # gathering CFLAGS # if [ -z "$CFLAGS" ]; then get_make_var CFLAGS CFLAGS=$make_var_value else printf "CFLAGS defined, skipping detection.\n" fi # # gathering CLDFLAGS # if [ -z "$CLDFLAGS" ]; then get_make_var CLDFLAGS CLDFLAGS=$make_var_value else printf "CLDFLAGS defined, skipping detection.\n" fi ################## # check binaries # ######################################################################## # # cc check # if [ -z "$CC" ]; then # check first for C99 then C89 compilers if check_binary cc; then CC="cc" elif check_binary c99; then CC="c99" elif check_binary c89; then CC="c89" else printf "Unable to find C compiler.\n" exit 1 fi else printf "CC defined, skipping C compiler check.\n" fi mkf_sed 'CC' "$CC" # # cpp check # # 'cc -E' is the C99 standard for preprocessing C-language source files. # See: http://www.opengroup.org/onlinepubs/009695399/utilities/c99.html # # However, the results are unspecified for assembler source files. # Gcc has its own conventions for preprocessing assembler files, only the cpp # binary preprocesses assembler files at any time. In gcc, 'cc -E' only # processes assembler files which end in '.S'. To work around we first look # for the cpp binary and fall back to 'cc -E' if not successful. if [ -z "$CPP" ]; then if check_binary cpp; then CPP="cpp" else printf "Using '$CC -E'.\n" CPP="$CC -E" fi else printf "CPP defined, skipping C preprocessor check.\n" fi mkf_sed 'CPP' "$CPP" # # as check # if [ -z "$AS" ]; then if ! check_binary as; then printf "Unable to find assembler.\n" exit 1 fi else printf "AS defined, skipping assembler.\n" fi mkf_sed 'AS' "$AS" ############### # check types # ######################################################################## # # _Bool type check # check_type _Bool # # blkcnt_t type check # check_type_header blkcnt_t sys/types.h # # long long type check # check_type "long long" # # unsigned long long type check # check_type "unsigned long long" # # long double type check # check_type "long double" # # intmax_t type check # check_type_header intmax_t stdint.h # # ptrdiff_t type check # check_type_header ptrdiff_t stddef.h # # wchar_t type check # check_type_header wchar_t wchar.h # # wint_t type check # check_type_header wint_t wchar.h ################# # check headers # ######################################################################## # # stdbool.h check # check_header stdbool.h # # libgen.h check # check_header libgen.h ################### # check functions # ######################################################################## # # strlcpy() check # check_header_function string.h strlcpy # # strlcat() check # check_header_function string.h strlcat # # strdup() check # check_header_function string.h strdup # # vsnprintf() check # check_header_function stdio.h vsnprintf # # snprintf() check # check_header_function stdio.h snprintf # # isblank() check # check_header_function ctype.h isblank # # mkstemps() check # check_header_function unistd.h mkstemps # # seteuid() check # if check_header_function unistd.h seteuid; then PS_FLAGS="" else PS_FLAGS="-DWITHOUT_FORK" fi # # dirname() check # if check_lib_function gen dirname; then LGEN_FLAGS="-lgen" else LGEN_FLAGS="" fi # # basename() check # check_lib_function gen basename # # isnan() check # if check_lib_function m isnan; then LM_FLAGS="-lm" else LM_FLAGS="" fi ##################### # compilation flags # ######################################################################## mkf_sed 'configure_input' "Generated by pmkcfg.sh" mkf_sed 'CFLAGS' "$CFLAGS $PS_FLAGS" mkf_sed 'CLDFLAGS' "$CLDFLAGS" mkf_sed 'LIBS' "$LGEN_FLAGS $LM_FLAGS" # # end # exit 0 pmk-0.10.4/AUTHORS010064400017500000000000000007131011506533100123110ustar00mipswheel----------------------------------------------------------------------- Pre Make Kit AUTHORS file Document revision: $Id: AUTHORS 1194 2004-08-31 12:11:05Z xsa $ ----------------------------------------------------------------------- Active Developers: ------------------ - Damien Couderc - Lead Developer - Xavier Santolaria - Developer - Martin Reindl - Developer pmk-0.10.4/pmkfile010064400017500000000000000100721062512151600126160ustar00mipswheel# $Id: pmkfile 1989 2007-05-23 20:25:50Z coudercd $ # pmkfile for pmk SETTINGS { LANG="C" TARGET = ("Makefile.pmk", "compat/config.h.pmk", "tests/Makefile.pmk") } SWITCHES { sw_usermode = FALSE } IF(sw_usermode) { DEFINE { # override prefix PREFIX = "\\$(HOME)" CONFDIR = "\\$(PREFIX)/.pmk" SBINDIR = "\\$(PREFIX)/bin" DATADIR = "\\$(CONFDIR)" } } IF(!sw_usermode) { DEFINE { CONFDIR = "\\$(SYSCONFDIR)/pmk" SBINDIR = "\\$(PREFIX)/sbin" DATADIR = "\\$(PREFIX)/share/\\$(PREMAKE)" } } DEFINE { PACKAGE = "pmk" BINDIR = "\\$(PREFIX)/bin" MANDIR = "\\$(PREFIX)/man" MAN1DIR = "\\$(MANDIR)/man1" MAN5DIR = "\\$(MANDIR)/man5" MAN8DIR = "\\$(MANDIR)/man8" PRIVSEP_USER = "nobody" VERSION = "0.9.3" INSTALL = "./pmkinstall" } # check alternate privsep user CHECK_VARIABLE(var_privsep) { REQUIRED = FALSE NAME = "PRIVSEP_USER" } # if not defined fall to default user IF(!var_privsep) { DEFINE { PRIVSEP_USER = "nobody" } } # # binary checks # CHECK_BINARY(binary_cpp) { NAME = "cpp" VARIABLE = "CPP" } CHECK_BINARY(binary_as) { NAME = "as" VARIABLE = "AS" } # check _Bool type CHECK_TYPE(type__bool) { REQUIRED = FALSE NAME = "_Bool" } # check type bool CHECK_TYPE(c_type_bool) { REQUIRED = FALSE NAME = "bool" HEADER = "stdbool.h" } # check type gid_t CHECK_TYPE(c_type_gid_t) { REQUIRED = FALSE NAME = "gid_t" HEADER = "sys/types.h" } # check type blkcnt_t CHECK_TYPE(c_type_blkcnt_t) { REQUIRED = FALSE NAME = "blkcnt_t" HEADER = "sys/types.h" } # check type long long CHECK_TYPE(c_type_long_long) { REQUIRED = FALSE NAME = "long long" } # check type unsigned long long CHECK_TYPE(c_type_unsigned_long_long) { REQUIRED = FALSE NAME = "unsigned long long" } # check type long double CHECK_TYPE(c_type_long_double) { REQUIRED = FALSE NAME = "long double" } # check type intmax_t CHECK_TYPE(c_type_intmax_t) { REQUIRED = FALSE NAME = "intmax_t" HEADER = "stdint.h" } # check type mode_t CHECK_TYPE(c_type_mode_t) { REQUIRED = FALSE NAME = "mode_t" LANG = "C" HEADER = "sys/types.h" } # check type ptrdiff_t CHECK_TYPE(c_type_ptrdiff_t) { REQUIRED = FALSE NAME = "ptrdiff_t" HEADER = "stddef.h" } # check type size_t CHECK_TYPE(c_type_size_t) { REQUIRED = FALSE NAME = "size_t" LANG = "C" HEADER = "sys/types.h" } # check type uid_t CHECK_TYPE(c_type_uid_t) { REQUIRED = FALSE NAME = "uid_t" LANG = "C" HEADER = "sys/types.h" } # check type wchar_t CHECK_TYPE(c_type_wchar_t) { REQUIRED = FALSE NAME = "wchar_t" HEADER = "wchar.h" } # check type wint_t CHECK_TYPE(type_wint_t) { REQUIRED = FALSE NAME = "wint_t" HEADER = "wchar.h" } # check header ctype.h CHECK_HEADER(c_header_ctype_h) { REQUIRED = FALSE NAME = "ctype.h" LANG = "C" FUNCTION = ("isblank") } # check header dirent.h CHECK_HEADER(c_header_dirent_h) { REQUIRED = FALSE NAME = "dirent.h" } # check header libgen.h CHECK_HEADER(c_header_libgen_h) { REQUIRED = FALSE NAME = "libgen.h" FUNCTION = ("basename", "dirname") } # check header stdarg.h CHECK_HEADER(c_header_stdarg_h) { REQUIRED = FALSE NAME = "stdarg.h" } # check header stdio.h CHECK_HEADER(c_header_stdio_h) { REQUIRED = FALSE NAME = "stdio.h" FUNCTION = ("snprintf", "vsnprintf") } # check header stdlib.h CHECK_HEADER(c_header_stdlib_h) { REQUIRED = FALSE NAME = "stdlib.h" FUNCTION = ("free", "malloc") } # check header string.h CHECK_HEADER(c_header_string_h) { REQUIRED = FALSE NAME = "string.h" LANG = "C" FUNCTION = ("strlcat", "strlcpy", "strdup", "memcpy") } # check header sys/param.h CHECK_HEADER(c_header_sys_param_h) { REQUIRED = FALSE NAME = "sys/param.h" LANG = "C" } # check header sys/wait.h CHECK_HEADER(c_header_sys_wait_h) { REQUIRED = FALSE NAME = "sys/wait.h" LANG = "C" SUBHDR = ("sys/type.h") } # check header unistd.h CHECK_HEADER(c_header_unistd_h) { REQUIRED = FALSE NAME = "unistd.h" LANG = "C" FUNCTION = ("mkstemps") } # check library gen CHECK_LIB(c_library_gen) { REQUIRED = FALSE NAME = "gen" LANG = "C" FUNCTION = ("basename", "dirname") } # check library m CHECK_LIB(c_library_m) { REQUIRED = FALSE NAME = "m" FUNCTION = ("isinf", "isnan") } pmk-0.10.4/BUGS010064400017500000000000000023451032174522300117330ustar00mipswheel----------------------------------------------------------------------- Pre Make Kit BUGS file Document revision: $Id: BUGS 1487 2005-10-08 13:33:07Z mipsator $ ----------------------------------------------------------------------- CYGWIN : - cygwin seems to not handle perfectly its binaries, a 'which gcc' give the path to gcc but when you're looking for it directly with dir functions you can't get it because its real name is gcc.exe ... So we decided to stop cygwin support until they learn how to make their system working transparently (yes, between the lines you can read cygwin sucks). HP-UX : - S_BLKSIZE doesn't exist. - install is not bsd compatible. Debian/KFreeBSD : - this system could have the same problem than Debian/KNetBSD. Debian/KNetBSD : - the uname utility is returning the 'NetBSD' string when asking for the operating system name. As this behavior is resulting from the fact that Linux distributions return the kernel name instead of the system name we are not able to differenciate between it from a real NetBSD system. That said, we do not support this system until we known how to deal with it. Tru64 : - int64_t doesn't exist. SunOS: - S_BLKSIZE doesn't exist. pmk-0.10.4/man004075500017500000000000000000001077177765600117735ustar00mipswheelpmk-0.10.4/man/pmkinstall.1010064400017500000000000000125031060026337300142610ustar00mipswheel.\" $Id: pmkinstall.1 1958 2007-03-21 17:10:19Z coudercd $ . .\" $OpenBSD: install.1,v 1.19 2003/06/10 09:12:13 jmc Exp $ .\" $NetBSD: install.1,v 1.4 1994/11/14 04:57:17 jtc Exp $ .\" .\" Copyright (c) 1987, 1990, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. 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. .\" 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. .\" .\" @(#)install.1 8.1 (Berkeley) 6/6/93 .\" .\" .\" Copyright (c) 2003 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: .\" - Redistribution 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 AUTHOR ''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 AUTHOR 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. .\" .\" . .Dd June 6, 1993 .Dt PMKINSTALL 1 .Os . .Sh NAME .Nm pmkinstall .Nd install binaries and data . .Sh SYNOPSIS .Nm .Op Fl bcs .Op Fl B Ar suffix .Op Fl g Ar group .Op Fl m Ar mode .Op Fl o Ar owner .Ar file1 file2 .Nm .Op Fl bcs .Op Fl B Ar suffix .Op Fl g Ar group .Op Fl m Ar mode .Op Fl o Ar owner .Ar file1 \&... .Ar fileN directory .Nm pmkinstall .Fl d .Op Fl g Ar group .Op Fl m Ar mode .Op Fl o Ar owner .Ar directory \&... .Nm pmkinstall .Fl v .Nm pmkinstall .Fl h . .Sh DESCRIPTION The file(s) are copied to the target file or directory. If the destination is a directory, then the .Ar file is copied into .Ar directory with its original filename. If the .Fl b option is given and the target file already exists, it is renamed to the original name folloeb by the backup suffix. The default suffix is ".old" but can be overriden with the .Fl B option. .Pp The options are as follows: .Bl -tag -width Ds .It Fl B Ar suffix Orverride backup suffix .It Fl b Backup any existing files before overwriting. .It Fl c Copy the file. This is actually the default. The .Fl c option is only included for backwards compatibility. .It Fl d Create directories. Missing parent directories are created as required. .It Fl g Ar group Specify a group. A numeric GID is allowed. .It Fl h Display usage. .It Fl m Ar mode Specify an alternate mode. The default mode is set to rwxr-xr-x (0755). The specified mode may be either an octal or symbolic value; see .Xr chmod 1 for a description of possible mode values. .It Fl o Ar owner Specify an owner. A numeric UID is allowed. .It Fl s .Nm exec's the command of environment variable .Ev STRIP to strip binaries so that install can be portable over a large number of systems and binary types. If the environment variable .Ev STRIP is not set, the action is skipped. .It Fl h Display version. .El . .Ex -std pmkinstall .Sh ENVIRONMENT .Bl -tag -width "STRIP" .It Ev STRIP Set which .Xr strip 1 program to run. .El . .Sh SEE ALSO .Xr pmk 1 , .Xr pmkscan 1 , .Xr pmksetup 8 . .Sh AUTHOR .An Damien Couderc. pmk-0.10.4/man/pmksyntax.5010064400017500000000000000046161061073261500141540ustar00mipswheel.\" $Id: pmksyntax.5 1976 2007-04-16 17:42:37Z coudercd $ . .Dd November 5, 2005 .Dt PMKSYNTAX 5 .Os . .Sh NAME .Nm PMK Syntax .Nd PMK files syntax manual . .Sh DESCRIPTION This manual page describe the basic syntax used in PMK files such as .Nm pmkfile and .Nm scanfile . .Sh DATA TYPES .Nm uses pseudo types like the following: .Bl -tag -width "identifier" .It Cm bool The classical boolean type with TRUE and FALSE values. .Pp For example: .Bd -literal -offset indent TRUE FALSE .Ed .It Cm identifier An identifier is a string of alphanumerical and underscores characters. .Pp For example: .Bd -literal -offset indent REQUIRED a_label underscores_are_nice .Ed .It Cm quoted This means quoted string which can contain a set of characters delimited by quotation marks. .Pp For examples: .Bd -literal -offset indent "simple quoted string" "string that contain \\"quotes\\" backslashed" "can also contain filenames like pmkfile.scan" .Ed .It Cm list It is one or more of the previous types between brackets. Multiple objects are separated with a comma. Blanks are currently not allowed beside commas, this means that you can find them only in a quoted string of the list. .Pp For example: .Bd -literal -offset indent ("only_one_string") ("added a boolean",TRUE) (mixed_list_of,"words","and",TRUE,"quoted strings") .Ed .El . .Sh BASIC SYNTAX .Nm can contain comments, blank lines and commands. .Pp A command has the following format (? character means optional field): .Bd -literal -offset indent { } .Ed .Pp The command and label names can be assimilated to the 'word' type. See .Sx DATA TYPES above. .Pp The body can contain comment(s) and definition line(s). A commented line start with a '#' character like the following: .Bd -literal -offset indent # this is a comment line .Ed .Pp A definition line has the following format: .Bd -literal -offset indent = .Ed .Pp The key name is of identifier type. .Pp The key value type can be 'bool', 'quoted' or 'list'. The right type will depend on the key name (see further). .Pp For example: .Bd -literal -offset indent CHECK_INCLUDE(header_sys_param) { # following options use different uses of blank characters # key value is word type REQUIRED = TRUE # key value is list type DEPEND= ("dep_one",dep_two,"dep_three") # key value is quoted type INCLUDE = "sys/param.h" } .Ed . .Sh SEE ALSO .Xr pmkfile 5 , .Xr scanfile 5 pmk-0.10.4/man/pmk.1010064400017500000000000000033171060026337300126750ustar00mipswheel.\" $Id: pmk.1 1958 2007-03-21 17:10:19Z coudercd $ . .Dd March 28, 2003 .Dt PMK 1 .Os . .Sh NAME .Nm pmk .Nd configuring tool . .Sh SYNOPSIS .Nm .Bk -words .Op Fl hlv .Op Fl b Ar path .Op Fl d Ar switch_disable_list .Op Fl e Ar switch_enable_list .Op Fl f Ar file .Op Fl o Ar file .Op Ar options .Ek . .Sh DESCRIPTION .Nm is a configuring tool which aims to help building project on different operating systems. .Pp The options are as follows: .Bl -tag -width Ds .It Fl b Ar path Use given path as basedir. .It Fl d Ar switch_disable_list Provide a list of switches to disable. .It Fl e Ar switch_enable_list Provide a list of switches to enable. .It Fl f Ar file Use an alternate file instead of .Xr pmkfile 5 . .It Fl h Display usage. .It Fl l Enable check build log. .It Fl o Ar file Override pmk.conf data with the content of the given file. .It Fl v Display the version number. .El . .Sh FILES .Bl -tag -width "/etc/pmk/pmk.conf" -compact .It Pa pmkfile .Xr pmk 1 specification file. .It Pa /etc/pmk/pmk.conf default .Xr pmk 1 configuration file .El . .Sh EXAMPLES To display pmk version number: .Pp .Dl $ pmk -v .Pp To use .Em src as the basedir and disable two switches: .Pp .Dl $ pmk -b src -d use_gtk,use_qt .Pp To specify an alternate .Xr pmkfile 5 , enabling one switch and overriding .Pa /etc/pmk/pmk.conf with the content of a given file ( .Pa pmk/pmkovr in this case): .Pp .Dl $ pmk -f pmk/pmkfile -e use_curses -o pmk/pmkovr . .Sh SEE ALSO .Xr make 1 , .Xr pmkscan 1 , .Xr pmkfile 5 , .Xr pmk.conf 5 , .Xr pmksetup 8 . .Sh HISTORY The idea to replace configure script was existing since a long time. But the projet was initiated in the begining of March 2003. . .Sh AUTHOR .An Damien Couderc. . .Sh BUGS You have to find them. pmk-0.10.4/man/scanfile.5010075500017500000000000000102011060026337300136670ustar00mipswheel.\" $Id: scanfile.5 1958 2007-03-21 17:10:19Z coudercd $ . .Dd September 15, 2005 .Dt SCANFILE 5 .Os . .Sh NAME .Nm scanfile .Nd pmkscan specification file . .Sh DESCRIPTION .Nm is a file containing specifications that defines which sources are to be scanned and what to generate from the resulting data. . .Sh SYNTAX See .Xr pmksyntax.5 to have an overview of the basic syntax of scanfiles. . .Sh COMMANDS .Pp The available commands are the following : .Bl -tag -width Ds .It Cm GEN_PMKFILE This command specify a zone to scan and generate a pmkfile. .Pp Arguments: .Bl -tag -width DIRECTORY -offset indent .It Dv CFGNAME type is 'quoted', give the name of the template config file to use instead of the default one. .It Dv DIRECTORY type is 'quoted', define the zone directory to scan. .It Dv DISCARD type is 'list', list of directories to discard in recursive mode. .It Dv EXTRATAG type is 'list', list of extra tags to add in template files. .It Dv RECURSE type is 'bool', enable recursive scanning, default is FALSE. .It Dv UNIQUE type is 'bool', enable unique resulting file instead of one for each directory. This is actually the default and only one method available (work in progress). .El .Pp For example: .Bd -literal -offset indent GEN_PMKFILE { DIRECTORY = "." RECURSE = TRUE DISCARD = ("samples", "doc", "data", "man") UNIQUE = TRUE } .Ed . .It Cm GEN_MAKEFILE This command specify a zone to scan and generate a makefile. .Pp Arguments: .Bl -tag -width DIRECTORY -offset indent .It Dv DIRECTORY type is 'quoted', define the zone directory to scan. .It Dv DISCARD type is 'list', list of directories to discard in recursive mode. .It Dv EXTRATAG type is 'list', list of extra tags to add in template files. .It Dv MKFNAME type is 'quoted', give the name of the template makefile to use instead of the default one. .It Dv RECURSE type is 'bool', enable recursive scanning, default is FALSE. .It Dv UNIQUE type is 'bool', enable unique resulting file instead of one for each directory. This is actually the default and only one method available (work in progress). .El .Pp For example: .Bd -literal -offset indent GEN_MAKEFILE { DIRECTORY = "." RECURSE = TRUE DISCARD = ("samples", "doc", "tests") MKFNAME = "Makefile.pmk" UNIQUE = TRUE } .Ed . .It Cm GEN_ZONE This command specify a zone to scan and what to generate. .Pp Arguments: .Bl -tag -width DIRECTORY -offset indent .It Dv CFGNAME type is 'quoted', give the name of the template config file to use instead of the default one. .It Dv DIRECTORY type is 'quoted', define the zone directory to scan. .It Dv DISCARD type is 'list', list of directories to discard in recursive mode. .It Dv EXTRATAG type is 'list', list of extra tags to add in template files. .It Dv PMKFILE type is 'bool', enable generation of a pmkfile .It Dv MAKEFILE type is 'bool', enable generation of a makefile .It Dv MKFNAME type is 'quoted', give the name of the template makefile to use instead of the default one. .It Dv RECURSE type is 'bool', enable recursive scanning, default is FALSE. .It Dv UNIQUE type is 'bool', enable unique resulting file instead of one for each directory. This is actually the default and only one method available (work in progress). .El .Pp For example: .Bd -literal -offset indent GEN_ZONE(main) { DIRECTORY = "." RECURSE = TRUE DISCARD = ("samples", "doc", "tests") PMKFILE = TRUE MAKEFILE = TRUE MKFNAME = "Makefile.pmk" UNIQUE = TRUE } .Ed . .It Cm DEF_LIB This command define library attributes. .Pp Arguments: .Bl -tag -width DIRECTORY -offset indent .It Dv NAME type is 'quoted', give the name of the library. .It Dv VMAJ type is 'quoted', give the major version of the library. .It Dv VMIN type is 'quoted', give the minor version of the library. .It Dv LINKER type is 'quoted', define the relative language of the linker to be used. .It Dv SOURCES type is 'list', list of the main sources which objects must be linked in the library. .It Dv HEADERS type is 'list', list of library headers to be installed. .El .Pp For example: .Bd -literal -offset indent DEFINE_LIB { NAME = "testc" VMAJ = "1" VMIN = "3" LINKER = "C" SOURCES = ("libtest.c") HEADERS = ("libtest.h") } .Ed .El . .Sh SEE ALSO .Xr pmkscan 1 , .Xr pmkfile 5 pmk-0.10.4/man/pmkpc.1010064400017500000000000000061671060026337300132260ustar00mipswheel.\" $Id: pmkpc.1 1958 2007-03-21 17:10:19Z coudercd $ . .Dd January 20, 2004 .Dt PMKPC 1 .Os . .Sh NAME .Nm pmkpc .Nd Packages metainformation management tool. . .Sh SYNOPSIS .Nm .B pmkpc .Op Ar options .Op Ar modules . .Sh DESCRIPTION .Nm is a tool that gathers metainformation about installed libraries that provide pkg-config data files. It aims to be an alternative to the pkg-config tool. . .Sh OPTIONS .Pp The options are as follows: .Bl -tag -width Ds .It --version Display compatibility version relative to pkgconfig. .It --atleast-pkgconfig-version Check if compatibility version is at least equal or greater than the version provided as an argument. .It --modversion Display the version of the given library modules using one line for each version. .It --atleast-version Check if each module version is at least equal or greater than the version provided as an argument. .It --exact-version Check if each module version is equal to the version provided as an argument. .It --max-version Check if each module version is at least equal or smaller than the version provided as an argument. .It --exists Check if given library modules exists. .It --cflags Display pre-processor and compiler flags for given library modules. Duplicates values are automatically removed. .It --cflags-only-I Enable output filtering of compiler flags and keep include path. See output filtering section. .It --cflags-only-other Enable output filtering of compiler flags and keep other flags than include path. See output filtering section. .It --libs Display linker flags for given library modules. Duplicate values are automatically removed. .It --libs_only_l Enable output filtering of linker flags and keep library linking flags. See output filtering section. .It --libs_only_L Enable output filtering of linker flags and keep library path flags. See output filtering section. .It --libs_only_other Enable output filtering of linker flags and keep other flags than library linking and path flags. See output filtering section. .It --help Only for compatibility with pkg-config. Refers to this man page. .It --usage Display usage. .It --list-all Display all module names and descriptions. .El . .Pp The following options have not been implemented yet: .Bd -literal -offset indent --uninstalled --debug --variable --define-variable --print-errors --silence-errors --errors-to-stdout .Ed . .Sh OUTPUT FILTERING As pkg-config has no standard specifications we determinated its behavior from pkg-config man page. The result is that filtering options can be accumulated. The default behavior is like if all filtering options were enabled. . .Sh FILES .Bl -tag -width "pmkcfgtool.dat" -compact .It Pa pmkcfgtool.dat config tool specific data. .El .Sh SEE ALSO .Xr pkg-config 1 .Sh HISTORY Initialy pmk was using pkg-config in a sub shell. Further, internal support was developed to improve the speed of data gathering. While studying the code of pkg-config we discovered some chunks of code that were unsafe (malloc return unchecked, use of strcpy without any check, ...). Knowing that, we decided to try to do a safer implementation and pmkpc was born. .Sh AUTHORS .An Damien Couderc and Xavier Santolaria . pmk-0.10.4/man/pmkfile.5010064400017500000000000000155351061073261500135470ustar00mipswheel.\" $Id: pmkfile.5 1976 2007-04-16 17:42:37Z coudercd $ . .Dd April 27, 2003 .Dt PMKFILE 5 .Os . .Sh NAME .Nm pmkfile .Nd pmk specification file . .Sh DESCRIPTION .Nm is a file containing specifications that help configuring a package build on a given platform. . .Sh SYNTAX See .Xr pmksyntax.5 to have an overview of the basic syntax of pmkfiles. . .Sh SPECIFIC COMMANDS .Pp The following commands have no label. .Bl -tag -width Ds .It Cm SETTINGS This command sets pmk parameters. .Pp Arguments: .Bl -tag -width AC_COMPAT -offset indent .It Dv AC_COMPAT type is 'quoted', enable autoconf compatibility (empty string or filename). .It Dv LANG type is 'quoted', global default language. .It Dv TARGET type is 'list', list of target's filenames. .It Dv DETECT type is 'list', list of languages (compilers to identify). .El .Pp For example: .Bd -literal -offset indent SETTINGS { AC_COMPAT="config.h" LANG="C" TARGET=("src/file.c","src/file.h") DETECT=("CC") } .Ed . .It Cm DEFINE This command permits to define variables. .Pp Arguments: .Bd -literal -offset Those are the variables to be defined (quote data type only). .Ed .Pp For example: .Bd -literal -offset indent DEFINE { PACKAGE="my_prog" VERSION="0.1" } .Ed . .It Cm SWITCHES This command is setting dependency switches (see further DEPEND definition). .Pp Arguments: .Pp For example: .Bd -literal -offset indent SWITCHES { use_curses=TRUE use_gtk=FALSE } .Ed .El . .Sh STANDARD COMMANDS .Pp All these commands need a label. .Pp They can all have the following optional arguments: .Bl -tag -width REQUIRED -offset indent .It Cm REQUIRED Specify if this test is required to achieve the configuration. Type is 'bool'. If not specified, it is TRUE by default. .It Cm DEPEND Specify check dependencies. Type is 'list'. A dependency is a label or a switch name. The value of each dependency can be negated by adding a leading '!' sign. If at least one of the dependencies is false then the check will be disabled. .Pp For example: .Bd -literal -offset indent DEPEND = ("header_gtk","!header_qt") .Ed .It Cm DEFS Specify additional defines. Type is 'list'. If the check succeeds then the given defines are also recorded else they are ignored. .El .Pp Some of these commands can also have the following arguments: .Bl -tag -width Ds .It Cm LANG Specify the language used in the following list: .Bl -tag -width xxx .It Dv C , C++ .El .Pp Type is 'quoted', by default \\"C\\" is the used language. .El .Pp Here the list of commands: .Bl -tag -width Ds .It Cm CHECK_BINARY Check if a binary is in the path. .Pp Arguments: .Bl -tag -width REQUIRED -offset indent .It Dv REQUIRED .It Dv DEPEND .It Dv DEFS .It Dv NAME type is 'quoted', name of the binary. .It Dv VARIABLE type is 'quoted', variable name to store the path. .El .It Cm CHECK_HEADER Check language header and optionally a function. .Pp Arguments: .Bl -tag -width REQUIRED -offset indent .It Dv REQUIRED .It Dv DEPEND .It Dv DEFS .It Dv LANG .It Dv NAME type is 'quoted', name of the header. .It Dv MACRO type is 'list', list of one or more compiler macros to check, optional. .It Dv FUNCTION type is 'quoted' or 'list', name or list of functions to check, optional. .It Dv CFLAGS type is 'quoted', variable name to store CFLAGS values, optional. .It Dv SUBHDR type is 'list', list of header dependencies, optional. .El .It Cm CHECK_LIB Check a library and optionally a function. .Pp Arguments: .Bl -tag -width REQUIRED -offset indent .It Dv REQUIRED .It Dv DEPEND .It Dv DEFS .It Dv LANG .It Dv NAME type is 'quoted', name of the library to check. .It Dv FUNCTION type is 'quoted' or 'list', name or list of functions to check, optional. .It Dv LIBS type is 'quoted', variable name to store LIBS values, optional. .El .It Cm CHECK_CONFIG Check using a *-config tool. .Pp Arguments: .Bl -tag -width REQUIRED -offset indent .It Dv REQUIRED .It Dv DEPEND .It Dv DEFS .It Dv NAME type is 'quoted', config tool name. .It Dv VERSION type is 'quoted', minimal version needed, optional. .It Dv CFLAGS type is 'quoted', variable name to store CFLAGS values, optional. .It Dv LIBS type is 'quoted', variable name to store LIBS values, optional. .It Dv VARIABLE type is 'quoted', variable name to store the path of the config tool, optional. .El .It Cm CHECK_PKG_CONFIG Check a package using pkg-config. .Pp Arguments: .Bl -tag -width REQUIRED -offset indent .It Dv REQUIRED .It Dv DEPEND .It Dv DEFS .It Dv NAME type is 'quoted', package name. .It Dv VERSION type is 'quoted', minimal version needed, optional. .It Dv CFLAGS type is 'quoted', variable name to store CFLAGS values, optional. .It Dv LIBS type is 'quoted', variable name to store LIBS values, optional. .El .It Cm CHECK_TYPE Check if the given type exists. .Pp Arguments: .Bl -tag -width REQUIRED -offset indent .It Dv REQUIRED .It Dv DEPEND .It Dv DEFS .It Dv LANG .It Dv NAME type is 'quoted', name of the type to check. .It Dv HEADER type is quoted, name of the header where to find the given type. .It Dv MEMBER type is quoted, name of a member of the structure given in NAME to be checked. .El .It Cm CHECK_VARIABLE Check if the given variable does exist and optionally its value. .Pp Arguments: .Bl -tag -width REQUIRED -offset indent .It Dv REQUIRED .It Dv DEPEND .It Dv DEFS .It Dv NAME type is 'quoted', name of the variable to check. .It Dv VALUE type is 'quoted', value to check with the variable, optional. .El .El . .Sh CONDITIONAL COMMANDS .Bl -tag -width Ds .It Cm IF(expression) It contains other commands that will be executed only if the given expression is true. .Pp Arguments: .Pp For example: .Bd -literal -offset indent IF(header_gtk) { DEFINE { HAVE_GTK = "1" } } .Ed .It Cm ELSE(expression) It contains other commands that will be executed only if the given expression is false. .Pp Arguments: .Pp For example: .Bd -literal -offset indent ELSE(header_glib) { DEFINE { HAVE_GLIB = "0" } } .Ed .El . .Sh LIBRARY NAME BUILDING .Bl -tag -width Ds .It Cm BUILD_LIB_NAME This command helps you to build static and/or shared library name(s) depending on the rules of the host operanding system. .Pp Arguments: .Bl -tag -width VERSION -offset indent .It Dv NAME type is 'quoted', name of the library (without leading 'lib'). .It Dv MAJOR type is 'quoted', major number for the version, optional. .It Dv MINOR type is 'quoted', minor number for the version, optional. .It Dv SHARED type is 'quoted', variable that will be set with the shared library name, optional. .It Dv STATIC type is 'quoted', variable that will be set with the static library name, optional. .It Dv VERSION type is 'boolean', boolean value for library version processing , optional. .El .Pp For example: .Bd -literal -offset indent BUILD_LIB_NAME { NAME = "test" STATIC = "TESTLIB_STATIC" SHARED = "TESTLIB_SHARED" MAJOR = "0" MINOR = "2" VERSION = TRUE } .Ed .El .Bl -tag -width Ds .It Cm BUILD_SHLIB_NAME This command has been obsoleted by the BUILD_LIB_NAME command. .El . .Sh SEE ALSO .Xr pmk 1 , .Xr pmkscan 1 , .Xr pmksyntax.5 pmk-0.10.4/man/pmkscan.1010064400017500000000000000017411060026337300135410ustar00mipswheel.\" $Id: pmkscan.1 1958 2007-03-21 17:10:19Z coudercd $ . .Dd March 28, 2003 .Dt PMKSCAN 1 .Os . .Sh NAME .Nm pmkscan .Nd source scanning tool . .Sh SYNOPSIS .Nm .Bk -words .Op Fl hlv .Op Fl f Ar file .Ek . .Sh DESCRIPTION .Nm is a tool which scans the sources with the intention to generate build files like .Xr pmkfile 5 , config file template (by default config.h.pmk) and makefile template (by default Makefile.pmk). .Pp The options are as follows: .Bl -tag -width Ds .It Fl f Ar file Use the given file instead of the default script named .Xr scanfile 5 which should be in the working directory. .It Fl h Display usage. .It Fl l Log into pmkscan log file. .It Fl v Display the version number. .El .Pp .Sh FILES .Bl -tag -width "pmkfile" -compact .It Pa pmkfile default .Xr pmkscan 1 generated pmkfile. .It Pa pmkscan.dat .Xr pmkscan 1 database .It Pa scanfile .Xr pmkscan 1 specifications file .El . .Sh SEE ALSO .Xr pmk 1 , .Xr pmkfile 5 .Xr scanfile 5 . .Sh AUTHOR .An Damien Couderc . pmk-0.10.4/man/pmk.conf.5010064400017500000000000000164001060026337300136220ustar00mipswheel.\" $Id: pmk.conf.5 1958 2007-03-21 17:10:19Z coudercd $ .\" .\" Copyright (c) 2003-2004 Xavier Santolaria .\" 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: .\" - Redistribution 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 AUTHOR ''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 AUTHOR 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. .\" .\" .Dd April 03, 2003 .Dt PMK.CONF 5 .Os .Sh NAME .Nm pmk.conf .Nd premake configuration file .Sh DESCRIPTION .Nm pmk.conf contains a series of assignements that are used by .Xr pmk 1 and created by .Xr pmksetup 8 . . .Sh DATA TYPES These are common types used by pmk, see .Xr pmkfile 5 for a complete description. . .Sh OPERATORS .Bl -tag -width Ds .It Cm = This operator makes the value dynamic, which means that it will be (re)assigned everytime you run .Xr pmksetup 8 . .Pp For example: .Bd -literal -offset indent BIN_CC = "/usr/bin/cc" .Ed .It Cm : This operator makes the value static, which means that if you want to regenerate the .Nm pmk.conf , the value will be kept and not dynamically assigned by .Xr pmksetup 8 . .Pp For example: .Bd -literal -offset indent BIN_INSTALL:"/usr/local/bin/install" .Ed .El .Pp . .Sh FAMILY CLASSES Assignements can be classed in different families. .Bl -tag -width PATH_* .It Ev AC_* Compatibility with autoconf. .It Ev BIN_* This class is used for binary paths. .It Ev HW_* Hardware related data like for example byte order or cpu features. .It Ev PATH_* Specific paths family. .It Ev OS_* System specific data. .It Ev misc Some other data (such as PREFIX) cannot fit into previous families. .El . .Sh AC CLASS This class is providing some variables for GNU Autoconf compatibility: .Bl -tag -width AC_ECHO_C .It Ev AC_ECHO_C Support for "\\c". .It Ev AC_ECHO_N Support for "\\n". .It Ev AC_ECHO_T Support for "\\t". .El . .Sh BIN CLASS This class is providing locations of various useful binaries such as ar, as, cc, cpp, ... . .Sh HW CLASS This class is giving some information about the host hardware. .Bl -tag -width HW_BYTEORDER .It Ev HW_BYTEORDER Provide the byte order of the host: 'BIG_ENDIAN' or 'LITTLE_ENDIAN'. .It Ev HW_CPU_ARCH Identify the cpu architecture. .El . We support actually the following architectures (with cpu identification for some of them): .Bl -tag -width parisc_64 .It Ev alpha .Bl -tag -width HW_ALPHA_CPU_FEATURES .It Ev HW_ALPHA_CPU_CLASS Cpu class (EV4, EV5 or EV6). .It Ev HW_ALPHA_CPU_FEATURES Cpu features list (BWX, FIX, CIX, MVI, PAT and PMI) .El . .It Ev ia_64 .Bl -tag -width HW_IA64_CPU_FEATURES .It Ev HW_IA64_CPU_ARCHREV Cpu architecture revision number. .It Ev HW_IA64_CPU_CLASS Cpu class ('Itanium' or 'Itanium2') .It Ev HW_IA64_CPU_FAMILY Cpu family number. .It Ev HW_IA64_CPU_FEATURES Cpu features list (LB, SD and AO). .It Ev HW_IA64_CPU_MODEL Cpu model number. .It Ev HW_IA64_CPU_REVISION Cpu revision number. .It Ev HW_IA64_CPU_VENDOR Cpu vendor string. .El . .It Ev m68k No specific variables. . .It Ev parisc_64 No specific variables. . .It Ev ppc No specific variables. . .It Ev sparc_32 No specific variables. . .It Ev sparc_64 No specific variables. . .It Ev x86_32 .Bl -tag -width HW_X86_CPU_STD_VENDOR .It Ev HW_X86_CPU_CLASS Cpu family class (386, 486, 586, ...). .It Ev HW_X86_CPU_EXTFAM Extended family number. .It Ev HW_X86_CPU_EXTMOD Extended model number. .It Ev HW_X86_CPU_FAMILY Cpu family number. .It Ev HW_X86_CPU_FEATURES Cpu features list (FPU, VME, DE, PSE, TSC, ...). .It Ev HW_X86_CPU_MODEL Cpu model number. .It Ev HW_X86_CPU_STD_VENDOR Standardised cpu vendor ('INTEL', 'AMD', ...). .It Ev HW_X86_CPU_VENDOR Cpu vendor string. .El . .It Ev x86_64 Same as x86_32 architecture. . .It Ev vax No specific variables. .El . .Sh OS CLASS This class is providing informations about the host's operating system: .Bl -tag -width OS_VERSION .It Ev OS_ARCH Operating system architecture (warning: this is OS specific). .It Ev OS_NAME Operating system name (warning: linux distributions return the kernel name). .It Ev OS_VERSION Operating system version (warning: linux distributions return the kernel version). .El . .Sh PATH CLASS This class is providing path for binaries, headers and libraries. . .Sh MISC CLASS This class is regrouping what can not be classed elsewhere. .Bl -tag -width PC_PATH_LIB .It Ev PREFIX Prefix environnement variable. .It Ev SYSCONFDIR System configuration directory. .It Ev PC_PATH_LIB Library path for pmkpc or pkg_config. .El . .Sh FILES .Bl -tag -width "/etc/pmk/pmk.conf" -compact .It Pa /etc/pmk/pmk.conf default .Xr pmk 1 configuration file .El .Sh EXAMPLES A typical pmk.conf might appear as follows: .Bd -literal # autoconf compatibility AC_ECHO_C = "\\c" AC_ECHO_N = "" AC_ECHO_T = "" # specific binaries BIN_AR = "/usr/bin/ar" BIN_AS = "/usr/bin/as" BIN_AWK = "/usr/bin/awk" BIN_CAT = "/bin/cat" BIN_CC = "/usr/bin/cc" BIN_CPP = "/usr/bin/cpp" BIN_CXX = "/usr/bin/c++" BIN_ECHO = "/bin/echo" BIN_EGREP = "/usr/bin/egrep" BIN_GREP = "/usr/bin/grep" BIN_ID = "/usr/bin/id" BIN_INSTALL = "/usr/bin/install" BIN_LEX = "/usr/bin/lex" BIN_LN = "/bin/ln" BIN_PKGCONFIG = "/usr/local/bin/pkg-config" BIN_RANLIB = "/usr/bin/ranlib" BIN_SH = "/bin/sh" BIN_STRIP = "/usr/bin/strip" BIN_SUDO = "/usr/bin/sudo" BIN_TAR = "/bin/tar" BIN_YACC = "/usr/bin/yacc" # architecture specific HW_BYTEORDER = "LITTLE_ENDIAN" HW_CPU_ARCH = "x86_32" HW_X86_CPU_CLASS = "i686" HW_X86_CPU_EXTFAM = "0" HW_X86_CPU_EXTMOD = "0" HW_X86_CPU_FAMILY = "15" HW_X86_CPU_FEATURES = "FPU VME DE PSE TSC MSR PAE MCE CX8 APIC SEP MTRR PGE MCA CMOV PAT PSE36 CLFL DTES ACPI MMX FXR SSE SSE2 HTT TM1 PBE FPU MON DSCPL EST TM2 CX16 ETPRD " HW_X86_CPU_MODEL = "2" HW_X86_CPU_STD_VENDOR = "INTEL" HW_X86_CPU_VENDOR = "GenuineIntel" # OS related OS_ARCH = "i386" OS_NAME = "OpenBSD" OS_VERSION = "3.6" # PATH related PATH_BIN = "/bin,/sbin,/usr/bin,/usr/sbin,/usr/X11R6/bin,/usr/local/sbin,/usr/local/bin" PATH_INC = "/usr/include" PATH_LIB = "/usr/lib" # misc PC_PATH_LIB = "$PREFIX/lib/pkgconfig" PREFIX = "/usr/local" SYSCONFDIR = "/etc" .Ed .Pp . .Sh SEE ALSO .Xr make 1 , .Xr pmk 1 , .Xr pmkscan 1 , .Xr pmkfile 5 , .Xr pmksetup 8 pmk-0.10.4/man/pmksetup.8010064400017500000000000000055021051426315500137650ustar00mipswheel.\" $Id: pmksetup.8 1913 2006-10-14 22:36:29Z coudercd $ .\" .\" Copyright (c) 2003 Xavier Santolaria .\" Copyright (c) 2006 Couderc Damien .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" - Redistribution 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 AUTHOR ''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 AUTHOR 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. .\" .\" .Dd April 03, 2003 .Dt PMKSETUP 8 .Os .Sh NAME .Nm pmksetup .Nd premake setup .Sh SYNOPSIS .Nm pmksetup .Bk -words .Op Fl hVv .Op Fl r Ar variable .Xo .Oo Fl u .Ar variable Ns = Ns Ar value Oc .Xc .Ek .Sh DESCRIPTION The .Nm utility is meant to create or update the .Xr pmk.conf 5 file in order to run the .Xr pmk 1 configuration tool. .Pp .Nm reads all configuration information from the .Xr pmk.conf 5 file. .Pp The options are as follows: .Bl -tag -width Ds .It Fl h Display the help menu. .It Fl r Ar variable Remove the given variable from .Xr pmk.conf 5 if its value isn't static. Data gathering is skipped by this option. .It Fl u Ar variable Ns = Ns Ar value Add or update existing variable from .Xr pmk.conf 5 if its value isn't static. The value must have its double quotes escaped to pass through shell filter. Data gathering is skipped by this option. .It Fl V Verbose, display debugging messages. .It Fl v Display the version number. .El .Sh FILES .Bl -tag -width "/etc/pmk/pmk.conf" -compact .It Pa /etc/pmk/pmk.conf default .Xr pmk 1 configuration file .El .Sh SEE ALSO .Xr make 1 , .Xr pmk 1 , .Xr pmkscan 1 , .Xr pmk.conf 5 , .Xr pmkfile 5 .Sh AUTHORS .An Damien Couderc and Xavier Santolaria . pmk-0.10.4/parse_lang.c010075500017500000000000000520171047114646400135430ustar00mipswheel/* $Id: parse_lang.c 1555 2006-08-17 20:10:28Z mipsator $ */ /* * Copyright (c) 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. * */ #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "common.h" #include "parse_lang.h" /*#define DEBUG_PRSC 1*/ /************* * variables * ***********************************************************************/ /* preprocessor keywords ***********************************************/ char *pp_keywords[] = { RKW_PP_DEF, RKW_PP_ELIF, RKW_PP_ELSE, RKW_PP_ENDF, RKW_PP_ERR, RKW_PP_IF, RKW_PP_IFDF, RKW_PP_IFND, RKW_PP_INCL, RKW_PP_LINE, RKW_PP_PRGM, RKW_PP_UDEF }; /* assembler directives ************************************************/ char *as_keywords[] = { RKW_AS_TSEG, RKW_AS_DSEG }; size_t nb_as_keywords = sizeof(as_keywords) / sizeof(char *); /* C language reserved keywords (without types) ************************/ char *c_keywords[] = { RKW_C_BOOL, RKW_C_CMPLX, RKW_C_IMGNR, RKW_C_AUTO, RKW_C_BREAK, RKW_C_CASE, RKW_C_CHAR, RKW_C_CONST, RKW_C_CONTN, RKW_C_DFLT, RKW_C_DO, RKW_C_DBL, RKW_C_ELSE, RKW_C_ENUM, RKW_C_EXTRN, RKW_C_FLOAT, RKW_C_FOR, RKW_C_GOTO, RKW_C_IF, RKW_C_INLN, RKW_C_INT, RKW_C_LONG, RKW_C_RGSTR, RKW_C_RSTCT, RKW_C_RTRN, RKW_C_SHORT, RKW_C_SGND, RKW_C_SIZOF, RKW_C_STTC, RKW_C_STRCT, RKW_C_SWTCH, RKW_C_TPDEF, RKW_C_UNION, RKW_C_USGND, RKW_C_VOID, RKW_C_VLTL, RKW_C_WHILE }; /* C language reserved type keywords ***********************************/ char *c_type_keywords[] = { RKW_C_BOOL, RKW_C_CMPLX, RKW_C_IMGNR, RKW_C_CHAR, RKW_C_DBL, RKW_C_FLOAT, RKW_C_INT, RKW_C_LONG, RKW_C_SHORT, RKW_C_VOID }; /* C++ language reserved keywords (without types) **********************/ char *cxx_keywords[] = { RKW_CXX_AND, RKW_CXX_ANDEQ, RKW_CXX_ASM, RKW_CXX_AUTO, RKW_CXX_BITAND, RKW_CXX_BITOR, RKW_CXX_BOOL, RKW_CXX_BREAK, RKW_CXX_CASE, RKW_CXX_CATCH, RKW_CXX_CHAR, RKW_CXX_CLASS, RKW_CXX_COMPL, RKW_CXX_CONST, RKW_CXX_CNSTCST, RKW_CXX_CONTN, RKW_CXX_DFLT, RKW_CXX_DELETE, RKW_CXX_DO, RKW_CXX_DBL, RKW_CXX_DYNCAST, RKW_CXX_ELSE, RKW_CXX_ENUM, RKW_CXX_EXPLI, RKW_CXX_EXPORT, RKW_CXX_EXTRN, RKW_CXX_FALSE, RKW_CXX_FLOAT, RKW_CXX_FOR, RKW_CXX_FRIEND, RKW_CXX_GOTO, RKW_CXX_IF, RKW_CXX_INLN, RKW_CXX_INT, RKW_CXX_LONG, RKW_CXX_MUTABL, RKW_CXX_NSPC, RKW_CXX_NEW, RKW_CXX_NOT, RKW_CXX_NOTEQ, RKW_CXX_OPER, RKW_CXX_OR, RKW_CXX_OREQ, RKW_CXX_PRIV, RKW_CXX_PROT, RKW_CXX_PUBLIC, RKW_CXX_RGSTR, RKW_CXX_RINTCST, RKW_CXX_RTRN, RKW_CXX_SHORT, RKW_CXX_SGND, RKW_CXX_SIZOF, RKW_CXX_STTC, RKW_CXX_STCCST, RKW_CXX_STRCT, RKW_CXX_SWTCH, RKW_CXX_TMPLT, RKW_CXX_THIS, RKW_CXX_THROW, RKW_CXX_TRUE, RKW_CXX_TRY, RKW_CXX_TYPEDEF, RKW_CXX_TYPEID, RKW_CXX_TYPENAM, RKW_CXX_UNION, RKW_CXX_USGND, RKW_CXX_USING, RKW_CXX_VIRT, RKW_CXX_VOID, RKW_CXX_VLTL, RKW_CXX_WCHART, RKW_CXX_WHILE, RKW_CXX_XOR, RKW_CXX_XOREQ }; size_t nb_cxx_keywords = sizeof(cxx_keywords) / sizeof(char *); /* C++ language reserved type keywords *********************************/ char *cxx_type_keywords[] = { RKW_CXX_BOOL, RKW_CXX_CHAR, RKW_CXX_DBL, RKW_CXX_FLOAT, RKW_CXX_INT, RKW_CXX_LONG, RKW_CXX_SHORT, RKW_CXX_VOID, RKW_CXX_WCHART }; size_t nb_cxx_type_keywords = sizeof(cxx_type_keywords) / sizeof(char *); /****************************** * assembly parsing functions * **********************************************************************/ /****************** * prs_asm_file() * *********************************************************************** DESCR C file parsing main function IN pcmn : common parsing structure fp : file to parse OUT boolean ***********************************************************************/ bool prs_asm_file(prs_cmn_t *pcmn, FILE *fp) { bool askw_flag = false; char idtf[MAX_IDTF_LEN]; unsigned int segtype = SEG_TYPE_UNKNW; prseng_t *ppe; #ifdef DEBUG_PRSC debugf("prs_asm_file() BEGIN"); #endif /* init prseng */ ppe = prseng_init(fp, NULL); if (ppe == NULL) { return(false); } /* while end of file is not reached */ while (prseng_eof(ppe) == false) { #ifdef DEBUG_PRSC debugf("cursor: '%.16s'", ppe->cur); #endif prs_c_skip(ppe); #ifdef DEBUG_PRSC debugf("cursor after skipping useless : '%.16s'", ppe->cur); #endif if (prseng_test_char(ppe, '#') == true) { /* parse preprocessing directive */ #ifdef DEBUG_PRSC debugf("found preprocessor directive: '%.16s'", ppe->cur); #endif prs_c_prepro(pcmn, ppe); continue; #ifdef DEBUG_PRSC } else { debugf("cursor is not '#'"); #endif } /* assembler keyword */ if (prseng_test_char(ppe, '.') == true) { /* mark as assembler directive */ askw_flag = true; #ifdef DEBUG_PRSC debugf("found assembler directive '%.16s'.", ppe->cur); #endif prseng_next_char(ppe); } prseng_get_idtf(ppe, idtf, sizeof(idtf), PRS_C_IDTF_STR); #ifdef DEBUG_PRSC debugf("found identifier : '%.16s'", idtf); #endif if (askw_flag == true) { /* check if the identifier is a keyword */ if (strncmp(idtf, RKW_AS_TSEG, strlen(idtf) + 1) == 0) { /* start of text segment */ segtype = SEG_TYPE_TEXT; #ifdef DEBUG_PRSC debugf("entered text section."); #endif } if (strncmp(idtf, RKW_AS_DSEG, strlen(idtf) + 1) == 0) { /* start of data segment */ segtype = SEG_TYPE_DATA; #ifdef DEBUG_PRSC debugf("entered data section."); #endif } askw_flag = false; } else { if ((segtype == SEG_TYPE_TEXT) && (prseng_test_char(ppe, ':') == true)) { #ifdef DEBUG_PRSC debugf("possible function declaration of '%s'", idtf); #endif /* => function call */ if (pcmn->func_decl != NULL) { if (pcmn->func_decl(pcmn->data, idtf, ppe) == false) { #ifdef DEBUG_PRSC debugf("prs_asm_file() END"); #endif return(false); } } } } /* skip until end of line */ prs_c_skip_to_char(ppe, '\n'); } #ifdef DEBUG_PRSC debugf("prs_asm_file() END"); #endif return(true); } /******************************** * C language parsing functions * **********************************************************************/ /************************ * prs_c_skip_to_char() * *********************************************************************** DESCR skip until a given char IN ppe : parsing engine structure c : delimiter character OUT boolean ***********************************************************************/ bool prs_c_skip_to_char(prseng_t *ppe, char c) { bool flag = false; /* check for end of line or end of file */ while ((prseng_eof(ppe) == false) && ((prseng_test_char(ppe, c) == false) || (flag == false))) { if (prseng_test_char(ppe, '\\') == true) { /* unset the flag to avoid stopping if newline is preceded by the '\' character */ flag = false; } else { /* else unset flag */ flag = true; } /* skip character */ if (prseng_next_char(ppe) == false) { return(false); } } if (prseng_test_char(ppe, c) == true) { /* skip given character */ if (prseng_next_char(ppe) == false) { return(false); } } return(true); } /********************* * prs_c_line_skip() * *********************************************************************** DESCR skip until end of file IN ppe : parsing engine structure OUT boolean ***********************************************************************/ bool prs_c_line_skip(prseng_t *ppe) { bool flag = false; /* check for end of line or end of file */ while ((prseng_eof(ppe) == false) && ((prseng_test_char(ppe, '\n') == false) || (flag == false))) { if (prseng_test_char(ppe, '\\') == true) { /* unset the flag to avoid stopping if newline is preceded by the '\' character */ flag = false; } else { /* else unset flag */ flag = true; } /* skip character */ if (prseng_next_char(ppe) == false) { return(false); } } if (prseng_test_char(ppe, '\n') == true) { /* skip newline */ if (prseng_next_char(ppe) == false) { return(false); } } return(true); } /************************ * prs_c_comment_skip() * *********************************************************************** DESCR skip C style comments IN ppe : parsing engine structure OUT boolean ***********************************************************************/ bool prs_c_comment_skip(prseng_t *ppe) { bool flag = false, loop = true; /* skip '/' character */ prseng_next_char(ppe); if (prseng_eof(ppe) == true) { /* XXX err msg unexpected eof */ return(false); } switch(prseng_get_char(ppe)) { case '*' : /* skip '*' character */ prseng_next_char(ppe); if (prseng_eof(ppe) == true) { /* XXX err msg unexpected eof */ return(false); } /* loop until end of comment is found */ while (loop == true) { if (flag == true) { if (prseng_test_char(ppe, '/') == true) { /* can exit from the loop after skipping this char */ loop = false; } else { /* else unset flag */ flag = false; } } if (prseng_test_char(ppe, '*') == true) { /* set flag to stop if the next char is '/' */ flag = true; } /* going to next char */ prseng_next_char(ppe); if (prseng_eof(ppe) == true) { /* XXX err msg unexpected eof */ return(false); } } break; case '/' : /* skip second '/' character */ prseng_next_char(ppe); if (prs_c_line_skip(ppe) == false) { return(false); } break; } return(true); } /*********************** * prs_c_squote_skip() * *********************************************************************** DESCR process simple quotes IN ppe : parsing engine structure OUT boolean ***********************************************************************/ bool prs_c_squote_skip(prseng_t *ppe) { /* skip starting quote */ prseng_next_char(ppe); if (prseng_eof(ppe) == true) { /* XXX err msg unexpected eof */ return(false); } /* if it's an escape character ... */ if (prseng_test_char(ppe, '\\') == true) { /* ... then skip it */ prseng_next_char(ppe); } if (prseng_eof(ppe) == true) { /* XXX err msg unexpected eof */ return(false); } /* skip quoted character */ prseng_next_char(ppe); if (prseng_eof(ppe) == true) { /* XXX err msg unexpected eof */ return(false); } if (prseng_test_char(ppe, '\'') == false) { /* XXX msg cannot found ending quote ! */ return(false); } /* skip ending quote */ prseng_next_char(ppe); return(true); } /*********************** * prs_c_dquote_skip() * *********************************************************************** DESCR process double quotes IN ppe : parsing engine structure OUT boolean ***********************************************************************/ bool prs_c_dquote_skip(prseng_t *ppe) { bool escape = false; /* skip starting double quote */ prseng_next_char(ppe); while ((prseng_test_char(ppe, '"') == false) || (escape == true)) { escape = false; #ifdef DEBUG_PRSC debugf("current char = %c", prseng_get_char(ppe)); #endif if (prseng_eof(ppe) == true) { /* XXX msg cannot find ending double quote ! */ return(false); } if (prseng_test_char(ppe, '\\') == true) { escape = true; } prseng_next_char(ppe); } /* skip ending double quote */ prseng_next_char(ppe); return(true); } /**************** * prs_c_skip() * *********************************************************************** DESCR skip useless stuff like spaces, tabs, newlines and comments IN ppe : parsing engine structure OUT boolean ***********************************************************************/ bool prs_c_skip(prseng_t *ppe) { bool do_exit = false; #ifdef DEBUG_PRSC /*debugf("prs_c_skip() : start");*/ #endif while (do_exit == false) { #ifdef DEBUG_PRSC /*debugf("prs_c_skip() : char number is %d", (int) prseng_get_char(ppe));*/ #endif switch(prseng_get_char(ppe)) { case ' ' : case '\t' : case '\n' : case '\f' : case 13 : /* skip character */ prseng_next_char(ppe); break; case '/' : /* comment ? */ if (prs_c_comment_skip(ppe) == false) { return(false); } break; default: do_exit = true; } } #ifdef DEBUG_PRSC /*debugf("prs_c_skip() : stop");*/ #endif return(true); } /****************** * prs_c_prepro() * *********************************************************************** DESCR handle preprocesor directives IN pcmn : common parsing structure ppe : parsing engine structure OUT boolean ***********************************************************************/ bool prs_c_prepro(prs_cmn_t *pcmn, prseng_t *ppe) { char pp_idtf[MAX_IDTF_LEN]; /* skip leading '#' character */ prseng_next_char(ppe); if (prseng_eof(ppe) == true) { /* XXX err msg unexpected eof */ return(false); } if (pcmn->func_ppro != NULL) { /* process directive with a call to pcmn->func_ppro() */ prseng_get_idtf(ppe, pp_idtf, sizeof(pp_idtf), PRS_C_IDTF_STR); pcmn->func_ppro(pcmn->data, pp_idtf, ppe); } else { /* skip directive */ if (prs_c_line_skip(ppe) == false) { return(false); } } return(true); } /***************** * prs_c_is_kw() * *********************************************************************** DESCR check if identifier is a keyword IN XXX OUT boolean ***********************************************************************/ bool prs_c_is_kw(char *idtf, char **kw, size_t nbkw) { size_t i, s; /* get the size of the identifier */ s = strlen(idtf) + 1; /* loop into the list of keywords */ for (i = 0 ; i < nbkw ; i++) { if (strncmp(idtf, kw[i], s) == 0) { /* and return true if one matches */ return(true); } } /* not a known C keyword */ return(false); } /**************** * prs_c_file() * *********************************************************************** DESCR C file parsing main function IN pcmn : common parsing structure fp : file to parse OUT boolean ***********************************************************************/ bool prs_c_file(prs_cmn_t *pcmn, FILE *fp) { return(prs_c_common(pcmn, fp, c_keywords, c_type_keywords)); } /****************** * prs_cxx_file() * *********************************************************************** DESCR C file parsing main function IN pcmn : common parsing structure fp : file to parse OUT boolean ***********************************************************************/ bool prs_cxx_file(prs_cmn_t *pcmn, FILE *fp) { return(prs_c_common(pcmn, fp, cxx_keywords, cxx_type_keywords)); } /****************** * prs_c_common() * *********************************************************************** DESCR C file parsing main function IN pcmn : common parsing structure fp : file to parse lkw : language keywords nb_lkw : number of language keywords OUT boolean ***********************************************************************/ bool prs_c_common(prs_cmn_t *pcmn, FILE *fp, char **lkw, char **tkw) { bool idtf_flag = false, type_flag = false; char idtf[MAX_IDTF_LEN], type[MAX_IDTF_LEN]; prseng_t *ppe; size_t nb_lkw, nb_tkw; /* compute keyword array size */ nb_lkw = sizeof(lkw) / sizeof(char *); nb_tkw = sizeof(tkw) / sizeof(char *); /* init prseng */ ppe = prseng_init(fp, NULL); if (ppe == NULL) { errorf("parse engine init failed."); return(false); } /* while end of file is not reached */ while (prseng_eof(ppe) == false) { #ifdef DEBUG_PRSC /*debugf("cursor: '%.16s'", ppe->cur);*/ #endif prs_c_skip(ppe); #ifdef DEBUG_PRSC debugf("cursor after skipping useless : '%.16s'", ppe->cur); #endif if (prseng_test_char(ppe, '#') == true) { /* parse preprocessing directive */ prs_c_prepro(pcmn, ppe); continue; #ifdef DEBUG_PRSC } else { debugf("cursor is not '#'"); #endif } if (prseng_test_char(ppe, '(') == true) { if (idtf_flag == true) { if (type_flag == true) { #ifdef DEBUG_PRSC debugf("possible function declaration of '%s'", idtf); #endif /* if an identifier flag is on => function call */ if (pcmn->func_decl != NULL) { if (pcmn->func_decl(pcmn->data, idtf, ppe) == false) { errorf("error in processing of function declarator."); return(false); } } } else { #ifdef DEBUG_PRSC debugf("possible function call of '%s'", idtf); #endif /* if an identifier flag is on => function call */ if (pcmn->func_proc != NULL) { if (pcmn->func_proc(pcmn->data, idtf, ppe) == false) { errorf("error in processing of function call."); return(false); } } } idtf_flag = false; } /* skip character */ prseng_next_char(ppe); continue; #ifdef DEBUG_PRSC } else { debugf("cursor is not '('"); #endif } if (prseng_test_char(ppe, '*') == true) { if (idtf_flag == true) { /* if the idtf flag is on => type identifier */ #ifdef DEBUG_PRSC debugf("possible type identifier '%s'", idtf); #endif /* processing, call to pcmn->func_type */ if (pcmn->func_type(pcmn->data, idtf, ppe) == false) { errorf("error in processing of type."); return(false); } idtf_flag = false; type_flag = true; } /* skip character */ prseng_next_char(ppe); continue; #ifdef DEBUG_PRSC } else { debugf("cursor is not '*'"); #endif } if (prseng_test_char(ppe, '[') == true) { if (type_flag == true) { /* if a type flag is on => type identifier */ #ifdef DEBUG_PRSC debugf("possible type identifier '%s'", type); #endif /* processing, call to pcmn->func_type */ if (pcmn->func_type(pcmn->data, idtf, ppe) == false) { errorf("error in processing of type."); return(false); } type_flag = false; } /* skip character */ prseng_next_char(ppe); continue; #ifdef DEBUG_PRSC } else { debugf("cursor is not '['"); #endif } if (prseng_test_char(ppe, '"') == true) { if (prs_c_dquote_skip(ppe) == false) { return(false); } continue; #ifdef DEBUG_PRSC } else { debugf("cursor is not '\"'"); #endif } if (prseng_test_char(ppe, '\'') == true) { if (prs_c_squote_skip(ppe) == false) { return(false); } continue; #ifdef DEBUG_PRSC } else { debugf("cursor is not '\''"); #endif } /* if it's a misc char ... */ if (prseng_test_idtf_char(PRS_C_MISC_STR, prseng_get_char(ppe)) == true) { #ifdef DEBUG_PRSC debugf("cursor '%.16s is a misc char", ppe->cur); #endif /* clear flags */ idtf_flag = false; /* XXX here idtf could contain a constant */ type_flag = false; /* skip character */ prseng_next_char(ppe); continue; #ifdef DEBUG_PRSC } else { debugf("cursor is not a misc char"); #endif } if (idtf_flag == true) { /* save previous idtf as it could be a type */ strlcpy(type, idtf, sizeof(type)); /* no check needed */ #ifdef DEBUG_PRSC debugf("save type identifier '%s'", type); #endif idtf_flag = false; type_flag = true; } prseng_get_idtf(ppe, idtf, sizeof(idtf), PRS_C_IDTF_STR); #ifdef DEBUG_PRSC debugf("found identifier '%s'", idtf); #endif if (idtf[0] == '\0') { if (prseng_eof(ppe) == true) { #ifdef DEBUG_PRSC debugf("normal end of parsing"); #endif return(true); } else { #ifdef DEBUG_PRSC debugf("problem with '%d'", prseng_get_char(ppe)); #endif return(false); } } /* check if the identifier is a type keyword */ if (prs_c_is_kw(idtf, tkw, nb_tkw) == true) { /* if yes then we have to mark this identifier */ type_flag = true; #ifdef DEBUG_PRSC debugf("skipped type keyword '%s'", idtf); #endif continue; } /* check if the identifier is a keyword */ if (prs_c_is_kw(idtf, lkw, nb_lkw) == false) { /* if not then we have to mark this identifier */ idtf_flag = true; #ifdef DEBUG_PRSC } else { debugf("skipped keyword '%s'", idtf); #endif } } prseng_destroy(ppe); return(true); } /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/hash.c010064400017500000000000000531651040066543300123470ustar00mipswheel/* $Id: hash.c 1541 2006-02-27 21:11:55Z mipsator $ */ /* * 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 : * - Marek Habersack */ /******************************************************************* * * * Hash-coding functions * * * *******************************************************************/ #include #include "hash.h" #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" /*#define HASH_DEBUG 1*/ #ifdef HASH_DEBUG #include "common.h" #endif /****************** * hash_compute() * *********************************************************************** DESCR compute hash (perfect hashing) IN key : key string OUT resulting hash ***********************************************************************/ unsigned int hash_compute(char *key, size_t table_size) { unsigned int len = 0, hash = 0; unsigned char c; c = *key; while (c != '\0') { /* sum all characters with modulo */ hash = (hash + (int) c) % table_size; c = *key; key++; len++; } /* add the len always with modulo */ hash = (hash + len) % table_size; return(hash); } /*************** * hash_init() * *********************************************************************** DESCR init hash structure of character strings IN table_size : number of hash elements OUT a pointer to the hash structure ***********************************************************************/ htable *hash_init(size_t table_size) { return(hash_init_adv(table_size, (void *(*)(void *))strdup, free, hash_str_append)); } /******************* * hash_init_adv() * *********************************************************************** DESCR init hash structure of objects IN table_size : number of hash elements dupfunc : function to duplicate an object freefunc : function to free an object appdfunc : function to create appended object OUT a pointer to the hash structure NOTE append function will have three arguments (original object, value to append, misc data) and will return the resulting object (see hash_append_str for an example). ***********************************************************************/ htable *hash_init_adv(size_t table_size, void *(*dupfunc)(void *), void (*freefunc)(void *), void *(*appdfunc)(void *, void *, void *)) { htable *pht; hnode *phn; size_t i; /* allocate hash table */ pht = (htable *) malloc(sizeof(htable)); if (pht != NULL) { /* allocate node table */ phn = (hnode *) malloc(sizeof(hnode) * table_size); if (phn == NULL) { /* allocation failed then deallocate and return NULL */ free(pht); return(NULL); } } else { /* allocation failed, return NULL */ return(NULL); } for(i = 0 ; i < table_size ; i++) { phn[i].first = NULL; phn[i].last = NULL; } /* finish init */ pht->size = table_size; pht->count = 0; pht->autogrow = false; /* disabled by default */ pht->dupobj = dupfunc; pht->freeobj = freefunc; pht->appdobj = appdfunc; pht->nodetab = phn; return(pht); } /***************** * hash_resize() * *********************************************************************** DESCR resizing hash table IN ht : hash table to resize newsize : new size OUT boolean ***********************************************************************/ bool hash_resize(htable *ht, size_t newsize) { hcell *phc, *next; hnode *newhn; size_t c = 0, i; unsigned int h; /* allocate new node table */ newhn = (hnode *) malloc(sizeof(hnode) * newsize); if (newhn == NULL) return(false); /* init */ for (i = 0 ; i < newsize ; i++) { newhn[i].first = NULL; newhn[i].last = NULL; } for (i = 0 ; i < ht->size ; i++) { phc = ht->nodetab[i].first; while (phc != NULL) { h = hash_compute(phc->key, newsize); next = phc->next; hash_add_cell(&newhn[h], phc); phc = next; c++; } } free(ht->nodetab); ht->nodetab = newhn; ht->size = newsize; return(true); } /******************* * hash_set_grow() * *********************************************************************** DESCR set hash table as automatically resizable IN ht : hash table to set OUT - ***********************************************************************/ void hash_set_grow(htable *ht) { ht->autogrow = true; } /****************** * hash_destroy() * *********************************************************************** DESCR destroy hash table IN pht : hash table to remove OUT number of keys deleted ***********************************************************************/ size_t hash_destroy(htable *pht) { hcell *p, *t; size_t s, c = 0; unsigned int i; if (pht == NULL) return(0); s = pht->size; for(i = 0 ; i < s ; i++) { p = pht->nodetab[i].first; t = NULL; while (p != NULL) { t = p->next; hash_free_hcell(pht, p); c++; /* removed one more key */ p = t; } } free(pht->nodetab); free(pht); pht = NULL; return(c); } /************** * hash_add() * *********************************************************************** DESCR add a key in the hash table IN pht : hash structure key : key string value : value object OUT return an error code HASH_ADD_FAIL : addition failed. HASH_ADD_OKAY : added (no collision). HASH_ADD_COLL : added (collision, key chained). HASH_ADD_UPDT : key already exists, change value. ***********************************************************************/ unsigned int hash_add(htable *pht, char *key, void *value) { return(hash_update(pht, key, value)); } /***************** * hash_update() * *********************************************************************** DESCR update or add a key in the hash table IN pht : hash structure key : key string value : value object OUT return an error code HASH_ADD_FAIL : addition failed. HASH_ADD_OKAY : added (no collision). HASH_ADD_COLL : added (collision, key chained). HASH_ADD_UPDT : key already exists, change value. ***********************************************************************/ unsigned int hash_update(htable *pht, char *key, void *value) { unsigned int hash, rval; hnode *phn; hcell *phc = NULL; size_t size; rval = HASH_ADD_FAIL; size = pht->size; /* test remaing free cells */ if (pht->count >= size) { /* number of cell is higher than the supposed table size */ if (pht->autogrow == false) { /* fixed size */ return(HASH_ADD_FAIL); } else { /* resize the hash table (long) */ if (hash_resize(pht, size * 2) == false) { /* cannot resize the hash */ return(HASH_ADD_FAIL); } } } phc = (hcell *) malloc(sizeof(hcell)); if (phc == NULL) return(rval); /* if okay put key & value in a new cell */ if (strlcpy_b(phc->key, key, sizeof(phc->key)) == false) { hash_free_hcell(pht, phc); return(HASH_ADD_FAIL); } phc->value = value; /* compute hash code */ hash = hash_compute(key, size); phn = &pht->nodetab[hash]; rval = hash_add_cell(phn, phc); if (rval == HASH_ADD_OKAY || rval == HASH_ADD_COLL) pht->count++; return(rval); } /********************* * hash_update_dup() * *********************************************************************** DESCR update or add a key in the hash table but duplicate the value IN pht : hash structure key : key string value : value object OUT return an error code HASH_ADD_FAIL : addition failed. HASH_ADD_OKAY : added (no collision). HASH_ADD_COLL : added (collision, key chained). HASH_ADD_UPDT : key already exists, change value. ***********************************************************************/ unsigned int hash_update_dup(htable *pht, char *key, void *value) { return(hash_update(pht, key, pht->dupobj(value))); } /******************* * hash_add_cell() * *********************************************************************** DESCR add a new cell in a node IN phn : storage node phc : cell to add OUT return an error code HASH_ADD_OKAY : added (no collision). HASH_ADD_COLL : added (collision, key chained). HASH_ADD_UPDT : key already exists, change value. NOTE this function does not increment the cell number of the hash table. ***********************************************************************/ unsigned int hash_add_cell(hnode *phn, hcell *phc) { hcell *np; phc->next = NULL; if (phn->first == NULL) { /* hash code unused */ phn->first = phc; phn->last = phc; return(HASH_ADD_OKAY); } else { /* collision, hash code already used */ np = phn->first; /* looking for last element */ while (1) { if (strncmp(phc->key, np->key, sizeof(phc->key)) == 0) { /* key already exists */ np->value = phc->value; phc->value = NULL; /* XXX useless ??? */ /* new cell no longer needed, free struct only */ free(phc); return(HASH_ADD_UPDT); } else { if (np->next == NULL) { /* last element found */ phn->last = phc; /* chaining new cell */ np->next = phc; return(HASH_ADD_COLL); } else { np = np->next; } } } } } /******************** * hash_add_array() * *********************************************************************** DESCR add an array into the hash table IN ht : storage hash table ary : array to add size : size of the array OUT boolean ***********************************************************************/ bool hash_add_array(htable *pht, hpair *php, size_t size) { return(hash_add_array_adv(pht, php, size, (void *(*)(void *)) strdup)); } /************************ * hash_add_array_adv() * *********************************************************************** DESCR add an array into the hash table IN ht : storage hash table ary : array to add size : size of the array dup_func : object duplication function OUT boolean ***********************************************************************/ bool hash_add_array_adv(htable *pht, hpair *php, size_t size, void *(dupfunc)(void *)) { bool error = false, rval = false; htable *pmht; unsigned int i; pmht = hash_init(size); if (pmht == NULL) return(false); for (i = 0 ; (i < size) && (error == false) ; i ++) { if (hash_add(pmht, php[i].key, dupfunc(php[i].value)) == HASH_ADD_FAIL) error = true; } if (error == false) { hash_merge(pht, pmht); rval = true; } hash_destroy(pmht); return(rval); } /***************** * hash_append() * *********************************************************************** DESCR append a value to the existing value IN pht : hash structure key : key to be appended value : value to append misc : extra data to transmit to append function OUT return an error code. HASH_ADD_OKAY : added (no collision). HASH_ADD_COLL : added (collision, key chained). HASH_ADD_UPDT : key already exists, change value. ***********************************************************************/ unsigned int hash_append(htable *pht, char *key, void *value, void *misc) { unsigned int rval; void *pobj, *robj; if (value == NULL) { #ifdef HASH_DEBUG debugf("hash_append : value is null"); #endif return(HASH_ADD_FAIL); } if (pht->appdobj == NULL) { #ifdef HASH_DEBUG debugf("hash_append : appobj is null"); #endif return(HASH_ADD_FAIL); } pobj = hash_get(pht, key); if (pobj == NULL) { /* no previous value, adding given data */ rval = hash_add(pht, key, value); } else { robj = pht->appdobj(pobj, value, misc); if (robj != NULL) { rval = hash_add(pht, key, robj); if (rval == HASH_ADD_UPDT) rval = HASH_ADD_APPD; /* not an update as we append */ } else { #ifdef HASH_DEBUG debugf("hash_append : robj is null"); #endif rval = HASH_ADD_FAIL; } } return(rval); } /***************** * hash_delete() * *********************************************************************** DESCR remove a key from the hash table IN pht : hash table key : key to search OUT - ***********************************************************************/ void hash_delete(htable *pht, char *key) { hcell *phc, *last; unsigned int hash; /* compute hash code */ hash = hash_compute(key, pht->size); phc = pht->nodetab[hash].first; last = NULL; while (phc != NULL) { /* hash not empty */ if (strncmp(key, phc->key, MAX_HASH_KEY_LEN) == 0) { /* found key */ if (last == NULL) { /* first cell */ if (phc->next == NULL) { /* only one cell */ pht->nodetab[hash].first = NULL; pht->nodetab[hash].last = NULL; } else { /* re-link with next cell */ pht->nodetab[hash].first = phc->next; } } else { last->next = phc->next; if (phc->next == NULL) { /* delete last cell, update node */ pht->nodetab[hash].last = last; } } hash_free_hcell(pht, phc); phc = NULL; pht->count--; } else { /* go to next cell */ last = phc; phc = phc->next; } } /* key not found */ } /****************** * hash_extract() * *********************************************************************** DESCR remove a key from the hash table IN pht : hash table key : key to search OUT - ***********************************************************************/ void *hash_extract(htable *pht, char *key) { hcell *phc, *last; unsigned int hash; void *data = NULL; /* compute hash code */ hash = hash_compute(key, pht->size); phc = pht->nodetab[hash].first; last = NULL; while (phc != NULL) { /* hash not empty */ if (strncmp(key, phc->key, MAX_HASH_KEY_LEN) == 0) { /* found key */ if (last == NULL) { /* first cell */ if (phc->next == NULL) { /* only one cell */ pht->nodetab[hash].first = NULL; pht->nodetab[hash].last = NULL; } else { /* re-link with next cell */ pht->nodetab[hash].first = phc->next; } } else { last->next = phc->next; if (phc->next == NULL) { /* delete last cell, update node */ pht->nodetab[hash].last = last; } } data = phc->value; phc->value = NULL; hash_free_hcell(pht, phc); pht->count--; break; } else { /* go to next cell */ last = phc; phc = phc->next; } } /* key not found */ return(data); } /************** * hash_get() * *********************************************************************** DESCR get a key from the hash table IN pht : hash table key : key to search OUT return the value or NULL ***********************************************************************/ void *hash_get(htable *pht, char *key) { hcell *phc; unsigned int hash; /* compute hash code */ hash = hash_compute(key, pht->size); phc = pht->nodetab[hash].first; while (phc != NULL) { /* hash not empty */ #ifdef HASH_DEBUG debugf("hash_get : comparing with '%s'", phc->key); #endif if (strncmp(key, phc->key, MAX_HASH_KEY_LEN) == 0) { /* found key, return pointer on value */ return(phc->value); } else { /* go to next cell */ phc = phc->next; } } /* key not found */ return(NULL); } /**************** * hash_merge() * *********************************************************************** DESCR merge one hash table into another IN dst_ht : destination table src_ht : table to merge OUT number of merged key ***********************************************************************/ size_t hash_merge(htable *dst_ht, htable *src_ht) { hcell *p; size_t s, c = 0; unsigned int i; /* get table size */ s = src_ht->size; for(i = 0 ; i < s ; i++) { p = src_ht->nodetab[i].first; while (p != NULL) { /* add the key in dst_ht */ if (hash_add(dst_ht, p->key, p->value) != HASH_ADD_FAIL) { /* merged one more key */ c++; /* unset p->value to prevent deletion */ p->value = NULL; } p = p->next; } } /* return count of merged keys */ return(c); } /**************** * hash_nbkey() * *********************************************************************** DESCR get number of keys IN pht : hash table OUT number of keys ***********************************************************************/ size_t hash_nbkey(htable *pht) { return(pht->count); } /*************** * hash_keys() * *********************************************************************** DESCR get the keys of the hash table IN pht : hash table OUT hkeys structure NOTE don't forget to free the array after use. ***********************************************************************/ hkeys *hash_keys(htable *pht) { hcell *p; hkeys *phk; unsigned int i, j = 0; /* init hkeys struct to be returned */ phk = (hkeys *)malloc(sizeof(hkeys)); if (phk != NULL) { if (pht->count == 0) return(NULL); phk->nkey = pht->count; /* create an array with a size of the number of keys */ phk->keys = (char **)malloc(sizeof(char *) * phk->nkey); if (phk->keys != NULL) { for(i = 0 ; i < pht->size ; i++) { p = pht->nodetab[i].first; while (p != NULL) { /* add the key in key_ary */ phk->keys[j] = p->key; j++; p = p->next; } } return(phk); } else { #ifdef HASH_DEBUG debugf("keys alloc failed"); #endif /* free allocated space only */ free(phk); } #ifdef HASH_DEBUG } else { debugf("hkeys struct alloc failed"); #endif } return(NULL); } /********************** * hash_keys_sorted() * *********************************************************************** DESCR get the sorted list of keys of the hash table IN pht : hash table OUT return an hkeys structure NOTE don't forget to free the array after use ***********************************************************************/ static int hash_strcmp(const void *a, const void *b) { return(strcmp(*(char * const *)a, *(char * const *) b)); } hkeys *hash_keys_sorted(htable *pht) { hkeys *phk; /* build hkey structure */ phk = hash_keys(pht); if (phk != NULL) { /* sort key names */ qsort((void *) phk->keys, phk->nkey, sizeof(char *), hash_strcmp); } return(phk); } /********************* * hash_free_hcell() * *********************************************************************** DESCR free memory allocated to the hcell structure IN phc : structure to free OUT - ***********************************************************************/ void hash_free_hcell(htable *pht, hcell *phc) { if (phc != NULL) { if (phc->value != NULL) { if (pht->freeobj != NULL) #ifdef HASH_DEBUG debugf("free phcell '%s' data", phc->key); #endif pht->freeobj(phc->value); } #ifdef HASH_DEBUG debugf("free phcell '%s'", phc->key); #endif free(phc); } } /********************* * hash_free_hkeys() * *********************************************************************** DESCR free memory allocated to the hkeys structure IN phk : structure to free OUT - ***********************************************************************/ void hash_free_hkeys(hkeys *phk) { /* doesn't free pointed values */ free(phk->keys); free(phk); } /********************* * hash_str_append() * *********************************************************************** DESCR append function for string hash IN orig : XXX value : XXX sep : XXX OUT - ***********************************************************************/ void *hash_str_append(void *orig, void *value, void *sep) { char *pbuf; size_t s; /* compute needed space */ if (sep != NULL) { s = strlen((char *) sep); } else { s = 0; } s = s + strlen((char *) orig) + strlen((char *) value) + 1; /* allocate space */ pbuf = (char *) malloc(s); if (strlcpy_b(pbuf, orig, s) == false) { free(value); free(pbuf); #ifdef HASH_DEBUG debugf("hash_str_append : strlcpy1 failed"); #endif return(NULL); } if ((sep != NULL) && (pbuf[0] != '\0')) { /* adding separator if provided and if string is not empty */ if (strlcat_b(pbuf, (char *) sep, s) == false) { free(value); free(pbuf); #ifdef HASH_DEBUG debugf("hash_str_append : strlcat1 failed"); #endif return(NULL); } } if (strlcat_b(pbuf, value, s) == false) { free(value); free(pbuf); #ifdef HASH_DEBUG debugf("hash_str_append : strlcat2 failed"); #endif return(NULL); } free(value); return((void *) pbuf); } /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/parse_lang.h010075500017500000000000000217011034764133300135410ustar00mipswheel/* $Id: parse_lang.h 1520 2005-12-13 21:53:31Z mipsator $ */ /* * Copyright (c) 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. * */ #include "prseng.h" /*#define DEBUG_PRSENG 1*/ /********** constants ***********************************************************************/ /* Preprocessor keywords */ #define RKW_PP_DEF "define" #define RKW_PP_ELIF "elif" #define RKW_PP_ELSE "else" #define RKW_PP_ENDF "endif" #define RKW_PP_ERR "error" #define RKW_PP_IF "if" #define RKW_PP_IFDF "ifdef" #define RKW_PP_IFND "ifndef" #define RKW_PP_INCL "include" #define RKW_PP_LINE "line" #define RKW_PP_PRGM "pragma" #define RKW_PP_UDEF "undef" /* assembler directives */ #define RKW_AS_TSEG "text" #define RKW_AS_DSEG "data" /* C keywords */ #define RKW_C_BOOL "_Bool" /* ISO C99 */ #define RKW_C_CMPLX "_Complex" /* ISO C?? *//* XXX */ #define RKW_C_IMGNR "_Imaginary" /* ISO C?? *//* XXX */ #define RKW_C_AUTO "auto" /* ISO C?? *//* XXX */ #define RKW_C_BREAK "break" /* ISO C90 */ #define RKW_C_CASE "case" /* ISO C90 */ #define RKW_C_CHAR "char" /* ISO C90 */ #define RKW_C_CONST "const" /* ISO C90 */ #define RKW_C_CONTN "continue" /* ISO C90 */ #define RKW_C_DFLT "default" /* ISO C90 */ #define RKW_C_DO "do" /* ISO C90 */ #define RKW_C_DBL "double" /* ISO C90 */ #define RKW_C_ELSE "else" /* ISO C90 */ #define RKW_C_ENUM "enum" /* ISO C90 */ #define RKW_C_EXTRN "extern" /* ISO C90 */ #define RKW_C_FLOAT "float" /* ISO C90 */ #define RKW_C_FOR "for" /* ISO C90 */ #define RKW_C_GOTO "goto" /* ISO C90 */ #define RKW_C_IF "if" /* ISO C90 */ #define RKW_C_INLN "inline" /* ISO C?? *//* XXX */ #define RKW_C_INT "int" /* ISO C90 */ #define RKW_C_LONG "long" /* ISO C90 */ #define RKW_C_RGSTR "register" /* ISO C90 */ #define RKW_C_RSTCT "restrict" /* ISO C99 *//* XXX */ #define RKW_C_RTRN "return" /* ISO C90 */ #define RKW_C_SHORT "short" /* ISO C90 */ #define RKW_C_SGND "signed" /* ISO C90 */ #define RKW_C_SIZOF "sizeof" /* ISO C90 */ #define RKW_C_STTC "static" /* ISO C90 */ #define RKW_C_STRCT "struct" /* ISO C90 */ #define RKW_C_SWTCH "switch" /* ISO C90 */ #define RKW_C_TPDEF "typedef" /* ISO C90 */ #define RKW_C_UNION "union" /* ISO C90 */ #define RKW_C_USGND "unsigned" /* ISO C90 */ #define RKW_C_VOID "void" /* ISO C90 */ #define RKW_C_VLTL "volatile" /* ISO C?? *//* XXX */ #define RKW_C_WHILE "while" /* ISO C90 */ /* C++ extra keywords */ #define RKW_CXX_AND "and" /* ISO C++98 */ #define RKW_CXX_ANDEQ "and_eq" /* ISO C++98 */ #define RKW_CXX_ASM "asm" /* ISO C++98 */ #define RKW_CXX_AUTO "auto" /* ISO C++98 */ #define RKW_CXX_BITAND "bitand" /* ISO C++98 */ #define RKW_CXX_BITOR "bitor" /* ISO C++98 */ #define RKW_CXX_BOOL "bool" /* ISO C++98 */ #define RKW_CXX_BREAK "break" /* ISO C++98 */ #define RKW_CXX_CASE "case" /* ISO C++98 */ #define RKW_CXX_CATCH "catch" /* ISO C++98 */ #define RKW_CXX_CHAR "char" /* ISO C++98 */ #define RKW_CXX_CLASS "class" /* ISO C++98 */ #define RKW_CXX_COMPL "compl" /* ISO C++98 */ #define RKW_CXX_CONST "const" /* ISO C++98 */ #define RKW_CXX_CNSTCST "const_cast" /* ISO C++98 */ #define RKW_CXX_CONTN "continue" /* ISO C++98 */ #define RKW_CXX_DFLT "default" /* ISO C++98 */ #define RKW_CXX_DELETE "delete" /* ISO C++98 */ #define RKW_CXX_DO "do" /* ISO C++98 */ #define RKW_CXX_DBL "double" /* ISO C++98 */ #define RKW_CXX_DYNCAST "dynamic_cast" /* ISO C++98 */ #define RKW_CXX_ELSE "else" /* ISO C++98 */ #define RKW_CXX_ENUM "enum" /* ISO C++98 */ #define RKW_CXX_EXPLI "explicit" /* ISO C++98 */ #define RKW_CXX_EXPORT "export" /* ISO C++98 */ #define RKW_CXX_EXTRN "extern" /* ISO C++98 */ #define RKW_CXX_FALSE "false" /* ISO C++98 */ #define RKW_CXX_FLOAT "float" /* ISO C++98 */ #define RKW_CXX_FOR "for" /* ISO C++98 */ #define RKW_CXX_FRIEND "friend" /* ISO C++98 */ #define RKW_CXX_GOTO "goto" /* ISO C++98 */ #define RKW_CXX_IF "if" /* ISO C++98 */ #define RKW_CXX_INLN "inline" /* ISO C++98 */ #define RKW_CXX_INT "int" /* ISO C++98 */ #define RKW_CXX_LONG "long" /* ISO C++98 */ #define RKW_CXX_MUTABL "mutable" /* ISO C++98 */ #define RKW_CXX_NSPC "namespace" /* ISO C++98 */ #define RKW_CXX_NEW "new" /* ISO C++98 */ #define RKW_CXX_NOT "not" /* ISO C++98 */ #define RKW_CXX_NOTEQ "not_eq" /* ISO C++98 */ #define RKW_CXX_OPER "operator" /* ISO C++98 */ #define RKW_CXX_OR "or" /* ISO C++98 */ #define RKW_CXX_OREQ "or_eq" /* ISO C++98 */ #define RKW_CXX_PRIV "private" /* ISO C++98 */ #define RKW_CXX_PROT "protected" /* ISO C++98 */ #define RKW_CXX_PUBLIC "public" /* ISO C++98 */ #define RKW_CXX_RGSTR "register" /* ISO C++98 */ #define RKW_CXX_RINTCST "reinterpret_cast" /* ISO C++98 */ #define RKW_CXX_RTRN "return" /* ISO C++98 */ #define RKW_CXX_SHORT "short" /* ISO C++98 */ #define RKW_CXX_SGND "signed" /* ISO C++98 */ #define RKW_CXX_SIZOF "sizeof" /* ISO C++98 */ #define RKW_CXX_STTC "static" /* ISO C++98 */ #define RKW_CXX_STCCST "static_cast" /* ISO C++98 */ #define RKW_CXX_STRCT "struct" /* ISO C++98 */ #define RKW_CXX_SWTCH "switch" /* ISO C++98 */ #define RKW_CXX_TMPLT "template" /* ISO C++98 */ #define RKW_CXX_THIS "this" /* ISO C++98 */ #define RKW_CXX_THROW "throw" /* ISO C++98 */ #define RKW_CXX_TRUE "true" /* ISO C++98 */ #define RKW_CXX_TRY "try" /* ISO C++98 */ #define RKW_CXX_TYPEDEF "typedef" /* ISO C++98 */ #define RKW_CXX_TYPEID "typeid" /* ISO C++98 */ #define RKW_CXX_TYPENAM "typename" /* ISO C++98 */ #define RKW_CXX_UNION "union" /* ISO C++98 */ #define RKW_CXX_USGND "unsigned" /* ISO C++98 */ #define RKW_CXX_USING "using" /* ISO C++98 */ #define RKW_CXX_VIRT "virtual" /* ISO C++98 */ #define RKW_CXX_VOID "void" /* ISO C++98 */ #define RKW_CXX_VLTL "volatile" /* ISO C++98 */ #define RKW_CXX_WCHART "wchar_t" /* ISO C++98 */ #define RKW_CXX_WHILE "while" /* ISO C++98 */ #define RKW_CXX_XOR "xor" /* ISO C++98 */ #define RKW_CXX_XOREQ "xor_req" /* ISO C++98 */ #define MAX_IDTF_LEN 64 /* maximum length of an identifier *//* XXX enough ??? */ enum { SEG_TYPE_UNKNW = 0, SEG_TYPE_TEXT, SEG_TYPE_DATA }; #define PRS_C_IDTF_STR "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" #define PRS_C_IDTF_FNAME PRS_C_IDTF_STR "./" #define PRS_C_MISC_STR "]){}<>&|!?:;,=+-*/%.^~\\" /********************* types and structures ***********************************************************************/ typedef struct { bool strict, /* stop on errors when true */ (*func_ppro)(void *, char *, prseng_t *), /* function to call on preprocessor keyword */ (*func_proc)(void *, char *, prseng_t *), /* function called on procedure identifier */ (*func_decl)(void *, char *, prseng_t *), /* function called on procedure declaration */ (*func_type)(void *, char *, prseng_t *); /* function called on type identifier */ void *data; /* data structure provided to the functions */ } prs_cmn_t; /******************** function prototypes ***********************************************************************/ bool prs_asm_file(prs_cmn_t *, FILE *); bool prs_c_skip_to_char(prseng_t *, char); bool prs_c_line_skip(prseng_t *); bool prs_c_comment_skip(prseng_t *); bool prs_c_squote_skip(prseng_t *); bool prs_c_dquote_skip(prseng_t *); bool prs_c_skip(prseng_t *); bool prs_c_prepro(prs_cmn_t *, prseng_t *); bool prs_c_is_kw(char *, char **, size_t); bool prs_c_file(prs_cmn_t *, FILE *); bool prs_cxx_file(prs_cmn_t *, FILE *); bool prs_c_common(prs_cmn_t *, FILE *, char **, char **); pmk-0.10.4/pmkinstall.c010064400017500000000000000321461030204026600135660ustar00mipswheel/* $Id: pmkinstall.c 1462 2005-08-21 08:52:06Z mipsator $ */ /* * 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. * */ #include /* include it first as if it was - this will avoid errors */ #include "compat/pmk_sys_types.h" #include #include #include #include #include #include "compat/pmk_ctype.h" #include "compat/pmk_libgen.h" #include "compat/pmk_stdbool.h" #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "compat/pmk_unistd.h" #include "common.h" #include "pathtools.h" #include "pmkinstall.h" #include "premake.h" /*#define INST_DEBUG 1*/ extern char *optarg; extern int optind; #ifndef errno extern int errno; #endif char *bsfx = DEFAULT_BACKUP_SFX; /* backup extension */ /* strip file : file to strip return : nothing at the moment :) NOTE: could use BIN_STRIP from pmk.conf */ void strip(char *file) { char *s_path, cmd[MAXPATHLEN]; s_path = getenv(STRIP_ENV_NAME); if (s_path == NULL) { errorf("%s env variable not set, skipping.", STRIP_ENV_NAME); } else { /* build the command */ if (snprintf_b(cmd, sizeof(cmd), "%s %s", s_path, file) == false) { errorf("failed to build strip command, skipping."); } else { /* stripping */ if (system(cmd) != EXIT_SUCCESS) { errorf("strip failed."); } } } } /* convert symbolic value to octal mstr : symbolic value string pmode : resulting mode return : boolean */ bool symbolic_to_octal_mode(char *mstr, mode_t *pmode) { bool do_loop = true; char *pstr, op = CHAR_EOS; mode_t mask = 0, perm = 0; pstr = mstr; /* who symbols */ while (do_loop == true) { #ifdef INST_DEBUG debugf("char = '%c'", *pstr); #endif switch (*pstr) { case 'a': mask = mask | FULL_MASK; break; case 'g': mask = mask | GRP_MASK; break; case 'o': mask = mask | OTH_MASK; break; case 'u': mask = mask | USR_MASK; break; default: /* separator found */ op = *pstr; do_loop = false; break; } pstr++; #ifdef INST_DEBUG debugf("mask = %o", mask); #endif } /* check if operator is valid */ if ((op != '+') && (op != '-') && (op != '=')) { errorf("syntax error in symbolic mode '%s'", mstr); return(false); } /* perm symbols */ do_loop = true; while (do_loop == true) { switch (*pstr) { case 'r': perm = perm | R_PERM; break; case 'w': perm = perm | W_PERM; break; case 'x': perm = perm | X_PERM; break; case 's': perm = perm | S_PERM; break; case CHAR_EOS: /* reached end of string */ do_loop = false; break; default: /* unknown perm */ errorf("unknown permission '%c'.", *pstr); return(false); break; } pstr++; } #ifdef INST_DEBUG debugf("perm = %o", perm); #endif /* apply operator */ switch (op) { case '+': if (perm == 0) { /* no perms given */ *pmode = 0; } else { if (mask == 0) { /* mask not set, give perms to all */ mask = FULL_MASK; } *pmode = mask & perm; } break; case '-': /* no perms */ *pmode = 0; break; case '=': if (mask == 0) { *pmode = perm; } else { *pmode = 0; } break; } return(true); } /* check_mode mstr : mode string pmode : resulting mode return : boolean */ bool check_mode(char *mstr, mode_t *pmode) { unsigned long mode = 0; if (mstr == NULL) return(false); if (isdigit(*mstr) != 0) { /* octal value */ if (str_to_ulong(mstr, 8, &mode) == false) { return(false); /* unable to get numerical value */ } } else { /* symbolic value */ if (symbolic_to_octal_mode(mstr, (mode_t *)&mode) == false) { return(false); }; } /* set mode */ *pmode = (mode_t) mode; return(true); } /* process owner string pstr: owner string puid: storage of uid returns: true on success else false */ bool process_owner(char *pstr, uid_t *puid) { struct passwd *pp = NULL; unsigned long ul; if (isdigit(*pstr) == 0) { /* user name */ pp = getpwnam(pstr); if (pp == NULL) { errorf("invalid user name."); return(false); } else { *puid = pp->pw_uid; } } else { /* uid */ if (str_to_ulong(pstr, 10, &ul) == false) { errorf("cannot get numerical value of '%s'.", pstr); return(false); } *puid = (uid_t) ul; } return(true); } /* process owner string pstr: owner string puid: storage of uid returns: true on success else false */ bool process_group(char *pstr, gid_t *pgid) { struct group *pg = NULL; unsigned long ul; if (isdigit(*pstr) == 0) { /* group name */ pg = getgrnam(pstr); if (pg == NULL) { errorf("invalid group name."); return(false); } *pgid = pg->gr_gid; } else { /* gid */ if (str_to_ulong(pstr, 10, &ul) == false) { errorf("cannot get numerical value of '%s'.", pstr); return(false); } *pgid = (gid_t) ul; } return(true); } /* create directory psrc: source directory buffer: destination buffer bsize: buffer size returns: true on success else false */ bool create_directory(char *psrc, char *buffer, size_t bsize) { #ifdef INST_DEBUG debugf("create dir '%s'", psrc); #endif /* create path */ if (*psrc == CHAR_SEP) { /* absolute path, copy */ if (strlcpy_b(buffer, psrc, bsize) == false) { errorf("overflow in directory creation (abs. path)."); return(false); } } else { /* relative, getting current directory */ if (getcwd(buffer, bsize) == NULL) { errorf("unable to get current directory"); return(false); } /* appending path */ strlcat(buffer, STR_SEP, bsize); /* no check */ if (strlcat_b(buffer, psrc, bsize) == false) { errorf("overflow in directory creation (rel. path)."); return(false); } } #ifdef INST_DEBUG debugf("dir = '%s'", buffer); #endif if (makepath(buffer, S_IRWXU | S_IRWXG | S_IRWXO) == false) { errorf("cannot create directory."); return(false); } return(true); } /* build destination target psrc: source file pdst: destination directory buffer: destination buffer bsize: buffer size returns: true on success else false */ bool build_destination(char *psrc, char *pdst, char *buffer, size_t bsize) { char *pstr; strlcpy(buffer, pdst, bsize); /* no check */ if (strlcat_b(buffer, STR_SEP, bsize) == false) { errorf("overflow detected in destination."); return(false); } pstr = basename(psrc); if (pstr == NULL) { errorf("unable to get basename of source."); return(false); } if (strlcat_b(buffer, pstr, bsize) == false) { errorf("overflow detected in destination."); return(false); } return(true); } /* usage */ void usage(void) { fprintf(stderr, "usage: pmkinstall [-cs] [-g group] [-m mode] " "[-o owner] file1 file2\n"); fprintf(stderr, " pmkinstall [-cs] [-g group] [-m mode] " "[-o owner] file1 ... fileN directory\n"); fprintf(stderr, " pmkinstall -d [-g group] [-m mode] " "[-o owner] directory ...\n"); fprintf(stderr, " pmkinstall -v\n"); fprintf(stderr, " pmkinstall -h\n"); exit(EXIT_FAILURE); } /* main */ int main(int argc, char *argv[]) { struct stat sb; bool create_dir = false, do_backup = false, do_chown = false, do_strip = false, go_exit = false; char *gstr = NULL, *ostr = NULL, *src, *dst, dir[MAXPATHLEN], backup[MAXPATHLEN]; gid_t gid = (gid_t) -1; int chr; mode_t mode = DEFAULT_MODE, tmode; uid_t uid = (uid_t) -1; unsigned int src_idx, last_idx; while (go_exit == false) { chr = getopt(argc, argv, "B:bcdg:hm:o:stv"); if (chr == -1) { go_exit = true; } else { switch (chr) { case 'B' : bsfx = optarg; #ifdef INST_DEBUG debugf("backup suffix = %s", bsfx); #endif break; case 'b' : /* backup */ do_backup = true; break; case 'c' : /* default behavior, do nothing (backwards compat.) */ break; case 'd' : /* create directories */ create_dir = true; break; case 'g' : /* specify group */ gstr = optarg; #ifdef INST_DEBUG debugf("gstr = %s", gstr); #endif break; case 'm' : /* specify mode */ if (check_mode(optarg, &mode) == false) exit(EXIT_FAILURE); #ifdef INST_DEBUG debugf("mode = %o", mode); #endif break; case 'o' : /* specifiy owner */ ostr = optarg; break; case 's' : /* strip */ do_strip = true; break; case 't' : /* autconf shit, only for compat */ break; case 'v' : /* display version */ fprintf(stdout, "%s\n", PREMAKE_VERSION); exit(EXIT_SUCCESS); break; case 'h' : case '?' : default : usage(); break; } } } argc = argc - optind; argv = argv + optind; /* only directory creation allow 1 parameter */ if ((argc < 2) && (create_dir == false)) { /* not enough parameters */ usage(); } /* check if an owner has been provided */ if (ostr != NULL) { if (process_owner(ostr, &uid) == false) { /* error message already done */ exit(EXIT_FAILURE); } #ifdef INST_DEBUG debugf("uid = %d", uid); #endif do_chown = true; } /* if a group has been provided */ if (gstr != NULL) { if (process_group(gstr, &gid) == false) { /* error message already done */ exit(EXIT_FAILURE); } #ifdef INST_DEBUG debugf("gid = %d", gid); #endif do_chown = true; } /* set last_idx respectively */ if (create_dir == true) { last_idx = argc; } else { last_idx = argc - 1; } /* process each source */ for (src_idx = 0 ; src_idx < last_idx ; src_idx++) { src = argv[src_idx]; if (create_dir == true) { /* create directory */ if (create_directory(src, dir, sizeof(dir)) == false) { /* error message already done */ exit(EXIT_FAILURE); } /* set dst for further operations */ dst = dir; } else { /* install file */ #ifdef INST_DEBUG debugf("process install of '%s'", src); #endif /* set dst */ dst = argv[last_idx]; #ifdef INST_DEBUG debugf("initial dst = '%s'", dst); #endif /* check if destination is a directory */ if (stat(dst, &sb) == 0) { /* many checks to do (is a directory, etc ...) */ tmode = sb.st_mode & S_IFDIR; if (tmode == 0) { /* not a directory */ unlink(dst); } else { /* build destination */ if (build_destination(src, dst, dir, sizeof(dir)) == false) { /* error message already done */ exit(EXIT_FAILURE); } /* set dst for further operations */ dst = dir; } } /* backup, check dst again as it could have been modified */ if ((do_backup == true) && (stat(dst, &sb) == 0)) { #ifdef INST_DEBUG debugf("backup of '%s'", dst); #endif if (snprintf_b(backup, sizeof(backup), "%s%s", dst, bsfx) == false) { errorf("failed to generate backup name for '%s': %s.", dst, strerror(errno)); /* XXX exit ? */ } if (rename(dst, backup) != 0) { errorf("failed to backup %s: %s.", dst, strerror(errno)); } } #ifdef INST_DEBUG debugf("copy to '%s'", dst); #endif /* copy file */ if (fcopy(src, dst, mode) == false) { /* copy failed, error message already displayed */ exit(EXIT_FAILURE); } /* strip binary if asked */ if (do_strip == true) { strip(dst); } } /* change owner and group */ if (do_chown == true) { #ifdef INST_DEBUG debugf("doing chown('%s', %d, %d)", dst, uid, gid); #endif if (chown(dst, uid, gid) != 0) { errorf("chown failed : %s.", strerror(errno)); exit(EXIT_FAILURE); } } /* change perms (must follow chown that can change perms) */ if (chmod(dst, mode) == -1) { #ifdef INST_DEBUG debugf("chmod('%s', %o)", dst, mode); #endif errorf("chmod failed : %s.", strerror(errno)); exit(EXIT_FAILURE); } } return(0); } pmk-0.10.4/cpu_arch_def.h010064400017500000000000000044031017575041600140270ustar00mipswheel/* $Id: cpu_arch_def.h 1369 2005-01-26 17:19:10Z mipsator $ */ /* * Copyright (c) 2004 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. * */ #ifndef _CPU_ARCH_DEF_ #define _CPU_ARCH_DEF_ /* check x86 32 bits architecture */ #if defined(i386) || defined(__i386) || defined(__i386__) #define ARCH_X86_32 1 #endif /* check x86 64 bits architecture */ #if defined(__AMD64__) || defined(AMD64) || \ defined(__amd64__) || defined(__x86_64__) #define ARCH_X86_64 1 #endif /* check alpha architecture */ #if defined(__alpha__) || defined(__alpha) || \ defined(__ALPHA) #define ARCH_ALPHA 1 #endif /* check ia64 architecture */ #if defined(__ia64__) || defined(__IA64__) || \ defined(_IA64) || defined(_M_IA64) #define ARCH_IA64 1 #endif #endif /* _CPU_ARCH_DEF_ */ pmk-0.10.4/dynarray.c010064400017500000000000000216731030204026600132440ustar00mipswheel/* $Id: dynarray.c 1462 2005-08-21 08:52:06Z mipsator $ */ /* * 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 : * - Ted Unangst */ /******************************************************************* * * * Dynamic Array * * * * Simulate an array of string with a variable size. * * * *******************************************************************/ #include #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "dynarray.h" /***************** * da_init_adv() * *********************************************************************** DESCR Initialise dynamic array and provide specific free function IN freefunc : free function OUT returns pointer of dynamic array ***********************************************************************/ dynary *da_init_adv(void (*freefunc)(void *)) { dynary *da = NULL; da = (dynary *)malloc(sizeof(dynary)); if (da != NULL) { da->nbcell = 0; da->nextidx = 0; da->pary = malloc(DYNARY_AUTO_GROW * sizeof(void *)); if (freefunc != NULL) { da->freeobj = freefunc; } else { da->freeobj = free; } } return(da); } /************* * da_init() * *********************************************************************** DESCR Initialise dynamic array IN NONE OUT returns pointer of dynamic array ***********************************************************************/ dynary *da_init(void) { return(da_init_adv(NULL)); } /**************** * da_destroy() * *********************************************************************** DESCR destroy dynamic array IN da : dynamic array to destroy OUT NONE ***********************************************************************/ void da_destroy(dynary *da) { int i; if (da != NULL) { for (i = 0 ; i < da->nextidx ; i++) { da->freeobj(da->pary[i]); } free(da->pary); free(da); } } /*************** * da_resize() * *********************************************************************** DESCR Resize the array to the given size IN da : array to resize nsize : new size OUT return : boolean ***********************************************************************/ bool da_resize(dynary *da, size_t nsize) { void **tary; if (da == NULL) return(false); tary = realloc(da->pary, nsize * sizeof(void *)); if (tary != NULL) { da->pary = tary; da->nbcell = nsize; return(true); } else { return(false); } } /************* * da_size() * *********************************************************************** DESCR Get the size of the array IN NONE OUT returns number of cell of the array ***********************************************************************/ size_t da_size(dynary *da) { if (da == NULL) abort(); /* shouldn't happen */ return((size_t) da->nbcell); } /************** * da_usize() * *********************************************************************** DESCR Get the 'used' size of the array IN NONE OUT returns the number of 'used' cells ***********************************************************************/ size_t da_usize(dynary *da) { if (da == NULL) abort(); /* shouldn't happen */ return((size_t) da->nextidx); } /************* * da_push() * *********************************************************************** DESCR Add a new value at the end of the array IN da : dynamic array pval : string to append OUT return : boolean ***********************************************************************/ bool da_push(dynary *da, void *pval) { size_t gsize; if (da == NULL) return(false); if (da->nbcell == da->nextidx) { /* compute growing size */ gsize = (da->nbcell + DYNARY_AUTO_GROW); if (da_resize(da, gsize) == false) { /* cannot resize dynary */ return(false); } } /* insert in last place */ da->pary[da->nextidx] = pval; da->nextidx++; return(true); } /************ * da_pop() * *********************************************************************** DESCR Pop the last value of the array IN da : dynamic array OUT return : the last element or NULL ***********************************************************************/ void *da_pop(dynary *da) { void *p; size_t gsize; if (da == NULL) return(NULL); if (da->nextidx == 0) { /* empty */ return(NULL); } da->nextidx--; p = da->pary[da->nextidx]; da->pary[da->nextidx] = NULL; /* resize if allocated space is too big */ if ((da->nbcell - da->nextidx) > DYNARY_AUTO_GROW) { gsize = da->nbcell - DYNARY_AUTO_GROW; if (da_resize(da, gsize) == false) { /* cannot resize dynary */ return (NULL); } } return(p); } /************** * da_shift() * *********************************************************************** DESCR Pop the first value and shift the array IN da : dynamic array OUT return : the first cell ***********************************************************************/ void *da_shift(dynary *da) { void *p; int i; size_t gsize; if (da == NULL) return(NULL); if (da->nextidx == 0) { /* empty */ return(NULL); } p = da->pary[0]; da->nextidx--; /* shift remaining values */ for (i = 0 ; i < da->nextidx ; i++) { da->pary[i] = da->pary[i+1]; } /* clear previous latest element */ da->pary[da->nextidx] = NULL; /* resize if allocated space is too big */ if ((da->nbcell - da->nextidx) > DYNARY_AUTO_GROW) { gsize = da->nbcell - DYNARY_AUTO_GROW; if (da_resize(da, gsize) == false) { /* cannot resize dynary */ return (NULL); } } return(p); } /************ * da_idx() * *********************************************************************** DESCR Get a value IN da : dynamic array idx : index of the wanted value OUT returns value or NULL ***********************************************************************/ void *da_idx(dynary *da, int idx) { if (da == NULL) return(NULL); if (idx >= da->nextidx) { return(NULL); } return(da->pary[idx]); } /************* * da_find() * *********************************************************************** DESCR try to find an element in the given dynary IN da : dynary structure str : string to find OUT boolean relative to the result of the search NOTE : this only work with dynaries intialised with da_init() ***********************************************************************/ bool da_find(dynary *da, char *str) { bool rslt = false; size_t i, s; /* compute size of string including the delimiter */ s = strlen(str) + 1; /* for each item of the dynary */ for (i = 0 ; i < da_usize(da) ; i++) { /* check if equal to the string */ if (strncmp(str, da_idx(da, i), s) == 0) { /* and set the flag if true */ rslt = true; break; } } return(rslt); } /************* * da_sort() * *********************************************************************** DESCR sort the dynary IN da : dynary structure OUT NONE NOTE : this only work with dynaries intialised with da_init() ***********************************************************************/ static int da_strcmp(const void *a, const void *b) { return(strcmp(*(char * const *)a, *(char * const *) b)); } void da_sort(dynary *da) { qsort((void *) da->pary, da->nextidx, sizeof(char *), da_strcmp); } pmk-0.10.4/codebuild.c010075500017500000000000000506151062512151600133540ustar00mipswheel/* $Id: codebuild.c 1989 2007-05-23 20:25:50Z coudercd $ */ /* * Copyright (c) 2005-2006 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. * */ #include #include #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "codebuild.h" #include "common.h" /******************** * name_randomize() * *********************************************************************** DESCR randomize a filename IN name : filename to randomize OUT NONE ***********************************************************************/ void name_randomize(char *name) { struct timeval tv; char subst[] = "aZbY0cXdWe1VfUgT2hSiRj3QkPlO4mNnMo5LpKqJ6rIsHt7GuFvE8wDxCy9BzA"; int len, i; /* intialise random() */ len = strlen(subst); gettimeofday(&tv, NULL); srandom(tv.tv_sec * tv.tv_usec); while (*name != '\0') { /* if character is X then randomize */ if (*name == 'X') { /* get random value */ i = (int) random() % len; /* replace */ *name = subst[i]; } /* next character */ name++; } } /******************* * code_bld_init() * *********************************************************************** DESCR initialize code build structure IN pcb : code build data structure blog : build log file name OUT NONE ***********************************************************************/ void code_bld_init(code_bld_t *pcb, char *blog) { /* init data pointers */ pcb->header = NULL; pcb->library = NULL; pcb->define = NULL; pcb->procedure = NULL; pcb->type = NULL; pcb->member = NULL; pcb->pathcomp = NULL; pcb->cflags = NULL; pcb->ldflags = NULL; pcb->slcflags = NULL; pcb->slldflags = NULL; pcb->alt_cflags = NULL; pcb->alt_libs = NULL; pcb->subhdrs = NULL; /* init filename buffers */ pcb->binfile[0] = '\0'; pcb->objfile[0] = '\0'; pcb->srcfile[0] = '\0'; /* init command line buffer */ pcb->bldcmd[0] = '\0'; /* set build log file name */ pcb->blog = blog; } /********************* * verify_language() * *********************************************************************** DESCR verify support for the given language IN lang : language identifier string OUT boolean ***********************************************************************/ int verify_language(char *lang) { size_t i, len; len = strlen(lang); /* search for language data */ for (i = 0 ; i < nb_lang_data ; i++) { /* if language is found */ if (strncmp(lang_data[i].name, lang, len) == 0) { /* return index of the language cell */ return(i); } } /* unknown language */ return(LANG_UNKNOWN); } /****************** * set_language() * *********************************************************************** DESCR set the language used for the code building IN pcb : code build data structure lang : language identifier string OUT boolean ***********************************************************************/ bool set_language(code_bld_t *pcb, char *lang) { int i; /* verify if the language is supported */ i = verify_language(lang); if (i == LANG_UNKNOWN) { /* unknown language */ pcb->pld = NULL; return(false); } /* language found */ pcb->lang = lang_data[i].lang; pcb->pld = &lang_data[i]; return(true); } /****************** * set_compiler() * *********************************************************************** DESCR set the path to the compiler to be used for building IN pcb : code build data structure pht : XXX OUT returns the compiler path ***********************************************************************/ char *set_compiler(code_bld_t *pcb, htable *pht) { pcb->pathcomp = hash_get(pht, pcb->pld->compiler); return(pcb->pathcomp); } /********************* * PROC set_cflags() * *********************************************************************** * DESCR XXX * * PARAM XXX * PARAM XXX * * RETURN XXX ***********************************************************************/ void set_cflags(code_bld_t *pcb, char *cflags) { /* set cflags value */ pcb->cflags = cflags; } /********************** * PROC set_ldflags() * *********************************************************************** * DESCR XXX * * PARAM XXX * PARAM XXX * * RETURN XXX ***********************************************************************/ void set_ldflags(code_bld_t *pcb, char *ldflags) { /* set cflags value */ pcb->ldflags = ldflags; } /********************** * PROC set_slcflags() * *********************************************************************** * DESCR XXX * * PARAM XXX * PARAM XXX * * RETURN XXX ***********************************************************************/ void set_slcflags(code_bld_t *pcb, char *slcflags) { /* set slcflags value */ pcb->slcflags = slcflags; } /*********************** * PROC set_slldflags() * *********************************************************************** * DESCR XXX * * PARAM XXX * PARAM XXX * * RETURN XXX ***********************************************************************/ void set_slldflags(code_bld_t *pcb, char *slldflags) { /* set slldflags value */ pcb->slldflags = slldflags; } /******************** * get_lang_label() * *********************************************************************** DESCR get the label of the language used for building IN pcb : code build data structure OUT returns the language label string ***********************************************************************/ char *get_lang_label(code_bld_t *pcb) { return(pcb->pld->name); } /************************ * get_compiler_label() * *********************************************************************** DESCR get the label of the language used for building IN pcb : code build data structure OUT returns the language label string ***********************************************************************/ char *get_compiler_label(code_bld_t *pcb) { return(pcb->pld->compiler); } /********************** * get_cflags_label() * *********************************************************************** DESCR get the compiler flags variable name (can be default or alternative) IN pcb : code build data structure OUT returns the variable name ***********************************************************************/ char *get_cflags_label(code_bld_t *pcb) { /* if an alternative cflags variable name exists */ if (pcb->alt_cflags != NULL) { /* then return the alternative name */ return(pcb->alt_cflags); } else { /* else return the default name of the used language */ return(pcb->pld->cflags); } } /******************** * get_libs_label() * *********************************************************************** DESCR get the linker flags variable name (can be default or alternative) IN pcb : code build data structure OUT returns the variable name ***********************************************************************/ char *get_libs_label(code_bld_t *pcb) { /* if an alternative libs variable name exists */ if (pcb->alt_libs != NULL) { /* then return the alternative name */ return(pcb->alt_libs); } else { /* else return the default name */ return("LIBS"); /* XXX TODO use premake.h standard value (smth like PMK_STD_LIBS) */ } } /***************** * code_logger() * *********************************************************************** DESCR write code in the temporary source file and log it IN tfp : temporary source file descriptor lfp : log file descriptor fmt : message format string OUT NONE NOTE TODO : check returned values XXX ***********************************************************************/ void code_logger(FILE *tfp, FILE *lfp, const char *fmt, ...) { va_list plst1, plst2; va_start(plst1, fmt); va_copy(plst2, plst1); vfprintf(tfp, fmt, plst1); vfprintf(lfp, fmt, plst2); va_end(plst1); va_end(plst2); } /****************** * code_builder() * *********************************************************************** DESCR code building wrapper IN pcb : code build data structure OUT boolean ***********************************************************************/ bool code_builder(code_bld_t *pcb) { switch (pcb->lang) { case LANG_C : case LANG_CXX : return(c_code_builder(pcb)); } return(false); } /******************** * c_code_builder() * *********************************************************************** DESCR C language code building IN pcb : code build data structure OUT boolean ***********************************************************************/ bool c_code_builder(code_bld_t *pcb) { FILE *tfp, *lfp; size_t i; /* open temporary file */ tfp = tmps_open(TEST_FILE_NAME, "w", pcb->srcfile, sizeof(pcb->srcfile), strlen(C_FILE_EXT)); if (tfp == NULL) { errorf("c_code_builder: tmps_open() failed"); return(false); /* failed to open */ } lfp = fopen(pcb->blog, "a"); if (lfp == NULL) { errorf("c_code_builder: build log fopen() failed"); return(false); /* failed to open */ } fprintf(lfp, "Generated source file:\n"); /* sub headers */ if (pcb->subhdrs != NULL) { code_logger(tfp, lfp, "/* dependency headers */\n"); for (i = 0 ; i < da_usize(pcb->subhdrs) ; i++) { code_logger(tfp, lfp, CODE_C_HDR, (char *) da_idx(pcb->subhdrs, i)); } } /* main header */ if (pcb->header != NULL) { code_logger(tfp, lfp, "/* main header to test */\n"); code_logger(tfp, lfp, CODE_C_HDR, pcb->header); } else { if (pcb->procedure != NULL) { /* prototype */ code_logger(tfp, lfp, CODE_C_DECL, pcb->procedure); } } /* main proc */ code_logger(tfp, lfp, CODE_C_BEG); /* define test */ if (pcb->define != NULL) { code_logger(tfp, lfp, CODE_C_DEF, pcb->define); } /* procedure test */ if (pcb->procedure != NULL) { code_logger(tfp, lfp, CODE_C_PROC, pcb->procedure); } /* type test */ if (pcb->type != NULL) { if (pcb->member == NULL) { /* simple */ code_logger(tfp, lfp, CODE_C_VAR, pcb->type); code_logger(tfp, lfp, CODE_C_TYPE); } else { /* with member */ code_logger(tfp, lfp, CODE_C_VAR, pcb->type); code_logger(tfp, lfp, CODE_C_MEMBER, pcb->member); } } code_logger(tfp, lfp, CODE_C_END); if (fclose(tfp) != 0) { errorf("c_code_builder: generated source I/O failure"); return(false); } if (fclose(lfp) != 0) { errorf("c_code_builder: build log I/O failure"); return(false); } return(true); } /******************** * shared_builder() * *********************************************************************** DESCR shared code building wrapper IN pcb : code build data structure OUT boolean ***********************************************************************/ bool shared_builder(code_bld_t *pcb, char *content) { switch (pcb->lang) { case LANG_C : case LANG_CXX : return(c_shared_builder(pcb, content)); } return(false); } /********************** * c_shared_builder() * *********************************************************************** DESCR C shared code builder IN pcb : code build data structure OUT boolean ***********************************************************************/ bool c_shared_builder(code_bld_t *pcb, char *content) { FILE *tfp, *lfp; /* open temporary file */ tfp = tmps_open(TEST_FILE_NAME, "w", pcb->srcfile, sizeof(pcb->srcfile), strlen(C_FILE_EXT)); if (tfp == NULL) { errorf("c_shared_builder: tmps_open() failed"); return(false); /* failed to open */ } lfp = fopen(pcb->blog, "a"); if (lfp == NULL) { errorf("c_shared_builder: build log fopen() failed"); return(false); /* failed to open */ } fprintf(lfp, "Generated source file:\n"); /* code content */ code_logger(tfp, lfp, content); if (fclose(tfp) != 0) { errorf("c_shared_builder: generated source I/O failure"); return(false); } if (fclose(lfp) != 0) { errorf("c_shared_builder: build log I/O failure"); return(false); } return(true); } /********************* * cmdline_builder() * *********************************************************************** DESCR wrapper for compiler command line building IN pcb : code build data structure lnk : linking method OUT boolean ***********************************************************************/ bool cmdline_builder(code_bld_t *pcb, int lnk) { FILE *lfp; bool r = false; switch (pcb->lang) { case LANG_C : case LANG_CXX : r = c_cmdline_builder(pcb, lnk); } if (r == true) { lfp = fopen(pcb->blog, "a"); if (lfp == NULL) { errorf("cmdline_builder: build log fopen() failed"); return(false); /* failed to open */ } fprintf(lfp, "Generated command line:\n"); fprintf(lfp, "%s\n", pcb->bldcmd); if (fclose(lfp) != 0) { errorf("cmdline_builder: build log I/O failure"); return(false); } } return(r); } /*********************** * c_cmdline_builder() * *********************************************************************** DESCR build C compiler command line IN pcb : code build data structure lnk : linking method OUT boolean ***********************************************************************/ bool c_cmdline_builder(code_bld_t *pcb, int lnk) { /* start with compiler */ if (pcb->pathcomp == NULL) { return(false); } strlcpy(pcb->bldcmd, pcb->pathcomp, sizeof(pcb->bldcmd)); /* if compiler flags are provided */ if (pcb->cflags != NULL) { strlcat(pcb->bldcmd, " ", sizeof(pcb->bldcmd)); strlcat(pcb->bldcmd, pcb->cflags, sizeof(pcb->bldcmd)); } if (lnk != LINK_NONE) { /* if linker flags are provided */ if (pcb->ldflags != NULL) { strlcat(pcb->bldcmd, " ", sizeof(pcb->bldcmd)); strlcat(pcb->bldcmd, pcb->ldflags, sizeof(pcb->bldcmd)); } } /* if not in linking mode */ if (lnk == LINK_NONE) { /* append shared lib compiler flags if they are provided */ if (pcb->slcflags != NULL) { strlcat(pcb->bldcmd, " ", sizeof(pcb->bldcmd)); strlcat(pcb->bldcmd, pcb->slcflags, sizeof(pcb->bldcmd)); } } else { /* else append shared lib linker flags if they are provided */ if (pcb->slldflags != NULL) { strlcat(pcb->bldcmd, " ", sizeof(pcb->bldcmd)); strlcat(pcb->bldcmd, pcb->slldflags, sizeof(pcb->bldcmd)); } } /* append the object name */ strlcat(pcb->bldcmd, " -o ", sizeof(pcb->bldcmd)); if (lnk != LINK_NONE) { /* * linking => create a binary file */ /* copy filename template */ strlcpy(pcb->binfile, BIN_TEST_NAME, sizeof(pcb->binfile)); /* randomize binary name */ name_randomize(pcb->binfile); /* append binary file name */ strlcat(pcb->bldcmd, pcb->binfile, sizeof(pcb->bldcmd)); } else { /* * no linking => create object file */ /* copy filename template */ strlcpy(pcb->objfile, BIN_TEST_NAME, sizeof(pcb->objfile)); /* randomize object name */ name_randomize(pcb->objfile); /* append object extension */ strlcat(pcb->objfile, ".o", sizeof(pcb->objfile)); /* append object file name */ strlcat(pcb->bldcmd, pcb->objfile, sizeof(pcb->bldcmd)); } /* if an optional library has been provided */ if (pcb->library != NULL) { strlcat(pcb->bldcmd, " -l ", sizeof(pcb->bldcmd)); strlcat(pcb->bldcmd, pcb->library, sizeof(pcb->bldcmd)); } /* if we don't link use -c */ if (lnk == LINK_NONE) { strlcat(pcb->bldcmd, " -c", sizeof(pcb->bldcmd)); } if (lnk == LINK_OBJ) { /* append object filename */ strlcat(pcb->bldcmd, " ", sizeof(pcb->bldcmd)); strlcat(pcb->bldcmd, pcb->objfile, sizeof(pcb->bldcmd)); } else { /* append source filename */ strlcat(pcb->bldcmd, " ", sizeof(pcb->bldcmd)); strlcat(pcb->bldcmd, pcb->srcfile, sizeof(pcb->bldcmd)); } /* append log redirection */ strlcat(pcb->bldcmd, " >>", sizeof(pcb->bldcmd)); strlcat(pcb->bldcmd, pcb->blog, sizeof(pcb->bldcmd)); if (strlcat_b(pcb->bldcmd, " 2>&1", sizeof(pcb->bldcmd)) == false) { return(false); } return(true); } /******************** * object_builder() * *********************************************************************** DESCR execute object building command line IN compiler command line builder OUT boolean ***********************************************************************/ bool object_builder(code_bld_t *pcb) { if (system(pcb->bldcmd) == 0) { return(true); } else { return(false); } } /**************** * cb_cleaner() * *********************************************************************** DESCR clean code builder files (temporary source and eventually generated binary) IN compiler command line builder OUT NONE ***********************************************************************/ void cb_cleaner(code_bld_t *pcb) { if (pcb->srcfile[0] != '\0') { if (unlink(pcb->srcfile) == -1) { /* cannot remove temporary source file */ errorf("cannot remove source file '%s'", pcb->srcfile); } } if (pcb->objfile[0] != '\0') { /* No need to check return here as object could not exists */ unlink(pcb->objfile); } if (pcb->binfile[0] != '\0') { /* No need to check return here as binary could not exists */ unlink(pcb->binfile); } } /********************** * check_so_support() * *********************************************************************** DESCR XXX IN XXX OUT XXX ***********************************************************************/ bool check_so_support(code_bld_t *pcb, char *slcflags, char *slldflags) { /* set shared library compiler flags */ set_slcflags(pcb, slcflags); /* set shared library linker flags */ set_slldflags(pcb, slldflags); /* prepare source of first shared object */ if (shared_builder(pcb, CODE_C_SHARED_F) == false) { /* failed to build source code */ return(false); } else { /* set command line for shared object */ if (cmdline_builder(pcb, LINK_NONE) == false) { /* failed to generate command line */ return(false); } else { /* let's go compiling */ if (object_builder(pcb) == false) { /* failed to compile */ return(false); } } } /* * now try linking shared object */ /* set command line for shared object */ if (cmdline_builder(pcb, LINK_OBJ) == false) { /* failed to generate command line */ return(false); } else { /* let's go compiling */ if (object_builder(pcb) == false) { /* failed to compile */ return(false); } } return(true); } /********************************* * obsolete_get_lang_from_comp() * *********************************************************************** DESCR provide compiler path IN compname : compiler name from lgdata structure OUT language name NOTE : OBSOLETE, to remove later when useless ***********************************************************************/ char *obsolete_get_lang_from_comp(char *compname) { char key[OPT_NAME_LEN]; size_t i, len; /* failed to build compiler label */ if (snprintf_b(key, sizeof(key), "BIN_%s", compname) == false) { return(NULL); } /* length of the generated string */ len = strlen(key); /* search for matching compiler label */ for (i = 0 ; i < nb_lang_data ; i++) { /* if compiler is found */ if (strncmp(lang_data[i].compiler, key, len) == 0) { /* return the language name */ return(lang_data[i].name); } } /* unknown compiler */ return(NULL); } /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/pmkscan.c010064400017500000000000004071001061073261500130500ustar00mipswheel/* $Id: pmkscan.c 1976 2007-04-16 17:42:37Z coudercd $ */ /* * Copyright (c) 2003-2006 Damien Couderc * Copyright (c) 2004 Xavier Santolaria * 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. * */ /* include it first as if it was - this will avoid errors */ #include "compat/pmk_sys_types.h" #include #include #include #include #include #include #include #include #include "compat/pmk_ctype.h" #include "compat/pmk_libgen.h" #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "compat/pmk_unistd.h" #include "common.h" #include "dynarray.h" #include "hash_tools.h" #include "parse.h" #include "pathtools.h" #include "pmkscan.h" #include "premake.h" #include "tags.h" /*#define PMKSCAN_DEBUG 1*/ /* file types **********************************************************/ scn_ext_t file_ext[] = { {"*.1", FILE_TYPE_MAN1}, {"*.2", FILE_TYPE_MAN2}, {"*.3", FILE_TYPE_MAN3}, {"*.4", FILE_TYPE_MAN4}, {"*.5", FILE_TYPE_MAN5}, {"*.6", FILE_TYPE_MAN6}, {"*.7", FILE_TYPE_MAN7}, {"*.8", FILE_TYPE_MAN8}, {"*.9", FILE_TYPE_MAN9}, {"*.asm", FILE_TYPE_ASM}, {"*.C", FILE_TYPE_C}, {"*.c", FILE_TYPE_C}, {"*.cc", FILE_TYPE_C}, {"*.cpp", FILE_TYPE_CXX}, {"*.cxx", FILE_TYPE_CXX}, {"*.c++", FILE_TYPE_CXX}, {"*.dat", FILE_TYPE_DATA}, {"*.gif", FILE_TYPE_IMG}, {"*.H", FILE_TYPE_C}, {"*.h", FILE_TYPE_C}, {"*.hh", FILE_TYPE_C}, {"*.hpp", FILE_TYPE_CXX}, {"*.html", FILE_TYPE_HTML}, {"*.htm", FILE_TYPE_HTML}, {"*.hxx", FILE_TYPE_CXX}, {"*.h++", FILE_TYPE_CXX}, {"*.in", FILE_TYPE_TEMPL}, {"*.jpg", FILE_TYPE_IMG}, {"*.jpeg", FILE_TYPE_IMG}, {"*.l", FILE_TYPE_LEX}, {"*.pmk", FILE_TYPE_TEMPL}, {"*.png", FILE_TYPE_IMG}, {"*.S", FILE_TYPE_ASM}, {"*.s", FILE_TYPE_ASM}, {"*.txt", FILE_TYPE_TEXT}, {"*.xpm", FILE_TYPE_IMG}, {"*.y", FILE_TYPE_YACC} }; size_t nb_file_ext = sizeof(file_ext) / sizeof(scn_ext_t); lib_type_t lib_types[] = { /*{LANG_LABEL_ASM, LIB_TYPE_ASM},*/ {LANG_LABEL_C, LIB_TYPE_C}, {LANG_LABEL_CXX, LIB_TYPE_CXX} }; size_t nb_lib_types = sizeof(lib_types) / sizeof(lib_type_t); /* pmkscan data parser options *****************************************/ /* common required options */ kw_t req_name[] = { {KW_OPT_NAM, PO_STRING} }; /* ADD_HEADER options */ kw_t opt_addhdr[] = { {KW_OPT_LIB, PO_STRING}, {KW_OPT_PRC, PO_LIST}, {KW_OPT_SUB, PO_LIST} }; kwopt_t kw_addhdr = { req_name, sizeof(req_name) / sizeof(kw_t), opt_addhdr, sizeof(opt_addhdr) / sizeof(kw_t) }; /* ADD_LIBRARY options */ kw_t opt_addlib[] = { {KW_OPT_PRC, PO_LIST} }; kwopt_t kw_addlib = { req_name, sizeof(req_name) / sizeof(kw_t), opt_addlib, sizeof(opt_addlib) / sizeof(kw_t) }; /* ADD_TYPE options */ kw_t opt_addtyp[] = { {KW_OPT_HDR, PO_STRING}, {KW_OPT_MBR, PO_LIST} }; kwopt_t kw_addtyp = { req_name, sizeof(req_name) / sizeof(kw_t), opt_addtyp, sizeof(opt_addtyp) / sizeof(kw_t) }; prskw kw_pmkscan[] = { {KW_CMD_ADDHDR, PSC_TOK_ADDHDR, PRS_KW_CELL, PRS_TOK_NULL, &kw_addhdr}, {KW_CMD_ADDLIB, PSC_TOK_ADDLIB, PRS_KW_CELL, PRS_TOK_NULL, &kw_addlib}, {KW_CMD_ADDTYP, PSC_TOK_ADDTYP, PRS_KW_CELL, PRS_TOK_NULL, &kw_addtyp} }; size_t nbkwps = sizeof(kw_pmkscan) / sizeof(prskw); /* pmkscan script parser options ***************************************/ /* DEFINE_LIB required options */ kw_t req_deflib[] = { {KW_OPT_NAM, PO_STRING}, {KW_OPT_LINKER, PO_STRING}, {KW_OPT_SRCS, PO_LIST} }; /* DEFINE_LIB options */ kw_t opt_deflib[] = { {KW_OPT_HDRS, PO_LIST}, {KW_OPT_VMAJ, PO_STRING}, {KW_OPT_VMIN, PO_STRING} }; kwopt_t kw_deflib = { req_deflib, sizeof(req_deflib) / sizeof(kw_t), opt_deflib, sizeof(opt_deflib) / sizeof(kw_t) }; /* common required options */ kw_t req_dir[] = { {KW_OPT_DIR, PO_STRING} }; /* GEN_PMKFILE options */ kw_t opt_genpmk[] = { {KW_OPT_ADVTAG, PO_BOOL}, {KW_OPT_CFGALT, PO_STRING}, {KW_OPT_DSC, PO_LIST}, {KW_OPT_EXTTAG, PO_LIST}, {KW_OPT_LIB, PO_LIST}, {KW_OPT_PMKALT, PO_STRING}, {KW_OPT_REC, PO_BOOL}, {KW_OPT_UNI, PO_BOOL} }; kwopt_t kw_genpmk = { req_dir, sizeof(req_dir) / sizeof(kw_t), opt_genpmk, sizeof(opt_genpmk) / sizeof(kw_t) }; /* GEN_MAKEFILE options */ kw_t opt_genmkf[] = { {KW_OPT_DSC, PO_LIST}, {KW_OPT_EXTMKF, PO_STRING}, {KW_OPT_EXTTAG, PO_LIST}, {KW_OPT_LIB, PO_LIST}, {KW_OPT_NAM, PO_STRING}, {KW_OPT_MKFALT, PO_STRING}, {KW_OPT_REC, PO_BOOL}, {KW_OPT_UNI, PO_BOOL} }; kwopt_t kw_genmkf = { req_dir, sizeof(req_dir) / sizeof(kw_t), opt_genmkf, sizeof(opt_genmkf) / sizeof(kw_t) }; /* GEN_ZONE options */ kw_t opt_genzone[] = { {KW_OPT_ADVTAG, PO_BOOL}, {KW_OPT_CFGALT, PO_STRING}, {KW_OPT_DSC, PO_LIST}, {KW_OPT_EXTMKF, PO_STRING}, {KW_OPT_EXTTAG, PO_LIST}, {KW_OPT_LIB, PO_LIST}, {KW_OPT_MKF, PO_BOOL}, {KW_OPT_MKFALT, PO_STRING}, {KW_OPT_NAM, PO_STRING}, {KW_OPT_PMK, PO_BOOL}, {KW_OPT_PMKALT, PO_STRING}, {KW_OPT_REC, PO_BOOL}, {KW_OPT_UNI, PO_BOOL} }; kwopt_t kw_genzone = { req_dir, sizeof(req_dir) / sizeof(kw_t), opt_genzone, sizeof(opt_genzone) / sizeof(kw_t) }; prskw kw_scanfile[] = { {KW_CMD_GENPF, PSC_TOK_PMKF, PRS_KW_CELL, PRS_TOK_NULL, &kw_genpmk}, {KW_CMD_GENMF, PSC_TOK_MAKF, PRS_KW_CELL, PRS_TOK_NULL, &kw_genmkf}, {KW_CMD_GENZN, PSC_TOK_ZONE, PRS_KW_CELL, PRS_TOK_NULL, &kw_genzone}, {KW_CMD_DEFLIB, PSC_TOK_DEFLIB, PRS_KW_CELL, PRS_TOK_NULL, &kw_deflib} }; size_t nbkwsf = sizeof(kw_scanfile) / sizeof(prskw); /* global variables ****************************************************/ /* log file descriptor */ FILE *fp_log = NULL; extern char *optarg; extern int optind; /****************************** * init and destroy functions * ***********************************************************************/ /******************** * scan_node_init() * *********************************************************************** DESCR initialize scan node IN fname : node file name OUT scan node structure ***********************************************************************/ scn_node_t *scan_node_init(char *fname) { char *pstr; scn_node_t *pnode; size_t len; /* allocate memory */ pnode = (scn_node_t *) malloc(sizeof(scn_node_t)); if (pnode != NULL) { /* set filename */ pnode->fname = strdup(fname); if (pnode->fname == NULL) { /* failed */ scan_node_destroy(pnode); return(NULL); } /* build prefix name */ len = strlen(fname); pstr = &fname[len]; while (pstr > fname) { if (*pstr == '.') { len = (size_t) (pstr - fname); break; } else { pstr--; } } /* get the size including null char */ len++; pnode->prefix = (char *) malloc(len); if (pnode->prefix == NULL) { return(NULL); } strlcpy(pnode->prefix, fname, len); /* init dynamic array of dependencies */ pnode->system_inc = da_init(); if (pnode->system_inc == NULL) { /* failed */ scan_node_destroy(pnode); return(NULL); } /* init dynamic array of dependencies */ pnode->local_inc = da_init(); if (pnode->local_inc == NULL) { /* failed */ scan_node_destroy(pnode); return(NULL); } /* init dynamic array of dependencies */ pnode->func_calls = da_init(); if (pnode->func_calls == NULL) { /* failed */ scan_node_destroy(pnode); return(NULL); } /* init dynamic array of dependencies */ pnode->func_decls = da_init(); if (pnode->func_decls == NULL) { /* failed */ scan_node_destroy(pnode); return(NULL); } /* init dynamic array of dependencies */ pnode->type_idtfs = da_init(); if (pnode->type_idtfs == NULL) { /* failed */ scan_node_destroy(pnode); return(NULL); } /* init dynamic array of dependencies */ pnode->src_deps = da_init(); if (pnode->src_deps == NULL) { /* failed */ scan_node_destroy(pnode); return(NULL); } /* init dynamic array of dependencies */ pnode->sys_deps = da_init(); if (pnode->sys_deps == NULL) { /* failed */ scan_node_destroy(pnode); return(NULL); } /* init dynamic array of dependencies */ pnode->obj_links = da_init(); if (pnode->obj_links == NULL) { /* failed */ scan_node_destroy(pnode); return(NULL); } /* init object dependency list */ pnode->obj_deps = NULL; /* init dependency state */ pnode->isdep = false; /* XXX useful ? see scan_file() */ /* init main() procedure flag */ pnode->mainproc = false; /* init dependency score */ pnode->score = 0; /* object pointer or null */ pnode->obj_name = NULL; /* target label */ pnode->label = NULL; /* directory name */ pnode->dname = NULL; } /* return initialized structure or NULL */ return(pnode); } /*********************** * scan_node_destroy() * *********************************************************************** DESCR destroy scan node structure IN pnode : scan node structure OUT NONE ***********************************************************************/ void scan_node_destroy(scn_node_t *pnode) { #ifdef PMKSCAN_DEBUG /*debugf("destroying node '%s'", pnode->fname);*/ #endif /* PMKSCAN_DEBUG */ if (pnode->fname != NULL) { free(pnode->fname); } if (pnode->obj_name != NULL) { free(pnode->obj_name); } if (pnode->prefix != NULL) { free(pnode->prefix); } if (pnode->label != NULL) { free(pnode->label); } if (pnode->dname != NULL) { free(pnode->dname); } if (pnode->system_inc != NULL) { da_destroy(pnode->system_inc); } if (pnode->local_inc != NULL) { da_destroy(pnode->local_inc); } if (pnode->func_calls != NULL) { da_destroy(pnode->func_calls); } if (pnode->func_decls != NULL) { da_destroy(pnode->func_decls); } if (pnode->type_idtfs != NULL) { da_destroy(pnode->type_idtfs); } if (pnode->src_deps != NULL) { da_destroy(pnode->src_deps); } if (pnode->sys_deps != NULL) { da_destroy(pnode->sys_deps); } if (pnode->obj_links != NULL) { da_destroy(pnode->obj_links); } free(pnode); } /******************* * lib_cell_init() * *********************************************************************** DESCR initialise a library cell structure IN name : library name srcs : object list OUT structure pointer or NULL ***********************************************************************/ lib_cell_t *lib_cell_init(char *name, dynary *srcs, dynary *hdrs, ltype_t type) { char buffer[TMP_BUF_LEN], ubuf[TMP_BUF_LEN]; lib_cell_t *plc; #ifdef PMKSCAN_DEBUG debugf("lib_cell_init(): processing '%s'", name); #endif plc = (lib_cell_t *) malloc(sizeof(lib_cell_t)); if (plc != NULL) { /* set library filename */ snprintf(buffer, sizeof(buffer), "lib%s", name); plc->lib_name = strdup(buffer); /* set library name variable */ str_to_upper(ubuf, sizeof(ubuf), buffer); plc->lib_label = strdup(ubuf); /* init version numbers */ plc->lib_vmaj = NULL; plc->lib_vmin = NULL; /* set library sources variable */ snprintf(buffer, sizeof(buffer), MKF_OBJ_SRCS_VAR, ubuf); plc->lib_srcs = strdup(buffer); /* set library headers variable */ snprintf(buffer, sizeof(buffer), MKF_TRGT_HDRS_VAR, ubuf); plc->lib_hdrs = strdup(buffer); /* set library objects variable */ snprintf(buffer, sizeof(buffer), MKF_TRGT_OBJS_VAR, ubuf); plc->lib_objs = strdup(buffer); /* set static library variable name */ snprintf(buffer, sizeof(buffer), "%s_STATIC", ubuf); plc->lib_static = strdup(buffer); /* set shared library variable name */ snprintf(buffer, sizeof(buffer), "%s_SHARED", ubuf); plc->lib_shared = strdup(buffer); /* library linking type */ plc->type = type; /* source dependencies */ plc->src_list = srcs; /* header dependencies */ plc->hdr_list = hdrs; /* object dependencies */ plc->obj_deps = da_init(); } return(plc); } /********************** * lib_cell_destroy() * *********************************************************************** DESCR free the given library cell structure IN plc : library cell to destroy OUT NONE ***********************************************************************/ void lib_cell_destroy(lib_cell_t *plc) { /* destroy sources list */ da_destroy(plc->src_list); /* destroy objects list */ da_destroy(plc->obj_deps); /* destroy headers list */ if (plc->hdr_list != NULL) { da_destroy(plc->hdr_list); } free(plc->lib_name); free(plc->lib_srcs); free(plc->lib_hdrs); free(plc->lib_objs); free(plc->lib_static); free(plc->lib_shared); } /******************** * scan_zone_init() * *********************************************************************** DESCR initialize scan zone structure IN nodes : global nodes table OUT scan zone structure ***********************************************************************/ scn_zone_t *scan_zone_init(htable *nodes) { scn_zone_t *pzone; size_t i; pzone = (scn_zone_t *) malloc(sizeof(scn_zone_t)); if (pzone != NULL) { /* set global nodes table */ pzone->nodes = nodes; /* init boolean flags */ pzone->advtag = true; pzone->gen_pmk = false; pzone->gen_mkf = false; pzone->gen_lib = false; pzone->recursive = false; pzone->unique = true; /* init file names */ pzone->cfg_name = PMKSCAN_CFGFILE; pzone->mkf_name = PMKSCAN_MKFILE; pzone->pmk_name = PMKSCAN_PMKFILE; pzone->ext_mkf = NULL; /* discard list */ pzone->discard = NULL; /* extra tags */ pzone->exttags = NULL; /* init file type flags */ for (i = 0 ; i < sizeof(pzone->found) ; i++) { pzone->found[i] = false; } /* init lib type flags */ for (i = 0 ; i < sizeof(pzone->lib_type) ; i++) { pzone->lib_type[i] = false; } /* init source flag */ pzone->found_src = false; /* init zone tables */ pzone->objects = hash_init(1024); /* XXX should be autogrow enabled */ pzone->targets = hash_init(512); /* XXX should be autogrow enabled */ pzone->libraries = hash_init_adv(16, NULL, (void (*)(void *)) lib_cell_destroy, NULL); /* library cells */ pzone->h_checks = hash_init_adv(128, NULL, (void (*)(void *)) destroy_chk_cell, NULL); /* XXX can do better :) */ pzone->l_checks = hash_init_adv(128, NULL, (void (*)(void *)) destroy_chk_cell, NULL); /* XXX can do better :) */ pzone->t_checks = hash_init_adv(128, NULL, (void (*)(void *)) destroy_chk_cell, NULL); /* XXX can do better :) */ /* init directory list to scan */ pzone->dirlist = da_init(); /* init man pages dynary */ pzone->manpgs = da_init(); /* init data files dynary */ pzone->datafiles = da_init(); /* init templates dynary */ pzone->templates = da_init(); /* init generated files dynary */ pzone->generated = da_init(); /* init tags dynary */ pzone->tags = da_init(); } return(pzone); } /*********************** * scan_zone_destroy() * *********************************************************************** DESCR destroy scan zone structure IN pzone : scan zone structure OUT NONE ***********************************************************************/ void scan_zone_destroy(scn_zone_t *pzone) { if (pzone->objects != NULL) { hash_destroy(pzone->objects); } if (pzone->targets != NULL) { hash_destroy(pzone->targets); } if (pzone->libraries != NULL) { hash_destroy(pzone->libraries); } if (pzone->h_checks != NULL) { hash_destroy(pzone->h_checks); } if (pzone->l_checks != NULL) { hash_destroy(pzone->l_checks); } if (pzone->t_checks != NULL) { hash_destroy(pzone->t_checks); } if (pzone->dirlist != NULL) { da_destroy(pzone->dirlist); } if (pzone->manpgs != NULL) { da_destroy(pzone->manpgs); } if (pzone->datafiles != NULL) { da_destroy(pzone->datafiles); } if (pzone->templates != NULL) { da_destroy(pzone->templates); } if (pzone->generated != NULL) { da_destroy(pzone->generated); } if (pzone->tags != NULL) { da_destroy(pzone->tags); } /* don't destroy discard and extra tags lists */ free(pzone); } /****************************** * pmkfile specific functions * ***********************************************************************/ /******************* * init_chk_cell() * *********************************************************************** DESCR initialize check cell IN NONE OUT pointer to new cell or NULL ***********************************************************************/ check_t *init_chk_cell(char *name) { check_t *pchk; pchk = (check_t *) malloc(sizeof(check_t)); if (pchk == NULL) { return(NULL); } /* set check name */ pchk->name = strdup(name); if (pchk->name == NULL) { free(pchk); return(NULL); } /* init procedure list */ pchk->procs = da_init(); if (pchk->procs == NULL) { free(pchk->name); free(pchk); return(NULL); } /* init misc */ pchk->header = NULL; pchk->library = NULL; pchk->member = NULL; pchk->subhdrs = NULL; return(pchk); } /********************** * destroy_chk_cell() * *********************************************************************** DESCR destroy allocated check cell IN pchk : check cell structure OUT NONE ***********************************************************************/ void destroy_chk_cell(check_t *pchk) { free(pchk->name); da_destroy(pchk->procs); free(pchk); } /***************** * mk_chk_cell() * *********************************************************************** DESCR make check cell IN pht : parser hash table token : cell type token OUT pointer to new cell or NULL ***********************************************************************/ check_t *mk_chk_cell(htable *pht, int token) { check_t *pchk; pchk = (check_t *) malloc(sizeof(check_t)); if (pchk != NULL) { /* get the name */ pchk->name = po_get_str(hash_get(pht, KW_OPT_NAM)); if (pchk->name == NULL) { free(pchk); return(NULL); } /* init */ pchk->procs = NULL; pchk->header = NULL; pchk->library = NULL; pchk->member = NULL; pchk->subhdrs = NULL; /* specific stuff */ switch (token) { case PSC_TOK_ADDHDR : /* get procedure list */ pchk->procs = po_get_list(hash_get(pht, KW_OPT_PRC)); /* get eventual related library */ pchk->library = po_get_str(hash_get(pht, KW_OPT_LIB)); /* get eventual sub headers */ pchk->subhdrs = po_get_list(hash_get(pht, KW_OPT_SUB)); break; case PSC_TOK_ADDLIB : /* get procedure list */ pchk->procs = po_get_list(hash_get(pht, KW_OPT_PRC)); break; case PSC_TOK_ADDTYP : /* get eventual header */ pchk->header = po_get_str(hash_get(pht, KW_OPT_HDR)); /* get eventual header */ pchk->member = po_get_str(hash_get(pht, KW_OPT_MBR)); break; } } return(pchk); } /********************* * parse_data_file() * *********************************************************************** DESCR parse data from PMKSCAN_DATA file IN pdata : parsing data structure scandata : scanning data structure OUT boolean (true on success) ***********************************************************************/ bool parse_data_file(prsdata *pdata, scandata *sdata) { FILE *fd; bool rval; check_t *pchk; prscell *pcell; fd = fopen(PMKSCAN_DATA, "r"); if (fd == NULL) { errorf("cannot open '%s' : %s.", PMKSCAN_DATA, strerror(errno)); return false; } /* init hash tables */ sdata->headers = hash_init_adv(256, NULL, free, NULL); sdata->libraries = hash_init_adv(256, NULL, free, NULL); sdata->types = hash_init_adv(256, NULL, free, NULL); rval = parse_pmkfile(fd, pdata, kw_pmkscan, nbkwps); fclose(fd); if (rval == false) { errorf("parsing of data file failed."); return(rval); } pcell = pdata->tree->first; while (pcell != NULL) { switch(pcell->token) { case PSC_TOK_ADDHDR : pchk = mk_chk_cell(pcell->data, pcell->token); if (pchk == NULL) { errorf("failed to initialize header check cell"); return false; } if (hash_add(sdata->headers, pchk->name, pchk) == HASH_ADD_FAIL) { errorf("failed to add '%s'", pchk->name); return false; } break; case PSC_TOK_ADDLIB : pchk = mk_chk_cell(pcell->data, pcell->token); if (pchk == NULL) { errorf("failed to initialize library check cell"); return false; } if (hash_add(sdata->libraries, pchk->name, pchk) == HASH_ADD_FAIL) { errorf("failed to add '%s'", pchk->name); return false; } break; case PSC_TOK_ADDTYP : pchk = mk_chk_cell(pcell->data, pcell->token); if (pchk == NULL) { errorf("failed to initialize type check cell"); return false; } if (hash_add(sdata->types, pchk->name, pchk) == HASH_ADD_FAIL) { errorf("failed to add '%s'", pchk->name); return false; } break; default : errorf("parsing of data file failed."); return false; break; } pcell = pcell->next; } return(rval); } /******************* * conv_to_label() * *********************************************************************** DESCR convert a string to a tag IN str : string to convert OUT pointer to the tag buffer ***********************************************************************/ char *conv_to_label(ftype_t ltype, char *fmt, ...) { static char buffer[TMP_BUF_LEN]; char *pbuf; size_t s; va_list plst; /* language prefix */ switch(ltype) { case FILE_TYPE_C : s = strlcpy(buffer, PMKSCAN_LABEL_C, sizeof(buffer)); break; case FILE_TYPE_CXX : s = strlcpy(buffer, PMKSCAN_LABEL_CXX, sizeof(buffer)); break; default : s = 0; } /* adjust pointer to end of language prefix */ pbuf = buffer + s; s = sizeof(buffer) - s; /* produce formatted string in the buffer */ va_start(plst, fmt); vsnprintf(pbuf, s, fmt, plst); va_end(plst); /* process the given string */ while ((*pbuf != '\0') && (s > 1)) { /* check if we have an alphanumeric character */ if (isalnum(*pbuf) == 0) { /* no, replace by an underscore */ *pbuf = '_'; } else { /* yes, convert to uppercase if needed */ *pbuf = (char) tolower((int) *pbuf); } /* next character */ s--; pbuf++; } /* end of string */ *pbuf = '\0'; return(buffer); } /********************** * recurse_sys_deps() * *********************************************************************** DESCR gather recursively the system include dependencies IN nodes : nodes hash table deps : dynary structure where to store dependencies nodename : node name to process recursively OUT boolean ***********************************************************************/ bool recurse_sys_deps(htable *nodes, dynary *deps, char *nodename) { char dir[PATH_MAX], *pstr; scn_node_t *pnode; size_t i; /* get node structure */ pnode = hash_get(nodes, nodename); /* should not fail */ if (pnode == NULL) { #ifdef PMKSCAN_DEBUG debugf("recurse_sys_deps() : node '%s' missing.", nodename); #endif /* PMKSCAN_DEBUG */ return true; } /* process all system headers linked to this node */ for (i = 0 ; i < da_usize(pnode->system_inc) ; i++) { pstr = (char *) da_idx(pnode->system_inc, i); /* check if the system header is already listed as a dependency */ if (da_find(deps, pstr) == false) { /* no, add it into the list */ if (da_push(deps, strdup(pstr)) == false) { return false; } } } /* get directory */ extract_dir(nodename, dir, sizeof(dir)); /* look for all the local dependencies of the current node */ for (i = 0 ; i < da_usize(pnode->local_inc) ; i++) { /* and recurse */ if (recurse_sys_deps(nodes, deps, (char *) da_idx(pnode->local_inc, i)) == false) { return false; } } return true; } /***************** * add_library() * *********************************************************************** DESCR generate a library check if a record exists for the given library IN checks : checks hash table library : library to add psd : scandata structure pn: node structure OUT boolean ***********************************************************************/ bool add_library(scn_zone_t *psz, char *library, scandata *psd, scn_node_t *pn) { char *label, *pstr, *tag, tmp[TMP_BUF_LEN]; check_t *pchk, *pcrec; size_t i, s; /* try to retrieve a check record for the given header */ pcrec = hash_get(psd->libraries, library); if (pcrec == NULL) { /* no record, skipping */ return true; } label = conv_to_label(pn->type, "library_%s", library); pchk = hash_get(psz->l_checks, label); if (pchk == NULL) { /* add new check */ pchk = init_chk_cell(library); if (pchk == NULL) { /* allocation failed */ errorf("failed to init check cell"); return false; } if (hash_update(psz->l_checks, label, pchk) == HASH_ADD_FAIL) { return false; } /* set language */ pchk->ftype = pn->type; /* add header tag */ snprintf(tmp, sizeof(tmp), "lib%s", library); tag = gen_basic_tag_def(tmp); if (da_find(psz->tags, tag) == false) { da_push(psz->tags, strdup(tag)); } } /* look for related procedures */ if (pcrec->procs != NULL) { s = da_usize(pcrec->procs); for (i = 0 ; i < s ; i++) { pstr = da_idx(pcrec->procs, i); /* if procedure has been found in parsing */ if (da_find(pn->func_calls, pstr) == true) { /* if it has not been added in the check yet */ if (da_find(pchk->procs, pstr) == false) { /* add in the list of function to check */ da_push(pchk->procs, strdup(pstr)); psc_log(NULL, "Node '%s': found procedure '%s'\n", pn->fname, pstr); /* add header tag */ tag = gen_basic_tag_def(pstr); if (da_find(psz->tags, tag) == false) { da_push(psz->tags, strdup(tag)); } } } } } return true; } /****************** * check_header() * *********************************************************************** DESCR generate an header check if a record exists for the given header IN checks : checks hash table header : header to process psd : scandata structure pn: node structure OUT boolean TODO add check if LIBRARY is specified ***********************************************************************/ bool check_header(scn_zone_t *psz, char *header, scandata *psd, scn_node_t *pn) { char *label, *pstr, *tag; check_t *pchk, *pcrec; size_t i, s; /* try to retrieve a check record for the given header */ pcrec = hash_get(psd->headers, header); if (pcrec == NULL) { /* no record, skipping */ return true; } label = conv_to_label(pn->type, "header_%s", header); pchk = hash_get(psz->h_checks, label); if (pchk == NULL) { /* add new check */ pchk = init_chk_cell(header); if (pchk == NULL) { /* allocation failed */ errorf("failed to init check cell"); return false; } if (hash_update(psz->h_checks, label, pchk) == HASH_ADD_FAIL) { return false; } /* set language */ pchk->ftype = pn->type; /* link to eventual sub headers */ pchk->subhdrs = pcrec->subhdrs; /* add AC style header tag */ tag = gen_basic_tag_def(header); if (da_find(psz->tags, tag) == false) { da_push(psz->tags, strdup(tag)); } /* add header tag */ tag = gen_tag_def(TAG_TYPE_HDR, header, NULL, NULL); if (da_find(psz->tags, tag) == false) { da_push(psz->tags, strdup(tag)); } } /* look for related procedures */ if (pcrec->procs != NULL) { s = da_usize(pcrec->procs); for (i = 0 ; i < s ; i++) { pstr = da_idx(pcrec->procs, i); /* if procedure has been found in parsing */ if (da_find(pn->func_calls, pstr) == true) { /* if it has not been added in the check yet */ if (da_find(pchk->procs, pstr) == false) { /* add in the list of function to check */ da_push(pchk->procs, strdup(pstr)); psc_log(NULL, "Node '%s': found procedure '%s'\n", pn->fname, pstr); /* add AC style header tag */ tag = gen_basic_tag_def(pstr); if (da_find(psz->tags, tag) == false) { da_push(psz->tags, strdup(tag)); } /* add header tag */ tag = gen_tag_def(TAG_TYPE_HDR_PRC, header, pstr, NULL); if (da_find(psz->tags, tag) == false) { da_push(psz->tags, strdup(tag)); } } } } } if (pcrec->library != NULL) { if (add_library(psz, pcrec->library, psd, pn) == false) { return false; } } return true; } /**************** * check_type() * *********************************************************************** DESCR generate a type check if a record exists for the given type IN checks : checks hash table type : type to process psd : scandata structure pn: node structure OUT boolean TODO handle member ? ***********************************************************************/ bool check_type(scn_zone_t *psz, char *type, scandata *psd, scn_node_t *pn) { char *label, *pstr; check_t *pchk, *pcrec; label = conv_to_label(pn->type, "type_%s", type); if (hash_get(psz->t_checks, label) != NULL) { /* check already exists */ return true; } /* try to retrieve a check record for the given header */ pcrec = hash_get(psd->types, type); if (pcrec == NULL) { /* no record */ return true; } /* add new check */ pchk = init_chk_cell(type); if (pchk == NULL) { /* allocation failed */ errorf("failed to init check cell"); return false; } /* set language */ pchk->ftype = pn->type; if (pcrec->header != NULL) { pchk->header = pcrec->header; /* XXX strdup ? */ } if (hash_update(psz->t_checks, label, pchk) == HASH_ADD_FAIL) { return false; } /* add AC style header tag */ pstr = gen_basic_tag_def(type); if (da_find(psz->tags, pstr) == false) { da_push(psz->tags, strdup(pstr)); } /* add header tag */ pstr = gen_tag_def(TAG_TYPE_TYPE, type, NULL, NULL); if (da_find(psz->tags, pstr) == false) { da_push(psz->tags, strdup(pstr)); } return true; } /**************** * gen_checks() * *********************************************************************** DESCR build pmkfile using gathered data IN psz : scanning zone data pht : check component hash table psd : parsing data structure OUT boolean ***********************************************************************/ bool gen_checks(scn_zone_t *psz, scandata *psd) { char *pstr; hkeys *phk; scn_node_t *pn; unsigned int i, j; /* for each node */ phk = hash_keys(psz->nodes); if (phk == NULL) { return true; } for(i = 0 ; i < phk->nkey ; i++) { pn = hash_get(psz->nodes, phk->keys[i]); /* no check needed */ /* check types */ if (psd->types != NULL) { /* process types */ for (j = 0 ; j < da_usize(pn->type_idtfs) ; j++) { pstr = (char *) da_idx(pn->type_idtfs, j); if (check_type(psz, pstr, psd, pn) == false) { errorf("check_type() failed."); hash_free_hkeys(phk); return false; } } } /* check headers */ if (psd->headers != NULL) { /* generate system dependencies */ recurse_sys_deps(psz->nodes, pn->sys_deps, pn->fname); /* process system dependencies */ for (j = 0 ; j < da_usize(pn->sys_deps) ; j++) { pstr = (char *) da_idx(pn->sys_deps, j); if (check_header(psz, pstr, psd, pn) == false) { errorf("check_header() failed."); hash_free_hkeys(phk); return false; } } } } hash_free_hkeys(phk); return true; } /********************* * build_cmd_begin() * *********************************************************************** DESCR output body start of a command IN fp : file pointer cmd : command name label : command label OUT - ***********************************************************************/ void build_cmd_begin(FILE *fp, char *cmd, char *label) { if (label == NULL) { fprintf(fp, PMKF_CMD_NOLABEL, cmd); } else { fprintf(fp, PMKF_CMD_LABEL, cmd, label); } } /******************* * build_cmd_end() * *********************************************************************** DESCR output body end of a command IN fp : file pointer OUT - ***********************************************************************/ void build_cmd_end(FILE *fp) { fprintf(fp, PMKF_CMD_END); } /******************* * build_comment() * *********************************************************************** DESCR output a comment line at the main level (no indent) IN fp : file pointer comment : comment text OUT - ***********************************************************************/ void build_comment(FILE *fp, char *fmt, ...) { va_list plst; /* build comment */ fprintf(fp, PMKF_COMMENT); /* format string */ va_start(plst, fmt); vfprintf(fp, fmt, plst); va_end(plst); fprintf(fp, "\n"); } /****************** * build_quoted() * *********************************************************************** DESCR output a quoted string assignment IN fp : file pointer vname : variable name qstr : quoted string content OUT - ***********************************************************************/ void build_quoted(FILE *fp, char *vname, char *qstr) { fprintf(fp, PMKF_VAR_QUOTED, vname, qstr); } /******************* * build_boolean() * *********************************************************************** DESCR output a boolean assignment IN fp : file pointer vname : variable name bval : boolean value OUT - ***********************************************************************/ void build_boolean(FILE *fp, char *vname, bool bval) { char *str; if (bval == true) { str = "TRUE"; } else { str = "FALSE"; } fprintf(fp, PMKF_VAR_BOOL, vname, str); } /**************** * build_list() * *********************************************************************** DESCR output a list assignment (if the list is not empty) IN fp : file pointer vname : variable name list : item list OUT - ***********************************************************************/ bool build_list(FILE *fp, char *vname, dynary *list) { size_t i, s; if (list == NULL) { return true; } /* get number of items */ s = da_usize(list); /* if no items then leave */ if (s == 0) { return false; } fprintf(fp, PMKF_VAR_LIST_BEG, vname); /* process all items but the last */ s--; for (i = 0 ; i < s ; i++) { fprintf(fp, PMKF_VAR_LIST_ITEM, (char *) da_idx(list, i)); } /* process last item */ fprintf(fp, PMKF_VAR_LIST_END, (char *) da_idx(list, s)); return true; } /************** * set_lang() * *********************************************************************** DESCR IN buf : storage buffer siz : size of buffer ltype : language type OUT boolean ***********************************************************************/ bool set_lang(FILE *fp, ftype_t ltype) { char *lang; /* set current language */ switch(ltype) { case FILE_TYPE_C : lang = PMKSCAN_LANG_C; break; case FILE_TYPE_CXX : lang = PMKSCAN_LANG_CXX; break; default : lang = NULL; } if (lang != NULL) { /* output language name */ build_quoted(fp, "LANG", lang); } return true; } /****************** * ouput_header() * *********************************************************************** DESCR ouput an header check IN checks : checks hash table header : header to process psd : scandata structure pn: node structure OUT boolean ***********************************************************************/ bool output_header(htable *checks, char *cname, FILE *fp) { check_t *pchk; pchk = hash_get(checks, cname); if (pchk == NULL) { return false; } /* output comment */ build_comment(fp, "check header %s", pchk->name); /* output pmk command */ build_cmd_begin(fp, "CHECK_HEADER", cname); /* output type name */ build_boolean(fp, "REQUIRED", false); /* output header name */ build_quoted(fp, "NAME", pchk->name); /* output language */ if (set_lang(fp, pchk->ftype) == false) { return false; } /* output list (already handle empty list) */ build_list(fp, "FUNCTION", pchk->procs); /* output list (already handle empty list) */ build_list(fp, "SUBHDR", pchk->subhdrs); /* output end of command body */ build_cmd_end(fp); fprintf(fp, "\n"); return true; } /******************* * ouput_library() * *********************************************************************** DESCR ouput a library check IN checks : checks hash table header : header to process psd : scandata structure pn: node structure OUT boolean ***********************************************************************/ bool output_library(htable *checks, char *cname, FILE *fp) { check_t *pchk; pchk = hash_get(checks, cname); if (pchk == NULL) { return false; } /* output comment */ build_comment(fp, "check library %s", pchk->name); /* output pmk command */ build_cmd_begin(fp, "CHECK_LIB", cname); /* output type name */ build_boolean(fp, "REQUIRED", false); /* output header name */ build_quoted(fp, "NAME", pchk->name); /* output language */ if (set_lang(fp, pchk->ftype) == false) { return false; } /* output list (already handle empty list) */ build_list(fp, "FUNCTION", pchk->procs); /* output end of command body */ build_cmd_end(fp); fprintf(fp, "\n"); return true; } /***************** * output_type() * *********************************************************************** DESCR ouput a type check IN checks : checks hash table type : type to process psd : scandata structure pn: node structure OUT boolean TODO handle member ? ***********************************************************************/ bool output_type(htable *checks, char *cname, FILE *fp) { check_t *pchk; pchk = hash_get(checks, cname); if (pchk == NULL) { return false; } /* output comment */ build_comment(fp, "check type %s", pchk->name); /* output pmk command */ build_cmd_begin(fp, "CHECK_TYPE", cname); /* output type name */ build_boolean(fp, "REQUIRED", false); /* output type name */ build_quoted(fp, "NAME", pchk->name); /* output language */ if (set_lang(fp, pchk->ftype) == false) { return false; } if (pchk->header != NULL) { /* output header name */ build_quoted(fp, "HEADER", pchk->header); } /* output end of command body */ build_cmd_end(fp); fprintf(fp, "\n"); return true; } /******************** * scan_build_pmk() * *********************************************************************** DESCR build pmkfile using gathered data IN fname : output file name psz : scanning zone data psd : parsing data structure OUT boolean ***********************************************************************/ bool scan_build_pmk(scn_zone_t *psz) { FILE *fp; char buf[MKF_OUTPUT_WIDTH * 2]; dynary *da; hkeys *phk; lib_cell_t *plc; time_t now; unsigned int i; /* open output file */ fp = fopen(psz->pmk_name, "w"); if (fp == NULL) { errorf("cannot open '%s' : %s.", psz->pmk_name, strerror(errno)); return false; } /* header comment ******************/ /* generating date */ now = time(NULL); strftime(buf, sizeof(buf), STR_TIME_GEN, localtime(&now)); /* output formatted string */ build_comment(fp, PMKF_HDR_GEN, buf); /* settings command ****************/ /* output command */ build_cmd_begin(fp, "SETTINGS", NULL); /* template list comment */ build_comment(fp, PMKF_TRGT_CMT); /* genere template list */ if (build_list(fp, "TARGET", psz->templates) == false) { /* list is empty, produce comment */ build_comment(fp, "TARGET = ()\t# TO EDIT"); } if (psz->gen_lib == true) { /* compilers to detect */ da = da_init(); if (psz->found[FILE_TYPE_C] == true) { /* check for C compiler */ da_push(da, strdup("C")); } if (psz->found[FILE_TYPE_CXX] == true) { /* check for C++ compiler */ da_push(da, strdup("C++")); } build_list(fp, "DETECT", da); da_destroy(da); } /* end of command */ build_cmd_end(fp); fprintf(fp, "\n"); /* define command ******************/ /* warning comment */ build_comment(fp, PMKF_DEF_CMT); /* output command */ build_cmd_begin(fp, "DEFINE", NULL); /* output package name */ fprintf(fp, PMKF_DEF_PKG); /* output directories */ fprintf(fp, PMKF_DEF_DIR); if (psz->gen_lib == true) { fprintf(fp, PMKF_DEF_LIB); fprintf(fp, PMKF_DEF_INC); /* XXX add a check for headers existence ? */ } /* output needed man directories */ if (psz->found[FILE_TYPE_MAN] == true) { /* man pages directories */ for (i = 1 ; i < 10 ; i++) { /* check if current category is needed */ if (psz->found[FILE_TYPE_MAN + i] == true) { fprintf(fp, PMKF_DEF_MAN, i, i); } } } /* extra tags */ if (psz->exttags != NULL) { da_sort(psz->exttags); /* output each extra tag */ for (i = 0 ; i < da_usize(psz->exttags) ; i++) { fprintf(fp, PMKF_DEF_TAG, (char *) da_idx(psz->exttags, i)); } } /* end of command */ build_cmd_end(fp); fprintf(fp, "\n"); /* type checks *********************/ phk = hash_keys_sorted(psz->t_checks); if (phk != NULL) { /* output every type checks */ for(i = 0 ; i < phk->nkey ; i++) { if (output_type(psz->t_checks, phk->keys[i], fp) == false) { hash_free_hkeys(phk); fclose(fp); return false; } } hash_free_hkeys(phk); } /* header checks *******************/ phk = hash_keys_sorted(psz->h_checks); if (phk != NULL) { /* output every header checks */ for(i = 0 ; i < phk->nkey ; i++) { if (output_header(psz->h_checks, phk->keys[i], fp) == false) { hash_free_hkeys(phk); fclose(fp); return false; } } hash_free_hkeys(phk); } /* library checks ******************/ phk = hash_keys_sorted(psz->l_checks); if (phk != NULL) { /* output every library checks */ for(i = 0 ; i < phk->nkey ; i++) { if (output_library(psz->l_checks, phk->keys[i], fp) == false) { hash_free_hkeys(phk); fclose(fp); return false; } } hash_free_hkeys(phk); } /* shared libraries ****************/ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { /* output every library */ for(i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); /* output command */ build_cmd_begin(fp, "BUILD_LIB_NAME", NULL); /* output lib name */ build_quoted(fp, "NAME", phk->keys[i]); /* output lib variables */ build_quoted(fp, "STATIC", plc->lib_static); build_quoted(fp, "SHARED", plc->lib_shared); if ((plc->lib_vmaj != NULL) && (plc->lib_vmin != NULL)) { /* output major version */ build_quoted(fp, "MAJOR", plc->lib_vmaj); /* output minor version */ build_quoted(fp, "MINOR", plc->lib_vmin); /* output versioned variable name */ build_boolean(fp, "VERSION", true); } else { /* output non versioned variable name */ build_boolean(fp, "VERSION", false); } /* end of command */ build_cmd_end(fp); } hash_free_hkeys(phk); } fprintf(fp, "\n"); fclose(fp); psc_log("Saved as '%s'\n", NULL, psz->pmk_name); return true; } /******************** * scan_build_cfg() * *********************************************************************** DESCR build config file using gathered data IN fname : output file name psz : scanning zone data psd : parsing data structure OUT boolean ***********************************************************************/ bool scan_build_cfg(scn_zone_t *psz) { FILE *fp; char buf[MKF_OUTPUT_WIDTH * 2], *pstr; time_t now; unsigned int i; fp = fopen(psz->cfg_name, "w"); if (fp == NULL) { errorf("unable to open file '%s' for writing.", psz->cfg_name); return false; } /* generating date */ now = time(NULL); strftime(buf, sizeof(buf), STR_TIME_GEN, localtime(&now)); fprintf(fp, CFGF_HDR_GEN, buf); if (psz->exttags != NULL) { fprintf(fp, "/* extra tags */\n\n"); for (i = 0 ; i < da_usize(psz->exttags) ; i++) { pstr = gen_basic_tag_def(da_idx(psz->exttags, i)); fprintf(fp, "@%s@\n\n", pstr); } } fprintf(fp, "/* scanned tags */\n\n"); for (i = 0 ; i < da_usize(psz->tags) ; i++) { fprintf(fp, "@%s@\n\n", (char *) da_idx(psz->tags, i)); } fclose(fp); psc_log("Saved as '%s'\n", NULL, psz->cfg_name); return true; } /******************************* * makefile specific functions * ***********************************************************************/ /*************** * find_deps() * *********************************************************************** DESCR check if function call list has at least one dependency with the function declaration list IN da_fc : function call list da_fd : function declaration list OUT boolean ***********************************************************************/ bool find_deps(dynary *da_fc, dynary *da_fd) { char *str_fc, *str_fd; size_t siz; unsigned int i, j; /* for each entry of the first dynary */ for (i = 0 ; i < da_usize(da_fc) ; i++) { str_fc = da_idx(da_fc, i); siz = strlen(str_fc) + 1; /* compare with each entry of the second dynary */ for (j = 0 ; j < da_usize(da_fd) ; j++) { str_fd = da_idx(da_fd, j); if (strncmp(str_fc, str_fd, siz) == 0) { psc_log(NULL, "\t\tFound common dependency '%s'\n", str_fc); /* and return true if a common dependency is found */ return true; } } } /* no common stuff found */ return false; } /***************** * extract_dir() * *********************************************************************** DESCR extract the directory portion of the given path IN path : original path dirbuf : buffer to store the extracted directory blen : buffer length OUT NONE ***********************************************************************/ void extract_dir(char *path, char *dirbuf, size_t blen) { char buffer[PATH_MAX], *p; /* work on a local copy due to implementations of dirname that do not preserve original string */ strlcpy(buffer, path, sizeof(buffer)); /* XXX check */ /* get directory part */ p = dirname(buffer); /* if the result start by "./" then skip it */ if ((p[0] == '.') && (p[1] == '/')) { p = p + 2; } /* copy result in storage location */ strlcpy(dirbuf, p, blen); /* XXX check */ } /**************** * build_path() * *********************************************************************** DESCR build a path from given directory and filename IN dir : directory string file : file name string buffer : buffer where to store the result blen : buffer length OUT NONE ***********************************************************************/ void build_path(char *dir, char *file, char *buffer, size_t blen) { char tmp[PATH_MAX], chk[PATH_MAX]; if (*dir == '\0') { /* directory empty, store only file name */ strlcpy(tmp, file, sizeof(tmp)); } else { /* join directory and file names with the directory separator */ snprintf(tmp, sizeof(tmp), "%s/%s", dir, file); } /* check resulting path */ chkpath(tmp, chk); strlcpy(buffer, chk, blen); } /********************** * recurse_obj_deps() * *********************************************************************** DESCR gather recursively the local include dependencies IN nodes : nodes hash table deps : dynary structure where to store dependencies nodename : node name to process recursively OUT boolean ***********************************************************************/ bool recurse_obj_deps(htable *nodes, dynary *deps, char *nodename) { char dir[PATH_MAX]; scn_node_t *pnode; size_t i; /* check if the node is already listed as target dependency */ if (da_find(deps, nodename) == true) { /* yes, skip processing */ return true; } /* else add the new dependency */ if (da_push(deps, strdup(nodename)) == false) { return false; } /* get node structure */ pnode = hash_get(nodes, nodename); /* should not fail */ if (pnode == NULL) { #ifdef PMKSCAN_DEBUG debugf("recurse_obj_deps() : node '%s' missing.", nodename); #endif /* PMKSCAN_DEBUG */ return true; } /* get directory */ extract_dir(nodename, dir, sizeof(dir)); /* look for all the local dependencies of the current node */ for (i = 0 ; i < da_usize(pnode->local_inc) ; i++) { /* and recurse */ if (recurse_obj_deps(nodes, deps, (char *)da_idx(pnode->local_inc, i)) == false) { return false; } } return true; } /***************** * gen_objects() * *********************************************************************** DESCR generate objects from the nodes IN psz : scanning zone data OUT boolean ***********************************************************************/ bool gen_objects(scn_zone_t *psz) { char buf[PATH_MAX], *pstr; hkeys *phk; scn_node_t *pnode, *pn; unsigned int i, j; phk = hash_keys(psz->nodes); if (phk == NULL) { /* no objects to process */ psc_log("No objects to generate.\n", NULL); return true; } for(i = 0 ; i < phk->nkey ; i++) { pnode = hash_get(psz->nodes, phk->keys[i]); /* XXX check needed ??? (think no) */ #ifdef PMKSCAN_DEBUG debugf("score of '%s' = %d", phk->keys[i], pnode->score); #endif /* PMKSCAN_DEBUG */ psc_log(NULL, "\tScore of '%s' = %d\n", phk->keys[i], pnode->score); /* if we got a node with a score of 0 then it should be an object */ if (pnode->score == 0) { /* build object name */ strlcpy(buf, pnode->prefix, sizeof(buf)); strlcat(buf, OBJ_SUFFIX, sizeof(buf)); psc_log(NULL, "\tAdding node '%s' linked to '%s' into object list\n", buf, pnode->fname); /* add object reference */ if (hash_update_dup(psz->objects, buf, pnode->fname) == HASH_ADD_FAIL) { hash_free_hkeys(phk); errorf("failed to update '%s' value with '%s'.", buf, pnode->fname); return false; } psc_log(NULL, "\tProcessing '%s'\n", buf); /* set object name */ pnode->obj_name = strdup(buf); /* build and store label name */ str_to_upper(buf, sizeof(buf), pnode->prefix); pnode->label = strdup(buf); /* generate object's source dependencies */ recurse_obj_deps(psz->nodes, pnode->src_deps, pnode->fname); /* for each local include */ for (j = 0 ; j < da_usize(pnode->local_inc) ; j++) { pstr = da_idx(pnode->local_inc, j); pn = hash_get(psz->nodes, pstr); if (pn == NULL) { #ifdef PMKSCAN_DEBUG debugf("gen_objects() : node '%s' missing.", pstr); #endif /* PMKSCAN_DEBUG */ continue; } /* check for common function declarators */ if (find_deps(pnode->func_decls, pn->func_decls) == true) { #ifdef PMKSCAN_DEBUG debugf("adding object link '%s' dependency to node '%s'", pnode->obj_name, pn->fname); #endif /* PMKSCAN_DEBUG */ psc_log(NULL, "\t\tAdding object link '%s' dependency to node '%s'\n", pnode->obj_name, pn->fname); /* and set object link if common declarator is found */ if (da_push(pn->obj_links, strdup(pnode->obj_name)) == false) { hash_free_hkeys(phk); errorf("failed to push '%s' into objects linking dependencies of '%s'.", buf, pn->fname); return false; } } } /* extra stuff */ if (pnode->type == FILE_TYPE_ASM) { /* try to find optionnal header file for assembly functions */ for(j = 0 ; j < phk->nkey ; j++) { pn = hash_get(psz->nodes, phk->keys[j]); /* check for common function declarators */ if (find_deps(pnode->func_decls, pn->func_decls) == true) { #ifdef PMKSCAN_DEBUG debugf("adding object link '%s' dependency to node '%s'", pnode->obj_name, pn->fname); #endif /* PMKSCAN_DEBUG */ psc_log(NULL, "\t\tAdding object link '%s' dependency to node '%s'\n", pnode->obj_name, pn->fname); /* and set object link if common declarator is found */ if (da_push(pn->obj_links, strdup(pnode->obj_name)) == false) { hash_free_hkeys(phk); errorf("failed to push '%s' into objects linking dependencies of '%s'.", buf, pn->fname); return false; } } } } } } hash_free_hkeys(phk); return true; } /********************** * recurse_src_deps() * *********************************************************************** DESCR generate targets from the objects IN psz : scanning zone data deps : dynary structure where to store object dependencies name : node name to process OUT boolean ***********************************************************************/ bool recurse_src_deps(scn_zone_t *psz, dynary *deps, char *name) { char *src, *odep; scn_node_t *pnode, *pn; size_t i, j; /* get node structure */ pnode = hash_get(psz->nodes, name); #ifdef PMKSCAN_DEBUG debugf("recurse_src_deps() : node '%s' START", pnode->fname); #endif /* PMKSCAN_DEBUG */ /* for each source dependency */ for (i = 0 ; i < da_usize(pnode->src_deps) ; i++) { /* get the node structure */ src = da_idx(pnode->src_deps, i); pn = hash_get(psz->nodes, src); if (pn == NULL) { #ifdef PMKSCAN_DEBUG debugf("recurse_src_deps() : source '%s' missing.", src); #endif /* PMKSCAN_DEBUG */ continue; } #ifdef PMKSCAN_DEBUG debugf("recurse_src_deps() : node '%s' : src dep '%s' (%d)", pnode->fname, src, da_usize(pn->obj_links)); #endif /* PMKSCAN_DEBUG */ /* check each object link */ for (j = 0 ; j < da_usize(pn->obj_links) ; j++) { /* get object name */ odep = da_idx(pn->obj_links, j); #ifdef PMKSCAN_DEBUG debugf("recurse_src_deps() : node '%s' : obj link '%s'", pnode->fname, odep); #endif /* PMKSCAN_DEBUG */ /* check if already in the list */ if (da_find(deps, odep) == false) { /* and add the object if not already present */ if (da_push(deps, strdup(odep)) == false) { errorf("failed to add '%s'", odep); return false; } #ifdef PMKSCAN_DEBUG debugf("recurse_src_deps() : node '%s' : adding '%s' in deps", pnode->fname, odep); #endif /* PMKSCAN_DEBUG */ /* recurse dependencies of this object */ src = hash_get(psz->objects, odep); #ifdef PMKSCAN_DEBUG debugf("recurse_src_deps() : node '%s' : => '%s'", pnode->fname, src); #endif if (recurse_src_deps(psz, deps, src) == false) { /* recurse failed */ return false; } } } } #ifdef PMKSCAN_DEBUG debugf("recurse_src_deps() : node '%s' END", pnode->fname); #endif /* PMKSCAN_DEBUG */ return true; } /***************** * gen_targets() * *********************************************************************** DESCR generate targets from the objects IN psz : scanning zone data OUT boolean ***********************************************************************/ bool gen_targets(scn_zone_t *psz) { char buf[PATH_MAX], *nodename; hkeys *phk; scn_node_t *pnode; unsigned int i; phk = hash_keys(psz->objects); if (phk == NULL) { /* no objects, skip */ psc_log("No targets to generate.\n", NULL); return true; } /* for each object */ for (i = 0 ; i < phk->nkey ; i++) { /* get it's node structure */ nodename = hash_get(psz->objects, phk->keys[i]); pnode = hash_get(psz->nodes, nodename); /* XXX check needed ??? (think no) */ /* if main procedure has been found then it's a target */ if (pnode->mainproc == true) { /* adding in the target list */ if (hash_update_dup(psz->targets, pnode->prefix, pnode->fname) == HASH_ADD_FAIL) { return false; } /* init object deps */ pnode->obj_deps = da_init(); if (pnode->obj_deps == NULL) { errorf("failed to init object dependencies dynary."); return false; } /* build and store object name */ strlcpy(buf, pnode->prefix, sizeof(buf)); strlcat(buf, OBJ_SUFFIX, sizeof(buf)); if (da_find(pnode->obj_deps, buf) == false) { if (da_push(pnode->obj_deps, strdup(buf)) == false) { /* XXX err msg */ return false; } } #ifdef PMKSCAN_DEBUG debugf("START recurse_src_deps() for node '%s'", pnode->fname); #endif /* PMKSCAN_DEBUG */ /* recurse source deps to find object deps */ if (recurse_src_deps(psz, pnode->obj_deps, pnode->fname) == false) { /* failed */ return false; } #ifdef PMKSCAN_DEBUG debugf("END recurse_src_deps() for node '%s'\n", pnode->fname); #endif /* PMKSCAN_DEBUG */ } } return true; } /********************* * gen_lib_targets() * *********************************************************************** DESCR generate targets from the objects IN psz : scanning zone data OUT boolean ***********************************************************************/ bool gen_lib_targets(scn_zone_t *psz) { char *srcname; hkeys *phk; lib_cell_t *plc; scn_node_t *pnode; unsigned int i, j; phk = hash_keys(psz->libraries); if (phk == NULL) { /* no libraries, skip */ psc_log("No library targets to generate.\n", NULL); return true; } /* for each library */ for (i = 0 ; i < phk->nkey ; i++) { /* get it's cell structure */ plc = hash_get(psz->libraries, phk->keys[i]); /* check each object link */ for (j = 0 ; j < da_usize(plc->src_list) ; j++) { /* get source name name */ srcname = da_idx(plc->src_list, j); /* fetch source node */ pnode = hash_get(psz->nodes, srcname); if (pnode == NULL) { psc_log("cannot find node '%s'.\n", NULL, srcname); return false; } if (da_find(plc->obj_deps, pnode->obj_name) == false) { /* push object name of source file into dependencies */ if (da_push(plc->obj_deps, strdup(pnode->obj_name)) == false) { /* XXX err msg */ return false; } } #ifdef PMKSCAN_DEBUG debugf("START recurse_src_deps() for source '%s'", srcname); #endif /* PMKSCAN_DEBUG */ /* recurse source deps to find object deps */ if (recurse_src_deps(psz, plc->obj_deps, srcname) == false) { /* failed */ return false; } #ifdef PMKSCAN_DEBUG debugf("END recurse_src_deps() for for source '%s'", srcname); #endif /* PMKSCAN_DEBUG */ } } return true; } /******************* * fprintf_width() * *********************************************************************** DESCR print in a file in a formated width IN width : width of a line offset : actual column offset fp : file stream str : string to append OUT new offset NOTE NONE could support of a left limit for indentation ***********************************************************************/ size_t fprintf_width(size_t left, size_t width, size_t offset, FILE *fp, char *str) { unsigned int i, m; size_t s, t; /* compute new offset with the string length */ s = strlen(str); t = offset + s; /* check if offset is greater than allowed width */ if (t < width) { if (left != offset) { /* not the first append */ fprintf(fp, " "); t++; } /* got enough space on the line */ fprintf(fp, "%s", str); offset = t; } else { /* compute number of tabs for the left margin */ m = (left / MKF_TAB_WIDTH); if ((left % MKF_TAB_WIDTH) != 0) { m++; } /* terminate current line */ fprintf(fp, " \\\n"); offset = 0; /* build left margin */ for (i = 0 ; i < m ; i ++) { fprintf(fp, "\t"); offset = offset + MKF_TAB_WIDTH; } /* print string */ fprintf(fp, "%s", str); offset = offset + s; } return(offset); } /*********************** * mkf_output_header() * *********************************************************************** DESCR ouput makefile template header IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_header(FILE *fp, scn_zone_t *psz) { char buf[MKF_OUTPUT_WIDTH * 2], *pstr; int i; size_t s; time_t now; /* generating date */ now = time(NULL); strftime(buf, sizeof(buf), STR_TIME_GEN, localtime(&now)); /* set header */ fprintf(fp, MKF_HEADER_GEN, buf); fprintf(fp, "\n# build tools\n"); /* assembly stuff */ if (psz->found[FILE_TYPE_ASM] == true) { fprintf(fp, MKF_HEADER_ASM); fprintf(fp, MKF_HEADER_CPP); } /* C stuff */ if (psz->found[FILE_TYPE_C] == true) { fprintf(fp, MKF_HEADER_C); } /* C++ stuff */ if (psz->found[FILE_TYPE_CXX] == true) { fprintf(fp, MKF_HEADER_CXX); } /* lex stuff */ if (psz->found[FILE_TYPE_LEX] == true) { fprintf(fp, MKF_HEADER_LEX); } /* yacc stuff */ if (psz->found[FILE_TYPE_YACC] == true) { fprintf(fp, MKF_HEADER_YACC); } /* library stuff */ if (psz->gen_lib == true) { if (psz->lib_type[LIB_TYPE_C] == true) { fprintf(fp, MKF_HDR_C_SL); } if (psz->lib_type[LIB_TYPE_CXX] == true) { fprintf(fp, MKF_HDR_CXX_SL); } fprintf(fp, MKF_HEADER_AR); fprintf(fp, MKF_HEADER_RANLIB); } /* misc stuff */ fprintf(fp, MKF_HEADER_MISC); fprintf(fp, MKF_LINE_JUMP); /* tool aliases */ fprintf(fp, "\n# tool aliases\n"); fprintf(fp, MKF_HEADER_ALIAS); fprintf(fp, MKF_LINE_JUMP); /* directories */ fprintf(fp, "# specific directories\n"); fprintf(fp, MKF_HEADER_DIR); if (psz->found[FILE_TYPE_MAN] == true) { /* main man pages directory */ fprintf(fp, MKF_MAN_DIR); /* man pages directories */ for (i = 1 ; i < 10 ; i++) { /* check if current category is needed */ if (psz->found[FILE_TYPE_MAN + i] == true) { fprintf(fp, MKF_MANX_DIR, i, i); } } } /* library install directory */ if (psz->gen_lib == true) { fprintf(fp, MKF_LIB_DIR); fprintf(fp, MKF_INC_DIR); /* add a check */ } /* system configuration directory */ fprintf(fp, MKF_SYSCONF_DIR); fprintf(fp, MKF_LINE_JUMP); /* package data */ fprintf(fp, "# packaging\n"); fprintf(fp, MKF_HEADER_DATA); /* XXX useful ? */ fprintf(fp, MKF_LINE_JUMP); /* extra tags */ if (psz->exttags != NULL) { fprintf(fp, "# extra tags\n"); da_sort(psz->exttags); /* output each extra tag */ s = da_usize(psz->exttags); for (i = 0 ; i < (int) s ; i++) { pstr = (char *) da_idx(psz->exttags, i); fprintf(fp, MKF_SUBSTVAR, pstr, pstr); } fprintf(fp, MKF_LINE_JUMP); } } /*********************** * mkf_output_recurs() * *********************************************************************** DESCR ouput recursively gathered items IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_recurs(FILE *fp, scn_zone_t *psz) { char *pstr; size_t ofst, lm, i, s; /* XXX not used yet */ /*|+ generate the list of scanned directories +| */ /*s = da_usize(psz->dirlist); */ /*if (s > 0) { */ /* |+ get directory list +| */ /* fprintf(fp, "#\n# directory list\n#\n"); */ /* fprintf(fp, MKF_SDIR_LIST); */ /* */ /* da_sort(psz->dirlist); */ /* */ /* lm = strlen(MKF_SDIR_LIST); */ /* ofst = lm; */ /* for (i = 0 ; i < s ; i++) { */ /* |+ get directory +| */ /* pstr = da_idx(psz->dirlist, i); */ /* */ /* |+ add to the list +| */ /* ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, pstr);*/ /* } */ /* */ /* fprintf(fp, MKF_TWICE_JUMP); */ /*} */ /*|+ generate the list of template files +| */ /*s = da_usize(psz->templates); */ /*if (s > 0) { */ /* |+ get list of template files +| */ /* fprintf(fp, "#\n# list of generated files\n#\n"); */ /* fprintf(fp, MKF_TEMPLATES); */ /* */ /* da_sort(psz->templates); */ /* */ /* lm = strlen(MKF_TEMPLATES); */ /* ofst = lm; */ /* for (i = 0 ; i < s ; i++) { */ /* |+ get template file name +| */ /* pstr = da_idx(psz->templates, i); */ /* */ /* |+ add to the list +| */ /* ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, pstr);*/ /* } */ /* */ /* fprintf(fp, MKF_TWICE_JUMP); */ /*} */ /* generate the list of template generated files */ s = da_usize(psz->templates); if (s > 0) { /* get list of generated files */ fprintf(fp, "#\n# list of generated files\n#\n"); fprintf(fp, MKF_GEN_FILES); da_sort(psz->templates); for (i = 0 ; i < s ; i++) { /* generate file name from template */ pstr = gen_from_tmpl(da_idx(psz->templates, i)); if (da_find(psz->generated, pstr) == false) { /* add default config file template in the list */ if (da_push(psz->generated, strdup(pstr)) == false) { /*return false; XXX make return boolean */ return; } } } lm = strlen(MKF_GEN_FILES); ofst = lm; s = da_usize(psz->generated); for (i = 0 ; i < s ; i++) { /* get generated file name */ pstr = da_idx(psz->generated, i); /* add result to the list */ ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, pstr); } fprintf(fp, MKF_TWICE_JUMP); } } /********************* * mkf_output_srcs() * *********************************************************************** DESCR output source lists IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_srcs(FILE *fp, scn_zone_t *psz) { char buf[MKF_OUTPUT_WIDTH * 2], *pstr; hkeys *phk; scn_node_t *pn; size_t ofst, lm, i, j; /* check if objects exist */ phk = hash_keys_sorted(psz->objects); if (phk == NULL) { /* nothing to do */ return; } fprintf(fp, "#\n# source dependency lists\n#\n"); for (i = 0 ; i < phk->nkey ; i++) { pstr = hash_get(psz->objects, phk->keys[i]); pn = hash_get(psz->nodes, pstr); /* object label */ snprintf(buf, sizeof(buf), MKF_OBJECT_SRCS, pn->label); fprintf(fp, buf); lm = strlen(buf); ofst = lm; da_sort(pn->src_deps); /* append sources */ for (j = 0 ; j < da_usize(pn->src_deps) ; j++) { ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, (char *) da_idx(pn->src_deps, j)); } fprintf(fp, MKF_TWICE_JUMP); } hash_free_hkeys(phk); } /********************* * mkf_output_bins() * *********************************************************************** DESCR output library name macros IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_bins(FILE *fp, scn_zone_t *psz) { char *pstr; hkeys *phk; scn_node_t *pn; size_t i; phk = hash_keys_sorted(psz->targets); if (phk != NULL) { /* generate binary name variables */ fprintf(fp, "#\n# binary name macros\n#\n"); for (i = 0 ; i < phk->nkey ; i++) { pstr = hash_get(psz->targets, phk->keys[i]); pn = hash_get(psz->nodes, pstr); fprintf(fp, "%s=\t%s\n\n", pn->label, pn->prefix); } hash_free_hkeys(phk); } } /********************* * mkf_output_libs() * *********************************************************************** DESCR output library name macros IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_libs(FILE *fp, scn_zone_t *psz) { char buf[MKF_OUTPUT_WIDTH * 2]; hkeys *phk; lib_cell_t *plc; size_t ofst, lm, i, j; phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { /* generate library name variables */ fprintf(fp, "#\n# library name macros\n#\n"); for (i = 0 ; i < phk->nkey ; i++) { plc = hash_get(psz->libraries, phk->keys[i]); fprintf(fp, "%s=\t%s\n", plc->lib_label, plc->lib_name); fprintf(fp, MKF_SUBSTVAR, plc->lib_static, plc->lib_static); fprintf(fp, MKF_SUBSTVAR, plc->lib_shared, plc->lib_shared); fprintf(fp, MKF_LIB_HEADERS, plc->lib_label); lm = strlen(buf); ofst = lm; da_sort(plc->hdr_list); /* append sources */ for (j = 0 ; j < da_usize(plc->hdr_list) ; j++) { ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, (char *) da_idx(plc->hdr_list, j)); } fprintf(fp, MKF_TWICE_JUMP); } hash_free_hkeys(phk); } } /********************* * mkf_output_objs() * *********************************************************************** DESCR output object lists IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_objs(FILE *fp, scn_zone_t *psz) { char buf[MKF_OUTPUT_WIDTH * 2], *pstr; hkeys *phk; lib_cell_t *plc; scn_node_t *pn; size_t ofst, lm, i, j; /* binaries *************************/ phk = hash_keys_sorted(psz->targets); if (phk != NULL) { /* generate target deps */ fprintf(fp, "#\n# binary target dependency lists\n#\n"); for (i = 0 ; i < phk->nkey ; i++) { pstr = hash_get(psz->targets, phk->keys[i]); pn = hash_get(psz->nodes, pstr); /* target label */ snprintf(buf, sizeof(buf), MKF_TARGET_OBJS, pn->label); fprintf(fp, buf); lm = strlen(buf); ofst = lm; da_sort(pn->obj_deps); /* append objects */ for (j = 0 ; j < da_usize(pn->obj_deps) ; j++) { ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, (char *) da_idx(pn->obj_deps, j)); } fprintf(fp, MKF_TWICE_JUMP); } hash_free_hkeys(phk); } /* shared libraries ****************/ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { /* output every library */ fprintf(fp, "#\n# library target dependency lists\n#\n"); for(i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); /* target label */ snprintf(buf, sizeof(buf), MKF_VARHDR, plc->lib_objs); fprintf(fp, buf); lm = strlen(buf); ofst = lm; da_sort(plc->obj_deps); /* append objects */ for (j = 0 ; j < da_usize(plc->obj_deps) ; j++) { ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, (char *) da_idx(plc->obj_deps, j)); } fprintf(fp, MKF_TWICE_JUMP); } hash_free_hkeys(phk); } } /************************* * mkf_output_suffixes() * *********************************************************************** DESCR ouput makefile template suffixes IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_suffixes(FILE *fp, scn_zone_t *psz) { /* suffixes */ fprintf(fp, MKF_SUFFIXES); /* assembly object build rule */ if (psz->found[FILE_TYPE_ASM] == true) { fprintf(fp, MKF_BLD_ASM_OBJ); } /* C object build rule */ if (psz->found[FILE_TYPE_C] == true) { fprintf(fp, MKF_BLD_C_OBJ); } /* C++ object build rule */ if (psz->found[FILE_TYPE_CXX] == true) { fprintf(fp, MKF_BLD_CXX_OBJ); } /* lex source build rule */ if (psz->found[FILE_TYPE_LEX] == true) { fprintf(fp, MKF_BLD_LEX_SRC); } /* yacc source build rule */ if (psz->found[FILE_TYPE_YACC] == true) { fprintf(fp, MKF_BLD_YACC_SRC); } } /*************************** * mkf_output_build_trgs() * *********************************************************************** DESCR output build targets IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_build_trgs(FILE *fp, scn_zone_t *psz) { bool need_sep; char buf[MKF_OUTPUT_WIDTH * 2], *pstr; hkeys *phk; lib_cell_t *plc; scn_node_t *pn; size_t ofst, lm, i; fprintf(fp, "#\n# target lists\n#\n"); /* generate main building target list */ fprintf(fp, "\n# building\n"); fprintf(fp, MKF_VARHDR, MKF_TRGT_BLD_VAR); need_sep = false; if (hash_nbkey(psz->targets) > 0) { /* if binary targets have been found */ fprintf(fp, MKF_VAR, MKF_TRGT_ALL_BIN); need_sep = true; } if (hash_nbkey(psz->libraries) > 0) { if (need_sep == true) { /* put a separator if needed */ fprintf(fp, " "); } /* if library targets have been found */ fprintf(fp, MKF_VAR, MKF_LIB_BLD_VAR); } fprintf(fp, MKF_TWICE_JUMP); if (hash_nbkey(psz->targets) > 0) { /* generate main binary building target list */ fprintf(fp, MKF_VARHDR, MKF_TRGT_ALL_BIN); /* list of binary targets */ phk = hash_keys_sorted(psz->targets); if (phk != NULL) { lm = strlen(MKF_TRGT_ALL_BIN); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { pstr = hash_get(psz->targets, phk->keys[i]); pn = hash_get(psz->nodes, pstr); snprintf(buf, sizeof(buf), "$(%s)", pn->label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } fprintf(fp, MKF_TWICE_JUMP); } if (hash_nbkey(psz->libraries) > 0) { /* generate main library building target list */ fprintf(fp, MKF_TRGT_ALL_LIB); fprintf(fp, MKF_LINE_JUMP); /* generate static libraries building target list */ fprintf(fp, MKF_VARHDR, MKF_STATIC_LIB_VAR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_STATIC_LIB_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); snprintf(buf, sizeof(buf), "$(%s)", plc->lib_static); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } fprintf(fp, MKF_TWICE_JUMP); /* generate shared libraries building target list */ fprintf(fp, MKF_SUBSTVAR, MKF_SHARED_LIB_VAR, MKF_SHARED_LIB_VAR); fprintf(fp, MKF_LINE_JUMP); /* C shared lib support */ if (psz->lib_type[LIB_TYPE_C] == true) { fprintf(fp, MKF_VARHDR, MKF_C_SHLIB_VAR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_C_SHLIB_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); if (plc->type == LIB_TYPE_C) { snprintf(buf, sizeof(buf), "$(%s)", plc->lib_shared); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } } fprintf(fp, MKF_LINE_JUMP); } /* C++ shared lib support */ if (psz->lib_type[LIB_TYPE_CXX] == true) { fprintf(fp, MKF_VARHDR, MKF_CXX_SHLIB_VAR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_CXX_SHLIB_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); if (plc->type == LIB_TYPE_CXX) { snprintf(buf, sizeof(buf), "$(%s)", plc->lib_shared); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } } fprintf(fp, MKF_LINE_JUMP); } } } /*************************** * mkf_output_clean_trgs() * *********************************************************************** DESCR output build targets IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_clean_trgs(FILE *fp, scn_zone_t *psz) { bool need_sep; char buf[MKF_OUTPUT_WIDTH * 2], *pstr; hkeys *phk; lib_cell_t *plc; scn_node_t *pn; size_t ofst, lm, i; /* generate main cleaning target list */ fprintf(fp, "\n# cleaning\n"); fprintf(fp, MKF_VARHDR, MKF_TRGT_CLEAN_VAR); need_sep = false; if (hash_nbkey(psz->targets) > 0) { /* if binary targets have been found */ fprintf(fp, MKF_VAR, MKF_BIN_CLEAN_VAR); need_sep = true; } if (hash_nbkey(psz->libraries) > 0) { if (need_sep == true) { /* put a separator if needed */ fprintf(fp, " "); } /* if library targets have been found */ fprintf(fp, MKF_VAR, MKF_LIB_CLEAN_VAR); } fprintf(fp, MKF_TWICE_JUMP); if (hash_nbkey(psz->targets) != 0) { /* generate main binary cleaning target list */ fprintf(fp, MKF_VARHDR, MKF_BIN_CLEAN_VAR); /* list of binary targets */ phk = hash_keys_sorted(psz->targets); if (phk != NULL) { lm = strlen(MKF_BIN_CLEAN_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { pstr = hash_get(psz->targets, phk->keys[i]); pn = hash_get(psz->nodes, pstr); snprintf(buf, sizeof(buf), "$(%s)_clean", pn->label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } hash_free_hkeys(phk); } fprintf(fp, MKF_TWICE_JUMP); } if (hash_nbkey(psz->libraries) > 0) { /* generate main library cleaning target list */ fprintf(fp, MKF_LIB_CLEAN_ALL); fprintf(fp, MKF_LINE_JUMP); /* generate static libraries building target list */ fprintf(fp, MKF_VARHDR, MKF_STLIB_CLN_VAR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_STLIB_CLN_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); snprintf(buf, sizeof(buf), "$(%s)_static_clean", plc->lib_label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } hash_free_hkeys(phk); } fprintf(fp, MKF_TWICE_JUMP); /* generate shared libraries cleaning target list */ fprintf(fp, MKF_SUBSTVAR, MKF_SHLIB_CLN_VAR, MKF_SHLIB_CLN_VAR); fprintf(fp, MKF_LINE_JUMP); /* C shared lib support */ if (psz->lib_type[LIB_TYPE_C] == true) { fprintf(fp, MKF_VARHDR, MKF_C_SHL_CLN_VAR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_C_SHL_CLN_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); if (plc->type == LIB_TYPE_C) { snprintf(buf, sizeof(buf), "$(%s)_shared_clean", plc->lib_label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } hash_free_hkeys(phk); } fprintf(fp, MKF_LINE_JUMP); } /* C++ shared lib support */ if (psz->lib_type[LIB_TYPE_CXX] == true) { fprintf(fp, MKF_VARHDR, MKF_CXX_SHL_CLN_VAR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_CXX_SHL_CLN_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); if (plc->type == LIB_TYPE_CXX) { snprintf(buf, sizeof(buf), "$(%s)_shared_clean", plc->lib_label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } hash_free_hkeys(phk); } fprintf(fp, MKF_LINE_JUMP); } } } /************************** * mkf_output_inst_trgs() * *********************************************************************** DESCR output build targets IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_inst_trgs(FILE *fp, scn_zone_t *psz) { bool need_sep; char buf[MKF_OUTPUT_WIDTH * 2], *pstr; hkeys *phk; lib_cell_t *plc; scn_node_t *pn; size_t ofst, lm, i; /* generate main installing target list */ fprintf(fp, "\n# installing\n"); /* main installing target list */ fprintf(fp, MKF_VARHDR, MKF_TRGT_INST_VAR); need_sep = false; if (hash_nbkey(psz->targets) > 0) { /* if binary targets have been found */ fprintf(fp, MKF_TRGT_INST_BIN); need_sep = true; } if (hash_nbkey(psz->libraries) > 0) { if (need_sep == true) { /* put a separator if needed */ fprintf(fp, " "); } /* if library targets have been found */ fprintf(fp, MKF_TRGT_INST_LIB); need_sep = true; } if (psz->found[FILE_TYPE_MAN] == true) { if (need_sep == true) { /* put a separator if needed */ fprintf(fp, " "); } /* if manual pages have been found */ fprintf(fp, MKF_TRGT_INST_MAN); need_sep = true; } if (psz->found[FILE_TYPE_DATA] == true) { if (need_sep == true) { /* put a separator if needed */ fprintf(fp, " "); } /* if data files have been found */ fprintf(fp, MKF_TRGT_INST_DATA); need_sep = true; } fprintf(fp, MKF_TWICE_JUMP); if (hash_nbkey(psz->targets) > 0) { /* generate main binary building target list */ fprintf(fp, MKF_VARHDR, MKF_BIN_INST_VAR); /* list of binary targets */ phk = hash_keys_sorted(psz->targets); if (phk != NULL) { lm = strlen(MKF_BIN_INST_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { pstr = hash_get(psz->targets, phk->keys[i]); pn = hash_get(psz->nodes, pstr); snprintf(buf, sizeof(buf), "$(%s)_install", pn->label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } fprintf(fp, MKF_TWICE_JUMP); } if (hash_nbkey(psz->libraries) > 0) { /* generate main library building target list */ fprintf(fp, MKF_LIB_INSTALL_ALL); fprintf(fp, MKF_LINE_JUMP); /* generate static libraries building target list */ fprintf(fp, MKF_VARHDR, MKF_STLIB_INST_VAR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_STLIB_INST_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); snprintf(buf, sizeof(buf), "$(%s)_static_install", plc->lib_label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } fprintf(fp, MKF_TWICE_JUMP); /* generate shared libraries building target list */ fprintf(fp, MKF_SUBSTVAR, MKF_SHLIB_INST_VAR, MKF_SHLIB_INST_VAR); fprintf(fp, MKF_LINE_JUMP); /* C shared lib support */ if (psz->lib_type[LIB_TYPE_C] == true) { fprintf(fp, MKF_VARHDR, MKF_C_SHL_INST_VAR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_C_SHL_INST_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); if (plc->type == LIB_TYPE_C) { snprintf(buf, sizeof(buf), "$(%s)_shared_install", plc->lib_label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } } fprintf(fp, MKF_LINE_JUMP); } /* C++ shared lib support */ if (psz->lib_type[LIB_TYPE_CXX] == true) { fprintf(fp, MKF_VARHDR, MKF_CXX_SHL_INST_VAR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_CXX_SHL_INST_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); if (plc->type == LIB_TYPE_CXX) { snprintf(buf, sizeof(buf), "$(%s)_shared_install", plc->lib_label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } } fprintf(fp, MKF_LINE_JUMP); } } } /**************************** * mkf_output_deinst_trgs() * *********************************************************************** DESCR output build targets IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_deinst_trgs(FILE *fp, scn_zone_t *psz) { bool need_sep; char buf[MKF_OUTPUT_WIDTH * 2], *pstr; hkeys *phk; lib_cell_t *plc; scn_node_t *pn; size_t ofst, lm, i; /* generate main deinstalling target list */ fprintf(fp, "\n# deinstalling\n"); /* main installing target list */ fprintf(fp, MKF_VARHDR, MKF_TRGT_DEINST_VAR); need_sep = false; if (hash_nbkey(psz->targets) > 0) { /* if binary targets have been found */ fprintf(fp, MKF_VAR, MKF_BIN_DEINST_VAR); need_sep = true; } if (hash_nbkey(psz->libraries) > 0) { if (need_sep == true) { /* put a separator if needed */ fprintf(fp, " "); } /* if library targets have been found */ fprintf(fp, MKF_VAR, MKF_LIB_DEINST_VAR); need_sep = true; } if (psz->found[FILE_TYPE_MAN] == true) { if (need_sep == true) { /* put a separator if needed */ fprintf(fp, " "); } /* if manual pages have been found */ fprintf(fp, MKF_TRGT_DEINST_MAN); need_sep = true; } if (psz->found[FILE_TYPE_DATA] == true) { if (need_sep == true) { /* put a separator if needed */ fprintf(fp, " "); } /* if data files have been found */ fprintf(fp, MKF_TRGT_DEINST_DATA); need_sep = true; } fprintf(fp, MKF_TWICE_JUMP); if (hash_nbkey(psz->targets) > 0) { /* generate main binary building target list */ fprintf(fp, MKF_VARHDR, MKF_BIN_DEINST_VAR); /* list of binary targets */ phk = hash_keys_sorted(psz->targets); if (phk != NULL) { lm = strlen(MKF_BIN_DEINST_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { pstr = hash_get(psz->targets, phk->keys[i]); pn = hash_get(psz->nodes, pstr); snprintf(buf, sizeof(buf), "$(%s)_deinstall", pn->label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } fprintf(fp, MKF_TWICE_JUMP); } if (hash_nbkey(psz->libraries) > 0) { /* generate main library building target list */ fprintf(fp, MKF_LIB_DEINSTALL_ALL); fprintf(fp, MKF_LINE_JUMP); /* generate static libraries building target list */ fprintf(fp, MKF_VARHDR, MKF_STLIB_DEINST_VAR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_STLIB_DEINST_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); snprintf(buf, sizeof(buf), "$(%s)_static_deinstall", plc->lib_label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } fprintf(fp, MKF_TWICE_JUMP); /* generate shared libraries building target list */ fprintf(fp, MKF_SUBSTVAR, MKF_SHLIB_DEINST_VAR, MKF_SHLIB_DEINST_VAR); fprintf(fp, MKF_LINE_JUMP); /* C shared lib support */ if (psz->lib_type[LIB_TYPE_C] == true) { fprintf(fp, MKF_VARHDR, MKF_C_SHL_DEINST_VAR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_C_SHL_DEINST_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); if (plc->type == LIB_TYPE_C) { snprintf(buf, sizeof(buf), "$(%s)_shared_deinstall", plc->lib_label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } } fprintf(fp, MKF_LINE_JUMP); } /* C++ shared lib support */ if (psz->lib_type[LIB_TYPE_CXX] == true) { fprintf(fp, MKF_VARHDR, MKF_CXX_SHL_DEINST_VAR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_CXX_SHL_DEINST_VAR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); if (plc->type == LIB_TYPE_CXX) { snprintf(buf, sizeof(buf), "$(%s)_shared_deinstall", plc->lib_label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } } } fprintf(fp, MKF_LINE_JUMP); } } } /************************* * mkf_output_man_trgs() * *********************************************************************** DESCR output man page targets IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_man_trgs(FILE *fp, scn_zone_t *psz) { char buf[MKF_OUTPUT_WIDTH * 2], *pstr; size_t ofst, lm, i, j, k; if (psz->found[FILE_TYPE_MAN] == false) { /* no man page, skip */ return; } /* generate man page lists */ for (i = 1 ; i < 10 ; i++) { /* if category has at least one file */ if (psz->found[FILE_TYPE_MAN + i] == true) { /* output category list macro */ snprintf(buf, sizeof(buf), MKF_FILE_MAN_VAR, (int) i); fprintf(fp, buf); lm = strlen(buf); ofst = lm; da_sort(psz->manpgs); /* for each man page */ for (j = 0 ; j < da_usize(psz->manpgs) ; j++) { /* get the last character */ pstr = da_idx(psz->manpgs, j); k = strlen(pstr) - 1; /* if the numeric conversion of the character is equal to the current man page category */ if ((size_t) atoi(&pstr[k]) == i) { /* record it into the list */ ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, pstr); } } fprintf(fp, MKF_TWICE_JUMP); } } } /************************** * mkf_output_data_trgs() * *********************************************************************** DESCR ouput data targets IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_data_trgs(FILE *fp, scn_zone_t *psz) { char buf[MKF_OUTPUT_WIDTH * 2], *pstr; size_t ofst, lm, i; if (psz->found[FILE_TYPE_DATA] == false) { /* no data files */ return; } /* data files */ fprintf(fp, MKF_FILE_DATA_VAR); lm = strlen(buf); ofst = lm; da_sort(psz->datafiles); /* for each data file */ for (i = 0 ; i < da_usize(psz->datafiles) ; i++) { pstr = da_idx(psz->datafiles, i); /* record it into the list */ ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, pstr); } fprintf(fp, MKF_TWICE_JUMP); } /************************** * mkf_output_obj_rules() * *********************************************************************** DESCR output object rules IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_obj_rules(FILE *fp, scn_zone_t *psz) { char buf[MKF_OUTPUT_WIDTH * 2], *pstr; hkeys *phk; scn_node_t *pn; size_t i; phk = hash_keys_sorted(psz->objects); if (phk == NULL) { /* nothing to do */ return; } fprintf(fp, "#\n# object rules\n#\n"); for (i = 0 ; i < phk->nkey ; i++) { pstr = hash_get(psz->objects, phk->keys[i]); pn = hash_get(psz->nodes, pstr); /* object label */ str_to_upper(buf, sizeof(buf), pn->prefix); fprintf(fp, MKF_OBJECT_LABL, phk->keys[i], buf); fprintf(fp, MKF_TWICE_JUMP); } hash_free_hkeys(phk); } /************************** * mkf_output_trg_rules() * *********************************************************************** DESCR output target rules IN fp : file pointer psz : scanning zone data OUT NONE ************************************************************************/ void mkf_output_trg_rules(FILE *fp, scn_zone_t *psz) { char *pstr, *pname; hkeys *phk; scn_node_t *pn; size_t i; phk = hash_keys_sorted(psz->targets); if (phk == NULL) { /* nothing to do */ return; } if (phk != NULL) { /* generate targets */ fprintf(fp, MKF_GTRGT_INST_BIN); for (i = 0 ; i < phk->nkey ; i++) { pstr = phk->keys[i]; pname = hash_get(psz->targets, phk->keys[i]); pn = hash_get(psz->nodes, pname); if (pn != NULL) { fprintf(fp, "# %s binary targets\n", phk->keys[i]); /* build target */ fprintf(fp, "$(%s): $(%s_OBJS)\n", pn->label, pn->label); /* process node depending on its type */ switch (pn->type) { /*case FILE_TYPE_ASM : XXX */ case FILE_TYPE_C : fprintf(fp, MKF_TARGET_C, pn->label); break; case FILE_TYPE_CXX : fprintf(fp, MKF_TARGET_CXX, pn->label); break; default : fprintf(fp, MKF_TARGET_DEF, pn->label); } } /* clean target */ fprintf(fp, MKF_TARGET_CLN, pn->label, pn->label, pn->label); /* install target */ fprintf(fp, MKF_INST_BIN, pn->label, pn->label, pn->label, pn->label); /* deinstall target */ fprintf(fp, MKF_DEINST_BIN, pn->label, pn->label); } hash_free_hkeys(phk); } } /****************************** * mkf_output_lib_trg_rules() * *********************************************************************** DESCR output library target rules IN fp : file pointer psz : scanning zone data OUT NONE ************************************************************************/ void mkf_output_lib_trg_rules(FILE *fp, scn_zone_t *psz) { char buf[MKF_OUTPUT_WIDTH * 2]; hkeys *phk; lib_cell_t *plc; size_t ofst, lm, i, j; phk = hash_keys_sorted(psz->libraries); if (phk == NULL) { /* nothing to do */ return; } /* generate targets */ fprintf(fp, MKF_GTRGT_INST_LIB); fprintf(fp, "\n# library headers install target\n"); fprintf(fp, MKF_TRGT, MKF_TRGT_INST_LIBHDR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_TRGT_INST_LIBHDR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); snprintf(buf, sizeof(buf), "$(%s)_headers_install", plc->lib_label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } hash_free_hkeys(phk); } fprintf(fp, MKF_TWICE_JUMP); fprintf(fp, "\n# library headers deinstall target\n"); fprintf(fp, MKF_TRGT, MKF_TRGT_DEINST_LIBHDR); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if (phk != NULL) { lm = strlen(MKF_TRGT_DEINST_LIBHDR); ofst = lm; for (i = 0 ; i < phk->nkey ; i++) { /* get lib cell */ plc = hash_get(psz->libraries, phk->keys[i]); snprintf(buf, sizeof(buf), "$(%s)_headers_deinstall", plc->lib_label); ofst = fprintf_width(lm, MKF_OUTPUT_WIDTH, ofst, fp, buf); } hash_free_hkeys(phk); } fprintf(fp, MKF_TWICE_JUMP); /* static library main targets */ fprintf(fp, MKF_TRGT_STLIBS); /* list of library targets */ phk = hash_keys_sorted(psz->libraries); if ((phk != NULL) && (psz->lib_type[LIB_TYPE_C] == true)) { /* C shared libs targets */ fprintf(fp, MKF_TRGT_C_SHLIBS); fprintf(fp, MKF_LINE_JUMP); } if ((phk != NULL) && (psz->lib_type[LIB_TYPE_CXX] == true)) { /* C++ shared libs targets */ fprintf(fp, MKF_TRGT_CXX_SHLIBS); fprintf(fp, MKF_LINE_JUMP); } for (i = 0 ; i < phk->nkey ; i++) { plc = hash_get(psz->libraries, phk->keys[i]); /* build target */ fprintf(fp, "# %s library targets\n", plc->lib_name); fprintf(fp, "$(%s)_headers_install: $(%s_HEADERS)\n", plc->lib_label, plc->lib_label); for (j = 0 ; j < da_usize(plc->hdr_list) ; j++) { /* install of each header */ fprintf(fp, "\t$(INSTALL_DATA) %s $(DESTDIR)$(INCDIR)/%s\n", (char *) da_idx(plc->hdr_list, j), (char *) da_idx(plc->hdr_list, j)); } fprintf(fp, MKF_LINE_JUMP); fprintf(fp, "$(%s)_headers_deinstall:\n", plc->lib_label); for (j = 0 ; j < da_usize(plc->hdr_list) ; j++) { /* install of each header */ fprintf(fp, "\t$(RM) $(RMFLAGS) $(DESTDIR)$(INCDIR)/%s\n", (char *) da_idx(plc->hdr_list, j)); } fprintf(fp, MKF_LINE_JUMP); fprintf(fp, "$(%s)_clean:\n", plc->lib_label); fprintf(fp, MKF_TARGET_LIB_CLN, plc->lib_objs); fprintf(fp, MKF_LINE_JUMP); fprintf(fp, MKF_TARGET_SIMPLE, plc->lib_static, plc->lib_objs); fprintf(fp, MKF_TARGET_LIB_STC, plc->lib_objs); fprintf(fp, "$(%s)_static_clean: $(%s)_clean\n", plc->lib_label, plc->lib_label); fprintf(fp, MKF_TARGET_LIB_CLN, plc->lib_static); fprintf(fp, MKF_LINE_JUMP); fprintf(fp, "$(%s)_static_install: $(%s)\n", plc->lib_label, plc->lib_static); fprintf(fp, MKF_INST_STLIB, plc->lib_static, plc->lib_static); fprintf(fp, MKF_LINE_JUMP); fprintf(fp, "$(%s)_static_deinstall:\n", plc->lib_label); fprintf(fp, "\t$(RM) $(RMFLAGS) $(DESTDIR)$(LIBDIR)/$(%s)\n", plc->lib_static); fprintf(fp, MKF_LINE_JUMP); fprintf(fp, MKF_TARGET_SIMPLE, plc->lib_shared, plc->lib_objs); switch(plc->type) { case LIB_TYPE_C : fprintf(fp, MKF_TARGET_SL_C, plc->lib_objs); break; case LIB_TYPE_CXX : fprintf(fp, MKF_TARGET_SL_CXX, plc->lib_objs); break; default : fprintf(fp, MKF_TARGET_LIB_SHD, plc->lib_objs); } fprintf(fp, "$(%s)_shared_clean: $(%s)_clean\n", plc->lib_label, plc->lib_label); fprintf(fp, MKF_TARGET_LIB_CLN, plc->lib_shared); fprintf(fp, MKF_LINE_JUMP); fprintf(fp, "$(%s)_shared_install: $(%s)\n", plc->lib_label, plc->lib_shared); fprintf(fp, MKF_INST_SHLIB, plc->lib_shared, plc->lib_shared); fprintf(fp, MKF_LINE_JUMP); fprintf(fp, "$(%s)_shared_deinstall:\n", plc->lib_label); fprintf(fp, "\t$(RM) $(RMFLAGS) $(DESTDIR)$(LIBDIR)/$(%s)\n", plc->lib_shared); fprintf(fp, MKF_LINE_JUMP); } hash_free_hkeys(phk); fprintf(fp, MKF_TWICE_JUMP); } /************************* * mkf_output_man_inst() * *********************************************************************** DESCR output manual pages install rule IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_man_inst(FILE *fp, scn_zone_t *psz) { char *pstr; size_t j, k; unsigned int i; /* manual pages to install */ fprintf(fp, MKF_INST_MAN_H); for (i = 1 ; i < 10 ; i++) { /* if category has at least one file */ if (psz->found[FILE_TYPE_MAN + i] == true) { /* output directory creation */ fprintf(fp, MKF_INST_MAN_D, i, i); /* for each man page */ for (j = 0 ; j < da_usize(psz->manpgs) ; j++) { /* get the last character */ pstr = da_idx(psz->manpgs, j); k = strlen(pstr) - 1; /* if the numeric conversion of the character is equal to the current man page category */ if ((size_t) atoi(&pstr[k]) == i) { fprintf(fp, MKF_INST_MAN_P, pstr, i, basename(pstr)); } } } } fprintf(fp, MKF_LINE_JUMP); /* manual pages to deinstall */ fprintf(fp, MKF_DEINST_MAN_H); for (i = 1 ; i < 10 ; i++) { /* if category has at least one file */ if (psz->found[FILE_TYPE_MAN + i] == true) { /* output directory */ fprintf(fp, MKF_DEINST_MAN_D, i); /* for each man page */ for (j = 0 ; j < da_usize(psz->manpgs) ; j++) { /* get the last character */ pstr = da_idx(psz->manpgs, j); k = strlen(pstr) - 1; /* if the numeric conversion of the character is equal to the current man page category */ if ((size_t) atoi(&pstr[k]) == i) { fprintf(fp, MKF_DEINST_MAN_P, i, basename(pstr)); } } } } fprintf(fp, MKF_LINE_JUMP); } /************************** * mkf_output_data_trgs() * *********************************************************************** DESCR ouput data targets IN fp : file pointer psz : scanning zone data OUT NONE ***********************************************************************/ void mkf_output_data_inst(FILE *fp, scn_zone_t *psz) { char *pstr; size_t i; da_sort(psz->datafiles); /* data files to install */ fprintf(fp, MKF_INST_DATA_H); for (i = 0 ; i < da_usize(psz->datafiles) ; i++) { pstr = da_idx(psz->datafiles, i); fprintf(fp, MKF_INST_DATA_P, pstr, basename(pstr)); } fprintf(fp, MKF_LINE_JUMP); /* data files to deinstall */ fprintf(fp, MKF_DEINST_DATA_H); for (i = 0 ; i < da_usize(psz->datafiles) ; i++) { pstr = da_idx(psz->datafiles, i); fprintf(fp, MKF_DEINST_DATA_P, basename(pstr)); } fprintf(fp, MKF_LINE_JUMP); } /********************* * scan_output_mkf() * *********************************************************************** DESCR build makefile using gathered data IN fname : file name psz : scanning zone data OUT NONE ***********************************************************************/ bool scan_build_mkf(scn_zone_t *psz) { FILE *fp, *fp_ext; bool ferr = false; char buf[512]; size_t len; fp = fopen(psz->mkf_name, "w"); if (fp == NULL) { errorf("unable to open file '%s' for writing.", psz->mkf_name); return false; } /* generate header and definitions */ mkf_output_header(fp, psz); /* generate recursive data */ mkf_output_recurs(fp, psz); /* generate object dependency lists */ mkf_output_srcs(fp, psz); /* generate binary name macros */ mkf_output_bins(fp, psz); /* generate library name macros */ mkf_output_libs(fp, psz); /* generate target dependency lists */ mkf_output_objs(fp, psz); /* generate building target list */ mkf_output_build_trgs(fp, psz); /* generate cleaning target list */ mkf_output_clean_trgs(fp, psz); /* generate installing target list */ mkf_output_inst_trgs(fp, psz); /* generate deinstalling target list */ mkf_output_deinst_trgs(fp, psz); /* manual pages to install/deinstall */ mkf_output_man_trgs(fp, psz); /* data files */ mkf_output_data_trgs(fp, psz); /* binaries to install/deinstall */ fprintf(fp, MKF_LINE_JUMP); fprintf(fp, MKF_FILE_BIN_VAR); fprintf(fp, MKF_FILE_SBIN_VAR); /* generate suffixes */ if (psz->found_src == true) { mkf_output_suffixes(fp, psz); } fprintf(fp, "\n#\n# generic targets\n#\n"); fprintf(fp, MKF_TARGET_ALL); /* fprintf(fp, MKF_TARGET_CFG); XXX TO ENABLE: auto config update target */ fprintf(fp, MKF_TARGET_INST); if (psz->found[FILE_TYPE_MAN] == true) { mkf_output_man_inst(fp, psz); } if (psz->found[FILE_TYPE_DATA] == true) { mkf_output_data_inst(fp, psz); } fprintf(fp, MKF_DIST_CLEAN); if (psz->unique == true) { fprintf(fp, MKF_LINE_JUMP); } else { /* recursive targets wrapper */ /* XXX not implemented yet */ } /* generate objects */ mkf_output_obj_rules(fp, psz); /* generate binary targets */ if (hash_nbkey(psz->targets) > 0) { mkf_output_trg_rules(fp, psz); } /* generate library targets */ if (hash_nbkey(psz->libraries) > 0) { mkf_output_lib_trg_rules(fp, psz); } /* extra to append */ if (psz->ext_mkf != NULL) { fp_ext = fopen(psz->ext_mkf, "r"); if (fp_ext == NULL) { errorf("unable to open file '%s' for reading.", psz->ext_mkf); return false; } /* append extra content to the template */ while ((feof(fp_ext) == 0) && (ferr == false)) { len = fread(buf, sizeof(char), sizeof(buf), fp_ext); if (ferror(fp_ext) != 0) { ferr = true; } else { fwrite(buf, sizeof(char), len, fp); if (ferror(fp) != 0) { ferr = true; } } } fclose(fp_ext); } fclose(fp); /* append failed */ if (ferr == true) { errorf("unable to append '%s' content into template.", psz->ext_mkf); return false; } psc_log("Saved as '%s'\n", NULL, psz->mkf_name); return true; } /******************** * common functions * ***********************************************************************/ /************** * psc_log () * *********************************************************************** DESCR log on standard output and log file if enabled IN fmt : standard output format string fmtl : log file format string ... : common parameters OUT NONE ***********************************************************************/ void psc_log(char *fmt, char *fmtl, ...) { va_list vlst, vlstl; va_start(vlst, fmtl); va_copy(vlstl, vlst); if (fmt != NULL) { vprintf(fmt, vlst); } /* if log is enabled */ if (fp_log != NULL) { /* if a log format is not provided take the first */ if (fmtl == NULL) { fmtl = fmt; } if (fmtl != NULL) { vfprintf(fp_log, fmtl, vlstl); } } va_end(vlst); } /****************** * str_to_upper() * *********************************************************************** DESCR store in the buffer the conversion in upper case of the string IN buf : storage buffer siz : size of buffer str : string to convert OUT NONE ***********************************************************************/ void str_to_upper(char *buf, size_t siz, char *str) { while ((siz > 1) && (*str != '\0')) { if ((*str == '.') || (*str == '/')) { /* replaces dot and slashes by underscores ex: if we got "../" then replace by "___" */ *buf = '_'; } else { /* else copy character in uppercase */ *buf = toupper(*str); } buf++; str++; siz--; } *buf = '\0'; } /******************** * check_file_ext() * *********************************************************************** DESCR check the file extension and return the supposed file type IN fname : file name OUT file type ***********************************************************************/ ftype_t check_file_ext(char *fname) { int i; for (i = 0 ; i < (int) nb_file_ext ; i++) { #ifdef PMKSCAN_DEBUG /*debugf("check '%s' extension with file '%s'", file_ext[i].ext, fname);*/ #endif /* PMKSCAN_DEBUG */ /* check files that match known extension */ if (fnmatch(file_ext[i].ext, fname, 0) != FNM_NOMATCH) { /* exit the loop */ return(file_ext[i].type); } } /* unknown type */ return(FILE_TYPE_UNKNOWN); } /****************** * process_ppro() * *********************************************************************** DESCR called when a preprocessor directive is found IN data : parsing data pstr : directive identifier ppe : parsing engine structure OUT boolean ***********************************************************************/ bool process_ppro(void *data, char *pstr, prseng_t *ppe) { char iname[PATH_MAX], buf[PATH_MAX], c; scn_node_t *pnode; scn_zone_t *psz; psz = (scn_zone_t *) data; pnode = psz->pnode; if (strncmp(pstr, RKW_PP_INCL, strlen(pstr) + 1) == 0) { prs_c_skip(ppe); /* XXX check ? */ c = prseng_get_char(ppe); prseng_next_char(ppe); /* XXX check */ prseng_get_idtf(ppe, iname, sizeof(iname), PRS_C_IDTF_FNAME); /* XXX check ? */ switch(c) { case '"' : #ifdef PMKSCAN_DEBUG debugf("process_ppro() : found local include '%s'", iname); #endif /* PMKSCAN_DEBUG */ /* build relative path of the include */ build_path(pnode->dname, iname, buf, sizeof(buf)); #ifdef PMKSCAN_DEBUG debugf("process_ppro() : adding include path '%s'", buf); #endif /* PMKSCAN_DEBUG */ /* add include in depedencies */ if (da_push(pnode->local_inc, strdup(buf)) == false) { errorf("unable to add '%s' in local deps", buf); return false; } psc_log(NULL, "\t\tFound local include '%s'.\n", iname); break; case '<' : #ifdef PMKSCAN_DEBUG debugf("process_ppro() : found system include '%s'", iname); #endif /* PMKSCAN_DEBUG */ /* add include in depedencies */ if (da_push(pnode->system_inc, strdup(iname)) == false) { errorf("unable to add '%s' in sys deps", iname); return false; } psc_log(NULL, "\t\tFound system include '%s'.\n", iname); break; default : return false; } } prs_c_line_skip(ppe); /* XXX check ? */ return true; } /*********************** * process_proc_call() * *********************************************************************** DESCR called when a procedure call is found IN data : parsing data pstr : function call identifier ppe : parsing engine structure OUT boolean ***********************************************************************/ bool process_proc_call(void *data, char *pstr, prseng_t *ppe) { scn_node_t *pnode; scn_zone_t *psz; psz = (scn_zone_t *) data; pnode = psz->pnode; #ifdef PMKSCAN_DEBUG debugf("process_proc_call() : found procedure call of '%s'", pstr); #endif /* PMKSCAN_DEBUG */ /* add function in list */ if (da_push(pnode->func_calls, strdup(pstr)) == false) { errorf("unable to add '%s' in function call list", pstr); return false; } psc_log(NULL, "\t\tFound procedure call '%s'.\n", pstr); return true; } /*********************** * process_proc_decl() * *********************************************************************** DESCR called when a procedure declaration is found IN data : parsing data pstr : function declarator identifier ppe : parsing engine structure OUT boolean ***********************************************************************/ bool process_proc_decl(void *data, char *pstr, prseng_t *ppe) { scn_node_t *pnode; scn_zone_t *psz; psz = (scn_zone_t *) data; pnode = psz->pnode; #ifdef PMKSCAN_DEBUG debugf("process_proc_decl() : found procedure declaration of '%s'", pstr); #endif /* PMKSCAN_DEBUG */ /* add function in list */ if (da_push(pnode->func_decls, strdup(pstr)) == false) { errorf("unable to add '%s' in function declaration list", pstr); return false; } /* check for main procedure */ if (strncmp(pstr, PSC_MAIN_C, strlen(pstr)) == 0) { #ifdef PMKSCAN_DEBUG debugf("process_proc_decl() : found main procedure '%s' in '%s'", pstr, pnode->fname); #endif /* PMKSCAN_DEBUG */ pnode->mainproc = true; } psc_log(NULL, "\t\tFound procedure declaration '%s'.\n", pstr); return true; } /****************** * process_type() * *********************************************************************** DESCR called when a type identifier is found IN data : parsing data pstr : type identifier ppe : parsing engine structure OUT boolean ***********************************************************************/ bool process_type(void *data, char *pstr, prseng_t *ppe) { scn_node_t *pnode; scn_zone_t *psz; psz = (scn_zone_t *) data; pnode = psz->pnode; /* add type in list */ if (da_push(pnode->type_idtfs, strdup(pstr)) == false) { errorf("unable to add '%s' in type list", pstr); return false; } psc_log(NULL, "\t\tFound type '%s'.\n", pstr); return true; } /**************** * parse_file() * *********************************************************************** DESCR parse a file that has a known type IN pcmn : common parser structure pnode : scan node structure fname : file to parse ft : file type isdep : dependency flag OUT boolean ***********************************************************************/ bool parse_file(prs_cmn_t *pcmn, char *fname, ftype_t ft, bool isdep) { FILE *fp; char *ptr, dir[PATH_MAX], idir[PATH_MAX]; scn_node_t *pnode; scn_zone_t *psz; unsigned int i; /* get misc data */ psz = (scn_zone_t *) pcmn->data; /* check if this node is already existing */ pnode = hash_get(psz->nodes, fname); if (pnode == NULL) { #ifdef PMKSCAN_DEBUG debugf("parse_file() : adding node for '%s'", fname); /* XXX */ #endif /* PMKSCAN_DEBUG */ /* open file */ fp = fopen(fname, "r"); if (fp == NULL) { fprintf(stderr, "Warning : cannot open '%s' : %s.\n", fname, strerror(errno)); return true; } /* create new node */ pnode = scan_node_init(fname); if (pnode == NULL) { errorf("unable to initialize scan node"); fclose(fp); return false; } /* set curret node */ psz->pnode = pnode; /* get directory name */ extract_dir(fname, dir, sizeof(dir)); /* and store it for further use */ pnode->dname = strdup(dir); pnode->type = ft; switch (ft) { case FILE_TYPE_ASM : psz->found[FILE_TYPE_ASM] = true; psz->found_src = true; psc_log(NULL, "\tStart parsing of assembly file '%s'\n", fname); if (prs_asm_file(pcmn, fp) == false) { fclose(fp); return false; } /* display parsed assembly file */ psc_log("a", "\tEnd of parsing of assembly file '%s'\n", fname); break; case FILE_TYPE_C : case FILE_TYPE_CXX : psz->found_src = true; if (ft == FILE_TYPE_C) { psz->found[FILE_TYPE_C] = true; psc_log(NULL, "\tStart parsing of C file '%s'\n", fname); } else { psz->found[FILE_TYPE_CXX] = true; psc_log(NULL, "\tStart parsing of C++ file '%s'\n", fname); } if (prs_c_file(pcmn, fp) == false) { fclose(fp); return false; } if (ft == FILE_TYPE_C) { /* display parsed c file */ psc_log("c", "\tEnd of parsing of C file '%s'\n", fname); } else { /* display parsed c++ file */ psc_log("C", "\tEnd of parsing of C++ file '%s'\n", fname); } break; } /* close file */ fclose(fp); } /* update dependency state */ pnode->isdep = isdep; if (isdep == true) { /* update dependency score */ pnode->score++; #ifdef PMKSCAN_DEBUG debugf("parse_file() : score of '%s' = %d", pnode->fname, pnode->score); #endif /* PMKSCAN_DEBUG */ } /* add the node in the table of nodes */ if (hash_add(psz->nodes, fname, pnode) == HASH_ADD_FAIL) { errorf("failed to add node '%s' in the hash table.", pnode->fname); scan_node_destroy(pnode); return false; } for (i = 0 ; i < da_usize(pnode->local_inc) ; i++) { ptr = (char *) da_idx(pnode->local_inc, i); #ifdef PMKSCAN_DEBUG debugf("parse_file() : dir = '%s', inc = '%s'", pnode->dname, ptr); #endif /* PMKSCAN_DEBUG */ /* scan local include */ if (scan_node_file(pcmn, ptr, true) == false) { errorf("failed to scan file '%s'.", ptr); return false; } /* add include directory in list */ extract_dir(ptr, idir, sizeof(idir)); #ifdef PMKSCAN_DEBUG debugf("parse_file() : include extracted dir = '%s'", idir); #endif /* PMKSCAN_DEBUG */ /* if the header directory is not yet in the scan list */ if ((*idir != '\0') && (da_find(psz->dirlist, idir) == false)) { #ifdef PMKSCAN_DEBUG debugf("parse_file() : adding '%s' in directory list to scan", idir); #endif /* PMKSCAN_DEBUG */ /* add in zone directory list for further process */ da_push(psz->dirlist, strdup(idir)); /* and in the list of directorie to be scanned */ da_push(psz->dirscan, strdup(idir)); } } return true; } /******************** * scan_node_file() * *********************************************************************** DESCR scan a node file to extract useful data IN pcmn : common parser structure fname : file to scan isdep : flag to notice if fname is a dependency or not OUT boolean ***********************************************************************/ bool scan_node_file(prs_cmn_t *pcmn, char *fname, bool isdep) { ftype_t ft; scn_zone_t *psz; #ifdef PMKSCAN_DEBUG debugf("scan_node_file() : fname = '%s'", fname); #endif /* PMKSCAN_DEBUG */ psz = (scn_zone_t *) pcmn->data; ft = check_file_ext(fname); switch (ft) { case FILE_TYPE_ASM : case FILE_TYPE_C : case FILE_TYPE_CXX : if (parse_file(pcmn, fname, ft, isdep) == false) { /* XXX err msg ? */ return false; } break; case FILE_TYPE_LEX : /* XXX TODO */ psc_log(".", "\tFound Lex file '%s' (unsupported yet)\n", fname); break; case FILE_TYPE_YACC : /* XXX TODO */ psc_log(".", "\tFound Yacc file '%s' (unsupported yet)\n", fname); break; case FILE_TYPE_MAN1 : case FILE_TYPE_MAN2 : case FILE_TYPE_MAN3 : case FILE_TYPE_MAN4 : case FILE_TYPE_MAN5 : case FILE_TYPE_MAN6 : case FILE_TYPE_MAN7 : case FILE_TYPE_MAN8 : case FILE_TYPE_MAN9 : /* man pages will be processed later */ psz->found[FILE_TYPE_MAN] = true; psz->found[ft] = true; /* add man page in the list */ da_push(psz->manpgs, strdup(fname)); /* XXX check ? */ #ifdef PMKSCAN_DEBUG debugf("scan_node_file() : added '%s' in psz->manpgs.", fname); #endif /* PMKSCAN_DEBUG */ /* display man page file as recorded */ psc_log("m", "\tRecorded manual page '%s'\n", fname); break; case FILE_TYPE_DATA : /* data files will be processed later */ psz->found[FILE_TYPE_DATA] = true; /* add data file in the list */ da_push(psz->datafiles, strdup(fname)); /* XXX check ? */ #ifdef PMKSCAN_DEBUG debugf("scan_node_file() : added '%s' in psz->datafiles.", fname); #endif /* PMKSCAN_DEBUG */ /* display data file as recorded */ psc_log("d", "\tRecorded data file '%s'\n", fname); break; case FILE_TYPE_TEMPL : /* data files will be processed later */ psz->found[FILE_TYPE_TEMPL] = true; /* if not already added */ if (da_find(psz->templates, fname) == false) { /* add template file in the list */ if (da_push(psz->templates, strdup(fname)) == false) { return false; } #ifdef PMKSCAN_DEBUG debugf("scan_node_file() : added '%s' in psz->templates.", fname); #endif /* PMKSCAN_DEBUG */ } /* display data file as recorded */ psc_log("t", "\tRecorded template file '%s'\n", fname); break; default : /* skip unsupported file extension */ /* display a file with unknown type */ psc_log(".", "\tFound file '%s' with unknown type\n", fname); } return true; } /************** * scan_dir() * *********************************************************************** DESCR scan a directory to find and scan known file type IN pcmn : common parser structure dir : directory to scan recursive : recursive flag OUT boolean ***********************************************************************/ bool scan_dir(prs_cmn_t *pcmn, char *dir, bool recursive) { struct dirent *pde; struct stat tstat; DIR *pd; char buf[PATH_MAX], *fname; dynary *hdr_dir, *to_scan = NULL; scn_zone_t *psz; size_t i; psz = pcmn->data; if ((psz->discard != NULL) && (da_find(psz->discard, dir) == true)) { /* discard directory */ psc_log("Discarding directory '%s'\n", NULL, dir); return true; } pd = opendir(dir); if (pd == NULL) { /* this is not a directory */ return false; } hdr_dir = da_init(); if (hdr_dir == NULL) { /* XXX msg ? */ closedir(pd); return false; } if (recursive == true) { to_scan = da_init(); if (to_scan == NULL) { /* XXX msg ? */ da_destroy(hdr_dir); closedir(pd); return false; } } /* set pointer to dynary of directories to scan */ psz->dirscan = hdr_dir; psc_log("Scanning directory '%s'\n", NULL, dir); psc_log("[", "[\n"); /* check each directory's entries */ while ((pde = readdir(pd)) && (pde != NULL)) { fname = pde->d_name; #ifdef PMKSCAN_DEBUG debugf("scan_dir() : checking entry '%s'", fname); #endif /* PMKSCAN_DEBUG */ if (*fname == '.') { /* skip every entries that starts with a dot */ #ifdef PMKSCAN_DEBUG debugf("scan_dir() : skipping '%s'", fname); #endif /* PMKSCAN_DEBUG */ continue; } /* build full path */ build_path(dir, fname, buf, sizeof(buf)); #ifdef PMKSCAN_DEBUG debugf("scan_dir() : built path = '%s'", buf); #endif /* PMKSCAN_DEBUG */ if (stat(buf, &tstat) == -1) { continue; } /* if the entry is a directory */ if ((tstat.st_mode & S_IFDIR) != 0) { /* and if recursivity is enabled */ if (recursive == true) { /* then process the directory */ if (da_find(psz->dirlist, buf) == false) { da_push(psz->dirlist, strdup(buf)); da_push(to_scan, strdup(buf)); } } /* go to next entry */ continue; } if (scan_node_file(pcmn, buf, false) == false) { /* display scan failure for the file */ psc_log("!", "Failed to scan '%s'", fname); } } closedir(pd); psc_log("]\n", "]\n\n"); /* scan directories of relative headers (no recurse) */ for (i = 0 ; i < da_usize(hdr_dir) ; i++) { scan_dir(pcmn, da_idx(hdr_dir, i), false); } da_destroy(hdr_dir); if (recursive == true) { /* recurse sub directories and directory found in headers */ for (i = 0 ; i < da_usize(to_scan) ; i++) { scan_dir(pcmn, da_idx(to_scan, i), true); } da_destroy(to_scan); } return true; } /****************** * process_zone() * *********************************************************************** DESCR process a scanning zone IN pcmn : common parser structure psd : scanning data structure OUT boolean (true on success) ***********************************************************************/ bool process_zone(prs_cmn_t *pcmn, scandata *psd) { bool frslt, rslt; char sdir[PATH_MAX]; scn_zone_t *psz; psz = pcmn->data; /* save current working directory */ if (getcwd(sdir, sizeof(sdir)) == NULL) { errorf("cannot get current working directory."); return false; } /* change to zone directory */ if (chdir(psz->directory) != 0) { errorf("cannot set working directory to '%s'.", psz->directory); return false; } /* scanning directory */ psc_log("Starting file parsing in '%s':\n", NULL, psz->directory); da_push(psz->dirlist, strdup(".")); frslt = scan_dir(pcmn, ".", psz->recursive); if (frslt == false) { psc_log("Parsing failed.\n\n", NULL); } else { psc_log("Parsing finished.\n\n", NULL); /* pmkfile stuff */ if (psz->gen_pmk == true) { /* compare with known functions in pmkscan db */ psc_log("Processing nodes for check generation ...\n", NULL); rslt = gen_checks(psz, psd); if (rslt == false) { psc_log("Failed\n\n", NULL); } else { psc_log("Ok\n\n", NULL); /* generate pmkfile */ psc_log("Generating %s ...\n", NULL, psz->pmk_name); rslt = scan_build_pmk(psz); if (rslt == true) { psc_log("Ok\n\n", NULL); } else { psc_log("Failed\n\n", NULL); } /* generate config file */ psc_log("Generating %s ...\n", NULL, psz->cfg_name); if (scan_build_cfg(psz) == true ) { psc_log("Ok\n\n", NULL); } else { psc_log("Failed\n\n", NULL); } } if (rslt == false) { frslt = false; } } /* makefile stuff */ if (psz->gen_mkf == true) { /* scanning resulting nodes */ psc_log("Processing nodes for object generation ...\n", NULL); rslt = gen_objects(psz); if (rslt == false) { psc_log("Failed\n\n", NULL); } else { psc_log("Ok\n\n", NULL); /* scanning generated objects */ psc_log("Processing objects for binary target generation ...\n", NULL); rslt = gen_targets(psz); if (rslt == false) { psc_log("Failed\n\n", NULL); } else { psc_log("Ok\n\n", NULL); psc_log("Processing objects for library target generation ...\n", NULL); rslt = gen_lib_targets(psz); if (rslt == false) { psc_log("Failed\n\n", NULL); } else { psc_log("Ok\n\n", NULL); /* generate makefile */ psc_log("Generating %s ...\n", NULL, psz->mkf_name); if (scan_build_mkf(psz) == true ) { psc_log("Ok\n\n", NULL); } else { psc_log("Failed\n\n", NULL); } } } } if (rslt == false) { frslt = false; } } } /* come back to previously saved directory */ if (chdir(sdir) != 0) { errorf("cannot set working directory back to '%s'.", sdir); return false; } return(frslt); } /****************** * parse_deflib() * *********************************************************************** DESCR define library parameters IN XXX OUT boolean ***********************************************************************/ bool parse_deflib(htable *pht, htable *libs) { char *name, *linker = NULL; dynary *srcs = NULL, *hdrs = NULL; int i; lib_cell_t *plc; ltype_t type = LIB_TYPE_UNKNOWN; pmkobj *ppo; /* get library name (REQUIRED) */ name = po_get_str(hash_get(pht, KW_OPT_NAM)); if (name == NULL) { return false; } /* get source list (REQUIRED) */ ppo = hash_extract(pht, KW_OPT_SRCS); /* XXX duplicate ? */ if (ppo == NULL) { return false; } srcs = po_get_list(ppo); /* get header list */ ppo = hash_extract(pht, KW_OPT_HDRS); /* XXX duplicate ? */ if (ppo != NULL) { hdrs = po_get_list(ppo); } /* get linker type */ linker = po_get_str(hash_get(pht, KW_OPT_LINKER)); /* check lib type */ for (i = 0 ; i < (int) nb_lib_types ; i++) { if (strncmp(lib_types[i].lang, linker, strlen(lib_types[i].lang) + 1) == 0) { type = lib_types[i].type; break; } } /* init lib cell */ plc = lib_cell_init(name, srcs, hdrs, type); if (plc == NULL) { return false; } /* get library major version number */ plc->lib_vmaj = po_get_str(hash_get(pht, KW_OPT_VMAJ)); /* get library minor version number */ plc->lib_vmin = po_get_str(hash_get(pht, KW_OPT_VMIN)); if (hash_add(libs, name, plc) == HASH_ADD_FAIL) { lib_cell_destroy(plc); return false; } psc_log("Recording library definition '%s'.\n", NULL, name); return true; } /*********************** * parse_zone_opts() * *********************************************************************** DESCR XXX IN XXX OUT XXX ***********************************************************************/ bool parse_zone_opts(prs_cmn_t *pcmn, htable *pht, htable *libs) { char *pdir, *pstr; dynary *da_l; /* library list */ pmkobj *ppo; htable *tnodes; lib_cell_t *plc; scn_zone_t *psz; size_t i; /* init of nodes table */ tnodes = hash_init_adv(2048, NULL, (void (*)(void *))scan_node_destroy, NULL); if (tnodes == NULL) { /* XXX errmsg !! */ return false; } /* init zone structure */ psz = scan_zone_init(tnodes); if (psz == NULL) { /* XXX err msg */ hash_destroy(tnodes); return false; } pcmn->data = psz; /* get pmkfile switch */ ppo = hash_get(pht, KW_OPT_PMK); if (ppo != NULL) { psz->gen_pmk = po_get_bool(ppo); if (psz->gen_pmk == true) { /* alternate name for config file template */ ppo = hash_get(pht, KW_OPT_CFGALT); if (ppo != NULL) { pstr = po_get_str(ppo); if (pstr == NULL) { return false; } /* set config file template name */ psz->cfg_name = pstr; } else { /* add default config file template in the list */ if (da_push(psz->templates, strdup(PMKSCAN_CFGFILE)) == false) { return false; } #ifdef PMKSCAN_DEBUG debugf("parse_zone_opts() : added '%s' in psz->templates.", PMKSCAN_CFGFILE); #endif /* PMKSCAN_DEBUG */ } /* alternate name for pmkfile template */ ppo = hash_get(pht, KW_OPT_PMKALT); if (ppo != NULL) { pstr = po_get_str(ppo); if (pstr == NULL) { return false; } /* set pmkfile file template name */ psz->pmk_name = pstr; } } } /* get makefile switch */ ppo = hash_get(pht, KW_OPT_MKF); if (ppo != NULL) { psz->gen_mkf = po_get_bool(ppo); if (psz->gen_mkf == true) { /* alternate name for makefile template */ ppo = hash_get(pht, KW_OPT_MKFALT); /* check new option */ if (ppo != NULL) { pstr = po_get_str(ppo); if (pstr == NULL) { return false; } /* set makefile name */ psz->mkf_name = po_get_str(ppo); /* add alternative makefile template in the list */ if (da_push(psz->templates, strdup(pstr)) == false) { return false; } #ifdef PMKSCAN_DEBUG debugf("parse_zone_opts() : added '%s' in psz->templates.", pstr); #endif /* PMKSCAN_DEBUG */ } else { /* add default makefile template in the list */ if (da_push(psz->templates, strdup(PMKSCAN_MKFILE)) == false) { return false; } #ifdef PMKSCAN_DEBUG debugf("parse_zone_opts() : added '%s' in psz->templates.", PMKSCAN_MKFILE); #endif /* PMKSCAN_DEBUG */ } /* extra to append to makefile template */ ppo = hash_get(pht, KW_OPT_EXTMKF); if (ppo != NULL) { pstr = po_get_str(ppo); if (pstr != NULL) { /* set config file name name */ psz->ext_mkf = pstr; } else { return false; } } } } /* get base directory (REQUIRED) */ pdir = po_get_str(hash_get(pht, KW_OPT_DIR)); psz->directory = strdup(pdir); /* get discard list */ ppo = hash_get(pht, KW_OPT_DSC); if (ppo != NULL) { psz->discard = po_get_list(ppo); } /* get library name list */ ppo = hash_get(pht, KW_OPT_LIB); if (ppo != NULL) { da_l = po_get_list(ppo); if (da_l != NULL) { for (i = 0 ; i < da_usize(da_l) ; i++) { /* get lib name */ pstr = da_idx(da_l, i); /* look for lib cell */ plc = hash_extract(libs, pstr); if (plc == NULL) { /* lib cell not found */ return false; } /* adds the extracted cell in zone libraries */ if (hash_add(psz->libraries, pstr, plc) == HASH_ADD_FAIL) { return false; } /* set library type flag */ psz->lib_type[plc->type] = true; } } psz->gen_lib = true; } /* get recursivity switch (OPTIONAL, false by default) */ ppo = hash_get(pht, KW_OPT_REC); if (ppo != NULL) { psz->recursive = po_get_bool(ppo); } /* get unique file switch (OPTIONAL, false by default) */ ppo = hash_get(pht, KW_OPT_UNI); if (ppo != NULL) { psz->unique = po_get_bool(ppo); } /* get extra tags list */ ppo = hash_get(pht, KW_OPT_EXTTAG); if (ppo != NULL) { psz->exttags = po_get_list(ppo); } return true; } /****************** * parse_script() * *********************************************************************** DESCR parse script file IN cfname : configuration script filename pcmn : common parser structure psd : scanning data structure OUT boolean (true on success) ***********************************************************************/ bool parse_script(char *cfname, prs_cmn_t *pcmn, scandata *psd) { FILE *fd; bool frslt = true; htable *lcells; prscell *pcell; prsdata *pdata; scn_zone_t *psz; fd = fopen(cfname, "r"); if (fd == NULL) { errorf("cannot open '%s' : %s.", cfname, strerror(errno)); return false; } /* init of library cells hash table */ lcells = hash_init_adv(32, NULL, (void (*)(void *)) lib_cell_destroy, NULL); if (lcells == NULL) { /* XXX errmsg */ return false; } /* initialise parsing data structure */ pdata = prsdata_init(); if (pdata == NULL) { /* XXX errmsg */ return false; } if (parse_pmkfile(fd, pdata, kw_scanfile, nbkwsf) == false) { fclose(fd); prsdata_destroy(pdata); errorf("parsing of script file failed."); return false; } fclose(fd); pcell = pdata->tree->first; while (pcell != NULL) { switch(pcell->token) { case PSC_TOK_DEFLIB : if (parse_deflib(pcell->data, lcells) == false) { errorf("parsing of script file failed (token %d).", pcell->token); prsdata_destroy(pdata); return false; } break; case PSC_TOK_PMKF : case PSC_TOK_MAKF : case PSC_TOK_ZONE : if (parse_zone_opts(pcmn, pcell->data, lcells) == false) { errorf("parsing of script file failed (token %d).", pcell->token); prsdata_destroy(pdata); return false; } /* process current zone */ if (process_zone(pcmn, psd) == false) { frslt = false; } /* free scan zone stuff */ psz = pcmn->data; hash_destroy(psz->nodes); scan_zone_destroy(psz); break; default : errorf("parsing of script file failed (unexpected token %d).", pcell->token); prsdata_destroy(pdata); return false; break; } pcell = pcell->next; } prsdata_destroy(pdata); return(frslt); } /*********** * usage() * *********************************************************************** DESCR pmkscan(1) usage IN NONE OUT NONE ***********************************************************************/ void usage(void) { fprintf(stderr, "usage: pmkscan [-hlv] [-f file] [path]\n"); } /********** * main() * *********************************************************************** DESCR main loop. ***********************************************************************/ int main(int argc, char *argv[]) { bool go_exit = false; char scfile[PATH_MAX] = PMKSCAN_CONFIG; int chr; prs_cmn_t pcmn; prsdata *pdata = NULL; scandata sd; while (go_exit == false) { chr = getopt(argc, argv, "f:hlv"); switch (chr) { case -1 : go_exit = true; break; case 'f' : /* use alternate script file */ strlcpy(scfile, optarg, sizeof(scfile)); /* XXX test !! */ break; case 'l' : fp_log = fopen("pmkscan.log", "w"); if (fp_log == NULL) { /* XXX err msg */ exit(EXIT_FAILURE); } break; case 'v' : /* display version */ fprintf(stdout, "%s\n", PREMAKE_VERSION); exit(EXIT_SUCCESS); break; case 'h' : case '?' : default : usage(); exit(EXIT_FAILURE); /* NOTREACHED */ } } argc = argc - optind; argv = argv + optind; psc_log("PMKSCAN version %s\n\n", NULL, PREMAKE_VERSION); psc_log("Initializing data ... \n", NULL); /* init common parser structure */ pcmn.func_ppro = &process_ppro; pcmn.func_proc = &process_proc_call; pcmn.func_decl = &process_proc_decl; pcmn.func_type = &process_type; pcmn.data = NULL; /* will be updated later */ /* initialise parsing data structure */ pdata = prsdata_init(); if (pdata == NULL) { errorf("\ncannot initialize prsdata."); exit(EXIT_FAILURE); } else { if (parse_data_file(pdata, &sd) == false) { /* error message displayed by parse_data_file */ prsdata_destroy(pdata); exit(EXIT_FAILURE); } } psc_log("Using scanning script '%s'.\n", NULL, scfile); if (parse_script(scfile, &pcmn, &sd) == false) { exit(EXIT_FAILURE); } prsdata_destroy(pdata); if (fp_log != NULL) { fclose(fp_log); } return(0); } /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/functool.h010064400017500000000000000066401051201023000132350ustar00mipswheel/* $Id: functool.h 1904 2006-10-07 20:39:52Z 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. * */ #ifndef _PMK_FUNCTOOL_H_ #define _PMK_FUNCTOOL_H_ #include "common.h" #include "hash_tools.h" #include "pmk.h" #include "premake.h" /************* * constants * **********************************************************************************************/ #define LANG_NAME_LEN 64 #define COMP_NAME_LEN 64 #define PRE_NAME_LEN 64 #define CFLG_NAME_LEN 64 #define SHFLG_NAME_LEN 64 #define KW_OPT_DEPEND "DEPEND" #define KW_OPT_LANG "LANG" #define KW_OPT_REQUIRED "REQUIRED" #define CHAR_VERSION_SEPARATOR '.' /********************************** * type and structure definitions * ***********************************************************************/ typedef struct { char name[LANG_NAME_LEN], comp[COMP_NAME_LEN], pre[PRE_NAME_LEN], cflg[CFLG_NAME_LEN], slflg[CFLG_NAME_LEN]; } lgdata; /************** * prototypes * ***********************************************************************/ bool check_bool_str(char *); bool invert_bool(bool); char *bool_to_str(bool); bool get_file_dir_path(char *, char *, char *, int); bool find_pattern(dynary *, char *, char *, int); bool record_def(htable *, char *, bool); bool record_def_data(htable *, char *, char *); bool record_def_adv(htable *, int, char *, char *, char *, char *); bool process_def_list(htable *, dynary *, bool); bool record_have(htable *, char *, char *); bool label_set(htable *, char *, bool); bool label_check(htable *, char *); bool depend_check(htable *, pmkdata *); bool require_check(htable *); char *get_lang_str(htable *, pmkdata *); bool check_cfgt_data(pmkdata *); bool process_required(pmkdata *, pmkcmd *, bool , char *, char *); bool obsolete_string_to_list(htable *, char *); #endif /* _PMK_FUNCTOOL_H_ */ /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/dynarray.h010064400017500000000000000052011027375242700132560ustar00mipswheel/* $Id: dynarray.h 1434 2005-08-02 20:18:31Z mipsator $ */ /* * 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. * */ #ifndef _PMK_DYNARRAY_H_ #define _PMK_DYNARRAY_H_ #include "compat/pmk_stdbool.h" /************* * constants * ************************************************************************/ #ifndef DYNARY_AUTO_GROW #define DYNARY_AUTO_GROW 4 #endif /********************************** * type and structure definitions * ***********************************************************************/ typedef struct { int nbcell, nextidx; void (*freeobj)(void *), **pary; } dynary; /************************ * functions prototypes * ***********************************************************************/ dynary *da_init(void); dynary *da_init_adv(void (*)(void *)); bool da_resize(dynary *, size_t); size_t da_size(dynary *); size_t da_usize(dynary *); bool da_push(dynary *, void *); void *da_pop(dynary *); void *da_shift(dynary *); void *da_idx(dynary *, int); void da_destroy(dynary *); bool da_find(dynary *, char *); void da_sort(dynary *); #endif /* _PMK_DYNARRAY_H_ */ pmk-0.10.4/codebuild.h010075500017500000000000000127721062512151600133630ustar00mipswheel/* $Id: codebuild.h 1989 2007-05-23 20:25:50Z coudercd $ */ /* * Copyright (c) 2005-2006 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. * */ #ifndef _PMK_CODEBUILD_H_ #define _PMK_CODEBUILD_H_ #include "compat/pmk_stdbool.h" #include "compat/pmk_stdio.h" #include "dynarray.h" #include "hash.h" #include "lang.h" #include "premake.h" /************* * constants * **********************************************************************************************/ /* linking methods */ enum { LINK_NONE = 0, /* no linking */ LINK_SRC, /* link source */ LINK_OBJ /* link object */ }; #define C_FILE_EXT ".c" #define BIN_TEST_NAME TMPDIR "/pmk_XXXXXXXX" #define TEST_FILE_NAME BIN_TEST_NAME C_FILE_EXT #define CODE_C_HDR "#include <%s>\n" #define CODE_C_BEG "/* main procedure */\n" \ "int main() {\n" #define CODE_C_END "return(0);\n" \ "}\n" #define CODE_C_DEF "/* check define */\n" \ "#ifndef %s\n" \ "break_build_process();\n" \ "#endif\n" #define CODE_C_DECL "int %s();\n\n" #define CODE_C_PROC "/* check procedure */\n" \ "void (*pmk_funcp)() = (void *) %s;\n" #define CODE_C_VAR "%s test_var;\n\n" #define CODE_C_TYPE "/* check type */\n" \ "if (sizeof(test_var)) {\n" \ "\treturn(0);\n" \ "}\n" #define CODE_C_MEMBER "/* check structure member */\n" \ "if (sizeof(test_var.%s)) {\n" \ "\treturn(0);\n" \ "}\n" #define CODE_C_SHARED_F "/* simple C function for shared object */\n" \ "void shfunc(void);\n\n" \ "void shfunc(void) {\n" \ "\tint i = 0;\n\n" \ "\ti++;\n" \ "}\n" #define CODE_C_SHARED_M "/* main object */\n" \ "void shfunc(void);\n\n" \ "int main() {\n" \ "\tshfunc();\n" \ "\treturn(0);\n" \ "}\n" /********************************** * type and structure definitions * ***********************************************************************/ /* code building cell */ typedef struct { char binfile[MAXPATHLEN], /* binary file */ bldcmd[MAXPATHLEN], /* building command buffer */ objfile[MAXPATHLEN], /* binary file */ srcfile[MAXPATHLEN], /* source file */ *header, /* header filename */ *library, /* library name */ *define, /* macro name */ *procedure, /* procedure name */ *type, /* type name */ *member, /* type member name */ *pathcomp, /* compiler path */ *cflags, /* compilation flags */ *ldflags, /* linker flags */ *slcflags, /* shared lib compilation flags */ *slldflags, /* shared lib linking flags */ *alt_cflags, /* alternative compilation flags variable */ *alt_libs, /* alternative linker flags variable */ *blog; /* build log */ dynary *subhdrs; /* header dependencies */ int lang; /* language id */ lgdata_t *pld; /* pointer to related language structure */ } code_bld_t; /************** * prototypes * ***********************************************************************/ void name_randomize(char *); void code_bld_init(code_bld_t *, char *); int verify_language(char *); bool set_language(code_bld_t *, char *); char *set_compiler(code_bld_t *, htable *t); void set_cflags(code_bld_t *, char *); void set_ldflags(code_bld_t *, char *); void set_slcflags(code_bld_t *, char *); void set_slldflags(code_bld_t *, char *); char *get_lang_label(code_bld_t *); char *get_compiler_label(code_bld_t *); char *get_cflags_label(code_bld_t *); char *get_libs_label(code_bld_t *); void code_logger(FILE *, FILE *, const char *, ...); bool code_builder(code_bld_t *); bool c_code_builder(code_bld_t *); bool shared_builder(code_bld_t *, char *); bool c_shared_builder(code_bld_t *, char *); bool cmdline_builder(code_bld_t *, int); bool c_cmdline_builder(code_bld_t *, int); bool object_builder(code_bld_t *); void cb_cleaner(code_bld_t *); bool check_so_support(code_bld_t *, char *, char *); char *obsolete_get_lang_from_comp(char *); #endif /* _PMK_CODEBUILD_H_ */ /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/pmkscan.h010064400017500000000000000624061060720600100130520ustar00mipswheel/* $Id: pmkscan.h 1966 2007-04-11 16:25:37Z 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. * */ #ifndef _PMKSCAN_H_ #define _PMKSCAN_H_ #include "dynarray.h" #include "hash.h" #include "lang.h" #include "parse_lang.h" /************* * constants * ***********************************************************************/ /* pmkscan specific version */ #define PREMAKE_SUBVER_PMKSCAN "6" #ifndef DATADIR /* for lint */ #define DATADIR "/DATADIR_not_defined" #endif #define PMKSCAN_DATA DATADIR "/pmkscan.dat" #define PMKSCAN_CFGFILE "config.h.pmk" #define PMKSCAN_PMKFILE "pmkfile" #define PMKSCAN_MKFILE "Makefile.pmk" #define PMKSCAN_CONFIG "scanfile" /* languages, should use lgdata later */ #define PMKSCAN_LANG_C LANG_LABEL_C #define PMKSCAN_LANG_CXX LANG_LABEL_CXX /* label language strings */ #define PMKSCAN_LABEL_C "c_" #define PMKSCAN_LABEL_CXX "cxx_" #define PSC_MAIN_C "main" /* parser tokens *******************************************************/ /* pmkscan data */ enum { PSC_TOK_FUNC = 1, PSC_TOK_INCL, PSC_TOK_TYPE, PSC_TOK_ADDHDR, PSC_TOK_ADDLIB, PSC_TOK_ADDTYP }; /* pmkscan script */ enum { PSC_TOK_PMKF = 1, PSC_TOK_MAKF, PSC_TOK_ZONE, PSC_TOK_DEFLIB, PSC_TOK_DEFLIBS, PSC_TOK_SETLIB }; /* command keywords */ #define KW_CMD_ADDHDR "ADD_HEADER" #define KW_CMD_ADDLIB "ADD_LIBRARY" #define KW_CMD_ADDTYP "ADD_TYPE" /* command keyword options */ #define KW_OPT_HDR "HEADER" #define KW_OPT_MBR "MEMBER" #define KW_OPT_PRC "PROCEDURE" #define KW_OPT_SUB "SUBHDR" /* script keywords */ #define KW_CMD_GENPF "GEN_PMKFILE" #define KW_CMD_GENMF "GEN_MAKEFILE" #define KW_CMD_GENZN "GEN_ZONE" #define KW_CMD_DEFLIB "DEFINE_LIB" /* script keyword options */ #define KW_OPT_ADVTAG "ADVTAG" #define KW_OPT_CFGALT "CFGNAME" #define KW_OPT_DIR "DIRECTORY" #define KW_OPT_DSC "DISCARD" #define KW_OPT_EXTMKF "EXTRAMKF" #define KW_OPT_EXTTAG "EXTRATAG" #define KW_OPT_LINKER "LINKER" #define KW_OPT_MKF "MAKEFILE" #define KW_OPT_MKFALT "MKFNAME" #define KW_OPT_PMK "PMKFILE" #define KW_OPT_PMKALT "PMKNAME" #define KW_OPT_REC "RECURSE" #define KW_OPT_SRCS "SOURCES" #define KW_OPT_HDRS "HEADERS" #define KW_OPT_UNI "UNIQUE" #define KW_OPT_VMAJ "VMAJ" #define KW_OPT_VMIN "VMIN" /* common options */ #define KW_OPT_LIB "LIBRARY" #define KW_OPT_NAM "NAME" /* file types **********************************************************/ enum { FILE_TYPE_UNKNOWN = 0, FILE_TYPE_ASM, FILE_TYPE_C, FILE_TYPE_CXX, FILE_TYPE_DATA, FILE_TYPE_IMG, FILE_TYPE_HTML, FILE_TYPE_LEX, /* WARNING : respect the following order as it is used in pmkscan procedures. Common type MAN comes first followed by category types from MAN1 to MAN9. */ FILE_TYPE_MAN, FILE_TYPE_MAN1, FILE_TYPE_MAN2, FILE_TYPE_MAN3, FILE_TYPE_MAN4, FILE_TYPE_MAN5, FILE_TYPE_MAN6, FILE_TYPE_MAN7, FILE_TYPE_MAN8, FILE_TYPE_MAN9, /* end of man categories */ FILE_TYPE_TEMPL, FILE_TYPE_TEXT, FILE_TYPE_YACC, NB_FILE_TYPE /* number of file types */ }; /* library types *******************************************************/ enum { LIB_TYPE_UNKNOWN = 0, LIB_TYPE_ASM, LIB_TYPE_C, LIB_TYPE_CXX, NB_LIB_TYPE /* number of library types */ }; /* object type *********************************************************/ enum { OBJ_TYPE_UNKNOWN = 0, OBJ_TYPE_ASM, OBJ_TYPE_C, OBJ_TYPE_CXX }; /**************** * misc defines * ***********************************************************************/ #define OBJ_SUFFIX ".o" #define STR_TIME_GEN "%Y-%m-%d %H:%M" #define CFGF_HDR_GEN "/* config file template built by pmkscan (%s) */\n" \ "/* @configure_input@ */\n\n" /******************* * pmkfile defines * ***********************************************************************/ #define PMKF_HDR_GEN "pmkfile generated by pmkscan (%s).\n" #define PMKF_TRGT_CMT "list of template files" #define PMKF_DEF_CMT "main defines (NEED MANUAL EDITION)" #define PMKF_DEF_PKG "\tPACKAGE = \"mypackage\"\n" #define PMKF_DEF_DIR "\tBINDIR = \"\\\\$(PREFIX)/bin\"\n" \ "\tSBINDIR = \"\\\\$(PREFIX)/sbin\"\n" \ "\tMANDIR = \"\\\\$(PREFIX)/man\"\n" \ "\tDATADIR = \"\\\\$(PREFIX)/share/\\\\$(PACKAGE)\"\n" #define PMKF_DEF_LIB "\tLIBDIR = \"\\\\$(PREFIX)/lib\"\n" #define PMKF_DEF_INC "\tINCDIR = \"\\\\$(PREFIX)/include\"\n" #define PMKF_DEF_MAN "\tMAN%dDIR = \"\\\\$(MANDIR)/man%d\"\n" #define PMKF_DEF_TAG "\t%s = \"extra tag to edit\"\n" #define PMKF_CMD_NOLABEL "%s {\n" #define PMKF_CMD_LABEL "%s(%s) {\n" #define PMKF_CMD_END "}\n" #define PMKF_COMMENT "# " #define PMKF_VAR_BOOL "\t%s = %s\n" #define PMKF_VAR_QUOTED "\t%s = \"%s\"\n" #define PMKF_VAR_LIST_BEG "\t%s = (" #define PMKF_VAR_LIST_ITEM "\"%s\", " #define PMKF_VAR_LIST_END "\"%s\")\n" /******************** * makefile defines * ***********************************************************************/ /* misc defines ***********************/ #define MKF_OUTPUT_WIDTH 72 #define MKF_TAB_WIDTH 8 #define MKF_LINE_JUMP "\n" #define MKF_TWICE_JUMP "\n\n" #define MKF_HEADER_GEN "# Makefile template built by pmkscan (%s)\n" \ "# @configure_input@\n\n" #define MKF_OBJ_SRCS_VAR "%s_SRCS" #define MKF_OBJECT_SRCS MKF_OBJ_SRCS_VAR "=\t" #define MKF_TRGT_OBJS_VAR "%s_OBJS" #define MKF_TARGET_OBJS MKF_TRGT_OBJS_VAR "=\t" #define MKF_TRGT_HDRS_VAR "%s_HDRS" #define MKF_SUBSTVAR "%s=\t@%s@\n" #define MKF_VARHDR "%s=\t" #define MKF_VAR "$(%s)" #define MKF_STCLIB_VAR "%s=\t$(%s).a\n" #define MKF_LIB_HEADERS "%s_HEADERS=\t" #define MKF_TRGT "%s: " #define MKF_VARTRGT "$(%s): " #define MKF_HEADER_DATA "PACKAGE=\t@PACKAGE@\n\n" /* labels *****************************/ #define MKF_LABEL_AR "AR" #define MKF_LABEL_AS "AS" #define MKF_LABEL_CPP "CPP" #define MKF_LABEL_INSTALL "INSTALL" #define MKF_LABEL_LEX "LEX" #define MKF_LABEL_LN "LN" #define MKF_LABEL_RANLIB "RANLIB" #define MKF_LABEL_RM "RM" #define MKF_LABEL_YACC "YACC" /* build tools ************************/ #define MKF_HEADER_ASM MKF_LABEL_AS "=\t\t@" MKF_LABEL_AS "@\n" \ MKF_LABEL_AS "FLAGS=\n" #define MKF_HEADER_CPP MKF_LABEL_CPP "=\t\t@" MKF_LABEL_CPP "@\n" #define MKF_HEADER_C COMP_LABEL_C "=\t\t@" COMP_LABEL_C "@\n" \ CFLAGS_LABEL_C "=\t\t@" CFLAGS_LABEL_C "@\n" \ LDFLAGS_LABEL_C "=\t@" LDFLAGS_LABEL_C "@\n" #define MKF_HDR_C_SL SLCFLAGS_LABEL_C "=\t@" SLCFLAGS_LABEL_C "@\n" \ SLLDFLAGS_LABEL_C "=\t@" SLLDFLAGS_LABEL_C "@\n" #define MKF_HEADER_CXX COMP_LABEL_CXX "=\t\t@" COMP_LABEL_CXX "@\n" \ CFLAGS_LABEL_CXX "=\t@" CFLAGS_LABEL_CXX "@\n" \ LDFLAGS_LABEL_CXX "=\t@" LDFLAGS_LABEL_CXX "@\n" #define MKF_HDR_CXX_SL SLCFLAGS_LABEL_CXX "=\t@" SLCFLAGS_LABEL_CXX "@\n" \ SLLDFLAGS_LABEL_CXX "=\t@" SLLDFLAGS_LABEL_CXX "@\n" #define MKF_HEADER_YACC MKF_LABEL_YACC "=\t@" MKF_LABEL_YACC "@\n" \ MKF_LABEL_YACC "FLAGS=\t@" MKF_LABEL_YACC "FLAGS@\n" #define MKF_HEADER_LEX MKF_LABEL_LEX "=\t@" MKF_LABEL_LEX "@\n" \ MKF_LABEL_LEX "FLAGS=\t@" MKF_LABEL_LEX "FLAGS@\n" #define MKF_HEADER_LD "LD=\t\t@LD@\n" \ "# LDFLAGS shall contain -lc if used with ld\n" \ "LDFLAGS=\t-lc @LDFLAGS@\n\n" #define MKF_HEADER_AR MKF_LABEL_AR "=\t\t@" MKF_LABEL_AR "@\n" \ MKF_LABEL_AR "FLAGS=\tcru\n" /*MKF_LABEL_AR "FLAGS=\t@" MKF_LABEL_AR "FLAGS@\n"*/ #define MKF_HEADER_RANLIB MKF_LABEL_RANLIB "=\t\t@" MKF_LABEL_RANLIB "@\n" #define MKF_HEADER_MISC MKF_LABEL_INSTALL "=\t@" MKF_LABEL_INSTALL"@\n" \ MKF_LABEL_RM "=\t\trm\n" \ MKF_LABEL_RM "FLAGS=\t-rf\n" /* tool aliases ***********************/ #define MKF_HEADER_ALIAS "INSTALL_BIN=\t$(INSTALL) -m 755\n" \ "INSTALL_SBIN=\t$(INSTALL) -m 755\n" \ "INSTALL_STLIB=\t$(INSTALL) -m 644\n" \ "INSTALL_SHLIB=\t$(INSTALL) -m 755\n" \ "INSTALL_DATA=\t$(INSTALL) -m 644\n" \ "INSTALL_DIR=\t$(INSTALL) -d -m 755\n" \ "INSTALL_MAN=\t$(INSTALL) -m 644\n\n" /* directories ************************/ #define MKF_HEADER_DIR "PREFIX=\t\t@PREFIX@\n" \ "BINDIR=\t\t@BINDIR@\n" \ "SBINDIR=\t@SBINDIR@\n" \ "DATADIR=\t@DATADIR@\n" #define MKF_LIB_DIR "LIBDIR=\t\t@LIBDIR@\n" #define MKF_INC_DIR "INCDIR=\t\t@INCDIR@\n" #define MKF_MAN_DIR "MANDIR=\t\t@MANDIR@\n" #define MKF_MANX_DIR "MAN%iDIR=\t@MAN%iDIR@\n" #define MKF_SYSCONF_DIR "SYSCONFDIR=\t@SYSCONFDIR@\n" /* simple macros */ /* lists */ #define MKF_SDIR_LIST "SUBDIRS=\t" #define MKF_GEN_FILES "GEN_FILES=\t" #define MKF_TEMPLATES "TEMPLATES=\t" /* suffix defines */ #define MKF_SUFFIXES ".SUFFIXES: .o .s .c .C .cc .cxx .cpp\n\n" #define MKF_BLD_ASM_OBJ "# assembly suffix\n" \ "# we use CPP to be more portable\n" \ ".s.o:\n" \ "\t$(" MKF_LABEL_CPP ") $< | sed '/^#/d' > tmp_asm.s\n" \ "\t$(" MKF_LABEL_AS ") $(" MKF_LABEL_AS "FLAGS) -o $@ tmp_asm.s\n" \ "\t$(" MKF_LABEL_RM ") $(" MKF_LABEL_RM "FLAGS) tmp_asm.s\n\n" #define MKF_BLD_C_OBJ "# C suffixes\n" \ ".c.o:\n" \ "\t$(CC) $(CFLAGS) $(SLCFLAGS) -o $@ -c $<\n" \ "\n.C.o:\n" \ "\t$(CC) $(CFLAGS) $(SLCFLAGS) -o $@ -c $<\n" \ "\n.cc.o:\n" \ "\t$(CC) $(CFLAGS) $(SLCFLAGS) -o $@ -c $<\n\n" #define MKF_BLD_CXX_OBJ "# C++ suffixes\n" \ ".cxx.o:\n" \ "\t$(CXX) $(CXXFLAGS) $(SLCXXFLAGS) -o $@ -c $<\n" \ "\n.cpp.o:\n" \ "\t$(CXX) $(CXXFLAGS) $(SLCXXFLAGS) -o $@ -c $<\n\n" #define MKF_BLD_YACC_SRC "# yacc suffix\n" \ ".y.c:\n" \ "\t$(" MKF_LABEL_YACC ") $(YFLAGS) $<\n" \ "\tmv y.tab.c $@\n\n" #define MKF_BLD_LEX_SRC "# lex suffix\n" \ ".l.c:\n" \ "\t$(" MKF_LABEL_LEX ") $(LFLAGS) $<\n" \ "\tmv lex.yy.c $@\n\n" /* target labels **********************/ #define MKF_OBJECT_LABL "%s: $(" MKF_OBJ_SRCS_VAR ")\n" #define MKF_TARGET_LABL "%s: $(" MKF_TRGT_OBJS_VAR ")\n" /* main targets ***********************/ #define MKF_TARGET_SIMPLE "$(%s): $(%s)\n" /* building ***************************/ #define MKF_TARGET_DEF "\t$(LD) $(LDFLAGS) -o $@ $(%s_OBJS)\n\n" #define MKF_TARGET_C "\t$(CC) $(CLDFLAGS) -o $@ $(%s_OBJS)\n\n" #define MKF_TARGET_CXX "\t$(CXX) $(CXXLDFLAGS) -o $@ $(%s_OBJS)\n\n" #define MKF_TARGET_LIB_STC "\t$(" MKF_LABEL_AR ") $(" MKF_LABEL_AR "FLAGS) $@ $(%s)\n" \ "\t$(" MKF_LABEL_RANLIB ") $@\n\n" #define MKF_TARGET_LIB_SHD "\t$(LD) $(LDFLAGS) $(SLLDFLAGS) -o $@ $(%s)\n" #define MKF_TARGET_SL_C "\t$(CC) $(CLDFLAGS) $(SLCLDFLAGS) -o $@ $(%s)\n\n" /* XXX make better */ #define MKF_TARGET_SL_CXX "\t$(CXX) $(CXXLDFLAGS) $(SLCXXLDFLAGS) -o $@ $(%s)\n\n" /* XXX make better */ #define MKF_TARGET_CLN "$(%s)_clean:\n" \ "\t$(" MKF_LABEL_RM ") $("MKF_LABEL_RM "FLAGS) $(%s_OBJS)\n" \ "\t$(" MKF_LABEL_RM ") $(" MKF_LABEL_RM "FLAGS) $(%s)\n\n" #define MKF_TARGET_LIB_CLN "\t$(" MKF_LABEL_RM ") $(" MKF_LABEL_RM "FLAGS) $(%s)\n" #define MKF_TRGT_BLD_VAR "BUILD_TARGETS" #define MKF_LIB_BLD_VAR "LIB_BUILD_TARGETS" #define MKF_STATIC_LIB_VAR "STATIC_LIB_TARGETS" #define MKF_SHARED_LIB_VAR "SHARED_LIB_TARGETS" #define MKF_C_SHLIB_VAR "C_SHLIB_TARGETS" #define MKF_CXX_SHLIB_VAR "CXX_SHLIB_TARGETS" #define MKF_TRGT_CLEAN_VAR "CLEAN_TARGETS" #define MKF_BIN_CLEAN_VAR "BIN_CLEAN_TARGETS" #define MKF_LIB_CLEAN_VAR "LIB_CLEAN_TARGETS" #define MKF_STLIB_CLN_VAR "STLIB_CLEAN_TARGETS" #define MKF_SHLIB_CLN_VAR "SHLIB_CLEAN_TARGETS" #define MKF_C_SHL_CLN_VAR "C_SHLIB_CLEAN_TARGETS" #define MKF_CXX_SHL_CLN_VAR "CXX_SHLIB_CLEAN_TARGETS" #define MKF_TRGT_INST_VAR "INSTALL_TARGETS" #define MKF_BIN_INST_VAR "BIN_INSTALL_TARGETS" #define MKF_LIB_INST_VAR "LIB_INSTALL_TARGETS" #define MKF_STLIB_INST_VAR "STLIB_INST_TARGETS" #define MKF_SHLIB_INST_VAR "SHLIB_INST_TARGETS" #define MKF_C_SHL_INST_VAR "C_SHLIB_INST_TARGETS" #define MKF_CXX_SHL_INST_VAR "CXX_SHLIB_INST_TARGETS" #define MKF_TRGT_DEINST_VAR "DEINSTALL_TARGETS" #define MKF_BIN_DEINST_VAR "BIN_DEINSTALL_TARGETS" #define MKF_LIB_DEINST_VAR "LIB_DEINSTALL_TARGETS" #define MKF_STLIB_DEINST_VAR "STLIB_DEINST_TARGETS" #define MKF_SHLIB_DEINST_VAR "SHLIB_DEINST_TARGETS" #define MKF_C_SHL_DEINST_VAR "C_SHLIB_DEINST_TARGETS" #define MKF_CXX_SHL_DEINST_VAR "CXX_SHLIB_DEINST_TARGETS" #define MKF_TRGT_ALL_BIN "ALL_BIN_TARGETS" #define MKF_TRGT_ALL_LIB MKF_LIB_BLD_VAR "=\tstatic_libs $(" MKF_SHARED_LIB_VAR ")\n" #define MKF_LIB_CLEAN_ALL MKF_LIB_CLEAN_VAR "=\tstatic_libs_clean $(" MKF_SHLIB_CLN_VAR ")\n" #define MKF_TRGT_CLEAN_STL MKF_STLIB_CLN_VAR "=\t" #define MKF_TRGT_CLEAN_SHL MKF_SHLIB_CLN_VAR "=\t" #define MKF_TRGT_INST_LIBHDR "lib_headers_install" #define MKF_TRGT_INST_STLIB "static_libs_install" #define MKF_TRGT_INST_SHLIB "shared_libs_install" #define MKF_TRGT_INST_BIN "install_bin" #define MKF_TRGT_INST_LIB "install_lib" #define MKF_TRGT_INST_MAN "install_man" #define MKF_TRGT_INST_DATA "install_data" #define MKF_LIB_INSTALL_ALL MKF_LIB_INST_VAR "=\t" MKF_TRGT_INST_LIBHDR " " MKF_TRGT_INST_STLIB " $(" MKF_SHLIB_INST_VAR ")\n" #define MKF_GTRGT_INST_BIN "#\n# binary target rules\n#\n\n" \ "# main binary install target\n" \ "install_bin: install_bindir $(" MKF_BIN_INST_VAR ")\n\n" \ "# install binary directory\n" \ "install_bindir:\n" \ "\t$(INSTALL_DIR) $(DESTDIR)$(BINDIR)\n\n" #define MKF_GTRGT_INST_LIB "#\n# library target rules\n#\n\n" \ "# main library install target\n" \ "install_lib: install_libdir $(" MKF_LIB_INST_VAR ")\n\n" \ "# install library directory\n" \ "install_libdir:\n" \ "\t$(INSTALL_DIR) $(DESTDIR)$(LIBDIR)\n\n" #define MKF_TRGT_DEINST_LIBHDR "lib_headers_deinstall" #define MKF_TRGT_DEINST_STLIB "static_libs_deinstall" #define MKF_TRGT_DEINST_SHLIB "shared_libs_deinstall" #define MKF_TRGT_DEINST_MAN "deinstall_man" #define MKF_TRGT_DEINST_DATA "deinstall_data" #define MKF_LIB_DEINSTALL_ALL MKF_LIB_DEINST_VAR "=\t" MKF_TRGT_DEINST_LIBHDR " " MKF_TRGT_DEINST_STLIB " $(" MKF_SHLIB_DEINST_VAR ")\n" #define MKF_TRGT_STLIBS "# static library targets\n" \ "static_libs: $(" MKF_STATIC_LIB_VAR ")\n\n" \ "static_libs_clean: $(" MKF_STLIB_CLN_VAR ")\n\n" \ MKF_TRGT_INST_STLIB ": $(" MKF_STLIB_INST_VAR ")\n\n" \ MKF_TRGT_DEINST_STLIB ": $(" MKF_STLIB_DEINST_VAR ")\n\n" #define MKF_TRGT_C_SHLIBS "# C language shared library targets\n" \ MK_BLD_TARGET_C ": $(" MKF_C_SHLIB_VAR ")\n\n" \ MK_CLN_TARGET_C ": $(" MKF_C_SHL_CLN_VAR ")\n\n" \ MK_INST_TARGET_C ": $(" MKF_C_SHL_INST_VAR ")\n\n" \ MK_DEINST_TARGET_C ": $(" MKF_C_SHL_DEINST_VAR ")\n\n" #define MKF_TRGT_CXX_SHLIBS "# C++ language shared library targets\n" \ MK_BLD_TARGET_CXX ": $(" MKF_CXX_SHLIB_VAR ")\n\n" \ MK_CLN_TARGET_CXX ": $(" MKF_CXX_SHL_CLN_VAR ")\n\n" \ MK_INST_TARGET_CXX ": $(" MKF_CXX_SHL_INST_VAR ")\n\n" \ MK_DEINST_TARGET_CXX ": $(" MKF_CXX_SHL_DEINST_VAR ")\n\n" #define MKF_FILE_BIN_VAR "# by default we consider all binaries as non privileged\n" \ "BIN_FILES=\t$(ALL_BIN_TARGETS)\n\n" #define MKF_FILE_SBIN_VAR "# move privileged binaries here if needed\n" \ "SBIN_FILES=\n\n" #define MKF_FILE_MAN_VAR "MAN%d_FILES=\t" #define MKF_FILE_DATA_VAR "DATA_FILES=\t" #define MKF_TARGET_ALL "all: $(" MKF_TRGT_BLD_VAR ")\n\n" \ "clean: $(" MKF_TRGT_CLEAN_VAR ")\n\n" #define MKF_TARGET_CFG "config: $(GEN_FILES)\n\n" \ "$(GEN_FILES): $(TEMPLATES)\n" \ "\t@pmk\n\n" #define MKF_TARGET_INST "install: $(" MKF_TRGT_INST_VAR ")\n\n" \ "deinstall: $(" MKF_TRGT_DEINST_VAR ")\n\n" #define MKF_INST_BIN "$(%s)_install: $(%s)\n" \ "\t$(INSTALL_BIN) $(%s) $(DESTDIR)$(BINDIR)/$(%s)\n\n" #define MKF_DEINST_BIN "$(%s)_deinstall:\n" \ "\t$(RM) $(RMFLAGS) $(DESTDIR)$(BINDIR)/$(%s)\n\n" #define MKF_INST_STLIB "\t$(INSTALL_STLIB) $(%s) $(DESTDIR)$(LIBDIR)/$(%s)\n" #define MKF_INST_SHLIB "\t$(INSTALL_SHLIB) $(%s) $(DESTDIR)$(LIBDIR)/$(%s)\n" /* XXX put dependencies in rule ? */ #define MKF_INST_MAN_H "# install manual pages\n" \ "install_man:\n" \ "\t$(INSTALL_DIR) $(DESTDIR)$(MANDIR)\n" #define MKF_INST_MAN_D "\t# man%d\n" \ "\t$(INSTALL_DIR) $(DESTDIR)$(MAN%uDIR)\n" #define MKF_INST_MAN_P "\t$(INSTALL_DATA) %s $(DESTDIR)$(MAN%uDIR)/%s\n" #define MKF_DEINST_MAN_H "# deinstall manual pages\n" \ "deinstall_man:\n" #define MKF_DEINST_MAN_D "\t# man%d\n" #define MKF_DEINST_MAN_P "\t$(RM) $(RMFLAGS) $(DESTDIR)$(MAN%uDIR)/%s\n" #define MKF_INST_DATA_H "# install data files\n" \ "install_data: $(DATA_FILES)\n" \ "\t$(INSTALL_DIR) $(DESTDIR)$(DATADIR)\n" #define MKF_INST_DATA_P "\t$(INSTALL_DATA) %s $(DESTDIR)$(DATADIR)/%s\n" #define MKF_DEINST_DATA_H "# deinstall data files\n" \ "deinstall_data:\n" #define MKF_DEINST_DATA_P "\t$(RM) $(RMFLAGS) $(DESTDIR)$(DATADIR)/%s\n" #define MKF_DIST_CLEAN "distclean: clean\n" \ "\t$(RM) $(RMFLAGS) $(GEN_FILES)\n" /********************************** * type and structure definitions * ***********************************************************************/ /* pseudo token type */ typedef unsigned char ttype_t; /* file type and extension struct */ typedef unsigned char ftype_t; typedef struct { char *ext; ftype_t type; } scn_ext_t; /* library type */ typedef unsigned char ltype_t; typedef struct { char *lang; ltype_t type; } lib_type_t; /* node structure */ typedef struct { char *fname, /* filename */ *obj_name, /* object name */ *prefix, /* prefix name */ *label, /* binary label */ *dname; /* directory name */ bool isdep, /* dependency flag */ mainproc; /* has main() proc flag ? */ dynary *system_inc, /* system include list */ *local_inc, /* local include list */ *func_calls, /* function call list */ *func_decls, /* function declaration list */ *type_idtfs, /* type identifier list */ *src_deps, /* source dependency list */ *sys_deps, /* system header dependency list */ *obj_links, /* object link dependencies */ *obj_deps; /* type dependency list */ ftype_t type; /* file type */ int score; /* hit score */ } scn_node_t; /* library cell */ typedef struct { char *lib_name, /* library name */ *lib_label, /* library name label */ *lib_vmaj, /* major version number */ *lib_vmin, /* minor version number */ *lib_srcs, /* library sources variable */ *lib_hdrs, /* library headers variable */ *lib_objs, /* library objects variable */ *lib_static, /* static library filename */ *lib_shared; /* shared library filename */ dynary *src_list, /* object dependency list */ *hdr_list, /* object dependency list */ *obj_deps; /* object dependency list */ ltype_t type; /* link type */ } lib_cell_t; /* scanning zone data structure */ typedef struct { bool found[NB_FILE_TYPE], /* file type flags */ found_src, /* source file flag */ advtag, /* use advanced tagging */ gen_pmk, /* pmkfile generation flag */ gen_mkf, /* makefile generation flag */ gen_lib, /* library generation flag *//* XXX to remove ? */ lib_type[NB_LIB_TYPE], /* file type flags *//* XXX to init */ recursive, /* recursive scan flag */ unique; /* unique file flag */ char *directory, /* initial directory */ *cfg_name, /* alternate config file name */ *mkf_name, /* alternate makefile name */ *pmk_name, /* alternative pmkfile name */ *ext_mkf; /* extra to append to makefile template */ dynary *dirlist, /* scanned directory list */ *dirscan, /* directory list to scan (just a pointer) */ *exttags, /* extra tags */ *tags, /* zone tags */ *manpgs, /* man pages dynary */ *datafiles, /* data files dynary */ *discard, /* discard list */ *templates, /* template files */ *generated; /* files to be generated from templates */ htable *nodes, /* global nodes table */ *objects, /* zone objects */ *targets, /* zone targets */ *libraries, /* zone libraries */ *h_checks, /* zone header checks */ *l_checks, /* zone header checks */ *t_checks; /* zone type checks */ scn_node_t *pnode; } scn_zone_t; /* check type */ typedef struct { char *name, *header, *library, *member; dynary *procs, *subhdrs; ftype_t ftype; } check_t; /* scanning data parsed from dat file */ typedef struct { htable *headers, *libraries, *types; } scandata; /************************ * functions prototypes * ***********************************************************************/ /* init functions ******************************************************/ scn_node_t *scan_node_init(char *); void scan_node_destroy(scn_node_t *); lib_cell_t *lib_cell_init(char *, dynary *, dynary *, ltype_t); void lib_cell_destroy(lib_cell_t *); scn_zone_t *scan_zone_init(htable *); void scan_zone_destroy(scn_zone_t *); /* pmkfile specific ****************************************************/ check_t *init_chk_cell(char *); void destroy_chk_cell(check_t *); check_t *mk_chk_cell(htable *, int); bool parse_data_file(prsdata *, scandata *); char *conv_to_label(ftype_t, char *, ...); bool recurse_sys_deps(htable *, dynary *, char *); bool add_library(scn_zone_t *, char *, scandata *, scn_node_t *); bool check_header(scn_zone_t *, char *, scandata *, scn_node_t *); bool check_type(scn_zone_t *, char *, scandata *, scn_node_t *); bool gen_checks(scn_zone_t *, scandata *); void build_cmd_begin(FILE *, char *, char *); void build_cmd_end(FILE *); void build_comment(FILE *, char *, ...); void build_boolean(FILE *, char *, bool); void build_quoted(FILE *, char *, char *); bool build_list(FILE *, char *, dynary *); bool set_lang(FILE *, ftype_t); bool output_header(htable *, char *, FILE *); bool output_library(htable *, char *, FILE *); bool output_type(htable *, char *, FILE *); bool scan_build_pmk(scn_zone_t *); bool scan_build_cfg(scn_zone_t *); /* makefile specific ***************************************************/ bool find_deps(dynary *, dynary *); void extract_dir(char *, char *, size_t); void build_path(char *, char *, char *, size_t); bool recurse_obj_deps(htable *, dynary *, char *); bool gen_objects(scn_zone_t *); bool recurse_src_deps(scn_zone_t *, dynary *, char *); bool gen_targets(scn_zone_t *); bool gen_lib_targets(scn_zone_t *); size_t fprintf_width(size_t, size_t, size_t, FILE *, char *); void mkf_output_header(FILE *, scn_zone_t *); void mkf_output_recurs(FILE *, scn_zone_t *); void mkf_output_srcs(FILE *, scn_zone_t *); void mkf_output_bins(FILE *, scn_zone_t *); void mkf_output_libs(FILE *, scn_zone_t *); void mkf_output_objs(FILE *, scn_zone_t *); void mkf_output_suffixes(FILE *, scn_zone_t *); void mkf_output_build_trgs(FILE *, scn_zone_t *); void mkf_output_clean_trgs(FILE *, scn_zone_t *); void mkf_output_inst_trgs(FILE *, scn_zone_t *); void mkf_output_deinst_trgs(FILE *, scn_zone_t *); void mkf_output_man_trgs(FILE *, scn_zone_t *); void mkf_output_data_trgs(FILE *, scn_zone_t *); void mkf_output_obj_rules(FILE *, scn_zone_t *); void mkf_output_trg_rules(FILE *, scn_zone_t *); void mkf_output_lib_trg_rules(FILE *, scn_zone_t *); void mkf_output_man_inst(FILE *, scn_zone_t *); void mkf_output_data_inst(FILE *, scn_zone_t *); bool scan_build_mkf(scn_zone_t *); /* common functions */ void psc_log(char *, char *, ...); void str_to_upper(char *, size_t, char *); ftype_t check_file_ext(char *); bool process_ppro(void *, char *, prseng_t *); bool process_proc_call(void *, char *, prseng_t *); bool process_proc_decl(void *, char *, prseng_t *); bool process_type(void *, char *, prseng_t *); bool parse_deflib(htable *, htable *); bool parse_zone_opts(prs_cmn_t *, htable *, htable *); bool parse_file(prs_cmn_t *, char *, ftype_t, bool); bool process_zone(prs_cmn_t *, scandata *); bool parse_script(char *, prs_cmn_t *, scandata *); bool scan_node_file(prs_cmn_t *, char *, bool); bool scan_dir(prs_cmn_t *, char *, bool); void usage(void); #endif /* _PMKSCAN_H_ */ /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/pkgconfig.c010064400017500000000000000521011077176125000133650ustar00mipswheel/* $Id: pkgconfig.c 2049 2008-03-24 17:19:36Z 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. * */ /* include it first as if it was - this will avoid errors */ #include "compat/pmk_sys_types.h" #include #include #include #include "compat/pmk_ctype.h" #include "compat/pmk_stdio.h" #include "compat/pmk_stdbool.h" #include "compat/pmk_string.h" #include "common.h" #include "hash.h" #include "hash_tools.h" #include "parse.h" #include "pkgconfig.h" #include "premake.h" /*#define PKGCFG_DEBUG 1*/ /* * env PKG_CONFIG_PATH => list of colon separated path * env PKG_CONFIG_LIBDIR => replace default location (aka prefix/lib/pkgconfig) */ /********** constants ************************************************************************/ #define PKGCFG_HTABLE_SIZE 32 #define PKGCFG_TOK_ADDCT 1 #define PKGCFG_KW_NAME 0 #define PKGCFG_KW_DESCR 1 #define PKGCFG_KW_VERS 2 #define PKGCFG_KW_REQS 3 #define PKGCFG_KW_LIBS 4 #define PKGCFG_KW_CFLGS 5 #define PKGCFG_KW_CFLCT 6 /********** variables ************************************************************************/ /* pc file keywords */ pkgkw kw_pkg[] = { {"Name", PKGCFG_KW_NAME}, {"Description", PKGCFG_KW_DESCR}, {"Version", PKGCFG_KW_VERS}, {"Requires", PKGCFG_KW_REQS}, {"Libs", PKGCFG_KW_LIBS}, {"Cflags", PKGCFG_KW_CFLGS}, {"CFlags", PKGCFG_KW_CFLGS}, {"Conflicts", PKGCFG_KW_CFLCT} }; size_t nb_pkgkw = sizeof(kw_pkg) / sizeof(pkgkw); /********** functions ************************************************************************/ /*************** pkgcell_init() DESCR initialize pkgcell structure IN NONE OUT pkgcell structure or NULL ************************************************************************/ pkgcell *pkgcell_init(void) { pkgcell *ppc; ppc = (pkgcell *) malloc(sizeof(pkgcell)); if (ppc == NULL) { errorf("cannot initialize pkgcell."); return(NULL); } ppc->variables = hash_init(PKGCFG_HTABLE_SIZE); if (ppc->variables == NULL) { free(ppc); errorf("cannot initialize pkgcell hash table."); return(NULL); } ppc->cflags = NULL; ppc->libs = NULL; ppc->requires = NULL; return(ppc); } /****************** pkgcell_destroy() DESCR free pkgcell structure IN ppc : pkgcell structure OUT NONE ************************************************************************/ void pkgcell_destroy(pkgcell *ppc) { if (ppc->name != NULL) free(ppc->name); if (ppc->descr != NULL) free(ppc->descr); if (ppc->version != NULL) free(ppc->version); if (ppc->requires != NULL) free(ppc->requires); da_destroy(ppc->cflags); da_destroy(ppc->libs); hash_destroy(ppc->variables); free(ppc); } /*************** pkgdata_init() DESCR initialize pkgdata structure IN NONE OUT pkgdata structure or NULL ************************************************************************/ pkgdata *pkgdata_init(void) { pkgdata *ppd; ppd = (pkgdata *) malloc(sizeof(pkgdata)); if (ppd == NULL) return(NULL); /* init pc files hash table */ ppd->files = hash_init(PKGCFG_HT_SIZE); if (ppd->files == NULL) { free(ppd); return(NULL); } /* init package cells hash table */ ppd->cells = hash_init_adv(PKGCFG_HT_SIZE, NULL, (void (*)(void *))pkgcell_destroy, NULL); if (ppd->cells == NULL) { hash_destroy(ppd->files); free(ppd); return(NULL); } /* init recursed modules hash table */ ppd->mods = da_init(); if (ppd->mods == NULL) { hash_destroy(ppd->files); hash_destroy(ppd->cells); free(ppd); return(NULL); } return(ppd); } /****************** pkgdata_destroy() DESCR free pkgdata structure IN ppd : pkgdata structure OUT NONE ************************************************************************/ void pkgdata_destroy(pkgdata *ppd) { #ifdef PKGCFG_DEBUG debugf("clean pc files hash"); #endif hash_destroy(ppd->files); #ifdef PKGCFG_DEBUG debugf("clean cells hash"); #endif hash_destroy(ppd->cells); #ifdef PKGCFG_DEBUG debugf("clean modules list"); #endif da_destroy(ppd->mods); #ifdef PKGCFG_DEBUG debugf("clean structure"); #endif free(ppd); } /************* skip_blank() DESCR skip blank character(s) IN pstr: current parsing cursor OUT new parsing cursor ***********************************************************************/ char *skip_blank(char *pstr) { while (isblank(*pstr) != 0) { pstr++; } return(pstr); } /*********** scan_dir() DESCR scan given directory for pc files IN dir : directory to scan ppd : pkgdata structure OUT boolean ************************************************************************/ bool scan_dir(char *dir, pkgdata *ppd) { struct dirent *pde; DIR *pdir; char *pstr, buf[MAXPATHLEN], fpath[MAXPATHLEN]; size_t l; /* open directory */ pdir = opendir(dir); if (pdir == NULL) { errorf("cannot open '%s' directory : %s.", dir, strerror(errno)); return(false); } /* parse directory */ do { pde = readdir(pdir); if (pde != NULL) { /* got an entry */ pstr = pde->d_name; l = strlen(pstr); /* check if it's a .pc file */ if ((pstr[l-3] == '.') && (pstr[l-2] == 'p') && (pstr[l-1] == 'c')) { /* build pkg name */ if (strlcpy_b(buf, pstr, sizeof(buf)) == false) { /* XXX err msg ? */ closedir(pdir); return(false); } buf[l-3] = CHAR_EOS; /* build full path of pc file */ strlcpy(fpath, dir, sizeof(fpath)); /* no check */ strlcat(fpath, "/", sizeof(fpath)); /* no check */ if (strlcat_b(fpath, pstr, sizeof(fpath)) == false) { /* XXX err msg ? */ closedir(pdir); return(false); } hash_update_dup(ppd->files, buf, fpath); /* XXX detect if the package has already been detected ? */ #ifdef PKGCFG_DEBUG debugf("add module '%s' with file '%s'", buf, pstr); #endif } } } while (pde != NULL); closedir(pdir); return(true); } /************** pkg_collect() DESCR collect packages data IN pkglibdir : default packages data directory ppd : pkgdata structure OUT return : boolean ************************************************************************/ bool pkg_collect(char *pkglibdir, pkgdata *ppd) { char *pstr; dynary *ppath, *ppcpath; unsigned int i; pstr = getenv(PMKCFG_ENV_PATH); if (pstr != NULL) { /* also scan path provided in env variable */ ppath = str_to_dynary(pstr, PKGCFG_CHAR_PATH_SEP); for (i = 0 ; i < da_usize(ppath) ; i++) { pstr = da_idx(ppath, i); if (scan_dir(pstr, ppd) == false) { da_destroy(ppath); return(false); } } da_destroy(ppath); } /* check if pkg-config library directory has been set in env variable */ pstr = getenv(PMKCFG_ENV_LIBDIR); if (pstr == NULL) { /* env variable is not set, getting pmk.conf variable */ ppcpath = str_to_dynary(pkglibdir, PKGCFG_CHAR_PATH_SEP); } else { /* else use env variable */ ppcpath = str_to_dynary(pstr, PKGCFG_CHAR_PATH_SEP); } /* scan all path for pc files */ for (i = 0 ; i < da_usize(ppcpath) ; i++) { /* get directory */ pstr = da_idx(ppcpath, i); /* scan directory */ if (scan_dir(pstr, ppd) == false) { return(false); } } return(true); } /**************** parse_keyword() DESCR parse keyword and set data IN ppc : pkgcell structure kword : keyword value : value to assign OUT boolean ************************************************************************/ bool parse_keyword(pkgcell *ppc, char *kword, char *value) { unsigned int i; for (i = 0 ; i < nb_pkgkw ; i ++) { if (strncmp(kword, kw_pkg[i].kw_name, sizeof(kword)) == 0) { /* assgin keyword */ switch (kw_pkg[i].kw_id) { case PKGCFG_KW_NAME : ppc->name = strdup(value); if (ppc->name == NULL) { errorf(ERRMSG_MEM); return(false); } break; case PKGCFG_KW_DESCR : ppc->descr = strdup(value); if (ppc->descr == NULL) { errorf(ERRMSG_MEM); return(false); } break; case PKGCFG_KW_VERS : ppc->version = strdup(value); if (ppc->version == NULL) { errorf(ERRMSG_MEM); return(false); } break; case PKGCFG_KW_REQS : if (*value != CHAR_EOS) { ppc->requires = strdup(value); if (ppc->requires == NULL) { errorf(ERRMSG_MEM); return(false); } } break; case PKGCFG_KW_CFLGS : ppc->cflags = str_to_dynary(value, ' '); break; case PKGCFG_KW_LIBS : ppc->libs = str_to_dynary(value, ' '); break; case PKGCFG_KW_CFLCT : /* unused */ break; default : break; } return(true); } } return(true); } /******************** process_variables() DESCR process string to substitute variables with their values IN pstr : string to process pht : hash table where variables are stored OUT new string or NULL ************************************************************************/ char *process_variables(char *pstr, htable *pht) { bool bs = false; char buf[OPT_VALUE_LEN], var[OPT_NAME_LEN], *pvar, *pbuf; size_t size; size = sizeof(buf); pbuf = buf; while ((*pstr != CHAR_EOS) && (size > 0)) { switch(*pstr) { case '\\' : bs = true; pstr++; break; case '$' : if (bs == false) { /* found variable */ pstr++; /* skip '{' */ pstr++; pstr = parse_idtf(pstr, var, sizeof(var)); if (pstr == NULL) { /* debugf("parse_idtf returned null."); */ return(NULL); } else { /* check if identifier exists */ pvar = hash_get(pht, var); if (pvar != NULL) { /* identifier found, append value */ while ((*pvar != CHAR_EOS) && (size > 0)) { *pbuf = *pvar; pbuf++; pvar++; size--; } /* skip '}' */ pstr++; } } } else { /* copy character */ *pbuf = *pstr; pbuf++; pstr++; size--; bs = false; } break; default : if (bs == true) { *pbuf = '\\'; pbuf++; pstr++; size--; if (size == 0) { /* debugf("overflow."); */ return(NULL); } bs = false; } /* copy character */ *pbuf = *pstr; pbuf++; pstr++; size--; break; } } if (size == 0) { /* debugf("overflow."); */ return(NULL); } *pbuf = CHAR_EOS; return(strdup(buf)); } /**************** parse_pc_file() DESCR parse pc file IN pcfile : file to parse OUT pkgcell structure or NULL ************************************************************************/ pkgcell *parse_pc_file(char *pcfile) { FILE *fp; char *pstr, *pps, buf[TMP_BUF_LEN], line[TMP_BUF_LEN]; pkgcell *ppc; fp = fopen(pcfile, "r"); if (fp == NULL) { errorf("cannot open .pc file '%s' : %s.", pcfile, strerror(errno)); return(NULL); } ppc = pkgcell_init(); if (ppc == NULL) { errorf("cannot initialize pkgcell."); return(NULL); } /* main parsing */ while (get_line(fp, line, sizeof(line)) == true) { /* collect identifier */ pstr = parse_idtf(line, buf, sizeof(buf)); switch (*pstr) { case ':' : /* keyword */ pstr++; pstr = skip_blank(pstr); /* process variables */ pps = process_variables(pstr, ppc->variables); #ifdef PKGCFG_DEBUG debugf("keyword = '%s', value = '%s', string = '%s'", buf, pps, pstr); #endif /* set variable with parsed data */ if (parse_keyword(ppc, buf, pps) == false) { errorf("cannot fill pkgcell structure (keyword)."); pkgcell_destroy(ppc); return(NULL); } break; case '=' : /* variable */ pstr++; pstr = skip_blank(pstr); /* process variables */ pps = process_variables(pstr, ppc->variables); #ifdef PKGCFG_DEBUG debugf("variable = '%s', value = '%s', string = '%s'", buf, pps, pstr); #endif /* store variable in hash */ if (hash_update_dup(ppc->variables, buf, pps) == HASH_ADD_FAIL) { errorf("cannot fill pkgcell structure (variables)."); pkgcell_destroy(ppc); return(NULL); } break; default : /* unknown or empty line */ #ifdef PKGCFG_DEBUG debugf("unknown = '%s'", line); #endif break; } } fclose(fp); return(ppc); } /*************** pkg_cell_add() DESCR insert a package cell and return a pointer on it IN mod : module name to process ppd : packages data structure OUT pkgcell structure or NULL ************************************************************************/ pkgcell *pkg_cell_add(pkgdata *ppd, char *mod) { char *pcf; pkgcell *ppc; /* get pc file name */ pcf = hash_get(ppd->files, mod); if (pcf == NULL) { /* config file not found */ return NULL; } /* parse pc file */ ppc = parse_pc_file(pcf); if (ppc == NULL) { return(NULL); } /* store pkgcell in hash */ if (hash_update(ppd->cells, mod, ppc) == HASH_ADD_FAIL) { return(NULL); #ifdef PKGCFG_DEBUG } else { debugf("adding pkgcell for '%s'", mod); #endif } /* add module in list */ da_push(ppd->mods, strdup(mod)); if (ppc->requires != NULL) { #ifdef PKGCFG_DEBUG debugf("pkgcell requires = '%s'", ppc->requires); #endif if (pkg_recurse(ppd, ppc->requires) == false) { pkgcell_destroy(ppc); return(NULL); } } return(ppc); } /************** pkg_recurse() DESCR recurse packages IN ppd : packages data structure reqs : requires string OUT boolean ************************************************************************/ bool pkg_recurse(pkgdata *ppd, char *reqs) { char *mod; dynary *pda; unsigned int i; #ifdef PKGCFG_DEBUG debugf("recursing '%s'", reqs); #endif pda = str_to_dynary_adv(reqs, " ,"); if (pda == NULL) { errorf("failed to process requirements in pkg_recurse()."); return(false); } for (i = 0 ; i < da_usize(pda) ; i++) { /* get module name */ mod = da_idx(pda, i); /* check if module has been already processed */ if (hash_get(ppd->cells, mod) == NULL) { /* * here we don't check the result as dependencies * can be missing in some cases. */ pkg_cell_add(ppd, mod); /* no check */ } } da_destroy(pda); return(true); } /******************** pkg_single_append() DESCR append module name if it does not already exists IN ostr : modules list string astr : module to append OUT return : new list of modules or NULL ************************************************************************/ char *pkg_single_append(char *ostr, char *astr) { char *pstr, *buf; size_t s; #ifdef PKGCFG_DEBUG debugf("single_append '%s', '%s'", ostr, astr); #endif if (*astr == CHAR_EOS) return(ostr); if ((*ostr != CHAR_EOS) && (ostr != NULL)) { pstr = strstr(ostr, astr); while (pstr != NULL) { pstr = pstr + strlen (astr); if ((*pstr == ' ') || (*pstr == CHAR_EOS)) { /* found existing value */ return(ostr); } pstr = strstr(pstr, astr); } /* 2 is for the separator and the end of file char */ s = strlen(ostr) + strlen(astr) + 2; buf = (char *) malloc(s); if (buf == NULL) return(NULL); if (snprintf_b(buf, s, "%s %s", ostr, astr) == false) { return(NULL); } free(ostr); } else { buf = strdup(astr); } return(buf); } /***************** pkg_get_cflags() DESCR get recursed list of cflags IN ppd : packages data structure OUT cflags string ************************************************************************/ char *pkg_get_cflags(pkgdata *ppd) { return(pkg_get_cflags_adv(ppd, PKGCFG_CFLAGS_ALL)); } /********************* pkg_get_cflags_adv() DESCR get recursed list of cflags with output filtering IN ppd : packages data structure opts : output filtering options OUT cflags string ************************************************************************/ char *pkg_get_cflags_adv(pkgdata *ppd, unsigned int opts) { char *cflags = "", *pstr; dynary *pda; pkgcell *ppc; unsigned int i, j, o; pda = ppd->mods; for (i = 0 ; i < da_usize(pda) ; i++) { /* get module name */ ppc = hash_get(ppd->cells, da_idx(pda, i)); /* append each element but avoid duplicate*/ for (j = 0 ; j < da_usize(ppc->cflags) ; j++) { /* get element */ pstr = da_idx(ppc->cflags, j); /* check type of element */ if (pstr[0] == '-' && pstr[1] == 'I') { /* include path */ o = PKGCFG_CFLAGS_I; } else { /* other */ o = PKGCFG_CFLAGS_o; } /* append if not filtered */ if ((opts & o) != 0) cflags = pkg_single_append(cflags, pstr); } } return(cflags); } /*************** pkg_get_libs() DESCR get recursed list of libs IN ppd : packages data structure OUT libs string ************************************************************************/ char *pkg_get_libs(pkgdata *ppd) { return(pkg_get_libs_adv(ppd, PKGCFG_LIBS_ALL)); } /******************* pkg_get_libs_adv() DESCR get recursed list of libs with output filtering IN ppd : packages data structure opts : output filtering options OUT libs string ************************************************************************/ char *pkg_get_libs_adv(pkgdata *ppd, unsigned int opts) { char *libs = "", *pstr; dynary *pda; pkgcell *ppc; unsigned int i, j, o; pda = ppd->mods; for (i = 0 ; i < da_usize(pda) ; i++) { /* get module name */ ppc = hash_get(ppd->cells, da_idx(pda, i)); /* append each element but avoid duplicate*/ for (j = 0 ; j < da_usize(ppc->libs) ; j++) { /* get element */ pstr = da_idx(ppc->libs, j); /* check type of element */ if (pstr[0] == '-') { switch (pstr[1]) { case 'L': /* lib path */ o = PKGCFG_LIBS_L; break; case 'l': /* lib name */ o = PKGCFG_LIBS_l; break; default: /* other */ o = PKGCFG_LIBS_o; break; } } else { /* other */ o = PKGCFG_LIBS_o; } /* append if not filtered */ if ((opts & o) != 0) libs = pkg_single_append(libs, pstr); } } return(libs); } /***************** pkg_mod_exists() DESCR check if the given module exists IN mod : module to check OUT boolean ************************************************************************/ bool pkg_mod_exists(pkgdata *ppd, char *mod) { if (hash_get(ppd->files, mod) == NULL) { return(false); } else { return(true); } } /****************** compare_version() DESCR compare two version strings IN vref : reference version vcomp : version to check OUT <0 if vref is greater than vcomp =0 if vref is equal to vcomp >0 if vref is smaller than vcomp ************************************************************************/ int compare_version(char *vref, char *vcomp) { bool bexit = false; char *sr, *sc; dynary *vr, *vc; int delta, ref, cmp; unsigned int i = 0; unsigned long tl; /* need to check da_* returns */ vr = str_to_dynary(vref, VERSION_CHAR_SEP); if (vr == NULL) { errorf("cannot parse reference version '%s'.", vref); return(false); } vc = str_to_dynary(vcomp, VERSION_CHAR_SEP); if (vc == NULL) { errorf("cannot parse comparison version '%s'.", vcomp); return(false); } while (bexit == false) { /* process reference version */ sr = da_idx(vr, i); if (sr != NULL) { /* convert string */ if (str_to_ulong(sr, 10, &tl) == false) { errorf("cannot get numerical value of '%s'.", sr); return(false); } ref = (int) tl; } else { /* end of version string */ ref = 0; bexit = true; } /* process compared version */ sc = da_idx(vc, i); if (sc != NULL) { if (str_to_ulong(sc, 10, &tl) == false) { errorf("cannot get numerical value of '%s'.", sc); return(false); } cmp = (int) tl; } else { /* end of version string */ cmp = 0; bexit = true; } /* compare versions */ delta = cmp - ref; if (delta != 0) { /* not equal end of comparison */ bexit = true; } else { i++; } } /* destroy dynaries */ da_destroy(vr); da_destroy(vc); return(delta); } pmk-0.10.4/pmksetup.c010064400017500000000000000721171077177575600133170ustar00mipswheel/* $Id: pmksetup.c 2051 2008-03-24 19:07:26Z coudercd $ */ /* * Copyright (c) 2003-2006 Damien Couderc * Copyright (c) 2003-2004 Xavier Santolaria * 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. * */ /* include it first as if it was - this will avoid errors */ #include "compat/pmk_sys_types.h" #include #include #include #include #include #include #include #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "compat/pmk_unistd.h" #include "common.h" #include "detect_cpu.h" #include "dynarray.h" #include "parse.h" #include "pmksetup.h" /*#define PMKSETUP_DEBUG 1*/ /*#define WITHOUT_FORK 1*/ /******************** * global variables * ***********************************************************************/ extern int optind; FILE *sfp; /* scratch file pointer */ char sfn[MAXPATHLEN]; /* scratch file name */ htable *ht; int verbose_flag = 0; /* -V option at the cmd-line */ hpair predef[] = { {PMKCONF_MISC_SYSCONFDIR, SYSCONFDIR}, {PMKCONF_MISC_PREFIX, "/usr/local"}, {PMKCONF_PATH_INC, "/usr/include"}, {PMKCONF_PATH_LIB, "/usr/lib"} }; int nbpredef = sizeof(predef) / sizeof(hpair); char *pcpath[] = { "/usr", "/usr/local" }; int nbpcpath = sizeof(pcpath) / sizeof(char *); /************* * functions * ***********************************************************************/ /***************** * record_data() * *********************************************************************** DESCR record data IN pht: hash table key: record name opchar: operation char PMKSTP_REC_REMV => remove PMKSTP_REC_UPDT => add/update value: record data OUT boolean ***********************************************************************/ bool record_data(htable *pht, char *key, char opchar, char *value) { prsopt *ppo; switch (opchar) { case PMKSTP_REC_REMV : /* delete record */ ppo = prsopt_init_adv(key, opchar, NULL); if (ppo == NULL) { return(false); } break; case PMKSTP_REC_UPDT : /* update record */ ppo = prsopt_init_adv(key, opchar, value); if (ppo == NULL) { return(false); } break; default : /* unknown operation */ #ifdef PMKSETUP_DEBUG debugf("unknown '%c' operator in record_data.", opchar); #endif return(false); } if (hash_update(pht, ppo->key, ppo) == HASH_ADD_FAIL) { prsopt_destroy(ppo); return(false); } return(true); } /***************** * gather_data() * *********************************************************************** DESCR Gathering of system data, predefinied data, ... IN pht: storage hash table OUT boolean ***********************************************************************/ bool gather_data(htable *pht) { printf("==> Looking for default parameters...\n"); /* gather env variables */ if (get_env_vars(pht) == false) { errorf("failed to gather env variables."); return(false); } /* gather env variables and look for specific binaries */ if (get_binaries(pht) == false) { errorf("failed to locate binaries."); return(false); } /* set predifined variables */ if (predef_vars(pht) == false) { errorf("predefined variables."); return(false); } check_libpath(pht); /* check byte order */ if (byte_order_check(pht) == false) { errorf("failure in byte order check."); return(false); } /* try to detect cpu family and specific data */ if (get_cpu_data(pht) == false) { errorf("failure in cpu detection."); return(false); } if (check_echo(pht) == false) { errorf("failure in echo check."); return(false); } return(true); } /******************** * write_new_data() * *********************************************************************** DESCR Write remaining data IN pht: hash table OUT boolean ***********************************************************************/ bool write_new_data(htable *pht) { char *val; hkeys *phk; prsopt *ppo; unsigned int i; phk = hash_keys_sorted(pht); if (phk == NULL) { verbosef("Nothing to merge."); return(true); } /* processing remaining keys */ for(i = 0 ; i < phk->nkey ; i++) { #ifdef PMKSETUP_DEBUG debugf("write_new_data: processing '%s'", phk->keys[i]); #endif ppo = hash_get(pht, phk->keys[i]); if (ppo == NULL) { errorf("unable to get '%s' record.", phk->keys[i]); return(false); } /* check if this key is marked for being removed */ if (ppo->opchar == PMKSTP_REC_REMV) { #ifdef PMKSETUP_DEBUG debugf("write_new_data: skipping '%s', remove record.", phk->keys[i]); #endif continue; } /* add value */ val = po_get_str(ppo->value); if (val == NULL) { errorf("'%s' key has an empty value.", phk->keys[i]); return(false); } fprintf(sfp, PMKSTP_WRITE_FORMAT, phk->keys[i], CHAR_ASSIGN_UPDATE, val); } hash_free_hkeys(phk); return(true); } /*************** * check_opt() * *********************************************************************** DESCR Check and process option IN pht: htable for comparison popt: option to process OUT boolean ***********************************************************************/ bool check_opt(htable *cht, prsopt *popt) { char *recval, *optval; prsopt *ppo; optval = po_get_str(popt->value); if ((popt->opchar == CHAR_COMMENT) || (popt->opchar == CHAR_EOS)) { /* found comment or empty line */ fprintf(sfp, "%s\n", optval); #ifdef PMKSETUP_DEBUG debugf("check_opt() appended '%s\n'", optval); #endif return(true); } #ifdef PMKSETUP_DEBUG debugf("check_opt: checking key '%s'", popt->key); #endif ppo = hash_get(ht, popt->key); if (ppo == NULL) { #ifdef PMKSETUP_DEBUG debugf("check_opt: key '%s' does not exist.", popt->key); #endif fprintf(sfp, PMKSTP_WRITE_FORMAT, popt->key, popt->opchar, optval); return(true); } /* XXX check value ? */ recval = po_get_str(ppo->value); #ifdef PMKSETUP_DEBUG debugf("check_opt: original opchar '%c'", popt->opchar); #endif /* checking the VAR<->VALUE separator */ switch (popt->opchar) { case CHAR_ASSIGN_UPDATE : #ifdef PMKSETUP_DEBUG debugf("check_opt: update opchar '%c'", ppo->opchar); #endif switch (ppo->opchar) { case PMKSTP_REC_REMV : /* do nothing, value will not be refreshed */ verbosef("Removing '%s'", popt->key); break; case PMKSTP_REC_UPDT : /* update value */ fprintf(sfp, PMKSTP_WRITE_FORMAT, popt->key, CHAR_ASSIGN_UPDATE, recval); #ifdef PMKSETUP_DEBUG debugf("check_opt() appended '" PMKSTP_WRITE_FORMAT "'", popt->key, CHAR_ASSIGN_UPDATE, recval); #endif break; } hash_delete(cht, popt->key); break; case CHAR_ASSIGN_STATIC : /* static definition, stay unchanged */ fprintf(sfp, PMKSTP_WRITE_FORMAT, popt->key, CHAR_ASSIGN_STATIC, optval); #ifdef PMKSETUP_DEBUG debugf("check_opt() appended '" PMKSTP_WRITE_FORMAT "'", popt->key, CHAR_ASSIGN_STATIC, optval); #endif hash_delete(cht, popt->key); break; default : /* should not happen now */ errorf("unknown operator '%c'.", popt->opchar); return(false); break; } return(true); } /****************** * get_env_vars() * *********************************************************************** DESCR Get the environment variables needed for the configuration file IN ht: hash table where we have to store the values OUT boolean ***********************************************************************/ bool get_env_vars(htable *pht) { struct utsname utsname; char *bin_path; if (uname(&utsname) == -1) { errorf("uname : %s.", strerror(errno)); return(false); } if (record_data(pht, PMKCONF_OS_NAME, 'u', utsname.sysname) == false) return(false); verbosef("Setting '%s' => '%s'", PMKCONF_OS_NAME, utsname.sysname); if (record_data(pht, PMKCONF_OS_VERS, 'u', utsname.release) == false) return(false); verbosef("Setting '%s' => '%s'", PMKCONF_OS_VERS, utsname.release); if (record_data(pht, PMKCONF_OS_ARCH, 'u', utsname.machine) == false) return(false); verbosef("Setting '%s' => '%s'", PMKCONF_OS_ARCH, utsname.machine); /* getting the environment variable PATH */ if ((bin_path = getenv("PATH")) == NULL) { errorf("could not get the PATH environment variable."); return(false); } if (record_data(pht, PMKCONF_PATH_BIN, 'u', bin_path) == false) return(false); verbosef("Setting '%s' => '%s'", PMKCONF_PATH_BIN, bin_path); return(true); } /****************** * get_binaries() * *********************************************************************** DESCR Look for location of some predefined binaries IN ht: hash table where we have to store the values OUT boolean ***********************************************************************/ bool get_binaries(htable *pht) { char fbin[MAXPATHLEN], /* full binary path */ *pstr, *pcc; dynary *stpath; prsopt *ppo; unsigned int i; /* * splitting the PATH variable and storing in a * dynamic array for later use by find_file */ ppo = hash_get(pht, PMKCONF_PATH_BIN); if (ppo == NULL) { errorf("unable to get binary path record."); return(false); } pstr = po_get_str(ppo->value); if (pstr == NULL) { errorf("unable to get binary path value."); return(false); } stpath = str_to_dynary(pstr , PATH_STR_DELIMITER); if (stpath == NULL) { errorf("could not split the PATH environment variable correctly."); return(false); } /* check standard compilers */ pcc = NULL; for (i = 0 ; i < nb_c_compilers ; i++) { if (find_file(stpath, c_compilers[i][0], fbin, sizeof(fbin)) == true) { if (record_data(pht, c_compilers[i][1], 'u', fbin) == false) { da_destroy(stpath); return(false); } verbosef("Setting '%s' => '%s'", c_compilers[i][1], fbin); if (pcc == NULL) { pcc = strdup(fbin); } } else { verbosef("Info : '%s' (%s) not found", c_compilers[i][0], c_compilers[i][1]); } } /* setting PMKCONF_BIN_CC */ if (pcc != NULL) { /* standard compiler found */ snprintf(fbin, sizeof(fbin), "%s", pcc); /* XXX check ? */ free(pcc); if (record_data(pht, PMKCONF_BIN_CC, 'u', fbin) == false) { da_destroy(stpath); return(false); } verbosef("Setting '%s' => '%s'", PMKCONF_BIN_CC, fbin); } else { /* try to fallback on cc which is an "historical standard" */ if (find_file(stpath, "cc", fbin, sizeof(fbin)) == true) { if (record_data(pht, PMKCONF_BIN_CC, 'u', fbin) == false) { da_destroy(stpath); return(false); } verbosef("Setting '%s' => '%s'", PMKCONF_BIN_CC, fbin); } else { /* okay then maybe a fucking non standard "gcc" name ? */ if (find_file(stpath, "gcc", fbin, sizeof(fbin)) == true) { if (record_data(pht, PMKCONF_BIN_CC, 'u', fbin) == false) { da_destroy(stpath); return(false); } verbosef("Setting '%s' => '%s'", PMKCONF_BIN_CC, fbin); } else { /* no luck, unable to find the c compiler */ errorf("cannot find CC compiler."); da_destroy(stpath); return(false); } } } /* searching some specific binaries */ for (i = 0; i < MAXBINS; i++) { if (find_file(stpath, binaries[i][0], fbin, sizeof(fbin)) == true) { if (record_data(pht, binaries[i][1], 'u', fbin) == false) { da_destroy(stpath); return(false); } verbosef("Setting '%s' => '%s'", binaries[i][1], fbin); } else { verbosef("**warning: '%s' Not Found", binaries[i][0]); } } da_destroy(stpath); return(true); } /***************** * predef_vars() * *********************************************************************** DESCR Add to the hash table the predefined variables we cannot get automagically. IN pht: hash table where we have to store the values OUT boolean ***********************************************************************/ bool predef_vars(htable *pht) { int i; for (i = 0 ; i < nbpredef ; i++) { if (record_data(pht, predef[i].key, 'u', predef[i].value) == false) { errorf("failed to add '%s'.", predef[i].key); return(false); } verbosef("Setting '%s' => '%s'", predef[i].key, predef[i].value); } return(true); } /**************** * check_echo() * *********************************************************************** DESCR Check echo output IN pht: hash table where we have to store the values OUT boolean ***********************************************************************/ bool check_echo(htable *pht) { FILE *echo_pipe = NULL; char buf[TMP_BUF_LEN], echocmd[TMP_BUF_LEN]; char *echo_n, *echo_c, *echo_t; size_t s; snprintf(echocmd, sizeof(echocmd), ECHO_CMD); /* should not fail */ if ((echo_pipe = popen(echocmd, "r")) == NULL) { errorf("unable to execute '%s'.", echocmd); return(false); } s = fread(buf, sizeof(char), sizeof(buf), echo_pipe); buf[s] = CHAR_EOS; if (feof(echo_pipe) == 0) { errorf("pipe not empty."); pclose(echo_pipe); return(false); } pclose(echo_pipe); if (strncmp(buf, "one\\c\n-n two\nthree\n", sizeof(buf)) == 0) { /* ECHO_N= ECHO_C='\n' ECHO_T='\t' */ echo_n = ECHO_EMPTY; echo_c = ECHO_NL; echo_t = ECHO_HT; } else { if (strncmp(buf, "one\\c\ntwothree\n", sizeof(buf)) == 0) { /* ECHO_N='-n' ECHO_C= ECHO_T= */ echo_n = ECHO_N; echo_c = ECHO_EMPTY; echo_t = ECHO_EMPTY; } else { if (strncmp(buf, "one-n two\nthree\n", sizeof(buf)) == 0) { /* ECHO_N= ECHO_C='\c' ECHO_T= */ echo_n = ECHO_EMPTY; echo_c = ECHO_C; echo_t = ECHO_EMPTY; } else { if (strncmp(buf, "onetwothree\n", sizeof(buf)) == 0) { /* ECHO_N= ECHO_C='\\c' ECHO_T= */ echo_n = ECHO_EMPTY; echo_c = ECHO_C; echo_t = ECHO_EMPTY; } else { errorf("unable to set ECHO_* variables."); return(false); } } } } if (record_data(pht, PMKCONF_AC_ECHO_N, 'u', echo_n) == false) return(false); verbosef("Setting '%s' => '%s'", PMKCONF_AC_ECHO_N, echo_n); if (record_data(pht, PMKCONF_AC_ECHO_C, 'u', echo_c) == false) return(false); verbosef("Setting '%s' => '%s'", PMKCONF_AC_ECHO_C, echo_c); if (record_data(pht, PMKCONF_AC_ECHO_T, 'u', echo_t) == false) return(false); verbosef("Setting '%s' => '%s'", PMKCONF_AC_ECHO_T, echo_t); return(true); } /******************* * check_libpath() * *********************************************************************** DESCR Check pkgconfig libpath IN pht: hash table where we have to store the values OUT boolean NOTE this path must be relative to the real prefix. This means that we can't rely on predefined prefix. ***********************************************************************/ bool check_libpath(htable *pht) { bool found = false; char libpath[MAXPATHLEN]; int i; if (hash_get(pht, PMKCONF_BIN_PKGCONFIG) != NULL) { /* try predefined path for pkconfig lib path */ for (i = 0 ; (i < nbpcpath) && (found == false) ; i++) { strlcpy(libpath, pcpath[i], sizeof(libpath)); /* pkgconfig path suffix */ if (strlcat_b(libpath, PMKVAL_LIB_PKGCONFIG, sizeof(libpath)) == false) { return false; } if (dir_exists(libpath) == true) { found = true; } } if (found == true) { if (record_data(pht, PMKCONF_PC_PATH_LIB, 'u', libpath) == false) { return false; } verbosef("Setting '%s' => '%s'", PMKCONF_PC_PATH_LIB, libpath); } else { verbosef("**warning: pkgconfig lib path not found (%s not set).", PMKCONF_PC_PATH_LIB); } } return true; } /****************** * get_cpu_data() * *********************************************************************** DESCR Check the cpu family IN uname_m: uname machine string OUT boolean ***********************************************************************/ bool get_cpu_data(htable *pht) { char *uname_m; char *pstr; hkeys *phk; htable *spht; pmkobj *po; prsdata *pdata; prsopt *ppo; unsigned int i; ppo = hash_get(pht, PMKCONF_OS_ARCH); if (ppo == NULL) { errorf("failed to get value for %s", PMKCONF_OS_ARCH); return(false); } po = ppo->value; if (po == NULL) { errorf("unexpected data for %s", PMKCONF_OS_ARCH); return(false); } uname_m = po_get_str(po); if (uname_m == NULL) { errorf("unexpected value for %s", PMKCONF_OS_ARCH); return(false); } pdata = parse_cpu_data(PMKCPU_DATA); if (pdata == NULL) { /* error message already done */ return(false); } pstr = check_cpu_arch(uname_m, pdata); /* no check, never NULL */ if (record_data(pht, PMKCONF_HW_CPU_ARCH, 'u', pstr) == false) { errorf("failed to record value for %s", PMKCONF_HW_CPU_ARCH); return(false); } verbosef("Setting '%s' => '%s'", PMKCONF_HW_CPU_ARCH, pstr); spht = arch_wrapper(pdata, pstr); if (spht != NULL) { phk = hash_keys(spht); if (phk != NULL) { for(i = 0 ; i < phk->nkey ; i++) { pstr = hash_get(spht, phk->keys[i]); /* should not be NULL */ if (record_data(pht, phk->keys[i], 'u', pstr) == false) return(false); verbosef("Setting '%s' => '%s'", phk->keys[i], pstr); } hash_free_hkeys(phk); } hash_destroy(spht); } prsdata_destroy(pdata); return(true); } /**************** * dir_exists() * *********************************************************************** DESCR Check if a directory does exist IN fdir: directory to search OUT boolean ***********************************************************************/ bool dir_exists(const char *fdir) { DIR *dirp; size_t len; len = strlen(fdir); if (len < MAXPATHLEN) { dirp = opendir(fdir); if (dirp != NULL) { closedir(dirp); return(true); } } return(false); } /********************** * byte_order_check() * *********************************************************************** DESCR Byte order check IN pht: hash table to store value OUT boolean ***********************************************************************/ bool byte_order_check(htable *pht) { char bo_type[16]; int num = 0x41424344; if (((((char *)&num)[0]) == 0x41) && ((((char *)&num)[1]) == 0x42) && ((((char *)&num)[2]) == 0x43) && ((((char *)&num)[3]) == 0x44)) { strlcpy(bo_type, HW_ENDIAN_BIG, sizeof(bo_type)); /* should not fail */ } else { if (((((char *)&num)[3]) == 0x41) && ((((char *)&num)[2]) == 0x42) && ((((char *)&num)[1]) == 0x43) && ((((char *)&num)[0]) == 0x44)) { strlcpy(bo_type, HW_ENDIAN_LITTLE, sizeof(bo_type)); /* should not fail */ } else { strlcpy(bo_type, HW_ENDIAN_UNKNOWN, sizeof(bo_type)); /* should not fail */ } } if (record_data(pht, PMKCONF_HW_BYTEORDER, 'u', bo_type) == false) return(false); verbosef("Setting '%s' => '%s'", PMKCONF_HW_BYTEORDER, bo_type); return(true); } /************** * verbosef() * *********************************************************************** DESCR Simple formated verbose function IN fmt: format string OUT NONE ***********************************************************************/ void verbosef(const char *fmt, ...) { char buf[MAX_ERR_MSG_LEN]; va_list plst; if (verbose_flag == 1) { va_start(plst, fmt); vsnprintf(buf, sizeof(buf), fmt, plst); va_end(plst); printf("%s\n", buf); } } /******************** * detection_loop() * *********************************************************************** DESCR Detection loop IN argc: argument number argv: argument array OUT boolean ***********************************************************************/ bool detection_loop(int argc, char *argv[]) { FILE *config; bool process_clopts = false, cfg_backup = false; char *pstr; int ch; prsopt *ppo; #ifndef errno extern int errno; #endif /* errno */ optind = 1; while ((ch = getopt(argc, argv, PMKSTP_OPT_STR)) != -1) { switch(ch) { case 'r' : /* mark to be deleted in hash */ if (record_data(ht, optarg, PMKSTP_REC_REMV, NULL) == false) { errorf("failed to record '%s'.", optarg); return(false); } process_clopts = true; break; case 'u' : /* add or update value */ ppo = prsopt_init(); if (ppo == NULL) { errorf("prsopt init failed."); return(false); } if (parse_clopt(optarg, ppo, PRS_PMKCONF_SEP) == false) { errorf("bad argument for -%c option: %s.", ch, optarg); return(false); } /* add in hash */ pstr = po_get_str(ppo->value); if (pstr == NULL) { errorf("failed to get argument for -%c option", ch); return(false); } /* record prsopt structure directly, fast and simple */ ppo->opchar = PMKSTP_REC_UPDT; if (hash_update(ht, ppo->key, ppo) == HASH_ADD_FAIL) { prsopt_destroy(ppo); errorf("hash update failed."); return(false); } /* XXX use record_data => cost much memory and cpu XXX */ /*if (record_data(ht, ppo->key, PMKSTP_REC_UPDT, pstr) == false) {*/ /* errorf("failed to record '%s'.", ppo->key); */ /* prsopt_destroy(ppo); */ /* return(false); */ /*} */ /*prsopt_destroy(ppo); */ process_clopts = true; break; case 'v' : case 'V' : /* * already processed in main() */ break; case '?' : default : usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; printf("PMKSETUP version %s", PREMAKE_VERSION); #ifdef DEBUG printf(" [SUB #%s] [SNAP #%s]", PREMAKE_SUBVER_PMKSETUP, PREMAKE_SNAP); #endif /* DEBUG */ printf("\n\n"); if (process_clopts == false) { /* standard behavior, gathering data */ if (gather_data(ht) == false) return(false); } /* parse configuration file */ config = fopen(PREMAKE_CONFIG_PATH, "r"); if (config != NULL) { /* switch backup flag */ cfg_backup = true; printf("==> Configuration file found: %s\n", PREMAKE_CONFIG_PATH); if (parse_pmkconf(config, ht, PRS_PMKCONF_SEP, check_opt) == false) { fclose(config); errorf("parsing failed."); return(false); } else { fclose(config); } } else { printf("==> Configuration file not found.\n"); } printf("==> Merging remaining data...\n"); /* writing the remaining data stored in the hash */ if (write_new_data(ht) == false) return(false); return(true); } /**************** * child_loop() * *********************************************************************** DESCR Child main loop IN uid: privsep user id gid: privsep user group argc: argument number argv: argument array OUT NONE ***********************************************************************/ void child_loop(uid_t uid, gid_t gid, int argc, char *argv[]) { #ifndef WITHOUT_FORK if (getuid() == 0) { /* user has root privs, DROP THEM ! */ if (setgid(gid) != 0) { /* failed to change gid */ errorf(EMSG_PRIV_FMT, "gid"); _exit(EXIT_FAILURE); } if (setegid(gid) != 0) { /* failed to change egid */ errorf(EMSG_PRIV_FMT, "egid"); _exit(EXIT_FAILURE); } if (setuid(uid) != 0) { /* failed to change uid */ errorf(EMSG_PRIV_FMT, "uid"); _exit(EXIT_FAILURE); } if (seteuid(uid) != 0) { /* failed to change euid */ errorf(EMSG_PRIV_FMT, "euid"); _exit(EXIT_FAILURE); } } #endif /* WITHOUT_FORK */ #ifdef PMKSETUP_DEBUG debugf("gid = %d", getgid()); debugf("uid = %d", getuid()); #endif /* PMKSETUP_DEBUG */ ht = hash_init_adv(MAX_CONF_OPT, NULL, (void (*)(void *)) prsopt_destroy, NULL); if (ht == NULL) { errorf("cannot create hash table."); exit(EXIT_FAILURE); } if (detection_loop(argc, argv) == false) { hash_destroy(ht); exit(EXIT_FAILURE); } /* destroying the hash once we're done with it */ hash_destroy(ht); } /***************** * parent_loop() * *********************************************************************** DESCR Parent main loop IN pid: pid of the child OUT NONE ***********************************************************************/ void parent_loop(pid_t pid) { bool error = false; #ifndef WITHOUT_FORK int status; waitpid(pid, &status, WUNTRACED); #ifdef PMKSETUP_DEBUG debugf("waitpid() status = %d", WEXITSTATUS(status)); #endif /* PMKSETUP_DEBUG */ #endif /* WITHOUT_FORK */ if (fclose(sfp) != 0) { /* hazardous result => exit */ errorf("cannot close temporary file '%s' : %s.", sfp, strerror(errno)); exit(EXIT_FAILURE); } #ifdef WITHOUT_FORK /* * without fork, the child part will exit() if a problem occur * so we shouldn't need to care about what happens */ #else /* if child status is ok, writing changes */ if (status == 0) { #endif /* * check if pmk.conf already exists * NOTE: no race condition here for access(), BUT * BE CAREFUL if changes are to be made. */ if (access(PREMAKE_CONFIG_PATH, F_OK) == 0) { /* see above */ /* backup configuration file */ printf("==> Backing up configuration file: %s\n", PREMAKE_CONFIG_PATH_BAK); if (rename(PREMAKE_CONFIG_PATH, PREMAKE_CONFIG_PATH_BAK) != 0) { errorf("configuration file backup failed: %s.", strerror(errno)); error = true; } } /* copying the temporary config to the system one */ printf("==> Saving configuration file: %s\n", PREMAKE_CONFIG_PATH); if (fcopy(sfn, PREMAKE_CONFIG_PATH, PREMAKE_CONFIG_MODE) == false) { errorf("failed to copy temporary file '%s'.", sfn); exit(EXIT_FAILURE); } #ifndef WITHOUT_FORK } #endif #ifdef PMKSETUP_DEBUG debugf("%s has not been deleted!", sfn); #else if (unlink(sfn) == -1) { errorf("cannot remove temporary file: '%s' : %s.", sfn, strerror(errno)); error = true; } #endif /* PMKSETUP_DEBUG */ #ifndef WITHOUT_FORK if (status != 0) { errorf("child failed (status %d)", status); exit(EXIT_FAILURE); } #endif /* WITHOUT_FORK */ if (error == true) exit(EXIT_FAILURE); } /*********** * usage() * *********************************************************************** DESCR pmksetup(8) usage IN NONE OUT NONE ***********************************************************************/ void usage(void) { fprintf(stderr, "usage: pmksetup [-hVv] " "[-r variable] [-u variable=value]\n"); exit(EXIT_FAILURE); } /********** * main() * *********************************************************************** DESCR Main loop ***********************************************************************/ int main(int argc, char *argv[]) { struct passwd *pw; gid_t gid = 0; pid_t pid; uid_t uid = 0; int ch; optind = 1; while ((ch = getopt(argc, argv, PMKSTP_OPT_STR)) != -1) { switch(ch) { case 'r' : case 'u' : /* * ignore this options at this level, it * will be processed later */ break; case 'v' : fprintf(stderr, "%s\n", PREMAKE_VERSION); return(true); break; case 'V' : if (verbose_flag == 0) verbose_flag = 1; break; case '?' : default : usage(); /* NOTREACHED */ } } if (getuid() == 0) { #ifdef PMKSETUP_DEBUG debugf("PRIVSEP_USER = '%s'", PRIVSEP_USER); #endif /* PMKSETUP_DEBUG */ pw = getpwnam(PRIVSEP_USER); if (pw == NULL) { errorf("cannot get user data for '%s'.", PRIVSEP_USER); exit(EXIT_FAILURE); } uid = pw->pw_uid; gid = pw->pw_gid; } /* check if syconfdir exists */ if (access(CONFDIR, F_OK) != 0) { /* no race condition, just mkdir() */ verbosef("==> Creating '%s' directory.", CONFDIR); if (mkdir(CONFDIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { errorf("cannot create '%s' directory : %s.", CONFDIR, strerror(errno)); exit(EXIT_FAILURE); } } sfp = tmp_open(PREMAKE_CONFIG_TMP, "w", sfn, sizeof(sfn)); if (sfp == NULL) { errorf("cannot open temporary file '%s' : %s.", sfn, strerror(errno)); exit(EXIT_FAILURE); } #ifndef WITHOUT_FORK /* forking detection code */ pid = fork(); switch (pid) { case -1: /* fork failed */ errorf("fork failed."); break; case 0: /* child start here after forking */ #endif /* WITHOUT_FORK */ child_loop(uid, gid, argc, argv); #ifndef WITHOUT_FORK break; default: /* parent continue here after forking */ #else pid = getpid(); #endif /* WITHOUT_FORK */ parent_loop(pid); #ifndef WITHOUT_FORK break; } #endif /* WITHOUT_FORK */ return(EXIT_SUCCESS); } /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/pkgconfig.h010064400017500000000000000070351022730075300133710ustar00mipswheel/* $Id: pkgconfig.h 1399 2005-04-13 20:32:43Z mipsator $ */ /* * Copyright (c) 2003-2004 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. * */ #ifndef _PMK_PKGCONFIG_H_ #define _PMK_PKGCONFIG_H_ #include "dynarray.h" #include "hash.h" /********** constants ************************************************************************/ #define PMKCFG_ENV_PATH "PKG_CONFIG_PATH" #define PMKCFG_ENV_LIBDIR "PKG_CONFIG_LIBDIR" #define PKGCFG_CHAR_PATH_SEP ':' #define PKGCFG_HT_SIZE 512 #define VERSION_CHAR_SEP '.' /* specific flags */ #define PKGCFG_CFLAGS_I 1 #define PKGCFG_CFLAGS_o 2 #define PKGCFG_CFLAGS_ALL PKGCFG_CFLAGS_I | PKGCFG_CFLAGS_o #define PKGCFG_LIBS_L 1 #define PKGCFG_LIBS_l 2 #define PKGCFG_LIBS_o 4 #define PKGCFG_LIBS_ALL PKGCFG_LIBS_L | PKGCFG_LIBS_l | PKGCFG_LIBS_o /********** constants ************************************************************************/ /* package structures */ typedef struct { char *name, *descr, *version, *requires; dynary *cflags, *libs; htable *variables; } pkgcell; typedef struct { htable *files, *cells; dynary *mods; } pkgdata; typedef struct { char *kw_name; unsigned int kw_id; } pkgkw; /******************** function prototypes ************************************************************************/ pkgcell *pkgcell_init(void); void pkgcell_destroy(pkgcell *); pkgdata *pkgdata_init(void); void pkgdata_destroy(pkgdata *); char *skip_blank(char *); bool scan_dir(char *, pkgdata *); bool pkg_collect(char *, pkgdata *); bool parse_keyword(pkgcell *, char *, char *); char *process_variables(char *, htable *); pkgcell *parse_pc_file(char *); pkgcell *pkg_cell_add(pkgdata *, char *); bool pkg_recurse(pkgdata *, char *); char *pkg_single_append(char *, char *); char *pkg_get_cflags(pkgdata *); char *pkg_get_cflags_adv(pkgdata *, unsigned int); char *pkg_get_libs(pkgdata *); char *pkg_get_libs_adv(pkgdata *, unsigned int); bool pkg_mod_exists(pkgdata *, char *); int compare_version(char *, char *); #endif /* _PMK_PKGCONFIG_H_ */ pmk-0.10.4/detect.c010064400017500000000000000425131052021275100126610ustar00mipswheel/* $Id: detect.c 1921 2006-10-26 20:09:13Z coudercd $ */ /* * Copyright (c) 2003-2006 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. * */ #include #include #include "compat/pmk_stdio.h" #include "compat/pmk_unistd.h" #include "common.h" #include "detect.h" #include "lang.h" /*************** * keyword data * ***********************************************************************/ /* * ADD_COMPILER options */ kw_t req_addcomp[] = { {CC_KW_ID, PO_STRING}, {CC_KW_DESCR, PO_STRING}, {CC_KW_MACRO, PO_STRING} }; kw_t opt_addcomp[] = { {CC_KW_VERSION, PO_STRING}, {CC_KW_SLCFLAGS, PO_STRING}, {CC_KW_SLLDFLAGS, PO_STRING} }; kwopt_t kw_addcomp = { req_addcomp, sizeof(req_addcomp) / sizeof(kw_t), opt_addcomp, sizeof(opt_addcomp) / sizeof(kw_t) }; /* * ADD_SYSTEM options */ kw_t req_addsys[] = { {SYS_KW_NAME, PO_STRING}, {SYS_KW_SH_EXT, PO_STRING}, {SYS_KW_SH_NONE, PO_STRING}, {SYS_KW_SH_VERS, PO_STRING}, {SYS_KW_ST_EXT, PO_STRING}, {SYS_KW_ST_NONE, PO_STRING}, {SYS_KW_ST_VERS, PO_STRING}, {SYS_KW_VERSION, PO_STRING} }; kwopt_t kw_addsys = { req_addsys, sizeof(req_addsys) / sizeof(kw_t), NULL, /* allow 'custom' options */ 0 }; prskw kw_pmkcomp[] = { {"ADD_COMPILER", PCC_TOK_ADDC, PRS_KW_CELL, PRS_TOK_NULL, &kw_addcomp}, {"ADD_SYSTEM", PCC_TOK_ADDS, PRS_KW_CELL, PRS_TOK_NULL, &kw_addsys} }; int nbkwpc = sizeof(kw_pmkcomp) / sizeof(prskw); /************* * procedures * ***********************************************************************/ /***************************** * %PROC init_compiler_data() * *********************************************************************** * %DESCR initialize compiler data structure * * %PARAM pcd: compiler data structure * %PARAM sz: number of languages * * %RETURN boolean status ***********************************************************************/ bool init_compiler_data(comp_data_t *pcd, size_t lnb) { int i; /* record size of compiler profile array */ pcd->sz = lnb; /* allocate array of compiler profiles */ pcd->data = (compiler_t *) malloc(sizeof(compiler_t) * lnb); if (pcd->data == NULL) { return false; } /* initialize every cell of the array */ for (i = 0 ; i < (int) lnb ; i++) { pcd->data[i].c_id = NULL; pcd->data[i].descr = NULL; pcd->data[i].c_macro = NULL; pcd->data[i].v_macro = NULL; pcd->data[i].slcflags = NULL; pcd->data[i].slldflags = NULL; pcd->data[i].version = NULL; pcd->data[i].lang = LANG_UNKNOWN; } return true; } /****************************** * %PROC clean_compiler_cell() * *********************************************************************** * %DESCR initialize compiler data structure * * %PARAM pc: compiler cell structure * * %RETURN boolean status ***********************************************************************/ void clean_compiler_cell(compiler_t *pc) { if (pc->c_id != NULL) { free(pc->c_id); } if (pc->descr != NULL) { free(pc->descr); } if (pc->c_macro != NULL) { free(pc->c_macro); } if (pc->v_macro != NULL) { free(pc->v_macro); } if (pc->slcflags != NULL) { free(pc->slcflags); } if (pc->slldflags != NULL) { free(pc->slldflags); } if (pc->version != NULL) { free(pc->version); } } /****************************** * %PROC clean_compiler_data() * *********************************************************************** * %DESCR initialize compiler data structure * * %PARAM pcd: compiler data structure * * %RETURN boolean status ***********************************************************************/ void clean_compiler_data(comp_data_t *pcd) { int i; /* clean every cell of the array */ for (i = 0 ; i < (int) pcd->sz ; i++) { clean_compiler_cell(&(pcd->data[i])); } /* free allocated memory of the array */ free(pcd->data); pcd->sz = 0; } /*************************** * %PROC compcell_destroy() * *********************************************************************** * %DESCR clean comp_prscell_t structure * * %PARAM pcc: structure to clean * * %RETURN NONE ***********************************************************************/ void compcell_destroy(comp_prscell_t *pcc) { free(pcc->c_id); free(pcc->descr); free(pcc->c_macro); free(pcc->v_macro); free(pcc->slcflags); free(pcc->slldflags); free(pcc); } /************************** * %PROC init_comp_parse() * *********************************************************************** * %DESCR initialize comp_parse_t structure from compiler data file * * %RETURN new structure or NULL on failure ***********************************************************************/ comp_parse_t *init_comp_parse(void) { comp_parse_t *pcp; /* allocate compiler data structure */ pcp = (comp_parse_t *) malloc(sizeof(comp_parse_t)); if (pcp == NULL) { return NULL; } /* init compilers hash table */ pcp->cht = hash_init_adv(MAX_COMP, NULL, (void (*)(void *)) compcell_destroy, NULL); if (pcp->cht == NULL) { free(pcp); /*debugf("cannot initialize comp_data");*/ return NULL; } /* init systems hash table */ pcp->sht = hash_init(MAX_OS); if (pcp->sht == NULL) { free(pcp); hash_destroy(pcp->sht); /*debugf("cannot initialize comp_data");*/ return NULL; } /* init ok */ return pcp; } /***************************** * %PROC destroy_comp_parse() * *********************************************************************** * %DESCR destroy comp_parse_t structure * * %PARAM pcp: compiler parsed data structure * * %RETURN none ***********************************************************************/ void destroy_comp_parse(comp_parse_t *pcp) { /* destroy compiler cell hash table */ hash_destroy(pcp->cht); /* destroy system cell hash table */ hash_destroy(pcp->sht); } /*********************** * %PROC add_compiler() * *********************************************************************** * %DESCR add a new compiler cell * * %PARAM pcp: compiler parsed data structure * %PARAM pht: compiler cell hash table * * %RETURN boolean ***********************************************************************/ bool add_compiler(comp_parse_t *pcp, htable *pht) { comp_prscell_t *pcell; char *pstr, tstr[TMP_BUF_LEN]; pcell = (comp_prscell_t *) malloc(sizeof(comp_prscell_t)); if (pcell == NULL) return false; pstr = po_get_str(hash_get(pht, CC_KW_ID)); if (pstr == NULL) { free(pcell); return false; } else { pcell->c_id = strdup(pstr); } pstr = po_get_str(hash_get(pht, CC_KW_DESCR)); if (pstr == NULL) { free(pcell); return false; } else { pcell->descr = strdup(pstr); } pstr = po_get_str(hash_get(pht, CC_KW_MACRO)); if (pstr == NULL) { free(pcell); return false; } else { pcell->c_macro = strdup(pstr); } pstr = po_get_str(hash_get(pht, CC_KW_VERSION)); if (pstr == NULL) { pcell->v_macro = strdup(DEF_NOVERSION); } else { if (snprintf_b(tstr, sizeof(tstr), DEF_VERSION, pstr) == false) { free(pcell); return false; } pcell->v_macro = strdup(tstr); } pstr = po_get_str(hash_get(pht, CC_KW_SLCFLAGS)); if (pstr == NULL) { pcell->slcflags = strdup(""); /* default to empty string */ } else { pcell->slcflags = strdup(pstr); } pstr = po_get_str(hash_get(pht, CC_KW_SLLDFLAGS)); if (pstr == NULL) { pcell->slldflags = strdup(""); /* default to empty string */ } else { pcell->slldflags = strdup(pstr); } /* no need to strdup */ if (hash_update(pcp->cht, pcell->c_id, pcell) == HASH_ADD_FAIL) { return false; } return true; } /********************* * %PROC add_system() * *********************************************************************** * %DESCR add a new system cell * * %PARAM pcp: compiler parsed data structure * %PARAM pht: system cell hash table * * %RETURN boolean ***********************************************************************/ bool add_system(comp_parse_t *pcp, htable *pht, char *osname) { char *name, *pstr; hkeys *phk; unsigned int i; name = po_get_str(hash_get(pht, SYS_KW_NAME)); if (name == NULL) { return false; } if (strncmp(osname, name, sizeof(osname)) != 0) { /* not the target system, skipping */ return true; } hash_add(pht, SL_SYS_LABEL, po_mk_str(strdup(name))); /* XXX check */ hash_delete(pht, SYS_KW_NAME); /* XXX check ? */ /* remaining values are system overrides, save it */ phk = hash_keys(pht); for (i = 0 ; i < phk->nkey ; i++) { pstr = po_get_str(hash_get(pht, phk->keys[i])) ; hash_update_dup(pcp->sht, phk->keys[i], pstr); /* XXX check */ } return true; } /************************** * %PROC parse_comp_file() * *********************************************************************** * %DESCR parse compiler data file * * %PARAM cdfile: compiler data file to parse * %PARAM osname: name of the target OS * * %RETURN pointer to allocated compiler parsing structure ***********************************************************************/ comp_parse_t *parse_comp_file(char *cdfile, char *osname) { FILE *fd; bool rval; comp_parse_t *pcp; prscell *pcell; prsdata *pdata; /* try to open compilers data file */ fd = fopen(cdfile, "r"); if (fd == NULL) { errorf("cannot open '%s' : %s.", cdfile, strerror(errno)); return NULL; } /* init compiler data structure */ pcp = init_comp_parse(); if (pcp == NULL) { fclose(fd); return NULL; } /* initialize parsing structure */ pdata = prsdata_init(); if (pdata == NULL) { errorf("cannot initialize prsdata."); destroy_comp_parse(pcp); fclose(fd); return NULL; } /* parse data file and fill prsdata strucutre */ rval = parse_pmkfile(fd, pdata, kw_pmkcomp, nbkwpc); fclose(fd); if (rval == true) { pcell = pdata->tree->first; while (pcell != NULL) { switch(pcell->token) { case PCC_TOK_ADDC : if (add_compiler(pcp, pcell->data) == false) { errorf("add_compiler() failed in parse_comp_file_adv()."); destroy_comp_parse(pcp); prsdata_destroy(pdata); return NULL; } break; case PCC_TOK_ADDS : if (osname != NULL) { if (add_system(pcp, pcell->data, osname) == false) { errorf("add_system() failed in parse_comp_file_adv()."); destroy_comp_parse(pcp); prsdata_destroy(pdata); return NULL; } } break; default : errorf("parsing of data file failed."); destroy_comp_parse(pcp); prsdata_destroy(pdata); return NULL; break; } pcell = pcell->next; } } else { errorf("parsing of data file failed."); destroy_comp_parse(pcp); prsdata_destroy(pdata); return NULL; } /* parsing data no longer needed */ prsdata_destroy(pdata); return pcp; } /************************ * %PROC gen_test_file() * *********************************************************************** * %DESCR generate test file * * %PARAM pcp: compiler data structure * %PARAM fnbuf: filename buffer * %PARAM bsz: buffer size * * %RETURN boolean status ***********************************************************************/ bool gen_test_file(comp_parse_t *pcp, char *fnbuf, size_t bsz) { FILE *fp; comp_prscell_t *pcell; hkeys *phk; unsigned int i; /* get key list of parsed compiler data */ phk = hash_keys(pcp->cht); if (phk == NULL) { errorf("no parsed compiler data found"); return false; } /* open source file for writing */ fp = tmps_open(CC_TEST_FILE, "w", fnbuf, bsz, strlen(CC_TFILE_EXT)); if (fp == NULL) { errorf("cannot open compiler test file ('%s').", fnbuf); hash_free_hkeys(phk); return false; } /* * fill the source test file with the code that try to identify the compiler */ fprintf(fp, COMP_TEST_HEADER); for (i = 0 ; i < phk->nkey ; i++) { pcell = hash_get(pcp->cht, phk->keys[i]); fprintf(fp, COMP_TEST_FORMAT, pcell->descr, pcell->c_macro, pcell->c_id, pcell->v_macro); } fprintf(fp, COMP_TEST_FOOTER); fclose(fp); hash_free_hkeys(phk); return true; } /********************** * %PROC comp_identify * *********************************************************************** * %DESCR identify given compiler * * %PARAM cpath: path of the compiler to identify * %PARAM blog: build log file name * %PARAM pc: compiler cell to populate * %PARAM pcp: compiler parsing structure * * %RETURN boolean ***********************************************************************/ bool comp_identify(char *cpath, char *blog, compiler_t *pc, comp_parse_t *pcp) { FILE *rpipe; bool failed = false; char cfgcmd[MAXPATHLEN], ftmp[MAXPATHLEN], pipebuf[TMP_BUF_LEN]; int r; if (gen_test_file(pcp, ftmp, sizeof(ftmp)) == false) { return false; } /* build compiler command */ if (snprintf_b(cfgcmd, sizeof(cfgcmd), CC_TEST_FORMAT, cpath, CC_TEST_BIN, ftmp, blog) == false) { errorf("failed to build compiler command line."); return false; } /* get result */ r = system(cfgcmd); /* test file no longer needed */ if (unlink(ftmp) == -1) { /* cannot remove temporary file */ errorf("cannot remove %s : %s.", ftmp, strerror(errno)); } /* if compiled without error */ if (r == 0) { rpipe = popen(CC_TEST_BIN, "r"); if (rpipe != NULL) { if (get_line(rpipe, pipebuf, sizeof(pipebuf)) == false) { errorf("cannot get compiler id."); failed = true; } else { /* get compiler id */ pc->c_id = strdup(pipebuf); if (get_line(rpipe, pipebuf, sizeof(pipebuf)) == false) { errorf("cannot get compiler version."); failed = true; } else { pc->version = strdup(pipebuf); } } pclose(rpipe); } else { errorf("failed to get output from test binary."); } /* delete binary */ if (unlink(CC_TEST_BIN) == -1) { errorf("cannot remove %s : %s.", CC_TEST_BIN, strerror(errno)); } if (failed == true) { return false; } } else { errorf("failed to build test binary : %s.", strerror(errno)); return false; } return true; } /******************** * %PROC comp_detect * *********************************************************************** * %DESCR identify given compiler * * %PARAM cpath: path of the compiler to identify * %PARAM blog: build log file name * %PARAM pc: compiler cell to populate * %PARAM pcp: compiler parsing structure * %PARAM label: XXX * * %RETURN boolean ***********************************************************************/ bool comp_detect(char *cpath, char *blog, compiler_t *pc, comp_parse_t *pcp, char *label) { char buf[TMP_BUF_LEN], *pstr; comp_prscell_t *pcell; if (comp_identify(cpath, blog, pc, pcp) == false) { return false; } /* look for the detected compiler data */ pcell = hash_get(pcp->cht, pc->c_id); if (pcell == NULL) { errorf("unknown compiler identifier : %s\n", pc->c_id); return false; } /* * populate compiler cell with identified compiler data * * c_id and version have already been set by comp_identify * lang XXX ? */ pc->descr = strdup(pcell->descr); pc->c_macro = strdup(pcell->c_macro); /* XXX useless ? */ pc->v_macro = strdup(pcell->v_macro); /* XXX useless ? */ /* * check system specific flags for shared library support */ /* generate tag for system specific compiler flags */ if (snprintf_b(buf, sizeof(buf), "%s_%s", label, pc->c_id) == false) { errorf("overflow.\n"); return(false); } /* check if an override exists for compiler flags */ pstr = hash_get(pcp->sht, buf); if (pstr == NULL) { /* take compiler's generic flags */ pc->slcflags = strdup(pcell->slcflags); } else { /* take system specific flags */ pc->slcflags = strdup(pstr); } /* generate tag for system specific linker flags */ if (snprintf_b(buf, sizeof(buf), "%s_%s", SL_LDFLAG_VARNAME, pc->c_id) == false) { errorf("overflow.\n"); return(false); } /* check if an override exists for linker flags */ pstr = hash_get(pcp->sht, buf); if (pstr == NULL) { /* take compiler's generic flags */ pc->slldflags = strdup(pcell->slldflags); } else { /* take system specific flags */ pc->slldflags = strdup(pstr); } /*pcd->data[i].lang = LANG_UNKNOWN;*/ return true; } /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/tests004075500017500000000000000000001077177766200123575ustar00mipswheelpmk-0.10.4/tests/pkgconfig_test.c010064400017500000000000000025241030204577300155650ustar00mipswheel/* $Id: pkgconfig_test.c 1463 2005-08-21 09:40:11Z mipsator $ */ /* Public Domain */ /* pkg-config tools test */ /*#define PKGCFG_DEBUG 1*/ /*#define HASH_DEBUG 1*/ #include #include "../compat/pmk_stdbool.h" #include "../compat/pmk_stdio.h" #include "../common.h" #include "../pkgconfig.h" int main(int argc, char *argv[]) { char *mod; pkgcell *ppc; pkgdata *ppd; ppd = pkgdata_init(); if (ppd == NULL) { errorf("cannot init pkgdata."); exit(EXIT_FAILURE); } /*scan_dir(PKGCONFIG_DIR, ppd);*/ pkg_collect("/usr/local/lib/pkgconfig", ppd); /* nice hardcode isn't it ? :) */ if (argc == 2) { mod = argv[1]; if (pkg_mod_exists(ppd, mod) == true) { printf("module '%s' found\n", mod); ppc = pkg_cell_add(ppd, mod); printf("module name = %s\n", ppc->name); printf("module description = %s\n", ppc->descr); printf("module version = %s\n", ppc->version); printf("module requires: %s\n", ppc->requires); /*printf("module = %s\n", ppc->);*/ /* get cflags and libs */ if (pkg_recurse(ppd, mod) == false) { errorf("failed on recurse !"); } else { printf("\ncflags = '%s'\n", pkg_get_cflags(ppd)); printf("\nlibs = '%s'\n", pkg_get_libs(ppd)); } } else { printf("module not found\n"); } } #ifdef PKGCFG_DEBUG debugf("destroy pkgdata"); #endif pkgdata_destroy(ppd); return(0); } pmk-0.10.4/tests/gen_comp_test.c010064400017500000000000000011051027375450500154060ustar00mipswheel/* $Id: gen_comp_test.c 1442 2005-08-02 20:36:21Z mipsator $ */ /* Public Domain */ /* generate compiler detection test file */ /*#define PRS_DEBUG 1*/ #include #include #include "../detect.h" #include "../parse.h" int main(void) { FILE *fp; comp_data *cdata; printf("Parsing compiler data.\n"); cdata = parse_comp_file("../data/pmkcomp.dat"); fp = fopen("cc_test.c", "w"); if (fp == NULL) { printf("Failed to open 'cc_test.c'.\n"); exit(EXIT_FAILURE); } gen_test_file(fp, cdata); fclose(fp); compdata_destroy(cdata); return(0); } pmk-0.10.4/tests/mkvar_test.c010064400017500000000000000006201027375450500147400ustar00mipswheel/* $Id: mkvar_test.c 1442 2005-08-02 20:36:21Z mipsator $ */ /* Public Domain */ /* make variables test */ #include #include "../common.h" int main(void) { char tmp[256]; get_make_var("CC", tmp, 256); printf("CC => %s\n", tmp); get_make_var("CFLAGS", tmp, 256); printf("CFLAGS => %s\n", tmp); get_make_var("LDFLAGS", tmp, 256); printf("LDFLAGS => %s\n", tmp); return(0); } pmk-0.10.4/tests/plang_test.c010075500017500000000000000033371030204577300147250ustar00mipswheel/* $Id: plang_test.c 1463 2005-08-21 09:40:11Z mipsator $ */ /* Public Domain */ /* c parser test */ #include #include #include "../compat/pmk_stdio.h" #include "../compat/pmk_string.h" #include "../parse_lang.h" bool ppro(void *, char *, prseng_t *); bool proc(void *, char *, prseng_t *); bool decl(void *, char *, prseng_t *); bool type(void *, char *, prseng_t *); bool ppro(void *data, char *pstr, prseng_t *ppe) { char iname[MAXPATHLEN], c; printf("PPRO: found preprocessor directive '%s'\n", pstr); if (strncmp(pstr, RKW_PP_INCL, strlen(pstr) + 1) == 0) { prs_c_skip(ppe); c = prseng_get_char(ppe); prseng_next_char(ppe); /* XXX */ prseng_get_idtf(ppe, iname, sizeof(iname), PRS_C_IDTF_FNAME); switch(c) { case '"' : printf("PPRO: local include '%s'\n", iname); break; case '<' : printf("PPRO: system include '%s'\n", iname); break; } } prs_c_line_skip(ppe); return(true); } bool proc(void *data, char *pstr, prseng_t *ppe) { printf("PROC: found function call '%s'\n", pstr); return(true); } bool decl(void *data, char *pstr, prseng_t *ppe) { printf("PROC: found function declarator '%s'\n", pstr); return(true); } bool type(void *data, char *pstr, prseng_t *ppe) { printf("TYPE: found type '%s'\n", pstr); return(true); } int main(int argc, char **argv) { FILE *fp; prs_cmn_t pcmn; if (argc != 2) { printf("Expecting a filename as argument\n"); exit(1); /* XXX */ } pcmn.func_ppro = &ppro; pcmn.func_proc = &proc; pcmn.func_decl = &decl; pcmn.func_type = &type; pcmn.data = NULL; fp = fopen(argv[1], "r"); if (fp == NULL) { printf("cannot open '%s'\n", argv[1]); } else { prs_c_file(&pcmn, fp); } fclose(fp); return(0); } pmk-0.10.4/tests/Makefile.pmk010064400017500000000000000275531033275266600146630ustar00mipswheel# Makefile template generated by pmkscan (2005-10-23 18:25). CPP= @CPP@ # language specific AS= @AS@ ASFLAGS= CC= @CC@ CFLAGS= @CFLAGS@ # misc stuff LINKER= @CC@ # LDFLAGS shall contain -lc if used with ld LDFLAGS= @LDFLAGS@ INSTALL= @INSTALL@ INSTALL_BIN= $(INSTALL) -m 755 INSTALL_DATA= $(INSTALL) -m 644 INSTALL_DIR= $(INSTALL) -d -m 755 INSTALL_MAN= $(INSTALL) -m 644 INSTALL_SBIN= $(INSTALL) -m 755 RM= rm RMFLAGS= -rf # specific directories PREFIX= @PREFIX@ BINDIR= @BINDIR@ SBINDIR= @SBINDIR@ DATADIR= @DATADIR@ SYSCONFDIR= @SYSCONFDIR@ .SUFFIXES: .o .s .c .C .cc .cxx .cpp # assembly suffix # we use CPP to be more portable .s.o: $(CPP) $< | sed '/^#/d' > tmp_asm.s $(AS) $(ASFLAGS) -o $@ tmp_asm.s $(RM) $(RMFLAGS) tmp_asm.s # C suffixes .c.o: $(CC) $(CFLAGS) -o $@ -c $< .C.o: $(CC) $(CFLAGS) -o $@ -c $< .cc.o: $(CC) $(CFLAGS) -o $@ -c $< # # object dependency lists # ___AUTOCONF_SRCS= ../autoconf.c ../autoconf.h ../cfgtool.h ../common.h \ ../compat/config.h ../compat/pmk_ctype.h \ ../compat/pmk_libgen.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../compat/pmk_sys_types.h ../compat/pmk_unistd.h \ ../dynarray.h ../errmsg.h ../functool.h \ ../hash.h ../hash_tools.h ../parse.h \ ../pathtools.h ../pmk.h ../pmk_obj.h \ ../premake.h ../prseng.h ___CFGTOOL_SRCS= ../cfgtool.c ../cfgtool.h ../common.h \ ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../dynarray.h ../errmsg.h ../hash.h ../parse.h \ ../pmk_obj.h ../premake.h ../prseng.h ___CODEBUILD_SRCS= ../codebuild.c ../codebuild.h ../common.h \ ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../dynarray.h ../errmsg.h ../hash.h ../pmk_obj.h \ ../premake.h ___COMMON_SRCS= ../common.c ../common.h ../compat/config.h \ ../compat/pmk_stdbool.h ../compat/pmk_stdio.h \ ../compat/pmk_string.h ../compat/pmk_unistd.h \ ../dynarray.h ../errmsg.h ../hash.h ../pmk_obj.h \ ../premake.h ___COMPAT_SRCS= ../compat.c ../compat.h ../compat/config.h \ ../compat/pmk_ctype.h ../compat/pmk_libgen.h \ ../compat/pmk_stdbool.h ../compat/pmk_stdio.h \ ../compat/pmk_string.h ../compat/pmk_sys_types.h \ ../compat/pmk_unistd.h ___DETECT_SRCS= ../common.h ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../compat/pmk_unistd.h ../detect.c ../detect.h \ ../dynarray.h ../errmsg.h ../hash.h ../parse.h \ ../pmk_obj.h ../premake.h ../prseng.h ___DETECT_CPU_SRCS= ../common.h ../compat/config.h \ ../compat/pmk_stdbool.h ../compat/pmk_stdio.h \ ../compat/pmk_string.h ../compat/pmk_sys_types.h \ ../cpu_arch_def.h ../detect_cpu.c \ ../detect_cpu.h ../detect_cpu_asm.h \ ../dynarray.h ../errmsg.h ../hash.h ../parse.h \ ../pmk_obj.h ../premake.h ../prseng.h ___DETECT_CPU_ASM_SRCS= ../cpu_arch_def.h ../detect_cpu_asm.s ___DYNARRAY_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../dynarray.c ../dynarray.h ___FUNC_SRCS= ../autoconf.h ../cfgtool.h ../codebuild.h ../common.h \ ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../compat/pmk_unistd.h ../detect.h ../dynarray.h \ ../errmsg.h ../func.c ../func.h ../functool.h ../hash.h \ ../hash_tools.h ../parse.h ../pkgconfig.h ../pmk.h \ ../pmk_obj.h ../premake.h ../prseng.h ___FUNCTOOL_SRCS= ../cfgtool.h ../common.h ../compat/config.h \ ../compat/pmk_ctype.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../compat/pmk_unistd.h ../dynarray.h ../errmsg.h \ ../functool.c ../functool.h ../hash.h \ ../hash_tools.h ../parse.h ../pmk.h ../pmk_obj.h \ ../premake.h ../prseng.h ___HASH_SRCS= ../common.h ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../dynarray.h ../errmsg.h ../hash.c ../hash.h \ ../pmk_obj.h ../premake.h ___HASH_TOOLS_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../dynarray.h ../errmsg.h ../hash.h \ ../hash_tools.c ../hash_tools.h ../pmk_obj.h \ ../premake.h ___PARSE_SRCS= ../common.h ../compat/config.h ../compat/pmk_ctype.h \ ../compat/pmk_stdbool.h ../compat/pmk_stdio.h \ ../compat/pmk_string.h ../dynarray.h ../errmsg.h \ ../hash.h ../parse.c ../parse.h ../pmk_obj.h \ ../premake.h ../prseng.h ___PARSE_LANG_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../parse_lang.c ../parse_lang.h ../prseng.h ___PATHTOOLS_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../pathtools.c ../pathtools.h ___PKGCONFIG_SRCS= ../common.h ../compat/config.h ../compat/pmk_ctype.h \ ../compat/pmk_stdbool.h ../compat/pmk_stdio.h \ ../compat/pmk_string.h ../compat/pmk_sys_types.h \ ../dynarray.h ../errmsg.h ../hash.h \ ../hash_tools.h ../parse.h ../pkgconfig.c \ ../pkgconfig.h ../pmk_obj.h ../premake.h \ ../prseng.h ___PMK_OBJ_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../dynarray.h ../hash.h ../pmk_obj.c \ ../pmk_obj.h ___PRSENG_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h ../prseng.c \ ../prseng.h COMP_TEST_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_string.h ../detect.h ../dynarray.h \ ../errmsg.h ../hash.h ../parse.h ../pmk_obj.h \ ../premake.h ../prseng.h comp_test.c COMPAT_TEST_SRCS= ../compat.h ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_string.h compat_test.c CPUID_TEST_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_sys_types.h ../cpu_arch_def.h \ ../detect_cpu.h ../detect_cpu_asm.h \ ../dynarray.h ../errmsg.h ../hash.h ../parse.h \ ../pmk_obj.h ../premake.h ../prseng.h \ cpuid_test.c DA_TEST_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_string.h ../dynarray.h da_test.c GEN_COMP_TEST_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_string.h ../detect.h ../dynarray.h \ ../errmsg.h ../hash.h ../parse.h ../pmk_obj.h \ ../premake.h ../prseng.h gen_comp_test.c HASH_TEST_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h ../hash.h \ hash_test.c MKVAR_TEST_SRCS= ../common.h ../compat/config.h ../compat/pmk_stdbool.h \ ../dynarray.h ../errmsg.h ../hash.h ../pmk_obj.h \ ../premake.h mkvar_test.c PARSER_TEST_SRCS= ../cfgtool.h ../common.h ../compat/config.h \ ../compat/pmk_stdbool.h ../dynarray.h \ ../errmsg.h ../func.h ../hash.h ../parse.h \ ../pmk_obj.h ../premake.h ../prseng.h \ parser_test.c PATH_TEST_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../pathtools.h path_test.c PKGCONFIG_TEST_SRCS= ../common.h ../compat/config.h \ ../compat/pmk_stdbool.h ../compat/pmk_stdio.h \ ../dynarray.h ../errmsg.h ../hash.h \ ../pkgconfig.h ../pmk_obj.h ../premake.h \ pkgconfig_test.c PLANG_TEST_SRCS= ../compat/config.h ../compat/pmk_stdbool.h \ ../compat/pmk_stdio.h ../compat/pmk_string.h \ ../parse_lang.h ../prseng.h plang_test.c # # target dependency lists # COMP_TEST_OBJS= ../common.o ../compat.o ../detect.o ../dynarray.o \ ../hash.o ../parse.o ../pmk_obj.o ../prseng.o \ comp_test.o COMPAT_TEST_OBJS= ../compat.o compat_test.o CPUID_TEST_OBJS= ../common.o ../compat.o ../detect_cpu.o \ ../detect_cpu_asm.o ../dynarray.o ../hash.o \ ../parse.o ../pmk_obj.o ../prseng.o cpuid_test.o DA_TEST_OBJS= ../compat.o ../dynarray.o da_test.o GEN_COMP_TEST_OBJS= ../common.o ../compat.o ../detect.o ../dynarray.o \ ../hash.o ../parse.o ../pmk_obj.o ../prseng.o \ gen_comp_test.o HASH_TEST_OBJS= ../common.o ../compat.o ../dynarray.o ../hash.o \ ../pmk_obj.o hash_test.o MKVAR_TEST_OBJS= ../common.o ../compat.o ../dynarray.o ../hash.o \ ../pmk_obj.o mkvar_test.o PARSER_TEST_OBJS= ../autoconf.o ../cfgtool.o ../codebuild.o ../common.o \ ../compat.o ../detect.o ../dynarray.o ../func.o \ ../functool.o ../hash.o ../hash_tools.o \ ../parse.o ../pathtools.o ../pkgconfig.o \ ../pmk.o ../pmk_obj.o ../prseng.o parser_test.o PATH_TEST_OBJS= ../compat.o ../pathtools.o path_test.o PKGCONFIG_TEST_OBJS= ../common.o ../compat.o ../dynarray.o ../hash.o \ ../hash_tools.o ../parse.o ../pkgconfig.o \ ../pmk_obj.o ../prseng.o pkgconfig_test.o PLANG_TEST_OBJS= ../compat.o ../parse_lang.o ../prseng.o plang_test.o # # target lists # ALL_TARGETS= comp_test compat_test cpuid_test da_test gen_comp_test \ hash_test mkvar_test parser_test path_test \ pkgconfig_test plang_test ALL_CLEAN_TARGETS= comp_test_clean compat_test_clean \ cpuid_test_clean da_test_clean \ gen_comp_test_clean hash_test_clean \ mkvar_test_clean parser_test_clean \ path_test_clean pkgconfig_test_clean \ plang_test_clean # by default we consider all binaries as non privileged BIN_FILES= $(ALL_TARGETS) # move privileged binaries here if needed SBIN_FILES= # # generic targets # all: $(ALL_TARGETS) clean: $(ALL_CLEAN_TARGETS) # # object rules # ../autoconf.o: $(___AUTOCONF_SRCS) ../cfgtool.o: $(___CFGTOOL_SRCS) ../codebuild.o: $(___CODEBUILD_SRCS) ../common.o: $(___COMMON_SRCS) ../compat.o: $(___COMPAT_SRCS) ../detect.o: $(___DETECT_SRCS) ../detect_cpu.o: $(___DETECT_CPU_SRCS) ../detect_cpu_asm.o: $(___DETECT_CPU_ASM_SRCS) ../dynarray.o: $(___DYNARRAY_SRCS) ../func.o: $(___FUNC_SRCS) ../functool.o: $(___FUNCTOOL_SRCS) ../hash.o: $(___HASH_SRCS) ../hash_tools.o: $(___HASH_TOOLS_SRCS) ../parse.o: $(___PARSE_SRCS) ../parse_lang.o: $(___PARSE_LANG_SRCS) ../pathtools.o: $(___PATHTOOLS_SRCS) ../pkgconfig.o: $(___PKGCONFIG_SRCS) ../pmk_obj.o: $(___PMK_OBJ_SRCS) ../prseng.o: $(___PRSENG_SRCS) comp_test.o: $(COMP_TEST_SRCS) compat_test.o: $(COMPAT_TEST_SRCS) cpuid_test.o: $(CPUID_TEST_SRCS) da_test.o: $(DA_TEST_SRCS) gen_comp_test.o: $(GEN_COMP_TEST_SRCS) hash_test.o: $(HASH_TEST_SRCS) mkvar_test.o: $(MKVAR_TEST_SRCS) parser_test.o: $(PARSER_TEST_SRCS) path_test.o: $(PATH_TEST_SRCS) pkgconfig_test.o: $(PKGCONFIG_TEST_SRCS) plang_test.o: $(PLANG_TEST_SRCS) # # target rules # comp_test: $(COMP_TEST_OBJS) $(CC) $(LDFLAGS) -o $@ $(COMP_TEST_OBJS) comp_test_clean: $(RM) $(RMFLAGS) $(COMP_TEST_OBJS) $(RM) $(RMFLAGS) comp_test compat_test: $(COMPAT_TEST_OBJS) $(CC) $(LDFLAGS) -o $@ $(COMPAT_TEST_OBJS) compat_test_clean: $(RM) $(RMFLAGS) $(COMPAT_TEST_OBJS) $(RM) $(RMFLAGS) compat_test cpuid_test: $(CPUID_TEST_OBJS) $(CC) $(LDFLAGS) -o $@ $(CPUID_TEST_OBJS) cpuid_test_clean: $(RM) $(RMFLAGS) $(CPUID_TEST_OBJS) $(RM) $(RMFLAGS) cpuid_test da_test: $(DA_TEST_OBJS) $(CC) $(LDFLAGS) -o $@ $(DA_TEST_OBJS) da_test_clean: $(RM) $(RMFLAGS) $(DA_TEST_OBJS) $(RM) $(RMFLAGS) da_test gen_comp_test: $(GEN_COMP_TEST_OBJS) $(CC) $(LDFLAGS) -o $@ $(GEN_COMP_TEST_OBJS) gen_comp_test_clean: $(RM) $(RMFLAGS) $(GEN_COMP_TEST_OBJS) $(RM) $(RMFLAGS) gen_comp_test hash_test: $(HASH_TEST_OBJS) $(CC) $(LDFLAGS) -o $@ $(HASH_TEST_OBJS) hash_test_clean: $(RM) $(RMFLAGS) $(HASH_TEST_OBJS) $(RM) $(RMFLAGS) hash_test mkvar_test: $(MKVAR_TEST_OBJS) $(CC) $(LDFLAGS) -o $@ $(MKVAR_TEST_OBJS) mkvar_test_clean: $(RM) $(RMFLAGS) $(MKVAR_TEST_OBJS) $(RM) $(RMFLAGS) mkvar_test parser_test: $(PARSER_TEST_OBJS) $(CC) $(LDFLAGS) -o $@ $(PARSER_TEST_OBJS) parser_test_clean: $(RM) $(RMFLAGS) $(PARSER_TEST_OBJS) $(RM) $(RMFLAGS) parser_test path_test: $(PATH_TEST_OBJS) $(CC) $(LDFLAGS) -o $@ $(PATH_TEST_OBJS) path_test_clean: $(RM) $(RMFLAGS) $(PATH_TEST_OBJS) $(RM) $(RMFLAGS) path_test pkgconfig_test: $(PKGCONFIG_TEST_OBJS) $(CC) $(LDFLAGS) -o $@ $(PKGCONFIG_TEST_OBJS) pkgconfig_test_clean: $(RM) $(RMFLAGS) $(PKGCONFIG_TEST_OBJS) $(RM) $(RMFLAGS) pkgconfig_test plang_test: $(PLANG_TEST_OBJS) $(CC) $(LDFLAGS) -o $@ $(PLANG_TEST_OBJS) plang_test_clean: $(RM) $(RMFLAGS) $(PLANG_TEST_OBJS) $(RM) $(RMFLAGS) plang_test pmk-0.10.4/tests/hash_test.c010064400017500000000000000054131030204577300145410ustar00mipswheel/* $Id: hash_test.c 1463 2005-08-21 09:40:11Z mipsator $ */ /* Public Domain license */ /* hash table test */ #include #include #include "../compat/pmk_stdio.h" #include "../compat/pmk_string.h" #include "../hash.h" #define TAB_SIZE 256 #define NBKEYS 256 hpair testab[] = { { "test1", "test value 1"}, { "test2", "test value 2"}, { "test3", "test value 3"} }; int main(void) { int n; char tstr[256], ttstr[256], *val; hkeys *phk = NULL; htable *hp; unsigned int i; printf("Testing init\n"); hp = hash_init(TAB_SIZE / 2); hash_set_grow(hp); printf("Adding test key\n"); hash_add(hp, "prefix", strdup("/usr/local")); printf("Testing key : "); val = hash_get(hp, "prefix"); if (val == NULL) { printf("not found\n"); } else { printf("found '%s'\n", val); } printf("Appending to the test key value\n"); hash_append(hp, "prefix", strdup("lll"), NULL); printf("Testing key : "); val = hash_get(hp, "prefix"); if (val == NULL) { printf("not found\n"); } else { printf("found '%s'\n", val); } printf("Appending to the test key value with a separator\n"); hash_append(hp, "prefix", strdup("/opt"), ","); printf("Testing key : "); val = hash_get(hp, "prefix"); if (val == NULL) { printf("not found\n"); } else { printf("found '%s'\n", val); } printf("Removing test key\n"); hash_delete(hp, "prefix"); printf("Testing key : "); if (hash_get(hp, "prefix") == NULL) { printf("not found\n"); } else { printf("found\n"); } n = sizeof(testab) / sizeof(hpair); printf("Adding %d test keys\n", n); hash_add_array(hp, testab, n); phk = hash_keys(hp); printf("Displaying %d keys :\n", n); for(i = 0 ; i < phk->nkey ; i++) { printf("\t%s => %s\n", (char *) phk->keys[i], (char *) hash_get(hp, phk->keys[i])); } printf("Removing 3 test keys\n"); hash_delete(hp, "test1"); hash_delete(hp, "test2"); hash_delete(hp, "test3"); printf("Adding %d random keys\n", NBKEYS); for(i = 0 ; i < NBKEYS ; i++) { snprintf(tstr, sizeof(tstr), "XXXXXXXXXX"); /* mktemp() is only used to generate random values */ if (mktemp(tstr) != NULL) { snprintf(ttstr, sizeof(ttstr), "value.%s", tstr); n = hash_add(hp, tstr, strdup(ttstr)); printf("(%3d) ", i); switch (n) { case HASH_ADD_FAIL: printf("Failed add for key %s\n", tstr); break; case HASH_ADD_OKAY: printf("Added for key %s\n", tstr); break; case HASH_ADD_COLL: printf("Collision for key %s\n", tstr); break; case HASH_ADD_UPDT: printf("Updated key %s\n", tstr); break; default: printf("Unknown return value %s\n", tstr); break; } } else { printf("Random value failed\n"); } } printf("Testing destroy\n"); n = hash_destroy(hp); printf("Removed %d key(s)\n", n); return(0); } pmk-0.10.4/tests/cpuid_test.c010064400017500000000000000021071027375450500147260ustar00mipswheel/* $Id: cpuid_test.c 1442 2005-08-02 20:36:21Z mipsator $ */ /* Public Domain */ /* CPU ID detection test */ #include #include "../compat/pmk_sys_types.h" #include #include #include "../detect_cpu.h" #include "../detect_cpu_asm.h" #include "../hash.h" #include "../parse.h" #define PMKCPU_DATA "../data/pmkcpu.dat" int main(void) { char *pstr; hkeys *phk; htable *pht; prsdata *pdata; struct utsname utsname; unsigned int i; if (uname(&utsname) == -1) { printf("uname failed.\n"); exit(EXIT_FAILURE); } pdata = parse_cpu_data(PMKCPU_DATA); if (pdata == NULL) { /* XXX msg ? */ exit(EXIT_FAILURE); } pstr = check_cpu_arch(utsname.machine, pdata); /* XXX check ? */ printf("arch = '%s'\n", pstr); pht = arch_wrapper(pdata, pstr); if (pht != NULL) { phk = hash_keys(pht); if (phk != NULL) { for(i = 0 ; i < phk->nkey ; i++) { pstr = hash_get(pht, phk->keys[i]); printf("%s = '%s'\n", phk->keys[i], pstr); } hash_free_hkeys(phk); } hash_destroy(pht); } prsdata_destroy(pdata); return(0); } pmk-0.10.4/tests/da_test.c010064400017500000000000000026341027375450500142130ustar00mipswheel/* $Id: da_test.c 1442 2005-08-02 20:36:21Z mipsator $ */ /* Public Domain */ /* dynamic array tests */ #include #include #include "../compat/pmk_string.h" #include "../dynarray.h" char *tval[10] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; int main(void) { char *p; dynary *da; int i; printf("Init dynary.\n"); da = da_init(); printf("\nAdding 9 values :\n"); for (i = 0 ; i < 10 ; i++) { printf("\tAdd value '%s' ", tval[i]); da_push(da, strdup(tval[i])); printf("(%d)\n", da_size(da)); } printf("\nTesting values :\n"); for (i = 9 ; i >= 0 ; i--) { printf("\tda[%d] = %s\n", i, (char *)da_idx(da, i)); } printf("\nRemoving values using da_pop :\n"); do { p = da_pop(da); if (p != NULL) { printf("\tPoped '%s' (%d)\n", p, da_size(da)); free(p); } } while (p != NULL); printf("\nAdding 9 values :\n"); for (i = 0 ; i < 10 ; i++) { printf("\tAdd value '%s' ", tval[i]); da_push(da, strdup(tval[i])); printf("(%d)\n", da_size(da)); } printf("\nTesting values :\n"); for (i = 9 ; i >= 0 ; i--) { printf("\tda[%d] = %s\n", i, (char *)da_idx(da, i)); } printf("\nRemoving values using da_shift :\n"); do { p = da_shift(da); if (p != NULL) { printf("\tShifted '%s' (%d)\n", p, da_size(da)); free(p); } } while (p!= NULL); printf("\nCleaning.\n"); da_destroy(da); return(0); } pmk-0.10.4/tests/parser_test.c010064400017500000000000000037211030204577300151120ustar00mipswheel/* $Id: parser_test.c 1463 2005-08-21 09:40:11Z mipsator $ */ /* Public Domain */ /* parser engine test */ #include #include #include #include "../common.h" #include "../func.h" #include "../parse.h" extern prskw kw_pmkfile[]; extern size_t nbkwpf; bool process_fake(htable *, prsopt *); void usage(void); /* process option line of configuration file pht : storage hash table popt : option structure to record return : boolean */ bool process_fake(htable *pht, prsopt *popt) { return(true); } /* usage */ void usage(void) { fprintf(stderr, "usage: parser_test [-ch] [file path]\n"); } /* main loop */ int main(int argc, char *argv[]) { FILE *fd; bool loop = true, parse_cfg = false, rval; char chr; prsdata *pdata; htable *pht; while (loop == true) { chr = getopt(argc, argv, "ch"); if (chr == -1) { loop = false; } else { switch (chr) { case 'c' : /* parse a config file */ parse_cfg = true; break; case 'h' : case '?' : default : usage(); exit(EXIT_FAILURE); /* NOTREACHED */ } } } argc = argc - optind; argv = argv + optind; if (argc != 1) { printf("filename not provided.\n"); exit(EXIT_FAILURE); } pdata = prsdata_init(); fd = fopen(argv[0], "r"); if (fd == NULL) { errorf("cannot open '%s'.", argv[0]); return(false); } if (parse_cfg == false) { rval = parse_pmkfile(fd, pdata, kw_pmkfile, nbkwpf); printf("cleaning parsing tree ... "); prsdata_destroy(pdata); printf("ok\n"); } else { pht = hash_init_adv(1024, NULL, (void (*)(void *)) prsopt_destroy, NULL); if (pht == NULL) { printf("cannot create hash table.\n"); exit(EXIT_FAILURE); } rval = parse_pmkconf(fd, pht, PRS_PMKCONF_SEP, process_fake); printf("cleaning hash table ... "); hash_destroy(pht); printf("ok\n"); } fclose(fd); if (rval == true) { printf("Parsing succeeded.\n"); } else { printf("Parsing failed.\n"); } return(0); } pmk-0.10.4/tests/path_test.c010064400017500000000000000024521027375450500145610ustar00mipswheel/* $Id: path_test.c 1442 2005-08-02 20:36:21Z mipsator $ */ /* Public Domain */ /* path tools test */ #include #include #include "../compat/pmk_stdbool.h" #include "../pathtools.h" char *chk_paths[] = { "/usr/./local/bin/../lib//", "/usr/../../local", "/usr////lib/..", "./youpi/youpla/../paf", "blah/../odidonk", "/var/.", "../youpla/youpi/", "../youpla/../youpi", "/../", "/..//" }, *rel_paths[][2] = { {"/home/me/tmp/src/youpi", "/home/me/tmp/build/"}, {"/usr/local/lib/", "/var/named"}, {"/","/etc/ppp"}, {"/usr/local", "/usr/local"} }; int main(void) { char buf[MAXPATHLEN]; unsigned int i, s; s = (unsigned int) (sizeof(chk_paths) / sizeof(char *)); printf("* Checking paths :\n"); for (i = 0 ; i < s ; i++) { printf("Source path = '%s'\n", chk_paths[i]); if (chkpath(chk_paths[i], buf) == false) { printf("\tFailed (%s)\n", buf); } else { printf("\tOk => '%s'\n", buf); } printf("\n"); } s = (unsigned int) (sizeof(rel_paths) / (sizeof(char *) * 2)); printf("* Test relative paths :\n"); for (i = 0 ; i < s ; i++) { printf("\tfrom = '%s', to = '%s'\n", rel_paths[i][0], rel_paths[i][1]); relpath(rel_paths[i][0], rel_paths[i][1], buf); printf("\trelpath = '%s'\n\n", buf); } return(0); } pmk-0.10.4/tests/comp_test.c010064400017500000000000000020121027375450500145530ustar00mipswheel/* $Id: comp_test.c 1442 2005-08-02 20:36:21Z mipsator $ */ /* Public Domain */ /* compiler detection test */ /*#define PRS_DEBUG 1*/ #include #include #include "../detect.h" int main(int argc, char *argv[]) { char *cc; comp_cell *pcell; comp_data *cdata; comp_info cinfo; if (argc != 2) { printf("you must provide a compiler name\n"); exit(EXIT_FAILURE); } cc = argv[1]; printf("Using compiler : '%s'\n", cc); printf("Parsing compiler data.\n"); cdata = parse_comp_file("../data/pmkcomp.dat"); printf("Detecting compiler ...\n"); if (detect_compiler(cc, "/dev/null", cdata, &cinfo) == false) { compdata_destroy(cdata); printf("Failed"); exit(EXIT_FAILURE); } pcell = comp_get(cdata, cinfo.c_id); if (pcell == NULL) { compdata_destroy(cdata); printf("Failed.\n"); exit(EXIT_FAILURE); } else { printf("Detected compiler : '%s'\n", comp_get_descr(cdata, cinfo.c_id)); printf("Compiler version : '%s'\n", cinfo.version); } compdata_destroy(cdata); return(0); } pmk-0.10.4/detect.h010064400017500000000000000156611052021275100126720ustar00mipswheel/* $Id: detect.h 1921 2006-10-26 20:09:13Z coudercd $ */ /* * Copyright (c) 2003-2006 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. * */ #ifndef _DETECT_H_ #define _DETECT_H_ #include "compat/pmk_string.h" #include "parse.h" #include "premake.h" #ifndef DATADIR /* for lint */ #define DATADIR "/DATADIR_not_defined" #endif /************* * constants * ***********************************************************************/ #define PMKCOMP_DATA DATADIR "/pmkcomp.dat" #define PCC_TOK_ADDC 1 #define PCC_TOK_ADDS 2 /* max number of compilers hash table */ #define MAX_COMP 32 /* max number of OSes in hash table */ #define MAX_OS 128 #define CC_TFILE_EXT ".c" #define CC_TEST_FILE TMPDIR "/cc_testXXXXXXXX" CC_TFILE_EXT #define CC_TEST_BIN TMPDIR "/cc_test_bin" #define CC_TEST_FORMAT "%s -o %s %s >%s 2>&1" #define DEF_VERSION "#define CC_V\t%s" #define DEF_NOVERSION "#undef CC_V" #define SL_LDFLAG_VARNAME "SLLDFLAGS" #define SL_SYS_LABEL "SLSYSNAME" /**************** * keyword data * ***********************************************************************/ /* ADD_COMPILER keyword options */ #define CC_KW_ID "ID" #define CC_KW_DESCR "DESCR" #define CC_KW_MACRO "MACRO" #define CC_KW_VERSION "VERSION" #define CC_KW_SLCFLAGS "SLCFLAGS" #define CC_KW_SLLDFLAGS "SLLDFLAGS" /* ADD_SYSTEM keyword options */ #define SYS_KW_NAME "NAME" #define SYS_KW_VERSION "LIB_VERSION" #define SYS_KW_SH_EXT "SH_EXT" #define SYS_KW_SH_NONE "SH_LIBNAME_NONE" #define SYS_KW_SH_VERS "SH_LIBNAME_VERS" #define SYS_KW_ST_EXT "ST_EXT" #define SYS_KW_ST_NONE "ST_LIBNAME_NONE" #define SYS_KW_ST_VERS "ST_LIBNAME_VERS" /* reserved variable name */ #define LIB_KW_MAJ "LIB_MAJOR" #define LIB_KW_MIN "LIB_MINOR" #define LIB_KW_NAME "LIB_NAME" #define LIB_KW_SH_VAR "SH_VAR_NAME" #define LIB_KW_SH_NONE SYS_KW_SH_NONE #define LIB_KW_SH_VERS SYS_KW_SH_VERS #define LIB_KW_ST_VAR "ST_VAR_NAME" #define LIB_KW_ST_NONE SYS_KW_ST_NONE #define LIB_KW_ST_VERS SYS_KW_ST_VERS /************************ * code of various tests * ***********************************************************************/ /* header of test code */ #define COMP_TEST_HEADER \ "#include \n\n" /* descr macro c_id ver_macro */ #define COMP_TEST_FORMAT \ "/* %s */\n" \ "#ifdef %s\n" \ "#define CC_ID\t\"%s\"\n" \ "%s\n" \ "#endif\n" \ "\n" /* footer of test code */ #define COMP_TEST_FOOTER \ "/* unknown compiler found */\n" \ "#ifndef CC_ID\n" \ "#define CC_ID\t\"unknown\"\n" \ "#endif\n" \ "\n" \ "int main() {\n" \ "/* compiler id */\n" \ "\tprintf(\"%%s\\n\", CC_ID);\n" \ "/* compiler version */\n" \ "#ifdef CC_V\n" \ "\tprintf(\"%%d\\n\", CC_V);\n" \ "#else\n" \ "\tprintf(\"unknown\\n\");\n" \ "#endif\n" \ "\treturn(0);\n" \ "}\n" /*************************** * compiler data structures * ***********************************************************************/ /* compiler cell */ typedef struct { char *c_id, *descr, *c_macro, *v_macro, *slcflags, *slldflags; } comp_prscell_t; typedef struct { char *c_id, *version; } comp_info; typedef struct { htable *cht, /* compiler data hash table */ *sht; /* system data hash table */ } comp_data; /********************* * %TYPE comp_parse_t * *********************************************************************** * %DESCR compiler data storage for detection ***********************************************************************/ typedef struct { htable *cht, /* %FIELD cht: compiler cell data hash table */ *sht; /* %FIELD sht: system cell data hash table */ } comp_parse_t; /******************* * %TYPE compiler_t * *********************************************************************** * %DESCR compiler profile containing data for shared lib support ***********************************************************************/ typedef struct { char *c_id, /* %FIELD c_id: compiler identifier */ *descr, /* %FIELD descr: compiler description */ *c_macro, /* %FIELD c_macro: XXX */ *v_macro, /* %FIELD v_macro: XXX */ *slcflags, /* %FIELD slcflags: shared lib compiler flags */ *slldflags, /* %FIELD slldflags: shared lib linker flags */ *version; /* %FIELD version: detected version of the compiler */ int lang; /* %FIELD lang: language identifier */ } compiler_t; /******************** * %TYPE comp_data_t * *********************************************************************** * %DESCR parsed compilers data ***********************************************************************/ typedef struct { compiler_t *data; /* %FIELD data: array of data cells for detected compiler */ size_t sz; /* %FIELD sz: number of data cells */ } comp_data_t; /********************* * SECTION prototypes * ***********************************************************************/ bool init_compiler_data(comp_data_t *, size_t); void clean_compiler_cell(compiler_t *); void clean_compiler_data(comp_data_t *); void compcell_destroy(comp_prscell_t *); comp_parse_t *init_comp_parse(void); void destroy_comp_parse(comp_parse_t *); bool add_compiler(comp_parse_t *, htable *); bool add_system(comp_parse_t *, htable *, char *); comp_parse_t *parse_comp_file(char *, char *); bool gen_test_file(comp_parse_t *, char *, size_t); bool comp_identify(char *, char *, compiler_t *, comp_parse_t *); bool comp_detect(char *, char *, compiler_t *, comp_parse_t *, char *); #endif /* _DETECT_H_ */ /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/pmksetup.h010064400017500000000000000111251024136140200132570ustar00mipswheel/* $Id: pmksetup.h 1410 2005-05-14 11:37:38Z mipsator $ */ /* * Copyright (c) 2003-2004 Xavier Santolaria * 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. * */ #ifndef _PMKSETUP_H_ #define _PMKSETUP_H_ #include #include "hash.h" #include "premake.h" /************* * constants * ***********************************************************************/ /* pmksetup specific version */ #define PREMAKE_SUBVER_PMKSETUP "9" #define PREMAKE_CONFIG_TMP CONFDIR "/pmk.conf_XXXXXXXX" #define PREMAKE_CONFIG_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH #ifndef DATADIR /* for lint */ #define DATADIR "/DATADIR_not_defined" #endif /* set default priviledged user */ #ifndef PRIVSEP_USER #define PRIVSEP_USER "nobody" #endif #define PMKCPU_DATA DATADIR "/pmkcpu.dat" /* define printf format in pmk.conf */ #define PMKSTP_WRITE_FORMAT "%s %c \"%s\"\n" #define PMKSTP_REC_REMV 'r' #define PMKSTP_REC_UPDT 'u' /* buffer size in the copy_config() function */ #define MAX_LINE_BUF MAX_LINE_LEN #define MAX_CONF_OPT 256 /* XXX temp maximum hash entries */ #define ECHO_CMD "echo \"one\\c\"; echo -n two; echo three" #define ECHO_EMPTY "" #define ECHO_N "-n" #define ECHO_C "\\c" #define ECHO_NL "\\n" #define ECHO_HT "\\t" #define PMKSTP_OPT_STR "hr:u:vV" /* "a:hr:u:vV" */ #define EMSG_PRIV_FMT "Failed to change privilege (%s)" /* compiler list */ static char *c_compilers[][2] = { {"c99", PMKCONF_BIN_C99}, {"c89", PMKCONF_BIN_C89} /* {"cc", PMKCONF_BIN_CC}*/ }; size_t nb_c_compilers = sizeof(c_compilers) / (sizeof(char *) * 2); /* * Look for location of some predefined binaries. * Be sure to update this list in premake.h as well. */ static char *binaries[][2] = { {"ar", PMKCONF_BIN_AR}, {"as", PMKCONF_BIN_AS}, {"awk", PMKCONF_BIN_AWK}, {"c++", PMKCONF_BIN_CXX}, {"cat", PMKCONF_BIN_CAT}, {"cpp", PMKCONF_BIN_CPP}, {"echo", PMKCONF_BIN_ECHO}, {"egrep", PMKCONF_BIN_EGREP}, {"grep", PMKCONF_BIN_GREP}, {"id", PMKCONF_BIN_ID}, {"install", PMKCONF_BIN_INSTALL}, {"lex", PMKCONF_BIN_LEX}, {"ln", PMKCONF_BIN_LN}, {"pkg-config", PMKCONF_BIN_PKGCONFIG}, {"ranlib", PMKCONF_BIN_RANLIB}, {"sh", PMKCONF_BIN_SH}, {"strip", PMKCONF_BIN_STRIP}, {"sudo", PMKCONF_BIN_SUDO}, {"tar", PMKCONF_BIN_TAR}, {"yacc", PMKCONF_BIN_YACC} }; #define MAXBINS sizeof(binaries) / sizeof(char *) / 2 /************************ * functions prototypes * ***********************************************************************/ bool record_data(htable *, char *, char, char *); bool gather_data(htable *); bool check_opt(htable *, prsopt *); bool open_tmp_config(void); bool close_tmp_config(void); bool get_env_vars(htable *); bool get_binaries(htable *); bool predef_vars(htable *); bool check_echo(htable *); bool check_libpath(htable *); bool get_cpu_data(htable *); bool dir_exists(const char *); bool byte_order_check(htable *); bool write_new_data(htable *); void verbosef(const char *, ...); void usage(void); bool detection_loop(int, char *[]); void child_loop(uid_t, gid_t, int, char *[]); void parent_loop(pid_t); #endif /* _PMKSETUP_H_ */ pmk-0.10.4/detect_cpu_asm.h010064400017500000000000000054161027375246100144120ustar00mipswheel/* $Id: detect_cpu_asm.h 1435 2005-08-02 20:18:57Z mipsator $ */ /* * Copyright (c) 2004-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. * */ #ifndef _DETECT_CPU_ASM_H_ #define _DETECT_CPU_ASM_H_ #include #include "cpu_arch_def.h" /******************** * x86 architecture * ***********************************************************************/ #if defined(ARCH_X86_32) || defined(ARCH_X86_64) /* declare X86 assembly variables */ extern uint32_t x86_cpu_reg_eax; extern uint32_t x86_cpu_reg_ebx; extern uint32_t x86_cpu_reg_ecx; extern uint32_t x86_cpu_reg_edx; /* declare X86 assembly functions */ extern uint32_t x86_check_cpuid_flag(void); extern void x86_exec_cpuid(uint32_t); /* cpuid function */ #endif /* ARCH_X86_32 || ARCH_X86_64 */ /********************** * alpha architecture * ***********************************************************************/ #if defined(ARCH_ALPHA) uint64_t alpha_exec_implver(void); uint64_t alpha_exec_amask(void); #endif /* ARCH_ALPHA */ /********************* * ia64 architecture * ***********************************************************************/ #if defined(ARCH_IA64) uint64_t ia64_get_cpuid_register(uint64_t); /* cpuid register */ #endif /* ARCH_IA64 */ #endif /* _DETECT_CPU_ASM_H_ */ pmk-0.10.4/autoconf.c010064400017500000000000000357771033545327000132540ustar00mipswheel/* $Id: autoconf.c 1506 2005-11-12 20:55:20Z mipsator $ */ /* * 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. * */ #include #include #include "compat/pmk_sys_types.h" #include "compat/pmk_ctype.h" #include "compat/pmk_libgen.h" #include "compat/pmk_string.h" #include "compat/pmk_stdio.h" #include "compat/pmk_unistd.h" #include "autoconf.h" #include "common.h" #include "functool.h" #include "pathtools.h" #include "premake.h" #include "tags.h" /*#define AC_DEBUG 1*/ /********************* * ac_parse_config() * *********************************************************************** DESCR parse a config file assuming compatibility with autoconf IN ht : def table fpath : file path OUT boolean ***********************************************************************/ bool ac_parse_config(pmkdata *pgd) { FILE *fp_in, *fp_out; bool rval = true; char line[TMP_BUF_LEN], buf[TMP_BUF_LEN], fsrc[MAXPATHLEN], fname[MAXPATHLEN], ftmp[MAXPATHLEN], *fpath, *pstr, *defname; htable *ht; int i, s, fe; ht = pgd->htab; fpath = pgd->ac_file; /* compute full path */ if (abspath(pgd->srcdir, fpath, fsrc) == false) { errorf("failed to compute absolute path for '%s' (srcdir).", fpath); return(false); } #ifdef AC_DEBUG debugf("computed fsrc = '%s'", fsrc); #endif if (abspath(pgd->basedir, fpath, fname) == false) { errorf("failed to compute absolute path for '%s' (basedir).", fpath); return(false); } #ifdef AC_DEBUG debugf("computed fname = '%s'", fname); #endif fp_in = fopen(fsrc, "r"); if (fp_in == NULL) { errorf("failed to open '%s'.", fsrc); return(false); } /* open temporary file ? */ fp_out = tmp_open(PMK_TMP_AC_CONF, "w", ftmp, sizeof(ftmp)); if (fp_out == NULL) { errorf("failed to open '%s'.", ftmp); fclose(fp_in); return(false); } while (get_line(fp_in, line, sizeof(line)) == true) { /* look for '#define' */ pstr = strstr(line, "#define"); if (pstr == NULL) { /* else try to find '#undef' */ pstr = strstr(line, "#undef"); if (pstr != NULL) { /* jump after "#undef" */ pstr = pstr + sizeof("#undef"); } } else { /* jump after "#define" */ pstr = pstr + sizeof("#define"); } if (pstr != NULL) { /* look for the definition name */ while (isspace(*pstr) != 0) { /* ignore spaces */ pstr++; } s = sizeof(line); i = 0; while (((*pstr == '_') || (isalpha(*pstr) != 0)) && (i < s)) { buf[i] = *pstr; pstr++; i++; } buf[i] = CHAR_EOS; /* generate define name (DEF__*) */ defname = gen_basic_tag_def(buf); if (defname == NULL) { errorf("unable to build define name for '%s'", buf); fclose(fp_in); fclose(fp_out); return(false); } #ifdef AC_DEBUG debugf("built define name = '%s'", defname); #endif /* get the defined value */ pstr = (char *) hash_get(ht, defname); if (pstr != NULL) { fprintf(fp_out, "%s /* pmk parsed */\n", pstr); #ifdef AC_DEBUG debugf("define value for %s = '%s'", buf, pstr); #endif } else { pstr = (char *) hash_get(ht, buf); if (pstr != NULL) { fprintf(fp_out, "#define %s %s /* pmk parsed */\n", buf, pstr); #ifdef AC_DEBUG debugf("define value for %s = '%s'", buf, pstr); #endif } else { fprintf(fp_out, "#undef %s\t/* pmk parsed */\n", buf); #ifdef AC_DEBUG debugf("unset define for '%s'", buf); #endif } } } else { /* write line as is */ fprintf(fp_out, "%s\n", line); } } fe = feof(fp_in); fclose(fp_in); fclose(fp_out); if (fe == 0) { if (unlink(ftmp) == -1) errorf(ERRMSG_REMOVE_TMP, ftmp, strerror(errno)); return(false); } /* Try to erase original file if it exists. If build directory is different than source directory then there is nothing to delete (so we don't check the result). */ unlink(fname); /* copy new one */ rval = fcopy(ftmp, fname, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (unlink(ftmp) == -1) { errorf(ERRMSG_REMOVE_TMP, ftmp, strerror(errno)); return(false); } pmk_log("Saved '%s'.\n", fname); return(rval); } /************************ * ac_process_dyn_var() * *********************************************************************** DESCR process special variables IN pht : storage table pgd : global data template : target file OUT boolean ***********************************************************************/ bool ac_process_dyn_var(pmkdata *pgd, char *template) { char *pstr; htable *pht; /* should process variables like following (if i believe autoconf manual) : - srcdir : the relative path to the directory that contains the source code for that `Makefile'. - abs_srcdir : absolute path of srcdir. - top_srcdir : the relative path to the top-level source code directory for the package. In the top-level directory, this is the same as srcdir. - abs_top_srcdir : absolute path of top_srcdir. - builddir : rigorously equal to ".", added for symmetry only. - abs_builddir : absolute path of builddir. - top_builddir : the relative path to the top-level of the current build tree. In the top-level directory, this is the same as builddir. - abs_top_builddir : absolute path of top_builddir. The pmk directories should be equivalent to that. */ pht = pgd->htab; /* init builddir */ pstr = hash_get(pht, PMK_DIR_BLD_ROOT_ABS); if (hash_update_dup(pht, "abs_top_builddir", pstr) == HASH_ADD_FAIL) return(false); /* set abs_builddir */ pstr = hash_get(pht, PMK_DIR_BLD_ABS); if (hash_update_dup(pht, "abs_builddir", pstr) == HASH_ADD_FAIL) return(false); /* compute top_builddir */ pstr = hash_get(pht, PMK_DIR_BLD_ROOT_REL); if (hash_update_dup(pht, "top_builddir", pstr) == HASH_ADD_FAIL) return(false); /* Mr GNU said : rigorously equal to ".". So i did :) */ pstr = hash_get(pht, PMK_DIR_BLD_REL); if (hash_update_dup(pht, "builddir", pstr) == HASH_ADD_FAIL) return(false); /* set absolute srcdir */ pstr = hash_get(pht, PMK_DIR_SRC_ROOT_ABS); if (hash_update_dup(pht, "abs_top_srcdir", pstr) == HASH_ADD_FAIL) return(false); /* compute top_srcdir */ pstr = hash_get(pht, PMK_DIR_SRC_ROOT_REL); if (hash_update_dup(pht, "top_srcdir", pstr) == HASH_ADD_FAIL) return(false); /* absolute path of template */ pstr = hash_get(pht, PMK_DIR_SRC_ABS); if (hash_update_dup(pht, "abs_srcdir", pstr) == HASH_ADD_FAIL) return(false); /* relative path to template */ pstr = hash_get(pht, PMK_DIR_SRC_REL); if (hash_update_dup(pht, "srcdir", pstr) == HASH_ADD_FAIL) return(false); /* all operations succeeded */ return(true); } /******************** * ac_clean_dyn_var * *********************************************************************** DESCR clean dynamic variables IN pht : storage table OUT NONE ***********************************************************************/ void ac_clean_dyn_var(htable *pht) { hash_delete(pht, "srcdir"); hash_delete(pht, "abs_srcdir"); hash_delete(pht, "top_srcdir"); hash_delete(pht, "abs_top_srcdir"); hash_delete(pht, "builddir"); hash_delete(pht, "abs_builddir"); hash_delete(pht, "top_builddir"); hash_delete(pht, "abs_top_builddir"); } /********************** * ac_set_variables() * *********************************************************************** DESCR set autoconf specific variables IN pht : storage table OUT boolean ***********************************************************************/ bool ac_set_variables(htable *pht) { char buf[TMP_BUF_LEN], *pstr; /* path variables */ pstr = (char *) hash_get(pht, "PREFIX"); if (hash_update_dup(pht, "prefix", pstr) == HASH_ADD_FAIL) return(false); pstr = (char *) hash_get(pht, "SYSCONFDIR"); if (hash_update_dup(pht, "sysconfdir", pstr) == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "exec_prefix", "${prefix}") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "bindir", "${exec_prefix}/bin") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "sbindir", "${exec_prefix}/sbin") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "libexecdir", "${exec_prefix}/libexec") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "libdir", "${exec_prefix}/lib") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "datadir", "${prefix}/share") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "includedir", "${prefix}/include") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "mandir", "${prefix}/man") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "infodir", "${prefix}/info") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "sharedstatedir", "${prefix}/com") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "localstatedir", "${prefix}/var") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "oldincludedir", "/usr/include") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "INSTALL_DATA", "${INSTALL} -m 644") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "INSTALL_PROGRAM", "${INSTALL}") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "INSTALL_SCRIPT", "${INSTALL}") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "INSTALL_STRIP_PROGRAM", "${SHELL} $(install_sh) -c -s") == HASH_ADD_FAIL) return(false); /* well i dunno if the following really needs to be full compatible with autoconf */ pstr = (char *) hash_get(pht, "OS_ARCH"); if (hash_update_dup(pht, "host_cpu", pstr) == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "build_cpu", pstr) == HASH_ADD_FAIL) return(false); /* XXX ouargl cross compiling ... */ if (hash_update_dup(pht, "target_cpu", pstr) == HASH_ADD_FAIL) return(false); /* XXX ouargl cross compiling ... */ pstr = (char *) hash_get(pht, "OS_NAME"); strlcpy(buf, pstr, sizeof(buf)); /* no need to check here */ pstr = (char *) hash_get(pht, "OS_VERSION"); if (strlcat_b(buf, pstr, sizeof(buf)) ==false) return(false); if (hash_update_dup(pht, "host_os", buf) == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "build_os", buf) == HASH_ADD_FAIL) return(false); /* XXX ouargl cross compiling ... */ if (hash_update_dup(pht, "target_os", buf) == HASH_ADD_FAIL) return(false); /* XXX ouargl cross compiling ... */ if (hash_update_dup(pht, "host_vendor", "vendorisnotset") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "build_vendor", "vendorisnotset") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "target_vendor", "vendorisnotset") == HASH_ADD_FAIL) return(false); pstr = (char *) hash_get(pht, "host_cpu"); strlcpy(buf, pstr, sizeof(buf)); /* no need to check here */ strlcat(buf, "-", sizeof(buf)); /* no need to check here */ pstr = (char *) hash_get(pht, "host_vendor"); strlcat(buf, pstr, sizeof(buf)); /* no need to check here */ strlcat(buf, "-", sizeof(buf)); /* no need to check here */ pstr = (char *) hash_get(pht, "host_os"); if (strlcat_b(buf, pstr, sizeof(buf)) == false) return(false); /* overflow */ if (hash_update_dup(pht, "host", buf) == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "build", buf) == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "target", buf) == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "host_alias", "") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "build_alias", "") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "target_alias", "") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "build_triplet", "") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "host_triplet", "") == HASH_ADD_FAIL) return(false); if (hash_update_dup(pht, "target_triplet", "") == HASH_ADD_FAIL) return(false); /* use values from pmk.conf */ pstr = (char *) hash_get(pht, PMKCONF_AC_ECHO_C); if (pstr != NULL) { if (hash_update_dup(pht, AC_ECHO_C, pstr) == HASH_ADD_FAIL) { errorf("failed to set '%s'.", AC_ECHO_C); return(false); } } pstr = (char *) hash_get(pht, PMKCONF_AC_ECHO_N); if (pstr != NULL) { if (hash_update_dup(pht, AC_ECHO_N, pstr) == HASH_ADD_FAIL) { errorf("failed to set '%s'.", AC_ECHO_N); return(false); } } pstr = (char *) hash_get(pht, PMKCONF_AC_ECHO_T); if (pstr != NULL) { if (hash_update_dup(pht, AC_ECHO_T, pstr) == HASH_ADD_FAIL) { errorf("failed to set '%s'.", AC_ECHO_T); return(false); } } /* XXX TODO verify the following */ /*hash_add(pht, "SET_MAKE", strdup("")); */ /*hash_add(pht, "ACLOCAL", strdup("echo 'PMK: set as useless'")); */ /*hash_add(pht, "AUTOCONF", strdup("echo 'PMK: set as useless'")); */ /*hash_add(pht, "AUTOHEADER", strdup("echo 'PMK: set as useless'"));*/ /*hash_add(pht, "AUTOMAKE", strdup("echo 'PMK: set as useless'")); */ /*hash_add(pht, "MAKEINFO", strdup("echo 'PMK: set as useless'")); */ /*hash_add(pht, "EXEEXT", strdup("")); |+ cygwin shit ! +| */ /*hash_add(pht, "DEPDIR", strdup(".deps")); */ /*hash_add(pht, "CCDEPMODE", strdup("")); */ /*hash_add(pht, "LIBOBJS", strdup("")); */ /*hash_add(pht, "LTLIBOBJS", strdup("")); */ /*hash_add(pht, "PATH_SEPARATOR", strdup(":")); |+ default shell is sh +|*/ if (hash_update_dup(pht, "install_sh", "pmkinstall") == HASH_ADD_FAIL) return(false); /* provide our own */ if (hash_update_dup(pht, "program_transform_name", "s,x,x,") == HASH_ADD_FAIL) return(false); /* byte order */ pstr = (char *) hash_get(pht, PMKCONF_HW_BYTEORDER); if (strncmp(pstr, HW_ENDIAN_BIG, sizeof(pstr)) == 0) { if (hash_update_dup(pht, "WORDS_BIGENDIAN", "1") == HASH_ADD_FAIL) return(false); } return(true); } pmk-0.10.4/pmkinstall.h010064400017500000000000000053331020764330100135740ustar00mipswheel/* $Id: pmkinstall.h 1381 2005-02-25 15:39:45Z mipsator $ */ /* * Copyright (c) 2003 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. * */ #ifndef _PMKINSTALL_H_ #define _PMKINSTALL_H_ #define STRIP_ENV_NAME "STRIP" #define DEFAULT_BACKUP_SFX ".old" /* default mode */ #define DEFAULT_MODE S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH /* mode masks */ #define USR_MASK S_IRWXU | S_ISUID /* user */ #define GRP_MASK S_IRWXG | S_ISGID /* group */ #define OTH_MASK S_IRWXO /* other */ #define FULL_MASK USR_MASK | GRP_MASK | OTH_MASK /* all */ /* perm masks */ #define R_PERM S_IRUSR | S_IRGRP | S_IROTH /* read */ #define W_PERM S_IWUSR | S_IWGRP | S_IWOTH /* write */ #define X_PERM S_IXUSR | S_IXGRP | S_IXOTH /* execute */ #define S_PERM S_ISUID | S_ISGID /* user/group ids */ #define FULL_PERM R_PERM | W_PERM | X_PERM | S_PERM /* all */ /* Local functions declaration */ void strip(char *); bool symbolic_to_octal_mode(char *, mode_t *); bool check_mode(char *, mode_t *); bool process_owner(char *, uid_t *); bool process_group(char *, gid_t *); bool create_directory(char *, char *, size_t); bool build_destination(char *, char *, char *, size_t); void usage(void); #endif /* _PMKINSTALL_H_ */ pmk-0.10.4/autoconf.h010064400017500000000000000044031027375204200132370ustar00mipswheel/* $Id: autoconf.h 1433 2005-08-02 20:14:26Z mipsator $ */ /* * Copyright (c) 2003-2004 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. * */ #ifndef _PMK_AUTOCONF_H_ #define _PMK_AUTOCONF_H_ #include "hash.h" #include "pmk.h" /************* * constants * ***********************************************************************/ #define AC_VAR_DEF "DEFS" #define AC_VALUE_DEF "-DHAVE_CONFIG_H" #define AC_ECHO_N "ECHO_N" #define AC_ECHO_C "ECHO_C" #define AC_ECHO_T "ECHO_T" /************** * prototypes * ***********************************************************************/ bool ac_parse_config(pmkdata *); bool ac_process_dyn_var(pmkdata *, char *); void ac_clean_dyn_var(htable *); bool ac_set_variables(htable *); #endif /* _PMK_AUTOCONF_H_ */ pmk-0.10.4/compat.c010064400017500000000000001226641047114646400127160ustar00mipswheel/* $Id: compat.c 1555 2006-08-17 20:10:28Z mipsator $ */ /* * 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. * */ #include #include #include #include #include #include #include "compat/config.h" #ifdef HAVE_INTMAX_T #include #endif #if defined(HAVE_WCHAR_T) || defined (HAVE_WINT_T) #include #endif #ifdef HAVE_PTRDIFF_T #include #endif #include "compat.h" #include "compat/pmk_ctype.h" #include "compat/pmk_libgen.h" #include "compat/pmk_stdbool.h" #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "compat/pmk_sys_types.h" #include "compat/pmk_unistd.h" /********** * macros * ***********************************************************************/ /* macros for structure */ #define SET_FLAG(f) data.flags = data.flags | f #define UNSET_FLAG(f) data.flags = data.flags & (FLAG_ALL ^ f); #define F_IS_SET(f) (data.flags & f) != 0 #define F_IS_UNSET(f) (data.flags & f) == 0 /* macros for pointer of structure */ #define SET_PFLAG(f) pdt->flags = pdt->flags | f #define UNSET_PFLAG(f) pdt->flags = pdt->flags & (FLAG_ALL ^ f); #define PF_IS_SET(f) (pdt->flags & f) != 0 #define PF_IS_UNSET(f) (pdt->flags & f) == 0 /*#define DEBUG_VSNPRINTF 1*/ /************* * functions * ***********************************************************************/ /***************** * fill_buffer() * *********************************************************************** DESCR Append a character in the buffer if it does not override the buffer's length IN pdt : vsnprintf common data structure chr : char to append OUT NONE ***********************************************************************/ static void fill_buffer(vsnp_t *pdt, char chr) { #ifdef DEBUG_VSNPRINTF printf("cursor = %d, char = '%c'\n", pdt->cur, chr); #endif /* if buffer is not full */ if (pdt->cur < pdt->len) { /* insert character */ pdt->buf[pdt->cur] = chr; } /* increment cursor position */ pdt->cur++; } /****************** * build_number() * *********************************************************************** DESCR Convert an unsigned integer into a string. The resulting string is in the reverse order without terminating null character. IN buffer : buffer location len : buffer size value : unsigned integer to convert pdt : vsnprintf common data structure OUT size of the resulting string ***********************************************************************/ static size_t build_number(char *buf, size_t len, unsigned_t value, base_t base, flag_t flags) { char *basestr; size_t vlen = 0; /* if value is equal to zero */ if (value == 0) { buf[0] = '0'; return(1); } /* select reference string relative to the case */ if ((flags & FLAG_UPPERCASE) != 0) { basestr = UPPER_BASE; } else { basestr = LOWER_BASE; } /* create number string in reverse order */ while ((value > 0) && (vlen < len)) { buf[vlen] = basestr[value % base]; value = value / base; vlen++; } return(vlen); } /***************** * convert_int() * *********************************************************************** DESCR Convert an integer value IN pdt : vsnprintf common data structure value : unsigned integer to convert OUT NONE ***********************************************************************/ static void convert_int(vsnp_t *pdt, unsigned_t value) { char nbuf[MAXINTLEN+1], sign = ' '; int vlen, zplen, splen, have_sign = 0, have_hex_prefix = 0; if (PF_IS_SET(FLAG_NEGATIVE_VALUE)) { /* on negative value set the sign */ have_sign = 1; sign = '-'; } else { /* else if + flag is set display the positive sign */ if (PF_IS_SET(FLAG_SIGNED)) { have_sign = 1; sign = '+'; } } vlen = build_number(nbuf, sizeof(nbuf), value, pdt->base, pdt->flags); /* compute zero padding */ zplen = pdt->prec - vlen; if (zplen < 0) { zplen = 0; } /* compute space padding */ if (pdt->prec > vlen) { splen = pdt->fwidth - pdt->prec; } else { splen = pdt->fwidth - vlen; } if (have_sign != 0) { splen--; } if (PF_IS_SET(FLAG_ALTERNATIVE_FORM)) { switch (pdt->base) { case BASE_OCT : /* octal alternative form */ if ((value == 0) && (pdt->prec == 0)) { pdt->prec = 1; } break; case BASE_HEX : /* hex alternative form */ if (value > 0) { have_hex_prefix = 1; splen = splen - 2; /* length of '0x' */ } break; } } if (splen < 0) { splen = 0; } /* right justify space padding */ if (PF_IS_UNSET(FLAG_LEFT_JUSTIFIED)) { while (splen > 0) { fill_buffer(pdt, ' '); splen--; } } /* if we have a sign */ if (have_sign != 0) { fill_buffer(pdt, sign); } /* hex alternative form */ if (have_hex_prefix != 0) { fill_buffer(pdt, '0'); if (PF_IS_UNSET(FLAG_UPPERCASE)) { fill_buffer(pdt, 'x'); } else { fill_buffer(pdt, 'X'); } } /* zero padding */ while (zplen > 0) { fill_buffer(pdt, '0'); zplen--; } /* converted integer */ while (vlen > 0) { fill_buffer(pdt, nbuf[vlen - 1]); vlen--; } /* left justify space padding */ if (PF_IS_SET(FLAG_LEFT_JUSTIFIED)) { while (splen > 0) { fill_buffer(pdt, ' '); splen--; } } } /****************** * convert_sint() * *********************************************************************** DESCR Convert a signed integer IN pdt : vsnprintf common data structure value : unsigned integer to convert OUT NONE ***********************************************************************/ static void convert_sint(vsnp_t *pdt, signed_t value) { /* check if value is negative */ if (value < 0) { /* if true set flag */ SET_PFLAG(FLAG_NEGATIVE_VALUE); value = -value; } /* call generic conversion procedure */ convert_int(pdt, (unsigned_t) value); } /***************** * convert_str() * *********************************************************************** DESCR Convert the string. It means copying the string in the place of the conversion identifier. IN pdt : vsnprintf common data structure ptr : string to convert OUT NONE ***********************************************************************/ static void convert_str(vsnp_t *pdt, char *ptr) { while ((pdt->cur < pdt->len) && (pdt->prec > 0) && (*ptr != '\0')) { fill_buffer(pdt, *ptr); ptr++; pdt->prec--; } } /***************** * conv_to_exp() * *********************************************************************** DESCR Convert to exponent form IN pdt : vsnprintf common data structure expnt : exponent value OUT exponent presence flag ***********************************************************************/ static int conv_to_exp(vsnp_t *pdt, flt_t *pval, int *pexp) { flt_t uval; int expnt, have_exp = 1; #ifdef DEBUG_VSNPRINTF printf("conv_to_exp() -> in\n"); #endif /* work on local variable to save value in case of g conversion */ uval = *pval; /* init exponent value */ expnt = 0; /* process value to get only one digit before decimal point */ if (uval >= 0) { while (uval > pdt->base) { uval = uval / pdt->base; expnt++; } } else { while (uval < 0) { uval = uval * pdt->base; expnt--; } } /* check if exponent is needed for g conversion */ if (PF_IS_SET(FLAG_G_CONVERSION)) { if ((expnt >= -4) && (expnt < pdt->prec)) { /* XXX use define for ISOC99 lower limit */ /* unset exponent flag */ have_exp = 0; /* get back to original value */ uval = *pval; } } /* set values */ *pval = uval; *pexp = expnt; #ifdef DEBUG_VSNPRINTF printf("conv_to_exp() -> out\n"); #endif return(have_exp); } /*************** * print_exp() * *********************************************************************** DESCR process exponent IN pdt : vsnprintf common data structure expnt : exponent value OUT NONE ***********************************************************************/ static void print_exp(vsnp_t *pdt, int expnt) { char ebuf[MAXINTLEN+1], sign= ' '; #ifdef DEBUG_VSNPRINTF printf("print_exp() -> in\n"); #endif /* exponent sign */ if (expnt < 0) { sign = '-'; } else { sign = '+'; } /* exponent type may vary */ ebuf[1] = '0'; /* init */ switch (pdt->base) { case BASE_DEC : /* g or G conversion */ if (PF_IS_SET(FLAG_UPPERCASE)) { fill_buffer(pdt, 'E'); } else { fill_buffer(pdt, 'e'); } fill_buffer(pdt, sign); /* exponent 2 digits */ build_number(ebuf, 2, expnt, BASE_DEC, FLAG_NONE); fill_buffer(pdt, ebuf[1]); fill_buffer(pdt, ebuf[0]); break; case BASE_HEX : /* a or A conversion */ if (PF_IS_SET(FLAG_UPPERCASE)) { fill_buffer(pdt, 'P'); } else { fill_buffer(pdt, 'p'); } fill_buffer(pdt, sign); /* exponent 1 digit */ build_number(ebuf, 1, expnt, BASE_DEC, FLAG_NONE); fill_buffer(pdt, ebuf[0]); break; } #ifdef DEBUG_VSNPRINTF printf("print_exp() -> out\n"); #endif } /************************ * convert_real_float() * *********************************************************************** DESCR Convert a floating point number IN pdt : vsnprintf common data structure value : unsigned integer to convert OUT NONE TODO -inf -NaN ***********************************************************************/ static void convert_real_float(vsnp_t *pdt, flt_t value) { char ibuf[MAXINTLEN+1], fbuf[MAXINTLEN+1], sign= ' '; flt_t frac, uval; int expnt = 0, explen = 0, fplen, fzplen, have_alt_form, have_dot = 0, have_exp = 0, have_g_conv, have_sign = 0, izplen, splen, skip_zero = 0, t; long intval, fracval, lt; size_t ilen, flen; #ifdef DEBUG_VSNPRINTF printf("convert_real_float() -> in\n"); #endif have_g_conv = (int) (pdt->flags & FLAG_G_CONVERSION); have_alt_form = (int) (pdt->flags & FLAG_ALTERNATIVE_FORM); /* for g conversion without alternative form */ if ((have_g_conv != 0) && (have_alt_form == 0)) { /* we skip ending zeros */ skip_zero = 1; } if (value < 0) { /* on negative value set the sign */ have_sign = 1; sign = '-'; uval = -value; } else { /* else if + flag is set display the positive sign */ if (PF_IS_SET(FLAG_SIGNED)) { have_sign = 1; sign = '+'; } uval = value; } if ((PF_IS_SET(FLAG_EXPONENT)) || (have_g_conv != 0)) { /* process eventual exponent */ have_exp = conv_to_exp(pdt, &uval, &expnt); } /* get integral part of the value */ intval = (long) uval; /* build integral part number */ ilen = build_number(ibuf, sizeof(ibuf), intval, pdt->base, pdt->flags); if (have_g_conv != 0) { pdt->prec = pdt->prec - ilen; if (pdt->prec < 0) { pdt->prec = 0; } } if (pdt->prec > 0) { /* get the fractional part */ frac = uval - (flt_t) intval; /* shift as digits as precision specify */ t = pdt->prec; /* init round limit */ lt = 1; /* multiply successively by base to obtain the desired precision */ while (t > 0) { frac = frac * pdt->base; lt = lt * pdt->base; t--; } /* get integral part of the result */ fracval = (long) frac; /* rount value if needed */ if ((frac - fracval) > 0.5) { fracval++; /* if the rounded value add a digit (eg 999 -> 1000) */ if (fracval == lt) { /* then adjust fractional value */ fracval = fracval / pdt->base; } } /* unset signed flag for fractional part */ UNSET_PFLAG(FLAG_SIGNED); /* build fractional part number */ flen = build_number(fbuf, sizeof(fbuf), fracval, pdt->base, pdt->flags); } else { flen = 0; fracval = 0; } /* need a dot ? */ if ((have_alt_form != 0) || (pdt->prec > 0)) { have_dot = 1; } /* specific treatment for g conversion */ if ((skip_zero != 0) && (fracval == 0)) { have_dot = 0; flen = 0; pdt->prec = 0; } /* fractal part len */ if (flen < (size_t) pdt->prec) { fplen = pdt->prec; fzplen = pdt->prec - flen; } else { fplen = flen; fzplen = 0; } /* exponent len */ if (have_exp != 0) { switch (pdt->base) { case BASE_DEC : explen = 4; break; case BASE_HEX : explen = 3; break; } } else { explen = 0; } /* total string len */ t = ilen + fplen + explen; /* sign */ if (have_sign != 0) { t++; } /* decimal point */ if (have_dot != 0) { t++; } /* a or A conversion => hex prefix */ if (pdt->base == BASE_HEX) { t= t + 2; } /* compute space or zero (integer part) padding */ if (PF_IS_SET(FLAG_ZERO_PADDING)) { izplen = pdt->fwidth - t; if (izplen < 0) { izplen = 0; } splen = 0; } else { splen = pdt->fwidth - t; if (splen < 0) { splen = 0; } izplen = 0; } /* right justify space padding */ if (PF_IS_UNSET(FLAG_LEFT_JUSTIFIED)) { while (splen > 0) { fill_buffer(pdt, ' '); splen--; } } /* if we have a sign */ if (have_sign != 0) { fill_buffer(pdt, sign); } /* hex alternative form */ if (pdt->base == BASE_HEX) { fill_buffer(pdt, '0'); if (PF_IS_UNSET(FLAG_UPPERCASE)) { fill_buffer(pdt, 'x'); } else { fill_buffer(pdt, 'X'); } } /* zero padding */ while (izplen > 0) { fill_buffer(pdt, '0'); izplen--; } /* integral part */ while (ilen > 0) { fill_buffer(pdt, ibuf[ilen - 1]); ilen--; } if (have_dot) { fill_buffer(pdt, '.'); if (pdt->prec > 0) { /* fractional part */ while (flen > 0) { fill_buffer(pdt, fbuf[flen - 1]); flen--; } if (skip_zero == 0) { /* zero padding */ while (fzplen > 0) { fill_buffer(pdt, '0'); fzplen--; } } } } if (have_exp != 0) { /* exponent part */ print_exp(pdt, expnt); } /* left justify space padding */ if (PF_IS_SET(FLAG_LEFT_JUSTIFIED)) { while (splen > 0) { fill_buffer(pdt, ' '); splen--; } } #ifdef DEBUG_VSNPRINTF printf("convert_real_float() -> out\n"); #endif } /*************************** * convert_special_float() * *********************************************************************** DESCR Convert a NaN or an infinite float IN pdt : vsnprintf common data structure value : unsigned integer to convert type : type of special float OUT NONE ***********************************************************************/ static void convert_special_float(vsnp_t *pdt, flt_t value, int type) { char *fstr = NULL, sign = ' '; int have_sign = 0; size_t i, len, splen; #ifdef DEBUG_VSNPRINTF printf("convert_special_float() -> in\n"); #endif if (value < 0) { /* on negative value set the sign */ have_sign = 1; sign = '-'; } else { /* else if + flag is set display the positive sign */ if (PF_IS_SET(FLAG_SIGNED)) { have_sign = 1; sign = '+'; } } /* set special float type string */ switch (type) { case FLT_IS_NAN : /* float is NaN */ if (PF_IS_SET(FLAG_UPPERCASE)) { fstr = UPPER_NAN; } else { fstr = LOWER_NAN; } break; case FLT_IS_INF : /* float is infinite */ if (PF_IS_UNSET(FLAG_UPPERCASE)) { fstr = UPPER_INF; } else { fstr = LOWER_INF; } break; } /* compute space padding length */ len = strlen(fstr); splen = pdt->fwidth - len; if (have_sign != 0) { splen--; } /* right justify space padding */ if (PF_IS_UNSET(FLAG_LEFT_JUSTIFIED)) { while (splen > 0) { fill_buffer(pdt, ' '); splen--; } } /* if we have a sign */ if (have_sign != 0) { fill_buffer(pdt, sign); } /* special float string */ for (i = 0 ; i < len ; i++) { fill_buffer(pdt, fstr[i]); } /* left justify space padding */ if (PF_IS_SET(FLAG_LEFT_JUSTIFIED)) { while (splen > 0) { fill_buffer(pdt, ' '); splen--; } } #ifdef DEBUG_VSNPRINTF printf("convert_special_float() -> out\n"); #endif } /******************* * convert_float() * *********************************************************************** DESCR Wrapper of floating point conversion IN pdt : vsnprintf common data structure value : unsigned integer to convert OUT NONE ***********************************************************************/ static void convert_float(vsnp_t *pdt, flt_t value) { #ifdef DEBUG_VSNPRINTF printf("convert_float() -> in\n"); #endif if (isnan(value) != 0) { /* float is NaN */ convert_special_float(pdt, value, FLT_IS_NAN); } else { if (isinf(value) != 0) { /* float is infinite */ convert_special_float(pdt, value, FLT_IS_INF); } } /* process real float */ convert_real_float(pdt, value); #ifdef DEBUG_VSNPRINTF printf("convert_float() -> out\n"); #endif } /******************* * pmk_vsnprintf() * *********************************************************************** DESCR String formatting function with fixed bufer size and va_list argument type IN buf : buffer location len : buffer size fmt : format string args : list of arguments OUT number of characters that would have been written if the buffer had not been size limited TODO wide char support ***********************************************************************/ int pmk_vsnprintf(char *buf, size_t len, const char *fmt, va_list args) { char *pstr, *pc = NULL; flt_t flt_val; int *pi = NULL, state = PARSE_CHAR, modifier = 0, n_modsave = MDFR_NORMAL, have_n_conv = 0; #ifdef HAVE_INTMAX_T intmax_t *pimt = NULL; #endif /* HAVE_INTMAX_T */ long *pl = NULL; #ifdef HAVE_LONG_LONG long long *pll = NULL; #endif /* HAVE_LONG_LONG */ #ifdef HAVE_PTRDIFF_T ptrdiff_t *ppd = NULL; #endif /* HAVE_PTRDIFF_T */ short *ps = NULL; signed_t int_val; size_t *pst = NULL; unsigned_t uint_val; void *ptr; vsnp_t data; #ifdef HAVE_WCHAR_T wchar_t *wc; #endif /* HAVE_WCHAR_T */ #ifdef HAVE_WINT_T wint_t wi; #endif /* HAVE_WINT_T */ /* init common data */ data.buf = buf; data.len = len; data.cur = 0; /* loop until the end of the format string is reached */ while (*fmt != '\0') { switch (state) { case PARSE_CHAR : /* check if we have a conversion sequence */ #ifdef DEBUG_VSNPRINTF printf("Enter state PARSE_CHAR\n"); #endif if (*fmt == '%') { data.flags = FLAG_NONE; data.fwidth = 0; /* -1 ? */ data.prec = -1; modifier = MDFR_NORMAL; state = PARSE_FLAGS; } else { /* else copy the character in the buffer */ fill_buffer(&data, *fmt); } /* next character */ fmt++; break; case PARSE_FLAGS : /* parse the conversion flags */ #ifdef DEBUG_VSNPRINTF printf("Enter state PARSE_FLAGS\n"); #endif switch (*fmt) { case '+' : SET_FLAG(FLAG_SIGNED); fmt++; break; case '-' : SET_FLAG(FLAG_LEFT_JUSTIFIED); fmt++; break; case ' ' : SET_FLAG(FLAG_SPACE_PREFIX); fmt++; break; case '#' : SET_FLAG(FLAG_ALTERNATIVE_FORM); fmt++; break; case '0' : SET_FLAG(FLAG_ZERO_PADDING); fmt++; break; default : state = PARSE_FLD_WIDTH; } break; case PARSE_FLD_WIDTH : /* parse the field width */ #ifdef DEBUG_VSNPRINTF printf("Enter state PARSE_FLD_WIDTH\n"); #endif /* if we got an asterisk */ if (*fmt == '*') { /* then get the field width from arguments */ data.fwidth = va_arg(args, int); /* if field width is negative */ if (data.fwidth < 0) { /* take absolute value for the width */ data.fwidth = data.fwidth * (-1); /* and set left justify flag */ SET_FLAG(FLAG_LEFT_JUSTIFIED); } fmt++; } else { /* else take the width from format string */ while ((*fmt >= '0') && (*fmt <= '9')) { data.fwidth = (data.fwidth * 10) + (int) (*fmt - '0'); fmt++; } } /* ignore 0 flag if - flag is provided */ if (F_IS_SET(FLAG_LEFT_JUSTIFIED)) { UNSET_FLAG(FLAG_ZERO_PADDING); } state = PARSE_DOT; break; case PARSE_DOT : /* check if the dot of precision field is given */ #ifdef DEBUG_VSNPRINTF printf("Enter state PARSE_DOT\n"); #endif if (*fmt == '.') { /* if yes parse the precision field */ fmt++; data.prec = 0; state = PARSE_PRECISION; /*flags = flags & (FLAG_ALL ^ FLAG_ZERO_PADDING);*//* XXX meant for something ??? */ } else { /* else go parse the modifier */ state = PARSE_LEN_MDFR; } break; case PARSE_PRECISION : /* parse precision field */ /* if we got an asterisk */ if (*fmt == '*') { /* then get the precision from arguments */ data.prec = va_arg(args, int); fmt++; } else { /* else take the precision from format string */ while ((*fmt >= '0') && (*fmt <= '9')) { data.prec = (data.prec * 10) + (int) (*fmt - '0'); fmt++; } } /* go parse the modifier */ state = PARSE_LEN_MDFR; break; case PARSE_LEN_MDFR : /* parse modifier */ #ifdef DEBUG_VSNPRINTF printf("Enter state PARSE_LEN_MDFR\n"); #endif switch (*fmt) { case 'h' : switch (modifier) { case MDFR_NORMAL : modifier = MDFR_SHORT; fmt++; break; case MDFR_SHORT : modifier = MDFR_CHAR; state = PARSE_CONV_SPEC; fmt++; break; default : state = PARSE_CONV_SPEC; } break; case 'l' : switch (modifier) { case MDFR_NORMAL : modifier = MDFR_LONG; fmt++; break; case MDFR_LONG : #if defined(HAVE_LONG_LONG) || defined(HAVE_UNSIGNED_LONG_LONG) modifier = MDFR_LONG_LONG; #endif /* HAVE_LONG_LONG || HAVE_UNSIGNED_LONG_LONG */ state = PARSE_CONV_SPEC; fmt++; break; default : state = PARSE_CONV_SPEC; } break; case 'j' : modifier = MDFR_INTMAX; state = PARSE_CONV_SPEC; fmt++; break; case 'z' : modifier = MDFR_SIZET; state = PARSE_CONV_SPEC; fmt++; break; case 't' : modifier = MDFR_PTRDIFF; state = PARSE_CONV_SPEC; fmt++; break; case 'L' : modifier = MDFR_LONG_DBL; state = PARSE_CONV_SPEC; fmt++; break; default : state = PARSE_CONV_SPEC; } break; case PARSE_CONV_SPEC : /* parse conversion specifier */ #ifdef DEBUG_VSNPRINTF printf("Enter state PARSE_CONV_SPEC\n"); #endif switch(*fmt) { case 'd' : case 'i' : /* signed decimal */ /* default precision */ if (data.prec < 0) { data.prec = 1; } /* process modifier */ switch (modifier) { case MDFR_LONG : int_val = (signed_t) va_arg(args, long); break; #ifdef HAVE_LONG_LONG case MDFR_LONG_LONG : int_val = (signed_t) va_arg(args, long long); break; #endif /* HAVE_LONG_LONG */ case MDFR_SHORT : case MDFR_CHAR : /* short and char are promoted to int throught ... */ int_val = (signed_t) va_arg(args, int); break; #ifdef HAVE_INTMAX_T case MDFR_INTMAX : int_val = (signed_t) va_arg(args, intmax_t); break; #endif /* HAVE_INTMAX_T */ case MDFR_SIZET : int_val = (signed_t) va_arg(args, size_t); break; #ifdef HAVE_PTRDIFF_T case MDFR_PTRDIFF : int_val = (signed_t) va_arg(args, ptrdiff_t); break; #endif /* HAVE_PTRDIFF_T */ default : int_val = (signed_t) va_arg(args, int); } data.base = 10; convert_sint(&data, int_val); break; case 'o' : case 'u' : case 'x' : case 'X' : /* unsigned conversion */ /* default precision */ if (data.prec < 0) { data.prec = 1; } /* ignore - flag */ UNSET_FLAG(FLAG_SIGNED); /* process modifier */ switch (modifier) { case MDFR_LONG : uint_val = (unsigned_t) va_arg(args, unsigned long); break; #ifdef HAVE_UNSIGNED_LONG_LONG case MDFR_LONG_LONG : uint_val = (unsigned_t) va_arg(args, unsigned long long); break; #endif /* HAVE_UNSIGNED_LONG_LONG */ case MDFR_SHORT : case MDFR_CHAR : /* short and char are promoted to int throught ... */ uint_val = (unsigned_t) va_arg(args, unsigned int); break; #ifdef HAVE_UINTMAX_T case MDFR_INTMAX : uint_val = (unsigned_t) va_arg(args, uintmax_t); break; #endif /* HAVE_UINTMAX_T */ case MDFR_SIZET : uint_val = (unsigned_t) va_arg(args, size_t); break; #ifdef HAVE_PTRDIFF_T case MDFR_PTRDIFF : uint_val = (unsigned_t) va_arg(args, ptrdiff_t); break; #endif /* HAVE_PTRDIFF_T */ default : uint_val = (unsigned_t) va_arg(args, unsigned int); } /* set base */ switch (*fmt) { case 'o' : data.base = BASE_OCT; break; case 'u' : data.base = BASE_DEC; break; case 'X' : SET_FLAG(FLAG_UPPERCASE); /* no break */ case 'x' : data.base = BASE_HEX; break; } convert_int(&data, uint_val); break; case 'F' : case 'E' : case 'G' : case 'A' : /* float conversion (uppercase) */ SET_FLAG(FLAG_UPPERCASE); /* no break */ case 'f' : case 'e' : case 'g' : case 'a' : /* float conversion (common) */ switch (*fmt) { case 'F' : case 'f' : data.base = BASE_DEC; /* default precision */ if (data.prec < 0) { data.prec = 6; } break; case 'E' : case 'e' : data.base = BASE_DEC; SET_FLAG(FLAG_EXPONENT); /* default precision */ if (data.prec < 0) { data.prec = 6; } break; case 'G' : case 'g' : data.base = BASE_DEC; SET_FLAG(FLAG_G_CONVERSION); /* default precision */ if (data.prec <= 0) { data.prec = 6; /* XXX ISO C99 = 1 */ } break; case 'A' : case 'a' : data.base = BASE_HEX; SET_FLAG(FLAG_EXPONENT); /* default precision */ if (data.prec < 0) { data.prec = 4; /* XXX real default value is ? */ } break; } #ifdef HAVE_LONG_DOUBLE if (modifier == MDFR_LONG_DBL) { flt_val = (flt_t) va_arg(args, long double); } else { #endif /* HAVE_LONG_DOUBLE */ flt_val = (flt_t) va_arg(args, double); #ifdef HAVE_LONG_DOUBLE } #endif /* HAVE_LONG_DOUBLE */ convert_float(&data, flt_val); break; case 'c' : /* character conversion */ #ifdef HAVE_WINT_T if (modifier == MDFR_LONG) { /* wide char */ wi = va_arg(args, wint_t); /* XXX TODO wide char support */ } else { #endif /* HAVE_WINT_T */ /* char is promoted to int throught ... */ int_val = (signed_t) va_arg(args, int); fill_buffer(&data, (char) int_val); #ifdef HAVE_WINT_T } #endif /* HAVE_WINT_T */ break; case 's' : /* string conversion */ #ifdef HAVE_WCHAR_T if (modifier == MDFR_LONG) { /* wide char */ wc = va_arg(args, wchar_t *); /* XXX TODO wide char support */ } else { #endif /* HAVE_WCHAR_T */ pstr = va_arg(args, char *); if (data.prec <= 0) { data.prec = len; } convert_str(&data, pstr); #ifdef HAVE_WCHAR_T } #endif /* HAVE_WCHAR_T */ break; case 'p' : /* pointer conversion */ ptr = va_arg(args, void *); data.base = BASE_HEX; /* XXX ? SET_FLAG(FLAG_ALTERNATIVE_FORM); */ convert_int(&data, (unsigned_t) (size_t) ptr); break; case 'n' : /* pointer to the variable that will receive string size */ /* set flag */ have_n_conv = 1; /* save modifier */ n_modsave = modifier; /* process modifier */ switch (modifier) { case MDFR_LONG : pl = va_arg(args, long *); break; #ifdef HAVE_LONG_LONG case MDFR_LONG_LONG : pll = va_arg(args, long long *); break; #endif /* HAVE_LONG_LONG */ case MDFR_SHORT : ps = va_arg(args, short *); break; case MDFR_CHAR : pc = va_arg(args, char *); break; #ifdef HAVE_INTMAX_T case MDFR_INTMAX : pimt = va_arg(args, intmax_t *); break; #endif /* HAVE_INTMAX_T */ case MDFR_SIZET : pst = va_arg(args, size_t *); break; #ifdef HAVE_PTRDIFF_T case MDFR_PTRDIFF : ppd = va_arg(args, ptrdiff_t *); break; #endif /* HAVE_PTRDIFF_T */ default : pi = va_arg(args, int *); } break; case '%' : /* "escaped" conversion character */ /* XXX we allow complete specification, != ISO C99 ? */ fill_buffer(&data, *fmt); break; } /* next char */ fmt++; state = PARSE_CHAR; break; } } /* NULL terminate the string */ if (len > data.cur) { buf[data.cur] = '\0'; } else { buf[len - 1] = '\0'; } /* if %n provided, write lenght into the pointed area */ if (have_n_conv != 0) { /* process modifier */ switch (n_modsave) { case MDFR_LONG : *pl = (long) data.cur; break; #ifdef HAVE_LONG_LONG case MDFR_LONG_LONG : *pll = (long long) data.cur; break; #endif /* HAVE_LONG_LONG */ case MDFR_SHORT : *ps = (short) data.cur; break; case MDFR_CHAR : *pc = (char) data.cur; break; #ifdef HAVE_INTMAX_T case MDFR_INTMAX : *pimt = (intmax_t) data.cur; break; #endif /* HAVE_INTMAX_T */ case MDFR_SIZET : *pst = data.cur; break; #ifdef HAVE_PTRDIFF_T case MDFR_PTRDIFF : *ppd = (ptrdiff_t) data.cur; break; #endif /* HAVE_PTRDIFF_T */ default : *pi = (int) data.cur; } } /* return what should have been the string lenght if not limited */ return(data.cur); } /***************** * pmk_strlcpy() * *********************************************************************** DESCR This function duplicate a string. IN ostr : char pointer of source string OUT pointer to duplicated string or NULL ***********************************************************************/ char *pmk_strdup(const char *ostr) { char *pstr; size_t len; len = strlen(ostr) + 1; pstr = (char *) malloc(len); if (pstr != NULL) { memcpy(pstr, ostr, len); } return(pstr); } /***************** * pmk_strlcpy() * *********************************************************************** DESCR This function copy a given number of characters from a source string to a destination buffer. It also grants that this buffer will be null terminated. IN dst : char pointer of destination buffer src : char pointer of source string s : number of characters to copy OUT size of the source string ***********************************************************************/ size_t pmk_strlcpy(char *dst, const char *src, size_t s) { size_t len = 0; /* loop until we reach the end of the src string */ while (*src != '\0') { /* if buffer is not full */ if (s > 0) { if (s == 1) { /* last character, null terminate */ *dst = '\0'; } else { /* copy character */ *dst = *src; } /* adjust remaining size */ s--; /* update src string length */ len++; /* and dst pointer */ dst++; } /* increment src pointer */ src++; } /* if the end of the buffer has not been reached */ if (s > 0) { /* last character, null terminate */ *dst = '\0'; } return(len); } /***************** * pmk_strlcat() * *********************************************************************** DESCR This function append a given number of characters from a source string to the end of a destination buffer. It also grants that this buffer will be null terminated. IN dst : char pointer of destination buffer src : char pointer of source string s : number of characters to copy OUT size of the source string ***********************************************************************/ size_t pmk_strlcat(char *dst, const char *src, size_t s) { size_t len; /* get size of actual string */ len = strlen(dst); /* start right after the last character */ dst = dst + len; /* update size */ s = s -len; /* update len with the result of the string copy */ len = len + pmk_strlcpy(dst, src, s); return(len); } /*************************** * find_parent_separator() * *********************************************************************** DESCR try to find the last separator between directory name and file name IN path : path string psep : separator location plen : path string len OUT NONE ***********************************************************************/ static void find_parent_separator(char *path, char **psep, size_t *plen) { char *psave = NULL; int have_sep = 0; /* initialize length */ *plen = 0; /* initialize separator position */ *psep = NULL; while (*path != '\0') { if (*path == '/') { /* set flag */ have_sep = 1; /* save position */ psave = path; } else { if (have_sep != 0) { /* had a separator before -> save last position */ *psep = psave; } } /* next character */ path++; (*plen)++; } } /***************** * pmk_dirname() * *********************************************************************** DESCR XXX IN XXX OUT XXX ***********************************************************************/ char *pmk_dirname(char *path) { static char buffer[MAXPATHLEN]; char *pstr, *psep; size_t len; /* start at the begining of the buffer */ pstr = buffer; if ((path == NULL) || (*path == '\0')) { *pstr = '.'; pstr++; } else { /* look for base/dir separator */ find_parent_separator(path, &psep, &len); if (psep == NULL) { /* no valid separator found */ if (*path == '/') { *pstr = '/'; } else { *pstr = '.'; } pstr++; } else { while ((psep > path) && (*psep == '/')) { /* skip trailing slashes */ psep--; } /* take care of buffer overflow */ if ((size_t) (psep - path) > sizeof(buffer)) { return(NULL); } /* copy characters until separator position */ while (path <= psep) { *pstr = *path; pstr++; path++; } } } /* NULL terminate the buffer */ *pstr = '\0'; return(buffer); } /****************** * pmk_basename() * *********************************************************************** DESCR XXX IN XXX OUT XXX ***********************************************************************/ char *pmk_basename(char *path) { static char buffer[MAXPATHLEN]; char *pstr, *psep, *pbeg, *pend; size_t len; /* start at the begining of the buffer */ pstr = buffer; /* if path is a null pointer or empty string */ if ((path == NULL) || (*path == '\0')) { *pstr = '.'; pstr++; } else { /* else look for base/dir separator */ find_parent_separator(path, &psep, &len); /* if no valid separator is found */ if (psep == NULL) { /* return the whole string */ pbeg = path; } else { /* else return the string starting right after separator */ pbeg = psep + 1; } /* compute end of string pointer */ pend = path + len - 1; while ((pend > pbeg) && (*pend == '/')) { /* skip trailing slashes */ pend--; } /* take care of buffer overflow */ if ((size_t) (pend - pbeg) > sizeof(buffer)) { return(NULL); } /* copy characters until separator position */ while (pbeg <= pend) { *pstr = *pbeg; pstr++; pbeg++; } } /* NULL terminate the buffer */ *pstr = '\0'; return(buffer); } /***************** * pmk_isblank() * *********************************************************************** DESCR XXX IN XXX OUT XXX ***********************************************************************/ int pmk_isblank(int c) { if (c == ' ' || c == '\t') return (1); else return(0); } /****************** * pmk_mkstemps() * *********************************************************************** DESCR XXX IN XXX OUT XXX ***********************************************************************/ int pmk_mkstemps(char *template, int suffixlen) { struct timeval tv; char subst[] = "aZbY0cXdWe1VfUgT2hSiRj3QkPlO4mNnMo5LpKqJ6rIsHt7GuFvE8wDxCy9BzA", *start, *end, *p; int fd, len, i; /* forwarding to end of template */ for (p = template ; *p != '\0' ; p++); /* increment len to also count end of file character */ suffixlen++; /* compute (supposed) position of last character to replace */ p = p - suffixlen; /* check it baby ;) */ if (p < template) return(-1); /* set last character position */ end = p; /* step back until we found the starting character */ for ( ; *p == MKSTEMPS_REPLACE_CHAR && p > template; p--); /* set fisrt character position */ start = ++p; /* intialise random() */ len = strlen(subst); gettimeofday(&tv, NULL); srandom(tv.tv_sec * tv.tv_usec); /* lets go replacing the stuff */ for (p = start ; p <= end ; p++) { /* get random value */ i = (int) random() % len; /* replace */ *p = subst[i]; } /* open file */ fd = open(template, O_CREAT|O_EXCL|O_RDWR, S_IRUSR | S_IWUSR); return(fd); } /************************ * compatibility stuff * ***********************************************************************/ /******************** * pmk_stdio.h * ********************/ #ifndef HAVE_VSNPRINTF int vsnprintf(char *buf, size_t len, const char *fmt, va_list args) { return(pmk_vsnprintf(buf, len, fmt, args)); } #endif /* HAVE_VSNPRINTF */ #ifndef HAVE_SNPRINTF int snprintf(char *str, size_t size, const char *format, ...) { int rslt; va_list args; va_start(args, format); rslt = vsnprintf(str, size, format, args); va_end(args); return(rslt); } #endif /* HAVE_SNPRINTF */ /******************** * pmk_string.h * ********************/ #ifndef HAVE_STRDUP char *strdup(const char *str) { return(pmk_strdup(str)); } #endif /* HAVE_STRDUP */ #ifndef HAVE_STRLCAT size_t strlcat(char *dst, const char *src, size_t s) { return(pmk_strlcat(dst, src, s)); } #endif /* HAVE_STRLCAT */ #ifndef HAVE_STRLCPY size_t strlcpy(char *dst, const char *src, size_t s) { return(pmk_strlcpy(dst, src, s)); } #endif /* HAVE_STRLCPY */ /******************** * pmk_libgen.h * ********************/ #ifndef HAVE_LIBGEN_H char *dirname(char *path) { return(pmk_dirname(path)); } char *basename(char *path) { return(pmk_basename(path)); } #endif /* HAVE_LIBGEN_H */ /**************** * pmk_ctype.h * ****************/ #ifndef HAVE_ISBLANK int isblank(int c) { return(pmk_isblank(c)); } #endif /* HAVE_ISBLANK */ /******************** * pmk_unistd.h * ********************/ #ifndef HAVE_MKSTEMPS int mkstemps(char *template, int suffixlen) { return(pmk_mkstemps(template, suffixlen)); } #endif /* HAVE_MKSTEMPS */ /******************************** * boolean string functions * ***********************************************************************/ /**************** * snprintf_b() * *********************************************************************** DESCR boolean snprintf IN buf : buffer location siz : buffer size fmt : format string ... : argument list OUT boolean value ***********************************************************************/ bool snprintf_b(char *buf, size_t siz, const char *fmt, ...) { bool rslt; va_list ap; va_start(ap, fmt); if (vsnprintf(buf, siz, fmt, ap) >= (int) siz) rslt = false; else rslt = true; va_end(ap); return(rslt); } /*************** * strlcat_b() * *********************************************************************** DESCR boolean strlcat IN dst : destination buffer src : source string siz : size of destination buffer OUT boolean ***********************************************************************/ bool strlcat_b(char *dst, const char *src, size_t siz) { if (strlcat(dst, src, siz) >= siz) return(false); else return(true); } /*************** * strlcpy_b() * *********************************************************************** DESCR boolean strlcpy IN dst : destination buffer src : source string siz : size of destination buffer OUT boolean ***********************************************************************/ bool strlcpy_b(char *dst, const char *src, size_t siz) { if (strlcpy(dst, src, siz) >= siz) return(false); else return(true); } /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/pmk.c010064400017500000000000000666571053631601400122230ustar00mipswheel/* $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 /* include it first as if it was - this will avoid errors */ #include "compat/pmk_sys_types.h" #include #include #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: */ pmk-0.10.4/compat.h010064400017500000000000000110411027720374100127010ustar00mipswheel/* $Id: compat.h 1451 2005-08-12 20:34:41Z mipsator $ */ /* * 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. * */ #ifndef _PMK_COMPAT_H_ #define _PMK_COMPAT_H_ #include #include "compat/pmk_string.h" /********************************** * constants and type definitions * ***********************************************************************/ enum { PARSE_CHAR, PARSE_FLAGS, /* +,-, ,#,0 */ PARSE_FLD_WIDTH, PARSE_DOT, PARSE_PRECISION, PARSE_LEN_MDFR, /* hh,h,l,ll,j,z,t,L */ PARSE_CONV_SPEC /* d,i,o,u,x,X,f,F,e,E,g,G,a,A,c,s,p,n,% */ }; enum { MDFR_NORMAL, MDFR_CHAR, MDFR_SHORT, MDFR_LONG, MDFR_LONG_LONG, MDFR_INTMAX, MDFR_SIZET, MDFR_PTRDIFF, MDFR_LONG_DBL }; enum { FLT_IS_NAN, FLT_IS_INF }; /* conversion flag masks */ #define FLAG_NONE 0x0000 #define FLAG_SIGNED 0x0001 #define FLAG_LEFT_JUSTIFIED 0x0002 #define FLAG_SPACE_PREFIX 0x0004 #define FLAG_ALTERNATIVE_FORM 0x0008 #define FLAG_ZERO_PADDING 0x0010 #define FLAG_PRECISION 0x0020 #define FLAG_UPPERCASE 0x0040 #define FLAG_EXPONENT 0x0080 #define FLAG_G_CONVERSION 0x0100 #define FLAG_NEGATIVE_VALUE 0x0200 #define FLAG_ALL 0xffff /* base definition */ #define BASE_OCT 8 #define BASE_DEC 10 #define BASE_HEX 16 #ifdef HAVE_LONG_LONG typedef long long signed_t; #else /* HAVE_LONG_LONG */ typedef long signed_t; #endif /* HAVE_LONG_LONG */ #ifdef HAVE_UNSIGNED_LONG_LONG typedef unsigned long long unsigned_t; #else /* HAVE_UNSIGNED_LONG_LONG */ typedef unsigned long unsigned_t; #endif /* HAVE_UNSIGNED_LONG_LONG */ #ifdef HAVE_LONG_DOUBLE typedef long double flt_t; #else /* HAVE_LONG_DOUBLE */ typedef double flt_t; #endif /* HAVE_LONG_DOUBLE */ typedef unsigned char base_t; typedef unsigned int flag_t; #ifdef HAVE_UNSIGNED_LONG_LONG #define BYTESIZE sizeof(unsigned long long) #else /* HAVE_UNSIGNED_LONG_LONG */ #define BYTESIZE sizeof(unsigned long) #endif /* HAVE_UNSIGNED_LONG_LONG */ #define UPPER_BASE "0123456789ABCDEF" #define LOWER_BASE "0123456789abcdef" #define UPPER_INF "INF" #define LOWER_INF "inf" #define UPPER_NAN "NAN" #define LOWER_NAN "nan" /* compute approximative string size needed for maximum int conversion verified with values up to 2^128, 16 bytes values. */ #define MAXINTLEN ((BYTESIZE * 3) - (BYTESIZE / 2)) #define MKSTEMPS_REPLACE_CHAR 'X' /* vsnprintf data structure */ typedef struct { char *buf; size_t len, cur; base_t base; int fwidth, prec; flag_t flags; } vsnp_t; /************** * prototypes * ***********************************************************************/ int pmk_vsnprintf(char *, size_t, const char *, va_list); char *pmk_strdup(const char *); size_t pmk_strlcpy(char *, const char *, size_t); size_t pmk_strlcat(char *, const char *, size_t); char *pmk_dirname(char *); char *pmk_basename(char *); int pmk_isblank(int); int pmk_mkstemps(char *, int); bool snprintf_b(char *, size_t, const char *, ...); bool strlcat_b(char *, const char *, size_t); bool strlcpy_b(char *, const char *, size_t); #endif /* _PMK_COMPAT_H_ */ pmk-0.10.4/premake.h010064400017500000000000000143221077177720000130540ustar00mipswheel/* $Id: premake.h 2052 2008-03-24 19:18:24Z coudercd $ */ /* * Copyright (c) 2003-2006 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. * */ #ifndef _PREMAKE_H_ #define _PREMAKE_H_ #include "compat/pmk_stdbool.h" #include "errmsg.h" #include "pmk_obj.h" #include #ifndef MAXPATHLEN # define MAXPATHLEN 512 #endif #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #ifndef SYSCONFDIR # define SYSCONFDIR "/etc" #endif #ifndef CONFDIR # define CONFDIR SYSCONFDIR "/pmk" #endif #ifndef TMPDIR # define TMPDIR "." #endif #ifndef TMPBINDIR # define TMPBINDIR "." #endif /* major version */ #define PREMAKE_VMAJOR "0" /* minor version */ #define PREMAKE_VMINOR "10" /* minor subversion, only used for bugfixes */ #define PREMAKE_VSUB "4" /* full version */ #ifndef PREMAKE_VSUB #define PREMAKE_VFULL PREMAKE_VMAJOR "." PREMAKE_VMINOR #else #define PREMAKE_VFULL PREMAKE_VMAJOR "." PREMAKE_VMINOR "." PREMAKE_VSUB #endif /* only used for snapshots, comment for release */ /*#define PREMAKE_SNAP "20061028"*/ /* build version string */ #ifndef PREMAKE_SNAP #define PREMAKE_VERSION PREMAKE_VFULL #else #define PREMAKE_VERSION "SNAP" PREMAKE_SNAP #endif #define PREMAKE_CONFIG "pmk.conf" #define PREMAKE_FILENAME "pmkfile" #define PREMAKE_PKGFILE "pkgfile" #define PREMAKE_CONFIG_PATH CONFDIR "/" PREMAKE_CONFIG #define PREMAKE_CONFIG_PATH_BAK PREMAKE_CONFIG_PATH ".bak" #define PREMAKE_TMP_DIR TMPDIR /* pmk.conf keys */ /* key names (see also pmksetup.h) */ #define PMKCONF_BIN_AR "BIN_AR" #define PMKCONF_BIN_AS "BIN_AS" #define PMKCONF_BIN_AWK "BIN_AWK" #define PMKCONF_BIN_CAT "BIN_CAT" #define PMKCONF_BIN_C89 "BIN_C89" #define PMKCONF_BIN_C99 "BIN_C99" #define PMKCONF_BIN_CC "BIN_CC" #define PMKCONF_BIN_CPP "BIN_CPP" #define PMKCONF_BIN_CXX "BIN_CXX" #define PMKCONF_BIN_ECHO "BIN_ECHO" #define PMKCONF_BIN_EGREP "BIN_EGREP" #define PMKCONF_BIN_GREP "BIN_GREP" #define PMKCONF_BIN_ID "BIN_ID" #define PMKCONF_BIN_INSTALL "BIN_INSTALL" #define PMKCONF_BIN_LEX "BIN_LEX" #define PMKCONF_BIN_LN "BIN_LN" #define PMKCONF_BIN_PKGCONFIG "BIN_PKGCONFIG" #define PMKCONF_BIN_RANLIB "BIN_RANLIB" #define PMKCONF_BIN_SH "BIN_SH" #define PMKCONF_BIN_STRIP "BIN_STRIP" #define PMKCONF_BIN_SUDO "BIN_SUDO" #define PMKCONF_BIN_TAR "BIN_TAR" #define PMKCONF_BIN_YACC "BIN_YACC" #define PMKCONF_HW_CPU_ARCH "HW_CPU_ARCH" #define PMKCONF_HW_BYTEORDER "HW_BYTEORDER" #define PMKCONF_PATH_BIN "PATH_BIN" #define PMKCONF_PATH_INC "PATH_INC" #define PMKCONF_PATH_LIB "PATH_LIB" #define PMKCONF_PC_PATH_LIB "PC_PATH_LIB" #define PMKCONF_OS_NAME "OS_NAME" #define PMKCONF_OS_VERS "OS_VERSION" #define PMKCONF_OS_ARCH "OS_ARCH" #define PMKCONF_MISC_SYSCONFDIR "SYSCONFDIR" #define PMKCONF_MISC_PREFIX "PREFIX" #define PMKCONF_AC_ECHO_N "AC_ECHO_N" #define PMKCONF_AC_ECHO_C "AC_ECHO_C" #define PMKCONF_AC_ECHO_T "AC_ECHO_T" /* specific values */ #define PMKVAL_BIN_PKGCONFIG "pkg-config" #define PMKVAL_LIB_PKGCONFIG "/lib/pkgconfig" /* preceeded by PREFIX */ #define PMKVAL_ENV_LIBS "LIBS" #define PMKVAL_ENV_CFLAGS "CFLAGS" /* prefix character used for comments */ #define CHAR_COMMENT '#' /* end of string */ #define CHAR_EOS '\0' /* carriage return */ #define CHAR_CR '\n' /* pmk.conf separators */ #define CHAR_ASSIGN_UPDATE '=' #define CHAR_ASSIGN_STATIC ':' #define CHAR_LIST_SEPARATOR ',' /* misc boolean stuff */ #define BOOL_STRING_TRUE "TRUE" #define BOOL_STRING_FALSE "FALSE" /* hw values */ #define HW_ENDIAN_BIG "BIG_ENDIAN" #define HW_ENDIAN_LITTLE "LITTLE_ENDIAN" #define HW_ENDIAN_UNKNOWN "UNKNOWN_ENDIAN" /* make specific variable names */ #define MK_VAR_CFLAGS "CFLAGS" #define MK_VAR_CXXFLAGS "CXXFLAGS" #define MK_VAR_CPPFLAGS "CPPFLAGS" #define MK_VAR_LDFLAGS "LDFLAGS" #define MK_VAR_CLDFLAGS "CLDFLAGS" #define MK_VAR_CXXLDFLAGS "CXXLDFLAGS" #define MK_VAR_LIBS "LIBS" #define MK_VAR_DEBUG "DEBUG" #define MK_VAR_SL_BUILD "SHARED_LIB_TARGETS" #define MK_VAR_SL_CLEAN "SHLIB_CLEAN_TARGETS" #define MK_VAR_SL_INST "SHLIB_INST_TARGETS" #define MK_VAR_SL_DEINST "SHLIB_DEINST_TARGETS" /* maximal size of an error message */ #define MAX_ERR_MSG_LEN 256 /* maximal size of a command name */ #define CMD_LEN 32 /* maximal size of a command label */ #define LABEL_LEN 64 /* maximal sizes for command pair of option (name and value) */ #define OPT_NAME_LEN 64 #define OPT_VALUE_LEN MAXPATHLEN /* can contain a path */ /* maximal size of a line */ #define MAX_LINE_LEN MAXPATHLEN + OPT_NAME_LEN /* maximal number of key in data hash */ #define MAX_DATA_KEY 1024 /* size for temporary buffers */ #define TMP_BUF_LEN 512 /* string delimiter PATH variables */ #define PATH_STR_DELIMITER ':' #endif /* _PREMAKE_H_ */ /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/func.c010064400017500000000000001763421062137053100123570ustar00mipswheel/* $Id: func.c 1987 2007-05-12 16:54:49Z coudercd $ */ /* * Copyright (c) 2003-2006 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. * */ #include #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "compat/pmk_unistd.h" #include "autoconf.h" #include "cfgtool.h" #include "codebuild.h" #include "common.h" #include "detect.h" #include "func.h" #include "functool.h" #include "hash.h" #include "pkgconfig.h" #include "premake.h" #include "tags.h" /*#define SHLIB_DEBUG 1*/ /*************** * parser data * ***********************************************************************/ /* common required options */ kw_t req_name[] = { {KW_OPT_NAME, PO_STRING} }; /* CHECK_BIN options */ kw_t opt_chkbin[] = { {KW_OPT_DEFS, PO_LIST}, {KW_OPT_DEPEND, PO_LIST}, {KW_OPT_REQUIRED, PO_BOOL}, {KW_OPT_VARIABLE, PO_STRING} }; kwopt_t kw_chkbin = { req_name, sizeof(req_name) / sizeof(kw_t), opt_chkbin, sizeof(opt_chkbin) / sizeof(kw_t) }; /* CHECK_HEADER options */ kw_t opt_chkhdr[] = { {KW_OPT_CFLAGS, PO_STRING}, {KW_OPT_DEFS, PO_LIST}, {KW_OPT_DEPEND, PO_LIST}, {KW_OPT_SUBHDR, PO_LIST}, {KW_OPT_FUNCTION, PO_STRING | PO_LIST}, {KW_OPT_LANG, PO_STRING}, {KW_OPT_MACRO, PO_LIST}, {KW_OPT_REQUIRED, PO_BOOL} }; kwopt_t kw_chkhdr = { req_name, sizeof(req_name) / sizeof(kw_t), opt_chkhdr, sizeof(opt_chkhdr) / sizeof(kw_t) }; /* CHECK_LIB options */ kw_t opt_chklib[] = { {KW_OPT_DEFS, PO_LIST}, {KW_OPT_DEPEND, PO_LIST}, {KW_OPT_FUNCTION, PO_STRING | PO_LIST}, {KW_OPT_LANG, PO_STRING}, {KW_OPT_LIBS, PO_STRING}, {KW_OPT_MACRO, PO_LIST}, {KW_OPT_REQUIRED, PO_BOOL} }; kwopt_t kw_chklib = { req_name, sizeof(req_name) / sizeof(kw_t), opt_chklib, sizeof(opt_chklib) / sizeof(kw_t) }; /* CHECK_CONFIG options */ kw_t opt_chkcfg[] = { {KW_OPT_DEFS, PO_LIST}, {KW_OPT_DEPEND, PO_LIST}, {KW_OPT_CFLAGS, PO_STRING}, {KW_OPT_LIBS, PO_STRING}, {KW_OPT_REQUIRED, PO_BOOL}, {KW_OPT_VARIABLE, PO_STRING}, {KW_OPT_VERSION, PO_STRING} }; kwopt_t kw_chkcfg = { req_name, sizeof(req_name) / sizeof(kw_t), opt_chkcfg, sizeof(opt_chkcfg) / sizeof(kw_t) }; /* CHECK_PKG_CONFIG options */ kw_t opt_chkpc[] = { {KW_OPT_DEFS, PO_LIST}, {KW_OPT_DEPEND, PO_LIST}, {KW_OPT_CFLAGS, PO_STRING}, {KW_OPT_LIBS, PO_STRING}, {KW_OPT_REQUIRED, PO_BOOL}, {KW_OPT_VERSION, PO_STRING} }; kwopt_t kw_chkpc = { req_name, sizeof(req_name) / sizeof(kw_t), opt_chkpc, sizeof(opt_chkpc) / sizeof(kw_t) }; /* CHECK_TYPE options */ kw_t opt_chktyp[] = { {KW_OPT_DEFS, PO_LIST}, {KW_OPT_DEPEND, PO_LIST}, {KW_OPT_HEADER, PO_STRING}, {KW_OPT_LANG, PO_STRING}, {KW_OPT_MEMBER, PO_STRING}, {KW_OPT_REQUIRED, PO_BOOL} }; kwopt_t kw_chktyp = { req_name, sizeof(req_name) / sizeof(kw_t), opt_chktyp, sizeof(opt_chktyp) / sizeof(kw_t) }; /* CHECK_VARIABLE options */ kw_t opt_chkvar[] = { {KW_OPT_DEFS, PO_LIST}, {KW_OPT_DEPEND, PO_LIST}, {KW_OPT_REQUIRED, PO_BOOL}, {KW_OPT_VALUE, PO_STRING} }; kwopt_t kw_chkvar = { req_name, sizeof(req_name) / sizeof(kw_t), opt_chkvar, sizeof(opt_chkvar) / sizeof(kw_t) }; /* BUILD_LIB_NAME options */ kw_t req_bldlib[] = { {KW_OPT_NAME, PO_STRING} }; kw_t opt_bldlib[] = { {KW_OPT_REQUIRED, PO_BOOL}, {KW_OPT_MAJOR, PO_STRING}, {KW_OPT_MINOR, PO_STRING}, {KW_SL_STATIC, PO_STRING}, {KW_SL_SHARED, PO_STRING}, {KW_SL_VERSION, PO_BOOL} }; kwopt_t kw_bldlib = { req_bldlib, sizeof(req_bldlib) / sizeof(kw_t), opt_bldlib, sizeof(opt_bldlib) / sizeof(kw_t) }; /* BUILD_SHLIB_NAME options */ kw_t req_bldshl[] = { {KW_OPT_NAME, PO_STRING} }; kw_t opt_bldshl[] = { {KW_OPT_REQUIRED, PO_BOOL}, {KW_OPT_MAJOR, PO_STRING}, {KW_OPT_MINOR, PO_STRING}, {KW_SL_VERS_FULL, PO_STRING}, {KW_SL_VERS_NONE, PO_STRING} }; kwopt_t kw_bldshl = { req_bldshl, sizeof(req_bldshl) / sizeof(kw_t), opt_bldshl, sizeof(opt_bldshl) / sizeof(kw_t) }; /* keyword list */ prskw kw_pmkfile[] = { {"DEFINE", PMK_TOK_DEFINE, PRS_KW_NODE, PMK_TOK_SETVAR, NULL}, {"SETTINGS", PMK_TOK_SETNGS, PRS_KW_NODE, PMK_TOK_SETPRM, NULL}, {"IF", PMK_TOK_IFCOND, PRS_KW_NODE, PRS_TOK_NULL, NULL}, {"ELSE", PMK_TOK_ELCOND, PRS_KW_NODE, PRS_TOK_NULL, NULL}, {"SWITCHES", PMK_TOK_SWITCH, PRS_KW_CELL, PRS_TOK_NULL, NULL}, {"CHECK_BINARY", PMK_TOK_CHKBIN, PRS_KW_CELL, PRS_TOK_NULL, &kw_chkbin}, {"CHECK_HEADER", PMK_TOK_CHKINC, PRS_KW_CELL, PRS_TOK_NULL, &kw_chkhdr}, {"CHECK_LIB", PMK_TOK_CHKLIB, PRS_KW_CELL, PRS_TOK_NULL, &kw_chklib}, {"CHECK_CONFIG", PMK_TOK_CHKCFG, PRS_KW_CELL, PRS_TOK_NULL, &kw_chkcfg}, {"CHECK_PKG_CONFIG", PMK_TOK_CHKPKG, PRS_KW_CELL, PRS_TOK_NULL, &kw_chkpc}, {"CHECK_TYPE", PMK_TOK_CHKTYP, PRS_KW_CELL, PRS_TOK_NULL, &kw_chktyp}, {"CHECK_VARIABLE", PMK_TOK_CHKVAR, PRS_KW_CELL, PRS_TOK_NULL, &kw_chkvar}, {"BUILD_LIB_NAME", PMK_TOK_BLDLIB, PRS_KW_CELL, PRS_TOK_NULL, &kw_bldlib}, {"BUILD_SHLIB_NAME", PMK_TOK_BLDSLN, PRS_KW_CELL, PRS_TOK_NULL, &kw_bldshl} }; size_t nbkwpf = sizeof(kw_pmkfile) / sizeof(prskw); /****************** * misc functions * ***********************************************************************/ /***************** * func_wrapper()* *********************************************************************** DESCR wrapper from token to functions IN pcell : cell structure pgd : global data OUT boolean ***********************************************************************/ bool func_wrapper(prscell *pcell, pmkdata *pgd) { bool rval; pmkcmd cmd; cmd.token = pcell->token; cmd.label = pcell->label; switch (cmd.token) { case PMK_TOK_DEFINE : rval = pmk_define(&cmd, pcell->data, pgd); break; case PMK_TOK_SWITCH : rval = pmk_switches(&cmd, pcell->data, pgd); break; case PMK_TOK_SETNGS : rval = pmk_settings(&cmd, pcell->data, pgd); break; case PMK_TOK_IFCOND : rval = pmk_ifcond(&cmd, pcell->data, pgd); break; case PMK_TOK_ELCOND : rval = pmk_elcond(&cmd, pcell->data, pgd); break; case PMK_TOK_SETVAR : rval = pmk_set_variable(&cmd, pcell->data, pgd); break; case PMK_TOK_SETPRM : rval = pmk_set_parameter(&cmd, pcell->data, pgd); break; case PMK_TOK_CHKBIN : rval = pmk_check_binary(&cmd, pcell->data, pgd); break; case PMK_TOK_CHKINC : rval = pmk_check_header(&cmd, pcell->data, pgd); break; case PMK_TOK_CHKLIB : rval = pmk_check_lib(&cmd, pcell->data, pgd); break; case PMK_TOK_CHKCFG : rval = pmk_check_config(&cmd, pcell->data, pgd); break; case PMK_TOK_CHKPKG : rval = pmk_check_pkg_config(&cmd, pcell->data, pgd); break; case PMK_TOK_CHKTYP : rval = pmk_check_type(&cmd, pcell->data, pgd); break; case PMK_TOK_CHKVAR : rval = pmk_check_variable(&cmd, pcell->data, pgd); break; case PMK_TOK_BLDLIB : rval = pmk_build_lib_name(&cmd, pcell->data, pgd); break; case PMK_TOK_BLDSLN : rval = pmk_build_shlib_name(&cmd, pcell->data, pgd); break; default : errorf("unknown token %d", cmd.token); rval = false; } return(rval); } /****************** * process_node() * *********************************************************************** DESCR processing of given node IN pnode : node structure pgd : global data OUT boolean ***********************************************************************/ bool process_node(prsnode *pnode, pmkdata *pgd) { prscell *pcell; /* init pcell with the first cell of pdata */ pcell = pnode->first; while (pcell != NULL) { if (func_wrapper(pcell, pgd) == false) return(false); pcell = pcell->next; } return(true); } /***************** * node functions * * IN * cmd : command structure * pnode : node structure * pgd : global data * * OUT * boolean ***********************************************************************/ /**************** * pmk_define() * *********************************************************************** DESCR define variables ***********************************************************************/ bool pmk_define(pmkcmd *cmd, prsnode *pnode, pmkdata *pgd) { pmk_log("\n* Parsing define\n"); return(process_node(pnode, pgd)); } /****************** * pmk_settings() * *********************************************************************** DESCR pmk settings ***********************************************************************/ bool pmk_settings(pmkcmd *cmd, prsnode *pnode, pmkdata *pgd) { pmk_log("\n* Parsing settings\n"); return(process_node(pnode, pgd)); } /**************** * pmk_ifcond() * *********************************************************************** DESCR if condition ***********************************************************************/ bool pmk_ifcond(pmkcmd *cmd, prsnode *pnode, pmkdata *pgd) { if (label_check(pgd->labl, cmd->label) == true) { pmk_log("\n< Begin of 'IF' condition [%s]\n", cmd->label); process_node(pnode, pgd); pmk_log("\n> End of 'IF' condition [%s]\n", cmd->label); } else { pmk_log("\n- Skipping 'IF' condition [%s]\n", cmd->label); } return(true); } /**************** * pmk_elcond() * *********************************************************************** DESCR else condition ***********************************************************************/ bool pmk_elcond(pmkcmd *cmd, prsnode *pnode, pmkdata *pgd) { if (label_check(pgd->labl, cmd->label) == false) { pmk_log("\n< Begin of 'ELSE' condition [%s]\n", cmd->label); process_node(pnode, pgd); pmk_log("\n> End of 'ELSE' condition [%s]\n", cmd->label); } else { pmk_log("\n- Skipping 'ELSE' condition [%s]\n", cmd->label); } return(true); } /***************** * cell functions * * IN * cmd : command structure * ht : command options * pgd : global data * * OUT * boolean ***********************************************************************/ /****************** * pmk_switches() * *********************************************************************** DESCR switches ***********************************************************************/ bool pmk_switches(pmkcmd *cmd, htable *ht, pmkdata *pgd) { char *value; hkeys *phk; pmkobj *po; unsigned int i, n = 0; pmk_log("\n* Parsing switches\n"); phk = hash_keys(ht); for(i = 0 ; i < phk->nkey ; i++) { if (hash_get(pgd->labl, phk->keys[i]) == NULL) { po = hash_get(ht, phk->keys[i]); switch(po_get_type(po)) { case PO_BOOL : value = bool_to_str(po_get_bool(po)); break; case PO_STRING : value = po_get_str(po); break; default : errorf("bad type for switch '%s'.", phk->keys[i]); return(false); break; } if (hash_update_dup(pgd->labl, phk->keys[i], value) != HASH_ADD_FAIL) { pmk_log("\tAdded '%s' switch.\n", phk->keys[i]); n++; } else { errorf(HASH_ERR_UPDT_ARG, phk->keys[i]); return(false); } } else { pmk_log("\tSkipped '%s' switch (overriden).\n", phk->keys[i]); } } pmk_log("\tTotal %d switch(es) added.\n", n); hash_free_hkeys(phk); return(true); } /********************** * pmk_check_binary() * *********************************************************************** DESCR check binary ***********************************************************************/ bool pmk_check_binary(pmkcmd *cmd, htable *ht, pmkdata *pgd) { bool required, rslt; char *filename, *varname, *vtmp, *bpath, binpath[MAXPATHLEN]; pmk_log("\n* Checking binary [%s]\n", cmd->label); required = require_check(ht); filename = po_get_str(hash_get(ht, KW_OPT_NAME)); if (filename == NULL) { errorf("NAME not assigned in label '%s'", cmd->label); return(false); } record_def_adv(pgd->htab, TAG_TYPE_BIN, filename, NULL, NULL, NULL); /* check if a variable name is given */ varname = po_get_str(hash_get(ht, KW_OPT_VARIABLE)); if (varname == NULL) { vtmp = conv_to_tag(filename); if (vtmp == NULL) { errorf("failed to generate definition name for " "'%s' in label '%s'", filename, cmd->label); return(false); } /* if not then use default naming scheme */ varname = strdup(vtmp); if (varname == NULL) { errorf(ERRMSG_MEM); return(false); } } bpath = hash_get(pgd->htab, PMKCONF_PATH_BIN); if (bpath == NULL) { errorf("%s not available.", PMKCONF_PATH_BIN); return(false); } if (depend_check(ht, pgd) == false) { pmk_log("\t%s\n", pgd->errmsg); return(process_required(pgd, cmd, required, filename, NULL)); } /* try to locate binary */ pmk_log("\tFound binary '%s' : ", filename); if (get_file_path(filename, bpath, binpath, sizeof(binpath)) == false) { pmk_log("no.\n"); rslt = process_required(pgd, cmd, required, filename, NULL); if (rslt == true) { /* set path as empty for the key given by varname */ if (hash_update_dup(pgd->htab, varname, "") == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, varname); return(false); } } return(rslt); } else { pmk_log("yes.\n"); /* define for template */ record_def_data(pgd->htab, filename, DEFINE_DEFAULT); record_def_adv(pgd->htab, TAG_TYPE_BIN, filename, NULL, NULL, binpath); /* recording path of config tool under the key given by varname */ if (hash_update_dup(pgd->htab, varname, binpath) == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, varname); return(false); } label_set(pgd->labl, cmd->label, true); return(true); } } /********************** * pmk_check_header() * *********************************************************************** DESCR check header file ***********************************************************************/ bool pmk_check_header(pmkcmd *cmd, htable *ht, pmkdata *pgd) { bool required, rslt = true, rbis, rval; char inc_path[MAXPATHLEN] = "", *lang, *pstr, *target = NULL; code_bld_t scb; dynary *funcs, *macros, *shdrs, *defs; int i, n; pmk_log("\n* Checking header [%s]\n", cmd->label); code_bld_init(&scb, pgd->buildlog); required = require_check(ht); /* get include filename */ pstr = po_get_str(hash_get(ht, KW_OPT_NAME)); if (pstr == NULL) { errorf("%s not assigned in label '%s'", KW_OPT_NAME, cmd->label); return(false); } scb.header = pstr; record_def_data(pgd->htab, scb.header, NULL); record_def_adv(pgd->htab, TAG_TYPE_HDR, scb.header, NULL, NULL, NULL); /* any macro(s) to check ? */ macros = po_get_list(hash_get(ht, KW_OPT_MACRO)); if (macros != NULL) { for (i = 0 ; i < (int) da_usize(macros) ; i++) { pstr = da_idx(macros, i); record_def_data(pgd->htab, pstr, NULL); record_def_adv(pgd->htab, TAG_TYPE_HDR_MCR, scb.header, pstr, NULL, NULL); } } /* optional header sub dependencies */ shdrs = po_get_list(hash_get(ht, KW_OPT_SUBHDR)); /* check if a function or more must be searched */ obsolete_string_to_list(ht, KW_OPT_FUNCTION); funcs = po_get_list(hash_get(ht, KW_OPT_FUNCTION)); if (funcs != NULL) { n = da_usize(funcs); for (i = 0 ; i < n ; i++) { pstr = da_idx(funcs, i); record_def_data(pgd->htab, pstr, NULL); record_def_adv(pgd->htab, TAG_TYPE_HDR_PRC, scb.header, pstr, NULL, NULL); } } /* look for additional defines */ defs = po_get_list(hash_get(ht, KW_OPT_DEFS)); if (process_def_list(pgd->htab, defs, false) == false) { return(false); } if (depend_check(ht, pgd) == false) { pmk_log("\t%s\n", pgd->errmsg); return(process_required(pgd, cmd, required, NULL, NULL)); } /* get language */ lang = get_lang_str(ht, pgd); if (lang == NULL) { errorf("Failed, language has not been set."); return(false); } /* init build structure */ if (set_language(&scb, lang) == false) { pmk_log("\tSkipped, unknown language '%s'.\n", lang); return(process_required(pgd, cmd, required, NULL, NULL)); } /* get the appropriate compiler */ pstr = set_compiler(&scb, pgd->htab); if (pstr == NULL) { pmk_log("\tSkipped, cannot get compiler path for language '%s'.\n", lang); return(process_required(pgd, cmd, required, NULL, NULL)); } pmk_log("\tUse %s language with %s compiler.\n", lang, pstr); /* check for alternative variable for CFLAGS */ pstr = po_get_str(hash_get(ht, PMKVAL_ENV_CFLAGS)); if (pstr != NULL) { /* init alternative variable */ if (hash_get(pgd->htab, pstr) == NULL) { if (hash_update_dup(pgd->htab, pstr, "") == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, pstr); return(false); } } scb.alt_cflags = pstr; } pmk_log("\tStore compiler flags in '%s'.\n", get_cflags_label(&scb)); /* use each element of INC_PATH with -I */ pstr = (char *) hash_get(pgd->htab, PMKCONF_PATH_INC); if (pstr == NULL) { errorf("%s not available.", PMKCONF_PATH_INC); return(false); } if (get_file_dir_path(scb.header, pstr, inc_path, sizeof(inc_path)) == true) { pstr = strdup(inc_path); if (pstr == NULL) { errorf(ERRMSG_MEM); return(false); } strlcpy(inc_path, "-I", sizeof(inc_path)); /* no check */ if (strlcat_b(inc_path, pstr, sizeof(inc_path)) == false) { errorf("failed to add '%s' in include path.", inc_path); return(false); } } else { /* include not found, init inc_path with "" */ if (strlcpy_b(inc_path, "", sizeof(inc_path)) == false) { errorf("failed to initialise include path."); return(false); } } set_cflags(&scb, inc_path); /* check header file */ pmk_log("\tFound header '%s' : ", scb.header); /* build test source file */ if (code_builder(&scb) == false) { errorf("cannot build test file."); return(false); } /* build compiler command */ if (cmdline_builder(&scb, LINK_SRC) == false) { errorf(ERR_MSG_CC_CMD); return(false); } /* launch build and get result */ rslt = object_builder(&scb); /* clean files */ cb_cleaner(&scb); /* if result is false and dependency headers are provided */ if ((rslt == false) && (shdrs != NULL)) { /* output result of previous test */ pmk_log("no.\n"); /* check header file with sub headers */ pmk_log("\tFound header '%s' using dependency headers : ", scb.header); scb.subhdrs = shdrs; /* build test source file */ if (code_builder(&scb) == false) { errorf("cannot build test file."); return(false); } /* build compiler command */ if (cmdline_builder(&scb, LINK_SRC) == false) { errorf(ERR_MSG_CC_CMD); return(false); } /* launch build and get result */ rslt = object_builder(&scb); /* clean files */ cb_cleaner(&scb); /* XXX TODO set sub header flag ? */ } /* process result */ if (rslt == false) { pmk_log("no.\n"); return(process_required(pgd, cmd, required, NULL, NULL)); } pmk_log("yes.\n"); /* define for template */ record_def_data(pgd->htab, scb.header, DEFINE_DEFAULT); record_def_adv(pgd->htab, TAG_TYPE_HDR, scb.header, NULL, NULL, DEFINE_DEFAULT); /* check macros in header file */ if (macros != NULL) { while ((target = da_shift(macros)) && (target != NULL)) { /* init rbis */ rbis = false; /* if header is okay */ pmk_log("\tFound macro '%s' : ", target); scb.define = target; /* fill test file */ if (code_builder(&scb) == false) { errorf("cannot build test file."); return(false); } /* build compiler command */ if (cmdline_builder(&scb, LINK_SRC) == false) { errorf(ERR_MSG_CC_CMD); return(false); } /* launch build and get result */ rbis = object_builder(&scb); /* clean files */ cb_cleaner(&scb); /* process result */ if (rbis == true) { pmk_log("yes.\n"); /* define for template */ record_def_data(pgd->htab, target, DEFINE_DEFAULT); record_def_adv(pgd->htab, TAG_TYPE_HDR_MCR, scb.header, target, NULL, DEFINE_DEFAULT); } else { pmk_log("no.\n"); rslt = false; } } /* reset define */ scb.define = NULL; } /* check functions in header file */ if (funcs != NULL) { while ((target = da_shift(funcs)) && (target != NULL)) { /* test each function */ pmk_log("\tFound function '%s' : ", target); scb.procedure = target; /* fill test file */ if (code_builder(&scb) == false) { errorf("cannot build test file."); return(false); } if (cmdline_builder(&scb, LINK_SRC) == false) { errorf(ERR_MSG_CC_CMD); return(false); } /* launch build and get result */ rbis = object_builder(&scb); /* clean files */ cb_cleaner(&scb); /* process result */ if (rbis == true) { pmk_log("yes.\n"); /* define for template */ record_def_data(pgd->htab, target, DEFINE_DEFAULT); record_def_adv(pgd->htab, TAG_TYPE_HDR_PRC, scb.header, target, NULL, DEFINE_DEFAULT); } else { pmk_log("no.\n"); rslt = false; } } } if (rslt == true) { label_set(pgd->labl, cmd->label, true); /* process additional defines */ if (process_def_list(pgd->htab, defs, true) == false) { return(false); } /* put result in CFLAGS, CXXFLAGS or alternative variable */ if (single_append(pgd->htab, get_cflags_label(&scb), strdup(inc_path)) == false) { errorf("failed to append '%s' in '%s'.", inc_path, get_cflags_label(&scb)); return(false); } rval = true; } else { rval = process_required(pgd, cmd, required, NULL, NULL); } return(rval); } /******************* * pmk_check_lib() * *********************************************************************** DESCR check library ***********************************************************************/ bool pmk_check_lib(pmkcmd *cmd, htable *ht, pmkdata *pgd) { bool required, rbis, rslt = true, rval; char lib_buf[TMP_BUF_LEN] = "", lib_path[TMP_BUF_LEN] = "", *lang, pattern[TMP_BUF_LEN] = "", *pstr, *target = NULL; code_bld_t scb; dynary *da, *funcs, *defs; int i, n; pmk_log("\n* Checking library [%s]\n", cmd->label); code_bld_init(&scb, pgd->buildlog); required = require_check(ht); pstr = po_get_str(hash_get(ht, KW_OPT_NAME)); if (pstr == NULL) { errorf("NAME not assigned in label '%s'.", cmd->label); return(false); } scb.library = pstr; snprintf(lib_buf, sizeof(lib_buf), "lib%s", scb.library); record_def_data(pgd->htab, lib_buf, NULL); record_def_adv(pgd->htab, TAG_TYPE_LIB, scb.library, NULL, NULL, NULL); /* check if a function or more must be searched */ obsolete_string_to_list(ht, KW_OPT_FUNCTION); funcs = po_get_list(hash_get(ht, KW_OPT_FUNCTION)); if (funcs != NULL) { n = da_usize(funcs); for (i = 0 ; i < n ; i++) { pstr = da_idx(funcs, i); record_def_data(pgd->htab, pstr, NULL); record_def_adv(pgd->htab, TAG_TYPE_LIB_PRC, scb.library, pstr, NULL, NULL); } } /* look for additional defines */ defs = po_get_list(hash_get(ht, KW_OPT_DEFS)); if (process_def_list(pgd->htab, defs, false) == false) { return(false); } if (depend_check(ht, pgd) == false) { pmk_log("\t%s\n", pgd->errmsg); return(process_required(pgd, cmd, required, NULL, NULL)); } /* get language */ lang = get_lang_str(ht, pgd); if (lang == NULL) { errorf("Failed, language has not been set."); return(false); } /* init build structure */ if (set_language(&scb, lang) == false) { pmk_log("\tSkipped, unknown language '%s'.\n", lang); return(process_required(pgd, cmd, required, NULL, NULL)); } /* get the appropriate compiler */ pstr = set_compiler(&scb, pgd->htab); if (pstr == NULL) { pmk_log("\tSkipped, cannot get compiler path for language '%s'.\n", lang); return(process_required(pgd, cmd, required, NULL, NULL)); } pmk_log("\tUse %s language with %s compiler.\n", lang, pstr); if (rslt == true) { /* check for alternative variable for LIBS */ pstr = po_get_str(hash_get(ht, KW_OPT_LIBS)); if (pstr != NULL) { /* init alternative variable */ if (hash_get(pgd->htab, pstr) == NULL) { if (hash_update_dup(pgd->htab, pstr, "") == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, pstr); return(false); } } scb.alt_libs = pstr; } pmk_log("\tStore library flags in '%s'.\n", get_libs_label(&scb)); /* get actual content of LIBS, no need to check as it is initialised */ set_cflags(&scb, hash_get(pgd->htab, PMKVAL_ENV_LIBS)); } /* get the list of library path */ pstr = (char *) hash_get(pgd->htab, PMKCONF_PATH_LIB); if (pstr == NULL) { errorf("%s not available.", PMKCONF_PATH_LIB); return(false); } /* convert to dynary */ da = str_to_dynary(pstr, PATH_STR_DELIMITER); if (da == NULL) { errorf("unable to convert '%s'",PMKCONF_PATH_LIB); return(false); } /* generate library pattern */ snprintf(pattern, sizeof(pattern), "lib%s*.*", scb.library); /* parse list of path to find the pattern */ if (find_pattern(da, pattern, lib_buf, sizeof(lib_buf)) == true) { snprintf(lib_path, sizeof(lib_path), "-L%s", lib_buf); set_ldflags(&scb, lib_path); } /* clean dynary now useless */ da_destroy(da); /* check library */ pmk_log("\tFound library '%s' : ", scb.library); /* build test source file */ if (code_builder(&scb) == false) { errorf("cannot build test file."); return(false); } /* build compiler command */ if (cmdline_builder(&scb, LINK_SRC) == false) { errorf(ERR_MSG_CC_CMD); return(false); } /* launch build and get result */ rslt = object_builder(&scb); /* clean files */ cb_cleaner(&scb); /* process result */ if (rslt == false) { pmk_log("no.\n"); return(process_required(pgd, cmd, required, NULL, NULL)); } pmk_log("yes.\n"); /* define for template */ record_def_data(pgd->htab, scb.library, DEFINE_DEFAULT); record_def_adv(pgd->htab, TAG_TYPE_LIB, scb.library, pstr, NULL, DEFINE_DEFAULT); /* check functions */ if (funcs != NULL) { while ((target = da_shift(funcs)) && (target != NULL)) { /* test each function */ pmk_log("\tFound function '%s' : ", target); scb.procedure = target; /* build test source file */ if (code_builder(&scb) == false) { errorf("cannot build test file."); return(false); } /* build compiler command */ if (cmdline_builder(&scb, LINK_SRC) == false) { errorf(ERR_MSG_CC_CMD); return(false); } /* launch build and get result */ rbis = object_builder(&scb); /* clean files */ cb_cleaner(&scb); /* process result */ if (rbis == true) { pmk_log("yes.\n"); /* define for template */ record_def_data(pgd->htab, target, DEFINE_DEFAULT); record_def_adv(pgd->htab, TAG_TYPE_LIB_PRC, scb.library, target, NULL, DEFINE_DEFAULT); } else { pmk_log("no.\n"); rslt = false; } } } if (rslt == true) { label_set(pgd->labl, cmd->label, true); /* process additional defines */ if (process_def_list(pgd->htab, defs, true) == false) { return(false); } if (scb.ldflags != NULL) { if (snprintf_b(lib_buf, sizeof(lib_buf), "%s -l%s", scb.ldflags, scb.library) == false) { errorf("failed to build library path or name."); return(false); } } else { if (snprintf_b(lib_buf, sizeof(lib_buf), "-l%s", scb.library) == false) { errorf("failed to build library name."); return(false); } } /* put result in LIBS or alternative variable */ if (single_append(pgd->htab, get_libs_label(&scb), strdup(lib_buf)) == false) { errorf("failed to append '%s' in '%s'.", lib_buf, get_libs_label(&scb)); return(false); } rval = true; } else { rval = process_required(pgd, cmd, required, NULL, NULL); } return(rval); } /********************** * pmk_check_config() * *********************************************************************** DESCR check with *-config utility ***********************************************************************/ bool pmk_check_config(pmkcmd *cmd, htable *ht, pmkdata *pgd) { bool required = true, rval = false; char pipebuf[TMP_BUF_LEN], cfgpath[MAXPATHLEN], *bpath, *cfgtool, *cflags, *lang, *libs, *libvers, *modname, *opt, *varname, *vtmp; code_bld_t scb; dynary *defs; cfgtcell *pcc = NULL; pmk_log("\n* Checking with config tool [%s]\n", cmd->label); code_bld_init(&scb, pgd->buildlog); required = require_check(ht); cfgtool = po_get_str(hash_get(ht, KW_OPT_NAME)); if (cfgtool == NULL) { errorf("NAME not assigned in label '%s'.", cmd->label); return(false); } record_def_adv(pgd->htab, TAG_TYPE_CFGTOOL, cfgtool, NULL, NULL, NULL); /* check dependencies */ if (depend_check(ht, pgd) == false) { pmk_log("\t%s\n", pgd->errmsg); return(process_required(pgd, cmd, required, cfgtool, NULL)); } /* check if a module name is given */ modname = po_get_str(hash_get(ht, KW_OPT_MODULE)); /* check if a variable name is given */ varname = po_get_str(hash_get(ht, KW_OPT_VARIABLE)); if (varname == NULL) { vtmp = conv_to_tag(cfgtool); if (vtmp == NULL) { errorf("VARIABLE not assigned in label '%s'.", cmd->label); return(false); } /* if not then use default naming scheme */ varname = strdup(vtmp); if (varname == NULL) { errorf(ERRMSG_MEM); return(false); } } bpath = hash_get(pgd->htab, PMKCONF_PATH_BIN); if (bpath == NULL) { errorf("%s not available.", PMKCONF_PATH_BIN); return(false); } /* get language */ lang = get_lang_str(ht, pgd); if (lang == NULL) { errorf("Failed, language has not been set."); return(false); } /* init build structure */ if (set_language(&scb, lang) == false) { pmk_log("\tSkipped, unknown language '%s'.\n", lang); return(process_required(pgd, cmd, required, NULL, NULL)); } /* look for additional defines */ defs = po_get_list(hash_get(ht, KW_OPT_DEFS)); if (process_def_list(pgd->htab, defs, false) == false) { return(false); } /* check for alternative variable for CFLAGS */ cflags = po_get_str(hash_get(ht, PMKVAL_ENV_CFLAGS)); if (cflags != NULL) { /* init alternative variable */ if (hash_get(pgd->htab, cflags) == NULL) { if (hash_update_dup(pgd->htab, cflags, "") == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, cflags); return(false); } } } else { /* use default variable of the used language */ cflags = get_cflags_label(&scb); } /* check for alternative variable for LIBS */ libs = po_get_str(hash_get(ht, KW_OPT_LIBS)); if (libs != NULL) { /* init alternative variable */ if (hash_get(pgd->htab, libs) == NULL) { if (hash_update_dup(pgd->htab, libs, "") == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, libs); return(false); } } } else { /* use default library variable */ libs = PMKVAL_ENV_LIBS; } /* try to locate cfgtool */ pmk_log("\tFound config tool '%s' : ", cfgtool); if (get_file_path(cfgtool, bpath, cfgpath, sizeof(cfgpath)) == false) { pmk_log("no.\n"); rval = process_required(pgd, cmd, required, cfgtool, NULL); if (rval == true) { /* set path as empty for the key given by varname */ if (hash_update_dup(pgd->htab, varname, "") == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, varname); return(false); } } return(rval); } else { pmk_log("yes.\n"); /* recording path of config tool under the key given by varname */ if (hash_update_dup(pgd->htab, varname, cfgpath) == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, varname); return(false); } } /* check if config tool data is loaded */ if (check_cfgt_data(pgd) == false) { errorf("unable to load config tool data."); return(false); } /* check if specific tool option exists */ pmk_log("\tUse specific options : "); pcc = cfgtcell_get_cell(pgd->cfgt, cfgtool); if (pcc != NULL) { pmk_log("yes\n"); } else { pmk_log("no\n"); } libvers = po_get_str(hash_get(ht, KW_OPT_VERSION)); /* if VERSION is provided then check it */ if (libvers != NULL) { /* check if specific option exists */ if ((pcc != NULL) && (pcc->version != NULL)) { opt = pcc->version; } else { opt = CFGTOOL_OPT_VERSION; } if (ct_get_version(cfgpath, opt, pipebuf, sizeof(pipebuf)) == false) { errorf("cannot get version from '%s'.", cfgpath); return(false); } else { pmk_log("\tFound version >= %s : ", libvers); if (compare_version(libvers, pipebuf) < 0) { /* version does not match */ pmk_log("no (%s).\n", pipebuf); return(process_required(pgd, cmd, required, cfgtool, NULL)); } else { pmk_log("yes (%s).\n", pipebuf); } } } /* record gathered data */ record_def_data(pgd->htab, cfgtool, DEFINE_DEFAULT); record_def_adv(pgd->htab, TAG_TYPE_CFGTOOL, cfgtool, NULL, NULL, DEFINE_DEFAULT); label_set(pgd->labl, cmd->label, true); /* process additional defines */ if (process_def_list(pgd->htab, defs, true) == false) { return(false); } /* check if specific option exists */ if ((pcc != NULL) && (pcc->cflags != NULL)) { opt = pcc->cflags; } else { opt = CFGTOOL_OPT_CFLAGS; } if (ct_get_data(cfgpath, opt, modname, pipebuf, sizeof(pipebuf)) == false) { errorf("cannot get CFLAGS."); return(false); } else { /* put result in CFLAGS, CXXFLAGS or alternative variable */ if (single_append(pgd->htab, cflags, strdup(pipebuf)) == false) { errorf("failed to append '%s' in '%s'.", pipebuf, cflags); return(false); } else { pmk_log("\tStored compiler flags in '%s'.\n", cflags); } } /* check if specific option exists */ if ((pcc != NULL) && (pcc->libs != NULL)) { opt = pcc->libs; } else { opt = CFGTOOL_OPT_LIBS; } if (ct_get_data(cfgpath, opt, "", pipebuf, sizeof(pipebuf)) == false) { errorf("cannot get LIBS."); return(false); } else { /* put result in LIBS or alternative variable */ if (single_append(pgd->htab, libs, strdup(pipebuf)) == false) { errorf("failed to append '%s' in '%s'.", pipebuf, libs); return(false); } else { pmk_log("\tStored library flags in '%s'.\n", libs); } } return(true); } /************************** * pmk_check_pkg_config() * *********************************************************************** DESCR check pkg-config module using internal support ***********************************************************************/ bool pmk_check_pkg_config(pmkcmd *cmd, htable *ht, pmkdata *pgd) { bool required = true; char pc_cmd[MAXPATHLEN], pc_buf[MAXPATHLEN], *bpath, *cflags, *lang, *libs, *libvers, *pc_path, *pipebuf, *pstr, *target; code_bld_t scb; dynary *defs; pkgcell *ppc; pkgdata *ppd; pmk_log("\n* Checking pkg-config module [%s]\n", cmd->label); code_bld_init(&scb, pgd->buildlog); required = require_check(ht); target = po_get_str(hash_get(ht, KW_OPT_NAME)); if (target == NULL) { errorf("NAME not assigned in label '%s'.", cmd->label); return(false); } record_def_adv(pgd->htab, TAG_TYPE_PKGCFG, target, NULL, NULL, NULL); /* check dependencies */ if (depend_check(ht, pgd) == false) { pmk_log("\t%s\n", pgd->errmsg); return(process_required(pgd, cmd, required, target, NULL)); } /* try to get pkg-config lib path from pmk.conf */ pstr = hash_get(pgd->htab, PMKCONF_PC_PATH_LIB); if (pstr == NULL) { pmk_log("\tUnable to get %s from %s.\n", PMKCONF_PC_PATH_LIB, PREMAKE_CONFIG_PATH); return(false); } pc_path = process_string(pstr, pgd->htab); if (pc_path == NULL) { pmk_log("\tUnable to find pkg-config libdir.\n"); pmk_log("\tWARNING : pkg-config may not be installed\n"); pmk_log("\t or pmk.conf need to be updated.\n"); return(false); } /* get language */ lang = get_lang_str(ht, pgd); if (lang == NULL) { errorf("Failed, language has not been set."); return(false); } /* init build structure */ if (set_language(&scb, lang) == false) { pmk_log("\tSkipped, unknown language '%s'.\n", lang); return(process_required(pgd, cmd, required, NULL, NULL)); } /* look for additional defines */ defs = po_get_list(hash_get(ht, KW_OPT_DEFS)); if (process_def_list(pgd->htab, defs, false) == false) { return(false); } /* check for alternative variable for CFLAGS */ cflags = po_get_str(hash_get(ht, PMKVAL_ENV_CFLAGS)); if (cflags != NULL) { /* init alternative variable */ if (hash_get(pgd->htab, cflags) == NULL) { if (hash_update_dup(pgd->htab, cflags, "") == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, cflags); return(false); } } } else { /* use default variable of the used language */ cflags = get_cflags_label(&scb); } /* check for alternative variable for LIBS */ libs = po_get_str(hash_get(ht, KW_OPT_LIBS)); if (libs != NULL) { /* init alternative variable */ if (hash_get(pgd->htab, libs) == NULL) { if (hash_update_dup(pgd->htab, libs, "") == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, libs); return(false); } } } else { /* use default library variable */ libs = PMKVAL_ENV_LIBS; } ppd = pkgdata_init(); if (ppd == NULL) { errorf("cannot init pkgdata."); return(false); } /* collect packages data */ if (pkg_collect(pc_path, ppd) == false) { pkgdata_destroy(ppd); errorf("cannot collect packages data"); return(false); } /* check if package exists */ pmk_log("\tFound package '%s' : ", target); if (pkg_mod_exists(ppd, target) == false) { pkgdata_destroy(ppd); pmk_log("no.\n"); /* get binary path */ bpath = hash_get(pgd->htab, PMKCONF_PATH_BIN); if (bpath == NULL) { errorf("%s not available.", PMKCONF_PATH_BIN); return(false); } /* check if config tool data is loaded */ if (check_cfgt_data(pgd) == false) { errorf("unable to load config tool data."); return(false); } /* set config tool filename */ if (cfgtcell_get_binary(pgd->cfgt, target, pc_cmd, sizeof(pc_cmd)) == false) { if (snprintf_b(pc_cmd, sizeof(pc_cmd), "%s-config", target) == false) { errorf("overflow in snprintf()."); return(false); } } /* looking for it in the path */ if (get_file_path(pc_cmd, bpath, pc_buf, sizeof(pc_buf)) == true) { /* use CHECK_CONFIG */ pmk_log("\tFound alternative '%s' tool.\n", pc_cmd); /* override NAME to use divert on CHECK_CONFIG */ hash_update(ht, KW_OPT_NAME, po_mk_str(pc_cmd)); pmk_log("\tWARNING: rerouting to CHECK_CONFIG\n"); pmk_log("\tPlease consider using directly CHECK_CONFIG with '%s'\n", pc_cmd); /* call pmk_check_config with the config tool */ return(pmk_check_config(cmd, ht, pgd)); } return(process_required(pgd, cmd, required, target, NULL)); } else { pmk_log("yes.\n"); } libvers = po_get_str(hash_get(ht, KW_OPT_VERSION)); if (libvers != NULL) { /* if VERSION is provided then check it */ ppc = pkg_cell_add(ppd, target); if (ppc == NULL) { pkgdata_destroy(ppd); errorf("cannot get version."); return(false); } else { pmk_log("\tFound version >= %s : ", libvers); pipebuf = ppc->version; if (compare_version(libvers, pipebuf) < 0) { /* version does not match */ pmk_log("no (%s).\n", pipebuf); pkgdata_destroy(ppd); return(process_required(pgd, cmd, required, target, NULL)); } else { pmk_log("yes (%s).\n", pipebuf); } } } /* gather data */ if (pkg_recurse(ppd, target) == false) { pkgdata_destroy(ppd); errorf("failed to gather packages data (pkg_recurse() function call)"); return(false); } /* record gathered data */ record_def_data(pgd->htab, target, DEFINE_DEFAULT); record_def_adv(pgd->htab, TAG_TYPE_PKGCFG, target, NULL, NULL, DEFINE_DEFAULT); label_set(pgd->labl, cmd->label, true); /* process additional defines */ if (process_def_list(pgd->htab, defs, true) == false) { return(false); } /* get cflags recursively */ pipebuf = pkg_get_cflags(ppd); if (pipebuf == NULL) { pkgdata_destroy(ppd); errorf("cannot get CFLAGS."); return(false); } else { /* put result in CFLAGS, CXXFLAGS or alternative variable */ if (single_append(pgd->htab, cflags, pipebuf) == false) { pkgdata_destroy(ppd); errorf("failed to append '%s' in '%s'.", pipebuf, cflags); return(false); } else { pmk_log("\tStored compiler flags in '%s'.\n", cflags); } } /* get libs recursively */ pipebuf = pkg_get_libs(ppd); if (pipebuf == NULL) { pkgdata_destroy(ppd); errorf("cannot get LIBS."); return(false); } else { /* put result in LIBS or alternative variable */ if (single_append(pgd->htab, libs, pipebuf) == false) { pkgdata_destroy(ppd); errorf("failed to append '%s' in '%s'.", pipebuf, libs); return(false); } else { pmk_log("\tStored library flags in '%s'.\n", libs); } } return(true); } /******************** * pmk_check_type() * *********************************************************************** DESCR check type ***********************************************************************/ bool pmk_check_type(pmkcmd *cmd, htable *ht, pmkdata *pgd) { bool required, rslt = true, rval; char inc_path[MAXPATHLEN] = "", *type, *member, *lang, *pstr; code_bld_t scb; dynary *defs; pmk_log("\n* Checking type [%s]\n", cmd->label); code_bld_init(&scb, pgd->buildlog); required = require_check(ht); /* get type name */ type = po_get_str(hash_get(ht, KW_OPT_NAME)); if (type == NULL) { errorf("%s not assigned in label '%s'", KW_OPT_NAME, cmd->label); return(false); } record_def_data(pgd->htab, type, NULL); record_def_adv(pgd->htab, TAG_TYPE_TYPE, type, NULL, NULL, NULL); /* check if an header must be used */ scb.header = po_get_str(hash_get(ht, KW_OPT_HEADER)); if (scb.header != NULL) { record_def_data(pgd->htab, scb.header, NULL); } /* check if a structure member is given */ member = po_get_str(hash_get(ht, KW_OPT_MEMBER)); if (member != NULL) { record_def_data(pgd->htab, member, NULL); } if (scb.header != NULL) { record_def_adv(pgd->htab, TAG_TYPE_HDR_TYPE, scb.header, type, NULL, NULL); if (member != NULL) { record_def_adv(pgd->htab, TAG_TYPE_HDR_TYP_MBR, scb.header, type, member, NULL); } } else { if (member != NULL) { record_def_adv(pgd->htab, TAG_TYPE_TYP_MBR, type, member, NULL, NULL); } } /* look for additional defines */ defs = po_get_list(hash_get(ht, KW_OPT_DEFS)); if (process_def_list(pgd->htab, defs, false) == false) { return(false); } if (depend_check(ht, pgd) == false) { pmk_log("\t%s\n", pgd->errmsg); return(process_required(pgd, cmd, required, NULL, NULL)); } /* get language */ lang = get_lang_str(ht, pgd); if (lang == NULL) { errorf("Failed, language has not been set."); return(false); } /* init build structure */ if (set_language(&scb, lang) == false) { pmk_log("\tSkipped, unknown language '%s'.\n", lang); return(process_required(pgd, cmd, required, NULL, NULL)); } /* get the appropriate compiler */ pstr = set_compiler(&scb, pgd->htab); if (pstr == NULL) { pmk_log("\tSkipped, cannot get compiler path for language '%s'.\n", lang); return(process_required(pgd, cmd, required, NULL, NULL)); } pmk_log("\tUse %s language with %s compiler.\n", lang, pstr); /* check optional header */ if (scb.header != NULL) { /* use each element of INC_PATH with -I */ pstr = (char *) hash_get(pgd->htab, PMKCONF_PATH_INC); if (pstr == NULL) { errorf("%s not available.", PMKCONF_PATH_INC); return(false); } if (get_file_dir_path(scb.header, pstr, inc_path, sizeof(inc_path)) == true) { pstr = strdup(inc_path); if (pstr == NULL) { errorf(ERRMSG_MEM); return(false); } strlcpy(inc_path, "-I", sizeof(inc_path)); /* no check */ if (strlcat_b(inc_path, pstr, sizeof(inc_path)) == false) { errorf("failed to add '%s' in include path.", inc_path); return(false); } } else { /* include not found, init inc_path with "" */ if (strlcpy_b(inc_path, "", sizeof(inc_path)) == false) { errorf("failed to initialise include path."); return(false); } } set_cflags(&scb, inc_path); /* check header file */ pmk_log("\tFound header '%s' : ", scb.header); /* build test source file */ if (code_builder(&scb) == false) { errorf("cannot build test file."); return(false); } /* build compiler command */ if (cmdline_builder(&scb, LINK_SRC) == false) { errorf(ERR_MSG_CC_CMD); return(false); } /* launch build and get result */ rslt = object_builder(&scb); /* clean files */ cb_cleaner(&scb); /* process result */ if (rslt == false) { pmk_log("no.\n"); return(process_required(pgd, cmd, required, NULL, NULL)); } pmk_log("yes.\n"); /* define for template */ record_def_data(pgd->htab, scb.header, DEFINE_DEFAULT); record_def_adv(pgd->htab, TAG_TYPE_HDR_TYPE, scb.header, type, NULL, DEFINE_DEFAULT); } scb.type = type; pmk_log("\tFound type '%s' : ", scb.type); /* build test source file */ if (code_builder(&scb) == false) { errorf("cannot build test file."); return(false); } /* build compiler command */ if (cmdline_builder(&scb, LINK_SRC) == false) { errorf(ERR_MSG_CC_CMD); return(false); } /* launch build and get result */ rslt = object_builder(&scb); /* clean files */ cb_cleaner(&scb); /* process result */ if (rslt == false) { pmk_log("no.\n"); return(process_required(pgd, cmd, required, NULL, NULL)); } pmk_log("yes.\n"); /* define for template */ record_def_data(pgd->htab, type, DEFINE_DEFAULT); record_def_adv(pgd->htab, TAG_TYPE_TYPE, type, NULL, NULL, DEFINE_DEFAULT); /* check optional member */ if (member != NULL) { scb.member = member; pmk_log("\tFound member '%s' : ", scb.member); /* build test source file */ if (code_builder(&scb) == false) { errorf("cannot build test file."); return(false); } /* build compiler command */ if (cmdline_builder(&scb, LINK_SRC) == false) { errorf(ERR_MSG_CC_CMD); return(false); } /* clean files */ cb_cleaner(&scb); /* process result */ if (rslt == false) { pmk_log("no.\n"); return(process_required(pgd, cmd, required, NULL, NULL)); } pmk_log("yes.\n"); /* define for template */ record_def_data(pgd->htab, member, DEFINE_DEFAULT); record_def_adv(pgd->htab, TAG_TYPE_HDR_TYPE, type, member, NULL, DEFINE_DEFAULT); if (scb.header != NULL) { record_def_adv(pgd->htab, TAG_TYPE_HDR_TYP_MBR, scb.header, type, member, DEFINE_DEFAULT); } } if (rslt == true) { label_set(pgd->labl, cmd->label, true); /* process additional defines */ if (process_def_list(pgd->htab, defs, true) == false) { return(false); } rval = true; } else { rval = process_required(pgd, cmd, required, scb.type, NULL); } return(rval); } /************************ * pmk_check_variable() * *********************************************************************** DESCR check if variable exists and optionally it's value ***********************************************************************/ bool pmk_check_variable(pmkcmd *cmd, htable *ht, pmkdata *pgd) { bool required, rval = false; char *var, *value, *varval; dynary *defs; pmk_log("\n* Checking variable [%s]\n", cmd->label); required = require_check(ht); var = po_get_str(hash_get(ht, KW_OPT_NAME)); if (var == NULL) { errorf("NAME not assigned in label '%s'", cmd->label); return(false); } /* look for additional defines */ defs = po_get_list(hash_get(ht, KW_OPT_DEFS)); if (process_def_list(pgd->htab, defs, false) == false) { return(false); } if (depend_check(ht, pgd) == false) { pmk_log("\t%s\n", pgd->errmsg); return(process_required(pgd, cmd, required, var, NULL)); } pmk_log("\tFound variable '%s' : ", var); /* trying to get variable */ varval = hash_get(pgd->htab, var); if (varval != NULL) { pmk_log("yes.\n"); value = po_get_str(hash_get(ht, KW_OPT_VALUE)); if (value == NULL) { label_set(pgd->labl, cmd->label, true); /* process additional defines */ if (process_def_list(pgd->htab, defs, true) == false) { return(false); } rval = true; } else { pmk_log("\tVariable match value '%s' : ", value); if (strncmp(value, varval, sizeof(varval)) == 0) { pmk_log("yes.\n"); label_set(pgd->labl, cmd->label, true); if (process_def_list(pgd->htab, defs, true) == false) { return(false); } rval = true; } else { pmk_log("no.\n"); rval = process_required(pgd, cmd, required, NULL, NULL); if (rval == false) { errorf("variable value does not match ('%s' != '%s').", value, varval); } } } } else { pmk_log("no.\n"); rval = process_required(pgd, cmd, required, NULL, NULL); if (rval == false) { errorf("failed to find variable '%s'.", var); } } return(rval); } /************************ * pmk_build_lib_name() * *********************************************************************** DESCR build names of a library ***********************************************************************/ bool pmk_build_lib_name(pmkcmd *cmd, htable *ht, pmkdata *pgd) { bool required, versbool; char *shvar = NULL, *stvar = NULL, *pstr, *value; pmkobj *po; pmk_log("\n* Building library name\n"); required = require_check(ht); pmk_log("\tShared library support : "); if (pgd->sys_detect == false) { pmk_log("no.\n"); return(process_required(pgd, cmd, required, NULL, NULL)); } pmk_log("yes.\n"); pstr = hash_get(pgd->htab, SL_SYS_LABEL); pmk_log("\tUsing support for '%s'.\n", pstr); /* get name (REQUIRED) */ pstr = po_get_str(hash_get(ht, KW_OPT_NAME)); if (pstr == NULL) { errorf("NAME not assigned in label '%s'", cmd->label); return(false); } #ifdef SHLIB_DEBUG debugf("pstr(name) = '%s'", pstr); #endif value = process_string(pstr, pgd->htab); #ifdef SHLIB_DEBUG debugf("value = '%s'", value); #endif hash_update(pgd->htab, LIB_KW_NAME, value); /* get major version number */ pstr = po_get_str(hash_get(ht, KW_OPT_MAJOR)); if (pstr != NULL) { #ifdef SHLIB_DEBUG debugf("pstr(major) = '%s'", pstr); #endif value = process_string(pstr, pgd->htab); #ifdef SHLIB_DEBUG debugf("value = '%s'", value); #endif hash_update(pgd->htab, LIB_KW_MAJ, value); /* no dup */ } /* get minor version number */ pstr = po_get_str(hash_get(ht, KW_OPT_MINOR)); if (pstr != NULL) { #ifdef SHLIB_DEBUG debugf("pstr(minor) = '%s'", pstr); #endif value = process_string(pstr, pgd->htab); #ifdef SHLIB_DEBUG debugf("value = '%s'", value); #endif hash_update(pgd->htab, LIB_KW_MIN, value); /* no dup */ } /* get shared lib variable */ pstr = po_get_str(hash_get(ht, KW_SL_SHARED)); if (pstr != NULL) { #ifdef SHLIB_DEBUG debugf("pstr(SHARED) = '%s'", pstr); #endif shvar = process_string(pstr, pgd->htab); #ifdef SHLIB_DEBUG debugf("shvar = '%s'", shvar); #endif } /* get static lib variable */ pstr = po_get_str(hash_get(ht, KW_SL_STATIC)); if (pstr != NULL) { #ifdef SHLIB_DEBUG debugf("pstr(STATIC) = '%s'", pstr); #endif stvar = process_string(pstr, pgd->htab); #ifdef SHLIB_DEBUG debugf("stvar = '%s'", stvar); #endif } /* get versioning boolean */ po = hash_get(ht, KW_SL_VERSION); if (po != NULL) { versbool = po_get_bool(po); } else { /* no version by default */ versbool = false; } /* process shared lib name */ if (shvar != NULL) { if (versbool == false) { /* get libname without version */ pstr = hash_get(pgd->htab, LIB_KW_SH_NONE); #ifdef SHLIB_DEBUG debugf("pstr(LIB_KW_SH_NONE) = '%s'", pstr); #endif value = process_string(pstr, pgd->htab); #ifdef SHLIB_DEBUG debugf("value = '%s'", value); #endif } else { pstr = hash_get(pgd->htab, LIB_KW_SH_VERS); #ifdef SHLIB_DEBUG debugf("pstr(LIB_KW_SH_VERS) = '%s'", pstr); #endif value = process_string(pstr, pgd->htab); #ifdef SHLIB_DEBUG debugf("value = '%s'", value); #endif } /* no dup, no free */ if (hash_update(pgd->htab, shvar, value) == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, shvar); return(false); } pmk_log("\tSetting %s to '%s'\n", shvar, value); #ifdef SHLIB_DEBUG debugf("save in '%s'", shvar); #endif free(shvar); } /* process static lib name */ if (stvar != NULL) { if (versbool == false) { /* get libname without version */ pstr = hash_get(pgd->htab, LIB_KW_ST_NONE); #ifdef SHLIB_DEBUG debugf("pstr(LIB_KW_ST_NONE) = '%s'", pstr); #endif value = process_string(pstr, pgd->htab); #ifdef SHLIB_DEBUG debugf("value = '%s'", value); #endif } else { pstr = hash_get(pgd->htab, LIB_KW_ST_VERS); #ifdef SHLIB_DEBUG debugf("pstr(LIB_KW_ST_VERS) = '%s'", pstr); #endif value = process_string(pstr, pgd->htab); #ifdef SHLIB_DEBUG debugf("value = '%s'", value); #endif } /* no dup, no free */ if (hash_update(pgd->htab, stvar, value) == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, stvar); return(false); } pmk_log("\tSetting %s to '%s'\n", stvar, value); #ifdef SHLIB_DEBUG debugf("save in '%s'", stvar); #endif free(stvar); } return(true); } /************************** * pmk_build_shlib_name() * *********************************************************************** DESCR build name of a shared library ***********************************************************************/ bool pmk_build_shlib_name(pmkcmd *cmd, htable *ht, pmkdata *pgd) { pmk_log("\n* Building shared library name\n"); pmk_log("\tBUILD_SHLIB_NAME() has been obsoleted by BUILD_LIB_NAME().\n"); pmk_log("\tRead the man page for further information.\n"); return(false); } /******************** * option functions * *********************************************************************** * IN * cmd : command structure * popt : option structure * pgd : global data * * OUT * boolean ***********************************************************************/ /*********************** * pmk_set_parameter() * *********************************************************************** DESCR set parameter ***********************************************************************/ bool pmk_set_parameter(pmkcmd *cmd, prsopt *popt, pmkdata *pgd) { /* gnu autoconf compatibility */ if (strncmp(popt->key, KW_SETNGS_ACCOMP, sizeof(popt->key)) == 0) { return(pmk_setparam_accompat(cmd, popt, pgd)); } /* global language */ if (strncmp(popt->key, KW_SETNGS_GLANG, sizeof(popt->key)) == 0) { return(pmk_setparam_glang(cmd, popt, pgd)); } /* set target files */ if (strncmp(popt->key, KW_SETNGS_TARGET, sizeof(popt->key)) == 0) { return(pmk_setparam_target(cmd, popt, pgd)); } /* compiler detection */ if (strncmp(popt->key, KW_SETNGS_CCDTCT, sizeof(popt->key)) == 0) { return(pmk_setparam_detect(cmd, popt, pgd)); } /* found unknown setting */ pmk_log("\tunknown '%s' setting.\n", popt->key); return(false); } /*************************** * pmk_setparam_accompat() * *********************************************************************** DESCR set autoconf compatability parameter ***********************************************************************/ bool pmk_setparam_accompat(pmkcmd *cmd, prsopt *popt, pmkdata *pgd) { char *pstr; pmk_log("\tSetting autoconf compatibility :\n"); /* XXX must check if valid pstr = (char *) hash_get(pgd->htab, "SYSCONFDIR"); hash_update_dup(pgd->htab, "sysconfdir", pstr); */ /* if a file is given then it will be parsed later */ pstr = po_get_str(popt->value); if (*pstr != CHAR_EOS) { pgd->ac_file = strdup(pstr); if (pgd->ac_file == NULL) { errorf(ERRMSG_MEM); return(false); } pmk_log("\t\tSet file to '%s'.\n", pstr); if (hash_update_dup(pgd->htab, AC_VAR_DEF, AC_VALUE_DEF) == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, AC_VAR_DEF); return(false); } pmk_log("\t\tSet '%s' value to '%s'.\n", AC_VAR_DEF, AC_VALUE_DEF); } /* compatibility tags */ if (ac_set_variables(pgd->htab) == false) return(false); /* XXX error message ? */ pmk_log("\t\tSet specific variables.\n"); return(true); } /************************ * pmk_setparam_glang() * *********************************************************************** DESCR set global lang parameter ***********************************************************************/ bool pmk_setparam_glang(pmkcmd *cmd, prsopt *popt, pmkdata *pgd) { bool rval = false; char *pstr; pmk_log("\tSetting global language :\n"); /* set global language */ pstr = po_get_str(popt->value); if (pstr != NULL) { /* check if provided lang is supported */ if (verify_language(pstr) != LANG_UNKNOWN) { pgd->lang = strdup(pstr); if (pgd->lang == NULL) { errorf(ERRMSG_MEM); return(false); } pmk_log("\t\tSet to '%s'.\n", pstr); rval = true; } else { errorf("unknown language."); } } else { errorf("syntax error in LANG."); } return(rval); } /************************* * pmk_setparam_target() * *********************************************************************** DESCR set target list parameter ***********************************************************************/ bool pmk_setparam_target(pmkcmd *cmd, prsopt *popt, pmkdata *pgd) { dynary *da; int i = 0, n; pmk_log("\tCollecting targets :\n"); da = po_get_list(popt->value); if (da == NULL) { errorf("syntax error in TARGET."); return(false); } n = da_usize(da); for (i=0 ; i < n ; i++) { pmk_log("\t\tAdded '%s'.\n", da_idx(da, i)); } pgd->tlist = da; pmk_log("\t\tTotal %d target(s) added.\n", n); return(true); } /************************* * pmk_setparam_detect() * *********************************************************************** DESCR detect a list of compilers ***********************************************************************/ bool pmk_setparam_detect(pmkcmd *cmd, prsopt *popt, pmkdata *pgd) { char *ccpath, *lang, *osname, *pstr, temp[64]; /* XXX size */ code_bld_t scb; comp_parse_t *pcp; compiler_t *pc; dynary *da; hkeys *phk; int i = 0, n; pmk_log("\tDetecting compiler shared library support :\n"); da = po_get_list(popt->value); if (da == NULL) { errorf("syntax error in DETECT."); return(false); } /* get os name */ osname = hash_get(pgd->htab, PMKCONF_OS_NAME); /* * parsing compiler data to build a database that will be used further */ pmk_log("\t\tGathering data for compiler detection.\n"); pcp = parse_comp_file(PMKCOMP_DATA, osname); /* process each language provided in detection list */ n = da_usize(da); for (i=0 ; i < n ; i++) { lang = da_idx(da, i); /* init code building structure */ code_bld_init(&scb, pgd->buildlog); /* init build structure */ if (set_language(&scb, lang) == false) { /* * if language name is invalid then check * for obsolete compiler name */ pstr = obsolete_get_lang_from_comp(lang); /* OBSOLETE */ if (pstr == NULL) { errorf("Unknown language'%s'.\n", lang); return(false); } pmk_log("\t\tWARNING: obsolete value for compiler detection,\n"); pmk_log("\t\t\tuse language label instead.\n"); lang = pstr; if (set_language(&scb, lang) == false) { errorf("Unknown language '%s'.\n", lang); return(false); } } /* get the appropriate compiler */ set_compiler(&scb, pgd->htab); pstr = get_compiler_label(&scb); ccpath = hash_get(pgd->htab, pstr); if (ccpath == NULL) { errorf("Cannot get compiler path ('%s').\n", pstr); return(false); } pmk_log("\t\tDetecting %s compiler : ", lang); /* try to identify the compiler */ pc = &(pgd->comp_data.data[scb.lang]); if (comp_detect(ccpath, pgd->buildlog, pc, pcp, scb.pld->slcflags) == false) { pmk_log("failed.\n"); return(false); } /* set the language type, so the compiler data are valid */ pc->lang = scb.lang; /* XXX set in detect proc ? */ pmk_log("%s (version %s).\n", pc->descr, pc->version); /* set shared lib compiler flags */ pmk_log("\t\tSetting %s to '%s'\n", scb.pld->slcflags, pc->slcflags); if (hash_update_dup(pgd->htab, scb.pld->slcflags, pc->slcflags) == HASH_ADD_FAIL) { return(false); } /* set shared lib linker flags */ pmk_log("\t\tSetting %s to '%s'\n", scb.pld->slldflags, pc->slldflags); if (hash_update_dup(pgd->htab, scb.pld->slldflags, pc->slldflags) == HASH_ADD_FAIL) { return(false); } /* try to compile shared object */ pmk_log("\t\tChecking shared library support : "); if (check_so_support(&scb, pc->slcflags, pc->slldflags) == true) { pmk_log("ok.\n"); /* shared lib support */ snprintf(temp, sizeof(temp), "%s ", scb.pld->mk_bld_rule); if (hash_append(pgd->htab, MK_VAR_SL_BUILD, strdup(temp), NULL) == HASH_ADD_FAIL) { return(false); } snprintf(temp, sizeof(temp), "%s ", scb.pld->mk_cln_rule); if (hash_append(pgd->htab, MK_VAR_SL_CLEAN, strdup(temp), NULL) == HASH_ADD_FAIL) { return(false); } snprintf(temp, sizeof(temp), "%s ", scb.pld->mk_inst_rule); if (hash_append(pgd->htab, MK_VAR_SL_INST, strdup(temp), NULL) == HASH_ADD_FAIL) { return(false); } snprintf(temp, sizeof(temp), "%s ", scb.pld->mk_deinst_rule); if (hash_append(pgd->htab, MK_VAR_SL_DEINST, strdup(temp), NULL) == HASH_ADD_FAIL) { return(false); } } else { pmk_log("failed.\n"); } /* clean cdata */ cb_cleaner(&scb); } /* get system data */ pmk_log("\t\tGetting system data for %s : ", osname); phk = hash_keys_sorted(pcp->sht); if (phk == NULL) { pmk_log("failed.\n"); } else { for (i = 0 ; i < (int) phk->nkey ; i++) { pstr = hash_get(pcp->sht, phk->keys[i]) ; hash_update_dup(pgd->htab, phk->keys[i], pstr); /* XXX check */ } pmk_log("ok.\n"); /* mark system as detected */ pgd->sys_detect = true; } /* clean now useless parsed data */ destroy_comp_parse(pcp); return(true); } /********************** * pmk_set_variable() * *********************************************************************** DESCR set variable ***********************************************************************/ bool pmk_set_variable(pmkcmd *cmd, prsopt *popt, pmkdata *pgd) { char buffer[TMP_BUF_LEN], *pstr, *value, *defname; int hval; /* XXX better way to do (specific hash for override) if (hash_get(pgd->htab, popt->key) == NULL) { */ /* process value string */ pstr = po_get_str(popt->value); if (pstr == NULL) { errorf("bad value for '%s'.", popt->key); return(false); } value = process_string(pstr, pgd->htab); if (value != NULL) { hval = hash_update(pgd->htab, popt->key, value); /* no need to strdup */ /* check return for message : defined or redefined */ switch (hval) { case HASH_ADD_FAIL: errorf(HASH_ERR_UPDT_ARG, popt->key); return(false); break; case HASH_ADD_OKAY: case HASH_ADD_COLL: pmk_log("\tdefined"); break; case HASH_ADD_UPDT: pmk_log("\tredefined"); break; } /* remaining part of the message */ pmk_log(" '%s' variable.\n", popt->key); /* store definition for autoconf compatibility */ defname = gen_basic_tag_def(popt->key); if (defname == NULL) { errorf("unable to build define name for '%s'.", popt->key); return(false); } if (snprintf_b(buffer, sizeof(buffer), "#define %s \"%s\"", popt->key, value) == false) { errorf("buffer overflow for define value of '%s'.", popt->key); return(false); } if (hash_update_dup(pgd->htab, defname, buffer) == HASH_ADD_FAIL) { errorf(HASH_ERR_UPDT_ARG, defname); return(false); } } else { pmk_log("\tFailed processing of '%s'.\n", popt->key); return(false); } /* } else { pmk_log("\tSkipped '%s' define (overriden).\n", popt->key); } */ return(true); } /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/pmk.h010064400017500000000000000106631047114646400122220ustar00mipswheel/* $Id: pmk.h 1555 2006-08-17 20:10:28Z mipsator $ */ /* * 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. * */ #ifndef _PMK_H_ #define _PMK_H_ #include "detect.h" #include "dynarray.h" #include "hash.h" #include "cfgtool.h" #include "parse.h" #include "premake.h" /************* * constants * ***********************************************************************/ /* pmk specific version */ #define PREMAKE_SUBVER_PMK "7" /* character to assign a value to a key */ #define PMK_KEY_CHAR '=' /* character used as delimiter for template tags */ #define PMK_TAG_CHAR '@' /* maximal number of templates */ #define MAX_TEMPLATES 32 /* maximal number of key in label hash */ #define MAX_LABEL_KEY 1024 /* pmk's directory tags */ #define PMK_DIR_BLD_ABS "builddir_abs" #define PMK_DIR_BLD_REL "builddir_rel" #define PMK_DIR_BLD_ROOT_ABS "builddir_root_abs" #define PMK_DIR_BLD_ROOT_REL "builddir_root_rel" #define PMK_DIR_SRC_ABS "srcdir_abs" #define PMK_DIR_SRC_REL "srcdir_rel" #define PMK_DIR_SRC_ROOT_ABS "srcdir_root_abs" #define PMK_DIR_SRC_ROOT_REL "srcdir_root_rel" #define PMK_TMP_AC_CONF TMPDIR "/pmk_ac_XXXXXXXX" /* logs */ #define PMK_LOG_EXT ".log" #define PMK_LOG "pmk" PMK_LOG_EXT #define PMK_BUILD_LOG "pmk_build" PMK_LOG_EXT #define PMK_GENMSG "%s generated from %s by PMK." #define PMK_TAG_IDTF_STR "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789_" /* error messages */ #define PMK_ERR_OVRFLOW "buffer overflow." #define PMK_ERR_BLDLOG "failed to set buildlog output." /********************* * types definitions * ***********************************************************************/ typedef struct { char tmpl_name[MAXPATHLEN], src_root_abs[MAXPATHLEN], src_root_rel[MAXPATHLEN], src_abs[MAXPATHLEN], src_rel[MAXPATHLEN], bld_root_abs[MAXPATHLEN], bld_root_rel[MAXPATHLEN], bld_abs[MAXPATHLEN], bld_rel[MAXPATHLEN]; } pmkdyn_t; /* pmk data */ typedef struct { bool sys_detect; cfgtdata *cfgt; char *ac_file, *lang, basedir[MAXPATHLEN], srcdir[MAXPATHLEN], pmkfile[MAXPATHLEN], ovrfile[MAXPATHLEN], buildlog[MAXPATHLEN], errmsg[MAX_ERR_MSG_LEN]; comp_data_t comp_data; dynary *tlist; htable *htab, *labl; pmkdyn_t dyndata; } pmkdata; /*********************** * function prototypes * ***********************************************************************/ /* init functions */ pmkdata *pmkdata_init(void); bool init_var(pmkdata *); /* template functions */ bool process_dyn_paths(pmkdata *, char *); bool process_dyn_var(pmkdata *); bool process_template(pmkdata *, char *); bool template_main(pmkdata *); /* misc functions */ bool process_cmd(prsdata *, pmkdata *); bool parse_cmdline(char **, int, pmkdata *); bool set_switch_list(pmkdata *, char *, bool, int *); void clean(pmkdata *); void usage(void); #endif /* _PMK_H_ */ /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/prseng.c010075500017500000000000000217621034764151500127300ustar00mipswheel/* $Id: prseng.c 1521 2005-12-13 21:55:25Z mipsator $ */ /* * Copyright (c) 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. * */ #include #include #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "prseng.h" /*#define DEBUG_PRSENG 1*/ /***************** * prseng_init() * *********************************************************************** DESCR initialize parsing engine from a file IN fp : file descriptor data : extra data to transmit or NULL OUT parsing engine structure or NULL ***********************************************************************/ prseng_t *prseng_init(FILE *fp, void *data) { prseng_t *ppe; size_t s; ppe = (prseng_t *) malloc(sizeof(prseng_t)); if (ppe != NULL) { /* init the buffer */ fseek(fp, 0, SEEK_SET); s = fread((void *) ppe->buf, sizeof(char), (sizeof(ppe->buf ) - 1), fp); /* on error return NULL */ if (ferror(fp) != 0) { free(ppe); return(NULL); } /* end the string */ ppe->buf[s] = CHAR_EOS; /* extra data that could be needed */ ppe->data = data; /* misc init */ ppe->fp = fp; ppe->eof = false; ppe->err = false; ppe->str = NULL; ppe->cur = ppe->buf; ppe->linenum = 1; ppe->offset = 0; } return(ppe); } /********************* * prseng_init_str() * *********************************************************************** DESCR initialize parsing engine from a string IN str : string to parse data : extra data to transmit or NULL OUT parsing engine structure or NULL ***********************************************************************/ prseng_t *prseng_init_str(char *str, void *data) { prseng_t *ppe; ppe = (prseng_t *) malloc(sizeof(prseng_t)); if (ppe != NULL) { /* init the buffer */ strlcpy(ppe->buf, str, sizeof(ppe->buf)); /* no check */ /* keep track of start of line */ ppe->str = str; /* extra data that could be needed */ ppe->data = data; /* misc init */ ppe->fp = NULL; ppe->eof = true; ppe->err = false; ppe->cur = ppe->buf; ppe->linenum = 1; ppe->offset = 0; } return(ppe); } /******************** * prseng_destroy() * *********************************************************************** DESCR destroy parsing engine structure IN ppe : structure to destroy OUT NONE ***********************************************************************/ void prseng_destroy(prseng_t *ppe) { free(ppe); } /******************* * prseng_update() * *********************************************************************** DESCR update parsing engine buffer IN ppe : parsing engine structure OUT boolean ***********************************************************************/ bool prseng_update(prseng_t *ppe) { size_t s; /* if the cursor didn't move ... */ if (ppe->cur == ppe->buf) { /* then skip update */ return(true); } /* compute offset */ ppe->offset = (ppe->cur - ppe->buf) + ppe->offset; if (ppe->fp != NULL) { /* set the reading pointer at desired offset */ fseek(ppe->fp, ppe->offset, SEEK_SET); if (feof(ppe->fp) != 0) { ppe->eof = true; } /* fill buffer with size - 1 characters */ s = fread((void *) ppe->buf, sizeof(char), (sizeof(ppe->buf ) - 1), ppe->fp); /* ferror ? */ if (ferror(ppe->fp) != 0) { ppe->err = true; return(false); } /* put EOS right after the last read char */ ppe->buf[s] = CHAR_EOS; /* check if end of file has been reached */ if (feof(ppe->fp) != 0) { ppe->eof = true; } } else { strlcpy(ppe->buf, (ppe->str + ppe->offset), sizeof(ppe->buf)); /* no check ? */ } /* rewind cursor to the beginning of the buffer */ ppe->cur = ppe->buf; /* buffer filled, return pointer to the first character */ return(true); } /**************** * prseng_eof() * *********************************************************************** DESCR check for end of file IN ppe : parsing engine structure OUT boolean ***********************************************************************/ bool prseng_eof(prseng_t *ppe) { if (ppe->err == true) { /* file error, consider it as an end of file */ return(true); } /* not reached end of file neither get end of string */ if ((ppe->eof == false) || (*ppe->cur != '\0')) { return(false); } /* end of file and buffer */ return(true); } /********************* * prseng_get_char() * *********************************************************************** DESCR get character of parsing cursor IN ppe : parsing engine structure OUT character ***********************************************************************/ char prseng_get_char(prseng_t *ppe) { /* return character at the current cursor position */ return(*ppe->cur); } /********************** * prseng_next_char() * *********************************************************************** DESCR set parsing cursor to next character IN ppe : parsing engine structure OUT boolean ***********************************************************************/ bool prseng_next_char(prseng_t *ppe) { if (*ppe->cur == '\n') { #ifdef DEBUG_PRSENG debugf("prseng_next_char() : new line = %d", ppe->linenum); #endif ppe->linenum++; } /* set the cursor to the next char */ ppe->cur++; #ifdef DEBUG_PRSENG debugf("prseng_next_char() : new char = '%c'.", *ppe->cur); #endif /* if end of string try to update buffer */ if (*ppe->cur == CHAR_EOS) { if (prseng_update(ppe) == false) { return(false); } } return(true); } /********************** * prseng_test_char() * *********************************************************************** DESCR test character at the parsing cursor position IN ppe : parsing engine structure c : char to compare with OUT boolean ***********************************************************************/ bool prseng_test_char(prseng_t *ppe, char c) { if (*ppe->cur == c) { return(true); } return(false); } /*************************** * prseng_test_idtf_char() * *********************************************************************** DESCR test if character at the parsing cursor is an identifier character contained in the given string IN pstr : string of identifier characters c : character to test OUT boolean TODO XXX do it directly with ppe ???? ***********************************************************************/ bool prseng_test_idtf_char(char *pstr, char c) { /* parse the allowed characters string */ while (*pstr != CHAR_EOS) { if (*pstr == c) { /* character matches */ return(true); } /* next character */ pstr++; } /* not found */ return(false); } /********************* * prseng_get_idtf() * *********************************************************************** DESCR get an identifier from the actual parsing cursor position IN ppe : parsing engine structure pbuf : identifier storage buffer s : size of buffer pstr : identifier allowed characters OUT boolean ***********************************************************************/ bool prseng_get_idtf(prseng_t *ppe, char *pbuf, size_t s, char *pstr) { /* leave space for the end of string character */ s--; /* loop while we have allowed char and enough place in the buffer */ while ((prseng_test_idtf_char(pstr, *ppe->cur) == true) && (s > 0)) { /* copy character */ *pbuf = *ppe->cur; /* update buffer cursor */ pbuf++; s--; /* next character */ if (prseng_next_char(ppe) == false) { *pbuf = CHAR_EOS; return(false); } } *pbuf = CHAR_EOS; /* if (prseng_test_idtf_char(pstr, *ppe->cur) == true) { return(false); } */ return(true); } pmk-0.10.4/func.h010064400017500000000000000122561052021275100123520ustar00mipswheel/* $Id: func.h 1921 2006-10-26 20:09:13Z 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. * */ #ifndef _PMK_FUNC_H_ #define _PMK_FUNC_H_ #include "compat/pmk_stdbool.h" #include "pmk.h" #include "parse.h" /************* * constants * ***********************************************************************/ /* node tokens */ #define PMK_TOK_SETNGS 1 #define PMK_TOK_DEFINE 2 #define PMK_TOK_SWITCH 3 #define PMK_TOK_IFCOND 4 #define PMK_TOK_ELCOND 5 /* special setting tokens */ #define PMK_TOK_SETVAR 10 /* set variable */ #define PMK_TOK_SETPRM 11 /* set parameter */ /* item command tokens */ /* checks */ #define PMK_TOK_CHKBIN 20 #define PMK_TOK_CHKINC 21 #define PMK_TOK_CHKLIB 22 #define PMK_TOK_CHKCFG 23 #define PMK_TOK_CHKPKG 24 #define PMK_TOK_CHKTYP 25 #define PMK_TOK_CHKVAR 26 /* lib stuff */ #define PMK_TOK_BLDLIB 30 #define PMK_TOK_BLDSLN 31 /* option keywords */ /* common */ #define KW_OPT_NAME "NAME" #define KW_OPT_DEFS "DEFS" #define KW_OPT_FUNCTION "FUNCTION" #define KW_OPT_HEADER "HEADER" #define KW_OPT_CFLAGS "CFLAGS" #define KW_OPT_LANG "LANG" #define KW_OPT_LIBS "LIBS" #define KW_OPT_MACRO "MACRO" #define KW_OPT_MAJOR "MAJOR" #define KW_OPT_MEMBER "MEMBER" #define KW_OPT_MINOR "MINOR" #define KW_OPT_MODULE "MODULE" #define KW_OPT_SUBHDR "SUBHDR" #define KW_OPT_VERSION "VERSION" #define KW_OPT_VALUE "VALUE" #define KW_OPT_VARIABLE "VARIABLE" /* SETTINGS */ #define KW_SETNGS_GLANG "LANG" #define KW_SETNGS_TARGET "TARGET" #define KW_SETNGS_ACCOMP "AC_COMPAT" #define KW_SETNGS_ACCOMP "AC_COMPAT" #define KW_SETNGS_CCDTCT "DETECT" /* library name building */ #define KW_SL_VERSION "VERSION" #define KW_SL_STATIC "STATIC" #define KW_SL_SHARED "SHARED" /* obsolete stuff *//* XXX OBOSLETE */ #define KW_SL_VERS_NONE "VERSION_NONE" #define KW_SL_VERS_MAJ "VERSION_MAJ" #define KW_SL_VERS_FULL "VERSION_FULL" #define DEFINE_DEFAULT "1" /* error messages */ #define ERR_MSG_CC_CMD "failed to build compiler command line." /********************************** * type and structure definitions * ***********************************************************************/ /* structures */ typedef struct { char kw[CMD_LEN]; bool (*fnp)(pmkcmd *, htable *, pmkdata *); } cmdkw; /************** * prototypes * ***********************************************************************/ bool func_wrapper(prscell *, pmkdata *); bool process_node(prsnode *, pmkdata *); bool pmk_define(pmkcmd *, prsnode *, pmkdata *); bool pmk_target(pmkcmd *, htable *, pmkdata *); bool pmk_ac_compat(pmkcmd *, htable *, pmkdata *); bool pmk_settings(pmkcmd *, prsnode *, pmkdata *); bool pmk_ifcond(pmkcmd *, prsnode *, pmkdata *); bool pmk_elcond(pmkcmd *, prsnode *, pmkdata *); bool pmk_switches(pmkcmd *, htable *, pmkdata *); bool pmk_check_binary(pmkcmd *, htable *, pmkdata *); bool pmk_check_header(pmkcmd *, htable *, pmkdata *); bool pmk_check_lib(pmkcmd *, htable *, pmkdata *); bool pmk_check_config(pmkcmd *, htable *, pmkdata *); bool pmk_check_pkg_config(pmkcmd *, htable *, pmkdata *); bool pmk_check_type(pmkcmd *, htable *, pmkdata *); bool pmk_check_variable(pmkcmd *, htable *, pmkdata *); bool pmk_build_lib_name(pmkcmd *, htable *, pmkdata *); bool pmk_build_shlib_name(pmkcmd *, htable *, pmkdata *); bool pmk_set_parameter(pmkcmd *, prsopt *, pmkdata *); bool pmk_setparam_accompat(pmkcmd *, prsopt *, pmkdata *); bool pmk_setparam_glang(pmkcmd *, prsopt *, pmkdata *); bool pmk_setparam_target(pmkcmd *, prsopt *, pmkdata *); bool pmk_setparam_detect(pmkcmd *, prsopt *, pmkdata *); bool pmk_set_variable(pmkcmd *, prsopt *, pmkdata *); #endif /* _PMK_FUNC_H_ */ /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/STATUS010064400017500000000000000040311052762550500122200ustar00mipswheel----------------------------------------------------------------------- Pre Make Kit STATUS file Document revision: $Id: STATUS 1931 2006-11-18 15:48:21Z coudercd $ ----------------------------------------------------------------------- OS name OS version OS architecture PMK version build status Reported by Misc data ~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~ AIX 4.3.3 ppc 0.9.2 OK Martin Reindl CSet 3.1.4 Debian 3.1 i686 0.10 OK Damien Couderc FreeBSD 6.1 ia64 0.10 OK Damien Couderc FreeBSD 6.1 i386 0.10 OK Damien Couderc HP-UX B.11.11 parisc 0.10 OK Damien Couderc gcc IRIX 6.5 IP32 0.8.1-s7 OK Xavier Santolaria MIPSpro Compilers 7.30 Mac OS X 10.3.9 ppc 0.9.3-s2 OK Martin Reindl gcc-3.3, gmake-3.79 Mandrake 10.0 i686 0.9.1 OK Damien Couderc NetBSD 2.0G alpha 0.8.1-s7 OK Martin Reindl gcc-3.3.3 NetBSD 1.6 i386 0.9.0 OK Damien Couderc gcc-2.95.3 NetBSD 1.6.1 macppc 0.8.1 OK Martin Reindl gcc-2.95.3 NetBSD 2.0 sgimips 0.8.1-s9 OK Martin Reindl gcc-3.3.3 NetBSD 2.0G sparc 0.8.1-s7 OK Martin Reindl gcc-3.3.3 NetBSD 1.6ZG sparc64 0.8.1 OK Martin Reindl gcc-3.3.2 OpenBSD 4.0 i386 0.10 OK Damien Couderc OSF1 (Tru64) 5.1B alpha 0.9.0 OK Damien Couderc Compaq C V6.5-003 RedHat Ent. ES4 i686 0.10 OK Damien Couderc Slackware 9.1 i686 0.8.1 OK Damien Couderc gcc-3.2.2, gmake-3.80, linux-2.4.20 Slackware 10.0.0 i686 0.8.1-s7 OK Xavier Santolaria gcc-3.3.4, gmake-3.80, linux-2.4.26 SunOS 5.7 sun4u 0.8.1-s7 OK Xavier Santolaria gcc-2.95.2, gmake-3.76.1 SunOS 5.7 sun4u 0.8.1-s7 OK Xavier Santolaria WorkShop Compilers 5.0, gmake-3.76.1 SunOS 5.8 sun4u 0.9.2 OK Martin Reindl gcc-2.95.3, gmake-3.79.1 SunOS 5.8 sun4u 0.9.2 OK Martin Reindl Forte Developer 7 C 5.4 2002/03/09 SunOS 5.10 sun4u 0.8.1 OK Martin Reindl gcc-2.95.3, gmake-3.79.1 SuSE ES 10 i386 0.10 OK Damien Couderc SuSE ES 10 x86_64 0.10 OK Damien Couderc pmk-0.10.4/prseng.h010075500017500000000000000057211023224433300127200ustar00mipswheel/* $Id: prseng.h 1401 2005-04-22 18:56:27Z mipsator $ */ /* * Copyright (c) 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. * */ #ifndef _PRSENG_H_ #define _PRSENG_H_ #include "compat/pmk_stdbool.h" /*********** constants ***********************************************************************/ #define CHAR_EOS '\0' /* parsing engine buffer length */ #define PRSENG_BUF_LEN 512 /********************* types and structures ***********************************************************************/ typedef struct { FILE *fp; /* file structure pointer */ bool eof, /* end of file flag */ err; /* error flag */ char *str, /* string to parse (prseng_init_str) */ *cur, /* parsing cursor */ buf[PRSENG_BUF_LEN]; /* buffer window */ unsigned int linenum; /* current line */ unsigned long offset; /* offset of the buffer window */ void *data; } prseng_t; /******************** function prototypes ***********************************************************************/ prseng_t *prseng_init(FILE *, void *); prseng_t *prseng_init_str(char *, void *); void prseng_destroy(prseng_t *); bool prseng_update(prseng_t *); bool prseng_eof(prseng_t *); char prseng_get_char(prseng_t *); bool prseng_next_char(prseng_t *); bool prseng_test_char(prseng_t *, char); bool prseng_test_idtf_char(char *, char); bool prseng_get_idtf(prseng_t *, char *, size_t, char *); #endif /* _PRSENG_H_ */ pmk-0.10.4/scanfile010075500017500000000000000007601062137003400127560ustar00mipswheel# pmkscan script # $Id: scanfile 1985 2007-05-12 16:49:32Z coudercd $ GEN_ZONE(main) { DIRECTORY = "." RECURSE = TRUE DISCARD = ("samples", "doc", "tests") PMKFILE = TRUE PMKNAME = "pmkfile.scan" CFGNAME = "compat/config.h.scan" MAKEFILE = TRUE MKFNAME = "Makefile.scan" EXTRATAG = ("CONFDIR", "PRIVSEP_USER") } GEN_ZONE(tests) { DIRECTORY = "./tests" RECURSE = TRUE PMKFILE = TRUE PMKNAME = "pmkfile.scan" CFGNAME = "config.h.scan" MAKEFILE = TRUE MKFNAME = "Makefile.scan" } pmk-0.10.4/BONUS010064400017500000000000000017201011344605400120540ustar00mipswheel----------------------------------------------------------------------- Pre Make Kit BONUS file Document revision: $Id: BONUS 1163 2004-08-26 20:46:36Z xsa $ ----------------------------------------------------------------------- This package contains some files that are designed to permit their use in other projects: - String hash-coding : hash.c, hash.h - Dynamic string arrays : dynarray.c dynarray.h - Path manipulation tools : pathtools.c pathtools.h These files are released under the BSD license and are almost ready to be used. Some issues do exist due to portability as this package uses ISO99 booleans and string functions like strlcpy and strlcat. You are free to use some components of this package to assume compatibility on all the system targets as long as you do respect the BSD license. NOTE : Some functions are maybe missing as we do not have the use in this current package but we could add them on request (yes, you can also send patches ;) ). pmk-0.10.4/Changelog010064400017500000000000001654531077177720000131050ustar00mipswheel# PMK 0.10.4 release 24 Mar 2008 coudercd * fixed pkgconfig stuff in cases where dependencies can be missing. * removed use of (broken) variable substitution in pmk.conf. * added pkgconfig lib path detection. # PMK 0.10.3 release 26 May 2007 coudercd * fixed use of LIBS. 23 May 2007 coudercd * fixed function detection in library check. * add math library check in pmkfile. 12 May 2007 coudercd * updated pmkfile and scanfile. * added missing tag generation for pmk library check. 16 Apr 2007 coudercd * removed ending line with only one dot that makes Linux complaining, noticed by Magnus Holmgren. * added a carriage return that was missing in pmkscan log file message. * updated main Makefile template to fix GEN_FILES, noticed by Magnus Holmgren. # PMK 0.10.2 release 15 Apr 2007 coudercd * fixed processing of pkg-config library directory to support multiples path, noticed by Marco Ghirlanda. 13 Apr 2007 coudercd * fixed library source labels generation. * fixed object dependencies when an object is used in both a binary and a library to avoid duplicates. 10 Apr 2007 coudercd * resized ressources in pmkscan for larger projects. * added more messages in pmkscan. 05 Apr 2007 coudercd * removed obsolete option LIBOBJ. * added missing initialisation of lib_type in the scanzone structure. 21 Mar 2007 coudercd * fixed errors in manual pages and replaced blank lines by one dot lines, notified by Magnus Holmgren. * fixed the duplicates in macro GEN_FILES of generated makefiles, also notified by Magnus Holmgren. 28 Feb 2007 coudercd * fixed the label of shared lib linking flags variable in the log message (noticed by barratis from toy'd project). 25 Feb 2007 coudercd * fixed a segfaulting bug in code_logger(). 15 Feb 2007 coudercd * fixed a bug occuring in pmkpc when specifying both --cflags and --libs options. The result is now separated but a space. # PMK 0.10.1 release 24 Dec 2006 coudercd * fixed codebuild bug spotted by toyd team on linux. * reordered pmkcfg.sh compiler detection. 08 Dec 2006 coudercd * fixed install_lib target in makefile generation from pmkscan. * removed the compatibility option -c for install for portability. # PMK 0.10.0 release 18 Nov 2006 coudercd * added in pmkscan the code to create binary install directory in generated makefile template. * support alternative assembler in pmkcfg.sh via AS variable. * update Makefile.pmk template to create correctly the binary install directory. * also added in pmkscan the code for install data directory creation in the generated makefile template. # snapshot 20061028 22 Oct 2006 coudercd * added BUILD_LIB_NAME() to replace BUILD_SHLIB_NAME() as it also build the static library name. * marked BUILD_SHLIB_NAME() as obsolete. * fixed manual page directories for usermode install. 22 Oct 2006 coudercd * added support for shared library versioning. * library version numbers become optional. 14 Oct 2006 coudercd * lib checking fix was incomplete, it should be now (noticed by Phil aka wintellect). * fixed -u option of pmksetup and added a reminder in man page to escape double quotes. 11 Oct 2006 coudercd * fixed label generation for objects. * reimplemented instal targets for data files and man pages. * updated pmkcfg.sh to sync with latest changes. * updated scanfile to avoid unwanted template modification. * updated Makefile.pmk with pmkscan generated template. 10 Oct 2006 coudercd * reimplemented binary targets in makefile template generated by pmkscan to follow the same behavior as for libraries. 09 Oct 2006 coudercd * recovered shared library support from my broken laptop which died 2 seconds after the stuff was completed. * added missing file lang.c in the previous commit. 07 Oct 2006 coudercd * lib checking was broken in a previous commit, it is now fixed. 06 Oct 2006 coudercd * fixed coredumps in pmk_check_config() and pmk_check_pkg_config() due to missing initialization of the codebuild structure. 28 Sep 2006 coudercd * better management of the template files, now pmkscan can process them in only one pass. 24 Sep 2006 coudercd * started simplification and automatization of makefile template's targets. 23 Sep 2006 coudercd * removed obsolete command line options of pmkscan. * updated pmkscan and scanfile man pages. 22 Sep 2006 coudercd * import large chunk of code for better support of shared library. * fixed format of c++ suffix in generated makefile. 14 Sep 2006 coudercd * fixed CPUID checking for X86 32 bits CPUs, noticed by Leslie Polzer. 05 Sep 2006 coudercd * updated values for compiler detection in SETTINGS to sync with pmk. # snapshot 20060902 01 Sep 2006 coudercd * fixed a regression in rev. 102 that prevented from generating a complete pmkfile (header and library checks were missing). 17 Aug 2006 coudercd * rewritten compiler detection for shared lib support. * improved shared lib support verification. 03 Aug 2006 coudercd * much mode #defines in compiler detection module. 15 Jul 2006 coudercd * a long time since the last commit but had no feeling to work on pmk until last days. Here is some cleanup and the latest work done. # snapshot 20060319 19 Mar 2006 coudercd * import latest work on library support (both static and dynamic). 07 Mar 2006 coudercd * improved a bit the makefile generation before completing library generation support. 01 Mar 2006 coudercd * still going on with library handling. Result is still not useable yet as library generation targets are missing. That should be the last step before completion. 27 Feb 2006 coudercd * added hash_extract() to extract data from an hash table. * added more serious partial lib support. 05 Feb 2006 coudercd * added some experimental stuff into pmkscan to handle libraries lately. This stuff could make current unstable as i have not enough time to make sure all is fine before commit. I'll notifiy when everything will come back to normality. 30 Jan 2006 coudercd * pmk now inform when compiler has not been detected before checking for shared library support. 19 Jan 2006 coudercd * some temporary fixes for pmkcfg.sh portability. Better fixes will come further ... 16 Jan 2006 coudercd * fixed pmkcfg.sh to correctly set library flags. * added isnan() and seteuid() functions in pmkcfg.sh for failing architectures. 13 Jan 2006 coudercd * fixed missing tokens in detect_cpu.c for kw_pmkcpu. * fixed CPP substitution in pmkcfg.sh script. # snapshot 20051215 14 Dec 2005 coudercd * improved template tag substitution in pmk. 13 Dec 2005 coudercd * improved c++ file parser for pmkscan. 09 Dec 2005 coudercd * added more support for c++. * added advanced tags for config tools and pkg-config. 07 Dec 2005 coudercd * fixed C++ flag setting in pmkscan. 05 Dec 2005 coudercd * added more data in pmkscan database. 04 Dec 2005 coudercd * small fix for parse_lang in prs_c_file(). 30 Nov 2005 coudercd * fixed missing include for intmax_t in compat, noticed by veins. * added few more advanced tags in pmk. * added alternate pmkfile name support in pmkscan script. * added support for inclusion of third party file content into pmkscan generated makefile. * added some recursive target stuff to prepare multiple generation. 24 Nov 2005 coudercd * fixed extra define in pmkscan generated config file. * fixed lower in gen_tag(). * started to add advanced tags. 22 Nov 2005 coudercd * improved distclean target in generated makefile. 19 Nov 2005 coudercd * fixed pmkfile, pmkcfg.sh and compat. * polished a bit func.c. 17 Nov 2005 coudercd * added basic distclean target in generated makefile and started to prepare for advanced tags support. 10 Nov 2005 coudercd * added use of new tags functions in pmk. # snapshot 0.9.3-s4 05 Nov 2005 coudercd * finished basic tag support in pmkscan for config file generation. * added pmksyntax.5 manual page to give a common overview of PMK basic syntax used in pmkfile and scanfile. 04 Nov 2005 coudercd * fixed a small bug in c language parser. * added a start of config file template generation in pmkscan. 27 Oct 2005 coudercd * added support for extra tags in pmkscan. 27 Oct 2005 coudercd * started improvements to pmkscan (see TODO). 25 Oct 2005 coudercd * added support for sub headers, language label and language option in pmkscan. 24 Oct 2005 coudercd * fixed a bug when generating a pmkfile that has no checks, noticed by veins of skreel.org. * set './scanfile' as default specification file for pmkscan when no option is given at the command line. # snapshot 0.9.3-s3 23 Oct 2005 coudercd * misc changes before new snapshot. 19 Oct 2005 coudercd * improved/fixed the pmkfile generation in pmkscan. 13 Oct 2005 coudercd * polished checks in func. * added scanfile.5 man page. 10 Oct 2005 coudercd * rewritten check_header() and check_type() to guarantee the recording of tags. 06 Oct 2005 coudercd * added conv_to_label() to fix label generation in pmkscan. 05 Oct 2005 coudercd * new engine for pmkfile generation in pmkscan (thought need to have a better engine for label names). 02 Oct 2005 coudercd * fixed command line option parsing in pmksetup (broken after 0.9.3 with prseng import). 28 Sep 2005 coudercd * splitted member detection in CHECK_TYPE, now type and member are checked separatly. 27 Sep 2005 coudercd * polished code builder stuff, now used in check_header, check_lib and check_type. 24 Sep 2005 coudercd * unbreak the pmkfile. * fixed shared library support bug when system is not supported. 03 Sep 2005 coudercd * imported primary work on code builder engine. # snapshot 0.9.3-s2 21 Aug 2005 coudercd * replaced stdio.h by pmk_stdio.h. * replaced old tests/Makefile.pmk by the one generated by pmkscan (removed unneeded targets and install stuff). * fixed tests so all compile without warnings. 20 Aug 2005 coudercd * replaced old makefile template by the one generated by pmkscan (CFLAGS has been modified and added CONFDIR and PRIVSEP_USER). * enabled compat tests. * updated pmkscan latest changes (polishing). 18 Aug 2005 coudercd * added MANDIR and SYSCONFDIR support in pmkscan. * tuned pmkcfg.sh to prepare switch from hand made Makefile to pmkscan generated Makefile. 17 Aug 2005 coudercd * fixed %c conversion in vsnprintf(). * updated pmkcfg.sh and config.in.pmk in sync with compat. 15 Aug 2005 coudercd * updated pmkcfg.sh and config.h.pmk in sync with compat. 12 Aug 2005 coudercd * added support for NaN and infinity in vsnprintf(). 10 Aug 2005 coudercd * added strdup() in compat. * fragmented a bit vsnprintf() related functions. 09 Aug 2005 coudercd * handle template files in pmkscan. 06 Aug 2005 coudercd * added latest work done on pmkscan. The makefile generation is almost complete. Some work has to be done on pmkfile generation for the next release. 02 Aug 2005 coudercd * added da_sort() to sort the content of the dynary. * first import of code building functions for further use in pmk. * fixed bugs in pathtools. * synced pmkcfg.sh and pmkfile with compat. * updated pmkscan data. * cleaned test sources. 21 Jul 2005 coudercd * added ISO C99 vsnprintf() implementation (missing wide char support). * rewritten a bit compat. 07 Jul 2005 coudercd * added type data support in pmkscan. 05 Jul 2005 coudercd * finished support for man pages and data files in pmkscan's makefile generation. * fixed recursive scanning of directory in pmkscan. # snapshot 0.9.3-s1 01 Jul 2005 coudercd * fixed scan_dir() by replacing use of non portable member of structure dirent by the use of stat(). This should fix problems encountered on Solaris 8. * fixed our strlcpy(). * fixed CPP and CC values in pmkcfg.sh script. 30 Jun 2005 mreindl * include config.h in compat/pmk_sys_types.h. 30 Jun 2005 coudercd * added support for a configuration script in pmkscan. * added an example of configuration script. 13 Jun 2005 coudercd * add da_find() to search a string through a dynary. 20 May 2005 coudercd * fixed a bug in chkpath() when the parser come to the beginning of the string and that it does not start with a separator. 14 May 2005 coudercd * added hash_keys_sorted() which returns a sorted list of keys. * update of style for function header comments. * added parse_asm_file() to parse assembly files. * improvements to pmkscan. * misc change in compat module. 07 May 2005 coudercd * imported new compatibility layer. * polished pmkscan output. 04 May 2005 coudercd * improved target's object dependencies scanning in pmkscan. * removed useless pmkshgen* files as the idea will be implemented in pmkinstall. 25 Apr 2005 coudercd * fixed a bug that prevent --list-all option to work in pmkpc. * added missing variable substitution for library path in pmkpc. 21 Apr 2005 coudercd * modified pmkscan to use parse_lang. * improved the -m option of pmkscan. * fixed/improved stuff in prseng. * updated plang test. 17 Apr 2005 coudercd * updated parse_lang in sync with latest changes. 13 Apr 2005 coudercd * added missing parts for pmk and pmksetup, tree should be still broken due to the missing parts i did not committed yet. * added missing parts for pkgconfig object. 12 Apr 2005 coudercd * updated parse.c to use prseng functions. * added detection of C99 and C89 compilers. 07 Apr 2005 coudercd * imported the more than experimental c file parsing engine. This is still work in progress but is largely useable. * imported tests/plang_test.c to test c file parser. 06 Apr 2005 coudercd * imported new main engine of pmkscan to permit generation of pmkfile and makefile templates. This does not include the new file parser. 05 Apr 2005 coudercd * import of prseng sources, a set of functions to manage a parsing buffer. It will be used in pmkscan and later by the pmk parser. # snapshot 0.9.2-s1 23 Mar 2005 coudercd * added option checking for compiler data. * improved option checking so we can specify required options and allow any optional options. Or having no required options but a specified bunch of optional options. # snapshot 0.9.2-s1 23 Mar 2005 coudercd * added option checking for compiler data. * improved option checking so we can specify required options and allow any optional options. Or having no required options but a specified bunch of optional options. 20 Mar 2005 coudercd * improved the parser to allow type checking of options. 17 Mar 2005 mreindl * pmkcfg.sh: fall back to 'cc -E' when cpp isn't available and obey $CPP when set. 13 Mar 2005 coudercd * added option checking in parser. * comment cosmetics in parser. 25 Feb 2005 coudercd * implemented backup options in pmkinstall. 05 Feb 2005 coudercd * fragmented pmkinstall main loop into sub functions. # PMK 0.9.2 release 29 Jan 2005 coudercd * fixed the -v option of pmksetup. * fixed pmksetup behavior when the user has not the required privileges. * moved the configuration directory checking earlier in the program execution. # PMK 0.9.1 release 26 Jan 2005 coudercd * fixed segfault in x86 cpu detection. * added __ALPHA in alpha architecture macro. * fixed call order for setegid(), setgid(), seteuid() and setuid(). 21 Jan 2005 coudercd * keep the PATH separator as is instead of replacing it with a comma. NOTE: This means that you must update your pmk.conf before using pmk again. * added a debug mechanism in pmksetup to work without fork and privsep. * fixed keycomp() by reverting changes that broken sorting. * added more information about pmk.conf in its manual page. 20 Jan 2005 coudercd * fixed skip_useless() to update frame buffer. 18 Jan 2005 coudercd * moved pmksetup into bin instead of sbin. * use lists for install and deinstall. 17 Jan 2005 coudercd * merged PRIVSEP branch. 13 Jan 2005 coudercd * more stuff for ia64 cpu detection. 12 Jan 2005 coudercd * added basic ia64 cpu identification. 06 Jan 2005 coudercd * made pmksetup more verbose on cpu detection failure. 02 Jan 2005 coudercd * added alpha cpu identification. # PMK 0.9.0 release 27 Dec 2004 coudercd * improved handling of CFLAGS and LDFLAGS with pmkcfg.sh * added x86 64 bits cpu detection code. 26 Dec 2004 coudercd * added snprintf_b(), strlcat_b() and strlcpy_b() in pmk_string.c. * added support for AMD cpu feature detection. * replaced some snprintf(), strlcat() and strlcpy() with their boolean counterparts. 25 Dec 2004 coudercd * fixed respect of CC in pmkcfg.sh script. * added DEFS usage in pmkfile.5. * updated pmkfile. * improved pmkcfg.sh to provide full path in check_binary(). * updated pmk.conf.5 to reflect latest changes. * more warning fixes in compat found with aggressive compiler options. 23 Dec 2004 coudercd * fixed use of the assembler to comply with SunOS. 22 Dec 2004 coudercd * fixed a lot of compiler warnings (almost all about comparison between signed and unsigned) that were revealed with 'aggressive' options. 20 Dec 2004 coudercd * reworked CHECK_LIB in the same spirit as CHECK_HEADER. * replaced remaining copy_text_file() by fcopy(). * removed copy_text_file() from common object as it is useless now. 19 Dec 2004 coudercd * added c_file_builder() to reduce redundant code. * added MACRO option in CHECK_HEADER to detect compiler macros in headers. * removed copy_config() from pmksetup and use fcopy() instead. 11 Dec 2004 coudercd * added detection of 'id' and 'sudo' in pmksetup, idea from Sean Chittenden. 06 Dec 2004 coudercd * added detection of 'ls' and 'echo' in pmksetup. 27 Nov 2004 coudercd * added cpu features for x86 architecture. # snapshot 0.8.1-s9 27 Nov 2004 coudercd * incorporated x86 cpu detection code into pmksetup, enjoy ! * miscellaneous cosmetics changes. 26 Nov 2004 coudercd * made cpuid_test using compat. * done major clean-up in tests directory (but still need some work). * fixed a bug in x86_get_cpuid_data() that was remaining from before x86_cpu_cell structure changes. 25 Nov 2004 coudercd * added missing code that translate arch name into id. * improved architecture detection code. 24 Nov 2004 coudercd * x86 cpu detection engine is complete, need more data now. 21 Nov 2004 coudercd * improved tests/Makefile to preprocess assembly files by default. * added detection of cc,cpp and as in pmkcfg.sh. * added generation of tests/Makefile from a template. * improved Makefile to preprocess assembly files by default. 17 Nov 2004 coudercd * modified x86 cpu detection stuff to use less assembly. 05 Nov 2004 coudercd * improved cpu arch detection in pmksetup. * added some x86 cpu detection stuff used by tests/cpuid_test. 01 Nov 2004 coudercd * misc changes before cpu detection. 27 Oct 2004 coudercd * added 'as' (assembler) detection in pmksetup. 25 Oct 2004 coudercd * fixed pmkcfg.sh on IRIX. 18 Oct 2004 coudercd * improved pmkcfg.sh to try to detect posix shells before using /bin/sh (this fix the Tru64 and SunOS lack of default posix shell problem). 11 Oct 2004 coudercd * imported experimental cpu family detection. # snapshot 0.8.1-s8 26 Sep 2004 coudercd * updated pmkfile.5 to sync with latest changes. * updated README and INSTALL to warn about non POSIX compliant shells. 26 Sep 2004 coudercd * improved CHECK_LIB to handle more than one function. 24 Sep 2004 coudercd * CHECK_HEADER is now able to check more than one function (feature asked by Gergely Czuczy). * fixed initialisation of some variables in pmk.c (noticed on irix). * updated samples/bin_c to use config.h and one check for strl*() functions. 23 Sep 2004 coudercd * returned on getopts use in pmkcfg.sh to handle blanks in arguments. # snapshot 0.8.1-s7 10 Sep 2004 xsa * imported some IRIX stuff in pmkcomp.dat. 06 Sep 2004 coudercd * improved pmkcfg.sh function to return test status (0 or 1). 05 Sep 2004 coudercd * added check_lib_function() in pmkcfg.sh (preliminary stuff). 29 Aug 2004 coudercd * more process_required(), less redundant code. 28 Aug 2004 coudercd * added process_required() to remove redundant code for required flag. # snapshot 0.8.1-s6 28 Aug 2004 coudercd * fixed a bug introduced by an improvement while fixing config file parsing. # snapshot 0.8.1-s5 27 Aug 2004 coudercd * fixed bugs in parse_pmkconf(). * added more debug stuff. 21 Aug 2004 coudercd * added compiler flags in sample bin makefiles. 20 Aug 2004 mreindl * add bin_c++ sample 20 Aug 2004 coudercd * move backup right before copy of new config file. 19 Aug 2004 mreindl * backup pmk.conf in pmksetup if it already exists * update bin_c sample and integrate it into samples/Makefile # snapshot 0.8.1-s4 15 Aug 2004 coudercd * added missing support of additional defines in CHECK_CONFIG and CHECK_PKG_CONFIG. 08 Aug 2004 coudercd * added support for additional defines (keyword DEFS) in CHECK_HEADER, CHECK_LIB, CHECK_TYPE and CHECK_VARIABLE. * set option keywords as defines. * modified str_to_def() to use static buffer. * added record_def_data() that generate both DEF__* and HAVE_* records. * better handling of the additional defines. 08 Aug 2004 mreindl * added -fPIC in SLLDFLAGS for gcc. 05 Aug 2004 coudercd * fixed makefile template of c++ lib sample. 04 Aug 2004 mreindl * sprinkle some -fPICs in c++ lib sample for AMD64 platform. * spacing nitpicking in pmkcomp.dat. 02 Aug 2004 coudercd * fixed pmk_set_variable() to check type of value to prevent coredump on syntax error (noticed by Han Boetes). * removed redundant (and confusing dependency in samples/pmkfile.sample (noticed by Han Boetes). * added ELSE command to be less confusing than IF(!label). * updated pmkfile.5 with new ELSE command. # snapshot 0.8.1-s3 28 Jul 2004 coudercd * added lex and yacc detection in pmksetup (request from chandlerc). * processed some XXXs. 25 Jul 2004 coudercd * improved configuration header processing in autoconf support. # snapshot 0.8.1-s2 18 Jul 2004 coudercd * clean up the code before starting to play with parse_data(). * fixed getopt() parameters in pmkscan. * added option to parse config file in parser_test. * modified parse_pmkconf() to use prseng structure. * improved parser to be able to process a multiple lines list. * modified pmkscan.dat to put list data in multiple lines. * fixed C++ library sample. 13 Jul 2004 coudercd * misc fixes and cleanup for experimental parsing engine. 12 Jul 2004 coudercd * imported experimental parser engine. * synced parser test. 11 Jul 2004 coudercd * fixed compatibility headers. 28 Jun 2004 coudercd * added variable substitution in pmkscan. * cleaned-up Makefile.pmk (obsolete tests). 27 Jun 2004 coudercd * added more stuff to prepare changes in pmkscan. 26 Jun 2004 coudercd * moved process_string() and single_append() into hash_tools. * updated pmkfile (was using obsolete commands). 16 Jun 2004 coudercd * fixed parse_pc_file(). * fixed process_variables(). * misc. changes. 22 May 2004 coudercd * hunted some more XXX ... 16 May 2004 coudercd * fixed some XXX remaining in parse.c and pmkinstall.c. 11 May 2004 coudercd * fixed samples to run properly. * added missing error messages. * added misc defines for LIBS and CFLAGS. # snapshot 0.8.1-s1 02 May 2004 coudercd * fixed a bug recently introduced in CHECK_PKG_CONFIG. 24 Apr 2004 coudercd * more stuff related to the pmksetup engine changes. 15 Apr 2004 coudercd * added new engine for pmksetup. Some minor changes are still remaining but pmksetup is working fine. 01 Apr 2004 coudercd * imported skeleton of pmkshgen. * fixed use of parse_clopt's value in pmk and pmksetup. * booleanification of pmksetup. * added handling functions for prsopt structures. # PMK 0.8.1 release 14 Mar 2004 coudercd * modified a bit the version string format. 29 Feb 2004 coudercd * added failsafe checks in dynarray functions, based on a patch from Marek Habersack. * fixed pkgcell_destroy() to call free() only when needed, based on a patch from Marek Habersack. * added MODULE option to CHECK_CONFIG command. 25 Feb 2004 coudercd * moved tests for pmkscan and pmkinstall. * fixed pmkc against segfault when .pc doesn't exists or empty requires field, based on a patch from Marek Habersack. 21 Feb 2004 coudercd * fixed pmkscan bug that happens when no sources files exist, noticed by Marek Habersack. * updated pmkscan.dat to check for strndup(), strndupa() an vsyslog(), from Marek Habersack. 16 Feb 2004 mreindl * update pkgsrc and OpenBSD ports to 0.8 # PMK 0.8 release 14 Feb 2004 coudercd * added missing tutorial stuff for release. 13 Feb 2004 coudercd * updated the tutorial to speak about command label (noticed by Kurt V. Hindenburg). # snapshot 0.7.13 12 Feb 2004 coudercd * added parse_clopt() to handle line command options. * added support for addition and removal of variable in pmksetup. * fixed command line option support in pmk. * updated pmksetup.8 man page about -r and -u options. 10 Feb 2004 coudercd * added 2 sections to the tutorial. * updated pmkfile.5 with shared library name building. 09 Feb 2004 coudercd * rewritten pmkinstall to permit multiple directory creation. * updated pmkinstall man page. * updated usage() of pmkinstall. * fixed Darwin entry in pmkcomp.dat file. * imported the beginning of a tutorial. * rewritten a bit shared lib support and pmkcomp.dat format. 08 Feb 2004 coudercd * implemented output filtering options in pmkpc. * updated pmkpc(1) to sync with actual state. * added support for multiple sources in pmkinstall. * added support for case when destination is a directory in pmkinstall. * fixed str_to_ulong() to use an unsigned long like said by the name. * replaced use of strtoul() by str_to_ulong() in pmkinstall. * fixed check_mode() in pmkinstall to behave as BSD install. 07 Feb 2004 coudercd * fixed building of the pmkscan location in usermode. * moved sample tests in samples/Makefile. * added document headers that were missing in some files. # snapshot 0.7.12a 07 Feb 2004 mreindl * fix braino that got introduced with the bcopy -> memmove switch in parse.c # snapshot 0.7.12 05 Feb 2004 coudercd * converted pmk_set_parameter() to a wrapper. * added sub-functions for pmk_set_paremeter(). * added system specific overriding support of compiler flags. 05 Feb 2004 mreindl * replaced getopts with getopt in pmkcfg.sh * added pkgsrc stuff for stable and snapshot * big STATUS updates, pmk tested on nearly every Unix out there with C-only support 04 Feb 2004 coudercd * improved process_string() to be recursive. * imported experimental shared lib support. 27 Jan 2004 coudercd * fixed wrong check of init_var(). 26 Jan 2004 coudercd * fixed a bug in pmkpc that occurs when using non implemented option in pmkpc (noticed by xixi ;). 25 Jan 2004 coudercd * added support for --atleast-pkgconfig-version in pmkpc. * added man page for pmkpc. * added missing checks for hash_update* almost everywhere. * implemented --list-all in pmkpc. 25 Jan 2004 sourceforge * repaired developer cvs server 22 Jan 2004 sourceforge * broken developer cvs server 21 Jan 2004 xsa * added the --usage option in pmkpc. * added the --help option in pmkpc. 21 Jan 2004 coudercd * use str_to_ulong() in functool and pmkinstall. * added compare_version() in pkgconfig for version string comparison. * updated func to use compare_version() instead of check_version(). * removed check_version() from functool. * added support for option argument in pmkpc. * added support for --atleast-version, --exact-version and --max-version in pmkpc. 20 Jan 2004 coudercd * moved size type from int to size_t for most functions in common. * added str_to_ulong() in common for string to unsigned long conversions. 19 Jan 2004 xsa * imported sample test for C binary. 17 Jan 2004 coudercd * fixed specific deinstall stuff in Makefile. * fixed setting of shared lib cflags. * fixed init of ac_file and lang in global data. * added support for shared libs linking flags. * imported sample test for C shared library. # snapshot 0.7.11 16 Jan 2004 coudercd * fixed parse_pc_file() to use pkgcell_init(). * improved init of pmk's global data. * fixed some files to use our compatibility wrappers. 14 Jan 2004 coudercd * imported cfgtool.c and cfgtool.h to store config tool related code. * updated func.c to use cfgtool new functions. * moved config tool stuff from pkgconfig to cfgtool. * moved pmkcmd an pmkcmdopt typedefs to common. * improved pmkpc to fall back on config tool if module is not found. * added missing pkg-config options to pmkpc as 'not implemented' yet. 13 Jan 2004 coudercd * improved pmkpc to not care about argument order (like pkg-config). * added support for multiple module. * moved get_file_path() from functool to common. * moved process_opt() from pmk to parse. 12 Jan 2004 coudercd * imported preliminary code for our pkg-config alternative. * got rid of cfgrm, cfgum and config targets in Makefile template. * added showmode, sm and fclean targets in Makefile template. * modified clean target in Makefile template. * updated pmkcfg.sh and pmkfile to set the used mode. * added support for pmkpc in Makefile template. * removed Makefile which is now useless. * updated documentation. 11 Jan 2004 coudercd * added more C++ support in some checks (handle CXXFLAGS when needed). * improved some checks to be more verbose on used variables. * removed a fix into check_config() that was wrong. * added check_cfgt_data() to load config tool data only when needed. # snapshot 0.7.10 08 Jan 2004 coudercd * fixed segfault on some platform when cleaning cfgtdata. 06 Jan 2004 coudercd * fixed recording of cfgtool path in pmk_check_config(). 05 Jan 2004 coudercd * improved check_mode() in pmkinstall.c, patch provided by Pedro Martelletto. * improved a bit pmkcfg.sh to use a list of templates. * set INSTALL back to install and added a special comment for HPUX. * changed hash.c and hash.h to use better types. * fixed pmkinstall bug when destination already existed. * INSTALL can now safely set (back) to pmkinstall. 03 Jan 2004 coudercd * fixed get_make_var() by replacing misused mkstemp() by tmps_open(). * simplified mkstemps() to remove warnings about the cast. * improved a bit comp_test.c to display more info. * fixed compiler detection failure. * fixed makefiles for HPUX. * fixed pmkcomp.dat to use unique id for each compiler definition. * fixed use of int64_t on the Tru64 platform. # snapshot 0.7.9 02 Jan 2004 xsa * added PC_PATH_LIB to pmk.conf (look if PREFIX/lib/pkgconfig exists). * updated pmk.conf.5 accordinally. 02 Jan 2004 coudercd * added diverting from CHECK_PKG_CONFIG to CHECK_CONFIG. * added data file for specific config tool options. * added support for specific config tool options (huge). * finalized pkgconfig support. 01 Jan 2004 coudercd * added pkg_cell_add() and pkg_mod_exists() in pkgconfig. * rewritten pkg_recurse() to use pkg_cell_add(). * updated test/pkgconfig_test.c in sync pkgconfig support changes. * wished happy new year :) * introduced internal pkgconfig support in CHECK_PKG_CONFIG. 31 Dec 2003 coudercd * added str_to_dynary_adv() to handle numerous separators. * changed str_to_dynary() to reuse str_to_dynary_adv() code. * rewritten and cleaned pkgconfig stuff. * updated pkgconfig_test.c to sync with changes. * added pkgcell_init(). * added pkg_single_append() to avoid duplicates. * implemented pkg_get_cflags() and pkg_get_libs(). * misc changes in pkgconfig_test. 30 Dec 2003 coudercd * imported some code for internal support of pkgconfig. * added pkgconfig_test.c in tests. * added variable substitution in pkgconfig support. * added pkg_recurse() in pkgconfig to prepare for recursion. 29 Dec 2003 coudercd * moved hash_add() as hash_update() and kept hash_add() as an alias. * updated hash_init_adv() to support data duplication. * updated hash_init() in sync with hash_init_adv(). * added hash_update_dup() to automatically duplicate given data. * updated use of hash_add() in favor of hash_update() and hash_update_dup() in all files but pmksetup.c (check soon). * commented some code in autoconf.c which seems to be specific to dillo but not to autoconf. * made consistent use of boolean string values. * replaced remaining hash_add() calls in pmksetup. 28 Dec 2003 coudercd * added check_lang_comp() into functool to get lang info via compiler. * added code to set shared lib flags (SLCFLAGS and SLCXXFLAGS). * updated pmkcomp.dat to sync with shared lib support. * updated samples to sync with shared lib support. * fixed some hash_add() calls that were not using strdup(). # snapshot 0.7.8 23 Dec 2003 coudercd * moved compiler detection in SETTINGS section using DETECT option. * fixed bad stuff discovered by lint (wasn't changing pmk's behavior). * added some data in pmkcomp.dat about shared libs. * updated pmkfile.5 man page. 20 Dec 2003 coudercd * avoided use of srandomdev() in mkstemps as it is not portable. 19 Dec 2003 coudercd * added mkstemps.c, mkstemps.h and pmk_unistd.h in compat directory. * added detection of mkstemps() in pmkcfg.sh and pmkfile. * fixed pmkcfg.sh for function detection in an header. * replaced unistd header includes by pmk_unistd header. 18 Dec 2003 coudercd * fixed detect.c and func.c to use correctly tmps_open(). # snapshot 0.7.7 17 Dec 2003 coudercd * added pmkcomp.dat in data directory. * moved compiler detection data in pmkcomp.dat file. * modified detect.c and detect.h to use data from dat file. * updated pmk.c and tests/comp_test.c to sync with previous changes. * added pmkcomp.dat support in makefile. * fixed makefile to use correct path (DATADIR, BINDIR). * fixed check_header() to also clean object files. * fixed prsdata_destroy() to avoid segfault when NULL is provided. * added missing comments, cleaned-up code. * added better handling of the version when unknown. 15 Dec 2003 coudercd * added gen_test_file() to automate test file generation in detect. * improved detect_compiler() to store data about the compiler. * updated use of detect_compiler() in pmk. * added comp_test.c in tests directory. * fixed function detection in CHECK_HEADER. * added support for sudo in makefiles. * improved cleaning and added missing code in detect_compiler(). # snapshot 0.7.6 12 Dec 2003 coudercd * added tmp_open() in common. * updated func.c to use tmp_open(). * changed remaining fprintf() to sterr into errorf() in common. * added preliminary TMPDIR stuff. * rewritten tmp_open() and added tmps_open() in common. * finished c test file randomization in func. * randomized temporary ac config file in ac_parse_config(). * added detect.c and detect.h for compiler detection. * updated pmk to display detected compiler. 10 Dec 2003 coudercd * added new option to pmk to enable check build logging. * updated pmk man page with new -l option. 09 Dec 2003 coudercd * added MEMBER in CHECK_TYPE to check structure member. * updated pmkfile man page to sync with MEMBER addition. 06 Dec 2003 coudercd * moved fcopy() from pmkinstall to common. * add many missing code that was marked with XXX tags. (autoconf.c, common.c, func.c, functool.c) # snapshot 0.7.5 30 Nov 2003 coudercd * added optional HEADER in CHECK_TYPE command. * updated pmkcfg.sh and pmkfile to check blkcnt_t correctly. 29 Nov 2003 coudercd * added use of POSIX macro for exit() status in parse.c, pmk.c, pmkinstall.c and pmkscan.c files. * added support for suid and sgid flags in pmkinstall. * finished strip support in pmkinstall. * re-enabled pmkinstall build in makefiles. * added test_pmkinstall in test_all target in makefiles. * added mkvar_test.c in tests directory. * added mkvar target in tests makefile. * rewritten get_make_var() to work with gnu make. * added compat to I_OBJS to fix pmkinstall build. * added stuff related to blkcnt_t type. 27 Nov 2003 coudercd * updated pmkinstall man page. 27 Nov 2003 xsa * added ECHO_N, ECHO_C, ECHO_T variables to pmk.conf for autoconf compat. * sync pmk.conf(5) man page with the ECHO_* variables addition. 26 Nov 2003 coudercd * added test_pmkinstall target in makefiles. * improved mode operator support in pmkinstall. 25 Nov 2003 coudercd * added support for -o and -g options (owner and group) of pmkinstall. * added mode argument to makepath() in pathtools. * updated pmk.c to provide mode to makepath(). * moved defines from source to header in pathtools. * added support for -d option (directory creation) of pmkinstall. * updated makefiles to include pathtools for pmkinstall. * added some code for strip support in pmkinstall. 24 Nov 2003 coudercd * started to rewrite pmkinstall from scratch (much easier than making xinstall portable). * implemented -m option (only octal values) of pmkinstall. * added basic support for symbolic values in -m option of pmkinstall. 23 Nov 2003 coudercd * removed oboslete definitions in kw_pmkscan[]. # snapshot 0.7.4 18 Nov 2003 coudercd * added DESTDIR and fixed Makefiles. # snapshot 0.7.3 18 Nov 2003 coudercd * disabled build of pmkinstall as it's still work in progress. * added some getopts options to pmkcfg.sh (prefix override). * updated Makefile.pmk and Makefile in sync with pmkcfg.sh changes. * updated README and INSTALL to sync with pmkcfg.sh changes. 17 Nov 2003 coudercd * removed stuff in pmkinstall to make sunos happy. 14 Nov 2003 coudercd * replaced remaining warn() and warnx() calls in pmkinstall. 13 Nov 2003 coudercd * removed err() and errx() calls and replaced by errof() in pmkinstall. * removed paths.h in pmkinstall. # snapshot 0.7.2 10 Nov 2003 coudercd * fixed init of CXXFLAGS. * added init of CXX. # snapshot 0.7.1 07 Nov 2003 coudercd * improved init of CFLAGS, CXXFLAGS, CPPFLAGS, LIBS, LDFLAGS and DEBUG with values gathered from make. * changed target of get_make_var() from test to all. * enabled pmkinstall in Makefile and Makefile.pmk including man page. * added pmkinstall man page. * modified compat.c to make ansi compiler happy. 04 Nov 2003 coudercd * added makepath() in pathtools. * modified process_template() to use makepath(). 27 Oct 2003 coudercd * updated Makefile.pmk to build in a test directory. * rewritten ac_parse_config() and fixed AC_COMPAT to be relative to pmkfile location * added defines for pmk's specific directories (builddir, ...). * updated samples of pmkfile and Makefiles. * use pmk values for autoconf directories. * modified arguments of ac_process_dyn_var() and process_dyn_var(). * reorganised order of autoconf directories in Makefiles samples. 18 Oct 2003 coudercd * fixed computing of top_srcdir. * added processing of dynamic variables in pmk. * added creation of directories in template processing. * changed init_var() arguments. * updated pmkfile. 14 Oct 2003 coudercd * removed obsolete stuff (mostly compat with 0.6 syntax). # PMK 0.7 release 12 Oct 2003 coudercd * removed stuff not related to autoconf into ac_set_variables(). * added some more stuff in ac_set_variables(). * changed init of alternative variables in func. 10 Oct 2003 coudercd * improved process_template(). * fixed computing of top_srcdir in ac_process_dyn_var(). * more changes in ac_set_variables(). # snapshot 0.6.6 07 Oct 2003 coudercd * more autoconf compat. * added target for pmkinstall in Makefile.pmk. * updated Makefile. * fixed missing '/' in pmkscan.h. 06 Oct 2003 coudercd * finished addition of third license clause. 05 Oct 2003 coudercd * added missing variables for autoconf compatibility. * added third license clause to almost all the files. * imported pmkinstall tools for further use. * added more third license clause into compat directory. 02 Oct 2003 coudercd * renamed pmk_check_include() by pmk_check_header(). * removed a useless free() in single_append(). 01 Oct 2003 coudercd * added premk-cvs@lists.sourceforge.net to get commit messages. * updated pmkfile man page. * added init_var() in pmk to set specific variables. * added more stuff in ac_set_variables(). * added PMKCONF_BIN_CC in premake header. * more in init_var() and ac_set_variables(). * improved process_template() to set configure_input tag. 30 Sep 2003 coudercd * changed USERMODE by PMK_USERMODE to avoid conflicts. * fixed hash_str_append() in hash. * more debug messages in hash. * fixed single_append() in functool. * improved pmk_check_lib() to use optional LIBS variable. 28 Sep 2003 coudercd * added find_file_dir() in common. * rewritten find_file() to use find_file_dir(). * added get_file_dir_path() and single_append() in functool. * disabled temporay override in DEFINE command. * fixed pmk_check_variable(). * added VARIABLE in CHECK_CONFIG to store config tool path. * added CFLAGS in CHECK_HEADER to store in an alternative variable. * put Makefile back in root mode. # snapshot 0.6.5 27 Sep 2003 coudercd * improved process_string() to allow escaping of $ character. * improved parse_quoted() to not eat escape characters. * added mkf_sed() and renamed do_sed() to templ_sed() in pmkcfg. * improved Makefile to switch easily between root and user mode. * created Makefile.pmk * updated pmkcfg.sh and pmkfile to sync with Makefile changes. * synced pmkscan, pmksetup and premake.h with usermode changes. * updated README and INSTALL. * fixed pmk_switches() and missing escape in pmkfile. * bunch of fixes and cosmetics changes before next snapshot. * fixed vicious bug in pmksetup that results in segfault on tru64. 26 Sep 2003 coudercd * added support to negate labels in conditions like DEPEND or IF. * updated pmkfile.5 to sync with latest changes. * fixed pmk_switches() for use of bool type. 25 Sep 2003 coudercd * added prs_get_line(), parse_node(), parse_command() and parse_line() to allow use of real nodes (aka commands into another command). * rewritten parse_pmkfile() to use new functions. * updated test/parser_test.c to sync with latest changes. * added pmk_ifcond() into func.c to manage new 'IF' keyword. * updated pmkfile sample to use 'IF' keyword. 22 Sep 2003 coudercd * added small support for DEFS. # snapshot 0.6.4 20 Sep 2003 coudercd * added ac_set_variables() in autoconf. * added autoconf compatibility stuff for byte order. 19 Sep 2003 coudercd * made syntax more simple, now all the checks use NAME for the main target (example in CHECK_TYPE, NAME contain the type to check). * added CHECK_HEADER which does the same thing as CHECK_INCLUDE which is obsolete but kept for compatibility. * added pmk_check_variable() tu support CHECK_VARIABLE. * updated pmkfile.5 man page to sync with previous changes. * updated pmkfile sample. 18 Sep 2003 coudercd * improved str_to_dynary() to init and return dynary structure. * updated use of str_to_dynary in func, funtool, pmk and pmksetup. * changed syntax of path variables in pmk configuration file. * updated func.c to match with new PATH_* variables but kept the compatibility with old format. * added warnings for obsolete variables in both pmk and pmksetup. * updated pmk.conf.5 to match with PATH_* variables. * fixed parse_pmkconf() to take care of comment and blank lines as * fixed pmk to take care of parse_pmkconf() changes. * fixed pmksetup to keep comments and blank lines when updating the configuration file. * rewritten predef_vars() in pmksetup (i feel better like that :). * updated pmk.conf sample. * added pkg-config detection in pmksetup. * updated pmk_check_pkg_config() to use BIN_PKGCONFIG if provided. 15 Sep 2003 coudercd * removed useless parse_conf_line() in common. * added function comments that were missing. 14 Sep 2003 coudercd * made Makefile more portable. # snapshot 0.6.3 14 Sep 2003 coudercd * finished global language support. * fixed parsing of bool data in compatibility mode. * added parse_pmkconf(), a common configuration file parser (pmk.conf). * added process_opt() and modified pmk to use parse_pmkconf(). * removed read_conf() which is now useless in pmk. * added check_opt() and modified pmksetup to use parse_pmkconf(). * removed parse_conf() which is now useless in pmksetup. * updated pmkfile.5 and pmk.conf.5 man pages. * updated override file sample. 13 Sep 2003 coudercd * added dumping of pmk.conf in test_pmksetup target of Makefile. * added parse_obsolete() for pmk.conf compatibility with old format. * modified parse_opt() to check a list of operator instead of '=' by default. This permit to use it from pmksetup and pmk. * updated read_conf() and parse_conf() to use parse_opt(). * defined write format for pmk.conf in pmksetup.h (see PMKSTP_WRITE_FORMAT). 11 Sep 2003 coudercd * added bool object in pmk objects. * added bool object support in parser. * updated require_check() to support bool object. * updated pmkfile. * fixed pmkfile sample. * rewritten str_to_def() to have full compatibility with autoconf. 10 Sep 2003 coudercd * added parse_key() and parse_data() to enforce syntax checking. * removed parse_word which became useless. * added warning for AC_COMPAT and TARGET to mark them as obsolete. * misc cosmetics in pmkfile sample. # snapshot 0.6.2 06 Sep 2003 coudercd * more stuff to permit node command (i will explain later). * modified parse_cell() and prscell_init() to meet our current goal. * added more stuff again for node command. * finished node command stuff. * enabled SETTINGS command. * converted DEFINE command as node. * defined values can contain variable. * added some support for global language. * updated pmkfile.sample and pmkscan.dat to new format. * removed redundant code in pmk_target() and pmk_ac_acompat(). * updated pmkfile man page. 05 Sep 2003 coudercd * improved parser engine again (first part). * new pmk language style (no longer need leading dot) but keep compat with 0.6 release. * adapted pmk to new engine. * adapted pmkscan to new engine. * added stuff to parse variables in strings (deactived). * misc related stuff. * fixed and enabled variable parsing in pmk_define(). # snapshot 0.6.1 02 Sep 2003 coudercd * added byte_order_check() in pmksetup to set HW_BYTEORDER. 01 Sep 2003 coudercd * added invert_bool() and get_comp_path() in functool. * improved language checking and compiler path setting in func. * small improvement of pmk_target(). * cleaned po_get_data() use in func. 30 Aug 2003 coudercd * added VARNAME in CHECK_BINARY to specify alternate storage variable. * fixed deinstall target in Makefile. 28 Aug 2003 coudercd * added missing checks. * style. 23 Aug 2003 coudercd * added switches support. * update man pages about switches. # PMK 0.6 release 23 Aug 2003 coudercd * changes for 0.6 release. # snapshot 0.5.6 22 Aug 2003 coudercd * misc fixes # snapshot 0.5.5 21 Aug 2003 coudercd * changed type of DEPEND, it must be a list now. * LIST in TARGET command is now of the list type. * allow use of lists in pmkscan data file. * added code to set the language of a check in pmkscan. * updated pmkfile.5 man page. * added arguments to pmkscan (-v -h and optional path). * added pmkscan.1 man page. 20 Aug 2003 coudercd * added hash_add_array_adv() in hash. * add support for isblank() in compat. 18 Aug 2003 coudercd * added po_get_str() and po_get_list in pmk_obj. 17 Aug 2003 coudercd * fixed a small bug in depend_check(). * finished parser improvement for list parsing. 16 Aug 2003 coudercd * added po_dup() in pmk_obj. 15 Aug 2003 coudercd * added po_append() to pmk_obj. * adapted solution of dynarray to hash functions. * sync with new hash functions. 14 Aug 2003 coudercd * found a better solution to handle structure freeing in dynarray. * reversed changes relative to use of pmk objects with dynarray. 13 Aug 2003 coudercd * more (disabled) stuff for list support. 12 Aug 2003 coudercd * renamed pmk objects function in the same style as hash and dynarray. * misc renaming into sources. * switch dynarray to use pmk objects. * added preliminary support for list in parser. 11 Aug 2003 coudercd * added pmk objects. * added pmk object support in hash. * added pmk object support in dynarray. * changes to use pmk objects with hast tables. * removed incorrect code in pmksetup and added use of get_line. # snapshot 0.5.4 09 Aug 2003 coudercd * more stuff in pmkfile man page. * some changes in pmkscan data file. * some changes in pmkfile too. 08 Aug 2003 coudercd * rewritten parse_cell() in the same spirit as parse_opt(). * modified parse_cell() and parse() to parse new and old format of pmkfile. * updated pmkfile.5 with new format syntax. * update pmkfile sample to new format. * modified Makefile to configure with pmk if previous version is already installed. * added support of escape character in quoted string. * added missing error messages in parse_quoted(), parse_list() and parse_word(). * update pmkscan.dat to new parser format. 07 Aug 2003 coudercd * rewritten parse_opt(). * updated sample files to work with the new parser. * added parser_test.c into test directory. * added parse_word(), parse_quoted(), parse_list() and skip_blank(). * rewritten parse_opt() again to be more compact, simple and efficient. 01 Aug 2003 coudercd * added test_pmkscan target plus some cosmetics in Makefile. # snapshot 0.5.3 01 Aug 2003 coudercd * fixed a bad free() in pmkscan. 31 Jul 2003 coudercd * improved dynarrays to store void* instead of char*. * fixed use of new dynarrays. * updated man/pmkfile.5 to sync with reality. 30 Jul 2003 coudercd * massive style conforming. 29 Jul 2003 coudercd * style, descriptions and misc in pmk. * added pmk_check_type() and some style cosmetics in func. * updated pmkfile sample to use CHECK_TYPE. 28 Jul 2003 coudercd * improved dir_explore(). * added scanning support for c++ files. * added da_shift() and da_resize() in dynarray. * improved da_pop() and da_push() in dynarray. * changed return type of da_size() and da_usize() in dynarray. * updated test/da_test.c to use da_shift(). 26 Jul 2003 coudercd * added dir_recurse() in pmkscan to make it scanning a complete tree. * added missing function comments in parse.c . * added prsdata_destroy(). * re-enable error messages in parse(). * added init checks. # snapshot 0.5.2 24 Jul 2003 coudercd * added dir_explore() as first step to recursivity. 23 Jul 2003 coudercd * added detection and processing of functions in pmkscan. * replaced free() by hash_free_hcell() where needed in hash. * misc in pmkscan. * fixed ac_process_dyn_var(). * another misc changes in pmkscan. * two other fixes in hash. 22 Jul 2003 coudercd * rewritten hash_keys() to return a new structure (hkeys). * fix use of hash_keys() in sources. 21 Jul 2003 coudercd * added output_file() and misc in pmkscan. * improved hash functions to work with (void*) instead of (char*). * update all files that use hash_add() and hash_get(). * improve pmkscan for data parsing and output file. * updated data/pmkscan.dat file. * updated Makefile to install pmkscan. * use USER_TEST to define where to find pmkscan.dat file. 19 Jul 2003 coudercd * updated STATUS * fixed test/Makefile for portability. * misc in pmkscan (not debugged). # snapshot 0.5.1 17 Jul 2003 coudercd * added a check for _Bool type (fix for Tru64 >= 5.x and solaris 9). 16 Jul 2003 coudercd * misc changes in pmkscan.c to use regex. * added sub versions for all tools. * added display of subversion and snapversion in debug mode. * misc replacements in pmksetup. * misc checks. * added pmkscan in Makefile. * added missing pmkscan.dat in data. 15 Jul 2003 coudercd * add parse.c and parse.h with a new shared parsing engine. * add pmkscan.c and pmkscan.h, this is preliminary and unusable code. * pmk now use the new parsing engine. 05 Jul 2003 coudercd * added c++ in the binary list of pmksetup. * modified get_lang(). * added c++ support in pmk_check_include() and pmk_check_library(). * updated pmkfile sample to use c++ in one test. 02 Jul 2003 coudercd * added get_lang() as preliminary work on C++ support. * fixed a memory fault in pmk and corrected a typo (noticed by Ritschard Pierre-Yves). # PMK 0.5 release 30 Jun 2003 coudercd * changes for 0.5 # snapshot 0.4.7 27 Jun 2003 coudercd * fixed hash_destroy() to support null pointer as argument (noticed by Marek Habersack). * fixed use of dirname to avoid modification of the original string under linux (noticed by Marek Habersack). * added init of CFLAGS and LIBS alternatives in pmk_chek_config() and pmk_check_pkg_config(). # snapshot 0.4.6 26 Jun 2003 coudercd * added override file sample. * updated Makefile to use override file sample. * added subdir makefile example. * rewritten *srcdir and *buiddir computation, seems perfect now. 25 Jun 2003 coudercd * updated pmk man page. * added option to load a file that override pmk.conf (not tested yet). * updated man page. 24 Jun 2003 coudercd * added uabspath() in pathtools. * added -b option to set basedir. * moved pmkfile path in gdata. * related misc ... 22 Jun 2003 coudercd * added missing snapshots in Changelog. * fixed a bug in chkpath(). * finished (??) to implement srcdir and builddir stuff. * now templates are relative to the path of pmkfile. * files created from templates are now relative to basedir. * modified Makefile to respect basedir. # snapshot 0.4.5 21 Jun 2003 coudercd * added pathtools.c and pathtools.h files. * moved relpath() into pathtools. * added chkpath() into pathtools. * added path_test.c in test directory. * added abspath() into pathtools. * more support for srcdir and builddir stuff : * added ac_clean_dyn_var(). * rewritten ac_process_dyn_var(). * process_template() now process dynamic variables. * updated sample makefile to use srcdir and builddir stuff. * fixed remaining to "compat/string.h". * added BONUS file to talk about reusable components of this package. 18 Jun 2003 coudercd * added relpath() to common. 11 Jun 2003 coudercd * added srcdir in gdata structure. * modified hash_append() to avoid adding separator to an empty string. * added init of CFLAGS and LIBS. * empty binary path in pmk_check_binary() when not found this avoiding remaining tags after parsing. * added code to set srcdir and basedir. # snapshot 0.4.4 10 Jun 2003 coudercd * updated TODO * modified behavior of pmk_check_binary(). * added support for alternative CFLAGS and CLIBS in pmk_check_config() and pmk_check_pkg_config(). * updated pmkfile and makefile samples to use new features. * fixed pmk_check_config() and pmk_check_pkg_config() to avoid display of error messages. * updated TODO and STATUS 08 Jun 2003 coudercd * added support for pkg-config with CHECK_PKG_CONFIG. (added pmk_check_pkg_config() in func) * made version optional in CHECK_CONFIG. * updated pmkfile sample. * added version checking in pmk_check_pkg_config(). * added a check to ensure that the given package exists. * use PACKAGE instead of TARGET in CHECK_CONFIG. 07 Jun 2003 coudercd * cleaned-up and reorganized includes. * added autoconf.c and autoconf.h for autoconf compatibility stuff. # snapshot 0.4.3 05 Jun 2003 coudercd * massive changes in func.c to complete check functions. (added missing record_def, record_val and label_set and moved some portions of code) 04 Jun 2003 coudercd * makes pmkcfg.sh using the same tags as pmk (@DEF__*). * updates compat/compat.h.in to use DEF__* tags. 03 Jun 2003 coudercd * updated makefile sample to use LIBS and CFLAGS. * added CFLAGS and LIBS support in pmk_check_config(). * added LIBS support in pmk_check_lib(). * fixed initialisation of the buffer in hash_append(). 02 Jun 2003 coudercd * improved hash_append(). * updated hash_test.c to test appending function. 01 Jun 2003 coudercd * added hash_append(). # snapshot 0.4.2 31 May 2003 coudercd * added strlcat.c and strlcat.h in compat directory. * pmkcfg.sh now have a check for strlcat. * fully included strlcat in compat. * added da_pop() in dynarray and updated relative test. * use INC_PATH in pmk_check_include(). * use LIB_PATH in pmk_check_lib(). 28 May 2003 coudercd * misc changes in Makefile. * changed samples/ac_config.h into samples/ac_config.h.sample . * ac_config.h.sample is more complete. 27 May 2003 coudercd * record_val() is now functional. * use record_val() for almost all tests. * fixed/improved parse_ac_config(). * enabled parse_ac_config() in pmk. 25 May 2003 coudercd * few changes related to autoconf compatibility. 23 May 2003 coudercd * added AC_COMPAT in pmkfile.sample plus some comments. * added samples/ac_config.h for autoconf compatibility test. * AC_COMPAT now handle FILENAME to set the configuration file to process. * ac_file is now included in pmkdata structure. 22 May 2003 coudercd * improve a bit copy_text_file(). * add parse_ac_config(), not finished yet but it doesn't break the code. 21 May 2003 coudercd * added copy_text_file(). * misc on buffers. 15 May 2003 xsa * now using hash_add_array() for the predefined variables in pmksetup. 15 May 2003 coudercd * added AC_COMPAT for autoconf compatibility. * cleanup in various files (XXX comments). * added missing check (XXX comments). * misc. 14 May 2003 coudercd * moved functab and misc related. * use hash_add_array() in hash_test. 06 May 2003 coudercd * added hash_add_array(). 05 May 2003 xsa * added SYSCONFDIR to predef_vars(), so it's now in the pmk.conf as well. 04 May 2003 xsa * added verbosef(), now using it instead of debugf for the -V flag. * added predef_vars(), adding the static variables to the pmk.conf file. * error checking when hadh_add() 'ing values. 04 May 2003 coudercd * finished and tested hash_resize(). * added hash_set_grow() to set autogrow mode. * added autogrow in htable. * added hash_resize(), not tested yet. * added hash_add_cell() and make hash_add() and hash_resize() using it. * implemented depend_check(). * added checks in str_to_def(). * more checks in record_def(). * added checks in label_set() and label_check(). 03 May 2003 coudercd * rewritten record_def(). * added stuff to store label states (now need to handle dependencies). * added cleaning function to simplify pmk (need more work). 02 May 2003 coudercd * improved a bit find_file(). * rewritten dynarrays, mostly based on a patch from Ted Unangst. 30 Apr 2003 coudercd * added tagging stuff. 29 Apr 2003 coudercd * improved parse_cmd(). * some fixes from Ted Unangst. # PMK 0.4 release 28 Apr 2003 coudercd * many fixes for 0.4 release ... * fixed find_file() again should be the last time. 27 Apr 2003 coudercd * moved man pages in man directory. * added pmkfile(5). * fixed parse_conf_line(). * added BIN_CC in get_binaries and use it in pmk_check_include() an pmk_check_lib(). * more changes in process_template(). 26 Apr 2003 coudercd * implemented pmk_check_lib(). * added check_include_function in pmkcfg.sh . * improved str_to_dynary() and parse_conf_line(). * pmk_check_include() has been updated to check function again. 25 Apr 2003 coudercd * pmk_check_binary() has been completed. * pmk_check_include() has been rewritten to have a better test. * process_template() has been improved for speed. * pmk_check_version() has been rewritten as the previous code didn't work fine. * improved get_line(). 25 Apr 2003 xsa * moved BIN_PATH gathering in get_env_vars(). * change behavior of pmksetup when a binary is not found. 24 Apr 2003 coudercd * written check_version(). * improved version checking in pmk_check_config(). * fixed a vicious bug in find_file(). 24 Apr 2003 xsa * add INC_PATH and LIB_PATH. [... changes since PMK 0.3 ...] # PMK 0.3 release pmk-0.10.4/pmkpc.c010064400017500000000000000464311056512677500125510ustar00mipswheel/* $Id: pmkpc.c 1952 2007-02-15 19:01:17Z coudercd $ */ /* * Copyright (c) 2004-2005 Damien Couderc * Copyright (c) 2004 Xavier Santolaria * 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. * */ #include #include #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "cfgtool.h" #include "common.h" #include "dynarray.h" #include "hash_tools.h" #include "parse.h" #include "pkgconfig.h" #include "pmkpc.h" #include "premake.h" /*#define PMKPC_DEBUG 1*/ extern char *optarg; extern int optind; /********** variables ************************************************************************/ pcopt pcoptions[] = { {"version", false, PMKPC_OPT_VERSION, NULL}, {"atleast-pkgconfig-version", true, PMKPC_OPT_ATLPKGVERS, PC_USAGE_VERSION}, {"exists", false, PMKPC_OPT_EXISTS, NULL}, {"list-all", false, PMKPC_OPT_LISTALL, NULL}, {"uninstalled", false, PMKPC_OPT_UNINST, NULL}, {"debug", false, PMKPC_OPT_DEBUG, NULL}, {"help", false, PMKPC_OPT_HELP, NULL}, {"usage", false, PMKPC_OPT_USAGE, NULL}, {"modversion", false, PMKPC_OPT_MODVERS, NULL}, {"atleast-version", true, PMKPC_OPT_ATLVERS, PC_USAGE_VERSION}, {"exact-version", true, PMKPC_OPT_EXTVERS, PC_USAGE_VERSION}, {"max-version", true, PMKPC_OPT_MAXVERS, PC_USAGE_VERSION}, {"cflags", false, PMKPC_OPT_CFLAGS, NULL}, {"cflags-only-I", false, PMKPC_OPT_CFLAGS_ONLY_PATH, NULL}, {"cflags-only-other", false, PMKPC_OPT_CFLAGS_ONLY_OTHER, NULL}, {"libs", false, PMKPC_OPT_LIBS, NULL}, {"libs-only-l", false, PMKPC_OPT_LIBS_ONLY_LIB, NULL}, {"libs-only-L", false, PMKPC_OPT_LIBS_ONLY_PATH, NULL}, {"libs-only-other", false, PMKPC_OPT_LIBS_ONLY_OTHER, NULL}, {"variable", true, PMKPC_OPT_VAR, PC_USAGE_VARNAME}, {"define-variable", true, PMKPC_OPT_VAR_DEF, PC_USAGE_VARVAL}, {"print-errors", false, PMKPC_OPT_VAR_PRNT, NULL}, {"silence-errors", false, PMKPC_OPT_VAR_SILC, NULL}, {"errors-to-stdout", false, PMKPC_OPT_VAR_STDO, NULL}, }; size_t nbpcopt = sizeof(pcoptions) / sizeof(pcopt); /********** functions ************************************************************************/ /*************** optcell_init() DESCR init optcell structure IN - OUT optcell structure ************************************************************************/ optcell *optcell_init(void) { optcell *poc; poc = (optcell *) malloc(sizeof(optcell)); if (poc == NULL) { return(NULL); } poc->idx = 1; poc->id = PMKPC_OPT_UNKNOWN; poc->arg = NULL; return(poc); } /****************** optcell_destroy() DESCR destroy optcell structure IN poc : optcell structure OUT - ************************************************************************/ void optcell_destroy(optcell *poc) { free(poc); /* no more to free */ } /*********** pcgetopt() DESCR process command line options IN ac : argument number av : argument array poc : optcell structure OUT boolean ************************************************************************/ bool pcgetopt(unsigned int ac, char *av[], optcell *poc) { static char buf[PMKPC_MAX_OPT_SIZE]; char *opt, *pstr; size_t l; unsigned int i, idx; idx = poc->idx; if (idx >= ac) { #ifdef PMKPC_DEBUG debugf("{pcgetopt} ac = %d", ac); #endif /* no more args */ return(false); } opt = av[idx]; if ((opt[0] != '-') || (opt[1] != '-')) { #ifdef PMKPC_DEBUG debugf("{pcgetopt} full opt = '%s'", opt); #endif /* not an option */ poc->arg = opt; return(false); } else { /* skip leading "--" */ opt = opt + 2; #ifdef PMKPC_DEBUG debugf("{pcgetopt} opt = '%s'", opt); #endif /* option have argument ? */ pstr = strchr(opt, PMKPC_ARG_SEP); if (pstr != NULL) { /* argument found */ if (strlcpy_b(buf, opt, sizeof(buf)) == false) { #ifdef PMKPC_DEBUG debugf("{pcgetopt} strlcpy failed for '%s'", opt); #endif return(false); } /* delimit option name */ buf[pstr - opt] = CHAR_EOS; /* save argument position */ pstr++; poc->arg = pstr; #ifdef PMKPC_DEBUG debugf("{pcgetopt} opt arg = '%s'", poc->arg); #endif /* set opt back to the beginning of the option */ opt = buf; } l = strlen(opt); idx++; #ifdef PMKPC_DEBUG debugf("{pcgetopt} idx = %d", idx); #endif } for (i = 0 ; i < nbpcopt ; i++) { if (strncmp(pcoptions[i].name, opt, l) == 0) { /* known option */ poc->id = pcoptions[i].id; poc->err = pcoptions[i].name; poc->idx = idx; return(true); } } poc->id = PMKPC_OPT_UNKNOWN; poc->err = opt; return(true); } /*********** list_all() DESCR list all packages IN ppd : XXX OUT boolean ************************************************************************/ bool list_all(pkgdata *ppd) { bool rval = true; char *mod, *pcfile, **descr, fmt[32]; hkeys *phk; pkgcell *ppc; size_t len, maxs = 0; unsigned int i; phk = hash_keys(ppd->files); descr = (char **)malloc(sizeof(char *) * phk->nkey); if (descr == NULL) return(false); for(i = 0 ; (i < phk->nkey) && (rval == true) ; i++) { mod = phk->keys[i]; len = strlen(mod); if (len > maxs) maxs = len; pcfile = hash_get(ppd->files, mod); ppc = parse_pc_file(pcfile); if (ppc == NULL) { /* failed parsing */ rval = false; } else { descr[i] = strdup(ppc->descr); pkgcell_destroy(ppc); } } /* build format string to align descriptions */ if (snprintf_b(fmt, sizeof(fmt), "%%-%us %%s\n", (unsigned int)maxs) == false) { /* cleaning */ hash_free_hkeys(phk); free(descr); return(false); } for(i = 0 ; i < phk->nkey ; i++) { if (rval == true) { printf(fmt, phk->keys[i], descr[i]); } /* clean no longer used string */ free(descr[i]); } /* cleaning */ hash_free_hkeys(phk); free(descr); return(true); } /******** clean() DESCR clean XXX IN p_cd : XXX OUT - ************************************************************************/ void clean(pcdata *p_cd) { /* clean data */ if (p_cd->pda != NULL) { da_destroy(p_cd->pda); } if (p_cd->pht != NULL) { hash_destroy(p_cd->pht); } if (p_cd->ppd != NULL) { pkgdata_destroy(p_cd->ppd); } } /******** usage() DESCR pmkpc(1) usage IN - OUT - ************************************************************************/ void usage(void) { char option[MAXPATHLEN]; size_t alen, /* alignement length */ olen, /* option length */ cursor; unsigned int i; alen = strlen(PMKPC_USAGE_ALIGN); fprintf(stderr, "%s", PMKPC_USAGE_STR); cursor = strlen(PMKPC_USAGE_STR); for (i = 0; i < nbpcopt; i++) { strlcpy(option, PMKPC_USAGE_OPEN_OPT, sizeof(option)); /* no check needed */ strlcat(option, pcoptions[i].name, sizeof(option)); /* no check needed */ if (pcoptions[i].usagearg != NULL) { strlcat(option, "=", sizeof(option)); /* no check needed */ strlcat(option, pcoptions[i].usagearg, sizeof(option)); /* no check needed */ } strlcat(option, PMKPC_USAGE_CLOSE_OPT, sizeof(option)); /* no check needed */ olen = strlen(option); cursor += olen; if (cursor > 79) { fprintf(stderr, "\n%s", PMKPC_USAGE_ALIGN); cursor = olen + alen; } fprintf(stderr, "%s", option); } fprintf(stderr, "\n"); } /******* main() DESCR main loop ************************************************************************/ int main(int argc, char *argv[]) { FILE *fp; bool opt_version = false, opt_atl_vers = false, opt_modvers = false, opt_cmp_modvers = false, opt_exists = false, opt_listall = false, opt_cflags = false, opt_libs = false; cfgtcell *pcc = NULL; cfgtdata *pcd = NULL; char *mod, *bpath, *opt, *pc_path, *pstr, *mvers = NULL, *pvers = NULL, cmp_type = CHAR_EOS, pc_cmd[MAXPATHLEN], pc_buf[MAXPATHLEN], buf[TMP_BUF_LEN]; int r; optcell *poc; pcdata gdata; pkgcell *ppc; unsigned int i, cflags_opts = 0, libs_opts = 0; poc = optcell_init(); if (poc == NULL) { errorf("cannot init optcell."); exit(EXIT_FAILURE); } gdata.pda = da_init(); if (gdata.pda == NULL) { optcell_destroy(poc); errorf("cannot init dynary."); exit(EXIT_FAILURE); } gdata.ppd = pkgdata_init(); if (gdata.ppd == NULL) { optcell_destroy(poc); clean(&gdata); errorf("cannot init pkgdata."); exit(EXIT_FAILURE); } /* initialise global data hash table */ gdata.pht = hash_init(MAX_DATA_KEY); if (gdata.pht == NULL) { clean(&gdata); errorf("cannot initialize hash table for data."); exit(EXIT_FAILURE); } while (poc->idx != (unsigned int) argc) { if (pcgetopt(argc, argv, poc) == true) { #ifdef PMKPC_DEBUG debugf("{main} id = %d", poc->id); #endif /* found an option */ switch (poc->id) { case PMKPC_OPT_VERSION : opt_version = true; break; case PMKPC_OPT_ATLPKGVERS : opt_atl_vers = true; pvers = poc->arg; break; case PMKPC_OPT_MODVERS : opt_modvers = true; break; case PMKPC_OPT_ATLVERS : cmp_type = 'a'; opt_cmp_modvers = true; mvers = poc->arg; break; case PMKPC_OPT_EXTVERS : cmp_type = 'e'; opt_cmp_modvers = true; mvers = poc->arg; break; case PMKPC_OPT_MAXVERS : cmp_type = 'm'; opt_cmp_modvers = true; mvers = poc->arg; break; case PMKPC_OPT_CFLAGS : opt_cflags = true; break; case PMKPC_OPT_CFLAGS_ONLY_PATH : cflags_opts = cflags_opts | PKGCFG_CFLAGS_I; opt_cflags = true; break; case PMKPC_OPT_CFLAGS_ONLY_OTHER : cflags_opts = cflags_opts | PKGCFG_CFLAGS_o; opt_cflags = true; break; case PMKPC_OPT_LIBS : opt_libs = true; break; case PMKPC_OPT_LIBS_ONLY_PATH : libs_opts = libs_opts | PKGCFG_LIBS_L; opt_libs = true; break; case PMKPC_OPT_LIBS_ONLY_LIB : libs_opts = libs_opts | PKGCFG_LIBS_l; opt_libs = true; break; case PMKPC_OPT_LIBS_ONLY_OTHER : libs_opts = libs_opts | PKGCFG_LIBS_o; opt_libs = true; break; case PMKPC_OPT_EXISTS : opt_exists = true; break; case PMKPC_OPT_LISTALL : opt_listall = true; break; case PMKPC_OPT_HELP : fprintf(stderr, "For detailed help " "please see the pmkpc(1) " "man page.\n"); exit(EXIT_FAILURE); case PMKPC_OPT_USAGE : usage(); exit(EXIT_FAILURE); case PMKPC_OPT_UNINST : case PMKPC_OPT_DEBUG : case PMKPC_OPT_VAR : case PMKPC_OPT_VAR_DEF : case PMKPC_OPT_VAR_PRNT : case PMKPC_OPT_VAR_SILC : case PMKPC_OPT_VAR_STDO : errorf("option '--%s' is not yet " "implemented.", poc->err); optcell_destroy(poc); clean(&gdata); exit(EXIT_FAILURE); break; case PMKPC_OPT_UNKNOWN : default : errorf("unknown option '--%s'.", poc->err); optcell_destroy(poc); clean(&gdata); exit(EXIT_FAILURE); break; } } else { mod = argv[poc->idx]; if (mod[0] == '-') { switch (mod[1]) { case '?' : usage(); exit(EXIT_FAILURE); break; default : errorf("unknown option -%c", mod[1]); exit(EXIT_SUCCESS); break; } } else { /* add new module */ if (da_push(gdata.pda, strdup(mod)) == false) { errorf("unable to store module name in dynarray."); #ifdef PMKPC_DEBUG debugf("{main} mod = '%s'", mod); #endif exit(EXIT_FAILURE); } #ifdef PMKPC_DEBUG debugf("{main} new mod = '%s'", mod); #endif poc->idx++; } } } optcell_destroy(poc); if (opt_version == true) { printf("%s\n", PMKPC_COMPAT_VERSION); clean(&gdata); exit(EXIT_SUCCESS); } if (opt_atl_vers == true) { clean(&gdata); /* check if compat version is at least the specified one */ if (compare_version(pvers, PMKPC_COMPAT_VERSION) < 0) { exit(EXIT_FAILURE); } else { exit(EXIT_SUCCESS); } } fp = fopen(PREMAKE_CONFIG_PATH, "r"); if (fp != NULL) { if (parse_pmkconf(fp, gdata.pht, PRS_PMKCONF_SEP, process_opt) == false) { /* parsing failed */ clean(&gdata); fclose(fp); errorf("failed to parse '%s'.", PREMAKE_CONFIG_PATH); exit(EXIT_FAILURE); #ifdef PMKPC_DEBUG } else { debugf("{main} parsed '%s'", PREMAKE_CONFIG_PATH); #endif } fclose(fp); } else { clean(&gdata); errorf("cannot open '%s' : %s.", PREMAKE_CONFIG_PATH, strerror(errno)); exit(EXIT_FAILURE); } /* try to get pkg-config lib path from pmk.conf */ pstr = hash_get(gdata.pht, PMKCONF_PC_PATH_LIB); if (pstr == NULL) { clean(&gdata); errorf("unable to find pkg-config libdir."); exit(EXIT_FAILURE); } pc_path = process_string(pstr, gdata.pht); /* collect data */ pkg_collect(pc_path, gdata.ppd); if (opt_listall == true) { /* display all gathered modules */ if (list_all(gdata.ppd) == true) { exit(EXIT_SUCCESS); } else { exit(EXIT_FAILURE); } } #ifdef PMKPC_DEBUG debugf("{main} usize = '%d'", da_usize(gdata.pda)); #endif for (i = 0 ; i < da_usize(gdata.pda) ; i++) { mod = da_idx(gdata.pda, i); #ifdef PMKPC_DEBUG debugf("{main} mod = '%s' (i = %d)", mod, i); #endif if (pkg_mod_exists(gdata.ppd, mod) == true) { #ifdef PMKPC_DEBUG debugf("{main} module '%s' found", mod); #endif ppc = pkg_cell_add(gdata.ppd, mod); /* ppc is part of ppd, don't destroy */ /* display mod version */ if (opt_modvers == true) { /* print module version */ printf("%s\n", ppc->version); } /* check version */ if (opt_cmp_modvers == true) { /* compare module version */ r = compare_version(mvers, ppc->version); switch (cmp_type) { case 'a': if (r < 0) { clean(&gdata); /* XXX be more verbose ? */ /*errorf("module version (%s) is smaller than %s",*/ /* ppc->version, mvers); */ exit(EXIT_FAILURE); } break; /* not reached */ case 'e': if (r != 0) { clean(&gdata); /* XXX be more verbose ? */ /*errorf("module version (%s) is not equal to %s",*/ /* ppc->version, mvers); */ exit(EXIT_FAILURE); } break; /* not reached */ case 'm': if (r > 0) { clean(&gdata); /* XXX be more verbose ? */ /*errorf("module version (%s) is greater than %s",*/ /* ppc->version, mvers); */ exit(EXIT_FAILURE); } break; /* not reached */ default: clean(&gdata); errorf("unknown comparison type !"); exit(EXIT_FAILURE); break; /* not reached */ } } if ((opt_cflags == true) || (opt_libs == true)) { /* get cflags and/or libs */ if (pkg_recurse(gdata.ppd, mod) == false) { clean(&gdata); errorf("failed on recurse !"); exit(EXIT_FAILURE); } if (opt_cflags == true) { /* display cflags */ if (cflags_opts == 0) { cflags_opts = PKGCFG_CFLAGS_ALL; } printf("%s", pkg_get_cflags_adv(gdata.ppd, cflags_opts)); } if (opt_libs == true) { /* if cflags have been displayed, add a space */ if (opt_cflags == true) { printf(" "); } /* display libs */ if (libs_opts == 0) { libs_opts = PKGCFG_LIBS_ALL; } printf("%s", pkg_get_libs_adv(gdata.ppd, libs_opts)); } printf("\n"); } } else { #ifdef PMKPC_DEBUG debugf("module not found"); #endif /* init config tool data if needed */ if (pcd == NULL) { pcd = parse_cfgt_file(); if (pcd == NULL) { clean(&gdata); errorf("unable to load config tool data."); exit(EXIT_FAILURE); } } /* set config tool filename */ if (cfgtcell_get_binary(pcd, mod, pc_cmd, sizeof(pc_cmd)) == false) { if (snprintf_b(pc_cmd, sizeof(pc_cmd), "%s-config", mod) == false) { errorf("failed to build configure tool name."); exit(EXIT_FAILURE); } } bpath = hash_get(gdata.pht, PMKCONF_PATH_BIN); if (bpath == NULL) { errorf("unable to get binary path."); exit(EXIT_FAILURE); } pcc = cfgtcell_get_cell(pcd, pc_cmd); /* looking for it in the path */ if (get_file_path(pc_cmd, bpath, pc_buf, sizeof(pc_buf)) == true) { /* use CHECK_CONFIG */ #ifdef PMKPC_DEBUG debugf("Found alternative '%s' tool.", pc_cmd); #endif if (opt_modvers == true) { /* check if specific option exists */ if ((pcc != NULL) && (pcc->version != NULL)) { opt = pcc->version; } else { opt = CFGTOOL_OPT_VERSION; } if (ct_get_version(pc_buf, opt, buf, sizeof(buf)) == false) { clean(&gdata); errorf("cannot get version from '%s'.", pc_cmd); exit(EXIT_FAILURE); } else { printf("%s\n", buf); } } /* cflags and libs stuff */ if ((opt_cflags == true) || (opt_libs == true)) { if (opt_cflags == true) { /* check if there is a special option */ if ((pcc != NULL) && (pcc->cflags != NULL)) { opt = pcc->cflags; } else { opt = CFGTOOL_OPT_CFLAGS; } /* get cflags from config tool */ if (ct_get_data(pc_buf, opt, "", buf, sizeof(buf)) == false) { errorf("cannot get CFLAGS."); exit(EXIT_FAILURE); } else { printf("%s ", buf); } } if (opt_libs == true) { /* check if there is a special option */ if ((pcc != NULL) && (pcc->libs != NULL)) { opt = pcc->libs; } else { opt = CFGTOOL_OPT_LIBS; } /* get libs from config tool */ if (ct_get_data(pc_buf, opt, "", buf, sizeof(buf)) == false) { errorf("cannot get LIBS."); exit(EXIT_FAILURE); } else { printf("%s ", buf); } } printf("\n"); } } else { errorf("'%s' not found.", pc_cmd); exit(EXIT_FAILURE); } } } #ifdef PMKPC_DEBUG debugf("{main} destroy data"); #endif clean(&gdata); if (pcd != NULL) { cfgtdata_destroy(pcd); } #ifdef PMKPC_DEBUG debugf("End."); #endif return(0); } pmk-0.10.4/CREDITS010064400017500000000000000020241051323116400122570ustar00mipswheel----------------------------------------------------------------------- Pre Make Kit CREDITS file Document revision: $Id: CREDITS 1909 2006-10-11 18:05:40Z coudercd $ ----------------------------------------------------------------------- Additional credits: Patches: - Ted Unangst * dynarray rewrite * many fixes - Pedro Martelletto * check_mode() improvement - Marek Habersack * many segfault fixes - Leslie Polzer * CPUID checking for 32bits x86 CPU Bug report: - Marek Habersack * dirname failure with glibc implementation - Jean-Pierre Ritschard * memory fault in pmk - Han Boetes * memory fault in pmk_set_variable() due to a missing check * redundancy in pmkfile.sample - "veins" * problem of empty pmkfile when no check exists - "wintellect" * coredumps in pmk_check_config() and pmk_check_pkg_config() * library path detection failure in pmk_check_lib() Notices: - Pedro Martelletto - Kurt V. Hindenburg Typos: - Pedro Martelletto Testers: - Fiesh - Saad Khadi - Francois Petitjean - Sascha Welter pmk-0.10.4/pmkpc.h010064400017500000000000000074661023325765700125570ustar00mipswheel/* $Id: pmkpc.h 1405 2005-04-25 21:22:55Z mipsator $ */ /* * Copyright (c) 2004 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. * */ #ifndef _PMKPC_H_ #define _PMKPC_H_ /********** constants ************************************************************************/ /* options id */ #define PMKPC_OPT_UNKNOWN 0 #define PMKPC_OPT_VERSION 1 #define PMKPC_OPT_ATLPKGVERS 2 #define PMKPC_OPT_EXISTS 3 #define PMKPC_OPT_LISTALL 4 #define PMKPC_OPT_UNINST 5 #define PMKPC_OPT_DEBUG 6 #define PMKPC_OPT_HELP 7 #define PMKPC_OPT_USAGE 8 #define PMKPC_OPT_MODVERS 10 #define PMKPC_OPT_ATLVERS 11 #define PMKPC_OPT_EXTVERS 12 #define PMKPC_OPT_MAXVERS 13 #define PMKPC_OPT_CFLAGS 20 #define PMKPC_OPT_CFLAGS_ONLY_PATH 21 #define PMKPC_OPT_CFLAGS_ONLY_OTHER 22 #define PMKPC_OPT_LIBS 30 #define PMKPC_OPT_LIBS_ONLY_LIB 31 #define PMKPC_OPT_LIBS_ONLY_PATH 32 #define PMKPC_OPT_LIBS_ONLY_OTHER 33 #define PMKPC_OPT_VAR 40 #define PMKPC_OPT_VAR_DEF 41 #define PMKPC_OPT_VAR_PRNT 42 #define PMKPC_OPT_VAR_SILC 43 #define PMKPC_OPT_VAR_STDO 44 /* compatibility version with pkg-config */ #define PMKPC_COMPAT_VERSION "0.15.0" /* separator for option's argument */ #define PMKPC_ARG_SEP '=' /* maximum option size */ #define PMKPC_MAX_OPT_SIZE 64 /* usage related defines */ #define PMKPC_USAGE_STR "Usage: pmkpc" #define PMKPC_USAGE_OPEN_OPT " [--" #define PMKPC_USAGE_CLOSE_OPT "]" #define PMKPC_USAGE_ALIGN " " /* string to append to options in the usage() that need it */ #define PC_USAGE_VERSION "VERSION" #define PC_USAGE_VARNAME "VARIABLENAME" #define PC_USAGE_VARVAL "VARIABLENAME=VARIABLEVALUE" /********************************* types and structures definitions ************************************************************************/ typedef struct { char *name; bool arg; unsigned int id; char *usagearg; } pcopt; typedef struct { unsigned int idx, id; char *arg, *err; } optcell; typedef struct { dynary *pda; htable *pht; pkgdata *ppd; } pcdata; /******************** function prototypes ************************************************************************/ bool list_all(pkgdata *); bool pcgetopt(unsigned int, char **, optcell *); optcell *optcell_init(void); void clean(pcdata *); void optcell_destroy(optcell *); void usage(void); #endif /* _PMKPKGCFG_H_ */ pmk-0.10.4/data004075500017500000000000000000001077177766200121265ustar00mipswheelpmk-0.10.4/data/pmkcfgtool.dat010064400017500000000000000017271061043137600150250ustar00mipswheel# $Id: pmkcfgtool.dat 1971 2007-04-15 14:13:18Z coudercd $ # pmk configuration tools data # config tools with non standard options or specific name # means different than --version, --cflags and --libs # known compliant tools : glib-config # example #ADD_CFGTOOL { # NAME = "module name" # BINARY = "tool filename" # VERSION = "version option" # CFLAGS = "cflags option" # LIBS = "libs option" #} # gtk+ is named gtk-config in place or gtk+-config ADD_CFGTOOL { NAME = "gtk+" BINARY = "gtk-config" } ADD_CFGTOOL { NAME = "gtkmm" BINARY = "gtkmm-config" } ADD_CFGTOOL { NAME = "libgnomevfs" BINARY = "gnome-vfs-config" } ADD_CFGTOOL { NAME = "imlib" BINARY = "imlib-config" CFLAGS = "--cflags-gdk" LIBS = "--libs-gdk" } ADD_CFGTOOL { NAME = "orbit-client" BINARY = "orbit-config" MODULE = "client" } ADD_CFGTOOL { NAME = "orbit-server" BINARY = "orbit-config" MODULE = "server" } ADD_CFGTOOL { NAME = "php" BINARY = "php-config" CFLAGS = "--includes" } pmk-0.10.4/data/pmkscan.dat010064400017500000000000000045371034537321500143200ustar00mipswheel# $Id: pmkscan.dat 1516 2005-12-06 20:37:33Z mipsator $ ##################### # pmkscan data file # ######################################################################## # header data ########################## ADD_HEADER { NAME = "ctype.h" PROCEDURE = ("isblank") } ADD_HEADER { NAME = "dirent.h" } ADD_HEADER { NAME = "dlfcn.h" PROCEDURE = ("dlclose", "dlerror", "dlopen", "dlsym") } ADD_HEADER { NAME = "libgen.h" PROCEDURE = ("basename", "dirname") LIBRARY = "gen" } ADD_HEADER { NAME = "libintl.h" PROCEDURE = ("gettext") LIBRARY = "intl" } ADD_HEADER { NAME = "stdarg.h" } ADD_HEADER { NAME = "stdio.h" PROCEDURE = ("snprintf", "vsnprintf") } ADD_HEADER { NAME = "stdlib.h" PROCEDURE = ("free", "malloc") } ADD_HEADER { NAME = "string.h" PROCEDURE = ("strdup", "strlcat", "strlcpy", "strndup", "strndupa", "memcpy", "memcmp", "memset") } ADD_HEADER { NAME = "strings.h" PROCEDURE = ("bzero") } ADD_HEADER { NAME = "sys/socket.h" SUBHDR = ("sys/type.h") PROCEDURE = ("socket") LIBRARY = "net" } ADD_HEADER { NAME = "sys/param.h" } ADD_HEADER { NAME = "syslog.h" PROCEDURE = ("vsyslog") } ADD_HEADER { NAME = "sys/wait.h" SUBHDR = ("sys/type.h") PROCEDURE = ("wait") } ADD_HEADER { NAME = "unistd.h" PROCEDURE = ("mkstemps") } # library data ######################### ADD_LIBRARY { NAME = "gen" PROCEDURE = ("basename", "dirname") } ADD_LIBRARY { NAME = "intl" PROCEDURE = ("gettext") } ADD_LIBRARY { NAME = "net" PROCEDURE = ("socket") } # type data ############################ ADD_TYPE { NAME = "_Bool" } ADD_TYPE { NAME = "blkcnt_t" HEADER = "sys/types" } ADD_TYPE { NAME = "bool" HEADER = "stdbool.h" } ADD_TYPE { NAME = "gid_t" HEADER = "sys/types.h" } ADD_TYPE { NAME = "intmax_t" HEADER = "stdint.h" } ADD_TYPE { NAME = "long double" } ADD_TYPE { NAME = "long long" } ADD_TYPE { NAME = "mode_t" HEADER = "sys/types.h" } ADD_TYPE { NAME = "off_t" HEADER = "sys/types.h" } ADD_TYPE { NAME = "pid_t" HEADER = "sys/types.h" } ADD_TYPE { NAME = "ptrdiff_t" HEADER = "stddef.h" } ADD_TYPE { NAME = "size_t" HEADER = "sys/types.h" } ADD_TYPE { NAME = "time_t" HEADER = "sys/types.h" } ADD_TYPE { NAME = "uid_t" HEADER = "sys/types.h" } ADD_TYPE { NAME = "unsigned long long" } ADD_TYPE { NAME = "wchar_t" HEADER = "wchar.h" } ADD_TYPE { NAME = "wint_t" HEADER = "wchar.h" } pmk-0.10.4/data/pmkcpu.dat010064400017500000000000000025341040066775500141650ustar00mipswheel# $Id: pmkcpu.dat 1542 2006-02-27 21:32:29Z mreindl $ # pmk cpu identification data LIST_ARCH_EQUIV { # x86_32 "i386" = "x86_32" "i486" = "x86_32" "i586" = "x86_32" "i686" = "x86_32" # x86_64 "amd64" = "x86_64" "x86_64" = "x86_64" # sparc_32 "sparc" = "sparc_32" "sun4c" = "sparc_32" "sun4d" = "sparc_32" "sun4m" = "sparc_32" # sparc_64 "sparc64" = "sparc_64" "sun4u" = "sparc_64" #ia_64 "ia_64" = "ia_64" "ia64" = "ia_64" # ppc "ppc" = "ppc" "powerpc" = "ppc" "Power Macintosh" = "ppc" "macppc" = "ppc" # alpha "alpha" = "alpha" # m68k "hp300" = "m68k" "mac68k" = "m68k" "mvme68k" = "m68k" # mips "sgimips" = "mips" # parisc "9000/800" = "parisc_64" "parisc64" = "parisc_64" # vax "vax" = "vax" } # # X86 arch specific # LIST_X86_CPU_VENDOR { "GenuineIntel" = "INTEL" "AuthenticAMD" = "AMD" "AMD ISBETTER" = "AMD" } LIST_X86_CPU_MODEL { VENDOR = "INTEL" "EF15" = "PENTIUM4" } LIST_X86_CPU_CLASS { DEFAULT = "i386" "INTEL_FAM4" = "i486" "INTEL_FAM5" = "i586" "INTEL_FAM6" = "i686" "INTEL_EFAM0" = "i686" # pentium4 "AMD_FAM4" = "i486" "AMD_FAM5" = "i586" "AMD_FAM6" = "i686" "UNKNOWN_FAM4" = "i486" "UNKNOWN_FAM5" = "i586" } LIST_ALPHA_CPU_CLASS { "IMPLVER_0" = "EV4" "IMPLVER_1" = "EV5" "IMPLVER_2" = "EV6" } LIST_IA64_CPU_CLASS { DEFAULT = "Itanium" "FAM7" = "Itanium" "FAM31" = "Itanium2" } pmk-0.10.4/data/pmkcomp.dat010064400017500000000000000114301052021275100143100ustar00mipswheel# $Id: pmkcomp.dat 1921 2006-10-26 20:09:13Z coudercd $ # pmk compilers data # SLCFLAGS = shared libs compiler flags # SLLDFLAGS = shared libs linking flags # SLSUFFIX = shared lib suffix (needed?) ADD_COMPILER { ID = "tendra" DESCR = "TenDRA" MACRO = "__TenDRA__" SLCFLAGS = "-Wt,-D1" } ADD_COMPILER { ID = "gcc" DESCR = "GNU gcc" MACRO = "__GNUC__" VERSION = "(__GNUC__ * 100 + __GNUC_MINOR__)" SLCFLAGS = "-fPIC" SLLDFLAGS = "-fPIC -shared" } ADD_COMPILER { ID = "sunpro_cc" DESCR = "Sun Workshop C" MACRO = "__SUNPRO_C" VERSION = "__SUNPRO_C" SLCFLAGS = "-KPIC" SLLDFLAGS = "-G" } ADD_COMPILER { ID = "sunpro_cxx" DESCR = "Sun Workshop C++" MACRO = "__SUNPRO_CC" VERSION = "__SUNPRO_CC" SLCFLAGS = "-KPIC" SLLDFLAGS = "-G" } ADD_COMPILER { ID = "decc" DESCR = "Compaq C" MACRO = "__DECC" VERSION = "__DECC_VER" # no flags needed for PIC SLCFLAGS = "" } ADD_COMPILER { ID = "decxx" DESCR = "Compaq C++" MACRO = "__DECCXX" VERSION = "__DECCXX_VER" # no flags needed for PIC SLCFLAGS = "" } ADD_COMPILER { ID = "hp_cc" DESCR = "HP Ansi C" MACRO = "__HP_cc" SLCFLAGS = "+Z" SLLDFLAGS = "-b" } ADD_COMPILER { ID = "hp_cxx" DESCR = "HP Ansi C++" MACRO = "__HP_aCC" VERSION = "__HP_aCC" SLCFLAGS = "+Z" SLLDFLAGS = "-b" } ADD_COMPILER { ID = "xlc_cc" DESCR = "IBM C" MACRO = "__IBMC__" VERSION = "__IBMC__" # no flags needed for PIC SLCFLAGS = "" SLLDFLAGS = "-G" } ADD_COMPILER { ID = "xlc_cxx" DESCR = "IBM C++" MACRO = "__IBMCPP__" VERSION = "__IBMCPP__" # no flags needed for PIC SLCFLAGS = "" SLLDFLAGS = "-G" } ADD_COMPILER { ID = "icc" DESCR = "Intel" MACRO = "__INTEL_COMPILER" VERSION = "__INTEL_COMPILER" SLCFLAGS = "XXX flags not set in pmkcomp.dat XXX" SLLDFLAGS = "-shared" } ADD_COMPILER { ID = "mpro" DESCR = "SGI MIPSpro" MACRO = "__sgi" VERSION = "_COMPILER_VERSION" SLCFLAGS = "-KPIC" SLLDFLAGS = "-shared" } # # system specific data # ADD_SYSTEM { NAME = "Darwin" LIB_VERSION = "$LIB_MAJOR.$LIB_MINOR" ST_EXT = ".a" ST_LIBNAME_NONE = "lib$LIB_NAME$ST_EXT" ST_LIBNAME_VERS = "lib$LIB_NAME-$LIB_VERSION$ST_EXT" SH_EXT = ".dylib" SH_LIBNAME_NONE = "lib$LIB_NAME$SH_EXT" SH_LIBNAME_VERS = "lib$LIB_NAME.$LIB_VERSION$SH_EXT" SLLDFLAGS_gcc = "-dynamiclib" } ADD_SYSTEM { NAME = "FreeBSD" LIB_VERSION = "$LIB_MAJOR" ST_EXT = ".a" ST_LIBNAME_NONE = "lib$LIB_NAME$ST_EXT" ST_LIBNAME_VERS = "lib$LIB_NAME-$LIB_VERSION$ST_EXT" SH_EXT = ".so" SH_LIBNAME_NONE = "lib$LIB_NAME$SH_EXT" SH_LIBNAME_VERS = "lib$LIB_NAME$SH_EXT.$LIB_VERSION" } ADD_SYSTEM { NAME = "DragonFly" LIB_VERSION = "$LIB_MAJOR.$LIB_MINOR" ST_EXT = ".a" ST_LIBNAME_NONE = "lib$LIB_NAME$ST_EXT" ST_LIBNAME_VERS = "lib$LIB_NAME-$LIB_VERSION$ST_EXT" SH_EXT = ".so" SH_LIBNAME_NONE = "lib$LIB_NAME$SH_EXT" SH_LIBNAME_VERS = "lib$LIB_NAME$SH_EXT.$LIB_VERSION" } ADD_SYSTEM { NAME = "HP-UX" LIB_VERSION = "$LIB_MAJOR.$LIB_MINOR" ST_EXT = ".a" ST_LIBNAME_NONE = "lib$LIB_NAME$ST_EXT" ST_LIBNAME_VERS = "lib$LIB_NAME-$LIB_VERSION$ST_EXT" SH_EXT = ".sl" SH_LIBNAME_NONE = "lib$LIB_NAME$SH_EXT" SH_LIBNAME_VERS = "lib$LIB_NAME$SH_EXT.$LIB_VERSION" } ADD_SYSTEM { NAME = "IRIX" LIB_VERSION = "$LIB_MAJOR.$LIB_MINOR" ST_EXT = ".a" ST_LIBNAME_NONE = "lib$LIB_NAME$ST_EXT" ST_LIBNAME_VERS = "lib$LIB_NAME-$LIB_VERSION$ST_EXT" SH_EXT = ".so" SH_LIBNAME_NONE = "lib$LIB_NAME$SH_EXT" SH_LIBNAME_VERS = "lib$LIB_NAME$SH_EXT.$LIB_VERSION" } ADD_SYSTEM { NAME = "Linux" LIB_VERSION = "$LIB_MAJOR.$LIB_MINOR" ST_EXT = ".a" ST_LIBNAME_NONE = "lib$LIB_NAME$ST_EXT" ST_LIBNAME_VERS = "lib$LIB_NAME-$LIB_VERSION$ST_EXT" SH_EXT = ".so" SH_LIBNAME_NONE = "lib$LIB_NAME$SH_EXT" SH_LIBNAME_VERS = "lib$LIB_NAME$SH_EXT.$LIB_VERSION" } ADD_SYSTEM { NAME = "NetBSD" LIB_VERSION = "$LIB_MAJOR.$LIB_MINOR" ST_EXT = ".a" ST_LIBNAME_NONE = "lib$LIB_NAME$ST_EXT" ST_LIBNAME_VERS = "lib$LIB_NAME-$LIB_VERSION$ST_EXT" SH_EXT = ".so" SH_LIBNAME_NONE = "lib$LIB_NAME$SH_EXT" SH_LIBNAME_VERS = "lib$LIB_NAME$SH_EXT.$LIB_VERSION" } ADD_SYSTEM { NAME = "OpenBSD" LIB_VERSION = "$LIB_MAJOR.$LIB_MINOR" ST_EXT = ".a" ST_LIBNAME_NONE = "lib$LIB_NAME$ST_EXT" ST_LIBNAME_VERS = "lib$LIB_NAME-$LIB_VERSION$ST_EXT" SH_EXT = ".so" SH_LIBNAME_NONE = "lib$LIB_NAME$SH_EXT" SH_LIBNAME_VERS = "lib$LIB_NAME$SH_EXT.$LIB_VERSION" } ADD_SYSTEM { NAME = "OSF1" LIB_VERSION = "$LIB_MAJOR.$LIB_MINOR" ST_EXT = ".a" ST_LIBNAME_NONE = "lib$LIB_NAME$ST_EXT" ST_LIBNAME_VERS = "lib$LIB_NAME-$LIB_VERSION$ST_EXT" SH_EXT = ".so" SH_LIBNAME_NONE = "lib$LIB_NAME$SH_EXT" SH_LIBNAME_VERS = "lib$LIB_NAME$SH_EXT.$LIB_VERSION" } ADD_SYSTEM { NAME = "SunOS" LIB_VERSION = "$LIB_MAJOR.$LIB_MINOR" ST_EXT = ".a" ST_LIBNAME_NONE = "lib$LIB_NAME$ST_EXT" ST_LIBNAME_VERS = "lib$LIB_NAME-$LIB_VERSION$ST_EXT" SH_EXT = ".so" SH_LIBNAME_NONE = "lib$LIB_NAME$SH_EXT" SH_LIBNAME_VERS = "lib$LIB_NAME$SH_EXT.$LIB_VERSION" } pmk-0.10.4/detect_cpu_asm.s010064400017500000000000000133201050207653000144050ustar00mipswheel/* $Id: detect_cpu_asm.s 1559 2006-09-13 21:51:20Z mipsator $ */ /* * Copyright (c) 2004-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. * */ #include "cpu_arch_def.h" #ifdef ARCH_X86_32 .text /* * X86 32 bits code */ .align 16,0x90 /* check if cpuid is available */ .globl x86_check_cpuid_flag x86_check_cpuid_flag: /* save ecx register in the stack */ pushl %ecx /* push flags into stack */ pushfl /* pop EFLAGS register from stack into eax */ popl %eax /* save original EFLAGS into ecx */ movl %eax,%ecx /* flip CPUID flag (bit 21 of EFLAGS) for testing purpose */ xorl $0x200000,%eax /* put back modified EFLAGS into stack */ pushl %eax /* reload flags from stack */ popfl /* put flags again into stack to check it */ pushfl /* pop EFLAGS register from stack into eax */ popl %eax /* push the original EFLAGS value stored in ecx into stack */ pushl %ecx /* put original state back from the stack */ popfl /* xor between original EFLAGS saved in ecx and current in eax */ xorl %ecx,%eax /* keep only CPUID flag */ andl $0x200000,%eax /* and shift it to bit 0 */ rorl $21,%eax /* restore ecx register that was previously stored in stack */ popl %ecx /* return value of CPUID in bit 0 of eax */ ret /* exec cpuid function returns: pointer to static buffer */ .globl x86_exec_cpuid x86_exec_cpuid: /* get function number */ movl 4(%esp),%eax pushl %ebx pushl %ecx pushl %edx cpuid /* copy register values */ movl %eax,x86_cpu_reg_eax movl %ebx,x86_cpu_reg_ebx movl %ecx,x86_cpu_reg_ecx movl %edx,x86_cpu_reg_edx popl %edx popl %ecx popl %ebx ret #endif /* ARCH_X86_32 */ #ifdef ARCH_X86_64 .text /* * X86 64 bits code */ .align 16,0x90 /* check if cpuid is available */ .globl x86_check_cpuid_flag x86_check_cpuid_flag: pushq %rcx /* save rcx register */ pushfq popq %rax /* get eflags */ movq %rax,%rcx /* save flags */ xorq $0x200000,%rax /* clear CPU ID flag */ pushq %rax popfq /* load eflags */ pushfq popq %rax /* get current eflags state */ pushq %rcx popfq /* put original state back */ popq %rcx /* restore ebx register */ andq $0x200000,%rax /* keep CPU ID flag only */ rorq $21,%rax /* and shift it to bit 0 */ ret /* exec cpuid function returns: pointer to static buffer */ .globl x86_exec_cpuid x86_exec_cpuid: /* get function number (arg0 in rdi register) */ movq %rdi,%rax pushq %rbx pushq %rcx pushq %rdx cpuid /* copy register values */ movl %eax,x86_cpu_reg_eax movl %ebx,x86_cpu_reg_ebx movl %ecx,x86_cpu_reg_ecx movl %edx,x86_cpu_reg_edx popq %rdx popq %rcx popq %rbx ret #endif /* ARCH_X86_64 */ #if defined(ARCH_X86_32) || defined(ARCH_X86_64) .data .globl x86_cpu_reg_eax x86_cpu_reg_eax: .long 0 .globl x86_cpu_reg_ebx x86_cpu_reg_ebx: .long 0 .globl x86_cpu_reg_ecx x86_cpu_reg_ecx: .long 0 .globl x86_cpu_reg_edx x86_cpu_reg_edx: .long 0 #endif /* ARCH_X86_32 || ARCH_X86_64 */ /* * ALPHA code */ #if defined(ARCH_ALPHA) .text .globl alpha_exec_implver .ent alpha_exec_implver alpha_exec_implver: .frame $30,0,$26,0 $alpha_exec_implver..ng: .prologue 0 implver $0 /* get implver value */ ret $31,($26),1 .end alpha_exec_implver .globl alpha_exec_amask .ent alpha_exec_amask alpha_exec_amask: .frame $30,0,$26,0 $alpha_exec_amask..ng: .prologue 0 lda $0,-1 /* set all bits to 1 */ amask $0,$0 /* get amask */ ret $31,($26),1 .end alpha_exec_amask #endif /* ARCH_ALPHA */ /* * IA64 code */ #if defined(ARCH_IA64) .text .globl ia64_get_cpuid_register .proc ia64_get_cpuid_register ia64_get_cpuid_register: .prologue .body mov r8 = cpuid[r32] /* return cpuid register value in r8 */ br.ret.sptk.many b0 .endp ia64_get_cpuid_register #endif /* ARCH_IA64 */ /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/INSTALL010064400017500000000000000040041032174522300122730ustar00mipswheel----------------------------------------------------------------------- Pre Make Kit INSTALL file Document revision: $Id: INSTALL 1487 2005-10-08 13:33:07Z mipsator $ ----------------------------------------------------------------------- Quick install ------------- There are two basic ways of using pmk. The first one is the common installation that needs root privileges and that allows all users to access pmk. The second one is the "user mode" that installs binaries in $HOME/bin/ and data in $HOME/.pmk/ of the user doing the installation. There are two targets to configure pmk before building it: Configuring with root mode: sh pmkcfg.sh Else in user mode: sh pmkcfg.sh -u After configuring you can build the package with: make And finish by installing it with: make install For each new release of pmk we _highly_ recommend you to run pmksetup before any use of the new pmk binary. Installing PMK using previously installed binaries -------------------------------------------------- The package also contains a pmkfile that can be used as an alternative to the bootstrap script. For a standard install, see the following steps: pmk make make install As stated above don't forget to run pmksetup after install. More about pmkcfg.sh -------------------- The script has the following options: -p permits to override the default prefix used for BASE -u sets user mode as on -U provide an alternative user for privilege separation (default is nobody) The default prefixes are: - global mode : /usr/local or $PREFIX if it is set in env - user mode : $HOME Example: If you want a global use with /opt as prefix you will use the following: sh pmkcfg.sh -p /opt More about the pmkfile ---------------------- The sw_usermode switch is available to set user mode as on. To use it do the following: pmk -e sw_usermode To specify an alternate privsep user you need to set PRIVSEP_USER to the desired user. See the following example that sets the user to '_pmk': pmk PRIVSEP_USER="_pmk" pmk-0.10.4/cfgtool.h010064400017500000000000000063311027375204200130600ustar00mipswheel/* $Id: cfgtool.h 1433 2005-08-02 20:14:26Z mipsator $ */ /* * Copyright (c) 2004 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. * */ #ifndef _PMK_CFGTOOL_H_ #define _PMK_CFGTOOL_H_ #include "hash.h" /************* * constants * ***********************************************************************/ #define CFGT_TOK_ADDCT 1 #ifndef DATADIR /* for lint */ #define DATADIR "/DATADIR_not_defined" #endif #define PMKCFG_DATA DATADIR "/pmkcfgtool.dat" /* version format line: tool_path version_option */ #define CT_FORMAT_VERSION "%s %s 2>/dev/null" /* data gathering format line: tool_path data_option */ #define CT_FORMAT_DATA "%s %s 2>/dev/null" /* module gathering format line: tool_path data_option module */ #define CT_FORMAT_DATA_MOD "%s %s %s 2>/dev/null" #define CFGTOOL_HT_SIZE 32 #define CFGTOOL_OPT_VERSION "--version" #define CFGTOOL_OPT_CFLAGS "--cflags" #define CFGTOOL_OPT_LIBS "--libs" /******************** * type definitions * ***********************************************************************/ typedef struct { char *name, *binary, *version, *module, *cflags, *libs; } cfgtcell; typedef struct { htable *by_mod, *by_bin; } cfgtdata; /************** * prototypes * ***********************************************************************/ void cfgtcell_destroy(cfgtcell *); cfgtdata *cfgtdata_init(void); void cfgtdata_destroy(cfgtdata *); bool add_cfgtool(cfgtdata *, htable *); cfgtdata *parse_cfgt_file(void); bool cfgtcell_get_binary(cfgtdata *, char *, char *, size_t); cfgtcell *cfgtcell_get_cell(cfgtdata *, char *); bool ct_get_version(char *, char *, char *, size_t); bool ct_get_data(char *, char *, char *, char *, size_t); #endif /* _PMK_CFGTOOL_H_ */ pmk-0.10.4/LICENSE010064400017500000000000000030011020764330100122400ustar00mipswheelCopyright (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. pmk-0.10.4/cfgtool.c010064400017500000000000000266601036713320700130620ustar00mipswheel/* $Id: cfgtool.c 1535 2006-01-29 12:35:19Z mipsator $ */ /* * Copyright (c) 2004-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. * */ #include #include #include "compat/pmk_stdbool.h" #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "cfgtool.h" #include "common.h" #include "parse.h" #include "premake.h" /*#define CFGT_DEBUG 1*/ /* config tools data file keyword */ prskw kw_pmkcfgtool[] = { {"ADD_CFGTOOL", CFGT_TOK_ADDCT, PRS_KW_CELL, PRS_TOK_NULL, NULL} }; int nbkwct = sizeof(kw_pmkcfgtool) / sizeof(prskw); /********************** * cfgtcell_destroy() * *********************************************************************** DESCR free cfgtcell structure IN pcc : configtool cell OUT NONE ***********************************************************************/ void cfgtcell_destroy(cfgtcell *pcc) { #ifdef CFGT_DEBUG debugf("free cfgtcell '%s'", pcc->name); #endif free(pcc->name); free(pcc->binary); if (pcc->version != NULL) free(pcc->version); if (pcc->module != NULL) free(pcc->module); if (pcc->cflags != NULL) free(pcc->cflags); if (pcc->libs != NULL) free(pcc->libs); free(pcc); } /******************* * cfgtdata_init() * *********************************************************************** DESCR initialize cfgtdata structure IN NONE OUT config data structure ***********************************************************************/ cfgtdata *cfgtdata_init(void) { cfgtdata *pcd; /* initialise configt tool data structure */ pcd = (cfgtdata *) malloc(sizeof(cfgtdata)); if (pcd == NULL) { #ifdef CFGT_DEBUG debugf("cannot initialize config tool data"); #endif return(NULL); } /* initialize config tool hash table */ pcd->by_mod = hash_init_adv(CFGTOOL_HT_SIZE, NULL, (void (*)(void *)) cfgtcell_destroy, NULL); if (pcd->by_mod == NULL) { free(pcd); #ifdef CFGT_DEBUG debugf("cannot initialize config tool hash table"); #endif return(NULL); } /* initialize config tool hash table */ pcd->by_bin = hash_init(CFGTOOL_HT_SIZE); if (pcd->by_bin == NULL) { hash_destroy(pcd->by_mod); free(pcd); #ifdef CFGT_DEBUG debugf("cannot initialize config tool hash table"); #endif return(NULL); } return(pcd); } /********************** * cfgtdata_destroy() * *********************************************************************** DESCR free cfgtdata structure IN pcd : config data structure OUT ***********************************************************************/ void cfgtdata_destroy(cfgtdata *pcd) { #ifdef CFGT_DEBUG debugf("destroying module hash table."); #endif if (pcd->by_mod != NULL) { hash_destroy(pcd->by_mod); #ifdef CFGT_DEBUG debugf("destroyed module hash table."); } else { debugf("WARNING : by_mod doesn't exists !!!"); #endif } #ifdef CFGT_DEBUG debugf("destroying binary links hash table."); #endif if (pcd->by_mod != NULL) { hash_destroy(pcd->by_bin); #ifdef CFGT_DEBUG debugf("destroyed binary links hash table."); } else { debugf("WARNING : by_bin doesn't exists !!!"); #endif } } /***************** * add_cfgtool() * *********************************************************************** DESCR add a new config tool cell IN pcd : config tool data structure pht : parsed data OUT boolean ***********************************************************************/ bool add_cfgtool(cfgtdata *pcd, htable *pht) { cfgtcell *pcell; char *pstr; pcell = (cfgtcell *) malloc(sizeof(cfgtcell)); if (pcell == NULL) return(false); pstr = po_get_str(hash_get(pht, "NAME")); if (pstr == NULL) { free(pcell); return(false); } else { pcell->name = strdup(pstr); if (pcell->name == NULL) { free(pcell); errorf(ERRMSG_MEM); return(false); } } pstr = po_get_str(hash_get(pht, "BINARY")); if (pstr == NULL) { free(pcell->name); free(pcell); return(false); } else { pcell->binary = strdup(pstr); if (pcell->binary == NULL) { free(pcell); errorf(ERRMSG_MEM); return(false); } } pstr = po_get_str(hash_get(pht, "VERSION")); if (pstr != NULL) { pcell->version = strdup(pstr); if (pcell->version == NULL) { free(pcell); errorf(ERRMSG_MEM); return(false); } } else { pcell->version = NULL; } pstr = po_get_str(hash_get(pht, "MODULE")); if (pstr != NULL) { pcell->module = strdup(pstr); if (pcell->module == NULL) { free(pcell); errorf(ERRMSG_MEM); return(false); } } else { pcell->module = NULL; } pstr = po_get_str(hash_get(pht, "CFLAGS")); if (pstr != NULL) { pcell->cflags = strdup(pstr); if (pcell->cflags == NULL) { free(pcell); errorf(ERRMSG_MEM); return(false); } } else { pcell->cflags = NULL; } pstr = po_get_str(hash_get(pht, "LIBS")); if (pstr != NULL) { pcell->libs = strdup(pstr); if (pcell->libs == NULL) { free(pcell); errorf(ERRMSG_MEM); return(false); } } else { pcell->libs = NULL; } /* no need to strdup */ if (hash_update(pcd->by_mod, pcell->name, pcell) == HASH_ADD_FAIL) return(false); #ifdef CFGT_DEBUG debugf("added cfgtcell '%s'", pcell->name); #endif if (hash_update_dup(pcd->by_bin, pcell->binary, pcell->name) == HASH_ADD_FAIL) return(false); #ifdef CFGT_DEBUG debugf("added cfgtcell '%s'", pcell->binary); #endif return(true); } /********************* * parse_cfgt_file() * *********************************************************************** DESCR parse data from PMKCFG_DATA file IN NONE OUT compiler data structure or NULL ***********************************************************************/ cfgtdata *parse_cfgt_file(void) { FILE *fp; bool rval; cfgtdata *pcd; prscell *pcell; prsdata *pdata; /* initialize parsing structure */ pdata = prsdata_init(); if (pdata == NULL) { errorf("cannot intialize prsdata."); return(NULL); } /* initialise configt tool data structure */ pcd = cfgtdata_init(); if (pcd == NULL) { prsdata_destroy(pdata); debugf("cannot initialize config tool data"); return(NULL); } fp = fopen(PMKCFG_DATA, "r"); if (fp == NULL) { hash_destroy(pcd->by_mod); hash_destroy(pcd->by_bin); free(pcd); prsdata_destroy(pdata); errorf("cannot open '%s' : %s.", PMKCFG_DATA, strerror(errno)); return(NULL); } /* parse data file and fill prsdata strucutre */ rval = parse_pmkfile(fp, pdata, kw_pmkcfgtool, nbkwct); fclose(fp); if (rval == true) { pcell = pdata->tree->first; while (pcell != NULL) { switch(pcell->token) { case CFGT_TOK_ADDCT : add_cfgtool(pcd, pcell->data); break; default : errorf("parsing of data file failed."); hash_destroy(pcd->by_mod); hash_destroy(pcd->by_bin); free(pcd); prsdata_destroy(pdata); return(NULL); break; } pcell = pcell->next; } } else { errorf("parsing of data file failed."); hash_destroy(pcd->by_mod); hash_destroy(pcd->by_bin); free(pcd); prsdata_destroy(pdata); return(NULL); } /* parsing data no longer needed */ prsdata_destroy(pdata); return(pcd); } /************************* * cfgtcell_get_binary() * *********************************************************************** DESCR get binary name from a given module name IN pgd : global data structure mod : module name buf : buffer to store binary name sb : buffer size OUT boolean ***********************************************************************/ bool cfgtcell_get_binary(cfgtdata *pcd, char *mod, char *buf, size_t sb) { cfgtcell *pcc; if (pcd == NULL) { /* not found */ return(false); } pcc = hash_get(pcd->by_mod, mod); if (pcc == NULL) { /* not found */ return(false); } else { /* found, copy */ if (strlcpy_b(buf, pcc->binary, sb) == false) return(false); return(true); } } /*********************** * cfgtcell_get_cell() * *********************************************************************** DESCR get cell relative to a given config tool filename IN pgd : global data structure binary : binary name OUT cfgtcell structure or NULL ***********************************************************************/ cfgtcell *cfgtcell_get_cell(cfgtdata *pcd, char *binary) { char *mod; if (pcd == NULL) { /* not found */ return(false); } mod = hash_get(pcd->by_bin, binary); if (mod == NULL) { /* not found */ return(NULL); } else { /* found, copy */ return(hash_get(pcd->by_mod, mod)); } } /******************** * ct_get_version() * *********************************************************************** DESCR use config tool to get the version IN ctpath : config tool path vstr : option string to get version buffer : storage buffer for the result sbuf : size of buffer OUT boolean ***********************************************************************/ bool ct_get_version(char *ctpath, char *vstr, char *buffer, size_t sbuf) { FILE *rpipe; bool rval = false; char cfgcmd[MAXPATHLEN]; if (snprintf_b(cfgcmd, sizeof(cfgcmd), CT_FORMAT_VERSION, ctpath, vstr) == false) return(false); rpipe = popen(cfgcmd, "r"); if (rpipe != NULL) { /* get version line */ rval = get_line(rpipe, buffer, sbuf); pclose(rpipe); } return(rval); } /***************** * ct_get_data() * *********************************************************************** DESCR use config tool to get data IN ctpath : config tool path vstr : option string to get version buffer : storage buffer for the result sbuf : size of buffer OUT boolean ***********************************************************************/ bool ct_get_data(char *ctpath, char *ostr, char *mod, char *buffer, size_t sbuf) { FILE *rpipe; bool rval = false; char cfgcmd[MAXPATHLEN]; if (mod == NULL) { /* no module */ if (snprintf_b(cfgcmd, sizeof(cfgcmd), CT_FORMAT_DATA, ctpath, ostr) == false) return(false); } else { /* use module */ if (snprintf_b(cfgcmd, sizeof(cfgcmd), CT_FORMAT_DATA_MOD, ctpath, ostr, mod) == false) return(false); } rpipe = popen(cfgcmd, "r"); if (rpipe != NULL) { /* get version line */ rval = get_line(rpipe, buffer, sbuf); pclose(rpipe); } return(rval); } pmk-0.10.4/tags.c010075500017500000000000000203061034626745600123700ustar00mipswheel/* $Id: tags.c 1519 2005-12-09 11:49:02Z mipsator $ */ /* * Copyright (c) 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. * */ #include #include #include "compat/pmk_ctype.h" #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "tags.h" /***************** * conv_to_tag() * *********************************************************************** DESCR convert a string to a tag IN str : string to convert OUT pointer to the tag buffer TODO check if size of buffer has been reached ***********************************************************************/ char *conv_to_tag(char *str) { static char buffer[MAX_TAG_LEN]; char *pbuf; size_t s = MAX_TAG_LEN; pbuf = buffer; /* process the given string */ while ((*str != '\0') && (s > 1)) { /* if we got an asterisk (pointer character) */ if (*str == '*') { /* then replace by P */ *pbuf = 'P'; } else { /* check if we have an alphanumeric character */ if (isalnum(*str) == 0) { /* no, replace by an underscore */ *pbuf = '_'; } else { /* yes, convert to uppercase if needed */ *pbuf = (char) toupper((int) *str); } } /* next character */ s--; pbuf++; str++; } *pbuf = '\0'; return(buffer); } /************* * gen_tag() * *********************************************************************** DESCR generate a tag suffix IN type : tag type container : container name content : content name misc : misc content OUT pointer to the tag suffix buffer ***********************************************************************/ char *gen_tag(int type, char *container, char *content, char *misc) { static char buffer[MAX_TAG_LEN]; char cnt[MAX_TAG_LEN], ctt[MAX_TAG_LEN], msc[MAX_TAG_LEN]; /* set data pointers */ switch (type) { case TAG_TYPE_HDR_TYP_MBR : strlcpy(msc, conv_to_tag(misc), sizeof(msc)); /* no break */ case TAG_TYPE_HDR_PRC : case TAG_TYPE_HDR_MCR : case TAG_TYPE_LIB_PRC : case TAG_TYPE_TYP_MBR : case TAG_TYPE_HDR_TYPE : strlcpy(ctt, conv_to_tag(content), sizeof(ctt)); /* no break */ case TAG_TYPE_BIN : case TAG_TYPE_CFGTOOL : case TAG_TYPE_HDR : case TAG_TYPE_LIB : case TAG_TYPE_PKGCFG : case TAG_TYPE_TYPE : strlcpy(cnt, conv_to_tag(container), sizeof(cnt)); break; } /* generate tag from format string */ switch (type) { case TAG_TYPE_BIN : snprintf(buffer, sizeof(buffer), FMT_TAG_BIN, cnt); break; case TAG_TYPE_CFGTOOL : snprintf(buffer, sizeof(buffer), FMT_TAG_CFGTL, cnt); break; case TAG_TYPE_HDR : snprintf(buffer, sizeof(buffer), FMT_TAG_HDR, cnt); break; case TAG_TYPE_HDR_PRC : snprintf(buffer, sizeof(buffer), FMT_TAG_HPRC, cnt, ctt); break; case TAG_TYPE_HDR_MCR : snprintf(buffer, sizeof(buffer), FMT_TAG_HMCR, cnt, ctt); break; case TAG_TYPE_LIB : snprintf(buffer, sizeof(buffer), FMT_TAG_LIB, cnt); break; case TAG_TYPE_LIB_PRC : snprintf(buffer, sizeof(buffer), FMT_TAG_LPROC, cnt, ctt); break; case TAG_TYPE_PKGCFG : snprintf(buffer, sizeof(buffer), FMT_TAG_PCFG, cnt); break; case TAG_TYPE_TYPE : snprintf(buffer, sizeof(buffer), FMT_TAG_TYPE, cnt); break; case TAG_TYPE_TYP_MBR : snprintf(buffer, sizeof(buffer), FMT_TAG_TMBR, cnt, ctt); break; case TAG_TYPE_HDR_TYPE : snprintf(buffer, sizeof(buffer), FMT_TAG_HTYPE, cnt, ctt); break; case TAG_TYPE_HDR_TYP_MBR : snprintf(buffer, sizeof(buffer), FMT_TAG_HTMBR, cnt, ctt, msc); break; default : return(NULL); } return(buffer); } /****************** * gen_tag_name() * *********************************************************************** DESCR generate a tag name IN type : tag type container : container name content : content name misc : misc content OUT pointer to the tag name buffer ***********************************************************************/ char *gen_tag_name(int type, char *container, char *content, char *misc) { static char buffer[MAX_TAG_LEN]; char *tag; /* generate tag suffix */ tag = gen_tag(type, container, content, misc); /* concatenate prefix and converted name */ strlcpy(buffer, TAG_PREFIX, sizeof(buffer)); strlcat(buffer, tag, sizeof(buffer)); return(buffer); } /***************** * gen_tag_def() * *********************************************************************** DESCR generate a tag definition name IN type : tag type container : container name content : content name misc : misc content OUT pointer to the tag definition name buffer ***********************************************************************/ char *gen_tag_def(int type, char *container, char *content, char *misc) { static char buffer[MAX_TAG_LEN]; char *tag; /* generate tag suffix */ tag = gen_tag(type, container, content, misc); /* concatenate prefix and converted name */ strlcpy(buffer, TAG_DEF_PREFIX, sizeof(buffer)); strlcat(buffer, tag, sizeof(buffer)); return(buffer); } /********************* * gen_ac_tag_name() * *********************************************************************** DESCR generate an autoconf-like tag name IN content : content name OUT pointer to the tag name buffer ***********************************************************************/ char *gen_ac_tag_name(char *content) { static char buffer[MAX_TAG_LEN]; char *tag; /* convert name to tag */ tag = conv_to_tag(content); /* concatenate prefix and converted name */ strlcpy(buffer, AC_TAG_PREFIX, sizeof(buffer)); strlcat(buffer, tag, sizeof(buffer)); return(buffer); } /*********************** * gen_basic_tag_def() * *********************************************************************** DESCR generate an autoconf-like tag name IN content : content name OUT pointer to the tag name buffer ***********************************************************************/ char *gen_basic_tag_def(char *content) { static char buffer[MAX_TAG_LEN]; char *tag; /* convert name to tag */ tag = conv_to_tag(content); /* concatenate prefix and converted name */ strlcpy(buffer, BASIC_DEF_PREFIX, sizeof(buffer)); strlcat(buffer, tag, sizeof(buffer)); return(buffer); } /******************* * gen_from_tmpl() * *********************************************************************** DESCR generate a file name from a template name IN template : template file name OUT pointer to the file name buffer ***********************************************************************/ char *gen_from_tmpl(char *template) { static char buffer[PATH_MAX]; char *pstr; /* copy template into buffer */ strlcpy(buffer, template, sizeof(buffer)); /* find and remove the last suffix */ pstr = strrchr(buffer, '.'); if (pstr != NULL) { *pstr = '\0'; } return(buffer); } pmk-0.10.4/compat004075500017500000000000000000001077177766300125015ustar00mipswheelpmk-0.10.4/compat/pmk_sys_types.h010064400017500000000000000040111027515120600156050ustar00mipswheel/* $Id: pmk_sys_types.h 1444 2005-08-06 15:08:54Z mipsator $ */ /* * 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. * */ #ifndef _PMK_SYS_TYPES_H_ #define _PMK_SYS_TYPES_H_ #include #include "config.h" /* blkcnt_t type */ #ifndef HAVE_BLKCNT_T #ifdef __osf__ /* Tru64 defines int64_t in the following header */ #include #endif /* __osf__ */ typedef int64_t blkcnt_t; /* file block counts */ #endif /* HAVE_BLKCNT_T */ #endif /* _PMK_SYS_TYPES_H_ */ pmk-0.10.4/compat/pmk_stdio.h010064400017500000000000000040411062134650400146720ustar00mipswheel/* $Id: pmk_stdio.h 1984 2007-05-12 14:20:52Z coudercd $ */ /* * Copyright (c) 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. * */ #ifndef _PMK_STDIO_H_ #define _PMK_STDIO_H_ #include #include #include "config.h" #ifndef HAVE_VSNPRINTF /* vsnprintf() function */ int vsnprintf(char *, size_t, const char *, va_list); #endif /* HAVE_VSNPRINTF */ #ifndef HAVE_SNPRINTF /* snprintf() function */ int snprintf(char *, size_t, const char *, ...); #endif /* HAVE_SNPRINTF */ #endif /* _PMK_STDIO_H_ */ pmk-0.10.4/compat/config.h.pmk010064400017500000000000000055751030070540500147420ustar00mipswheel/* $Id: config.h.pmk 1454 2005-08-17 19:07:49Z mipsator $ */ /* * 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. * */ #ifndef _PMK_CONFIG_H_ #define _PMK_CONFIG_H_ /* ! WARNING ! The following data is automatically set, you should not have to modify it. */ /********* * types * ***********************************************************************/ /* _Bool type (ISO C99) */ @DEF___BOOL@ /* blkcnt_t type (POSIX 1003.1-2003) */ @DEF__BLKCNT_T@ /* long long type */ @DEF__LONG_LONG@ /* unsigned long long type */ @DEF__UNSIGNED_LONG_LONG@ /* long double type */ @DEF__LONG_DOUBLE@ /* intmax_t type */ @DEF__INTMAX_T@ /* ptrdiff_t type */ @DEF__PTRDIFF_T@ /* wchar_t type */ @DEF__WCHAR_T@ /* wint_t type */ @DEF__WINT_T@ /*********** * headers * ***********************************************************************/ /* stdbool.h (ISO C99) */ @DEF__STDBOOL_H@ /* libgen.h (dirname and filename) */ @DEF__LIBGEN_H@ /************* * functions * ***********************************************************************/ /* strlcpy() */ @DEF__STRLCPY@ /* strlcat() */ @DEF__STRLCAT@ /* strdup() */ @DEF__STRDUP@ /* vsnprintf() */ @DEF__VSNPRINTF@ /* snprintf() */ @DEF__SNPRINTF@ /* isblank() */ @DEF__ISBLANK@ /* mkstemps() */ @DEF__MKSTEMPS@ /* basename() */ @DEF__BASENAME@ /* dirname() */ @DEF__DIRNAME@ #endif /* _PMK_CONFIG_H_ */ pmk-0.10.4/compat/pmk_ctype.h010064400017500000000000000035411027515120600146760ustar00mipswheel/* $Id: pmk_ctype.h 1444 2005-08-06 15:08:54Z mipsator $ */ /* * Copyright (c) 2003 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. * */ #ifndef _PMK_CTYPE_H_ #define _PMK_CTYPE_H_ #include #include "config.h" /* isblank() function */ #ifndef HAVE_ISBLANK int isblank(int); #endif /* HAVE_ISBLANK */ #endif /* _PMK_CTYPE_H_ */ pmk-0.10.4/compat/pmk_stdbool.h010064400017500000000000000053641032673633400152350ustar00mipswheel/* $Id: pmk_stdbool.h 1496 2005-10-23 16:39:56Z mipsator $ */ /* * 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. * */ #ifndef _PMK_STDBOOL_H_ #define _PMK_STDBOOL_H_ #include "config.h" /* boolean types */ #ifdef HAVE_STDBOOL_H #include #else /* HAVE_STDBOOL_H */ /* Sun Forte 5.4 C compiler and previous versions give out a "warning: _Bool is a keyword in ISO C99" message when we use typedef. In addition, every Sun Pro C compiler which conforms to ANSI C (and therefore sets __STDC__ to 1) shows the same behaviour. We avoid this by defining _Bool in a macro in these cases. */ #ifndef HAVE__BOOL # if defined __SUNPRO_C && (__SUNPRO_C < 0x550 || __STDC__ == 1) # define _Bool unsigned char # else /* __SUNPRO_C && (__SUNPRO_C < 0x550 || __STDC__ == 1) */ typedef unsigned char _Bool; # endif /* __SUNPRO_C && (__SUNPRO_C < 0x550 || __STDC__ == 1) */ #endif /* HAVE__BOOL */ #ifndef bool #define bool _Bool #endif /* bool */ #ifndef true #define true 1 #endif /* true */ #ifndef false #define false 0 #endif /* false */ #ifndef __bool_true_false_are_defined #define __bool_true_false_are_defined 1 #endif /* __bool_true_false_are_defined */ #endif /* HAVE_STDBOOL_H */ #endif /* _PMK_STDBOOL_H_ */ pmk-0.10.4/compat/pmk_string.h010064400017500000000000000044321027646175300150740ustar00mipswheel/* $Id: pmk_string.h 1449 2005-08-10 20:30:35Z mipsator $ */ /* * 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. * */ #ifndef _PMK_STRING_H_ #define _PMK_STRING_H_ #include #include "config.h" #include "pmk_stdbool.h" #ifndef HAVE_STRDUP /* strdup() function */ char *strdup(const char *); #endif /* HAVE_STRDUP */ #ifndef HAVE_STRLCPY /* strlcpy() function */ size_t strlcpy(char *, const char *, size_t); #endif /* HAVE_STRLCPY */ #ifndef HAVE_STRLCAT /* strlcat() function */ size_t strlcat(char *, const char *, size_t); #endif /* HAVE_STRLCAT */ bool snprintf_b(char *, size_t, const char *, ...); bool strlcat_b(char *, const char *, size_t); bool strlcpy_b(char *, const char *, size_t); #endif /* _PMK_STRING_H_ */ pmk-0.10.4/compat/pmk_unistd.h010064400017500000000000000035671027515120600150700ustar00mipswheel/* $Id: pmk_unistd.h 1444 2005-08-06 15:08:54Z mipsator $ */ /* * 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. * */ #ifndef _PMK_UNISTD_H_ #define _PMK_UNISTD_H_ #include #include "config.h" /* mkstemps() function */ #ifndef HAVE_MKSTEMPS int mkstemps(char *, int); #endif /* HAVE_MKSTEMPS */ #endif /* _PMK_UNISTD_H_ */ pmk-0.10.4/compat/pmk_libgen.h010064400017500000000000000037001027515120600150070ustar00mipswheel/* $Id: pmk_libgen.h 1444 2005-08-06 15:08:54Z mipsator $ */ /* * 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. * */ #ifndef _PMK_LIBGEN_H_ #define _PMK_LIBGEN_H_ #include "config.h" /* basename() and dirname() functions */ #ifdef HAVE_LIBGEN_H #include #else /* HAVE_LIBGEN_H */ char *basename(const char *); char *dirname(const char *); #endif /* HAVE_LIBGEN_H */ #endif /* _PMK_LIBGEN_H_ */ pmk-0.10.4/pathtools.h010064400017500000000000000043241024337422600134410ustar00mipswheel/* $Id: pathtools.h 1413 2005-05-20 14:47:50Z mipsator $ */ /* * Copyright (c) 2003 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. * */ #ifndef _PMK_PATHTOOLS_H_ #define _PMK_PATHTOOLS_H_ /************* * constants * ***********************************************************************/ #define CHAR_DOT '.' #define CHAR_EOS '\0' #define CHAR_SEP '/' #define STR_SEP "/" /*********************** * function prototypes * ***********************************************************************/ bool chkpath(char *, char *); bool relpath(char *, char *, char *); bool abspath(char *, char *, char *); bool uabspath(char *, char *, char *); bool makepath(char *, mode_t); #endif /* _PMK_PATHTOOLS_H_ */ pmk-0.10.4/lang.c010064400017500000000000000046131051247024500123360ustar00mipswheel/* $Id$ */ /* * Copyright (c) 2006 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. * */ #include "lang.h" /***************** * language data * ***********************************************************************/ lgdata_t lang_data[] = { /* * language label * compiler label * compiler flags label * linker flags label * SL cflags label * SL ldflags label * language ID */ { LANG_LABEL_C, PMKCONF_BIN_CC, CFLAGS_LABEL_C, LDFLAGS_LABEL_C, SLCFLAGS_LABEL_C, SLLDFLAGS_LABEL_C, MK_BLD_TARGET_C, MK_CLN_TARGET_C, MK_INST_TARGET_C, MK_DEINST_TARGET_C, LANG_C }, { LANG_LABEL_CXX, PMKCONF_BIN_CXX, CFLAGS_LABEL_CXX, LDFLAGS_LABEL_CXX, SLCFLAGS_LABEL_CXX, SLLDFLAGS_LABEL_CXX, MK_BLD_TARGET_CXX, MK_CLN_TARGET_CXX, MK_INST_TARGET_CXX, MK_DEINST_TARGET_CXX, LANG_CXX } }; size_t nb_lang_data = sizeof(lang_data) / sizeof(lgdata_t); pmk-0.10.4/samples004075500017500000000000000000001077177766400126635ustar00mipswheelpmk-0.10.4/samples/bin_c++004075500017500000000000000000001077177766300140625ustar00mipswheelpmk-0.10.4/samples/bin_c++/Makefile.pmk010064400017500000000000000016021011162364300163330ustar00mipswheel# $Id: Makefile.pmk 1153 2004-08-21 10:44:51Z mipsator $ CXX= @BIN_CXX@ CFLAGS= @CXXFLAGS@ NAME= hello all: show $(NAME) run_$(NAME) clean show: @echo "" @echo "-> Dumping template" @echo "" @echo "Makefile.pmk:" @echo "--dump-begin----------------------------" @cat Makefile.pmk @echo "--dump-end------------------------------" @echo "-> Dumping generated file" @echo "" @echo "Makefile:" @echo "--dump-begin----------------------------" @cat Makefile @echo "--dump-end------------------------------" $(NAME): @echo "" @echo "-> Building binary" @echo "" $(CXX) $(CXXFLAGS) -o $(NAME) $(NAME).cc run_$(NAME): @echo "" @echo "-> Running program" @echo "" @echo "--exec-begin----------------------------" @./${NAME} @echo "--exec-end------------------------------" clean: @echo "" @echo "-> Cleaning ..." @echo "" rm -f $(NAME) rm -f *.log Makefile @echo "Done." pmk-0.10.4/samples/bin_c++/hello.cc010064400017500000000000000003121011147142000155060ustar00mipswheel/* $Id: hello.cc 1151 2004-08-20 21:54:24Z mreindl $ */ /* This file is in the public domain. */ #include using namespace std; int main() { cout << "Hello World !" << endl; return 0; } pmk-0.10.4/samples/bin_c++/pmkfile010064400017500000000000000003061011147010000154430ustar00mipswheel# $Id: pmkfile 1150 2004-08-20 21:42:24Z mreindl $ # settings SETTINGS { LANG = "C++" TARGET = ("Makefile.pmk") } DEFINE { PACKAGE = "hello" VERSION = "1.0" FULL_NAME = "$PACKAGE-$VERSION" } pmk-0.10.4/samples/install004075500017500000000000000000001077177766400143315ustar00mipswheelpmk-0.10.4/samples/install/hello.txt010064400017500000000000000000341001715210100162040ustar00mipswheelHello, i am a test file :) pmk-0.10.4/samples/install/hello.sh010075500017500000000000000000611001715210100160020ustar00mipswheel#!/bin/sh echo "Hello, i am a test program :)" pmk-0.10.4/samples/install/Makefile010064400017500000000000000026021011471256100160150ustar00mipswheel# $Id: Makefile 1192 2004-08-30 21:00:33Z xsa $ # install sample test INST= pmkinstall TEST_DIR= test_dir TEST_BIN= hello.sh TEST_FILE= hello.txt TEST_TARGET1= $(TEST_DIR)/test1.txt TEST_TARGET2= $(TEST_DIR)/test2.txt TEST_TARGET3= $(TEST_DIR)/test3.sh TARGET_LIST= $(TEST_TARGET1) $(TEST_TARGET2) $(TEST_TARGET3) all: $(TEST_DIR) chk_dir inst_data inst_prog chk_files clean $(TEST_DIR): @echo "" @echo "-> Creating test directory" @echo "" $(INST) -d -m 770 $(TEST_DIR) chk_dir: @echo "" @echo "-> Checking test directory" @echo "" @if (test -d "$(TEST_DIR)"); then \ ls -ld $(TEST_DIR); \ echo "Directory OK."; \ else \ echo "Failed."; \ exit 1; \ fi inst_data: @echo "" @echo "-> Installing test data" @echo "" $(INST) -m u+rw $(TEST_FILE) $(TEST_TARGET1) $(INST) -m ug+r $(TEST_FILE) $(TEST_TARGET2) inst_prog: @echo "" @echo "-> Installing test program" @echo "" $(INST) -m 766 $(TEST_BIN) $(TEST_TARGET3) chk_files: @echo "" @echo "-> Checking test files" @echo "" @for i in $(TARGET_LIST); do \ if (test -f $$i); then \ ls -l $$i; \ else \ echo "$$i detection failed."; \ exit 1; \ fi \ done @echo "" clean: @echo "" @echo "-> Cleaning ..." @echo "" @for i in $(TARGET_LIST); do \ if (test -f $$i); then \ echo "Removing $$i"; \ rm -f $$i; \ fi \ done @echo "Removing $(TEST_DIR)"; @rmdir $(TEST_DIR) @echo "Done." @echo "" pmk-0.10.4/samples/scan_c004075500017500000000000000000001077177766400141115ustar00mipswheelpmk-0.10.4/samples/scan_c/Makefile010064400017500000000000000013601022730050700155730ustar00mipswheel# $Id: Makefile 1398 2005-04-13 20:29:59Z mipsator $ # source scanning test SCAN= pmkscan SCAN_FILE= pmkfile.scan SAMPLE= hello.c all: show_sample $(SCAN) show_scan clean show_sample: @echo "-> Dumping sample C file" @echo "" @echo "$(SAMPLE):" @echo "--dump-begin----------------------------" @cat $(SAMPLE) @echo "--dump-end------------------------------" $(SCAN): @echo "" @echo "-> Running $(SCAN)" @echo "" $(SCAN) -p show_scan: @echo "" @echo "-> Dumping $(SCAN_FILE)" @echo "" @echo "--dump-begin----------------------------" @cat $(SCAN_FILE) @echo "--dump-end------------------------------" clean: @echo "" @echo "-> Cleaning ..." @echo "" @echo "Removing $(SCAN_FILE)" @rm $(SCAN_FILE) @echo "" @echo "Done." pmk-0.10.4/samples/scan_c/hello.c010064400017500000000000000004131001715210100153700ustar00mipswheel/* $Id: hello.c 1023 2004-02-25 16:58:41Z mipsator $ */ /* public domain */ #include #include #define STR "hello, i am a character string :)" int main() { char buf[256]; strlcpy(buf, STR, sizeof(buf)); printf("%s\n", buf); return(0); } pmk-0.10.4/samples/README.samples010064400017500000000000000011271011610245300152260ustar00mipswheelPre Make Kit samples/README.samples file Document revision: $Id: README.samples 1202 2004-09-03 14:52:27Z xsa $ Test samples for PMK -------------------- This directory provides some samples of pmk use. General test can be done via the Makefile located in the samples directory. To run these tests you must install pmk before (see INSTALL) and then run ``make test'' from the samples directory. You can send us feedback to the following e-mail: pmk-users@lists.sourceforge.net Or, if you have a sourceforge account, on this forum: http://sourceforge.net/forum/forum.php?forum_id=326673 pmk-0.10.4/samples/lib_c004075500017500000000000000000001077177766400137335ustar00mipswheelpmk-0.10.4/samples/lib_c/Makefile.pmk010064400017500000000000000032541011603234700162100ustar00mipswheel# $Id: Makefile.pmk 1200 2004-09-03 09:09:59Z xsa $ CC= @BIN_CC@ AR= @BIN_AR@ RANLIB= @BIN_RANLIB@ ARFLAGS= cr SLCFLAGS= @SLCFLAGS@ SLLDFLAGS= @SLLDFLAGS@ NAME= hello LIBNAME= lib$(NAME) MAJOR= @LIBPMK_MAJ@ MINOR= @LIBPMK_MIN@ LIB_STATIC= $(LIBNAME).a LIB_SHARED= @LIBNAME@ LIB_SHARED_V= @LIBNAMEV@ B_OBJS= $(NAME).o L_OBJS= $(LIBNAME).o all: show $(LIB_STATIC) $(LIB_SHARED) $(NAME) run_$(NAME) clean .c.o: @echo "" @echo "-> Building object file" $(CC) $(CFLAGS) $(SLCFLAGS) -c $< show: @echo "" @echo "-> Dumping template" @echo "" @echo "Makefile.pmk:" @echo "--dump-begin----------------------------" @cat Makefile.pmk @echo "--dump-end------------------------------" @echo "-> Dumping generated file" @echo "" @echo "Makefile:" @echo "--dump-begin----------------------------" @cat Makefile @echo "--dump-end------------------------------" $(LIB_STATIC): $(L_OBJS) @echo "" @echo "-> Building static lib" @echo "" $(AR) $(ARFLAGS) $@ $(L_OBJS) $(RANLIB) $@ $(LIB_SHARED): $(L_OBJS) @echo "" @echo "-> Building shared lib" @echo "" $(CC) $(SLLDFLAGS) -o $@ $(L_OBJS) cp $(LIB_SHARED) $(LIB_SHARED_V) $(NAME): @echo "" @echo "-> Building binary" @echo "" $(CC) -o $(NAME) -L. -l${NAME} $(NAME).c run_$(NAME): @echo "" @echo "-> Running program" @echo "" @echo "LD_LIBRARY_PATH=.:${LD_LIBRARY_PATH} ${NAME}" @echo "" @echo "--exec-begin----------------------------" @LD_LIBRARY_PATH=.:${LD_LIBRARY_PATH} ./${NAME} @echo "--exec-end------------------------------" clean: @echo "" @echo "-> Cleaning ..." @echo "" rm -f $(B_OBJS) $(L_OBJS) rm -f $(LIB_STATIC) $(LIB_SHARED) $(LIB_SHARED_V) rm -f $(NAME) rm -f *.log Makefile @echo "Done." pmk-0.10.4/samples/lib_c/libhello.h010064400017500000000000000001541000234265100157150ustar00mipswheel/* $Id: libhello.h 899 2004-01-17 23:30:49Z mipsator $ */ void print_hello(void); void print_world(void); pmk-0.10.4/samples/lib_c/libhello.c010064400017500000000000000002521000234265100157070ustar00mipswheel/* $Id: libhello.c 899 2004-01-17 23:30:49Z mipsator $ */ #include void print_hello(void) { printf("Hello"); } void print_world(void) { printf("World"); } pmk-0.10.4/samples/lib_c/hello.c010064400017500000000000000002771001570463600152400ustar00mipswheel/* $Id: hello.c 1020 2004-02-21 16:38:54Z mipsator $ */ #include #include "libhello.h" int main() { print_hello(); printf(" "); print_world(); printf(" !\n"); return(0); } pmk-0.10.4/samples/lib_c/pmkfile010064400017500000000000000006451011344605400153360ustar00mipswheel# $Id: pmkfile 1163 2004-08-26 20:46:36Z xsa $ # pmkfile example # settings SETTINGS { # set default language LANG = "C" # target files TARGET = ("Makefile.pmk") # detect compiler DETECT = ("CC") } DEFINE { LIBPMK_NAME = "hello" LIBPMK_MAJ = "1" LIBPMK_MIN = "2" } BUILD_SHLIB_NAME { NAME = "$LIBPMK_NAME" MAJOR = "$LIBPMK_MAJ" MINOR = "$LIBPMK_MIN" VERSION_NONE = "LIBNAME" VERSION_FULL = "LIBNAMEV" } pmk-0.10.4/samples/subdir004075500017500000000000000000001077177766400141535ustar00mipswheelpmk-0.10.4/samples/subdir/Makefile.subdir.pmk010064400017500000000000000012310774732527600177360ustar00mipswheel# $Id: Makefile.subdir.pmk 601 2003-10-27 23:31:10Z mipsator $ # Makefile example CFLAGS= @CFLAGS@ LIBS= @LIBS@ # pmk directories SRCDIR_ABS= @srcdir_abs@ SRCDIR_REL= @srcdir_rel@ SRCDIR_ROOT_ABS= @srcdir_root_abs@ SRCDIR_ROOT_REL= @srcdir_root_rel@ BUILDDIR_ABS= @builddir_abs@ BUILDDIR_REL= @builddir_rel@ BUILDDIR_ROOT_ABS= @builddir_root_abs@ BUILDDIR_ROOT_REL= @builddir_root_rel@ # autoconf directories ABS_SRCDIR= @abs_srcdir@ SRCDIR= @srcdir@ ABS_TOP_SRCDIR= @abs_top_srcdir@ TOP_SRCDIR= @top_srcdir@ ABS_BUILDDIR= @abs_builddir@ BUILDDIR= @builddir@ ABS_TOP_BUILDDIR= @abs_top_builddir@ TOP_BUILDDIR= @top_builddir@ test: @echo $(PACKAGE) pmk-0.10.4/samples/config_sample.h.pmk010064400017500000000000000002470765404075700164770ustar00mipswheel/* $Id: config_sample.h.pmk 240 2003-04-30 21:36:47Z mipsator $ */ /* availability of strlcpy */ @DEF__STRLCPY@ /* availability of sys/param.h */ @DEF__SYS_PARAM_H@ pmk-0.10.4/samples/Makefile.sample.pmk010064400017500000000000000016611010766070000164200ustar00mipswheel# $Id: Makefile.sample.pmk 1099 2004-08-15 13:14:40Z mipsator $ # Makefile example PACKAGE= @PACKAGE@ VERSION= @VERSION@ FULL_NAME= @FULL_NAME@ CFLAGS= @CFLAGS@ CXXFLAGS= @CXXFLAGS@ SLCFLAGS= @SLCFLAGS@ LIBS= @LIBS@ OS_NAME= @OS_NAME@ OS_VERSION= @OS_VERSION@ OS_ARCH= @OS_ARCH@ GTK_CFLAGS= @GTK_CFLAGS@ GTK_LIBS= @GTK_LIBS@ GTK_CONFIG= @GTK_CONFIG@ # pmk directories SRCDIR_ABS= @srcdir_abs@ SRCDIR_REL= @srcdir_rel@ SRCDIR_ROOT_ABS= @srcdir_root_abs@ SRCDIR_ROOT_REL= @srcdir_root_rel@ BUILDDIR_ABS= @builddir_abs@ BUILDDIR_REL= @builddir_rel@ BUILDDIR_ROOT_ABS= @builddir_root_abs@ BUILDDIR_ROOT_REL= @builddir_root_rel@ # autoconf directories ABS_SRCDIR= @abs_srcdir@ SRCDIR= @srcdir@ ABS_TOP_SRCDIR= @abs_top_srcdir@ TOP_SRCDIR= @top_srcdir@ ABS_BUILDDIR= @abs_builddir@ BUILDDIR= @builddir@ ABS_TOP_BUILDDIR= @abs_top_builddir@ TOP_BUILDDIR= @top_builddir@ test: @echo $(PACKAGE) @echo `$(GTK_CONFIG) --version` pmk-0.10.4/samples/ovrfile.sample010064400017500000000000000002510773073566500156020ustar00mipswheel# $Id: ovrfile.sample 513 2003-09-14 00:52:05Z mipsator $ # override file example # do you like Clarke and Kubrik ? OS_NAME="HAL" OS_VERSION="9000" OS_ARCH="discovery" pmk-0.10.4/samples/bin_c004075500017500000000000000000001077177766400137355ustar00mipswheelpmk-0.10.4/samples/bin_c/config.h.pmk010064400017500000000000000002271000301434000161510ustar00mipswheel/* $Id: config.h.pmk 901 2004-01-19 17:50:24Z xsa $ */ /* availability of strlcpy() */ @DEF__STRLCPY@ /* availability of strlcat() */ @DEF__STRLCAT@ pmk-0.10.4/samples/bin_c/Makefile.pmk010064400017500000000000000016031011162364300162060ustar00mipswheel# $Id: Makefile.pmk 1153 2004-08-21 10:44:51Z mipsator $ CC= @BIN_CC@ CFLAGS= @CFLAGS@ NAME= hello all: show $(NAME) run_${NAME} clean show: @echo "" @echo "-> Dumping template" @echo "" @echo "Makefile.pmk:" @echo "--dump-begin----------------------------" @cat Makefile.pmk @echo "--dump-end------------------------------" @echo "-> Dumping generated file" @echo "" @echo "Makefile:" @echo "--dump-begin----------------------------" @cat Makefile @echo "--dump-end------------------------------" ${NAME}: @echo "" @echo "-> Bulding binary" @echo "" $(CC) $(CFLAGS) -o $(NAME) $(NAME).c run_$(NAME): @echo "" @echo "-> Running program" @echo "" @echo "--exec-begin----------------------------" @./${NAME} @echo "--exec-end------------------------------" clean: @echo "" @echo "-> Cleaning ..." @echo "" rm -f $(NAME) rm -f *.log Makefile config.h @echo "Done." pmk-0.10.4/samples/bin_c/hello.c010064400017500000000000000011641012506736500152410ustar00mipswheel/* $Id: hello.c 1231 2004-09-24 19:01:09Z mipsator $ */ /* This file is in the public domain. */ #include #include #include "config.h" #define FMT_STRLCPY_MSG "Your system %s have strlcpy() in 'string.h'.\n" #define FMT_STRLCAT_MSG "Your system %s have strlcat() in 'string.h'.\n" #define MSG_HAS "does" #define MSG_HAS_NOT "does not" int main(void) { char buf[1024]; #ifdef HAVE_STRLCPY printf(FMT_STRLCPY_MSG, MSG_HAS); #else printf(FMT_STRLCPY_MSG, MSG_HAS_NOT); #endif #ifdef HAVE_STRLCAT printf(FMT_STRLCAT_MSG, MSG_HAS); #else printf(FMT_STRLCAT_MSG, MSG_HAS_NOT); #endif return(0); } pmk-0.10.4/samples/bin_c/pmkfile010064400017500000000000000005561012506736500153500ustar00mipswheel# $Id: pmkfile 1231 2004-09-24 19:01:09Z mipsator $ # settings SETTINGS { LANG = "C" TARGET = ("Makefile.pmk","config.h.pmk") } DEFINE { PACKAGE = "hello" VERSION = "1.0" FULL_NAME = "$PACKAGE-$VERSION" } # checking strlcpy() and strlcat() in string.h CHECK_HEADER(function_strlcat) { REQUIRED = FALSE NAME = "string.h" FUNCTION = ("strlcpy","strlcat") } pmk-0.10.4/samples/lib_c++004075500017500000000000000000001077177766400140615ustar00mipswheelpmk-0.10.4/samples/lib_c++/Makefile.pmk010064400017500000000000000033251011603234700163350ustar00mipswheel# $Id: Makefile.pmk 1200 2004-09-03 09:09:59Z xsa $ CXX= @BIN_CXX@ AR= @BIN_AR@ RANLIB= @BIN_RANLIB@ CXXFLAGS= @CXXFLAGS@ ARFLAGS= cr SLCXXFLAGS= @SLCXXFLAGS@ SLLDFLAGS= @SLLDFLAGS@ NAME= hello LIBNAME= lib$(NAME) MAJOR= @LIBPMK_MAJ@ MINOR= @LIBPMK_MIN@ LIB_STATIC= $(LIBNAME).a LIB_SHARED= @LIBNAME@ LIB_SHARED_V= @LIBNAMEV@ B_OBJS= $(NAME).o L_OBJS= $(LIBNAME).o all: show $(LIB_STATIC) $(LIB_SHARED) $(NAME) run_$(NAME) clean .cc.o: @echo "" @echo "-> Building object file" $(CXX) $(CXXFLAGS) $(SLCXXFLAGS) -c $< show: @echo "" @echo "-> Dumping template" @echo "" @echo "Makefile.pmk:" @echo "--dump-begin----------------------------" @cat Makefile.pmk @echo "--dump-end------------------------------" @echo "-> Dumping generated file" @echo "" @echo "Makefile:" @echo "--dump-begin----------------------------" @cat Makefile @echo "--dump-end------------------------------" $(LIB_STATIC): $(L_OBJS) @echo "" @echo "-> Building static lib" @echo "" $(AR) $(ARFLAGS) $@ $(L_OBJS) $(RANLIB) $@ $(LIB_SHARED): $(L_OBJS) @echo "" @echo "-> Building shared lib" @echo "" $(CXX) $(SLLDFLAGS) -o $@ $(L_OBJS) cp $(LIB_SHARED) $(LIB_SHARED_V) $(NAME): @echo "" @echo "-> Building binary" @echo "" $(CXX) -o $(NAME) -L. -l${NAME}++ $(NAME).cc run_$(NAME): @echo "" @echo "-> Running program" @echo "" @echo "LD_LIBRARY_PATH=.:${LD_LIBRARY_PATH} ./${NAME}" @echo "" @echo "--exec-begin----------------------------" @LD_LIBRARY_PATH=.:${LD_LIBRARY_PATH} ./${NAME} @echo "--exec-end------------------------------" clean: @echo "" @echo "-> Cleaning ..." @echo "" rm -f $(B_OBJS) $(L_OBJS) rm -f $(LIB_STATIC) $(LIB_SHARED) $(LIB_SHARED_V) rm -f $(NAME) rm -f *.log Makefile @echo "Done." pmk-0.10.4/samples/lib_c++/hello.cc010064400017500000000000000003411010304141700155060ustar00mipswheel/* $Id: hello.cc 1083 2004-08-01 01:10:39Z mreindl $ */ #include #include "libhello.hh" using namespace std; int main(void) { print_hello(); cout << " "; print_world(); cout << " !" << endl; return(0); } pmk-0.10.4/samples/lib_c++/pmkfile010064400017500000000000000006521011344605400154620ustar00mipswheel# $Id: pmkfile 1163 2004-08-26 20:46:36Z xsa $ # pmkfile example # settings SETTINGS { # set default language LANG = "C++" # target files TARGET = ("Makefile.pmk") # detect compiler DETECT = ("CXX") } DEFINE { LIBPMK_NAME = "hello++" LIBPMK_MAJ = "1" LIBPMK_MIN = "2" } BUILD_SHLIB_NAME { NAME = "$LIBPMK_NAME" MAJOR = "$LIBPMK_MAJ" MINOR = "$LIBPMK_MIN" VERSION_NONE = "LIBNAME" VERSION_FULL = "LIBNAMEV" } pmk-0.10.4/samples/lib_c++/libhello.hh010064400017500000000000000001561002263767500162340ustar00mipswheel/* $Id: libhello.hh 1035 2004-03-07 15:29:01Z mipsator $ */ void print_hello(void); void print_world(void); pmk-0.10.4/samples/lib_c++/libhello.cc010064400017500000000000000003021010304141700161720ustar00mipswheel/* $Id: libhello.cc 1083 2004-08-01 01:10:39Z mreindl $ */ #include using namespace std; void print_hello(void) { cout << "Hello"; } void print_world(void) { cout << "World"; } pmk-0.10.4/samples/pmkfile.sample010064400017500000000000000036571012556572100155620ustar00mipswheel# $Id: pmkfile.sample 1234 2004-09-26 16:18:25Z mipsator $ # pmkfile example # settings SETTINGS { # set autoconf compatibility AC_COMPAT = "ac_config.h" # set default language LANG = "C" # target files TARGET = ("Makefile.sample.pmk","config_sample.h.pmk", "subdir/Makefile.subdir.pmk") # detect compiler DETECT = ("CC") #DETECT = ("CC","CXX") } # put some defines DEFINE { PACKAGE = "scandisk" VERSION = "0.0.1b" FULL_NAME = "$PACKAGE-$VERSION" } # define switches SWITCHES { use_curses = TRUE use_gtk = FALSE } # check availability of termcap library CHECK_LIB(lib_termcap) { REQUIRED = FALSE NAME = "termcap" } # check function getwin in libcurses # this check depends of lib_termcap check for test purposes CHECK_LIB(lib_curses) { REQUIRED = FALSE DEPEND = ("use_curses","lib_termcap") NAME = "curses" FUNCTION = ("getwin", "getstr") } # check availability of sys/param.h header CHECK_HEADER(sys_param) { REQUIRED = FALSE NAME = "sys/param.h" LANG = "C++" } # check function strlcpy in string.h CHECK_HEADER(string_strlcpy) { REQUIRED = FALSE NAME = "string.h" FUNCTION = "strlcpy" } # try to find gtk-config in path CHECK_BINARY(bin_gtk_config) { REQUIRED = FALSE DEPEND = ("use_gtk") NAME = "gtk-config" } # get data via libpng-config CHECK_CONFIG(lib_png) { REQUIRED = FALSE NAME = "libpng-config" VERSION = "1.2" } IF(bin_gtk_config) { # enter only if 'bin_gtk_config' has been found # get data for gtk+ via pkg-config CHECK_PKG_CONFIG(gtk_data) { REQUIRED = FALSE NAME = "gtk+" VERSION = "1.2" CFLAGS = "GTK_CFLAGS" LIBS = "GTK_LIBS" } } # check _Bool type CHECK_TYPE(type_bool_posix) { REQUIRED = FALSE NAME = "_Bool" } IF(!type_bool_posix) { # check c++ bool type CHECK_TYPE(type_bool_cxx) { REQUIRED = FALSE NAME = "bool" LANG = "C++" } } # check byte order (useless, test purpose) CHECK_VARIABLE(var_endian) { REQUIRED=FALSE NAME = "HW_BYTEORDER" VALUE = "LITTLE_ENDIAN" } pmk-0.10.4/samples/Makefile010064400017500000000000000073611015214541400143550ustar00mipswheel# $Id: Makefile 1265 2004-11-27 18:44:28Z mipsator $ PREMAKE= pmk SETUP= $(PREMAKE)setup SCAN= $(PREMAKE)scan INST= $(PREMAKE)install PKGCFG= $(PREMAKE)pc SAMPLE= $(PREMAKE)file.sample CONFIG= $(PREMAKE).conf.sample #SELFINST= self-$(INST) TEST_SAMPLE= test_samples all: test_all test_bin_c: @echo "" @echo "=> Testing C binary building" @echo "" @echo "-> Running pmk" @echo "" @cd bin_c && pmk @echo "" @cd bin_c && make @echo "" @echo "=> End of test" @echo "" test_bin_cxx: @echo "" @echo "=> Testing C++ binary building" @echo "" @echo "-> Running pmk" @echo "" @cd bin_c++ && pmk @echo "" @cd bin_c++ && make @echo "" @echo "=> End of test" @echo "" test_lib_c: @echo "" @echo "=> Testing C library building" @echo "" @echo "-> Running pmk" @echo "" @cd lib_c && pmk @echo "" @cd lib_c && make @echo "" @echo "=> End of test" @echo "" test_lib_cxx: @echo "" @echo "=> Testing C++ library building" @echo "" @echo "-> Running pmk" @echo "" @cd lib_c++ && pmk @echo "" @cd lib_c++ && make @echo "" @echo "=> End of test" @echo "" test_$(PREMAKE): @echo "" @echo "=> Testing $(PREMAKE) with sample files" @echo "" @echo "-> Dumping target files" @echo "" @echo "Makefile.sample.pmk" @echo "----------------------------------------" @cat Makefile.sample.pmk @echo "----------------------------------------" @echo "" @echo "subdir/Makefile.subdir.pmk" @echo "----------------------------------------" @cat subdir/Makefile.subdir.pmk @echo "----------------------------------------" @echo "" @echo "config_sample.h.pmk" @echo "----------------------------------------" @cat config_sample.h.pmk @echo "----------------------------------------" @echo "" @echo "ac_config.h" @echo "----------------------------------------" @cp ac_config.h.sample ac_config.h @cat ac_config.h @echo "----------------------------------------" @echo "" @echo "-> Running pmk" $(PREMAKE) -l -b $(TEST_SAMPLE) -e use_gtk -f pmkfile.sample -o ovrfile.sample @echo "" @echo "-> Dumping generated files" @echo "" @echo "$(TEST_SAMPLE)/Makefile.sample" @echo "----------------------------------------" @cat $(TEST_SAMPLE)/Makefile.sample @echo "----------------------------------------" @echo "" @echo "$(TEST_SAMPLE)/subdir/Makefile.subdir" @echo "----------------------------------------" @cat $(TEST_SAMPLE)/subdir/Makefile.subdir @echo "----------------------------------------" @echo "" @echo "$(TEST_SAMPLE)/config_sample.h" @echo "----------------------------------------" @cat $(TEST_SAMPLE)/config_sample.h @echo "----------------------------------------" @echo "" @echo "$(TEST_SAMPLE)/ac_config.h" @echo "----------------------------------------" @cat $(TEST_SAMPLE)/ac_config.h @echo "----------------------------------------" @echo "" @echo "=> End of test" @echo "" test_$(SETUP): @echo "" @echo "=> Testing $(SETUP)" @echo "Generating local pmk.conf." @echo "(need USERMODE enabled)" @echo "" $(SETUP) -V @echo "" test_scan_c: @echo "" @echo "=> Testing $(SCAN)" @cd scan_c && make @echo "" @echo "=> End of test" @echo "" test_$(INST): @echo "" @echo "=> Testing $(INST)" @cd install && make @echo "" @echo "=> End of test" @echo "" test_clean: @echo "" @echo "=> Removing generated files" rm -rf $(TEST_SAMPLE) rm -f ac_config.h pmkfile.scan pmk*.log @echo "" @echo "=> End of cleaning." @echo "" test_pmk_only: test_$(SETUP) test_$(PREMAKE) test_clean test_old_all: test_pmk_only # all binary tests test_bins: test_bin_c test_bin_cxx # all scan tests test_scans: test_scan_c # all library tests test_libs: test_lib_c test_lib_cxx # all tests test_all: test_bins test_libs test_scans test_$(INST) # test target => alias to all target test: all # clean all clean: test_clean pmk-0.10.4/samples/ac_config.h.sample010064400017500000000000000007000766520502300162540ustar00mipswheel/* $Id: ac_config.h.sample 274 2003-05-28 19:12:19Z mipsator $ */ /* sample of configuration header used with autoconf */ /* termcap library */ #undef HAVE_TERMCAP /* getwin function in curses library */ #undef HAVE_GETWIN /* sys/param.h header */ #undef HAVE_SYS_PARAM_H /* strlcpy function in string.h header */ #undef HAVE_STRLCPY /* gtk-config binary */ #undef HAVE_GTK_CONFIG /* gathering data via png-config */ #undef HAVE_PNG_CONFIG pmk-0.10.4/hash_tools.c010064400017500000000000000121661031527674300135720ustar00mipswheel/* $Id: hash_tools.c 1475 2005-09-24 16:25:07Z mipsator $ */ /* * Copyright (c) 2004-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. * */ #include #include #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "hash_tools.h" #include "premake.h" /************** * parse_idtf * *********************************************************************** DESCR parse string for identifiers IN pstr : string to parse pbuf : resulting string buffer size : size of buffer OUT buffer address or NULL ***********************************************************************/ char *parse_idtf(char *pstr, char *pbuf, size_t size) { while (((isalnum(*pstr) != 0) || (*pstr == '_')) && (size > 0)) { *pbuf = *pstr; pbuf++; pstr++; size--; } if (size == 0) return(NULL); *pbuf = CHAR_EOS; /* return new cursor */ return(pstr); } /****************** * process_string * *********************************************************************** DESCR process string to substitute variables with their values IN pstr : string to process pht : hash table where variables are stored OUT new string or NULL ***********************************************************************/ char *process_string(char *pstr, htable *pht) { bool bs = false; char buf[OPT_VALUE_LEN], var[OPT_NAME_LEN], *pvar, *pval, *pbuf; size_t size; size = sizeof(buf); pbuf = buf; while ((*pstr != CHAR_EOS) && (size > 0)) { switch(*pstr) { case '\\' : bs = true; pstr++; break; case '$' : if (bs == false) { /* found variable */ pstr++; pstr = parse_idtf(pstr, var, size); if (pstr == NULL) { /* debugf("parse_idtf returned null."); */ return(NULL); } else { /* check if identifier exists */ pvar = hash_get(pht, var); if (pvar != NULL) { /* process identifer value */ pval = process_string(pvar, pht); pvar = pval; /* append value */ while ((*pvar != CHAR_EOS) && (size > 0)) { *pbuf = *pvar; pbuf++; pvar++; size--; } /* clean processed value */ free(pval); } } } else { /* copy character */ *pbuf = *pstr; pbuf++; pstr++; size--; bs = false; } break; default : if (bs == true) { *pbuf = '\\'; pbuf++; pstr++; size--; if (size == 0) { /* debugf("overflow."); */ return(NULL); } bs = false; } /* copy character */ *pbuf = *pstr; pbuf++; pstr++; size--; break; } } if (size == 0) { /* debugf("overflow.");*/ return(NULL); } *pbuf = CHAR_EOS; return(strdup(buf)); } /***************** * single_append * *********************************************************************** DESCR append only if not already in the string IN pht : hash table key : key where to append value : value to append OUT boolean ***********************************************************************/ bool single_append(htable *pht, char *key, char *value) { bool found = false; char *cval, *pstr; size_t s; if (value == NULL) return(false); if (*value == CHAR_EOS) return(true); cval = hash_get(pht, key); pstr = strstr(cval, value); s = strlen (value); while ((pstr != NULL) && (found == false)) { pstr = pstr + s; if ((*pstr == ' ') || (*pstr == CHAR_EOS)) { /* found existing value */ found = true; } pstr = strstr(pstr, value); } if (found == false) { if (hash_append(pht, key, value, " ") == HASH_ADD_FAIL) { /* add failed */ return(false); } } return(true); } pmk-0.10.4/tags.h010075500017500000000000000077371034626745600124120ustar00mipswheel/* $Id: tags.h 1519 2005-12-09 11:49:02Z mipsator $ */ /* * Copyright (c) 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. * */ #ifndef _PMK_TAGS_H_ #define _PMK_TAGS_H_ /************* * constants * **********************************************************************************************/ /* pmk tags related constants *****************************************************************/ /* tag types */ enum { TAG_TYPE_UNKNOWN = 0, TAG_TYPE_BIN, /* binary */ TAG_TYPE_CFGTOOL, /* config tool binary (*-config) */ TAG_TYPE_HDR, /* header */ TAG_TYPE_HDR_PRC, /* header procedure */ TAG_TYPE_HDR_MCR, /* header macro */ TAG_TYPE_LIB, /* library */ TAG_TYPE_LIB_PRC, /* library procedure */ TAG_TYPE_PKGCFG, /* pkg-config module */ TAG_TYPE_TYPE, /* type */ TAG_TYPE_TYP_MBR, /* type member */ TAG_TYPE_HDR_TYPE, /* header type */ TAG_TYPE_HDR_TYP_MBR, /* header type member */ /* XXX TODO config and pkgconfir stuff */ }; /* tag format strings */ #define FMT_TAG_BIN "BIN_%s" /* binary tag */ #define FMT_TAG_CFGTL "CFGTOOL_%s" /* config tool binary */ #define FMT_TAG_HDR "HDR_%s" /* header tag */ #define FMT_TAG_HPRC "HPROC_%s_%s" /* header procedure tag */ #define FMT_TAG_HMCR "HMACRO_%s_%s" /* header macro tag */ #define FMT_TAG_LIB "LIB_%s" /* library tag */ #define FMT_TAG_LPROC "LPROC_%s_%s" /* library procedure tag */ #define FMT_TAG_PCFG "PKGCFG_%s" /* pkg-config module tag */ #define FMT_TAG_TYPE "TYPE_%s" /* type tag */ #define FMT_TAG_TMBR "TMEMB_%s_%s" /* type member tag */ #define FMT_TAG_HTYPE "HTYPE_%s_%s" /* header type tag */ #define FMT_TAG_HTMBR "HTMEMB_%s_%s_%s" /* header type member tag */ /* tag prefixes */ #define TAG_PREFIX "TAG_" /* advanced tag prefix */ #define TAG_DEF_PREFIX "TAGDEF_" /* advanced tag definition prefix */ #define AC_TAG_PREFIX "HAVE_" /* autoconf-like tag prefix */ #define BASIC_DEF_PREFIX "DEF__" /* basic tag definition format */ /* maximum length of a tag name */ #define MAX_TAG_LEN 128 /* allowed characters in a tag name */ #define TAG_IDTF_CHAR "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" /************** * prototypes * ***********************************************************************/ char *conv_to_tag(char *); char *gen_tag(int, char *, char *, char *); char *gen_tag_name(int, char *, char *, char *); char *gen_tag_def(int, char *, char *, char *); char *gen_ac_tag_name(char *); char *gen_basic_tag_def(char *); char *gen_from_tmpl(char *); #endif /* _PMK_TAGS_H_ */ pmk-0.10.4/errmsg.h010064400017500000000000000045721011760661200127250ustar00mipswheel/* $Id: errmsg.h 1211 2004-09-08 13:47:54Z xsa $ */ /* * Copyright (c) 2004 Xavier Santolaria * 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. * */ #ifndef _ERRMSG_H_ #define _ERRMSG_H_ #define _ERRMSG_FILE_ERRNO "``%s'' : %s." #define ERRMSG_APPEND "failed to append ``%s'' in ``%s''." #define ERRMSG_CLOSE "failed to close %s ``%s'' : %s." #define ERRMSG_GET "failed to get" #define ERRMSG_INIT "failed to initialize" #define ERRMSG_MEM "out of memory." #define ERRMSG_OPEN "failed to open " _ERRMSG_FILE_ERRNO #define ERRMSG_OPEN_TMP "failed to open temporary file" \ _ERRMSG_FILE_ERRNO #define ERRMSG_PARSE "failed to parse ``%s''." #define ERRMSG_PROCESS "failed to process" #define ERRMSG_REMOVE "failed to remove " \ _ERRMSG_FILE_ERRNO #define ERRMSG_REMOVE_TMP "failed to remove temporary file" \ _ERRMSG_FILE_ERRNO #endif /* _ERRMSG_H_ */ pmk-0.10.4/hash_tools.h010064400017500000000000000035601006763341600135730ustar00mipswheel/* $Id: hash_tools.h 1063 2004-06-27 21:07:26Z mipsator $ */ /* * Copyright (c) 2004 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. * */ #ifndef _HASH_TOOLS_H_ #define _HASH_TOOLS_H_ #include "hash.h" char *parse_idtf(char *, char *, size_t); char *process_string(char *, htable *); bool single_append(htable *, char *, char *); #endif /* _HASH_TOOLS_H_ */ pmk-0.10.4/parse.c010064400017500000000000001262771051426245700125500ustar00mipswheel/* $Id: parse.c 1912 2006-10-14 22:31:11Z coudercd $ */ /* * Copyright (c) 2003-2006 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. * */ #include #include "compat/pmk_ctype.h" #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "common.h" #include "hash.h" #include "parse.h" #include "prseng.h" /*#define PRS_DEBUG 1*/ char parse_err[MAX_ERR_MSG_LEN]; /****************** * prsdata_init() * *********************************************************************** DESCR initialize parsing data structure IN NONE OUT prsdata structure ***********************************************************************/ prsdata *prsdata_init(void) { prsdata *pdata; pdata = (prsdata *) malloc(sizeof(prsdata)); if (pdata != NULL) { pdata->linenum = 0; pdata->tree = prsnode_init(); if (pdata->tree == NULL) { /* tree init failed, clean allocated structure */ prsdata_destroy(pdata); pdata = NULL; } } return(pdata); } /********************* * prsdata_destroy() * *********************************************************************** DESCR free space allocated by parsing data structure IN pdata: structure to clean OUT NONE ***********************************************************************/ void prsdata_destroy(prsdata *pdata) { #ifdef PRS_DEBUG debugf("prsdata_destroy() : cleaning tree"); #endif prsnode_destroy(pdata->tree); #ifdef PRS_DEBUG debugf("prsdata_destroy() : cleaning structure"); #endif free(pdata); #ifdef PRS_DEBUG debugf("prsdata_destroy() : exit"); #endif } /****************** * prsnode_init() * *********************************************************************** DESCR initialize parsing node structure IN NONE OUT parsing node structure ***********************************************************************/ prsnode *prsnode_init(void) { prsnode *pnode; pnode = (prsnode *) malloc(sizeof(prsnode)); if (pnode != NULL) { pnode->first = NULL; pnode->last = NULL; } return(pnode); } /***************** * prsnode_add() * *********************************************************************** DESCR add a cell to a node IN pnode: target node pcell: cell to add OUT NONE ***********************************************************************/ void prsnode_add(prsnode *pnode, prscell *pcell) { #ifdef PRS_DEBUG if (pnode == NULL) { debugf("prsnode_add() : pnode is NULL !"); } if (pcell == NULL) { debugf("prsnode_add() : pcell is NULL !"); } #endif if (pnode->last != NULL) { /* linking to last item of node */ pnode->last->next = pcell; } else { /* empty node, link as first */ pnode->first = pcell; } pnode->last = pcell; } /********************* * prsnode_destroy() * *********************************************************************** DESCR free space allocated by parsing node structure IN pnode: node structure to clean OUT NONE ***********************************************************************/ void prsnode_destroy(prsnode *pnode) { prscell *p, *n; if (pnode != NULL) { p = pnode->first; while (p != NULL) { n = p; p = n->next; prscell_destroy(n); } free(pnode); } } /****************** * prscell_init() * *********************************************************************** DESCR initialize parsing cell structure IN token: cell token type: cell type subtoken: cell subtoken OUT parsing cell structure or NULL if failed ***********************************************************************/ prscell *prscell_init(int token, int type, int subtoken) { bool rval = false; htable *pht; prscell *pcell; prsnode *pnode; prsopt *popt; pcell = (prscell *) malloc(sizeof(prscell)); if (pcell != NULL) { pcell->token = token; pcell->type = type; switch(type) { case PRS_KW_NODE : pnode = prsnode_init(); if (pnode != NULL) { pnode->token = subtoken; pcell->data = pnode; rval = true; } break; case PRS_KW_CELL : pht = hash_init_adv(MAX_CMD_OPT, (void *(*)(void *))po_dup, (void (*)(void *))po_free, (void *(*)(void *, void *, void *))po_append); if (pht != NULL) { pcell->data = pht; rval = true; } break; case PRS_KW_ITEM : popt = (prsopt *) malloc(sizeof(prsopt)); if (popt != NULL) { pcell->data = popt; rval = true; } break; default : break; } } if (rval == true) { pcell->next = NULL; } else { free(pcell); pcell = NULL; } return(pcell); } /********************* * prscell_destroy() * *********************************************************************** DESCR free space allocated for parsing cell structure IN pcell: structure to clean OUT NONE ***********************************************************************/ void prscell_destroy(prscell *pcell) { #ifdef PRS_DEBUG /*debugf("prscell_destroy().");*/ #endif if (pcell != NULL) { if (pcell->data != NULL) { switch(pcell->type) { case PRS_KW_NODE : prsnode_destroy(pcell->data); break; case PRS_KW_CELL : hash_destroy(pcell->data); break; default : break; } } free(pcell); } } /***************** * prsopt_init() * *********************************************************************** DESCR init a prsopt structure IN NONE OUT prsopt structure ***********************************************************************/ prsopt *prsopt_init(void) { prsopt *ppo; ppo = (prsopt *) malloc(sizeof(prsopt)); return(ppo); } /********************* * prsopt_init_adv() * *********************************************************************** DESCR init a prsopt structure with given aguments IN key: parse option key name opchar: operation character value: parse option value OUT prsopt structure ***********************************************************************/ prsopt *prsopt_init_adv(char *key, char opchar, char *value) { prsopt *ppo; ppo = (prsopt *) malloc(sizeof(prsopt)); if (ppo == NULL) { return(NULL); } if (strlcpy_b(ppo->key, key, sizeof(ppo->key)) == false) { free(ppo); return (NULL); /* truncated */ } ppo->opchar = opchar; if (value != NULL) { ppo->value = po_mk_str(value); if (ppo->value == NULL) { free(ppo); return(NULL); /* pmkobject failed */ } } else { /* permit value = NULL */ ppo->value = NULL; } return(ppo); } /******************** * prsopt_destroy() * *********************************************************************** DESCR destroy a prsopt structure IN ppo: prsopt structure to free OUT NONE ***********************************************************************/ void prsopt_destroy(prsopt *ppo) { if (ppo->value != NULL) { po_free(ppo->value); } free(ppo); } /****************** * keyword_hash() * *********************************************************************** DESCR create hash table with keyword structures IN kwtab: keyword table nbkw: size of table OUT hash table ***********************************************************************/ htable *keyword_hash(prskw kwtab[], int nbkw) { htable *phkw; int i; prskw *pkw; phkw = hash_init_adv(nbkw, (void *(*)(void *))strdup, free, NULL); if (phkw != NULL) { /* fill keywords hash */ for(i = 0 ; i < nbkw ; i++) { pkw = (prskw *) malloc(sizeof(prskw)); memmove(pkw, &kwtab[i], sizeof(prskw)); if (hash_update(phkw, kwtab[i].kw, /* no need to strdup */ pkw) == HASH_ADD_FAIL) { hash_destroy(phkw); errorf("failed to fill keywords hash table."); return(NULL); } } } return(phkw); } /******************** * prs_skip_blank() * *********************************************************************** DESCR skip blank character(s) IN ppe: parsing engine structure OUT new parsing cursor ***********************************************************************/ bool prs_skip_blank(prseng_t *ppe) { while (prseng_test_idtf_char(" \t", prseng_get_char(ppe)) == true) { if (prseng_next_char(ppe) == false) { return false; } } return true; } /********************** * prs_skip_comment() * *********************************************************************** DESCR skip a comment IN ppe: parsing engine structure OUT boolean ***********************************************************************/ bool prs_skip_comment(prseng_t *ppe) { bool loop = true; char c; /* check for end of line or end of file */ while (loop == true) { #ifdef PRS_DEBUG debugf("check if '%c' == CR.", prseng_get_char(ppe)); #endif c = prseng_get_char(ppe); /* reached end of line or buffer ? */ if ((c == CHAR_CR) || (c == CHAR_EOS)) { loop = false; } /* next char */ if (prseng_next_char(ppe) == false) { return false; } } return true; } /********************** * prs_skip_useless() * *********************************************************************** DESCR skip useless text (blanks, comments, empty lines) IN ppe: parsing engine structure OUT NONE ***********************************************************************/ bool prs_skip_useless(prseng_t *ppe) { bool loop = true; #ifdef PRS_DEBUG debugf("prs_skip_useless() : process start on line %d", ppe->linenum); #endif while (loop == true) { #ifdef PRS_DEBUG debugf("prs_skip_useless() : char = '%c'", prseng_get_char(ppe)); #endif switch(prseng_get_char(ppe)) { case ' ' : case '\t' : case '\n' : if (prseng_next_char(ppe) == false) { return false; } break; case PMK_CHAR_COMMENT : /* comment ? */ #ifdef PRS_DEBUG debugf("prs_skip_useless() : skip comment on line %d.", ppe->linenum); #endif prs_skip_comment(ppe); break; default: loop = false; } } #ifdef PRS_DEBUG debugf("prs_skip_useless() : process ended on line %d with char '%c'", ppe->linenum, prseng_get_char(ppe)); #endif return true; } /***************** * parse_label() * *********************************************************************** DESCR parse a label IN ppe: parsing engine structure pbuf: storage buffer size: size of buffer OUT new parsing cursor or NULL ***********************************************************************/ bool parse_label(prseng_t *ppe, char *pbuf, size_t size) { char c; c = prseng_get_char(ppe); if (c == '!') { *pbuf = c; pbuf++; size--; if (prseng_next_char(ppe) == false) { return false; } } return(prseng_get_idtf(ppe, pbuf, size, PRS_PMK_IDTF_STR)); } /**************** * parse_bool() * *********************************************************************** DESCR parse a bool value IN ppe: parsing engine structure po: storage pmk object size: size of buffer OUT new parsing cursor or NULL ***********************************************************************/ bool parse_bool(prseng_t *ppe, pmkobj *po, size_t size) { bool *pb; char *pbuf, buf[6]; pb = (bool *) malloc(sizeof (bool)); if (pb == NULL) { strlcpy(parse_err, PRS_ERR_ALLOC, sizeof(parse_err)); /* no check */ return false; } if (size > sizeof(buf)) size = sizeof(buf); pbuf = buf; /* get bool identifier */ if (prseng_get_idtf(ppe, buf, size, PRS_BOOL_IDTF_STR) == false) { strlcpy(parse_err, PRS_ERR_PRSENG, sizeof(parse_err)); /* no check */ return false; } /* is it true value ? */ if (strncmp(buf, PMK_BOOL_TRUE, sizeof(buf)) == 0) { *pb = true; } else { /* is it false value ? */ if (strncmp(buf, PMK_BOOL_FALSE, sizeof(buf)) == 0) { *pb = false; } else { /* unknown value identifier */ strlcpy(parse_err, "unknown boolean identifier.", sizeof(parse_err)); /* no check */ free(pb); return false; } } po->type = PO_BOOL; po->data = pb; return true; } /****************** * parse_quoted() * *********************************************************************** DESCR parse quoted string content IN ppe: parsing engine structure po: storage pmk object size: size of buffer OUT new parsing cursor ***********************************************************************/ bool parse_quoted(prseng_t *ppe, pmkobj *po, size_t size) { bool escape = false, loop = true; char *buffer, *pbuf, c; buffer = (char *) malloc(size); if (buffer == NULL) { return false; } pbuf = buffer; /* leave one char for end of line */ size--; /* skip starting double quote */ if (prseng_next_char(ppe) == false) { return false; } if (prseng_eof(ppe) == true) { free(buffer); strlcpy(parse_err, "ending quote is missing.", sizeof(parse_err)); /* no check */ return false; } /* unset escape flag */ escape = false; while (loop == true) { c = prseng_get_char(ppe); switch (c) { case CHAR_EOS : strlcpy(parse_err, "ending quote is missing.", sizeof(parse_err)); /* no check */ return false; case PMK_CHAR_ESCAPE : #ifdef PRS_DEBUG debugf("parse_quoted() : found escape char."); #endif if (escape == true) { /* double escape */ escape = false; #ifdef PRS_DEBUG debugf("parse_quoted() : escape = false."); #endif } else { /* found first escape, set flag */ escape = true; #ifdef PRS_DEBUG debugf("parse_quoted() : escape = true."); #endif } break; case PMK_CHAR_QUOTE_END : /* if not escaped ... */ if (escape == false) { /* ... found end quote */ loop = false; } else { escape = false; } break; default : escape = false; break; } /* if not escape or ending quote */ if ((escape == false) && (loop == true)) { /* copy character */ *pbuf = c; pbuf++; size--; /* check remaining space */ if (size < 0) { free(buffer); strlcpy(parse_err, PRS_ERR_OVERFLOW, sizeof(parse_err)); /* no check */ return false; } } if (prseng_next_char(ppe) == false) { free(buffer); return false; } } /* found end of quoted string */ *pbuf = CHAR_EOS; po->type = PO_STRING; /* use strdup() to get rid of the extra space that could result of the allocation with the max size of buffer */ po->data = strdup(buffer); /* deallocate the now useless buffer */ free(buffer); if (po->data == NULL) { /* strdup() failed */ errorf(ERRMSG_MEM); return false; } return true; } /**************** * parse_list() * *********************************************************************** DESCR parse a list IN ppe: parsing engine structure po: storage pmk object size: size of buffer OUT new parsing cursor ***********************************************************************/ bool parse_list(prseng_t *ppe, pmkobj *po, size_t size) { bool loop = true, prev_data = false; char *buffer, c; dynary *pda; pmkobj potmp; pda = da_init(); if (pda == NULL) { strlcpy(parse_err, PRS_ERR_ALLOC, sizeof(parse_err)); /* no check */ return false; } /* skip starting list char */ if (prseng_next_char(ppe) == false) { return false; } while (loop == true) { /* skip blank characters */ if (prs_skip_blank(ppe) == false) { return false; } c = prseng_get_char(ppe); switch (c) { case PMK_CHAR_LIST_END : #ifdef PRS_DEBUG debugf("found end of list."); #endif loop = false; break; case PMK_CHAR_QUOTE_START : /* check if data was right before */ if (prev_data == true) { /* yes => syntax error */ da_destroy(pda); strlcpy(parse_err, PRS_ERR_SYNTAX, sizeof(parse_err)); /* no check */ return false; } /* found string data */ if (parse_quoted(ppe, &potmp, size) == false) { da_destroy(pda); strlcpy(parse_err, PRS_ERR_SYNTAX, sizeof(parse_err)); /* no check */ return false; } #ifdef PRS_DEBUG debugf("add '%s' into dynary (quoted)", potmp.data); #endif if (da_push(pda, potmp.data) == false) { da_destroy(pda); return false; } /* set data flag */ prev_data = true; /* already at next character, continue */ continue; break; case PMK_CHAR_LIST_SEP : /* check if data was right before */ if (prev_data == false) { /* no => syntax error */ da_destroy(pda); strlcpy(parse_err, PRS_ERR_SYNTAX, sizeof(parse_err)); /* no check */ return false; } #ifdef PRS_DEBUG debugf("found separator."); #endif /* unset data flag */ prev_data = false; break; case CHAR_CR : /* ignore end of line */ #ifdef PRS_DEBUG debugf("found end of line."); #endif break; case CHAR_EOS : /* reached end of file */ da_destroy(pda); strlcpy(parse_err, "end of list not found.", sizeof(parse_err)); /* no check */ return false; break; default : /* check if data was right before */ if (prev_data == true) { /* yes => syntax error */ da_destroy(pda); strlcpy(parse_err, PRS_ERR_SYNTAX, sizeof(parse_err)); /* no check */ return false; } buffer = (char *) malloc(size); if (buffer == NULL) { strlcpy(parse_err, PRS_ERR_ALLOC, sizeof(parse_err)); /* no check */ return false; } if (prseng_get_idtf(ppe, buffer, size, PRS_PMK_IDTF_STR) == false) { da_destroy(pda); /* XXX better msg */ strlcpy(parse_err, PRS_ERR_OVERFLOW, sizeof(parse_err)); /* no check */ } /* XXX useless ? */ if (*buffer == CHAR_EOS) { da_destroy(pda); strlcpy(parse_err, PRS_ERR_SYNTAX, sizeof(parse_err)); /* no check */ return false; } #ifdef PRS_DEBUG debugf("add '%s' into dynary (simple).", buffer); #endif if (da_push(pda, buffer) == false) { da_destroy(pda); return false; } /* set data flag */ prev_data = true; break; } if (prseng_next_char(ppe) == false) { return false; } } /* check if data was right before */ if (prev_data == false) { /* no => syntax error */ da_destroy(pda); strlcpy(parse_err, PRS_ERR_SYNTAX, sizeof(parse_err)); /* no check */ #ifdef PRS_DEBUG debugf("no data before end of list."); #endif return(NULL); } /* found end of list */ po->type = PO_LIST; po->data = pda; return true; } /*************** * parse_key() * *********************************************************************** DESCR parse key IN ppe: parsing engine structure po: storage pmk object size: size of buffer OUT new parsing cursor or NULL ***********************************************************************/ bool parse_key(prseng_t *ppe, pmkobj *po, size_t size) { char *buffer; po->type = PO_NULL; #ifdef PRS_DEBUG debugf("parse_key() : cursor = '%.32s'", ppe->cur); #endif if (prseng_get_char(ppe) == PMK_CHAR_QUOTE_START) { #ifdef PRS_DEBUG debugf("parse_key() : found quoted string"); #endif /* found a quoted string */ if (parse_quoted(ppe, po, size) == false) { return false; } } else { #ifdef PRS_DEBUG debugf("parse_key() : found identifier"); #endif /* identifier */ buffer = (char *) malloc(size); if (buffer == NULL) { strlcpy(parse_err, PRS_ERR_ALLOC, sizeof(parse_err)); /* no check */ return false; } if (prseng_get_idtf(ppe, buffer, size, PRS_PMK_IDTF_STR) == false) { free(buffer); /* XXX better msg ? */ strlcpy(parse_err, PRS_ERR_OVERFLOW, sizeof(parse_err)); /* no check */ return false; } po->type = PO_STRING; po->data = buffer; } return true; } /**************** * parse_data() * *********************************************************************** DESCR parse data IN ppe: parsing engine structure po: storage pmk object size: size of buffer OUT boolean ***********************************************************************/ bool parse_data(prseng_t *ppe, pmkobj *po, size_t size) { po->type = PO_NULL; #ifdef PRS_DEBUG debugf("parse_data(): first character = '%c'", prseng_get_char(ppe)); #endif switch (prseng_get_char(ppe)) { /* found a quoted string */ case PMK_CHAR_QUOTE_START : #ifdef PRS_DEBUG debugf("parse_data(): calling parse_quoted()"); #endif if (parse_quoted(ppe, po, size) == false) { return false; } break; /* found a list */ case PMK_CHAR_LIST_START : #ifdef PRS_DEBUG debugf("parse_data(): calling parse_list()"); #endif if (parse_list(ppe, po, size) == false) { return false; } break; default : #ifdef PRS_DEBUG debugf("parse_data(): calling parse_bool()"); #endif if (parse_bool(ppe, po, size) == false) { return false; } break; } return true; } /********************** * parse_cmd_header() * *********************************************************************** DESCR parse command header IN ppe: parser engine structure pnode: parser node structure OUT parser cell structure on success or NULL ***********************************************************************/ prscell *parse_cmd_header(prseng_t *ppe, prsnode *pnode) { char name[CMD_LEN]; miscdata_t *pmd; prscell *pcell; prskw *pkw; if (prseng_get_idtf(ppe, name, sizeof(name), PRS_PMK_IDTF_STR) == false) { strlcpy(parse_err, "command parsing failed.", sizeof(parse_err)); /* no check */ return(NULL); } #ifdef PRS_DEBUG debugf("parse_cmd_header(): cmd name = '%s'", name); #endif /* get misc data */ pmd = (miscdata_t *) ppe->data; /* check validity of the command */ pkw = hash_get(pmd->phtkw, name); if (pkw != NULL) { /* command ok, creating cell */ pcell = prscell_init(pkw->token, pkw->type, pkw->subtoken); if (pcell == NULL) { strlcpy(parse_err, "pcell init failed.", sizeof(parse_err)); /* no check */ return(NULL); } #ifdef PRS_DEBUG debugf("parse_cmd_header(): cmd token = %d", pcell->token); debugf("parse_cmd_header(): cmd type = %d", pcell->type); #endif /* check if options have to be checked */ if (pkw->type == PRS_KW_CELL) { /* yes, keep pointer in prseng structure */ pmd->kwopts = pkw->kwo; if (pmd->kwopts != NULL) { /* assign number of required opts */ pmd->nbreq = pmd->kwopts->nbreq; } else { /* no required opts */ pmd->nbreq = 0; } } else { pmd->kwopts = NULL; pmd->nbreq = 0; } } else { /* unknown command */ snprintf(parse_err, sizeof(parse_err), "unknown command '%s'.", name); return(NULL); } /* look for a label */ if (prseng_test_char(ppe, PMK_CHAR_LABEL_START)) { /* label delimiter found */ if (prseng_next_char(ppe) == false) { return(NULL); } /* get label name */ if (parse_label(ppe, pcell->label, sizeof(pcell->label)) == false) { strlcpy(parse_err, "label parsing failed.", sizeof(parse_err)); /* no check */ prscell_destroy(pcell); return(NULL); } #ifdef PRS_DEBUG debugf("parse_cmd_header(): cmd label = '%s'", pcell->label); #endif /* check label's ending delimiter */ if (prseng_test_char(ppe, PMK_CHAR_LABEL_END) == false) { /* label name must be immediately followed by closing delimiter */ strlcpy(parse_err, "label parsing failed.", sizeof(parse_err)); /* no check */ prscell_destroy(pcell); return(NULL); } if (prseng_next_char(ppe) == false) { return(NULL); } #ifdef PRS_DEBUG debugf("parse_cmd_header(): parsed command '%s' with label '%s'", name, pcell->label); } else { debugf("parse_cmd_header(): parsed command '%s' with no label", name); #endif } /* look for command block starting sequence */ if (prseng_test_char(ppe, ' ') == false) { strlcpy(parse_err, PRS_ERR_UNKNOWN, sizeof(parse_err)); /* no check */ prscell_destroy(pcell); return(NULL); } if (prseng_next_char(ppe) == false) { return(NULL); } if (prseng_test_char(ppe, PMK_CHAR_COMMAND_START) == false) { strlcpy(parse_err, PRS_ERR_TRAILING, sizeof(parse_err)); /* no check */ prscell_destroy(pcell); return(NULL); } if (prseng_next_char(ppe) == false) { return(NULL); } if (prseng_test_char(ppe, CHAR_CR) == false) { strlcpy(parse_err, PRS_ERR_TRAILING, sizeof(parse_err)); /* no check */ prscell_destroy(pcell); return(NULL); } /* add cell in the node */ prsnode_add(pnode, pcell); return(pcell); } /*************** * parse_opt() * *********************************************************************** DESCR parse an option IN ppe: parsing engine structure popt: option storage structure seplst: string that contain all separator characters OUT boolean ***********************************************************************/ bool parse_opt(prseng_t *ppe, prsopt *popt, char *seplst) { char c; pmkobj po; #ifdef PRS_DEBUG debugf("parse_opt() : line = '%.32s'", ppe->cur); #endif if (parse_key(ppe, &po, sizeof(popt->key)) == false) { strlcpy(parse_err, PRS_ERR_SYNTAX, sizeof(parse_err)); /* no check */ return false; } if (strlcpy_b(popt->key, po.data, sizeof(popt->key)) == false) { free(po.data); return false; } free(po.data); #ifdef PRS_DEBUG debugf("parse_opt() : key = '%s'", popt->key); #endif if (prs_skip_blank(ppe) == false) { return false; } /* check if character is in separator list */ c = prseng_get_char(ppe); if (prseng_test_idtf_char(seplst, c) == false) { strlcpy(parse_err, PRS_ERR_SYNTAX, sizeof(parse_err)); /* no check */ return false; } else { popt->opchar = c; if (prseng_next_char(ppe) == false) { return false; } } #ifdef PRS_DEBUG debugf("parse_opt() : assign = '%c'", popt->opchar); #endif if (prs_skip_blank(ppe) == false) { return false; } popt->value = (pmkobj *) malloc(sizeof(pmkobj)); if (popt->value == NULL) { strlcpy(parse_err, PRS_ERR_ALLOC, sizeof(parse_err)); /* no check */ return false; } /* parse data */ if (parse_data(ppe, popt->value, OPT_VALUE_LEN) == false) { po_free(popt->value); /*strlcpy(parse_err, PRS_ERR_SYNTAX, */ /* sizeof(parse_err)); |+ no check +|*/ return false; } #ifdef PRS_DEBUG switch (popt->value->type) { case PO_BOOL : debugf("parse_opt() : value = *BOOL*"); break; case PO_STRING : debugf("parse_opt() : value = '%s'", popt->value->data); break; case PO_LIST : debugf("parse_opt() : value = (*LIST*)"); break; default : debugf("parse_opt() : value = !unknown type!"); break; } #endif return true; } /***************** * parse_clopt() * *********************************************************************** DESCR parse a command line option IN line: option line popt: storage structure seplst: string that contain all separator characters OUT boolean ***********************************************************************/ bool parse_clopt(char *line, prsopt *popt, char *seplst) { char c; pmkobj po; prseng_t *ppe; #ifdef PRS_DEBUG debugf("parse_clopt() : line = '%s'", line); #endif ppe = prseng_init_str(line, NULL); if (ppe == NULL) { strlcpy(parse_err, PRS_ERR_ALLOC, sizeof(parse_err)); /* no check */ return false; } if (parse_key(ppe, &po, sizeof(popt->key)) == false) { strlcpy(parse_err, PRS_ERR_SYNTAX, sizeof(parse_err)); /* no check */ return false; } else { if (strlcpy_b(popt->key, po.data, sizeof(popt->key)) == false) { free(po.data); return false; } free(po.data); } #ifdef PRS_DEBUG debugf("key = '%s'", popt->key); #endif /* check if character is in separator list */ c = prseng_get_char(ppe); if (prseng_test_idtf_char(seplst, c) == false) { strlcpy(parse_err, PRS_ERR_SYNTAX, sizeof(parse_err)); /* no check */ return false; } else { popt->opchar = c; if (prseng_next_char(ppe) == false) { return false; } } #ifdef PRS_DEBUG debugf("assign = '%c'", popt->opchar); #endif if (parse_data(ppe, &po, OPT_VALUE_LEN) == false) { strlcpy(parse_err, PRS_ERR_SYNTAX, sizeof(parse_err)); /* no check */ return false; } else { if (po.type != PO_STRING) { strlcpy(parse_err, PRS_ERR_SYNTAX, sizeof(parse_err)); /* no check */ return false; } else { #ifdef PRS_DEBUG debugf("value = '%s'", po.data); #endif popt->value = po_mk_str(po.data); free(po.data); } } return true; } /******************* * check_opt_avl() * *********************************************************************** DESCR check if the key is available in the given option array IN key: key to search opts: option array nbopts: number of options OUT return the pointer to the kw_t structure else NULL ***********************************************************************/ kw_t *check_opt_avl(char *key, kw_t *opts, size_t nbopts) { int i; for (i = 0 ; i < (int) nbopts ; i++) { if (strncmp(key, opts[i].name, MAX_HASH_VALUE_LEN) == 0) { return(&opts[i]); } } return(NULL); } /******************** * check_opt_type() * *********************************************************************** DESCR check if the option has a type allowed by the keyword mask IN pkw: keyword structure po: pmk object structure OUT boolean NOTE to disable type check set the mask to PO_NULL ***********************************************************************/ bool check_opt_type(kw_t *pkw, pmkobj *po) { if ((pkw->mask != PO_NULL) && ((pkw->mask & po->type) == 0)) { /* a type mask has been given but doesn't match with the option type */ return false; } /* the option type matches or the mask is set to PO_NULL */ return true; } /****************** * check_option() * *********************************************************************** DESCR check if the option name and type are valid IN pmd: misc data structure ppo: parse option structure OUT boolean ***********************************************************************/ bool check_option(miscdata_t *pmd, prsopt *ppo) { kw_t *pkw; kwopt_t *pkwo; pkwo = pmd->kwopts; if (pkwo == NULL) { /* nothing to check */ return true; } if (pkwo->req != NULL) { /* check given required options */ pkw = check_opt_avl(ppo->key, pkwo->req, pkwo->nbreq); if (pkw != NULL) { /* check option's type */ if (check_opt_type(pkw, ppo->value) == false) { /* wrong option type */ snprintf(parse_err, sizeof(parse_err), PRS_ERR_TYP_OPT, ppo->key); return false; } /* decrement required option counter */ pmd->nbreq--; return true; } if (pkwo->opt == NULL) { /* allow any optional variable names */ return true; } } if (pkwo->opt != NULL) { /* check given optional options */ pkw = check_opt_avl(ppo->key, pkwo->opt, pkwo->nbopt); if (pkw != NULL) { /* check option's type */ if (check_opt_type(pkw, ppo->value) == false) { /* wrong option type */ snprintf(parse_err, sizeof(parse_err), PRS_ERR_TYP_OPT, ppo->key); return false; } return true; } } /* provided option is not expected */ snprintf(parse_err, sizeof(parse_err), PRS_ERR_INV_OPT, ppo->key); return false; } /*********************** * process_block_opt() * *********************************************************************** DESCR process a block option IN ppe: parsing engine structure pnode: parsing node structure pcell: parent cell structure OUT boolean ***********************************************************************/ bool process_block_opt(prseng_t *ppe, prsnode *pnode, prscell *pcell) { prscell *ncell; prsopt *nopt, opt; #ifdef PRS_DEBUG debugf("process_block_opt() : calling parse_opt()"); #endif /* parse option */ if (parse_opt(ppe, &opt, PRS_PMKFILE_SEP) == false) { #ifdef PRS_DEBUG debugf("process_block_opt() : parse_opt() returned false"); #endif return false; } #ifdef PRS_DEBUG debugf("process_block_opt() : recording '%s' key", opt.key); #endif switch (pcell->type) { case PRS_KW_NODE : /* process a node */ /* init item's pcell */ ncell = prscell_init(pnode->token, PRS_KW_ITEM, PRS_TOK_NULL); if (ncell == NULL) { errorf("process_block_opt() : prscell init failed"); return false; } nopt = ncell->data; /* duplicate opt content in item */ strlcpy(nopt->key, opt.key, sizeof(opt.key)); /* XXX check */ nopt->value = opt.value; /* add item in cell node */ prsnode_add(pnode, ncell); break; case PRS_KW_CELL : /* process a command */ /* check keyword option (NULL handled) */ if (check_option(ppe->data, &opt) == false) { /* err msg done */ return false; } /* verify if option is allowed */ if (hash_get(pcell->data, opt.key) != NULL) { /* duplicate option */ strlcpy(parse_err, "duplicate option.", sizeof(parse_err)); /* XXX */ return false; } if (hash_update(pcell->data, opt.key, /* no need to strdup */ opt.value) == HASH_ADD_FAIL) { strlcpy(parse_err, PRS_ERR_HASH, sizeof(parse_err)); /* no check */ return false; } break; } return true; } /********************* * parse_opt_block() * *********************************************************************** DESCR parse a block of options IN pdata: parsing data structure ppe: parsing engine structure pcell: parent cell structure chk_delim: check delimiter switch OUT boolean ***********************************************************************/ bool parse_opt_block(prsdata *pdata, prseng_t *ppe, prscell *pcell, bool chk_delim) { bool loop = true; miscdata_t *pmd; prsnode *pnode; pnode = pcell->data; #ifdef PRS_DEBUG debugf("parse_opt_block() : pcell->type = %u.", pcell->type); debugf("parse_opt_block() : pnode->token = %u.", pnode->token); #endif if ((pcell->type == PRS_KW_NODE) && (pnode->token == PRS_TOK_NULL)) { #ifdef PRS_DEBUG debugf("parse_opt_block() : found a node, calling parse_cmd_block()."); #endif /* found a block node (like for example IF command) => parse the block */ return(parse_cmd_block(pdata, ppe, pnode, true)); } #ifdef PRS_DEBUG debugf("parse_opt_block() : parsing options."); #endif while (loop == true) { /* skip useless text */ if (prs_skip_useless(ppe) == false) { return false; } switch(prseng_get_char(ppe)) { case PMK_CHAR_COMMAND_END : #ifdef PRS_DEBUG debugf("parse_opt_block() : found end of block character."); #endif if (prseng_next_char(ppe) == false) { return false; } if (chk_delim == true) { /* delimiter found, exit from the loop */ loop = false; /* check if all required options have been parsed */ pmd = (miscdata_t *) ppe->data; if (pmd->nbreq != 0) { snprintf(parse_err, sizeof(parse_err), /* no check */ "at least one required option is missing (%d).", (int) pmd->nbreq); return false; } } else { /* delimiter not expected */ return false; } break; case CHAR_EOS : if (chk_delim == true) { /* expected delimiter not found */ return false; } else { /* main loop, no delimiter was expected => ok */ return true; } break; default : if (process_block_opt(ppe, pnode, pcell) == false) { /* error message already set */ return false; } break; } } return true; } /********************* * parse_cmd_block() * *********************************************************************** DESCR parse a block of commands IN pdata: parsing data structure ppe: parsing engine structure pnode: node structure chk_delim: check delimiter switch OUT boolean ***********************************************************************/ bool parse_cmd_block(prsdata *pdata, prseng_t *ppe, prsnode *pnode, bool chk_delim) { bool loop = true; prscell *pcell; /* start of block sequence does not exists or has already been parsed so don't look for it. */ while (loop == true) { /* skip useless text */ if (prs_skip_useless(ppe) == false) { return false; } #ifdef PRS_DEBUG debugf("parse_cmd_block() : checking character."); #endif switch(prseng_get_char(ppe)) { case PMK_CHAR_COMMAND_END : #ifdef PRS_DEBUG debugf("parse_cmd_block() : found end of command character."); #endif if (prseng_next_char(ppe) == false) { return false; } if (chk_delim == true) { /* delimiter found, exit from the loop */ loop = false; } else { /* delimiter not expected */ return false; } break; case CHAR_EOS : #ifdef PRS_DEBUG debugf("parse_cmd_block() : found end of string character."); #endif if (chk_delim == true) { /* expected delimiter not found */ return false; } else { /* main loop, no delimiter was expected => ok */ return true; } break; default : #ifdef PRS_DEBUG debugf("parse_cmd_block() : parsing command header."); #endif pcell = parse_cmd_header(ppe, pnode); if (pcell == NULL) { /* parsing failed, message done */ return false; } #ifdef PRS_DEBUG debugf("parse_cmd_block() : parsing command body."); #endif if (parse_opt_block(pdata, ppe, pcell, true) == false) { #ifdef PRS_DEBUG debugf("parse_cmd_block() : command boby parsing has fail."); #endif return false; } } } return true; } /******************* * parse_pmkfile() * *********************************************************************** DESCR parse pmkfile IN fp: file descriptor pdata: parsing data structure kwtab: keyword table size: size of keyword table OUT boolean ***********************************************************************/ bool parse_pmkfile(FILE *fp, prsdata *pdata, prskw kwtab[], size_t size) { bool rslt = true; miscdata_t md; prseng_t *ppe; ppe = prseng_init(fp, &md); if (ppe == NULL) { /* cannot init engine structure */ errorf("init of parsing engine structure failed."); return false; } /* init hash table of command keywords */ md.phtkw = keyword_hash(kwtab, size); if (md.phtkw == NULL) { /* message done */ rslt = false; } if ((rslt == true) && (parse_cmd_block(pdata, ppe, pdata->tree, false) == false)) { /* display error message */ errorf("line %d : %s", ppe->linenum, parse_err); rslt = false; } if ((rslt == true) && (feof(fp) == 0)){ /* error occured before EOF */ errorf("end of file not reached."); rslt = false; } hash_destroy(md.phtkw); prseng_destroy(ppe); return(rslt); } /***************** * process_opt() * *********************************************************************** DESCR process option line of configuration file IN pht: storage hash table popt: option structure to record OUT boolean ***********************************************************************/ bool process_opt(htable *pht, prsopt *popt) { if ((popt->opchar != CHAR_COMMENT) && (popt->opchar != CHAR_EOS)) { /* add options that are not comment neither blank lines */ if (hash_update_dup(pht, popt->key, po_get_str(popt->value)) == HASH_ADD_FAIL) { errorf("hash failure."); return false; } } return true; } /******************* * parse_pmkconf() * *********************************************************************** DESCR parse configuration file IN fp: file to parse pht: data used by processing function seplst: list of separators func: processing function OUT boolean ***********************************************************************/ bool parse_pmkconf(FILE *fp, htable *pht, char *seplst, bool (*func)(htable *, prsopt *)) { bool loop; char *pbuf, c, buf[MAX_LINE_LEN]; prseng_t *ppe; prsopt opt; size_t s; ppe = prseng_init(fp, NULL); if (ppe == NULL) { /* cannot init engine structure */ errorf("init of parsing engine structure failed."); return false; } while (prseng_eof(ppe) == false) { switch (prseng_get_char(ppe)) { case CHAR_COMMENT : /* comment */ strlcpy(opt.key, "comment", sizeof(opt.key)); /* no check */ opt.opchar = CHAR_COMMENT; /* check for end of line or end of file */ pbuf = buf; s = sizeof(buf); loop = true; while (loop == true) { #ifdef PRS_DEBUG debugf("check if '%c' == CR.", prseng_get_char(ppe)); #endif c = prseng_get_char(ppe); /* reached end of line or buffer ? */ if ((c == CHAR_CR) || (c == CHAR_EOS)) { loop = false; c = CHAR_EOS; } *pbuf = c; pbuf++; s--; /* check remaining space */ if (s < 0) { strlcpy(parse_err, PRS_ERR_OVERFLOW, sizeof(parse_err)); /* no check */ prseng_destroy(ppe); return false; } /* next char */ if (prseng_next_char(ppe) == false) { prseng_destroy(ppe); return false; } } #ifdef PRS_DEBUG debugf("parse_pmkconf() : found comment '%.32s'.", buf); #endif /* copy comment */ opt.value = po_mk_str(buf); #ifdef PRS_DEBUG debugf("parse_pmkconf() : cursor after comment '%.32s'.", ppe->cur); #endif /* process option */ if (func(pht, &opt) == false) { errorf("line %d : processing failed", ppe->linenum); return false; } break; case CHAR_CR : /* empty line */ strlcpy(opt.key, "", sizeof(opt.key)); /* no check */ opt.opchar = CHAR_EOS; opt.value = po_mk_str(""); #ifdef PRS_DEBUG debugf("parse_pmkconf() : found empty line."); #endif /* next char */ if (prseng_next_char(ppe) == false) { prseng_destroy(ppe); return false; } /* process option */ if (func(pht, &opt) == false) { errorf("line %d : processing failed", ppe->linenum); return false; } break; case CHAR_EOS : /* end of file reached */ loop = false; break; default : if (parse_opt(ppe, &opt, seplst) == true) { #ifdef PRS_DEBUG strlcpy(buf, po_get_str(opt.value), sizeof(buf)); /* no check */ debugf("parse_pmkconf(): opt line to parse = '%.32s'.", buf); #endif /* parse ok */ if (func(pht, &opt) == false) { errorf("line %d : processing failed", ppe->linenum); return false; } } else { #ifdef PRS_DEBUG debugf("parse_pmkconf(): incorrect line = '%.32s'.", ppe->cur); #endif /* incorrect line */ errorf("line %d : %s", ppe->linenum, parse_err); return false; } /* skip end of line */ if (prseng_test_char(ppe, CHAR_CR) == true) { /* next char */ if (prseng_next_char(ppe) == false) { prseng_destroy(ppe); return false; } } #ifdef PRS_DEBUG debugf("parse_pmkconf(): line after opt parse = '%.32s'.", ppe->cur); #endif break; } } if (prseng_eof(ppe) == false) { /* error occured before EOF */ errorf("line %d : %.32s", ppe->linenum, "end of file not reached."); return false; } return true; } /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/README010064400017500000000000000036031032174522300121260ustar00mipswheel----------------------------------------------------------------------- Pre Make Kit README file Document revision: $Id: README 1487 2005-10-08 13:33:07Z mipsator $ ----------------------------------------------------------------------- Introduction ------------ The Pre Make Kit project is a toolkit providing a collection of tools aimed to ease a lot of stages in project development. It provides a scanner that generate template source components such as configuration file or makefile. It also provides a dependency checker that sets up templates files depending on the system components (such as auto* tools or similar projects). For portability purpose, a BSD like install program is also part of the kit. The project aims the following goals : - opensource (BSD licensed) - portability (ISO C, POSIX, compatibility layer) - speed and memory lighweight (compiled C binaries) - security (replace scripts by data files, priviledge separation) - simplicity of use (generation tools, few basic instructions) - dependency low cost (only needs a POSIX shell and a C compiler) The provided tools are: - pmksetup: static data gathering tool - pmk: dependency checker - pmkscan: source scanner and build file generator - pmkinstall: BSD like install program - pmkpc: pkg-config compatible tool 1) Installation Steps --------------------- See the INSTALL file. 2) Testing ---------- We provide basic tests to have some pragmatic examples of how to use PMK. It is also a good method to test the whole kit. You're invited to look in the samples directory and check the README.sample file. 3) Supported Platforms ---------------------- Any POSIX compliant platform _should_be_ supported. We provide in the package a list of platform on which PMK has been compiled and tested (see STATUS file). You can also consult the BUGS file to see if your platform has specific problems that avoid PMK to run. pmk-0.10.4/pathtools.c010064400017500000000000000233561030204026600134300ustar00mipswheel/* $Id: pathtools.c 1462 2005-08-21 08:52:06Z mipsator $ */ /* * 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. * */ /******************************************************************* * * * Path manipulation tools * * * *******************************************************************/ #include #include #include #include "compat/pmk_stdbool.h" #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "pathtools.h" /************* * chkpath() * *********************************************************************** DESCR check a path and resolve "./", "../" and extra '/' characters IN path : path to check buffer : MAXPATHLEN sized buffer that will contain resolved path OUT returns bool if check is well done ***********************************************************************/ bool chkpath(char *path, char *buffer) { bool loop = true, dot = false, dotdot = false, sep = false; char *pbuf; int s = MAXPATHLEN; if (s < 2) { /* not enough space for at least "." */ /* XXX printf("not enough space\n"); */ return(false); } pbuf = buffer; while ((loop == true) && (s > 1)) { switch (*path) { case CHAR_DOT : /* unset separator flag */ sep = false; /* found a dot */ if (dot == false) { dot = true; } else { if (dotdot == false) { dotdot = true; } else { /* third dot found !!! */ /* printf("triple dot found\n"); */ return(false); } } break; case CHAR_EOS : /* exit from loop */ loop = false; /* but consider end of string as a separator before */ /* no break */ case CHAR_SEP : /* found separator */ if (dot == true) { /* if previous directory character sequence is not found then current directory character sequence is ignored */ if (dotdot == true) { /* if not at the begining of the buffer */ if (pbuf != buffer) { /* if not root look for previous directory */ if ((pbuf - buffer) > 1) { /* skip separator */ pbuf = pbuf - 2; s = s + 2; /* look for separator */ while ((*pbuf != CHAR_SEP) && (pbuf > buffer)) { pbuf--; s++; } /* if separator found go next char */ if (*pbuf == CHAR_SEP) { pbuf++; s--; } } } else { /* try to put dotdotsep */ if (s > 3) { *pbuf = CHAR_DOT; pbuf++; *pbuf = CHAR_DOT; pbuf++; *pbuf = CHAR_SEP; pbuf++; s = s - 3; } else { /* not enough space in buffer */ /* XXX printf("not enough space for dotdotsep\n"); */ return(false); } } /* unset dotdot flag */ dotdot = false; } /* unset dot flag */ dot = false; } else { if (sep == false) { /* previous was not a separator so copy it */ *pbuf = *path; pbuf++; s--; /* set flag */ sep = true; } } break; default : if (dot == true) { /* copy char in buffer */ *pbuf = CHAR_DOT; pbuf++; s--; /* XXX check */ if (dotdot == true) { /* copy char in buffer */ *pbuf = CHAR_DOT; pbuf++; s--; /* XXX check */ } } /* copy char in buffer */ *pbuf = *path; pbuf++; s--; /* unset flags */ sep = false; dot = false; dotdot = false; /* XXX let this happen ? ("..string" for example) */ } /* next character */ path++; } /* if end of string has not been reached */ if (loop == true) { /* XXX printf("s = %d, loop == true\n", s);*/ return(false); } switch(pbuf - buffer) { case 0 : *pbuf = CHAR_DOT; pbuf++; break; case 1 : /* don't try to skip trailing separator */ break; default : if (*(pbuf - 1) == CHAR_SEP) { /* skip trailing character */ pbuf--; } } /* NULL terminate string */ *pbuf = CHAR_EOS; return(true); } /************* * relpath() * *********************************************************************** DESCR provide a relative path IN from : source path to : destination path buffer : MAXPATHLEN sized buffer that will contain relative path OUT boolean ***********************************************************************/ bool relpath(char *from, char *to, char *buffer) { bool bexit = false; char from_buf[MAXPATHLEN], to_buf[MAXPATHLEN]; /* check 'from' path */ if (chkpath(from, from_buf) != true) { return(false); } from = from_buf; /* check 'to' path */ if (chkpath(to, to_buf) != true) { return(false); } to = to_buf; buffer[0] = CHAR_EOS; /* loop until common base is dropped */ while (bexit == false) { if ((*from == *to) && (*from != CHAR_EOS)) { from++; to++; } else { bexit = true; } } /* go back on the last '/' if needed */ if ((*from != CHAR_EOS) && (*to != CHAR_EOS)) { while (*from != CHAR_SEP) { from--; to--; } } /* ignore leading '/' for to */ if (*to == CHAR_SEP) { to++; } /* count directories */ while (*from != CHAR_EOS) { if (*from == CHAR_SEP) { /* one more */ if (strlcat_b(buffer, "../", MAXPATHLEN) == false) return(false); } from++; } /* appending remaining value of "to" */ if (strlcat_b(buffer, to, MAXPATHLEN) == false) return(false); if (buffer[0] == CHAR_EOS) { /* same path, return "." */ strlcpy(buffer, ".", MAXPATHLEN); /* should not fail */ } return(true); } /************* * abspath() * *********************************************************************** DESCR create a "valid" absolute path IN base : absolute base path rel : relative path from the base buffer : MAXPATHLEN buffer that will contain resulting absolute path OUT returns true on success ***********************************************************************/ bool abspath(char *base, char *rel, char *buffer) { char tmp_buf[MAXPATHLEN]; /* XXX should be greater ? */ /* check if 'rel' is not relative */ if (*rel == CHAR_SEP) { return(false); } strlcpy(tmp_buf, base, sizeof(tmp_buf)); /* no check */ strlcat(tmp_buf, "/", sizeof(tmp_buf)); /* no check */ if (strlcat_b(tmp_buf, rel, sizeof(tmp_buf)) == false) return(false); return(chkpath(tmp_buf, buffer)); } /************** * uabspath() * *********************************************************************** DESCR provide an absolute path from a path with unknown type. IN base : absolute base path upath : path with unknown type (relative or absolute) buffer : MAXPATHLEN sized buffer OUT boolean NOTE if upath is absolute then buffer is filled with upath else the buffer will contain the computed path. ***********************************************************************/ bool uabspath(char *base, char *upath, char *buffer) { if (*upath == CHAR_SEP) { /* upath is absolute */ return(chkpath(upath, buffer)); } else { /* upath is relative, we can call abspath */ return(abspath(base, upath, buffer)); } } /************** * makepath() * *********************************************************************** DESCR build path if it does not exists IN path : path to build mode : permissions used to create new directories OUT return : boolean ***********************************************************************/ bool makepath(char *path, mode_t mode) { bool bexit = false; char save, *pstr, *copy; struct stat sb; if (*path != CHAR_SEP) { /* path is not absolute */ return(false); } /* work on a copy */ copy = strdup(path); if (copy == NULL) return(false); pstr = copy; pstr++; /* skip leading separator */ while (bexit != true) { if ((*pstr == CHAR_SEP) || (*pstr == CHAR_EOS)) { /* separator found, replacing to make */ save = *pstr; *pstr = CHAR_EOS; /* check if the path already exists */ if (stat(copy, &sb) != 0) { if (mkdir(copy, mode) != 0) { free(copy); return(false); } } /* put separator back */ if (save == CHAR_EOS) { bexit = true; } else { *pstr = save; } } pstr++; } free(copy); return(true); } pmk-0.10.4/parse.h010064400017500000000000000154201051426245700125400ustar00mipswheel/* $Id: parse.h 1912 2006-10-14 22:31:11Z 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. * */ #ifndef _PMK_PARSE_H_ #define _PMK_PARSE_H_ #include "compat/pmk_stdbool.h" #include "pmk_obj.h" #include "premake.h" #include "prseng.h" #define KW_SIZEOF(s) sizeof(s) / sizeof(kw_t) /************* * constants * ***********************************************************************/ #define PMK_CHAR_COMMENT '#' #define PMK_CHAR_COMMAND '.' #define PMK_CHAR_COMMAND_START '{' #define PMK_CHAR_COMMAND_END '}' #define PMK_CHAR_LABEL_START '(' #define PMK_CHAR_LABEL_END ')' #define PMK_CHAR_QUOTE_START '"' #define PMK_CHAR_QUOTE_END PMK_CHAR_QUOTE_START #define PMK_CHAR_LIST_START '(' #define PMK_CHAR_LIST_END ')' #define PMK_CHAR_LIST_SEP ',' #define PMK_CHAR_ASSIGN '=' #define PMK_CHAR_ESCAPE '\\' #ifndef BOOL_STRING_TRUE #define PMK_BOOL_TRUE "TRUE" #else #define PMK_BOOL_TRUE BOOL_STRING_TRUE #endif #ifndef BOOL_STRING_FALSE #define PMK_BOOL_FALSE "FALSE" #else #define PMK_BOOL_FALSE BOOL_STRING_FALSE #endif #define PRS_PMKFILE_SEP "=" #define PRS_PMKCONF_SEP "=:" #define PRS_ERR_UNKNOWN "unknown error." #define PRS_ERR_ALLOC "memory allocation failed." #define PRS_ERR_HASH "hash add failure." #define PRS_ERR_DYNARY "dynary push failure." #define PRS_ERR_OVERFLOW "line too long." #define PRS_ERR_SYNTAX "syntax error." #define PRS_ERR_TRAILING "trailing garbage after value." #define PRS_ERR_PRSFILL "parsing buffer could not be filled." #define PRS_ERR_INV_OPT "invalid option '%s'." #define PRS_ERR_TYP_OPT "wrong type for option '%s'." #define PRS_ERR_PRSENG "parser engine error." #define PRS_PMK_IDTF_STR "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" #define PRS_BOOL_IDTF_STR "AEFLRSTU" /* letters of TRUE and FALSE */ /* keyword types */ #define PRS_KW_UNKW 0 #define PRS_KW_NODE 1 #define PRS_KW_CELL 2 #define PRS_KW_ITEM 3 /* null token */ #define PRS_TOK_NULL 0 /* maximal number of options per command */ #define MAX_CMD_OPT 32 /* parsing buffer size */ #define PRS_BUF_LEN 1024 /************************ * types and structures * ***********************************************************************/ typedef struct { char *name; potype mask; } kw_t; /* keyword options */ typedef struct { kw_t *req; size_t nbreq; kw_t *opt; size_t nbopt; } kwopt_t; /* keyword structure */ typedef struct { char *kw; /* keyword string */ int token, /* associated token */ type, /* type */ subtoken; /* node specific subtoken */ kwopt_t *kwo; /* keyword specific options */ } prskw; /* parser option structure */ typedef struct { char key[OPT_NAME_LEN], /* key name */ opchar; /* operator */ pmkobj *value; /* value */ } prsopt; /* parser cell structure */ typedef struct s_prscell { int token, /* item token id */ type; /* item type */ char label[LABEL_LEN]; /* command label */ void *data; /* misc data */ struct s_prscell *next; /* next item */ } prscell; /* parser node structure */ typedef struct { int token; /* node specific token */ prscell *first, /* first item of this node */ *last; /* last item of this node */ } prsnode; /* parser data structure */ typedef struct { int linenum; /* current line */ prsnode *tree; /* parser tree */ } prsdata; /* misc data structure */ typedef struct { void *data; /* misc_data */ htable *phtkw; /* command keywords */ kwopt_t *kwopts; /* pointer to keyword def */ size_t nbreq; /* number of required options */ } miscdata_t; /*********************** * function prototypes * ***********************************************************************/ prsdata *prsdata_init(void); void prsdata_destroy(prsdata *); prsnode *prsnode_init(void); void prsnode_add(prsnode *, prscell *); void prsnode_destroy(prsnode *); prscell *prscell_init(int, int, int); void prscell_destroy(prscell *); prsopt *prsopt_init(void); prsopt *prsopt_init_adv(char *, char, char *); void prsopt_destroy(prsopt *); htable *keyword_hash(prskw [], int); bool prs_skip_blank(prseng_t *); bool prs_skip_comment(prseng_t *); bool prs_skip_useless(prseng_t *); bool parse_label(prseng_t *, char *, size_t); bool parse_bool(prseng_t *, pmkobj *, size_t); bool parse_quoted(prseng_t *, pmkobj *, size_t); bool parse_list(prseng_t *, pmkobj *, size_t); bool parse_key(prseng_t *, pmkobj *, size_t); bool parse_data(prseng_t *, pmkobj *, size_t); prscell *parse_cell(char *, htable *); prscell *parse_cmd_header(prseng_t *, prsnode *pnode); bool parse_opt(prseng_t *, prsopt *, char *); bool parse_clopt(char *, prsopt *, char *); bool parse_node(prsdata *, prseng_t *, prscell *); bool parse_command(prsdata *, prseng_t *, prscell *); kw_t *check_opt_avl(char *, kw_t *, size_t); bool check_opt_type(kw_t *, pmkobj *); bool check_option(miscdata_t *, prsopt *); bool process_block_opt(prseng_t *, prsnode *, prscell *); bool parse_opt_block(prsdata *, prseng_t *, prscell *, bool); bool parse_cmd_block(prsdata *, prseng_t *, prsnode *, bool); bool parse_pmkfile(FILE *, prsdata *, prskw [], size_t); bool process_opt(htable *, prsopt *); bool parse_pmkconf(FILE *, htable *, char *, bool (*)(htable *, prsopt *)); #endif /* _PMK_PARSE_H_ */ /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/detect_cpu.c010064400017500000000000000570261036153341400135420ustar00mipswheel/* $Id: detect_cpu.c 1530 2006-01-12 20:07:40Z mipsator $ */ /* * Copyright (c) 2004-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. * */ #include /* include it first as if it was - this will avoid errors */ #include "compat/pmk_sys_types.h" #include #include #include "compat/pmk_string.h" #include "compat/pmk_stdio.h" #include "common.h" #include "detect_cpu.h" #include "detect_cpu_asm.h" /*************** * common code * ***********************************************************************/ /* config tools data file keyword */ prskw kw_pmkcpu[] = { {"LIST_ARCH_EQUIV", LIST_ARCH_EQUIV, PRS_KW_CELL, PRS_TOK_NULL, NULL}, {"LIST_X86_CPU_VENDOR", LIST_X86_CPU_VENDOR, PRS_KW_CELL, PRS_TOK_NULL, NULL}, {"LIST_X86_CPU_MODEL", LIST_X86_CPU_MODEL, PRS_KW_CELL, PRS_TOK_NULL, NULL}, {"LIST_X86_CPU_CLASS", LIST_X86_CPU_CLASS, PRS_KW_CELL, PRS_TOK_NULL, NULL}, {"LIST_ALPHA_CPU_CLASS", LIST_ALPHA_CPU_CLASS, PRS_KW_CELL, PRS_TOK_NULL, NULL}, {"LIST_IA64_CPU_CLASS", LIST_IA64_CPU_CLASS, PRS_KW_CELL, PRS_TOK_NULL, NULL} }; size_t nbkwc = sizeof(kw_pmkcpu) / sizeof(prskw); arch_cell arch_tab[] = { {"x86_32", PMK_ARCH_X86_32}, {"x86_64", PMK_ARCH_X86_64}, {"sparc32", PMK_ARCH_SPARC}, {"sparc64", PMK_ARCH_SPARC64}, {"ia_64", PMK_ARCH_IA_64}, {"ppc", PMK_ARCH_PPC}, {"alpha", PMK_ARCH_ALPHA}, {"m68k", PMK_ARCH_M68K}, {"parisc_64", PMK_ARCH_PARISC}, {"vax", PMK_ARCH_VAX} }; size_t nbarch = sizeof(arch_tab) / sizeof(arch_cell); /************** * seek_key() * *********************************************************************** DESCR seek parse data key IN pdata : parse data structure token : key token to find OUT key data or NULL ***********************************************************************/ void *seek_key(prsdata *pdata, int token) { prscell *pcell; pcell = pdata->tree->first; while (pcell != NULL) { if (pcell->token == token) { return(pcell->data); } pcell = pcell->next; } return(NULL); } /******************** * parse_cpu_data() * *********************************************************************** DESCR parse cpu data file IN fname : data file name OUT prsdata structure ***********************************************************************/ prsdata *parse_cpu_data(char *fname) { FILE *fp; bool rval; prsdata *pdata; /* initialize parsing structure */ pdata = prsdata_init(); if (pdata == NULL) { errorf("cannot intialize parsing data structure."); return(NULL); } fp = fopen(fname, "r"); if (fp == NULL) { prsdata_destroy(pdata); errorf("cannot open '%s' : %s.", fname, strerror(errno)); return(NULL); } /* parse data file and fill prsdata strucutre */ rval = parse_pmkfile(fp, pdata, kw_pmkcpu, nbkwc); fclose(fp); if (rval == false) { /* parsing failed, pdata is useless, cleaning */ prsdata_destroy(pdata); return(NULL); } return(pdata); } /******************** * check_cpu_arch() * *********************************************************************** DESCR check the cpu architecture IN uname_m : uname machine string OUT cpu architecture string ***********************************************************************/ char *check_cpu_arch(char *uname_m, prsdata *pdata) { char *pstr = NULL; htable *pht; void *ptmp; pht = (htable *) seek_key(pdata, LIST_ARCH_EQUIV); if (pht != NULL) { ptmp = hash_get(pht, uname_m); /* no check needed */ if (ptmp != NULL) pstr = po_get_str(ptmp); /* no check needed */ } if (pstr == NULL) pstr = PMK_ARCH_STR_UNKNOWN; return(strdup(pstr)); /* no check needed, NULL will be automatically returned */ } /********************* * arch_name_to_id() * *********************************************************************** DESCR convert arch name to id IN arch_name : architecture string OUT architecture identifier ***********************************************************************/ unsigned char arch_name_to_id(char *arch_name) { unsigned int i; unsigned char id = PMK_ARCH_UNKNOWN; for(i = 0 ; i < nbarch ; i++) { /* compare arch name with record key */ if (strncmp(arch_name, arch_tab[i].name, strlen(arch_name)) == 0) { /* they are same, get the id */ id = arch_tab[i].id; break; } } return(id); } /****************** * arch_wrapper() * *********************************************************************** DESCR architecture wrapper IN pdata : parsing data structure arch_name : architecture name OUT hash table with values or NULL ***********************************************************************/ htable *arch_wrapper(prsdata *pdata, char *arch_name) { htable *pht; unsigned char arch_id; #if defined(ARCH_X86_32) || defined(ARCH_X86_64) x86_cpu_cell *pcell; #endif /* ARCH_X86_32 || ARCH_X86_64 */ arch_id = arch_name_to_id(arch_name); pht = hash_init(ARCH_NB_MAX); if (pht == NULL) { printf("DEBUG pht init failed !\n"); return(NULL); } switch (arch_id) { case PMK_ARCH_X86_32 : case PMK_ARCH_X86_64 : #if defined(ARCH_X86_32) || defined(ARCH_X86_64) pcell = x86_cpu_cell_init(); if (pcell == NULL) return(NULL); if (x86_get_cpuid_data(pcell) == false) { errorf("unable to get x86 cpuid data."); return(NULL); } pcell->stdvendor = x86_get_std_cpu_vendor(pdata, pcell->vendor); if (x86_set_cpu_data(pdata, pcell, pht) == false) { errorf("failed to record cpu data."); return(NULL); } x86_cpu_cell_destroy(pcell); #else /* ARCH_X86_32 || ARCH_X86_64 */ errorf("architecture mismatch for '%s'.", arch_name); return(NULL); #endif /* ARCH_X86_32 || ARCH_X86_64 */ break; case PMK_ARCH_ALPHA : #if defined(ARCH_ALPHA) if (alpha_set_cpu_data(pdata, pht) == false) { errorf("failed to record cpu data."); return(NULL); } #else /* ARCH_ALPHA */ errorf("architecture mismatch for '%s'.", arch_name); return(NULL); #endif /* ARCH_ALPHA */ break; case PMK_ARCH_IA_64 : #if defined(ARCH_IA64) if (ia64_get_cpuid_data(pdata, pht) == false) { errorf("failed to record cpu data."); return(NULL); } #else /* ARCH_IA64 */ errorf("architecture mismatch for '%s'.", arch_name); return(NULL); #endif /* ARCH_IA64 */ break; } return(pht); } /**************** * x86 specific * ***********************************************************************/ #if defined(ARCH_X86_32) || defined(ARCH_X86_64) x86_cpu_feature x86_cpu_feat_reg1[] = { {X86_CPU_MASK_FEAT_FPU, "FPU"}, {X86_CPU_MASK_FEAT_VME, "VME"}, {X86_CPU_MASK_FEAT_DE, "DE"}, {X86_CPU_MASK_FEAT_PSE, "PSE"}, {X86_CPU_MASK_FEAT_TSC, "TSC"}, {X86_CPU_MASK_FEAT_MSR, "MSR"}, {X86_CPU_MASK_FEAT_PAE, "PAE"}, {X86_CPU_MASK_FEAT_MCE, "MCE"}, {X86_CPU_MASK_FEAT_CX8, "CX8"}, {X86_CPU_MASK_FEAT_APIC, "APIC"}, {X86_CPU_MASK_FEAT_SEP, "SEP"}, {X86_CPU_MASK_FEAT_MTRR, "MTRR"}, {X86_CPU_MASK_FEAT_PGE, "PGE"}, {X86_CPU_MASK_FEAT_MCA, "MCA"}, {X86_CPU_MASK_FEAT_CMOV, "CMOV"}, {X86_CPU_MASK_FEAT_PAT, "PAT"}, {X86_CPU_MASK_FEAT_PSE36, "PSE36"}, {X86_CPU_MASK_FEAT_PSN, "PSN"}, {X86_CPU_MASK_FEAT_CLFL, "CLFL"}, {X86_CPU_MASK_FEAT_DTES, "DTES"}, {X86_CPU_MASK_FEAT_ACPI, "ACPI"}, {X86_CPU_MASK_FEAT_MMX, "MMX"}, {X86_CPU_MASK_FEAT_FXR, "FXR"}, {X86_CPU_MASK_FEAT_SSE, "SSE"}, {X86_CPU_MASK_FEAT_SSE2, "SSE2"}, {X86_CPU_MASK_FEAT_SS, "SS"}, {X86_CPU_MASK_FEAT_HTT, "HTT"}, {X86_CPU_MASK_FEAT_TM1, "TM1"}, {X86_CPU_MASK_FEAT_IA64, "IA64"}, {X86_CPU_MASK_FEAT_PBE, "PBE"} }; size_t nb_feat_reg1 = sizeof(x86_cpu_feat_reg1) / sizeof(x86_cpu_feature); x86_cpu_feature x86_cpu_feat_reg2[] = { {X86_CPU_MASK_FEAT_FPU, "FPU"}, {X86_CPU_MASK_FEAT_MON, "MON"}, {X86_CPU_MASK_FEAT_DSCPL, "DSCPL"}, {X86_CPU_MASK_FEAT_EST, "EST"}, {X86_CPU_MASK_FEAT_TM2, "TM2"}, {X86_CPU_MASK_FEAT_CID, "CID"}, {X86_CPU_MASK_FEAT_CX16, "CX16"}, {X86_CPU_MASK_FEAT_ETPRD, "ETPRD"} }; size_t nb_feat_reg2 = sizeof(x86_cpu_feat_reg2) / sizeof(x86_cpu_feature); x86_cpu_feature x86_cpu_feat_extreg[] = { {X86_CPU_MASK_FEAT_LM, "LM"}, {X86_CPU_MASK_FEAT_EXT3DN, "EXT3DN"}, {X86_CPU_MASK_FEAT_3DNOW, "3DNOW"} }; size_t nb_feat_extreg = sizeof(x86_cpu_feat_extreg) / sizeof(x86_cpu_feature); /**** functions ****/ /*********************** * x86_cpu_cell_init() * *********************************************************************** DESCR initialise x86 cpu cell IN NONE OUT cpu cell or NULL ***********************************************************************/ x86_cpu_cell *x86_cpu_cell_init(void) { x86_cpu_cell *pcell; pcell = (x86_cpu_cell *) malloc(sizeof(x86_cpu_cell)); if (pcell == NULL) return(NULL); pcell->vendor = NULL; pcell->stdvendor = NULL; pcell->cpuname = NULL; pcell->features = NULL; pcell->family = 0; pcell->model = 0; pcell->extfam = 0; pcell->extmod = 0; return(pcell); } /************************** * x86_cpu_cell_destroy() * *********************************************************************** DESCR free x86 cpu cell structure IN pcell : structure to free OUT NONE ***********************************************************************/ void x86_cpu_cell_destroy(x86_cpu_cell *pcell) { if (pcell->vendor != NULL) free(pcell->vendor); if (pcell->stdvendor != NULL) free(pcell->stdvendor); if (pcell->cpuname != NULL) free(pcell->cpuname); free(pcell); } /**************************** * x86_get_std_cpu_vendor() * *********************************************************************** DESCR get (pmk) vendor identifier based on data from cpuid IN pdata : parsing structure OUT cpu vendor string ***********************************************************************/ char *x86_get_std_cpu_vendor(prsdata *pdata, char *civendor) { char *vendor = NULL; htable *pht; prscell *pcell; /* look for vendor list */ pcell = pdata->tree->first; while ((pcell != NULL) && (vendor == NULL)) { if (pcell->token == LIST_X86_CPU_VENDOR) { /* got list ! */ pht = pcell->data; /* look for standard vendor name */ vendor = po_get_str(hash_get(pht, civendor)); } pcell = pcell->next; } /* in case we don't find anything */ if (vendor == NULL) vendor = PMK_ARCH_STR_UNKNOWN; return(strdup(vendor)); /* no check needed, NULL will be automatically returned */ } /************************ * x86_get_cpuid_data() * *********************************************************************** DESCR gather x86 cpuid data IN cell : x86 cpu cell OUT boolean ***********************************************************************/ bool x86_get_cpuid_data(x86_cpu_cell *cell) { char feat_str[TMP_BUF_LEN] = ""; unsigned int i; uint32_t buffer[13], extlevel; if (x86_check_cpuid_flag() == 0) { /* no cpuid flag => 386 or old 486 */ cell->cpuid = false; cell->family = 3; /* fake family */ return(true); } cell->cpuid = true; /* get the cpuid vendor */ x86_exec_cpuid(0); cell->level = x86_cpu_reg_eax; buffer[0] = x86_cpu_reg_ebx; buffer[1] = x86_cpu_reg_edx; buffer[2] = x86_cpu_reg_ecx; buffer[3] = 0; /* terminate string */ cell->vendor = strdup((char *) buffer); if (cell->vendor == NULL) { return(false); } /* get the cpu type */ x86_exec_cpuid(1); cell->family = (unsigned int) ((x86_cpu_reg_eax & X86_CPU_MASK_FAMILY) >> 8); if (cell->family == 15) { /* extended family */ cell->extfam = (unsigned int) ((x86_cpu_reg_eax & X86_CPU_MASK_EXTFAM) >> 20); } cell->model = (unsigned int) ((x86_cpu_reg_eax & X86_CPU_MASK_MODEL) >> 4); /* processing feature register 1 */ for (i = 0 ; i < nb_feat_reg1 ; i++) { if ((x86_cpu_reg_edx & x86_cpu_feat_reg1[i].mask) != 0) { strlcat(feat_str, x86_cpu_feat_reg1[i].descr, sizeof(feat_str)); /* no check */ if (strlcat_b(feat_str, " ", sizeof(feat_str)) == false) { return(false); } } } /* processing feature register 2 */ for (i = 0 ; i < nb_feat_reg2 ; i++) { if ((x86_cpu_reg_edx & x86_cpu_feat_reg2[i].mask) != 0) { strlcat(feat_str, x86_cpu_feat_reg2[i].descr, sizeof(feat_str)); /* no check */ if (strlcat_b(feat_str, " ", sizeof(feat_str)) == false) { return(false); } } } /* check extended cpu level */ x86_exec_cpuid(0x80000000); extlevel = x86_cpu_reg_eax; if (extlevel >= 0x80000001) { /* get extended cpu features */ x86_exec_cpuid(0x80000001); /* processing extended feature register */ for (i = 0 ; i < nb_feat_extreg ; i++) { if ((x86_cpu_reg_edx & x86_cpu_feat_extreg[i].mask) != 0) { strlcat(feat_str, x86_cpu_feat_extreg[i].descr, sizeof(feat_str)); /* no check */ if (strlcat_b(feat_str, " ", sizeof(feat_str)) == false) { return(false); } } } } /* save feature string */ cell->features = strdup(feat_str); if (extlevel >= 0x80000002) { /* get the cpu name */ x86_exec_cpuid(0x80000002); buffer[0] = x86_cpu_reg_eax; buffer[1] = x86_cpu_reg_ebx; buffer[2] = x86_cpu_reg_ecx; buffer[3] = x86_cpu_reg_edx; x86_exec_cpuid(0x80000003); buffer[4] = x86_cpu_reg_eax; buffer[5] = x86_cpu_reg_ebx; buffer[6] = x86_cpu_reg_ecx; buffer[7] = x86_cpu_reg_edx; x86_exec_cpuid(0x80000004); buffer[8] = x86_cpu_reg_eax; buffer[9] = x86_cpu_reg_ebx; buffer[10] = x86_cpu_reg_ecx; buffer[11] = x86_cpu_reg_edx; buffer[12] = 0; /* terminate string */ cell->cpuname = strdup((char *) buffer); if (cell->cpuname == NULL) { return(false); } } else { cell->cpuname = NULL; } return(true); } /********************** * x86_set_cpu_data() * *********************************************************************** DESCR record cpu data in hash table IN pdata : parsing data pcell : x86 cpu data cell pht : storage hash table OUT boolean ***********************************************************************/ bool x86_set_cpu_data(prsdata *pdata, x86_cpu_cell *pcell, htable *pht) { char buffer[TMP_BUF_LEN], *pstr; htable *phtbis; if (snprintf_b(buffer, sizeof(buffer), "%u", pcell->family) == false) return(false); if (hash_update_dup(pht, PMKCONF_HW_X86_CPU_FAMILY, buffer) == HASH_ADD_FAIL) { return(false); } if (snprintf_b(buffer, sizeof(buffer), "%u", pcell->model) == false) return(false); if (hash_update_dup(pht, PMKCONF_HW_X86_CPU_MODEL, buffer) == HASH_ADD_FAIL) { return(false); } if (snprintf_b(buffer, sizeof(buffer), "%u", pcell->extfam) == false) return(false); if (hash_update_dup(pht, PMKCONF_HW_X86_CPU_EXTFAM, buffer) == HASH_ADD_FAIL) { return(false); } if (snprintf_b(buffer, sizeof(buffer), "%u", pcell->extmod) == false) return(false); if (hash_update_dup(pht, PMKCONF_HW_X86_CPU_EXTMOD, buffer) == HASH_ADD_FAIL) { return(false); } if (pcell->cpuname != NULL) { if (hash_update_dup(pht, PMKCONF_HW_X86_CPU_NAME, pcell->cpuname) == HASH_ADD_FAIL) { return(false); } } /* else put unknown ? */ if (pcell->vendor != NULL) { if (hash_update_dup(pht, PMKCONF_HW_X86_CPU_VENDOR, pcell->vendor) == HASH_ADD_FAIL) { return(false); } } /* else put unknown ? */ if (pcell->stdvendor != NULL) { if (hash_update_dup(pht, PMKCONF_HW_X86_CPU_STD_VENDOR, pcell->stdvendor) == HASH_ADD_FAIL) { return(false); } } /* else put unknown ? */ if (pcell->features != NULL) { if (hash_update_dup(pht, PMKCONF_HW_X86_CPU_FEATURES, pcell->features) == HASH_ADD_FAIL) { return(false); } } /* else put empty string ? */ phtbis = (htable *) seek_key(pdata, LIST_X86_CPU_CLASS); if (phtbis != NULL) { if (pcell->family < 15) { snprintf_b(buffer, sizeof(buffer), /* no check needed */ X86_CPU_CLASS_FAMILY_FMT, pcell->stdvendor, pcell->family); pstr = po_get_str(hash_get(phtbis, buffer)); /* no check needed */ } else { snprintf_b(buffer, sizeof(buffer), /* no check needed */ X86_CPU_CLASS_EXTFAM_FMT, pcell->stdvendor, pcell->extfam); pstr = po_get_str(hash_get(phtbis, buffer)); /* no check needed */ } if (pstr == NULL) { /* not found, get default */ pstr = po_get_str(hash_get(phtbis, "DEFAULT")); if (pstr == NULL) { errorf("failed to get default value for cpu family (%s).", buffer); return(false); } } if (hash_update_dup(pht, PMKCONF_HW_X86_CPU_CLASS, pstr) == HASH_ADD_FAIL) { return(false); } } else { errorf("failed to find '%s' key\n", LIST_X86_CPU_CLASS); return(false); } return(true); } #endif /* ARCH_X86_32 || ARCH_X86_64 */ /****************** * alpha specific * ***********************************************************************/ #if defined(ARCH_ALPHA) alpha_cpu_feature alpha_cpu_feat[] = { {ALPHA_CPU_MASK_FEAT_BWX, "BWX"}, {ALPHA_CPU_MASK_FEAT_FIX, "FIX"}, {ALPHA_CPU_MASK_FEAT_CIX, "CIX"}, {ALPHA_CPU_MASK_FEAT_MVI, "MVI"}, {ALPHA_CPU_MASK_FEAT_PAT, "PAT"}, {ALPHA_CPU_MASK_FEAT_PMI, "PMI"}, }; int nb_feat = sizeof(alpha_cpu_feat) / sizeof(alpha_cpu_feature); /************************ * alpha_set_cpu_data() * *********************************************************************** DESCR set alpha cpu data IN pdata: parsing data structure pht: data storage hash table OUT boolean ***********************************************************************/ bool alpha_set_cpu_data(prsdata *pdata, htable *pht) { char buffer[16], feat_str[TMP_BUF_LEN] = "", *pstr; htable *phtbis; unsigned int i; uint64_t implver, amask; /*debugf("alpha_set_cpu_data() : end");*/ phtbis = (htable *) seek_key(pdata, LIST_ALPHA_CPU_CLASS); if (phtbis != NULL) { /* get cpu class */ implver = alpha_exec_implver(); /*debugf("alpha_set_cpu_data() : implver = '%u'", implver);*/ if (snprintf_b(buffer, sizeof(buffer), ALPHA_CPU_CLASS_FMT, implver) == false) { return(false); } /*debugf("alpha_set_cpu_data() : buffer = '%s'", buffer);*/ pstr = po_get_str(hash_get(phtbis, buffer)); if (pstr == NULL) { pstr = ALPHA_CPU_UNKNOWN; } if (hash_update_dup(pht, PMKCONF_HW_ALPHA_CPU_CLASS, pstr) == HASH_ADD_FAIL) { return(false); } /* get cpu features */ amask = alpha_exec_amask(); /* processing feature mask */ for (i = 0 ; i < nb_feat ; i++) { if ((amask & alpha_cpu_feat[i].mask) != 0) { strlcat(feat_str, alpha_cpu_feat[i].descr, sizeof(feat_str)); /* no check */ if (strlcat_b(feat_str, " ", sizeof(feat_str)) == false) { return(false); } } } /* save feature string */ if (hash_update_dup(pht, PMKCONF_HW_ALPHA_CPU_FEATURES, feat_str) == HASH_ADD_FAIL) { return(false); } /*debugf("alpha_set_cpu_data() : amask = %x", amask);*/ } /*debugf("alpha_set_cpu_data() : end");*/ return(true); } #endif /* ARCH_ALPHA */ /***************** * ia64 specific * ***********************************************************************/ #if defined(ARCH_IA64) ia64_cpu_feature ia64_cpu_feat[] = { {IA64_CPU_MASK_FEAT_LB, "LB"}, {IA64_CPU_MASK_FEAT_SD, "SD"}, {IA64_CPU_MASK_FEAT_AO, "AO"} }; size_t nb_feat = sizeof(ia64_cpu_feat) / sizeof(ia64_cpu_feature); /**** functions ****/ /************************* * ia64_get_cpuid_data() * *********************************************************************** DESCR gather and save ia64 cpu data IN pdata: parsing data structure pht: storage hash table OUT boolean ***********************************************************************/ bool ia64_get_cpuid_data(prsdata *pdata, htable *pht) { char buffer[TMP_BUF_LEN], *pstr; htable *phtbis; uint64_t regbuf[3], level, rslt; unsigned int i; regbuf[0] = ia64_get_cpuid_register(0); regbuf[1] = ia64_get_cpuid_register(1); regbuf[2] = 0; if (hash_update_dup(pht, PMKCONF_HW_IA64_CPU_VENDOR, regbuf) == HASH_ADD_FAIL) return(false); /*debugf("cpuid register 0 = %x", regbuf[0]);*/ /*debugf("cpuid register 1 = %x", regbuf[1]);*/ /*debugf("vendor = '%s'", regbuf); */ regbuf[0] = ia64_get_cpuid_register(3); /*debugf("cpuid register 3 = %x", regbuf[0]);*/ level = regbuf[0] & IA64_CPU_MASK_LEVEL; /*debugf("level = %x", level);*/ rslt = (regbuf[0] & IA64_CPU_MASK_REVISION) >> 8; if (snprintf_b(buffer, sizeof(buffer), "%u", rslt) == false) return(false); if (hash_update_dup(pht, PMKCONF_HW_IA64_CPU_REVISION, buffer) == HASH_ADD_FAIL) return(false); /*debugf("revision = %x", rslt);*/ rslt = (regbuf[0] & IA64_CPU_MASK_MODEL) >> 16; if (snprintf_b(buffer, sizeof(buffer), "%u", rslt) == false) return(false); if (hash_update_dup(pht, PMKCONF_HW_IA64_CPU_MODEL, buffer) == HASH_ADD_FAIL) return(false); /*debugf("model = %x", rslt);*/ rslt = (regbuf[0] & IA64_CPU_MASK_FAMILY) >> 24; if (snprintf_b(buffer, sizeof(buffer), "%u", rslt) == false) return(false); if (hash_update_dup(pht, PMKCONF_HW_IA64_CPU_FAMILY, buffer) == HASH_ADD_FAIL) return(false); /*debugf("family = %x", rslt);*/ phtbis = (htable *) seek_key(pdata, LIST_IA64_CPU_CLASS); if (phtbis != NULL) { snprintf_b(buffer, sizeof(buffer), /* no check needed */ IA64_CPU_CLASS_FAMILY_FMT, rslt); /*debugf("buffer = '%s'", buffer);*/ pstr = po_get_str(hash_get(phtbis, buffer)); /* no check needed */ if (pstr == NULL) { /*debugf("getting default");*/ /* not found, get default */ pstr = po_get_str(hash_get(phtbis, "DEFAULT")); if (pstr == NULL) { errorf("failed to get default value for cpu class family."); return(false); } } /*debugf("pstr = '%s'", pstr);*/ if (hash_update_dup(pht, PMKCONF_HW_IA64_CPU_CLASS, pstr) == HASH_ADD_FAIL) { /* err msg ? */ return(false); } } else { errorf("failed to find '%s' key\n", LIST_IA64_CPU_CLASS); return(false); } rslt = (regbuf[0] & IA64_CPU_MASK_ARCHREV) >> 32; if (snprintf_b(buffer, sizeof(buffer), "%u", rslt) == false) return(false); if (hash_update_dup(pht, PMKCONF_HW_IA64_CPU_ARCHREV, buffer) == HASH_ADD_FAIL) return(false); /*printf("archrev = %x\n", rslt);*/ if (level >= 0x04) { /* getting feature register */ rslt = ia64_get_cpuid_register(4); /*printf("cpuid register 4 = %x\n", regbuf[0]);*/ /* processing feature mask */ buffer[0] = CHAR_EOS; for (i = 0 ; i < nb_feat ; i++) { if ((rslt & ia64_cpu_feat[i].mask) != 0) { strlcat(buffer, ia64_cpu_feat[i].descr, sizeof(buffer)); /* no check */ if (strlcat_b(buffer, " ", sizeof(buffer)) == false) return(false); /* err msg ? */ } } if (hash_update_dup(pht, PMKCONF_HW_IA64_CPU_FEATURES, buffer) == HASH_ADD_FAIL) /* err msg ? */ return(false); } return(true); } #endif /* ARCH_IA64 */ pmk-0.10.4/pmk_obj.c010064400017500000000000000167031037246313400130440ustar00mipswheel/* $Id: pmk_obj.c 1540 2006-02-08 21:45:00Z mipsator $ */ /* * 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. * */ #include #include "compat/pmk_stdio.h" #include "compat/pmk_string.h" #include "pmk_obj.h" /************* po_mk_bool() DESCR make a bool object IN value: boolean to objectify OUT object or NULL if failed ***********************************************************************/ pmkobj *po_mk_bool(bool value) { bool *pb; pmkobj *po; po = (pmkobj *) malloc(sizeof(pmkobj)); if (po != NULL) { po->type = PO_BOOL; pb = (bool *) malloc(sizeof(bool)); if (pb == NULL) { free(po); return(NULL); } *pb = value; po->data = pb; } return(po); } /************ po_mk_str() DESCR make string object IN str: string to objectify OUT object or NULL if failed ***********************************************************************/ pmkobj *po_mk_str(char *str) { pmkobj *p; p = (pmkobj *) malloc(sizeof(pmkobj)); if (p != NULL) { p->type = PO_STRING; p->data = strdup(str); } return(p); } /************* po_mk_list() DESCR make list object IN pda: dynary to objectify OUT object or NULL if failed ***********************************************************************/ pmkobj *po_mk_list(dynary *pda) { pmkobj *p; p = (pmkobj *) malloc(sizeof(pmkobj)); if (p != NULL) { p->type = PO_LIST; p->data = pda; /* XXX copy ? */ } return(p); } /************* po_mk_hash() DESCR make hash object IN pht: hash table to objectify OUT object or NULL if failed ***********************************************************************/ pmkobj *po_mk_hash(htable *pht) { pmkobj *p; p = (pmkobj *) malloc(sizeof(pmkobj)); if (p != NULL) { p->type = PO_HASH; p->data = pht; /* XXX copy ? */ } return(p); } /********* po_dup() DESCR duplicate object IN po: object to copy OUT duplicated object ***********************************************************************/ pmkobj *po_dup(pmkobj *po) { pmkobj *dup; dup = (pmkobj *) malloc(sizeof(pmkobj)); if (dup != NULL) { dup->type = po->type; switch (dup->type) { case PO_STRING : dup->data = strdup(po->data); break; default : free(dup); return(NULL); /* XXX TODO */ break; } } return(dup); } /************** po_get_type() DESCR get object type IN po: object OUT type of object ***********************************************************************/ potype po_get_type(pmkobj *po) { if (po != NULL) { return(po->type); } else { return(PO_NULL); } } /************** po_get_data() DESCR get object data IN po: object OUT generic data of object or NULL ***********************************************************************/ void *po_get_data(pmkobj *po) { if (po != NULL) { return(po->data); } else { return(NULL); } } /************** po_get_bool() DESCR get data from string object IN po: object OUT string or NULL ***********************************************************************/ bool po_get_bool(pmkobj *po) { if (po != NULL) { if (po->type == PO_BOOL) { return(*(bool *) po->data); } } return(false); } /************* po_get_str() DESCR get data from string object IN po: object OUT string or NULL ***********************************************************************/ char *po_get_str(pmkobj *po) { if (po != NULL) { if (po->type == PO_STRING) { return((char *) po->data); } } return(NULL); } /************** po_get_list() DESCR get data from list object IN po: object OUT dynary or NULL ***********************************************************************/ dynary *po_get_list(pmkobj *po) { if (po != NULL) { if (po->type == PO_LIST) { return((dynary *) po->data); } } return(NULL); } /********** po_free() DESCR free object IN po: object to deallocate OUT NONE ***********************************************************************/ void po_free(pmkobj *po) { if (po != NULL) { switch (po->type) { case PO_NULL : break; case PO_BOOL : free(po->data); break; case PO_STRING : free(po->data); break; case PO_LIST : da_destroy(po->data); break; case PO_HASH : hash_destroy(po->data); break; default : free(po->data); break; } free(po); } } /************ po_append() DESCR append a value in an object IN orig : original object value : data to append misc : misc specific data : - separator for a string object - unused for a list object OUT updated object or NULL if failed ***********************************************************************/ pmkobj *po_append(void *orig, void *value, void *misc) { char *pbuf; /* dynary *da; XXX TODO */ pmkobj *po_orig, *po_value, *po; size_t s; po_orig = (pmkobj *) orig; po_value = (pmkobj *) value; if (value == NULL) return(NULL); if (po_orig->type != po_value->type) return(NULL); po = (pmkobj *) malloc(sizeof(pmkobj)); if (po == NULL) { return(NULL); } switch (po_orig->type) { case PO_BOOL : /* not supported */ return(NULL); break; case PO_STRING : /* compute needed space */ if (misc != NULL) { s = strlen((char *) misc); } else { s = 0; } s = s + strlen(po_orig->data) + strlen(po_value->data) + 1; /* allocate space */ pbuf = (char *) malloc(s); if (strlcat_b(pbuf, po_orig->data, s) == false) { free(value); free(pbuf); return(NULL); } if ((misc != NULL) && (pbuf[0] != '\0')) { /* adding separator if provided and if string is not empty */ if (strlcat_b(pbuf, (char *) misc, s) == false) { free(value); free(pbuf); return(NULL); } } if (strlcat_b(pbuf, po_value->data, s) == false) { free(value); free(pbuf); return(NULL); } po = po_mk_str(pbuf); free(value); free(pbuf); break; case PO_LIST : /* XXX TODO */ return(NULL); break; default : return(NULL); break; } return(po); } pmk-0.10.4/common.c010064400017500000000000000376551047114646400127300ustar00mipswheel/* $Id: common.c 1555 2006-08-17 20:10:28Z mipsator $ */ /* * Copyright (c) 2003-2006 Damien Couderc * Copyright (c) 2003-2004 Xavier Santolaria * 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 : * - Ted Unangst */ #include #include #include #include #include #include #include "compat/pmk_string.h" #include "compat/pmk_stdio.h" #include "compat/pmk_unistd.h" #include "common.h" /*#define MKVAR_DEBUG 1*/ FILE *pmk_log_fp; /************** * get_line() * *********************************************************************** DESCR get a line from a file and remove newline character IN fd : file descriptor line : buffer that will contain the line lsize : size of the buffer OUT returns a boolean : - true when a line is available - false when error or eof occured ***********************************************************************/ bool get_line(FILE *fd, char *line, size_t lsize) { char *p; if (fgets(line, lsize, fd) != NULL) { p = line; while (*p != CHAR_EOS) { if (*p == '\n') { /* remove trailing newline */ *p= CHAR_EOS; } p++; } return(true); } else { /* reached eof or error */ return(false); } } /**************** * env_to_opt() * *********************************************************************** DESCR put env variable in an option IN env_name : variable name opt : option struct OUT returns true if env_name exists ***********************************************************************/ bool env_to_opt(char *env_name, pmkcmdopt *opt) { bool rval; char *env_val; env_val = getenv(env_name); if (env_val == NULL) { /* env variable name not found */ rval = false; } else { /* okay get it */ if (strlcpy_b(opt->value, env_val, sizeof(opt->value)) == false) { rval = true; } else { rval = false; } } return(rval); } /****************** * get_make_var() * *********************************************************************** DESCR get variable content from make IN varname: name of the variable like for example CC result: storage of result rsize: result size OUT boolean ***********************************************************************/ bool get_make_var(char *varname, char *result, size_t rsize) { FILE *mfp, *tfp; bool rval; char mfn[MAXPATHLEN], varstr[TMP_BUF_LEN]; if (strlcpy_b(mfn, TMP_MK_FILE, sizeof(mfn)) == false) { errorf("failed to create temporary file"); return(false); } mfp = tmps_open(TMP_MK_FILE, "w", mfn, sizeof(mfn), strlen(MK_FILE_EXT)); if (mfp != NULL) { /* create a tmp makefile with the following format : all: @printf ${VARNAME} /!\ should check content of VARNAME, could result in a security breach. */ fprintf(mfp, MKVAR_FMT_MK, varname, MKVAR_FILE); fclose(mfp); #ifdef MKVAR_DEBUG debugf(MKVAR_FMT_MK, varname, MKVAR_FILE); #endif } else { #ifdef MKVAR_DEBUG errorf("failed to open '%s' : %s.", mfn, strerror(errno)); #endif return(false); } if (snprintf_b(varstr, sizeof(varstr), MKVAR_FMT_CMD, mfn) == false) return(false); if (system(varstr) == 0) { tfp = fopen(MKVAR_FILE, "r"); if (tfp != NULL) { /* catch output of make */ if (get_line(tfp, result, rsize) == false) { #ifdef MKVAR_DEBUG errorf("failed to get result from '%s' : %s.", varstr, strerror(errno)); #endif rval = false; } fclose(tfp); rval = true; } else { #ifdef MKVAR_DEBUG errorf("failed to open '%s' : %s.", varstr, strerror(errno)); #endif rval = false; } } else { #ifdef MKVAR_DEBUG errorf("failed to execute '%s' : %s.", varstr, strerror(errno)); #endif rval = false; } if (unlink(mfn) == -1) { /* cannot remove temporary file */ errorf("cannot remove temporary file: '%s' : %s.", mfn, strerror(errno)); } if (unlink(MKVAR_FILE) == -1) { /* cannot remove temporary file */ #ifdef MKVAR_DEBUG errorf("cannot remove temporary file: '%s' : %s.", mfn, strerror(errno)); #endif } return(rval); } /****************** * str_to_ulong() * *********************************************************************** DESCR convert a string into an unsigned long IN XXX OUT XXX ***********************************************************************/ bool str_to_ulong(char *str, int base, unsigned long *value) { char *ep; *value = strtoul(str, &ep, base); if (*str == '\0' || *ep != '\0') { return(false); /* not a number */ } if ((errno == ERANGE) && (*value == ULONG_MAX)) { return(false); /* out of range */ } return(true); } /******************* * str_to_dynary() * *********************************************************************** DESCR split a string into a dynamic array (one separator) IN str : string to split sep : separator OUT dynary or NULL NOTE move to dynary.c ? ***********************************************************************/ dynary *str_to_dynary(char *str, char sep) { static char buf[2]; snprintf(buf, sizeof(buf), "%c", sep); /* should not overflow */ return(str_to_dynary_adv(str, buf)); } /*********************** * str_to_dynary_adv() * *********************************************************************** DESCR split a string into a dynamic array (list of separators) IN str : string to split sep : separators list OUT dynary or NULL NOTE move to dynary.c ? ***********************************************************************/ dynary *str_to_dynary_adv(char *str, char *seplst) { char buf[MAXPATHLEN], *pbuf; dynary *da; int s; if (str == NULL) { /* protect against NULL */ return(NULL); } /* init dynary */ da = da_init(); if (da == NULL) { return(NULL); } s = sizeof(buf); pbuf = buf; while (*str != CHAR_EOS) { /* check if character is in separator list */ if (strchr(seplst, *str) != NULL) { *pbuf = CHAR_EOS; if (da_push(da, strdup(buf)) == false) { da_destroy(da); return(NULL); } pbuf = buf; s = sizeof(buf); } else { *pbuf = *str; pbuf++; s--; if (s == 0) { /* not enough space in buffer */ da_destroy(da); return(NULL); } } str++; } *pbuf = CHAR_EOS; if (da_push(da, strdup(buf)) == false) { da_destroy(da); return(NULL); } return(da); } /******************* * find_file_dir() * *********************************************************************** DESCR find if one dir contain a given file in the specified list of path IN da : path list fname : file to search fpath : storage of the directory fplen : size of the storage OUT boolean ***********************************************************************/ bool find_file_dir(dynary *da, char *fname, char *fpath, size_t fplen) { char tstr[MAXPATHLEN], *path; unsigned int i; for (i = 0 ; i < da_usize(da) ; i++) { path = da_idx(da, i); strlcpy(tstr, path, sizeof(tstr)); /* no check */ strlcat(tstr, "/", sizeof(tstr)); /* no check */ if (strlcat_b(tstr, fname, sizeof(tstr)) == true) { if (access(tstr, F_OK) == 0) { /* no race condition here */ if (strlcpy_b(fpath, path, fplen) == true) { /* fpath correctly set */ return(true); } else { errorf("strlcpy failed in find_file_dir()."); return(false); } } } } /* not found */ return(false); } /*************** * find_file() * *********************************************************************** DESCR find a file in the specified list of path IN da : path list fname : file to search fpath : storage of the full path fplen : size of the storage OUT boolean ***********************************************************************/ bool find_file(dynary *da, char *fname, char *fpath, size_t fplen) { bool rval = false; if (find_file_dir(da, fname, fpath, fplen) == true) { strlcat(fpath, "/", fplen); /* no check */ if (strlcat_b(fpath, fname, fplen) == true) { /* fpath set correctly */ rval = true; } } return(rval); } /******************* * get_file_path() * *********************************************************************** DESCR get path of given filename in given path list IN filename : name of the file to look for path : string of the list of path storage : storage for resulting path size : size of storage OUT returns true if filename is found in one of the list's path ***********************************************************************/ bool get_file_path(char *filename, char *path, char *storage, size_t size) { bool rval = false; dynary *bplst; /* fill dynary with path */ bplst= str_to_dynary(path, PATH_STR_DELIMITER); if (bplst == NULL) { errorf("failed to put a path into a dynamic array."); return(false); } /* try to locate binary */ if (find_file(bplst, filename, storage, size) == true) { rval = true; } else { rval = false; } da_destroy(bplst); return(rval); } /************ * errorf() * *********************************************************************** DESCR formated simple error IN fmt : format string followed by arguments OUT NONE ***********************************************************************/ void errorf(const char *fmt, ...) { char buf[TMP_BUF_LEN]; va_list plst; va_start(plst, fmt); vsnprintf(buf, sizeof(buf), fmt, plst); va_end(plst); fprintf(stderr, "Error : %s\n", buf); } /***************** * errorf_line() * *********************************************************************** DESCR formated parse error IN filename : parsed file name line : line of error fmt : format string followed by arguments OUT NONE ***********************************************************************/ void errorf_line(char *filename, int line, const char *fmt, ...) { char buf[TMP_BUF_LEN]; va_list plst; va_start(plst, fmt); vsnprintf(buf, sizeof(buf), fmt, plst); va_end(plst); fprintf(stderr, "Error in '%s' line %d : %s\n", filename, line, buf); } /************ * debugf() * *********************************************************************** DESCR formated debug message IN fmt : format string followed by arguments OUT NONE ***********************************************************************/ void debugf(const char *fmt, ...) { char buf[TMP_BUF_LEN]; va_list plst; va_start(plst, fmt); vsnprintf(buf, sizeof(buf), fmt, plst); va_end(plst); fprintf(stdout, "!DEBUG! %s\n", buf); fflush(stdout); } /****************** * pmk_log_open() * *********************************************************************** DESCR open log file IN logname : log file name OUT returns true if opened ***********************************************************************/ bool pmk_log_open(char *logname) { if (pmk_log_fp != NULL) { errorf("'%s' is already open.", logname); return(false); } pmk_log_fp = fopen(logname, "w"); if (pmk_log_fp == NULL) { errorf("while opening '%s'.", logname); return(false); } else { return(true); } } /******************* * pmk_log_close() * *********************************************************************** DESCR close log file IN NONE OUT NONE ***********************************************************************/ void pmk_log_close(void) { fflush(pmk_log_fp); fclose(pmk_log_fp); } /************* * pmk_log() * *********************************************************************** DESCR log formatted line IN fmt : format string OUT boolean ***********************************************************************/ bool pmk_log(const char *fmt, ...) { char buf[TMP_BUF_LEN]; va_list plst; va_start(plst, fmt); vsnprintf(buf, sizeof(buf), fmt, plst); va_end(plst); if (pmk_log_fp != NULL) { fprintf(pmk_log_fp, buf); fflush(pmk_log_fp); fprintf(stdout, buf); fflush(stdout); return(true); } else { errorf("unable to log."); return(false); } } /*********** * fcopy() * *********************************************************************** DESCR copy file IN src : file to copy dst : destination file mode : destination perms OUT boolean ***********************************************************************/ bool fcopy(char *src, char *dst, mode_t mode) { char cbuf[S_BLKSIZE]; bool do_loop = true, rval = true; int src_fd, dst_fd; ssize_t rsz; /* try to open both source and destination files */ src_fd = open(src, O_RDONLY, 0); if (src_fd == -1) { errorf("cannot open '%s' : %s.", src, strerror(errno)); return(false); } /*debugf("mode = %o", mode);*/ dst_fd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, mode); if (dst_fd == -1) { close(src_fd); errorf("cannot open '%s' : %s.", dst, strerror(errno)); return(false); } while (do_loop == true) { /* reading data */ rsz = read(src_fd, cbuf, sizeof(cbuf)); switch(rsz) { case -1: /* read error */ errorf("failed to read '%s' : %s.", src, strerror(errno)); do_loop = false; rval = false; break; case 0: /* no more data to copy */ do_loop = false; break; default: /* data read, trying to write */ if (write(dst_fd, cbuf, rsz) != rsz) { /* write failed */ errorf("failed to write '%s' : %s.", dst, strerror(errno)); do_loop = false; rval = false; } break; } } close(src_fd); close(dst_fd); return(rval); } /************** * tmp_open() * *********************************************************************** DESCR open temporary file IN tfile : template file name mode : file mode buf : buffer for the randomized file name bsize : buffer size OUT file structure or NULL ***********************************************************************/ FILE *tmp_open(char *tfile, char *mode, char *buf, size_t bsize) { int fd; /* copy file name in buf */ if (strlcpy_b(buf, tfile, bsize) == false) return(NULL); /* randomize file name */ fd = mkstemp(buf); if (fd == -1) { return(NULL); } return(fdopen(fd, mode)); } /************** * tmps_open() * *********************************************************************** DESCR open temporary file with suffix IN tfile : template file name mode : file mode buf : buffer for the randomized file name bsize : buffer size slen : suffix length OUT file structure or NULL ***********************************************************************/ FILE *tmps_open(char *tfile, char *mode, char *buf, size_t bsize, size_t slen) { int fd; /* copy file name in buf */ if (strlcpy_b(buf, tfile, bsize) == false) return(NULL); /* randomize file name */ fd = mkstemps(buf, slen); if (fd == -1) { return(NULL); } return(fdopen(fd, mode)); } pmk-0.10.4/lang.h010075500017500000000000000117321051672735000123540ustar00mipswheel/* $Id: lang.h 1916 2006-10-22 17:48:24Z coudercd $ */ /* * Copyright (c) 2006 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. * */ #ifndef _PMK_LANG_H_ #define _PMK_LANG_H_ #include #include "premake.h" /************* * constants * **********************************************************************************************/ /************************* * define language tokens * ********************************************************************************************** * %CONST LANG_UNKNOWN: unknown language token * %CONST LANG_C: C language token * %CONST LANG_CXX: C++ language token * %CONST LANG_NUMBER: number of supported languages **********************************************************************************************/ enum { LANG_UNKNOWN = -1, /* unknown language */ LANG_C, /* C language */ LANG_CXX, /* C++ language */ LANG_NUMBER /* number of languages */ }; /* language labels */ #define LANG_LABEL_C "C" /* C language */ #define LANG_LABEL_CXX "C++" /* C++ language */ /* compiler labels */ #define COMP_LABEL_C "CC" /* C language */ #define COMP_LABEL_CXX "CXX" /* C++ language */ /* compiler flags labels */ #define CFLAGS_LABEL_C "CFLAGS" /* C language */ #define CFLAGS_LABEL_CXX "CXXFLAGS" /* C++ language */ /* linker flags labels */ #define LDFLAGS_LABEL_C "CLDFLAGS" /* C language */ #define LDFLAGS_LABEL_CXX "CXXLDFLAGS" /* C++ language */ /* shared lib compiler flags labels */ #define SLCFLAGS_LABEL_C "SLCFLAGS" /* C language */ #define SLCFLAGS_LABEL_CXX "SLCXXFLAGS" /* C++ language */ /* shared lib linker flags labels */ #define SLLDFLAGS_LABEL_C "SLCLDFLAGS" /* C language */ #define SLLDFLAGS_LABEL_CXX "SLCXXLDFLAGS" /* C++ language */ /* shared libs build targets */ #define MK_BLD_TARGET_C "c_shared_libs" #define MK_BLD_TARGET_CXX "cxx_shared_libs" /* shared libs clean targets */ #define MK_CLN_TARGET_C "c_shared_libs_clean" #define MK_CLN_TARGET_CXX "cxx_shared_libs_clean" /* shared libs install targets */ #define MK_INST_TARGET_C "c_shared_libs_install" #define MK_INST_TARGET_CXX "cxx_shared_libs_install" /* shared libs deinstall targets */ #define MK_DEINST_TARGET_C "c_shared_libs_deinstall" #define MK_DEINST_TARGET_CXX "cxx_shared_libs_deinstall" #define LANG_NAME_LEN 64 #define COMP_NAME_LEN 64 #define PRE_NAME_LEN 64 #define CFLG_NAME_LEN 64 #define SHFLG_NAME_LEN 64 #define MK_RULE_LEN 64 /********************************** * type and structure definitions * ***********************************************************************/ /* language cell */ typedef struct { char name[LANG_NAME_LEN], /* language label (ex. C) */ compiler[COMP_NAME_LEN], /* compiler label (ex. CC) */ cflags[CFLG_NAME_LEN], /* compiler flags label (ex. CFLAGS) */ ldflags[CFLG_NAME_LEN], /* linker flags label (ex. CLDFLAGS) */ slcflags[CFLG_NAME_LEN], /* shared lib compiler flags label (ex. SLCFLAGS) */ slldflags[CFLG_NAME_LEN], /* shared lib linker flags label (ex. SLCLDFLAGS) */ mk_bld_rule[MK_RULE_LEN], /* */ mk_cln_rule[MK_RULE_LEN], /* */ mk_inst_rule[MK_RULE_LEN], /* */ mk_deinst_rule[MK_RULE_LEN]; /* */ int lang; /* language token */ } lgdata_t; /******************** * global variables * **********************************************************************************************/ extern lgdata_t lang_data[]; extern size_t nb_lang_data; #endif /* _PMK_LANG_H_ */ /* vim: set noexpandtab tabstop=4 softtabstop=4 shiftwidth=4: */ pmk-0.10.4/TODO010064400017500000000000000052411060573177700117540ustar00mipswheel----------------------------------------------------------------------- Pre Make Kit TODO file Document revision: $Id: TODO 1964 2007-04-07 15:08:47Z coudercd $ ----------------------------------------------------------------------- Format: Who Status Description Status flags: - to do + done ~ in progress ! high priority . low priority R release goal S snapshot goal Indented lines means subtask. ----------------------------------------------------------------------- common: ----------------------------------------------------------------------- ~R! update tutorial ~ improve test_pmkinstall to check more modes => moved to testsuite ~! new samples => move to testsuite - add a sample that show architecture data from pmk +R! improve tag generation and substitution. ~R regroup common labels at the same place pmk: ----------------------------------------------------------------------- -R? check if ~/.pmk.conf is available ~. compatibility with autoconf (progressing) : ~ support for DEFS (-D options to pass to the compiler) - support for LDFLAGS (misc linker options) ? - support for CPPFLAGS (misc linker options) ? - VPATH ? -. verify in CHECK_BINARY that program has executable right ? pmksetup: ----------------------------------------------------------------------- ~. cpu identification - ppc support (priviledged) - sparc support - sparc64 support (priviledged) ~ man page update - cpu optimisation for compiler - option to append to variable of pmk.conf pmkscan ----------------------------------------------------------------------- +R add support for advanced tags in pmkscan and pmk -R update scanfile.5 (ADVTAG) ~R! add more entries in pmkscan.dat ~R move hard coded strings of pmkscan.c into macros ~R reorganize macros of pmkscan.h .R replace EXTRAMKF by EXTRA_MACROS and EXTRA_RULES - EXTRA_MACROS is the file containing macros to add to makefile - EXTRA_RULES is the file containing rules to add to makefile pmkinstall ----------------------------------------------------------------------- pmkpc ----------------------------------------------------------------------- -. missing options - PMKPC_OPT_UNINST - PMKPC_OPT_DEBUG - PMKPC_OPT_VAR - PMKPC_OPT_VAR_DEF - PMKPC_OPT_VAR_PRNT - PMKPC_OPT_VAR_SILC - PMKPC_OPT_VAR_STDO ~. man page -. special expression ('' quoted), post 0.8 misc ----------------------------------------------------------------------- ~R! convert samples directory into a seperated testsuite recursive tasks ----------------------------------------------------------------------- ~R track and code missing checks for snprintf and strl* ~R update README and INSTALL pmk-0.10.4/Makefile.pmk010064400017500000000000000321531062626154600135070ustar00mipswheel# Makefile template built by pmkscan (2006-10-11 20:09) # @configure_input@ # build tools AS= @AS@ ASFLAGS= CPP= @CPP@ CC= @CC@ CFLAGS= @CFLAGS@ \ $(WARN) $(DBGFLAGS) \ -DDATADIR=\"$(DATADIR)\" \ -DPRIVSEP_USER=\"$(PRIVSEP_USER)\" \ -DSYSCONFDIR=\"$(SYSCONFDIR)\" \ -DCONFDIR=\"$(CONFDIR)\" CLDFLAGS= @CLDFLAGS@ @LIBS@ INSTALL= @INSTALL@ RM= rm RMFLAGS= -rf # tool aliases INSTALL_BIN= $(INSTALL) -m 755 INSTALL_SBIN= $(INSTALL) -m 755 INSTALL_STLIB= $(INSTALL) -m 644 INSTALL_SHLIB= $(INSTALL) -m 755 INSTALL_DATA= $(INSTALL) -m 644 INSTALL_DIR= $(INSTALL) -d -m 755 INSTALL_MAN= $(INSTALL) -m 644 # specific directories PREFIX= @PREFIX@ BINDIR= @BINDIR@ SBINDIR= @SBINDIR@ DATADIR= @DATADIR@ MANDIR= @MANDIR@ MAN1DIR= @MAN1DIR@ MAN5DIR= @MAN5DIR@ MAN8DIR= @MAN8DIR@ SYSCONFDIR= @SYSCONFDIR@ # packaging PACKAGE= @PACKAGE@ # extra tags CONFDIR= @CONFDIR@ PRIVSEP_USER= @PRIVSEP_USER@ # # list of generated files # GEN_FILES= Makefile compat/config.h # # source dependency lists # AUTOCONF_SRCS= autoconf.c autoconf.h cfgtool.h common.h compat/config.h \ compat/pmk_ctype.h compat/pmk_libgen.h \ compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h compat/pmk_sys_types.h \ compat/pmk_unistd.h detect.h dynarray.h errmsg.h \ functool.h hash.h hash_tools.h parse.h pathtools.h pmk.h \ pmk_obj.h premake.h prseng.h tags.h CFGTOOL_SRCS= cfgtool.c cfgtool.h common.h compat/config.h \ compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h dynarray.h errmsg.h hash.h parse.h \ pmk_obj.h premake.h prseng.h CODEBUILD_SRCS= codebuild.c codebuild.h common.h compat/config.h \ compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h dynarray.h errmsg.h hash.h lang.h \ pmk_obj.h premake.h COMMON_SRCS= common.c common.h compat/config.h compat/pmk_stdbool.h \ compat/pmk_stdio.h compat/pmk_string.h \ compat/pmk_unistd.h dynarray.h errmsg.h hash.h pmk_obj.h \ premake.h COMPAT_SRCS= compat.c compat.h compat/config.h compat/pmk_ctype.h \ compat/pmk_libgen.h compat/pmk_stdbool.h \ compat/pmk_stdio.h compat/pmk_string.h \ compat/pmk_sys_types.h compat/pmk_unistd.h DETECT_SRCS= common.h compat/config.h compat/pmk_stdbool.h \ compat/pmk_stdio.h compat/pmk_string.h \ compat/pmk_unistd.h detect.c detect.h dynarray.h \ errmsg.h hash.h lang.h parse.h pmk_obj.h premake.h \ prseng.h DETECT_CPU_SRCS= common.h compat/config.h compat/pmk_stdbool.h \ compat/pmk_stdio.h compat/pmk_string.h \ compat/pmk_sys_types.h cpu_arch_def.h \ detect_cpu.c detect_cpu.h detect_cpu_asm.h \ dynarray.h errmsg.h hash.h parse.h pmk_obj.h \ premake.h prseng.h DETECT_CPU_ASM_SRCS= cpu_arch_def.h detect_cpu_asm.s DYNARRAY_SRCS= compat/config.h compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h dynarray.c dynarray.h FUNC_SRCS= autoconf.h cfgtool.h codebuild.h common.h compat/config.h \ compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h compat/pmk_unistd.h detect.h \ dynarray.h errmsg.h func.c func.h functool.h hash.h \ hash_tools.h lang.h parse.h pkgconfig.h pmk.h pmk_obj.h \ premake.h prseng.h tags.h FUNCTOOL_SRCS= cfgtool.h common.h compat/config.h compat/pmk_ctype.h \ compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h compat/pmk_unistd.h detect.h \ dynarray.h errmsg.h functool.c functool.h hash.h \ hash_tools.h parse.h pmk.h pmk_obj.h premake.h prseng.h \ tags.h HASH_SRCS= common.h compat/config.h compat/pmk_stdbool.h \ compat/pmk_stdio.h compat/pmk_string.h dynarray.h \ errmsg.h hash.c hash.h pmk_obj.h premake.h HASH_TOOLS_SRCS= compat/config.h compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h dynarray.h errmsg.h hash.h \ hash_tools.c hash_tools.h pmk_obj.h premake.h LANG_SRCS= compat/config.h compat/pmk_stdbool.h dynarray.h errmsg.h \ hash.h lang.c lang.h pmk_obj.h premake.h PARSE_SRCS= common.h compat/config.h compat/pmk_ctype.h \ compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h dynarray.h errmsg.h hash.h parse.c \ parse.h pmk_obj.h premake.h prseng.h PARSE_LANG_SRCS= common.h compat/config.h compat/pmk_stdbool.h \ compat/pmk_stdio.h compat/pmk_string.h \ dynarray.h errmsg.h hash.h parse_lang.c \ parse_lang.h pmk_obj.h premake.h prseng.h PATHTOOLS_SRCS= compat/config.h compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h pathtools.c pathtools.h PKGCONFIG_SRCS= common.h compat/config.h compat/pmk_ctype.h \ compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h compat/pmk_sys_types.h dynarray.h \ errmsg.h hash.h hash_tools.h parse.h pkgconfig.c \ pkgconfig.h pmk_obj.h premake.h prseng.h PMK_SRCS= autoconf.h cfgtool.h common.h compat/config.h \ compat/pmk_ctype.h compat/pmk_libgen.h \ compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h compat/pmk_sys_types.h \ compat/pmk_unistd.h detect.h dynarray.h errmsg.h func.h \ hash.h hash_tools.h lang.h parse.h pathtools.h pmk.c \ pmk.h pmk_obj.h premake.h prseng.h tags.h PMK_OBJ_SRCS= compat/config.h compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h dynarray.h hash.h pmk_obj.c \ pmk_obj.h PMKINSTALL_SRCS= common.h compat/config.h compat/pmk_ctype.h \ compat/pmk_libgen.h compat/pmk_stdbool.h \ compat/pmk_stdio.h compat/pmk_string.h \ compat/pmk_sys_types.h compat/pmk_unistd.h \ dynarray.h errmsg.h hash.h pathtools.h pmk_obj.h \ pmkinstall.c pmkinstall.h premake.h PMKPC_SRCS= cfgtool.h common.h compat/config.h compat/pmk_stdbool.h \ compat/pmk_stdio.h compat/pmk_string.h dynarray.h \ errmsg.h hash.h hash_tools.h parse.h pkgconfig.h \ pmk_obj.h pmkpc.c pmkpc.h premake.h prseng.h PMKSCAN_SRCS= common.h compat/config.h compat/pmk_ctype.h \ compat/pmk_libgen.h compat/pmk_stdbool.h \ compat/pmk_stdio.h compat/pmk_string.h \ compat/pmk_sys_types.h compat/pmk_unistd.h dynarray.h \ errmsg.h hash.h hash_tools.h lang.h parse.h parse_lang.h \ pathtools.h pmk_obj.h pmkscan.c pmkscan.h premake.h \ prseng.h tags.h PMKSETUP_SRCS= common.h compat/config.h compat/pmk_stdbool.h \ compat/pmk_stdio.h compat/pmk_string.h \ compat/pmk_sys_types.h compat/pmk_unistd.h \ cpu_arch_def.h detect_cpu.h dynarray.h errmsg.h hash.h \ parse.h pmk_obj.h pmksetup.c pmksetup.h premake.h \ prseng.h PRSENG_SRCS= compat/config.h compat/pmk_stdbool.h compat/pmk_stdio.h \ compat/pmk_string.h prseng.c prseng.h TAGS_SRCS= compat/config.h compat/pmk_ctype.h compat/pmk_stdbool.h \ compat/pmk_stdio.h compat/pmk_string.h tags.c tags.h # # binary name macros # PMK= pmk PMKINSTALL= pmkinstall PMKPC= pmkpc PMKSCAN= pmkscan PMKSETUP= pmksetup # # binary target dependency lists # PMK_OBJS= autoconf.o cfgtool.o codebuild.o common.o compat.o detect.o \ dynarray.o func.o functool.o hash.o hash_tools.o lang.o parse.o \ pathtools.o pkgconfig.o pmk.o pmk_obj.o prseng.o tags.o PMKINSTALL_OBJS= common.o compat.o dynarray.o hash.o pathtools.o \ pmk_obj.o pmkinstall.o PMKPC_OBJS= cfgtool.o common.o compat.o dynarray.o hash.o hash_tools.o \ parse.o pkgconfig.o pmk_obj.o pmkpc.o prseng.o PMKSCAN_OBJS= common.o compat.o dynarray.o hash.o hash_tools.o parse.o \ parse_lang.o pathtools.o pmk_obj.o pmkscan.o prseng.o \ tags.o PMKSETUP_OBJS= common.o compat.o detect_cpu.o detect_cpu_asm.o \ dynarray.o hash.o parse.o pmk_obj.o pmksetup.o prseng.o # # target lists # # building BUILD_TARGETS= $(ALL_BIN_TARGETS) ALL_BIN_TARGETS= $(PMKINSTALL) $(PMK) $(PMKPC) $(PMKSCAN) $(PMKSETUP) # cleaning CLEAN_TARGETS= $(BIN_CLEAN_TARGETS) BIN_CLEAN_TARGETS= $(PMK)_clean $(PMKINSTALL)_clean $(PMKPC)_clean \ $(PMKSCAN)_clean $(PMKSETUP)_clean # installing INSTALL_TARGETS= install_bin install_man install_data BIN_INSTALL_TARGETS= $(PMKINSTALL)_install $(PMK)_install $(PMKPC)_install \ $(PMKSCAN)_install $(PMKSETUP)_install # deinstalling DEINSTALL_TARGETS= $(BIN_DEINSTALL_TARGETS) deinstall_man deinstall_data BIN_DEINSTALL_TARGETS= $(PMK)_deinstall $(PMKINSTALL)_deinstall \ $(PMKPC)_deinstall $(PMKSCAN)_deinstall \ $(PMKSETUP)_deinstall MAN1_FILES= man/pmk.1 man/pmkinstall.1 man/pmkpc.1 man/pmkscan.1 MAN5_FILES= man/pmk.conf.5 man/pmkfile.5 man/pmksyntax.5 man/scanfile.5 MAN8_FILES= man/pmksetup.8 DATA_FILES= data/pmkcfgtool.dat data/pmkcomp.dat data/pmkcpu.dat \ data/pmkscan.dat # by default we consider all binaries as non privileged BIN_FILES= $(ALL_BIN_TARGETS) # move privileged binaries here if needed SBIN_FILES= .SUFFIXES: .o .s .c .C .cc .cxx .cpp # assembly suffix # we use CPP to be more portable .s.o: $(CPP) $< | sed '/^#/d' > tmp_asm.s $(AS) $(ASFLAGS) -o $@ tmp_asm.s $(RM) $(RMFLAGS) tmp_asm.s # C suffixes .c.o: $(CC) $(CFLAGS) $(SLCFLAGS) -o $@ -c $< # # generic targets # all: $(BUILD_TARGETS) clean: $(CLEAN_TARGETS) install: $(INSTALL_TARGETS) deinstall: $(DEINSTALL_TARGETS) # install manual pages install_man: $(INSTALL_DIR) $(DESTDIR)$(MANDIR) # man1 $(INSTALL_DIR) $(DESTDIR)$(MAN1DIR) $(INSTALL_DATA) man/pmk.1 $(DESTDIR)$(MAN1DIR)/pmk.1 $(INSTALL_DATA) man/pmkinstall.1 $(DESTDIR)$(MAN1DIR)/pmkinstall.1 $(INSTALL_DATA) man/pmkpc.1 $(DESTDIR)$(MAN1DIR)/pmkpc.1 $(INSTALL_DATA) man/pmkscan.1 $(DESTDIR)$(MAN1DIR)/pmkscan.1 # man5 $(INSTALL_DIR) $(DESTDIR)$(MAN5DIR) $(INSTALL_DATA) man/pmk.conf.5 $(DESTDIR)$(MAN5DIR)/pmk.conf.5 $(INSTALL_DATA) man/pmkfile.5 $(DESTDIR)$(MAN5DIR)/pmkfile.5 $(INSTALL_DATA) man/pmksyntax.5 $(DESTDIR)$(MAN5DIR)/pmksyntax.5 $(INSTALL_DATA) man/scanfile.5 $(DESTDIR)$(MAN5DIR)/scanfile.5 # man8 $(INSTALL_DIR) $(DESTDIR)$(MAN8DIR) $(INSTALL_DATA) man/pmksetup.8 $(DESTDIR)$(MAN8DIR)/pmksetup.8 # deinstall manual pages deinstall_man: # man1 $(RM) $(RMFLAGS) $(DESTDIR)$(MAN1DIR)/pmk.1 $(RM) $(RMFLAGS) $(DESTDIR)$(MAN1DIR)/pmkinstall.1 $(RM) $(RMFLAGS) $(DESTDIR)$(MAN1DIR)/pmkpc.1 $(RM) $(RMFLAGS) $(DESTDIR)$(MAN1DIR)/pmkscan.1 # man5 $(RM) $(RMFLAGS) $(DESTDIR)$(MAN5DIR)/pmk.conf.5 $(RM) $(RMFLAGS) $(DESTDIR)$(MAN5DIR)/pmkfile.5 $(RM) $(RMFLAGS) $(DESTDIR)$(MAN5DIR)/pmksyntax.5 $(RM) $(RMFLAGS) $(DESTDIR)$(MAN5DIR)/scanfile.5 # man8 $(RM) $(RMFLAGS) $(DESTDIR)$(MAN8DIR)/pmksetup.8 # install data files install_data: $(DATA_FILES) $(INSTALL_DIR) $(DESTDIR)$(DATADIR) $(INSTALL_DATA) data/pmkcfgtool.dat $(DESTDIR)$(DATADIR)/pmkcfgtool.dat $(INSTALL_DATA) data/pmkcomp.dat $(DESTDIR)$(DATADIR)/pmkcomp.dat $(INSTALL_DATA) data/pmkcpu.dat $(DESTDIR)$(DATADIR)/pmkcpu.dat $(INSTALL_DATA) data/pmkscan.dat $(DESTDIR)$(DATADIR)/pmkscan.dat # deinstall data files deinstall_data: $(RM) $(RMFLAGS) $(DESTDIR)$(DATADIR)/pmkcfgtool.dat $(RM) $(RMFLAGS) $(DESTDIR)$(DATADIR)/pmkcomp.dat $(RM) $(RMFLAGS) $(DESTDIR)$(DATADIR)/pmkcpu.dat $(RM) $(RMFLAGS) $(DESTDIR)$(DATADIR)/pmkscan.dat distclean: clean $(RM) $(RMFLAGS) $(GEN_FILES) # # object rules # autoconf.o: $(AUTOCONF_SRCS) cfgtool.o: $(CFGTOOL_SRCS) codebuild.o: $(CODEBUILD_SRCS) common.o: $(COMMON_SRCS) compat.o: $(COMPAT_SRCS) detect.o: $(DETECT_SRCS) detect_cpu.o: $(DETECT_CPU_SRCS) detect_cpu_asm.o: $(DETECT_CPU_ASM_SRCS) dynarray.o: $(DYNARRAY_SRCS) func.o: $(FUNC_SRCS) functool.o: $(FUNCTOOL_SRCS) hash.o: $(HASH_SRCS) hash_tools.o: $(HASH_TOOLS_SRCS) lang.o: $(LANG_SRCS) parse.o: $(PARSE_SRCS) parse_lang.o: $(PARSE_LANG_SRCS) pathtools.o: $(PATHTOOLS_SRCS) pkgconfig.o: $(PKGCONFIG_SRCS) pmk.o: $(PMK_SRCS) pmk_obj.o: $(PMK_OBJ_SRCS) pmkinstall.o: $(PMKINSTALL_SRCS) pmkpc.o: $(PMKPC_SRCS) pmkscan.o: $(PMKSCAN_SRCS) pmksetup.o: $(PMKSETUP_SRCS) prseng.o: $(PRSENG_SRCS) tags.o: $(TAGS_SRCS) # # binary target rules # # main binary install target install_bin: install_bindir $(BIN_INSTALL_TARGETS) # install binary directory install_bindir: $(INSTALL_DIR) $(DESTDIR)$(BINDIR) # pmk binary targets $(PMK): $(PMK_OBJS) $(CC) $(CLDFLAGS) -o $@ $(PMK_OBJS) $(PMK)_clean: $(RM) $(RMFLAGS) $(PMK_OBJS) $(RM) $(RMFLAGS) $(PMK) $(PMK)_install: $(PMK) $(INSTALL_BIN) $(PMK) $(DESTDIR)$(BINDIR)/$(PMK) $(PMK)_deinstall: $(RM) $(RMFLAGS) $(DESTDIR)$(BINDIR)/$(PMK) # pmkinstall binary targets $(PMKINSTALL): $(PMKINSTALL_OBJS) $(CC) $(CLDFLAGS) -o $@ $(PMKINSTALL_OBJS) $(PMKINSTALL)_clean: $(RM) $(RMFLAGS) $(PMKINSTALL_OBJS) $(RM) $(RMFLAGS) $(PMKINSTALL) $(PMKINSTALL)_install: $(PMKINSTALL) $(INSTALL_BIN) $(PMKINSTALL) $(DESTDIR)$(BINDIR)/$(PMKINSTALL) $(PMKINSTALL)_deinstall: $(RM) $(RMFLAGS) $(DESTDIR)$(BINDIR)/$(PMKINSTALL) # pmkpc binary targets $(PMKPC): $(PMKPC_OBJS) $(CC) $(CLDFLAGS) -o $@ $(PMKPC_OBJS) $(PMKPC)_clean: $(RM) $(RMFLAGS) $(PMKPC_OBJS) $(RM) $(RMFLAGS) $(PMKPC) $(PMKPC)_install: $(PMKPC) $(INSTALL_BIN) $(PMKPC) $(DESTDIR)$(BINDIR)/$(PMKPC) $(PMKPC)_deinstall: $(RM) $(RMFLAGS) $(DESTDIR)$(BINDIR)/$(PMKPC) # pmkscan binary targets $(PMKSCAN): $(PMKSCAN_OBJS) $(CC) $(CLDFLAGS) -o $@ $(PMKSCAN_OBJS) $(PMKSCAN)_clean: $(RM) $(RMFLAGS) $(PMKSCAN_OBJS) $(RM) $(RMFLAGS) $(PMKSCAN) $(PMKSCAN)_install: $(PMKSCAN) $(INSTALL_BIN) $(PMKSCAN) $(DESTDIR)$(BINDIR)/$(PMKSCAN) $(PMKSCAN)_deinstall: $(RM) $(RMFLAGS) $(DESTDIR)$(BINDIR)/$(PMKSCAN) # pmksetup binary targets $(PMKSETUP): $(PMKSETUP_OBJS) $(CC) $(CLDFLAGS) -o $@ $(PMKSETUP_OBJS) $(PMKSETUP)_clean: $(RM) $(RMFLAGS) $(PMKSETUP_OBJS) $(RM) $(RMFLAGS) $(PMKSETUP) $(PMKSETUP)_install: $(PMKSETUP) $(INSTALL_BIN) $(PMKSETUP) $(DESTDIR)$(BINDIR)/$(PMKSETUP) $(PMKSETUP)_deinstall: $(RM) $(RMFLAGS) $(DESTDIR)$(BINDIR)/$(PMKSETUP) pmk-0.10.4/detect_cpu.h010064400017500000000000000224601027375246100135500ustar00mipswheel/* $Id: detect_cpu.h 1435 2005-08-02 20:18:57Z mipsator $ */ /* * Copyright (c) 2004-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. * */ #ifndef _DETECT_CPU_H_ #define _DETECT_CPU_H_ #include #include "cpu_arch_def.h" #include "hash.h" #include "parse.h" /*************** * common code * ***********************************************************************/ #define LIST_ARCH_EQUIV 1 #define LIST_X86_CPU_VENDOR 2 #define LIST_X86_CPU_MODEL 3 #define LIST_X86_CPU_CLASS 4 #define LIST_ALPHA_CPU_CLASS 5 #define LIST_IA64_CPU_CLASS 6 #define PMK_ARCH_UNKNOWN 0 #define PMK_ARCH_X86_32 1 #define PMK_ARCH_X86_64 2 #define PMK_ARCH_SPARC 3 #define PMK_ARCH_SPARC64 4 #define PMK_ARCH_IA_64 5 #define PMK_ARCH_PPC 6 #define PMK_ARCH_ALPHA 7 #define PMK_ARCH_M68K 8 #define PMK_ARCH_PARISC 9 #define PMK_ARCH_VAX 10 #define PMK_ARCH_STR_UNKNOWN "unknown" #define ARCH_NB_MAX 32 #define PMKCONF_HW_PPC_CPU_ALTIVEC "HW_PPC_CPU_ALTIVEC" /* powerpc altivec feature */ typedef struct { char *name; unsigned char id; } arch_cell; void *seek_key(prsdata *, int); prsdata *parse_cpu_data(char *); char *check_cpu_arch(char *, prsdata *); htable *arch_wrapper(prsdata *, char *); unsigned char arch_name_to_id(char *); /**************** * x86 specific * ***********************************************************************/ #if defined(ARCH_X86_32) || defined(ARCH_X86_64) /* register masks */ #define X86_CPU_MASK_EXTFAM 0x0ff00000 #define X86_CPU_MASK_EXTMOD 0x000f0000 #define X86_CPU_MASK_TYPE 0x0000f000 #define X86_CPU_MASK_FAMILY 0x00000f00 #define X86_CPU_MASK_MODEL 0x000000f0 /* feature register 1 (edx) */ #define X86_CPU_MASK_FEAT_FPU 0x00000001 /* bit 0 */ #define X86_CPU_MASK_FEAT_VME 0x00000002 /* bit 1 */ #define X86_CPU_MASK_FEAT_DE 0x00000004 /* bit 2 */ #define X86_CPU_MASK_FEAT_PSE 0x00000008 /* bit 3 */ #define X86_CPU_MASK_FEAT_TSC 0x00000010 /* bit 4 */ #define X86_CPU_MASK_FEAT_MSR 0x00000020 /* bit 5 */ #define X86_CPU_MASK_FEAT_PAE 0x00000040 /* bit 6 */ #define X86_CPU_MASK_FEAT_MCE 0x00000080 /* bit 7 */ #define X86_CPU_MASK_FEAT_CX8 0x00000100 /* bit 8 */ #define X86_CPU_MASK_FEAT_APIC 0x00000200 /* bit 9 */ /* RESERVED bit 10 */ #define X86_CPU_MASK_FEAT_SEP 0x00000800 /* bit 11 */ #define X86_CPU_MASK_FEAT_MTRR 0x00001000 /* bit 12 */ #define X86_CPU_MASK_FEAT_PGE 0x00002000 /* bit 13 */ #define X86_CPU_MASK_FEAT_MCA 0x00004000 /* bit 14 */ #define X86_CPU_MASK_FEAT_CMOV 0x00008000 /* bit 15 */ #define X86_CPU_MASK_FEAT_PAT 0x00010000 /* bit 16 */ #define X86_CPU_MASK_FEAT_PSE36 0x00020000 /* bit 17 */ #define X86_CPU_MASK_FEAT_PSN 0x00040000 /* bit 18 */ #define X86_CPU_MASK_FEAT_CLFL 0x00080000 /* bit 19 */ /* RESERVED bit 20 */ #define X86_CPU_MASK_FEAT_DTES 0x00200000 /* bit 21 */ #define X86_CPU_MASK_FEAT_ACPI 0x00400000 /* bit 22 */ #define X86_CPU_MASK_FEAT_MMX 0x00800000 /* bit 23 */ #define X86_CPU_MASK_FEAT_FXR 0x01000000 /* bit 24 */ #define X86_CPU_MASK_FEAT_SSE 0x02000000 /* bit 25 */ #define X86_CPU_MASK_FEAT_SSE2 0x04000000 /* bit 26 */ #define X86_CPU_MASK_FEAT_SS 0x00000000 /* bit 27 */ #define X86_CPU_MASK_FEAT_HTT 0x10000000 /* bit 28 */ #define X86_CPU_MASK_FEAT_TM1 0x20000000 /* bit 29 */ #define X86_CPU_MASK_FEAT_IA64 0x40000000 /* bit 30 */ #define X86_CPU_MASK_FEAT_PBE 0x80000000 /* bit 31 */ /* feature register 2 (ecx) */ #define X86_CPU_MASK_FEAT_FPU 0x00000001 /* bit 0 */ /* RESERVED bit 1 */ /* RESERVED bit 2 */ #define X86_CPU_MASK_FEAT_MON 0x00000008 /* bit 3 */ #define X86_CPU_MASK_FEAT_DSCPL 0x00000010 /* bit 4 */ /* RESERVED bit 5 */ /* RESERVED bit 6 */ #define X86_CPU_MASK_FEAT_EST 0x00000080 /* bit 7 */ #define X86_CPU_MASK_FEAT_TM2 0x00000100 /* bit 8 */ /* RESERVED bit 9 */ #define X86_CPU_MASK_FEAT_CID 0x00000400 /* bit 10 */ /* RESERVED bit 11 */ /* RESERVED bit 12 */ #define X86_CPU_MASK_FEAT_CX16 0x00002000 /* bit 13 */ #define X86_CPU_MASK_FEAT_ETPRD 0x00004000 /* bit 14 */ /* extended feature register (edx) */ #define X86_CPU_MASK_FEAT_LM 0x20000000 /* bit 29 */ #define X86_CPU_MASK_FEAT_EXT3DN 0x40000000 /* bit 30 */ #define X86_CPU_MASK_FEAT_3DNOW 0x80000000 /* bit 31 */ #define PMKCONF_HW_X86_CPU_FAMILY "HW_X86_CPU_FAMILY" /* family */ #define PMKCONF_HW_X86_CPU_MODEL "HW_X86_CPU_MODEL" /* model */ #define PMKCONF_HW_X86_CPU_EXTFAM "HW_X86_CPU_EXTFAM" /* extended family */ #define PMKCONF_HW_X86_CPU_EXTMOD "HW_X86_CPU_EXTMOD" /* extended model */ #define PMKCONF_HW_X86_CPU_NAME "HW_X86_CPU_NAME" /* name optionaly provided by cpuid */ #define PMKCONF_HW_X86_CPU_FEATURES "HW_X86_CPU_FEATURES" /* MMX,SSE,SSE2,HTT, etc ... */ #define PMKCONF_HW_X86_CPU_VENDOR "HW_X86_CPU_VENDOR" /* vendor name from cpuid */ #define PMKCONF_HW_X86_CPU_STD_VENDOR "HW_X86_CPU_STD_VENDOR" /* "standard" vendor name : INTEL, AMD, etc ... */ #define PMKCONF_HW_X86_CPU_CLASS "HW_X86_CPU_CLASS" /* ex: i386, i486, i586, etc ... */ #define X86_CPU_CLASS_FAMILY_FMT "%s_FAM%d" /* standard vendor, family */ #define X86_CPU_CLASS_EXTFAM_FMT "%s_EFAM%d" /* standard vendor, extended family */ typedef struct { bool cpuid; char *vendor, *cpuname, *stdvendor, *features; unsigned char family, model, extfam, extmod; uint32_t level; } x86_cpu_cell; typedef struct { uint32_t mask; char *descr; } x86_cpu_feature; x86_cpu_cell *x86_cpu_cell_init(void); void x86_cpu_cell_destroy(x86_cpu_cell *); char *x86_get_std_cpu_vendor(prsdata *, char *); bool x86_get_cpuid_data(x86_cpu_cell *); bool x86_set_cpu_data(prsdata *, x86_cpu_cell *, htable *); #endif /* ARCH_X86_32 || ARCH_X86_64 */ /****************** * alpha specific * ***********************************************************************/ #if defined(ARCH_ALPHA) #define ALPHA_IMPLVER_EV4 0 #define ALPHA_IMPLVER_EV5 1 #define ALPHA_IMPLVER_EV6 2 #define ALPHA_CPU_CLASS_FMT "IMPLVER_%u" #define ALPHA_CPU_UNKNOWN "unknown" #define ALPHA_CPU_MASK_FEAT_BWX 0x00000001 /* bit 0 */ #define ALPHA_CPU_MASK_FEAT_FIX 0x00000002 /* bit 1 */ #define ALPHA_CPU_MASK_FEAT_CIX 0x00000004 /* bit 2 */ #define ALPHA_CPU_MASK_FEAT_MVI 0x00000100 /* bit 8 */ #define ALPHA_CPU_MASK_FEAT_PAT 0x00000200 /* bit 9 */ #define ALPHA_CPU_MASK_FEAT_PMI 0x00001000 /* bit 12 */ #define PMKCONF_HW_ALPHA_CPU_CLASS "HW_ALPHA_CPU_CLASS" /* ex: EV4, EV5, EV6 */ #define PMKCONF_HW_ALPHA_CPU_FEATURES "HW_ALPHA_CPU_FEATURES" /* BWX, FIX, CIX, MVI, PAT, PMI */ typedef struct { uint64_t mask; char *descr; } alpha_cpu_feature; bool alpha_set_cpu_data(prsdata *, htable *); #endif /* ARCH_ALPHA */ /****************** * ia64 specific * ***********************************************************************/ #if defined(ARCH_IA64) /* register masks */ #define IA64_CPU_MASK_LEVEL 0x000000000ff #define IA64_CPU_MASK_REVISION 0x0000000ff00 #define IA64_CPU_MASK_MODEL 0x00000ff0000 #define IA64_CPU_MASK_FAMILY 0x000ff000000 #define IA64_CPU_MASK_ARCHREV 0x0ff00000000 /* feature register */ #define IA64_CPU_MASK_FEAT_LB 0x0000000000000001 /* bit 0 */ #define IA64_CPU_MASK_FEAT_SD 0x0000000000000002 /* bit 1 */ #define IA64_CPU_MASK_FEAT_AO 0x0000000000000004 /* bit 2 */ #define PMKCONF_HW_IA64_CPU_REVISION "HW_IA64_CPU_REVISION" /* revision */ #define PMKCONF_HW_IA64_CPU_MODEL "HW_IA64_CPU_MODEL" /* model */ #define PMKCONF_HW_IA64_CPU_FAMILY "HW_IA64_CPU_FAMILY" /* family */ #define PMKCONF_HW_IA64_CPU_ARCHREV "HW_IA64_CPU_ARCHREV" /* architecture revision */ #define PMKCONF_HW_IA64_CPU_FEATURES "HW_IA64_CPU_FEATURES" /* features */ #define PMKCONF_HW_IA64_CPU_VENDOR "HW_IA64_CPU_VENDOR" /* vendor name */ #define PMKCONF_HW_IA64_CPU_CLASS "HW_IA64_CPU_CLASS" /* cpu class */ #define IA64_CPU_CLASS_FAMILY_FMT "FAM%d" /* family */ typedef struct { uint64_t mask; char *descr; } ia64_cpu_feature; bool ia64_get_cpuid_data(prsdata *, htable *); #endif /* ARCH_IA64 */ #endif /* _DETECT_CPU_H_ */ pmk-0.10.4/pmk_obj.h010064400017500000000000000045131016131571600130430ustar00mipswheel/* $Id: pmk_obj.h 1272 2004-12-19 15:18:38Z mipsator $ */ /* * Copyright (c) 2003 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. * */ #ifndef _PMK_OBJECT_H_ #define _PMK_OBJECT_H_ #include "dynarray.h" #include "hash.h" typedef unsigned char potype; typedef struct { potype type; void *data; } pmkobj; /* define pmk object types */ #define PO_NULL 0x00 #define PO_BOOL 0x01 #define PO_STRING 0x02 #define PO_LIST 0x04 #define PO_HASH 0x08 pmkobj *po_mk_bool(bool); pmkobj *po_mk_str(char *); pmkobj *po_mk_list(dynary *); pmkobj *po_mk_hash(htable *); pmkobj *po_dup(pmkobj *); potype po_get_type(pmkobj *); void *po_get_data(pmkobj *); bool po_get_bool(pmkobj *); char *po_get_str(pmkobj *); dynary *po_get_list(pmkobj *); void po_free(pmkobj *); pmkobj *po_append(void *, void *, void *); #endif /* _PMK_OBJECT_H_ */ pmk-0.10.4/common.h010064400017500000000000000075611027375204200127210ustar00mipswheel/* $Id: common.h 1433 2005-08-02 20:14:26Z mipsator $ */ /* * Copyright (c) 2003-2004 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. * */ #ifndef _PMK_COMMON_H_ #define _PMK_COMMON_H_ #include #include #include "dynarray.h" #include "premake.h" /************* * constants * ***********************************************************************/ #ifndef S_BLKSIZE #define S_BLKSIZE 512 /* standard block size */ #endif #define MAXTOKENS 128 /* max slots in the paths array */ #define MK_FILE_EXT ".mk" #define TMP_MK_FILE TMPDIR "/pmk_XXXXXXXX" MK_FILE_EXT #define MKVAR_FILE "make_var_result" #define MKVAR_FMT_MK "all:\n\t@printf \"%%s\\n\" $(%s) >%s" #define MKVAR_FMT_CMD "make -f %s >/dev/null 2>&1" #define EMPTY_OPT_VALUE "" /* #define DEBUGF(fmt, arg...) fprintf(stderr, "DEBUGF File '%s', Line %d: " fmt "\n", __FILE__, __LINE__, ## arg) */ /******************** * type definitions * ***********************************************************************/ /* structure to store multiple path */ typedef struct { int pathnum; char *pathlst[MAXTOKENS]; } mpath; /* struct to store pmk.conf defines */ /* WARN opchar has been put first else linux binaries gives segfault !!! */ typedef struct { char opchar, key[OPT_NAME_LEN], val[OPT_VALUE_LEN]; } cfg_opt; /* command option type */ typedef struct { char name[OPT_NAME_LEN], value[OPT_VALUE_LEN]; } pmkcmdopt; /* command type */ typedef struct { int token; char *label; } pmkcmd; /************** * prototypes * ***********************************************************************/ bool get_line(FILE *, char *, size_t); bool env_to_opt(char *, pmkcmdopt *); bool get_make_var(char *, char *, size_t); bool str_to_ulong(char *, int, unsigned long *); dynary *str_to_dynary(char *, char); dynary *str_to_dynary_adv(char *, char *); bool find_file_dir(dynary *, char *, char *, size_t); bool find_file(dynary *, char *, char *, size_t); bool get_file_path(char *, char *, char *, size_t); void errorf(const char *, ...); void errorf_line(char *, int, const char *, ...); void debugf(const char *, ...); bool pmk_log_open(char *); void pmk_log_close(void); bool pmk_log(const char *, ...); bool fcopy(char *, char *, mode_t); FILE *tmp_open(char *, char *, char *, size_t); FILE *tmps_open(char *, char *, char *, size_t, size_t); #endif /* _PMK_COMMON_H_ */