diff options
author | Ritesh Raj Sarraf <rrs@debian.org> | 2013-12-02 14:27:40 -0500 |
---|---|---|
committer | Ritesh Raj Sarraf <rrs@debian.org> | 2013-12-02 14:27:40 -0500 |
commit | 00cc15e3ce4fc63e509a575ae3016ca80afcc344 (patch) | |
tree | 3e5d21daf12cbe8c9f163401eee6eb902305fb69 | |
parent | b31bdef8a3eba48bf069962004794c7ca58a6b92 (diff) | |
download | kbuild-upstream.tar.gz |
Imported Upstream version 0.1.9998svn2695+dfsgupstream/0.1.9998svn2695+dfsgupstream
217 files changed, 11711 insertions, 5098 deletions
@@ -1,10 +1,10 @@ -# $Id: Config.kmk 2555 2011-11-30 20:01:57Z bird $ +# $Id: Config.kmk 2668 2012-11-25 19:53:45Z bird $ ## @file # Build Configuration. # # -# Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# Copyright (c) 2005-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> # # This file is part of kBuild. # @@ -246,15 +246,12 @@ ifeq ($(KBUILD_TARGET),darwin) endif ifeq ($(filter-out win nt,$(KBUILD_TARGET)),) - ifeq ($(KBUILD_TARGET_ARCH),x86) - include $(KBUILD_PATH)/tools/VCC70.kmk # fixme! template expanding does something bad to _LIBS /me thinks. - TEMPLATE_BIN_TOOL = VCC70 - TEMPLATE_BIN_DEFS = WINDOWS32 _CONSOLE __WIN__ WIN32 __WIN32__ - else ifeq ($(KBUILD_TARGET_ARCH),amd64) - TEMPLATE_BIN_TOOL = VCC80AMD64 - TEMPLATE_BIN_DEFS = WINDOWS32 _CONSOLE __WIN__ WIN32 __WIN32__ __WIN64__ WIN64 \ - _CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_WARNINGS - endif + TEMPLATE_BIN_TOOL = VCC100 + TEMPLATE_BIN_TOOL.x86 = VCC100X86 + TEMPLATE_BIN_TOOL.amd64 = VCC100AMD64 + TEMPLATE_BIN_DEFS = WINDOWS32 _CONSOLE __WIN__ _CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_WARNINGS + TEMPLATE_BIN_DEFS.x86 = WIN32 __WIN32__ + TEMPLATE_BIN_DEFS.amd64 = WIN32 __WIN32__ __WIN64__ WIN64 TEMPLATE_BIN_CFLAGS = -W3 -Zi -Zl TEMPLATE_BIN_CFLAGS.release = -O2 TEMPLATE_BIN_CFLAGS.profile = -O2 -GH -Gh @@ -264,7 +261,7 @@ ifeq ($(filter-out win nt,$(KBUILD_TARGET)),) $(PATH_GNUMAKE_SRC)/glob TEMPLATE_BIN_LDFLAGS = /SUBSYSTEM:console /INCREMENTAL:no /NOD /DEBUG ifeq ($(KBUILD_TYPE),profile) - TEMPLATE_BIN_SDKS = WINPSDKINCS + TEMPLATE_BIN_SDKS = WINPSDKINCS TEMPLATE_BIN_CFLAGS += -MT TEMPLATE_BIN_LIBS = \ D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/lib/kPrf2.lib \ @@ -276,12 +273,19 @@ ifeq ($(filter-out win nt,$(KBUILD_TARGET)),) $(PATH_SDK_WINPSDKINCS_LIB)/AdvAPI32.lib \ $(PATH_SDK_WINPSDKINCS_LIB)/User32.lib else - TEMPLATE_BIN_SDKS = WINPSDK - TEMPLATE_BIN_CFLAGS += -MD - TEMPLATE_BIN_LIBS = \ - $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/oldnames.lib \ - $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/msvcrt.lib - # $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/msvcprt.lib - avoid this to save space! + TEMPLATE_BIN_SDKS = WINPSDK71 + ifdef KBUILD_WITH_STATIC_MSVCRT + TEMPLATE_BIN_CFLAGS += -MT + TEMPLATE_BIN_LIBS = \ + $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/oldnames.lib \ + $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcmt.lib \ + $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/libcpmt.lib + else + TEMPLATE_BIN_CFLAGS += -MD + TEMPLATE_BIN_LIBS = \ + $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/oldnames.lib \ + $(PATH_TOOL_$(TEMPLATE_BIN_TOOL)_LIB)/msvcrt.lib + endif endif endif diff --git a/Makefile.kmk b/Makefile.kmk index 79c58e9..91c98c0 100644 --- a/Makefile.kmk +++ b/Makefile.kmk @@ -1,4 +1,4 @@ -# $Id: Makefile.kmk 2440 2011-07-06 12:17:51Z bird $ +# $Id: Makefile.kmk 2674 2013-01-31 13:28:27Z bird $ ## @file # Top-Level Sub-Makefile for kBuild. # @@ -69,14 +69,13 @@ kBuild_bin_SOURCES.os2 = \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc06.dll=>libc06.dll \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc061.dll=>libc061.dll \ kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc062.dll=>libc062.dll \ - kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc063.dll=>libc063.dll + kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc063.dll=>libc063.dll \ + kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc064.dll=>libc064.dll \ + kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/libc065.dll=>libc065.dll if1of ($(KBUILD_TARGET), nt win) -kBuild_bin_SOURCES.$(KBUILD_TARGET).x86 = \ - kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/msvcr71.dll=>msvcr71.dll -kBuild_bin_SOURCES.$(KBUILD_TARGET).amd64 = \ - kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/Microsoft.VC80.CRT/msvcr80.dll=>Microsoft.VC80.CRT/msvcr80.dll \ - kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/Microsoft.VC80.CRT/Microsoft.VC80.CRT.manifest=>Microsoft.VC80.CRT/Microsoft.VC80.CRT.manifest +kBuild_bin_SOURCES.$(KBUILD_TARGET) = \ + kBuild/bin/$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)/msvcr100.dll kBuild_bin_SOURCES.profile = \ D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/bin/kPrf2.dll \ D:/coding/kStuff/svn/trunk/out/win.$(KBUILD_TARGET_ARCH)/release/kStuff/bin/kPrf2WinApiWrappers.dll diff --git a/VSlickMacros/kdev.e b/VSlickMacros/kdev.e index a86dd1d..bfb805a 100644 --- a/VSlickMacros/kdev.e +++ b/VSlickMacros/kdev.e @@ -1,4 +1,4 @@ -/* $Id: kdev.e 2413 2010-09-11 17:43:04Z bird $ -*- tab-width: 4 c-indent-level: 4 -*- */ +/* $Id: kdev.e 2685 2013-07-04 19:50:01Z bird $ -*- tab-width: 4 c-indent-level: 4 -*- */ /** @file * Visual SlickEdit Documentation Macros. */ @@ -58,7 +58,8 @@ */ defeventtab default_keys def 'C-S-A' = k_signature -def 'C-S-C' = k_javadoc_classbox +//def 'C-S-C' = k_javadoc_classbox +def 'C-S-C' = k_calc def 'C-S-E' = k_box_exported def 'C-S-F' = k_javadoc_funcbox def 'C-S-G' = k_box_globals @@ -2945,6 +2946,40 @@ _str _buffer_save_kdev(int buf_id) } +/** + * Command similar to the add() command in math.e, only this + * produces hex and doesn't do the multi line stuff. + */ +_command int k_calc() +{ + _str sLine; + filter_init(); + typeless rc = filter_get_string(sLine); + if (rc == 0) + { + _str sResultHex; + rc = eval_exp(sResultHex, sLine, 16); + if (rc == 0) + { + _str sResultDec; + rc = eval_exp(sResultDec, sLine, 10); + if (rc == 0) + { + _end_select(); + _insert_text(' = ' :+ sResultHex :+ ' (' :+ sResultDec :+ ')'); + return 0; + } + } + } + + if (isinteger(rc)) + message(get_message(rc)); + else + message(rc); + return 1; +} + + /******************************************************************************* * Menu and Menu commands * @@ -3329,7 +3364,284 @@ btnCancel.lbutton_up() p_active_form._delete_window("\r"); } +static _str aCLikeIncs[] = +{ + "c", "ansic", "java", "rul", "vera", "cs", "js", "as", "idl", "asm", "s", "imakefile", "rc", "lex", "yacc", "antlr" +}; + +static _str aMyLangIds[] = +{ + "applescript", + "ansic", + "antlr", + "as", + "asm", + "c", + "cs", + "csh", + "css", + "conf", + "d", + "docbook", + "dtd", + "e", + "html", + "idl", + "imakefile", + "ini", + "java", + "js", + "lex", + "mak", + "masm", + "pas", + "phpscript", + "powershell", + "py", + "rexx", + "rc", + "rul", + "tcl", + "s", + "unixasm", + "vbs", + "xhtml", + "xml", + "xmldoc", + "xsd", + "yacc" +}; + +#if __VERSION__ >= 17.0 +# require "se/lang/api/LanguageSettings.e" +using se.lang.api.LanguageSettings; +#endif + +#if __VERSION__ >= 16.0 +int def_auto_unsurround_block; +#endif + +/** + * Loads the standard bird settings. + */ +_command void kdev_load_settings() +{ + typeless nt1; + typeless nt2; + typeless nt3; + typeless nt4; + typeless nt5; + typeless nt6; + typeless i7; + _str sRest; + _str sTmp; + + /* + * Generl stuff. + */ + _default_option('A', '0'); /* ALT menu */ + def_alt_menu = 0; + _default_option('R', '130'); /* Vertical line in column 130. */ + def_mfsearch_init_flags = 2 | 4; /* MFSEARCH_INIT_CURWORD | MFSEARCH_INIT_SELECTION */ + def_line_insert = 'B'; /* insert before */ + def_file_types='All Files (*),' /** @todo make this prettier */ + 'C/C++ Files (*.c;*.cc;*.cpp;*.cp;*.cxx;*.c++;*.h;*.hh;*.hpp;*.hxx;*.inl;*.xpm),' + 'Assembler (*.s;*.asm;*.mac;*.S),' + 'Makefiles (*;*.mak;*.kmk)' + 'C# Files (*.cs),' + 'Ch Files (*.ch;*.chf;*.chs;*.cpp;*.h),' + 'D Files (*.d),' + 'Java Files (*.java),' + 'HTML Files (*.htm;*.html;*.shtml;*.asp;*.jsp;*.php;*.php3;*.rhtml;*.css),' + 'CFML Files (*.cfm;*.cfml;*.cfc),' + 'XML Files (*.xml;*.dtd;*.xsd;*.xmldoc;*.xsl;*.xslt;*.ent;*.tld;*.xhtml;*.build;*.plist),' + 'XML/SGML DTD Files (*.xsd;*.dtd),' + 'XML/JSP TagLib Files (*.tld;*.xml),' + 'Objective-C (*.m;*.mm;*.h),' + 'IDL Files (*.idl),' + 'Ada Files (*.ada;*.adb;*.ads),' + 'Applescript Files (*.applescript),' + 'Basic Files (*.vb;*.vbs;*.bas;*.frm),' + 'Cobol Files (*.cob;*.cbl;*.ocb),' + 'JCL Files (*.jcl),' + 'JavaScript (*.js;*.ds),' + 'ActionScript (*.as),' + 'Pascal Files (*.pas;*.dpr),' + 'Fortran Files (*.for;*.f),' + 'PL/I Files (*.pl1),' + 'InstallScript (*.rul),' + 'Perl Files (*.pl;*.pm;*.perl;*.plx),' + 'Python Files (*.py),' + 'Ruby Files (*.rb;*.rby),' + 'Java Properties (*.properties),' + 'Lua Files (*.lua),' + 'Tcl Files (*.tcl;*.tlib;*.itk;*.itcl;*.exp),' + 'PV-WAVE (*.pro),' + 'Slick-C (*.e;*.sh),' + 'SQL Files (*.sql;*.pgsql),' + 'SAS Files (*.sas),' + 'Text Files (*.txt),' + 'Verilog Files (*.v),' + 'VHDL Files (*.vhd),' + 'SystemVerilog Files (*.sv;*.svh;*.svi),' + 'Vera Files (*.vr;*.vrh),' + 'Erlang Files (*.erl;*.hrl),' + ; + + def_updown_col=0; /* cursor movement */ + def_cursorwrap=0; /* ditto. */ + def_click_past_end=1; /* ditto */ + def_start_on_first=1; /* vs A B C; view A. */ + def_vc_system='Subversion' /* svn is default version control */ +#if __VERSION__ >= 16.0 + def_auto_unsurround_block=0; /* Delete line, not block. */ +#endif + _config_modify_flags(CFGMODIFY_DEFDATA); + + /* Make it grok: # include <stuff.h> */ + for (i = 0; i < aCLikeIncs._length(); i++) + replace_def_data("def-":+aCLikeIncs[i]:+"-include", + '^[ \t]*(\#[ \t]*include|include|\#[ \t]*line)[ \t]#({#1:i}[ \t]#|)(<{#0[~>]#}>|"{#0[~"]#}")'); + replace_def_data("def-m-include", '^[ \t]*(\#[ \t]*include|\#[ \t]*import|include|\#[ \t]*line)[ \t]#({#1:i}[ \t]#|)(<{#0[~>]#}>|"{#0[~"]#}")'); + replace_def_data("def-e-include", '^[ \t]*(\#[ \t]*include|\#[ \t]*import|\#[ \t]*require|include)[ \t]#(''{#0[~'']#}''|"{#0[~"]#}")'); + + /* Replace the default unicode proportional font with the fixed oned. */ + _str sCodeFont = _default_font(CFG_SBCS_DBCS_SOURCE_WINDOW); + _str sUnicodeFont = _default_font(CFG_UNICODE_SOURCE_WINDOW); + if (pos("Default Unicode", sUnicodeFont) > 0 && length(sCodeFont) > 5) + _default_font(CFG_UNICODE_SOURCE_WINDOW,sCodeFont); + if (machine()=='INTELSOLARIS' || machine()=='SPARCSOLARIS') + { + _default_font(CFG_MENU,'DejaVu Sans,10,0,0,'); + _default_font(CFG_DIALOG,'DejaVu Sans,10,0,,'); + _ConfigEnvVar('VSLICKDIALOGFONT','DejaVu Sans,10,0,,'); + } + + /* Not so important. */ + int fSearch = 0x400400; /* VSSEARCHFLAG_WRAP | VSSEARCHFLAG_PROMPT_WRAP */; + _default_option('S', (_str)fSearch); + + +#if __VERSION__ >= 17.0 + /* + * Language settings via API. + */ + int fNewAff = AFF_BEGIN_END_STYLE \ + | AFF_INDENT_WITH_TABS \ + | AFF_SYNTAX_INDENT \ + /*| AFF_TABS*/ \ + | AFF_NO_SPACE_BEFORE_PAREN \ + | AFF_PAD_PARENS \ + | AFF_INDENT_CASE \ + | AFF_KEYWORD_CASING \ + | AFF_TAG_CASING \ + | AFF_ATTRIBUTE_CASING \ + | AFF_VALUE_CASING \ + /*| AFF_HEX_VALUE_CASING*/; + def_adaptive_formatting_flags = ~fNewAff; + replace_def_data("def-adaptive-formatting-flags", def_adaptive_formatting_flags); + _str sLangId; + foreach (sLangId in aMyLangIds) + { + LanguageSettings.setIndentCaseFromSwitch(sLangId, true); + LanguageSettings.setBeginEndStyle(sLangId, BES_BEGIN_END_STYLE_2); + LanguageSettings.setIndentWithTabs(sLangId, false); + LanguageSettings.setUseAdaptiveFormatting(sLangId, true); + LanguageSettings.setAdaptiveFormattingFlags(sLangId, ~fNewAff); + LanguageSettings.setSaveStripTrailingSpaces(sLangId, STSO_STRIP_MODIFIED); + LanguageSettings.setTabs(sLangId, "8+"); + LanguageSettings.setSyntaxIndent(sLangId, 4); + + /* C/C++ setup, wrap at column 80 not 64. */ + sTmp = LanguageSettings.getCommentWrapOptions(sLangId); + if (length(sTmp) > 10) + { + typeless ntBlockCommentWrap, ntDocCommentWrap, ntFixedWidth; + parse sTmp with ntBlockCommentWrap ntDocCommentWrap nt3 nt4 nt5 ntFixedWidth sRest; + if ((int)ntFixedWidth < 80) + LanguageSettings.setCommentWrapOptions('c', ntBlockCommentWrap:+' ':+ntDocCommentWrap:+' ':+nt3:+' ':+nt4:+' ':+nt5:+' 80 ':+sRest); + //replace_def_data("def-comment-wrap-c",'0 1 0 1 1 64 0 0 80 0 80 0 80 0 0 1 '); - default + //replace_def_data("def-comment-wrap-c",'0 1 0 1 1 80 0 0 80 0 80 0 80 0 0 0 '); - disabled + //replace_def_data("def-comment-wrap-c",'1 1 0 1 1 80 0 0 80 0 80 0 80 0 0 1 '); - enable block comment wrap. + } + + /* set the encoding to UTF-8 without any friggin useless signatures. */ + idxExt = name_match('def-lang-for-ext-', 1, MISC_TYPE); + while (idxExt > 0) + { + if (name_info(idxExt) == sLangId) + { + parse name_name(idxExt) with 'def-lang-for-ext-' auto sExt; + sVarName = 'def-encoding-' :+ sExt; + idxExtEncoding = find_index(sVarName, MISC_TYPE); + if (idxExtEncoding != 0) + delete_name(idxExtEncoding); + } + idxExt = name_match('def-lang-for-ext-', 0, MISC_TYPE); + } + replace_def_data('def-encoding-' :+ sLangId, '+futf8 '); + } + LanguageSettings.setIndentWithTabs('mak', true); + LanguageSettings.setLexerName('mak', 'kmk'); + LanguageSettings.setSyntaxIndent('mak', 8); + LanguageSettings.setBeautifierProfileName('c', "bird's Style"); + LanguageSettings.setBeautifierProfileName('m', "bird's Objective-C Style"); + + /* Fix .asm and add .mac, .kmk, .cmd, and .pgsql. */ + replace_def_data("def-lang-for-ext-asm", 'masm'); + replace_def_data("def-lang-for-ext-mac", 'masm'); + replace_def_data("def-lang-for-ext-kmk", 'mak'); + replace_def_data("def-lang-for-ext-cmd", 'bat'); + replace_def_data("def-lang-for-ext-pgsql", 'plsql'); + + /* + * Change the codehelp default. + */ + int fOldCodeHelp = def_codehelp_flags; + int fNewCodeHelp = fOldCodeHelp \ + | VSCODEHELPFLAG_AUTO_FUNCTION_HELP \ + | VSCODEHELPFLAG_AUTO_LIST_MEMBERS \ + | VSCODEHELPFLAG_SPACE_INSERTS_SPACE \ + | VSCODEHELPFLAG_INSERT_OPEN_PAREN \ + | VSCODEHELPFLAG_DISPLAY_MEMBER_COMMENTS \ + | VSCODEHELPFLAG_DISPLAY_FUNCTION_COMMENTS \ + | VSCODEHELPFLAG_REPLACE_IDENTIFIER \ + | VSCODEHELPFLAG_PRESERVE_IDENTIFIER \ + | VSCODEHELPFLAG_AUTO_PARAMETER_COMPLETION \ + | VSCODEHELPFLAG_AUTO_LIST_PARAMS \ + | VSCODEHELPFLAG_PARAMETER_TYPE_MATCHING \ + | VSCODEHELPFLAG_NO_SPACE_AFTER_PAREN \ + | VSCODEHELPFLAG_RESERVED_ON \ + | VSCODEHELPFLAG_MOUSE_OVER_INFO \ + | VSCODEHELPFLAG_AUTO_LIST_VALUES \ + | VSCODEHELPFLAG_FIND_TAG_PREFERS_DEFINITION \ + | VSCODEHELPFLAG_FIND_TAG_PREFERS_ALTERNATE \ + | VSCODEHELPFLAG_HIGHLIGHT_TAGS \ + ; + fNewCodeHelp &= ~( VSCODEHELPFLAG_SPACE_COMPLETION \ + | VSCODEHELPFLAG_AUTO_SYNTAX_HELP \ + | VSCODEHELPFLAG_NO_SPACE_AFTER_COMMA \ + | VSCODEHELPFLAG_STRICT_LIST_SELECT \ + | VSCODEHELPFLAG_AUTO_LIST_VALUES \ + ); + def_codehelp_flags = fNewCodeHelp; + foreach (sLangId in aMyLangIds) + { + _str sVarName = 'def-codehelp-' :+ sLangId; + int idxVar = find_index(sVarName, MISC_TYPE); + if (idxVar != 0) + replace_def_data(sVarName, fNewCodeHelp); + } +#endif + + /** @todo + * - def_save_options + * - Auto restore clipboards + * */ + + message("Please restart SlickEdit.") +} /** * Module initiation. @@ -3351,3 +3663,4 @@ definit() iTimer = _set_timer(1000, k_menu_create, "timer"); /* createMyColorSchemeAndUseIt();*/ } + diff --git a/VSlickMacros/uscheme.ini b/VSlickMacros/uscheme.ini deleted file mode 100644 index e195930..0000000 --- a/VSlickMacros/uscheme.ini +++ /dev/null @@ -1,73 +0,0 @@ -[knut's] -CFG_COMMENTfg=0xFF00 -CFG_COMMENTbg=0x840000 -CFG_COMMENTff=0x2 -CFG_CLINEfg=0xFFFF00 -CFG_CLINEbg=0x840000 -CFG_CLINEff=0x0 -CFG_CURSORfg=0x0 -CFG_CURSORbg=0xC0C0C0 -CFG_CURSORff=0x0 -CFG_NOSAVE_LINEfg=0xFFFF -CFG_NOSAVE_LINEbg=0x840000 -CFG_NOSAVE_LINEff=0x0 -CFG_INSERTED_LINEfg=0xFFFFFF -CFG_INSERTED_LINEbg=0x80 -CFG_INSERTED_LINEff=0x0 -CFG_KEYWORDfg=0xFF -CFG_KEYWORDbg=0x840000 -CFG_KEYWORDff=0x0 -CFG_LINENUMfg=0x808080 -CFG_LINENUMbg=0x840000 -CFG_LINENUMff=0x0 -CFG_MESSAGEfg=0x80000008 -CFG_MESSAGEbg=0x80000005 -CFG_MESSAGEff=0x0 -CFG_MODIFIED_LINEfg=0xFF -CFG_MODIFIED_LINEbg=0x840000 -CFG_MODIFIED_LINEff=0x0 -CFG_NUMBERfg=0xFF -CFG_NUMBERbg=0x840000 -CFG_NUMBERff=0x0 -CFG_PPKEYWORDfg=0xC0C0C0 -CFG_PPKEYWORDbg=0x840000 -CFG_PPKEYWORDff=0x0 -CFG_SELECTED_CLINEfg=0x800000 -CFG_SELECTED_CLINEbg=0x808000 -CFG_SELECTED_CLINEff=0x0 -CFG_SELECTIONfg=0x800000 -CFG_SELECTIONbg=0x808000 -CFG_SELECTIONff=0x0 -CFG_STATUSfg=0x80000008 -CFG_STATUSbg=0x80000005 -CFG_STATUSff=0x0 -CFG_STRINGfg=0xFFFF -CFG_STRINGbg=0x840000 -CFG_STRINGff=0x0 -CFG_WINDOW_TEXTfg=0xFFFF00 -CFG_WINDOW_TEXTbg=0x840000 -CFG_WINDOW_TEXTff=0x0 -CFG_SYMBOL1fg=0xC0C0C0 -CFG_SYMBOL1bg=0x840000 -CFG_SYMBOL1ff=0x0 -CFG_SYMBOL2fg=0xFF00FF -CFG_SYMBOL2bg=0x840000 -CFG_SYMBOL2ff=0x0 -CFG_SYMBOL3fg=0x8080 -CFG_SYMBOL3bg=0x840000 -CFG_SYMBOL3ff=0x0 -CFG_SYMBOL4fg=0x0 -CFG_SYMBOL4bg=0x840000 -CFG_SYMBOL4ff=0x0 -CFG_FUNCTIONfg=0x808000 -CFG_FUNCTIONbg=0x840000 -CFG_FUNCTIONff=0x0 -CFG_FILENAMEfg=0xFF0000 -CFG_FILENAMEbg=0x808000 -CFG_FILENAMEff=0x0 -CFG_HILIGHTfg=0x840000 -CFG_HILIGHTbg=0xFFFF00 -CFG_HILIGHTff=0x0 -CFG_ATTRIBUTEfg=0xFF00FF -CFG_ATTRIBUTEbg=0x840000 -CFG_ATTRIBUTEff=0x0 diff --git a/VSlickMacros/vusr_beautifier.xml b/VSlickMacros/vusr_beautifier.xml new file mode 100644 index 0000000..a05d330 --- /dev/null +++ b/VSlickMacros/vusr_beautifier.xml @@ -0,0 +1,447 @@ +<profiles> + <profile name="bird's Style" lang="c"> + <P N="syntax_indent" V="4" E="1"/> + <P N="tab_indent" V="8" E="1"/> + <P N="indent_policy" V="12" E="1"/> + <P N="indent_member_access" V="0" E="1"/> + <P N="access_spec_indent" V="1" E="1"/> + <P N="member_access_relative_indent" V="0" E="1"/> + <P N="indent_case" V="1" E="1"/> + <P N="case_indent_width" V="4" E="1"/> + <P N="continuation_width" V="4" E="1"/> + <P N="funcall_param_align" V="10" E="1"/> + <P N="sp_tmpldecl_comma" V="2" E="1"/> + <P N="sp_init_comma" V="2" E="1"/> + <P N="sp_member_dotstar" V="0" E="1"/> + <P N="sp_mptr_ccs" V="5" E="1"/> + <P N="sp_delete_padbracket" V="5" E="1"/> + <P N="sp_cppcast_pad" V="5" E="1"/> + <P N="st_nl_file" V="4" E="1"/> + <P N="sp_class_lbrace" V="1" E="1"/> + <P N="st_nl_empty" V="5" E="1"/> + <P N="sp_catch_padparen" V="5" E="1"/> + <P N="sp_switch_lparen" V="4" E="1"/> + <P N="sp_ref_arp" V="5" E="1"/> + <P N="sp_member_arrowstar" V="0" E="1"/> + <P N="sp_tmpldecl_equals" V="3" E="1"/> + <P N="sp_arrayexpr_lbracket" V="5" E="1"/> + <P N="sp_tmpldecl_pad" V="5" E="1"/> + <P N="sp_tmplparm_pad" V="5" E="1"/> + <P N="sp_arraydecl_lbracket" V="5" E="1"/> + <P N="st_fundecl_nameline" V="5" E="0"/> + <P N="st_oneline_dowhile" V="4" E="1"/> + <P N="sp_op_bitwise" V="3" E="1"/> + <P N="st_oneline_catch" V="5" E="1"/> + <P N="sp_ctlstmt_rparen" V="5" E="1"/> + <P N="sp_ctlstmt_padparen" V="5" E="1"/> + <P N="st_newline_after_extern" V="4" E="1"/> + <P N="sp_for_lparen" V="4" E="1"/> + <P N="sp_funcall_voidparen" V="5" E="1"/> + <P N="sp_switch_defcolon" V="0" E="1"/> + <P N="sp_switch_padparen" V="5" E="1"/> + <P N="sp_class_colon" V="3" E="1"/> + <P N="sp_fun_padparen" V="5" E="1"/> + <P N="sp_if_rparen" V="4" E="1"/> + <P N="sp_struct_comma" V="2" E="1"/> + <P N="sp_ptr_is" V="4" E="1"/> + <P N="sp_fun_equals" V="3" E="1"/> + <P N="sp_delete_rbracket" V="4" E="1"/> + <P N="sp_op_bitand" V="3" E="1"/> + <P N="sp_op_assignment" V="3" E="1"/> + <P N="sp_ref_av" V="5" E="1"/> + <P N="sp_new_lparen" V="5" E="1"/> + <P N="sp_struct_colon" V="3" E="1"/> + <P N="sp_ptr_srp" V="5" E="1"/> + <P N="sp_for_comma" V="2" E="1"/> + <P N="sp_funcall_comma" V="2" E="1"/> + <P N="sp_class_comma" V="2" E="1"/> + <P N="sp_funcall_operator" V="0" E="1"/> + <P N="st_oneline_access" V="4" E="1"/> + <P N="sp_arrayexpr_rbracket" V="5" E="1"/> + <P N="sp_cppcast_gt" V="5" E="1"/> + <P N="sp_op_mult" V="3" E="1"/> + <P N="sp_fun_commainit" V="2" E="1"/> + <P N="sp_tmpldecl_lt" V="5" E="1"/> + <P N="sp_arraydecl_rbracket" V="5" E="1"/> + <P N="sp_for_lbrace" V="1" E="0"/> + <P N="sp_init_lbrace" V="2" E="1"/> + <P N="st_oneline_then" V="5" E="1"/> + <P N="sp_catch_lparen" V="4" E="1"/> + <P N="sp_fun_operator" V="0" E="1"/> + <P N="sp_ptr_ss" V="5" E="1"/> + <P N="sp_member_dot" V="0" E="1"/> + <P N="sp_tmplcall_pad" V="5" E="1"/> + <P N="sp_enum_lbrace" V="1" E="1"/> + <P N="sp_ptr_sv" V="5" E="1"/> + <P N="sp_for_rparen" V="4" E="1"/> + <P N="sp_while_rparen" V="4" E="1"/> + <P N="sp_ret_parexpr" V="4" E="1"/> + <P N="sp_throw_parexpr" V="4" E="1"/> + <P N="st_nl_class" V="5" E="0"/> + <P N="st_oneline_statement" V="5" E="1"/> + <P N="sp_union_lbrace" V="1" E="1"/> + <P N="st_oneline_elsif" V="4" E="1"/> + <P N="sp_op_unary" V="0" E="1"/> + <P N="sp_op_binary" V="3" E="1"/> + <P N="sp_new_rparen" V="4" E="1"/> + <P N="sp_new_padparen" V="5" E="1"/> + <P N="sp_cast_lparen" V="5" E="1"/> + <P N="sp_op_comparison" V="3" E="1"/> + <P N="sp_catch_rparen" V="4" E="1"/> + <P N="sp_fun_lparen" V="5" E="1"/> + <P N="sp_fun_voidparen" V="5" E="1"/> + <P N="sp_enum_comma" V="2" E="1"/> + <P N="sp_enum_equals" V="3" E="1"/> + <P N="sp_cppcast_lt" V="5" E="1"/> + <P N="sp_while_lbrace" V="1" E="1"/> + <P N="sp_switch_lbrace" V="1" E="1"/> + <P N="sp_op_logical" V="3" E="1"/> + <P N="sp_for_semicolon" V="2" E="1"/> + <P N="st_nl_fn" V="4" E="0"/> + <P N="sp_cast_padparen" V="5" E="1"/> + <P N="sp_funcall_rparen" V="5" E="1"/> + <P N="sp_funcall_lparen" V="5" E="1"/> + <P N="sp_switch_colon" V="0" E="1"/> + <P N="sp_enum_colon" V="3" E="1"/> + <P N="sp_ptr_slp" V="5" E="1"/> + <P N="sp_ptr_sa" V="5" E="1"/> + <P N="sp_ref_ia" V="4" E="1"/> + <P N="sp_tmplcall_comma" V="2" E="1"/> + <P N="sp_fun_comma" V="2" E="1"/> + <P N="sp_tmplparm_comma" V="2" E="1"/> + <P N="st_leave_declmult" V="4" E="1"/> + <P N="sp_tmplcall_lt" V="5" E="1"/> + <P N="sp_catch_lbrace" V="1" E="1"/> + <P N="sp_fun_lbrace" V="3" E="1"/> + <P N="sp_if_lbrace" V="1" E="1"/> + <P N="sp_ptr_si" V="4" E="1"/> + <P N="sp_ctlstmt_lparen" V="4" E="1"/> + <P N="sp_for_padparen" V="5" E="1"/> + <P N="sp_cast_rparen" V="5" E="1"/> + <P N="sp_switch_rparen" V="4" E="1"/> + <P N="sp_fun_colon" V="3" E="1"/> + <P N="sp_delete_lbracket" V="5" E="1"/> + <P N="sp_tmplparm_lt" V="5" E="1"/> + <P N="sp_pp_eatspace" V="4" E="0"/> + <P N="sp_op_dereference" V="0" E="1"/> + <P N="sp_struct_lbrace" V="1" E="1"/> + <P N="sp_member_arrow" V="0" E="1"/> + <P N="sp_op_prefix" V="0" E="1"/> + <P N="sp_fptr_si" V="4" E="1"/> + <P N="sp_funcall_padparen" V="5" E="1"/> + <P N="sp_while_padparen" V="5" E="1"/> + <P N="sp_while_lparen" V="4" E="1"/> + <P N="sp_fun_rparen" V="5" E="1"/> + <P N="sp_ref_alp" V="5" E="1"/> + <P N="st_leave_stmtmult" V="4" E="1"/> + <P N="sp_arrayexpr_padbracket" V="5" E="1"/> + <P N="sp_arraydecl_padbracket" V="5" E="1"/> + <P N="sp_ctlstmt_lbrace" V="3" E="1"/> + <P N="st_oneline_else" V="5" E="1"/> + <P N="st_nl_case" V="4" E="0"/> + <P N="sp_init_rbrace" V="1" E="1"/> + <P N="sp_op_addressof" V="0" E="1"/> + <P N="sp_op_postfix" V="0" E="1"/> + <P N="sp_if_lparen" V="4" E="1"/> + <P N="sp_if_padparen" V="5" E="1"/> + <P N="original_tab" V="4" E="1"/> + <P N="indent_use_tab" V="1" E="1"/> + <P N="indent_tab_custom" V="0" E="1"/> + <P N="indent_first_level" V="1" E="1"/> + <P N="indent_goto" V="0" E="1"/> + <P N="indent_extern" V="0" E="1"/> + <P N="indent_namespace" V="0" E="1"/> + <P N="align_on_equals" V="1" E="1"/> + <P N="exp_paren_align" V="8" E="1"/> + <P N="indent_preprocessing" V="0" E="1"/> + <P N="indent_in_block" V="0" E="1"/> + <P N="indent_guard" V="0" E="1"/> + <P N="indent_pp_col1" V="0" E="1"/> + <P N="brace_loc_if" V="13" E="1"/> + <P N="brace_loc_for" V="13" E="1"/> + <P N="brace_loc_while" V="13" E="1"/> + <P N="brace_loc_switch" V="13" E="1"/> + <P N="brace_loc_do" V="13" E="1"/> + <P N="brace_loc_try" V="13" E="1"/> + <P N="brace_loc_catch" V="13" E="1"/> + <P N="brace_loc_asm" V="13" E="1"/> + <P N="brace_loc_namespace" V="13" E="1"/> + <P N="brace_loc_class" V="13" E="1"/> + <P N="brace_loc_enum" V="13" E="1"/> + <P N="brace_loc_fun" V="13" E="1"/> + <P N="rm_trailing_ws" V="4" E="1"/> + <P N="rm_dup_ws" V="5" E="1"/> + <P N="respace_other" V="4" E="1"/> + <P N="comment_indent" V="4" E="1"/> + <P N="comment_col1_indent" V="5" E="1"/> + <P N="parens_return" V="18" E="1"/> + <P N="parens_throw" V="5" E="0"/> + <P N="fundecl_void" V="5" E="0"/> + <P N="fun_assoc_with_ret_type" V="4" E="1"/> + <P N="cppb_sp_fptr_padparen" V="5" E="1"/> + <P N="cppb_sp_fptr_lparen" V="4" E="1"/> + <P N="cppb_sp_fptr_rparen" V="5" E="1"/> + <P N="allow_one_line_block" V="4" E="1"/> + <P N="allow_class_one_line_block" V="4" E="1"/> + <P N="st_newline_before_else" V="4" E="1"/> + <P N="cont_indent_returntype" V="0" E="1"/> + <P N="trailing_comment_align" V="2" E="1"/> + <P N="trailing_comment_value" V="70" E="1"/> + <P N="indent_from_brace" V="0" E="1"/> + <P N="label_indent" V="1" E="1"/> + <P N="sp_ty_star_prototype" V="4" E="1"/> + <P N="sp_ty_amp_prototype" V="4" E="1"/> + <P N="sp_return_padparen" V="5" E="1"/> + <P N="sp_return_rparen" V="5" E="1"/> + <P N="sp_throw_padparen" V="5" E="1"/> + <P N="sp_throw_rparen" V="5" E="1"/> + <P N="sp_expr_lparen" V="5" E="1"/> + <P N="sp_expr_padparen" V="5" E="1"/> + <P N="sp_expr_rparen" V="5" E="1"/> + <P N="sp_disassoc_ret_type_ref" V="4" E="1"/> + <P N="sp_stmt_semicolon" V="4" E="1"/> + <P N="sp_namespace_lbrace" V="3" E="1"/> + <P N="sp_try_lbrace" V="3" E="1"/> + <P N="brace_follows_case" V="1" E="1"/> + <P N="pp_indent_with_code" V="0" E="1"/> + </profile> + <profile name="bird's Objective-C Style" lang="m"> + <P N="syntax_indent" V="4" E="1"/> + <P N="tab_indent" V="8" E="1"/> + <P N="indent_policy" V="12" E="1"/> + <P N="indent_member_access" V="0" E="1"/> + <P N="access_spec_indent" V="1" E="1"/> + <P N="member_access_relative_indent" V="0" E="1"/> + <P N="indent_case" V="1" E="1"/> + <P N="case_indent_width" V="4" E="1"/> + <P N="continuation_width" V="4" E="1"/> + <P N="funcall_param_align" V="10" E="1"/> + <P N="sp_tmpldecl_comma" V="2" E="1"/> + <P N="sp_init_comma" V="2" E="1"/> + <P N="sp_member_dotstar" V="0" E="1"/> + <P N="sp_mptr_ccs" V="5" E="1"/> + <P N="sp_delete_padbracket" V="5" E="1"/> + <P N="sp_cppcast_pad" V="5" E="1"/> + <P N="st_nl_file" V="4" E="1"/> + <P N="sp_class_lbrace" V="1" E="1"/> + <P N="st_nl_empty" V="5" E="1"/> + <P N="sp_catch_padparen" V="5" E="1"/> + <P N="sp_switch_lparen" V="4" E="1"/> + <P N="sp_ref_arp" V="5" E="1"/> + <P N="sp_member_arrowstar" V="0" E="1"/> + <P N="sp_tmpldecl_equals" V="3" E="1"/> + <P N="sp_arrayexpr_lbracket" V="5" E="1"/> + <P N="sp_tmpldecl_pad" V="5" E="1"/> + <P N="sp_tmplparm_pad" V="5" E="1"/> + <P N="sp_arraydecl_lbracket" V="5" E="1"/> + <P N="st_fundecl_nameline" V="5" E="0"/> + <P N="st_oneline_dowhile" V="4" E="1"/> + <P N="sp_op_bitwise" V="3" E="1"/> + <P N="st_oneline_catch" V="5" E="1"/> + <P N="sp_ctlstmt_rparen" V="5" E="1"/> + <P N="sp_ctlstmt_padparen" V="5" E="1"/> + <P N="st_newline_after_extern" V="4" E="1"/> + <P N="sp_for_lparen" V="4" E="1"/> + <P N="sp_funcall_voidparen" V="5" E="1"/> + <P N="sp_switch_defcolon" V="0" E="1"/> + <P N="sp_switch_padparen" V="5" E="1"/> + <P N="sp_class_colon" V="3" E="1"/> + <P N="sp_fun_padparen" V="5" E="1"/> + <P N="sp_if_rparen" V="4" E="1"/> + <P N="sp_struct_comma" V="2" E="1"/> + <P N="sp_ptr_is" V="4" E="1"/> + <P N="sp_fun_equals" V="3" E="1"/> + <P N="sp_delete_rbracket" V="4" E="1"/> + <P N="sp_op_bitand" V="3" E="1"/> + <P N="sp_op_assignment" V="3" E="1"/> + <P N="sp_ref_av" V="5" E="1"/> + <P N="sp_new_lparen" V="5" E="1"/> + <P N="sp_struct_colon" V="3" E="1"/> + <P N="sp_ptr_srp" V="5" E="1"/> + <P N="sp_for_comma" V="2" E="1"/> + <P N="sp_funcall_comma" V="2" E="1"/> + <P N="sp_class_comma" V="2" E="1"/> + <P N="sp_funcall_operator" V="0" E="1"/> + <P N="st_oneline_access" V="4" E="1"/> + <P N="sp_arrayexpr_rbracket" V="5" E="1"/> + <P N="sp_cppcast_gt" V="5" E="1"/> + <P N="sp_op_mult" V="3" E="1"/> + <P N="sp_fun_commainit" V="2" E="1"/> + <P N="sp_tmpldecl_lt" V="5" E="1"/> + <P N="sp_arraydecl_rbracket" V="5" E="1"/> + <P N="sp_for_lbrace" V="1" E="0"/> + <P N="sp_init_lbrace" V="2" E="1"/> + <P N="st_oneline_then" V="5" E="1"/> + <P N="sp_catch_lparen" V="4" E="1"/> + <P N="sp_fun_operator" V="0" E="1"/> + <P N="sp_ptr_ss" V="5" E="1"/> + <P N="sp_member_dot" V="0" E="1"/> + <P N="sp_tmplcall_pad" V="5" E="1"/> + <P N="sp_enum_lbrace" V="1" E="1"/> + <P N="sp_ptr_sv" V="5" E="1"/> + <P N="sp_for_rparen" V="4" E="1"/> + <P N="sp_while_rparen" V="4" E="1"/> + <P N="sp_ret_parexpr" V="4" E="1"/> + <P N="sp_throw_parexpr" V="4" E="1"/> + <P N="st_nl_class" V="5" E="0"/> + <P N="st_oneline_statement" V="5" E="1"/> + <P N="sp_union_lbrace" V="1" E="1"/> + <P N="st_oneline_elsif" V="4" E="1"/> + <P N="sp_op_unary" V="0" E="1"/> + <P N="sp_op_binary" V="3" E="1"/> + <P N="sp_new_rparen" V="4" E="1"/> + <P N="sp_new_padparen" V="5" E="1"/> + <P N="sp_cast_lparen" V="5" E="1"/> + <P N="sp_op_comparison" V="3" E="1"/> + <P N="sp_catch_rparen" V="4" E="1"/> + <P N="sp_fun_lparen" V="5" E="1"/> + <P N="sp_fun_voidparen" V="5" E="1"/> + <P N="sp_enum_comma" V="2" E="1"/> + <P N="sp_enum_equals" V="3" E="1"/> + <P N="sp_cppcast_lt" V="5" E="1"/> + <P N="sp_while_lbrace" V="1" E="1"/> + <P N="sp_switch_lbrace" V="1" E="1"/> + <P N="sp_op_logical" V="3" E="1"/> + <P N="sp_for_semicolon" V="2" E="1"/> + <P N="st_nl_fn" V="4" E="0"/> + <P N="sp_cast_padparen" V="5" E="1"/> + <P N="sp_funcall_rparen" V="5" E="1"/> + <P N="sp_funcall_lparen" V="5" E="1"/> + <P N="sp_switch_colon" V="0" E="1"/> + <P N="sp_enum_colon" V="3" E="1"/> + <P N="sp_ptr_slp" V="5" E="1"/> + <P N="sp_ptr_sa" V="5" E="1"/> + <P N="sp_ref_ia" V="4" E="1"/> + <P N="sp_tmplcall_comma" V="2" E="1"/> + <P N="sp_fun_comma" V="2" E="1"/> + <P N="sp_tmplparm_comma" V="2" E="1"/> + <P N="st_leave_declmult" V="4" E="1"/> + <P N="sp_tmplcall_lt" V="5" E="1"/> + <P N="sp_catch_lbrace" V="1" E="1"/> + <P N="sp_fun_lbrace" V="3" E="1"/> + <P N="sp_if_lbrace" V="1" E="1"/> + <P N="sp_ptr_si" V="4" E="1"/> + <P N="sp_ctlstmt_lparen" V="4" E="1"/> + <P N="sp_for_padparen" V="5" E="1"/> + <P N="sp_cast_rparen" V="5" E="1"/> + <P N="sp_switch_rparen" V="4" E="1"/> + <P N="sp_fun_colon" V="3" E="1"/> + <P N="sp_delete_lbracket" V="5" E="1"/> + <P N="sp_tmplparm_lt" V="5" E="1"/> + <P N="sp_pp_eatspace" V="4" E="0"/> + <P N="sp_op_dereference" V="0" E="1"/> + <P N="sp_struct_lbrace" V="1" E="1"/> + <P N="sp_member_arrow" V="0" E="1"/> + <P N="sp_op_prefix" V="0" E="1"/> + <P N="sp_fptr_si" V="4" E="1"/> + <P N="sp_funcall_padparen" V="5" E="1"/> + <P N="sp_while_padparen" V="5" E="1"/> + <P N="sp_while_lparen" V="4" E="1"/> + <P N="sp_fun_rparen" V="5" E="1"/> + <P N="sp_ref_alp" V="5" E="1"/> + <P N="st_leave_stmtmult" V="4" E="1"/> + <P N="sp_arrayexpr_padbracket" V="5" E="1"/> + <P N="sp_arraydecl_padbracket" V="5" E="1"/> + <P N="sp_ctlstmt_lbrace" V="3" E="1"/> + <P N="st_oneline_else" V="5" E="1"/> + <P N="st_nl_case" V="4" E="0"/> + <P N="sp_init_rbrace" V="1" E="1"/> + <P N="sp_op_addressof" V="0" E="1"/> + <P N="sp_op_postfix" V="0" E="1"/> + <P N="sp_if_lparen" V="4" E="1"/> + <P N="sp_if_padparen" V="5" E="1"/> + <P N="original_tab" V="4" E="1"/> + <P N="indent_use_tab" V="1" E="1"/> + <P N="indent_tab_custom" V="0" E="1"/> + <P N="indent_first_level" V="1" E="1"/> + <P N="indent_goto" V="0" E="1"/> + <P N="indent_extern" V="0" E="1"/> + <P N="indent_namespace" V="0" E="1"/> + <P N="align_on_equals" V="1" E="1"/> + <P N="exp_paren_align" V="8" E="1"/> + <P N="indent_preprocessing" V="0" E="1"/> + <P N="indent_in_block" V="0" E="1"/> + <P N="indent_guard" V="0" E="1"/> + <P N="indent_pp_col1" V="0" E="1"/> + <P N="brace_loc_if" V="13" E="1"/> + <P N="brace_loc_for" V="13" E="1"/> + <P N="brace_loc_while" V="13" E="1"/> + <P N="brace_loc_switch" V="13" E="1"/> + <P N="brace_loc_do" V="13" E="1"/> + <P N="brace_loc_try" V="13" E="1"/> + <P N="brace_loc_catch" V="13" E="1"/> + <P N="brace_loc_asm" V="13" E="1"/> + <P N="brace_loc_namespace" V="13" E="1"/> + <P N="brace_loc_class" V="13" E="1"/> + <P N="brace_loc_enum" V="13" E="1"/> + <P N="brace_loc_fun" V="13" E="1"/> + <P N="rm_trailing_ws" V="4" E="1"/> + <P N="rm_dup_ws" V="5" E="1"/> + <P N="respace_other" V="4" E="1"/> + <P N="comment_indent" V="4" E="1"/> + <P N="comment_col1_indent" V="5" E="1"/> + <P N="parens_return" V="18" E="1"/> + <P N="parens_throw" V="5" E="0"/> + <P N="fundecl_void" V="5" E="0"/> + <P N="fun_assoc_with_ret_type" V="4" E="1"/> + <P N="cppb_sp_fptr_padparen" V="5" E="1"/> + <P N="cppb_sp_fptr_lparen" V="4" E="1"/> + <P N="cppb_sp_fptr_rparen" V="5" E="1"/> + <P N="allow_one_line_block" V="4" E="1"/> + <P N="allow_class_one_line_block" V="4" E="1"/> + <P N="st_newline_before_else" V="4" E="1"/> + <P N="cont_indent_returntype" V="0" E="1"/> + <P N="trailing_comment_align" V="2" E="1"/> + <P N="trailing_comment_value" V="70" E="1"/> + <P N="indent_from_brace" V="0" E="1"/> + <P N="label_indent" V="1" E="1"/> + <P N="sp_ty_star_prototype" V="4" E="1"/> + <P N="sp_ty_amp_prototype" V="4" E="1"/> + <P N="sp_return_padparen" V="5" E="1"/> + <P N="sp_return_rparen" V="5" E="1"/> + <P N="sp_throw_padparen" V="5" E="1"/> + <P N="sp_throw_rparen" V="5" E="1"/> + <P N="sp_expr_lparen" V="5" E="1"/> + <P N="sp_expr_padparen" V="5" E="1"/> + <P N="sp_expr_rparen" V="5" E="1"/> + <P N="sp_disassoc_ret_type_ref" V="4" E="1"/> + <P N="sp_stmt_semicolon" V="4" E="1"/> + <P N="sp_namespace_lbrace" V="3" E="1"/> + <P N="sp_try_lbrace" V="3" E="1"/> + <P N="brace_follows_case" V="1" E="1"/> + <P N="pp_indent_with_code" V="0" E="1"/> + <P N="meth_decl_align" V="19" E="1"/> + <P N="meth_call_align" V="19" E="1"/> + <P N="category_padparen" V="5" E="1"/> + <P N="category_lparen" V="4" E="1"/> + <P N="category_rparen" V="4" E="1"/> + <P N="sp_decl_selector_colon" V="2" E="1"/> + <P N="sp_call_selector_colon" V="2" E="1"/> + <P N="protocol_padparen" V="5" E="1"/> + <P N="protocol_lparen" V="4" E="1"/> + <P N="protocol_rparen" V="4" E="1"/> + <P N="protocol_comma" V="2" E="1"/> + <P N="meth_call_bracket_align" V="8" E="1"/> + <P N="meth_call_selalign_force" V="1" E="1"/> + <P N="prop_padparen" V="5" E="1"/> + <P N="prop_lparen" V="4" E="1"/> + <P N="prop_rparen" V="4" E="1"/> + <P N="prop_comma" V="2" E="1"/> + <P N="synth_comma" V="2" E="1"/> + <P N="synth_eq" V="0" E="1"/> + <P N="dynamic_comma" V="2" E="1"/> + <P N="meth_return_lparen" V="4" E="1"/> + <P N="meth_return_padparen" V="5" E="1"/> + <P N="meth_return_rparen" V="5" E="1"/> + <P N="meth_param_lparen" V="5" E="1"/> + <P N="meth_param_padparen" V="5" E="1"/> + <P N="meth_param_rparen" V="5" E="1"/> + <P N="block_initial_indent" V="4" E="1"/> + <P N="finally_lbrace" V="3" E="1"/> + <P N="synchronized_lparen" V="5" E="1"/> + <P N="synchronized_padparen" V="5" E="1"/> + <P N="synchronized_rparen" V="5" E="1"/> + <P N="synchronized_lbrace" V="3" E="1"/> + <P N="prop_eq" V="0" E="1"/> + </profile> +</profiles> diff --git a/kBuild/doc/QuickReference-kmk.html b/kBuild/doc/QuickReference-kmk.html index 3f56877..b6241b5 100644 --- a/kBuild/doc/QuickReference-kmk.html +++ b/kBuild/doc/QuickReference-kmk.html @@ -10,7 +10,7 @@ /* :Author: David Goodger :Contact: goodger@users.sourceforge.net -:Date: $Date: 2009-04-18 14:05:47 +0200 (Sa, 18 Apr 2009) $ +:Date: $Date: 2009-04-18 08:05:47 -0400 (Sat, 18 Apr 2009) $ :Revision: $Revision: 2340 $ :Copyright: This stylesheet has been placed in the public domain. diff --git a/kBuild/header.kmk b/kBuild/header.kmk index a4f51f3..852c1a6 100644 --- a/kBuild/header.kmk +++ b/kBuild/header.kmk @@ -1,4 +1,4 @@ -# $Id: header.kmk 2577 2012-06-04 11:01:00Z bird $ +# $Id: header.kmk 2689 2013-07-11 21:31:43Z bird $ ## @file # kBuild - File included at top of a makefile. # @@ -79,7 +79,7 @@ endif # The revision in which this file was last modified. # This can be useful when using development versions of kBuild. # -KMK_REVISION := $(patsubst %:,, $Rev: 2577 $ ) +KMK_REVISION := $(patsubst %:,, $Rev: 2689 $ ) # @@ -1276,10 +1276,17 @@ else if1of ($(KBUILD_TARGET), freebsd netbsd openbsd dragonfly) KBUILD_LIB_SEARCH_SUBS := lib/ else ifeq ($(KBUILD_TARGET),linux) - KBUILD_LIB_SEARCH_ROOTS := \ - / \ - /usr/ \ - /usr/local/ + ifeq ($(realpath /bin),/usr/bin) + KBUILD_LIB_SEARCH_ROOTS := \ + /usr/ \ + / \ + /usr/local/ + else + KBUILD_LIB_SEARCH_ROOTS := \ + / \ + /usr/ \ + /usr/local/ + endif ifeq ($(KBUILD_TARGET_ARCH),amd64) KBUILD_LIB_SEARCH_SUBS := \ lib/x86_64-linux-gnu/ \ @@ -1562,6 +1569,6 @@ endif # end-of-file-content __header_kmk__ := 1 -endif # __header_kmk__ +endif # !__header_kmk__ diff --git a/kBuild/sdks/ReorderCompilerIncs.kmk b/kBuild/sdks/ReorderCompilerIncs.kmk new file mode 100644 index 0000000..bf7aca5 --- /dev/null +++ b/kBuild/sdks/ReorderCompilerIncs.kmk @@ -0,0 +1,63 @@ +# $Id: ReorderCompilerIncs.kmk 2603 2012-07-12 20:26:28Z bird $ +## @file +# kBuild SDK - Pseudo SDK that inserts the compiler includes a bit earlier. +# +# Note! This SDK is using a number of internal kBuild variables as well as +# making assumptions about expansion order and location. +# Please, do NOT attempt anything like this in your own SDKs!! +# + +# +# Copyright (c) 2006-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# +# This file is part of kBuild. +# +# kBuild is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# kBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kBuild; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# As a special exception you are granted permission to include this file, via +# the kmk include directive, as you wish without this in itself causing the +# resulting makefile, program or whatever to be covered by the GPL license. +# This exception does not however invalidate any other reasons why the makefile, +# program, whatever should not be covered the GPL. +# +# + +SDK_ReorderCompilerIncs := Pseudo SDK that inserts the compiler includes a bit earlier. + +FN_SDK_ReorderCompilerIncs_GET_INCS = \ + $(TOOL_$(tool)_$(1)INCS.$(2).$(3).$(5)) \ + $(TOOL_$(tool)_$(1)INCS.$(2).$(3)) \ + $(TOOL_$(tool)_$(1)INCS.$(2).$(5)) \ + $(TOOL_$(tool)_$(1)INCS.$(4)) \ + $(TOOL_$(tool)_$(1)INCS.$(3)) \ + $(TOOL_$(tool)_$(1)INCS.$(2)) \ + $(TOOL_$(tool)_$(1)INCS.$(5)) \ + $(TOOL_$(tool)_$(1)INCS) \ + $(TOOL_$(tool)_INCS.$(2).$(3).$(5)) \ + $(TOOL_$(tool)_INCS.$(2).$(3)) \ + $(TOOL_$(tool)_INCS.$(2).$(5)) \ + $(TOOL_$(tool)_INCS.$(4)) \ + $(TOOL_$(tool)_INCS.$(3)) \ + $(TOOL_$(tool)_INCS.$(2)) \ + $(TOOL_$(tool)_INCS.$(5)) \ + $(TOOL_$(tool)_INCS) \ + +$(foreach os,$(KBUILD_OSES),$(foreach arch,$(KBUILD_ARCHES),$(foreach cat,$(KBUILD_COMPILE_CATEGTORIES) \ + ,$(eval SDK_ReorderCompilerIncs_$(cat)INCS.$(os).$(arch) = \ + $$(call FN_SDK_ReorderCompilerIncs_GET_INCS,CXX,win,amd64,$$(bld_trg_cpu),$$(bld_type))\ + )\ +))) + diff --git a/kBuild/sdks/WINDDK71.kmk b/kBuild/sdks/WINDDK71.kmk new file mode 100644 index 0000000..92f0f6c --- /dev/null +++ b/kBuild/sdks/WINDDK71.kmk @@ -0,0 +1,107 @@ +# $Id: WINDDK71.kmk 2602 2012-07-12 20:21:45Z bird $ +## @file +# kBuild SDK - The Microsoft Windows 7 DDK, v7.1. +# Defaults to $(KBUILD_TARGET_ARCH). Base SDK. +# + +# +# Copyright (c) 2006-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# +# This file is part of kBuild. +# +# kBuild is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# kBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kBuild; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# As a special exception you are granted permission to include this file, via +# the kmk include directive, as you wish without this in itself causing the +# resulting makefile, program or whatever to be covered by the GPL license. +# This exception does not however invalidate any other reasons why the makefile, +# program, whatever should not be covered the GPL. +# +# + +SDK_WINDDK71 := The Microsoft Windows 7 DDK, v7.1. \ + Defaults to $(KBUILD_TARGET_ARCH). Base SDK. + +# SDK Specific Properties +ifndef PATH_SDK_WINDDK71 + PATH_SDK_WINDDK71 := $(wildcard $(PATH_DEVTOOLS_TRG)/ddk/7600.16385.1*) + ifeq ($(PATH_SDK_WINDDK71),) + PATH_SDK_WINDDK71 := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddk/7600.16385.1*) + endif + ifeq ($(PATH_SDK_WINDDK71),) + PATH_SDK_WINDDK71 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/ddk/7600.16385.1*) + endif + ifeq ($(PATH_SDK_WINDDK71),) + ifeq ($(KBUILD_HOST),win) + PATH_SDK_WINDDK71 := $(wildcard C:/WinDDK/7600.16385.1*) + endif + endif + ifneq ($(PATH_SDK_WINDDK71),) + PATH_SDK_WINDDK71 := $(lastword $(sort $(PATH_SDK_WINDDK71))) + else + $(warning kBuild: PATH_SDK_WINDDK71 couldn't be determined!) + PATH_SDK_WINDDK71 := $(PATH_DEVTOOLS)/win.x86/ddk/7600.16385.1-not-found + endif +else + # Resolve any fancy stuff once and for all. + PATH_SDK_WINDDK71 := $(PATH_SDK_WINDDK71) +endif + +PATH_SDK_WINDDK71_INC ?= $(PATH_SDK_WINDDK71)/inc +PATH_SDK_WINDDK71_INC_API ?= $(PATH_SDK_WINDDK71_INC)/api +PATH_SDK_WINDDK71_INC_CRT ?= $(PATH_SDK_WINDDK71_INC)/crt +PATH_SDK_WINDDK71_INC_DDK ?= $(PATH_SDK_WINDDK71_INC)/ddk + +PATH_SDK_WINDDK71_LIB_ROOT ?= $(PATH_SDK_WINDDK71)/lib +PATH_SDK_WINDDK71_LIB_WLH_ROOT ?= $(PATH_SDK_WINDDK71_LIB_ROOT)/wlh +PATH_SDK_WINDDK71_LIB_WNET_ROOT ?= $(PATH_SDK_WINDDK71_LIB_ROOT)/wnet +PATH_SDK_WINDDK71_LIB_WXP_ROOT ?= $(PATH_SDK_WINDDK71_LIB_ROOT)/wxp +PATH_SDK_WINDDK71_LIB_W2K_ROOT ?= $(PATH_SDK_WINDDK71_LIB_ROOT)/w2k +PATH_SDK_WINDDK71_LIB_WDF_ROOT ?= $(PATH_SDK_WINDDK71_LIB_ROOT)/w2k + +PATH_SDK_WINDDK71_LIB_WLH.amd64 ?= $(PATH_SDK_WINDDK71_LIB_WLH_ROOT)/amd64 +PATH_SDK_WINDDK71_LIB_WLH.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WLH_ROOT)/ia64 +PATH_SDK_WINDDK71_LIB_WLH.x86 ?= $(PATH_SDK_WINDDK71_LIB_WLH_ROOT)/i386 +PATH_SDK_WINDDK71_LIB_WLH ?= $(PATH_SDK_WINDDK71_LIB_WLH.$(KBUILD_TARGET_ARCH)) + +PATH_SDK_WINDDK71_LIB_WNET.amd64?= $(PATH_SDK_WINDDK71_LIB_WNET_ROOT)/amd64 +PATH_SDK_WINDDK71_LIB_WNET.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WNET_ROOT)/ia64 +PATH_SDK_WINDDK71_LIB_WNET.x86 ?= $(PATH_SDK_WINDDK71_LIB_WNET_ROOT)/i386 +PATH_SDK_WINDDK71_LIB_WNET ?= $(PATH_SDK_WINDDK71_LIB_WNET.$(KBUILD_TARGET_ARCH)) + +PATH_SDK_WINDDK71_LIB_WXP.x86 ?= $(PATH_SDK_WINDDK71_LIB_WXP_ROOT)/i386 +PATH_SDK_WINDDK71_LIB_WXP ?= $(PATH_SDK_WINDDK71_LIB_WXP.$(KBUILD_TARGET_ARCH)) + +PATH_SDK_WINDDK71_LIB_W2K.x86 ?= $(PATH_SDK_WINDDK71_LIB_W2K_ROOT)/i386 +PATH_SDK_WINDDK71_LIB_W2K ?= $(PATH_SDK_WINDDK71_LIB_W2K.$(KBUILD_TARGET_ARCH)) + +PATH_SDK_WINDDK71_LIB.amd64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.amd64) +PATH_SDK_WINDDK71_LIB.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.ia64) +PATH_SDK_WINDDK71_LIB.x86 ?= $(PATH_SDK_WINDDK71_LIB_WLH.x86) +PATH_SDK_WINDDK71_LIB ?= $(PATH_SDK_WINDDK71_LIB.$(KBUILD_TARGET_ARCH)) + +# General Properties used by kBuild +SDK_WINDDK71_DEFS.amd64 ?= _AMD64_ AMD64 _WIN64 +SDK_WINDDK71_DEFS.ia64 ?= _IA64_=1 IA64=1 _WIN64 _MSC_EXTENSIONS +SDK_WINDDK71_DEFS.x86 ?= _X86_=1 i386=1 STD_CALL +SDK_WINDDK71_INCS ?= \ + $(PATH_SDK_WINDDK71_INC_API) \ + $(PATH_SDK_WINDDK71_INC_DDK) +# The compiler tool(s) will have to select the appropriate crt includes. +SDK_WINDDK71_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.amd64) +SDK_WINDDK71_LIBPATH.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.ia64) +SDK_WINDDK71_LIBPATH.x86 ?= $(PATH_SDK_WINDDK71_LIB_WLH.x86) + diff --git a/kBuild/sdks/WINDDK71WLH.kmk b/kBuild/sdks/WINDDK71WLH.kmk new file mode 100644 index 0000000..3b7e452 --- /dev/null +++ b/kBuild/sdks/WINDDK71WLH.kmk @@ -0,0 +1,47 @@ +# $Id: WINDDK71WLH.kmk 2602 2012-07-12 20:21:45Z bird $ +## @file +# kBuild SDK - The Microsoft Windows 7 DDKs, v7.1, Targeting Vista and 2008 (KBUILD_TARGET_ARCH). +# + +# +# Copyright (c) 2006-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# +# This file is part of kBuild. +# +# kBuild is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# kBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kBuild; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# As a special exception you are granted permission to include this file, via +# the kmk include directive, as you wish without this in itself causing the +# resulting makefile, program or whatever to be covered by the GPL license. +# This exception does not however invalidate any other reasons why the makefile, +# program, whatever should not be covered the GPL. +# +# + +SDK_WINDDK71WLH := The Microsoft Windows 7 DDKs, v7.1, Targeting Vista and 2008 (KBUILD_TARGET_ARCH). +SDK_WINDDK71WLH_EXTENDS = WINDDK71 +SDK_WINDDK71WLH_DEFS ?= WIN32=100 _WIN32_WINNT=0x0600 WINVER=0x0600 _WIN32_IE=0x0700 NTDDI_VERSION=0x06000000 KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 +SDK_WINDDK71WLH_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.amd64) +SDK_WINDDK71WLH_LIBPATH.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.ia64) +SDK_WINDDK71WLH_LIBPATH.x86 ?= $(PATH_SDK_WINDDK71_LIB_WLH.x86) + +# SDK Specific Properties. +# Note! extends the WINDDK71 sdk, so use those variables where ever possible +PATH_SDK_WINDDK71WLH_LIB.amd64?= $(PATH_SDK_WINDDK71_LIB_WLH.amd64) +PATH_SDK_WINDDK71WLH_LIB.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WLH.ia64) +PATH_SDK_WINDDK71WLH_LIB.x86 ?= $(PATH_SDK_WINDDK71_LIB_WLH.x86) +PATH_SDK_WINDDK71WLH_LIB ?= $(PATH_SDK_WINDDK71WLH_LIB.$(KBUILD_TARGET_ARCH)) + diff --git a/kBuild/sdks/WINDDK71WNET.kmk b/kBuild/sdks/WINDDK71WNET.kmk new file mode 100644 index 0000000..df02cab --- /dev/null +++ b/kBuild/sdks/WINDDK71WNET.kmk @@ -0,0 +1,47 @@ +# $Id: WINDDK71WNET.kmk 2602 2012-07-12 20:21:45Z bird $ +## @file +# kBuild SDK - The Microsoft Windows 7 DDKs, v7.1, Targeting Windows Server 2003 (KBUILD_TARGET_ARCH). +# + +# +# Copyright (c) 2006-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# +# This file is part of kBuild. +# +# kBuild is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# kBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kBuild; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# As a special exception you are granted permission to include this file, via +# the kmk include directive, as you wish without this in itself causing the +# resulting makefile, program or whatever to be covered by the GPL license. +# This exception does not however invalidate any other reasons why the makefile, +# program, whatever should not be covered the GPL. +# +# + +SDK_WINDDK71WNET := The Microsoft Windows 7 DDKs, v7.1, Targeting Windows Server 2003 (KBUILD_TARGET_ARCH). +SDK_WINDDK71WNET_EXTENDS = WINDDK71 +SDK_WINDDK71WNET_DEFS ?= WIN32=100 _WIN32_WINNT=0x0502 WINVER=0x0502 _WIN32_IE=0x0603 NTDDI_VERSION=0x05020100 +SDK_WINDDK71WNET_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK71_LIB_WNET.amd64) +SDK_WINDDK71WNET_LIBPATH.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WNET.ia64) +SDK_WINDDK71WNET_LIBPATH.x86 ?= $(PATH_SDK_WINDDK71_LIB_WNET.x86) + +# SDK Specific Properties. +# Note! extends the WINDDK71 sdk, so use those variables where ever possible +PATH_SDK_WINDDK71WNET_LIB.amd64?= $(PATH_SDK_WINDDK71_LIB_WNET.amd64) +PATH_SDK_WINDDK71WNET_LIB.ia64 ?= $(PATH_SDK_WINDDK71_LIB_WNET.ia64) +PATH_SDK_WINDDK71WNET_LIB.x86 ?= $(PATH_SDK_WINDDK71_LIB_WNET.x86) +PATH_SDK_WINDDK71WNET_LIB ?= $(PATH_SDK_WINDDK71WNET_LIB.$(KBUILD_TARGET_ARCH)) + diff --git a/kBuild/sdks/WINDDK71WXP.kmk b/kBuild/sdks/WINDDK71WXP.kmk new file mode 100644 index 0000000..42a4f73 --- /dev/null +++ b/kBuild/sdks/WINDDK71WXP.kmk @@ -0,0 +1,43 @@ +# $Id: WINDDK71WXP.kmk 2602 2012-07-12 20:21:45Z bird $ +## @file +# kBuild SDK - The Microsoft Windows 7 DDK, v7.1, Targeting Windows XP (x86). +# + +# +# Copyright (c) 2006-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# +# This file is part of kBuild. +# +# kBuild is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# kBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kBuild; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# As a special exception you are granted permission to include this file, via +# the kmk include directive, as you wish without this in itself causing the +# resulting makefile, program or whatever to be covered by the GPL license. +# This exception does not however invalidate any other reasons why the makefile, +# program, whatever should not be covered the GPL. +# +# + +SDK_WINDDK71WXP := The Microsoft Windows 7 DDK, v7.1, Targeting Windows XP (x86). +SDK_WINDDK71WXP_EXTENDS = WINDDK71 +SDK_WINDDK71WXP_DEFS ?= WIN32=100 _WIN32_WINNT=0x0501 WINVER=0x0501 _WIN32_IE=0x0603 NTDDI_VERSION=0x05010200 +SDK_WINDDK71WXP_LIBPATH.x86 ?= $(PATH_SDK_WINDDK71_LIB_WXP.x86) + +# SDK Specific Properties. +# Note! extends the WINDDK71 sdk, so use those variables where ever possible +PATH_SDK_WINDDK71WXP_LIB.x86 ?= $(PATH_SDK_WINDDK71_LIB_WXP.x86) +PATH_SDK_WINDDK71WXP_LIB ?= $(PATH_SDK_WINDDK71WXP_LIB.x86) + diff --git a/kBuild/sdks/WINDDK80.kmk b/kBuild/sdks/WINDDK80.kmk new file mode 100644 index 0000000..69acd16 --- /dev/null +++ b/kBuild/sdks/WINDDK80.kmk @@ -0,0 +1,98 @@ +# $Id: WINDDK80.kmk 2607 2012-07-20 12:12:58Z bird $ +## @file +# kBuild SDK - The Microsoft Windows 8 DDK. +# Defaults to $(KBUILD_TARGET_ARCH). Base SDK. +# + +# +# Copyright (c) 2006-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# +# This file is part of kBuild. +# +# kBuild is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# kBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kBuild; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# As a special exception you are granted permission to include this file, via +# the kmk include directive, as you wish without this in itself causing the +# resulting makefile, program or whatever to be covered by the GPL license. +# This exception does not however invalidate any other reasons why the makefile, +# program, whatever should not be covered the GPL. +# +# + +SDK_WINDDK80 := The Microsoft Windows 8 DDK. \ + Defaults to $(KBUILD_TARGET_ARCH). Base SDK. + +# SDK Specific Properties +ifndef PATH_SDK_WINDDK80 + PATH_SDK_WINDDK80 := $(wildcard $(PATH_DEVTOOLS_TRG)/ddk/v8*) + ifeq ($(PATH_SDK_WINDDK80),) + PATH_SDK_WINDDK80 := $(wildcard $(PATH_DEVTOOLS)/win.x86/ddk/v8*) + endif + ifeq ($(PATH_SDK_WINDDK80),) + PATH_SDK_WINDDK80 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/ddk/v8*) + endif + ifneq ($(PATH_SDK_WINDDK80),) + PATH_SDK_WINDDK80 := $(lastword $(sort $(PATH_SDK_WINDDK80))) + else + $(warning kBuild: PATH_SDK_WINDDK80 couldn't be determined!) + PATH_SDK_WINDDK80 := $(PATH_DEVTOOLS)/win.x86/ddk/v8.0/not/found + endif +else + # Resolve any fancy stuff once and for all. + PATH_SDK_WINDDK80 := $(PATH_SDK_WINDDK80) +endif + +PATH_SDK_WINDDK80_INC ?= $(PATH_SDK_WINDDK80)/Include +PATH_SDK_WINDDK80_INC_UM ?= $(PATH_SDK_WINDDK80_INC)/um +PATH_SDK_WINDDK80_INC_KM ?= $(PATH_SDK_WINDDK80_INC)/km +PATH_SDK_WINDDK80_INC_KM_CRT ?= $(PATH_SDK_WINDDK80_INC_KM)/crt +PATH_SDK_WINDDK80_INC_SHARED ?= $(PATH_SDK_WINDDK80_INC)/Shared + +PATH_SDK_WINDDK80_LIB_ROOT ?= $(PATH_SDK_WINDDK80)/Lib +PATH_SDK_WINDDK80_LIB_W8_ROOT ?= $(PATH_SDK_WINDDK80_LIB_ROOT)/win8 +PATH_SDK_WINDDK80_LIB_W7_ROOT ?= $(PATH_SDK_WINDDK80_LIB_ROOT)/win7 +PATH_SDK_WINDDK80_LIB_WLH_ROOT ?= $(PATH_SDK_WINDDK80_LIB_ROOT)/wlh +PATH_SDK_WINDDK80_LIB_WDF_ROOT ?= $(PATH_SDK_WINDDK80_LIB_ROOT)/wdf +PATH_SDK_WINDDK80_LIB_MFC_ROOT ?= $(PATH_SDK_WINDDK80_LIB_ROOT)/Mfc +PATH_SDK_WINDDK80_LIB_ATL_ROOT ?= $(PATH_SDK_WINDDK80_LIB_ROOT)/Atl + +PATH_SDK_WINDDK80_LIB_W8.amd64 ?= $(PATH_SDK_WINDDK80_LIB_W8_ROOT)/km/x64 +PATH_SDK_WINDDK80_LIB_W8.x86 ?= $(PATH_SDK_WINDDK80_LIB_W8_ROOT)/km/x86 +PATH_SDK_WINDDK80_LIB_W8 ?= $(PATH_SDK_WINDDK80_LIB_W8.$(KBUILD_TARGET_ARCH)) + +PATH_SDK_WINDDK80_LIB_W7.amd64 ?= $(PATH_SDK_WINDDK80_LIB_W7_ROOT)/km/x64 +PATH_SDK_WINDDK80_LIB_W7.x86 ?= $(PATH_SDK_WINDDK80_LIB_W7_ROOT)/km/x86 +PATH_SDK_WINDDK80_LIB_W7 ?= $(PATH_SDK_WINDDK80_LIB_W7.$(KBUILD_TARGET_ARCH)) + +PATH_SDK_WINDDK80_LIB_WLH.amd64 ?= $(PATH_SDK_WINDDK80_LIB_WLH_ROOT)/km/x64 +PATH_SDK_WINDDK80_LIB_WLH.x86 ?= $(PATH_SDK_WINDDK80_LIB_WLH_ROOT)/km/x86 +PATH_SDK_WINDDK80_LIB_WLH ?= $(PATH_SDK_WINDDK80_LIB_WLH.$(KBUILD_TARGET_ARCH)) + +PATH_SDK_WINDDK80_LIB.amd64 ?= $(PATH_SDK_WINDDK80_LIB_WLH.amd64) +PATH_SDK_WINDDK80_LIB.x86 ?= $(PATH_SDK_WINDDK80_LIB_WLH.x86) +PATH_SDK_WINDDK80_LIB ?= $(PATH_SDK_WINDDK80_LIB.$(KBUILD_TARGET_ARCH)) + +# General Properties used by kBuild +SDK_WINDDK80_DEFS.amd64 ?= _AMD64_ AMD64 _WIN64 +SDK_WINDDK80_DEFS.x86 ?= _X86_=1 i386=1 STD_CALL +SDK_WINDDK80_INCS ?= \ + $(PATH_SDK_WINDDK80_INC_KM) \ + $(PATH_SDK_WINDDK80_INC_UM) \ + $(PATH_SDK_WINDDK80_INC_SHARED) \ +# The compiler tool(s) will have to select the appropriate crt includes. +SDK_WINDDK80_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK80_LIB_WLH.amd64) +SDK_WINDDK80_LIBPATH.x86 ?= $(PATH_SDK_WINDDK80_LIB_WLH.x86) + diff --git a/kBuild/sdks/WINDDK80W8.kmk b/kBuild/sdks/WINDDK80W8.kmk new file mode 100644 index 0000000..24e48f8 --- /dev/null +++ b/kBuild/sdks/WINDDK80W8.kmk @@ -0,0 +1,46 @@ +# $Id: WINDDK80W8.kmk 2607 2012-07-20 12:12:58Z bird $ +## @file +# kBuild SDK - The Microsoft Windows 8 DDKs, Targeting Windows 8 (KBUILD_TARGET_ARCH). +# + +# +# Copyright (c) 2006-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# +# This file is part of kBuild. +# +# kBuild is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# kBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kBuild; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# As a special exception you are granted permission to include this file, via +# the kmk include directive, as you wish without this in itself causing the +# resulting makefile, program or whatever to be covered by the GPL license. +# This exception does not however invalidate any other reasons why the makefile, +# program, whatever should not be covered the GPL. +# +# + +SDK_WINDDK80W8 := The Microsoft Windows 8 DDKs, Targeting Windows 8 (KBUILD_TARGET_ARCH). +SDK_WINDDK80W8_EXTENDS = WINDDK80 +SDK_WINDDK80W8_DEFS ?= WIN32=100 _WIN32_WINNT=0x0602 WINVER=0x0602 _WIN32_IE=0x0A00 NTDDI_VERSION=0x06020000 \ + KMDF_MAJOR_VERSION=01 KMDF_MINOR_VERSION=005 +SDK_WINDDK80W8_LIBPATH.amd64 ?= $(PATH_SDK_WINDDK80_LIB_W8.amd64) +SDK_WINDDK80W8_LIBPATH.x86 ?= $(PATH_SDK_WINDDK80_LIB_W8.x86) + +# SDK Specific Properties. +# Note! extends the WINDDK80 sdk, so use those variables where ever possible +PATH_SDK_WINDDK80W8_LIB.amd64?= $(PATH_SDK_WINDDK80_LIB_W8.amd64) +PATH_SDK_WINDDK80W8_LIB.x86 ?= $(PATH_SDK_WINDDK80_LIB_W8.x86) +PATH_SDK_WINDDK80W8_LIB ?= $(PATH_SDK_WINDDK80W8_LIB.$(KBUILD_TARGET_ARCH)) + diff --git a/kBuild/sdks/WINPSDK.kmk b/kBuild/sdks/WINPSDK.kmk index 21ef6f6..e357676 100644 --- a/kBuild/sdks/WINPSDK.kmk +++ b/kBuild/sdks/WINPSDK.kmk @@ -1,10 +1,10 @@ -# $Id: WINPSDK.kmk 2430 2010-11-16 15:26:34Z bird $ +# $Id: WINPSDK.kmk 2602 2012-07-12 20:21:45Z bird $ ## @file # kBuild SDK - The Windows Platform SDK, targeting (KBUILD_TARGET). # # -# Copyright (c) 2006-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# Copyright (c) 2006-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> # # This file is part of kBuild. # @@ -43,9 +43,6 @@ ifndef PATH_SDK_WINPSDK PATH_SDK_WINPSDK := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/2*) endif ifeq ($(PATH_SDK_WINPSDK),) - PATH_SDK_WINPSDK := $(wildcard $(PATH_DEVTOOLS)/x86.win32/sdk/2*) - endif - ifeq ($(PATH_SDK_WINPSDK),) PATH_SDK_WINPSDK := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/2*) endif ifneq ($(PATH_SDK_WINPSDK),) diff --git a/kBuild/sdks/WINPSDK71.kmk b/kBuild/sdks/WINPSDK71.kmk new file mode 100644 index 0000000..f030435 --- /dev/null +++ b/kBuild/sdks/WINPSDK71.kmk @@ -0,0 +1,161 @@ +# $Id: WINPSDK71.kmk 2602 2012-07-12 20:21:45Z bird $ +## @file +# kBuild SDK - The Windows Platform SDK v7.1, targeting (KBUILD_TARGET). +# + +# +# Copyright (c) 2006-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# +# This file is part of kBuild. +# +# kBuild is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# kBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kBuild; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# As a special exception you are granted permission to include this file, via +# the kmk include directive, as you wish without this in itself causing the +# resulting makefile, program or whatever to be covered by the GPL license. +# This exception does not however invalidate any other reasons why the makefile, +# program, whatever should not be covered the GPL. +# +# + +SDK_WINPSDK71 := The Windows Platform SDK v7.1, targeting (KBUILD_TARGET). + +# SDK Specific Properties +ifndef PATH_SDK_WINPSDK71 + PATH_SDK_WINPSDK71 := $(wildcard $(PATH_DEVTOOLS_BLD)/sdk/v7.1*) + ifeq ($(PATH_SDK_WINPSDK71),) + PATH_SDK_WINPSDK71 := $(wildcard $(PATH_DEVTOOLS_TRG)/sdk/v7.1*) + endif + ifeq ($(PATH_SDK_WINPSDK71),) + PATH_SDK_WINPSDK71 := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/v7.1*) + endif + ifeq ($(PATH_SDK_WINPSDK71),) + PATH_SDK_WINPSDK71 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/v7.1*) + endif + ifneq ($(PATH_SDK_WINPSDK71),) + PATH_SDK_WINPSDK71 := $(lastword $(sort $(PATH_SDK_WINPSDK71))) + else + $(warning kBuild: PATH_SDK_WINPSDK71 couldn't be determined!) + PATH_SDK_WINPSDK71 := $(PATH_DEVTOOLS_BLD)/sdk/v7.1-not-found + endif +else + PATH_SDK_WINPSDK71 := $(PATH_SDK_WINPSDK71) +endif + +ifndef PATH_SDK_WINPSDK71_INC +PATH_SDK_WINPSDK71_INC := $(firstword $(wildcard $(PATH_SDK_WINPSDK71)/[Ii][Nn][Cc][Ll][Uu][Dd][Ee]) $(PATH_SDK_WINPSDK71)/Include) +endif + +ifndef PATH_SDK_WINPSDK71_LIB.x86 +PATH_SDK_WINPSDK71_LIB.x86 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71)/[Ll][Ii][Bb]) $(PATH_SDK_WINPSDK71)/Lib) +endif +ifndef PATH_SDK_WINPSDK71_LIB.amd64 +PATH_SDK_WINPSDK71_LIB.amd64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71)/[Ll][Ii][Bb]/[Aa][Mm][Dd]64 $(PATH_SDK_WINPSDK71)/[Ll][Ii][Bb]/[xX]64) $(PATH_SDK_WINPSDK71)/Lib/AMD64) +endif +ifndef PATH_SDK_WINPSDK71_LIB.ia64 +PATH_SDK_WINPSDK71_LIB.ia64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71)/[Ll][Ii][Bb]/[Ii][Aa]64) $(PATH_SDK_WINPSDK71)/Lib/IA64) +endif +PATH_SDK_WINPSDK71_LIB ?= $(PATH_SDK_WINPSDK71_LIB.$(KBUILD_TARGET_ARCH)) + +ifndef PATH_SDK_WINPSDK71_BIN +PATH_SDK_WINPSDK71_BIN := $(firstword $(wildcard $(PATH_SDK_WINPSDK71)/[Bb][Ii][Nn]) $(PATH_SDK_WINPSDK71)/Bin) +endif +ifndef PATH_SDK_WINPSDK71_BIN_AMD64 +PATH_SDK_WINPSDK71_BIN_AMD64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71_BIN)/[Ww][Ii][Nn]64/[Xx]86/[Aa][Mm][Dd]64 $(PATH_SDK_WINPSDK71_BIN)/[Ww][Ii][Nn]64/[Xx]86) $(PATH_SDK_WINPSDK71_BIN)/win64/AMD64) +endif +ifndef PATH_SDK_WINPSDK71_BIN_IA64 +PATH_SDK_WINPSDK71_BIN_IA64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71_BIN)/[Ww][Ii][Nn]64) $(PATH_SDK_WINPSDK71_BIN)/win64) +endif + + +# General Properties used by kBuild +SDK_WINPSDK71_INCS ?= $(PATH_SDK_WINPSDK71_INC) +SDK_WINPSDK71_LIBPATH.x86 ?= $(PATH_SDK_WINPSDK71_LIB.x86) +SDK_WINPSDK71_LIBPATH.amd64 ?= $(PATH_SDK_WINPSDK71_LIB.amd64) +SDK_WINPSDK71_LIBPATH.ia64 ?= $(PATH_SDK_WINPSDK71_LIB.ia64) +SDK_WINPSDK71_LIBS.x86 ?= \ + $(PATH_SDK_WINPSDK71_LIB.x86)/Kernel32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/User32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/Gdi32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/AdvAPI32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/Shell32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/ShLwApi.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/SetupAPI.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/Uuid.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/Version.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/WS2_32.Lib \ + \ + $(PATH_SDK_WINPSDK71_LIB.x86)/Ole32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/OleAut32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/OleDlg.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/RpcRT4.Lib \ + \ + $(PATH_SDK_WINPSDK71_LIB.x86)/DbgHelp.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/ImageHlp.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/IPHlpApi.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/ComCtl32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/ComDlg32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/WinSpool.Lib \ + $(PATH_SDK_WINPSDK71_LIB.x86)/WinMM.Lib +SDK_WINPSDK71_LIBS.amd64 ?= \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/Kernel32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/User32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/Gdi32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/AdvAPI32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/Shell32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/ShLwApi.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/SetupAPI.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/Uuid.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/Version.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/WS2_32.Lib \ + \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/Ole32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/OleAut32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/OleDlg.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/RpcRT4.Lib \ + \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/DbgHelp.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/ImageHlp.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/IPHlpApi.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/ComCtl32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/ComDlg32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/WinSpool.Lib \ + $(PATH_SDK_WINPSDK71_LIB.amd64)/WinMM.Lib +SDK_WINPSDK71_LIBS.ia64 ?= \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/Kernel32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/User32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/Gdi32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/AdvAPI32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/Shell32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/ShLwApi.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/SetupAPI.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/Uuid.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/Version.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/WS2_32.Lib \ + \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/Ole32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/OleAut32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/OleDlg.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/RpcRT4.Lib \ + \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/DbgHelp.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/ImageHlp.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/IPHlpApi.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/ComCtl32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/ComDlg32.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/WinSpool.Lib \ + $(PATH_SDK_WINPSDK71_LIB.ia64)/WinMM.Lib + diff --git a/kBuild/sdks/WINPSDK71INCS.kmk b/kBuild/sdks/WINPSDK71INCS.kmk new file mode 100644 index 0000000..4edf170 --- /dev/null +++ b/kBuild/sdks/WINPSDK71INCS.kmk @@ -0,0 +1,90 @@ +# $Id: WINPSDK71INCS.kmk 2602 2012-07-12 20:21:45Z bird $ +## @file +# kBuild SDK - The Windows Platform SDK v7.1, targeting (KBUILD_TARGET) but +# without any libraries or LIBPATH properties. +# Basically for finding specstrings.h when using the DDK. +# + +# +# Copyright (c) 2006-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# +# This file is part of kBuild. +# +# kBuild is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# kBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kBuild; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# As a special exception you are granted permission to include this file, via +# the kmk include directive, as you wish without this in itself causing the +# resulting makefile, program or whatever to be covered by the GPL license. +# This exception does not however invalidate any other reasons why the makefile, +# program, whatever should not be covered the GPL. +# +# + +SDK_WINPSDK71INCS := The Windows Platform SDK v7.1, targeting (KBUILD_TARGET) but \ + without any library or LIBPATH properties. \ + Basically for finding specstrings.h when using the DDK. + +# SDK Specific Properties +ifndef PATH_SDK_WINPSDK71INCS + ifdef PATH_SDK_WINPSDK71 + PATH_SDK_WINPSDK71INCS := $(PATH_SDK_WINPSDK71) + else + PATH_SDK_WINPSDK71INCS := $(wildcard $(PATH_DEVTOOLS_BLD)/sdk/v7.1*) + ifeq ($(PATH_SDK_WINPSDK71INCS),) + PATH_SDK_WINPSDK71INCS := $(wildcard $(PATH_DEVTOOLS_TRG)/sdk/v7.1*) + endif + ifeq ($(PATH_SDK_WINPSDK71INCS),) + PATH_SDK_WINPSDK71INCS := $(wildcard $(PATH_DEVTOOLS)/win.x86/sdk/v7.1*) + endif + ifeq ($(PATH_SDK_WINPSDK71INCS),) + PATH_SDK_WINPSDK71INCS := $(wildcard $(PATH_DEVTOOLS)/win.amd64/sdk/v7.1*) + endif + ifneq ($(PATH_SDK_WINPSDK71INCS),) + PATH_SDK_WINPSDK71INCS := $(lastword $(sort $(PATH_SDK_WINPSDK71INCS))) + else + $(warning kBuild: PATH_SDK_WINPSDK71INCS couldn't be determined!) + PATH_SDK_WINPSDK71INCS := $(PATH_DEVTOOLS_BLD)/sdk/v7.1-not-found + endif + endif +else + PATH_SDK_WINPSDK71INCS := $(PATH_SDK_WINPSDK71INCS) +endif +ifndef PATH_SDK_WINPSDK71INCS_INC +PATH_SDK_WINPSDK71INCS_INC := $(firstword $(wildcard $(PATH_SDK_WINPSDK71INCS)/[Ii][Nn][Cc][Ll][Uu][Dd][Ee]) $(PATH_SDK_WINPSDK71INCS)/Include) +endif + +ifndef PATH_SDK_WINPSDK71INCS_LIB.x86 +PATH_SDK_WINPSDK71INCS_LIB.x86 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71INCS)/[Ll][Ii][Bb]) $(PATH_SDK_WINPSDK71INCS)/Lib) +endif +ifndef PATH_SDK_WINPSDK71INCS_LIB.amd64 +PATH_SDK_WINPSDK71INCS_LIB.amd64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71INCS)/[Ll][Ii][Bb]/[Aa][Mm][Dd]64) $(PATH_SDK_WINPSDK71INCS)/Lib/AMD64) +endif +PATH_SDK_WINPSDK71INCS_LIB ?= $(PATH_SDK_WINPSDK71INCS_LIB.$(KBUILD_TARGET_ARCH)) + +ifndef PATH_SDK_WINPSDK71INCS_BIN +PATH_SDK_WINPSDK71INCS_BIN := $(firstword $(wildcard $(PATH_SDK_WINPSDK71INCS)/[Bb][Ii][Nn]) $(PATH_SDK_WINPSDK71INCS)/Bin) +endif +ifndef PATH_SDK_WINPSDK71INCS_BIN_AMD64 +PATH_SDK_WINPSDK71INCS_BIN_AMD64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71INCS_BIN)/[Ww][Ii][Nn]64/[Xx]86/[Aa][Mm][Dd]64) $(PATH_SDK_WINPSDK71INCS_BIN)/win64/AMD64) +endif +ifndef PATH_SDK_WINPSDK71INCS_BIN_IA64 +PATH_SDK_WINPSDK71INCS_BIN_IA64 := $(firstword $(wildcard $(PATH_SDK_WINPSDK71INCS_BIN)/[Ww][Ii][Nn]64) $(PATH_SDK_WINPSDK71INCS_BIN)/win64) +endif + + +# General Properties used by kBuild +SDK_WINPSDK71INCS_INCS ?= $(PATH_SDK_WINPSDK71INCS_INC) + diff --git a/kBuild/tools/JWASM.kmk b/kBuild/tools/JWASM.kmk new file mode 100644 index 0000000..748b7d2 --- /dev/null +++ b/kBuild/tools/JWASM.kmk @@ -0,0 +1,63 @@ +# $Id: JWASM.kmk 2578 2012-06-07 00:08:22Z bird $ +## @file +# kBuild Tool Config - JWasm +# + +# +# Copyright (c) 2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# +# This file is part of kBuild. +# +# kBuild is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# kBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kBuild; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# As a special exception you are granted permission to include this file, via +# the kmk include directive, as you wish without this in itself causing the +# resulting makefile, program or whatever to be covered by the GPL license. +# This exception does not however invalidate any other reasons why the makefile, +# program, whatever should not be covered the GPL. +# +# + + +TOOL_JWASM := JWasm - MASM clone based on the Open Watcom assembler. + +# Tool Specific Properties +ifndef TOOL_JWASM_AS + TOOL_JWASM_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_BLD)/jwasm/*/jwasm$(HOSTSUFF_EXE)))) + ifeq ($(TOOL_JWASM_AS),) + TOOL_JWASM_AS := $(firstword $(rsort $(wildcard $(PATH_DEVTOOLS_TRG)/jwasm/*/jwasm$(HOSTSUFF_EXE)))) + endif +endif +ifeq ($(TOOL_JWASM_AS),) + TOOL_JWASM_AS := $(firstword $(which ml$(HOSTSUFF_EXE)) jwasm$(HOSTSUFF_EXE)) +endif + +# General Properties used by kBuild +TOOL_JWASM_ASFLAGS ?= -X -nologo + +TOOL_JWASM_COMPILE_AS_OUTPUT = $(outbase).lst +TOOL_JWASM_COMPILE_AS_DEPEND = +TOOL_JWASM_COMPILE_AS_DEPORD = +define TOOL_JWASM_COMPILE_AS_CMDS + $(TOOL_JWASM_AS) -c \ + $(strip $(flags)) \ + $(addprefix -D,$(defs)) \ + $(addprefix -I,$(incs)) \ + -Fo$(obj) \ + -Fl$(outbase).lst \ + $(source) +endef + diff --git a/kBuild/tools/MINGWW64.kmk b/kBuild/tools/MINGWW64.kmk new file mode 100644 index 0000000..b838812 --- /dev/null +++ b/kBuild/tools/MINGWW64.kmk @@ -0,0 +1,273 @@ +# $Id: MINGWW64.kmk 2695 2013-07-26 12:42:25Z bird $ +## @file +# kBuild Tool Config - MinGW-W64. +# + +# +# Copyright (c) 2004-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# +# This file is part of kBuild. +# +# kBuild is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# kBuild is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with kBuild; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# As a special exception you are granted permission to include this file, via +# the kmk include directive, as you wish without this in itself causing the +# resulting makefile, program or whatever to be covered by the GPL license. +# This exception does not however invalidate any other reasons why the makefile, +# program, whatever should not be covered the GPL. +# +# + +ifdef TOOL_MINGWW64 +$(error Already included (TOOL_MINGWW64=$(TOOL_MINGWW64))) +endif +TOOL_MINGWW64 := MinGW-W64 - The incomprehensible 64-bit GCC port to Windows. + +# Tool Specific Properties +ifndef PATH_TOOL_MINGWW64 + PATH_TOOL_MINGWW64 := $(wildcard $(PATH_DEVTOOLS_BLD)/mingw-w64/r*) + ifeq ($(PATH_TOOL_MINGWW64),) + PATH_TOOL_MINGWW64 := $(wildcard $(PATH_DEVTOOLS)/win.amd64/mingw-w64/r*) + endif + ifeq ($(PATH_TOOL_MINGWW64),) + PATH_TOOL_MINGWW64 := $(wildcard $(PATH_DEVTOOLS)/win.x86/mingw-w64/r*) + endif + ifneq ($(PATH_TOOL_MINGWW64),) + PATH_TOOL_MINGWW64 := $(lastword $(sort $(PATH_TOOL_MINGWW64))) + endif +else + # Resolve any fancy stuff once and for all. + PATH_TOOL_MINGWW64 := $(PATH_TOOL_MINGWW64) +endif + +# figure out if it's native or needs a win32 launcher +TOOL_MINGWW64_HOSTSUFF_EXE ?= $(HOSTSUFF_EXE) +ifndef TOOL_MINGWW64_PREFIX + ifneq ($(PATH_TOOL_MINGWW64),) + TOOL_MINGWW64_PREFIX := $(PATH_TOOL_MINGWW64)/bin/ + else + TOOL_MINGWW64_PREFIX := + endif + ifneq ($(KBUILD_HOST),win) +# # we're cross compiling either using an emulator (wine/odin) or a cross compiler. +# ifneq ($(PATH_TOOL_MINGWW64),$(subst /win.x86,,$(subst /x86.win,,$(PATH_TOOL_MINGWW64)))) + TOOL_MINGWW64_PREFIX := $(EXEC_X86_WIN32) $(TOOL_MINGWW64_PREFIX) + TOOL_MINGWW64_HOSTSUFF_EXE := .exe +# else +# TOOL_MINGWW64_PREFIX := $(TOOL_MINGWW64_PREFIX)i386-mingw32msvc- +# TOOL_MINGWW64_HOSTSUFF_EXE := +# TOOL_MINGWW64_XCOMPILE := 1 +# endif + endif +else + # Resolve any fancy stuff once and for all. + TOOL_MINGWW64_PREFIX := $(TOOL_MINGWW64_PREFIX) +endif + +TOOL_MINGWW64_CC ?= $(TOOL_MINGWW64_PREFIX)gcc$(TOOL_MINGWW64_HOSTSUFF_EXE) +TOOL_MINGWW64_CXX ?= $(TOOL_MINGWW64_PREFIX)g++$(TOOL_MINGWW64_HOSTSUFF_EXE) +TOOL_MINGWW64_AS ?= $(TOOL_MINGWW64_PREFIX)gcc$(TOOL_MINGWW64_HOSTSUFF_EXE) +TOOL_MINGWW64_AR ?= $(TOOL_MINGWW64_PREFIX)ar$(TOOL_MINGWW64_HOSTSUFF_EXE) +ifndef TOOL_MINGWW64_XCOMPILE# The gentoo package doesn't have g++. +TOOL_MINGWW64_LD ?= $(TOOL_MINGWW64_PREFIX)g++$(TOOL_MINGWW64_HOSTSUFF_EXE) +else +TOOL_MINGWW64_LD ?= $(TOOL_MINGWW64_PREFIX)gcc$(TOOL_MINGWW64_HOSTSUFF_EXE) +endif +TOOL_MINGWW64_DLLWRAP ?= $(TOOL_MINGWW64_PREFIX)dllwrap$(TOOL_MINGWW64_HOSTSUFF_EXE) +TOOL_MINGWW64_DLLTOOL ?= $(TOOL_MINGWW64_PREFIX)dlltool$(TOOL_MINGWW64_HOSTSUFF_EXE) + +# General Properties used by kBuild +TOOL_MINGWW64_COBJSUFF ?= .o +TOOL_MINGWW64_CFLAGS ?= -g +TOOL_MINGWW64_CFLAGS.debug ?= -O0 +TOOL_MINGWW64_CFLAGS.release ?= -O2 +TOOL_MINGWW64_CFLAGS.profile ?= -O2 #-pg +TOOL_MINGWW64_CINCS ?= +TOOL_MINGWW64_CDEFS ?= + +TOOL_MINGWW64_CXXOBJSUFF ?= .o +TOOL_MINGWW64_CXXOBJSUFF ?= .o +TOOL_MINGWW64_CXXFLAGS ?= -g +TOOL_MINGWW64_CXXFLAGS.debug ?= -O0 +TOOL_MINGWW64_CXXFLAGS.release ?= -O2 +TOOL_MINGWW64_CXXFLAGS.profile ?= -O2 #-pg +TOOL_MINGWW64_CXXINCS ?= +TOOL_MINGWW64_CXXDEFS ?= + +TOOL_MINGWW64_ASFLAGS ?= -g -x assembler-with-cpp +TOOL_MINGWW64_ASOBJSUFF ?= .o + +TOOL_MINGWW64_ARFLAGS ?= cr +TOOL_MINGWW64_ARLIBSUFF ?= .a + +TOOL_MINGWW64_LDFLAGS ?= +TOOL_MINGWW64_LDFLAGS.debug ?= -g +TOOL_MINGWW64_LDFLAGS.release ?= -s + + +## Compile C source. +# @param $(target) Normalized main target name. +# @param $(source) Source filename (relative). +# @param $(obj) Object file name. This shall be (re)created by the compilation. +# @param $(dep) Dependcy file. This shall be (re)created by the compilation. +# @param $(flags) Flags. +# @param $(defs) Definitions. No -D or something. +# @param $(incs) Includes. No -I or something. +# @param $(dirdep) Directory creation dependency. +# @param $(deps) Other dependencies. +# @param $(outbase) Output basename (full). Use this for list files and such. +# @param $(objsuff) Object suffix. +TOOL_MINGWW64_COMPILE_C_OUTPUT = +TOOL_MINGWW64_COMPILE_C_DEPEND = +TOOL_MINGWW64_COMPILE_C_DEPORD = +define TOOL_MINGWW64_COMPILE_C_CMDS + $(QUIET)$(TOOL_MINGWW64_CC) -c\ + $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ + -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ + -o $(obj)\ + $(abspath $(source)) +endef + + +## Compile C++ source. +# @param $(target) Normalized main target name. +# @param $(source) Source filename (relative). +# @param $(obj) Object file name. This shall be (re)created by the compilation. +# @param $(dep) Dependcy file. This shall be (re)created by the compilation. +# @param $(flags) Flags. +# @param $(defs) Definitions. No -D or something. +# @param $(incs) Includes. No -I or something. +# @param $(dirdep) Directory creation dependency. +# @param $(deps) Other dependencies. +# @param $(outbase) Output basename (full). Use this for list files and such. +# @param $(objsuff) Object suffix. +TOOL_MINGWW64_COMPILE_CXX_OUTPUT = +TOOL_MINGWW64_COMPILE_CXX_DEPEND = +TOOL_MINGWW64_COMPILE_CXX_DEPORD = +define TOOL_MINGWW64_COMPILE_CXX_CMDS + $(QUIET)$(TOOL_MINGWW64_CXX) -c\ + $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ + -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ + -o $(obj)\ + $(abspath $(source)) +endef + + +## Compile Assembly source. +# @param $(target) Normalized main target name. +# @param $(source) Source filename (relative). +# @param $(obj) Object file name. This shall be (re)created by the compilation. +# @param $(dep) Dependcy file. This shall be (re)created by the compilation. +# @param $(flags) Flags. +# @param $(defs) Definitions. No -D or something. +# @param $(incs) Includes. No -I or something. +# @param $(dirdep) Directory creation dependency. +# @param $(deps) Other dependencies. +# @param $(outbase) Output basename (full). Use this for list files and such. +# @param $(objsuff) Object suffix. +# +TOOL_MINGWW64_COMPILE_AS_OUTPUT = +TOOL_MINGWW64_COMPILE_AS_DEPEND = +TOOL_MINGWW64_COMPILE_AS_DEPORD = +define TOOL_MINGWW64_COMPILE_AS_CMDS + $(QUIET)$(TOOL_MINGWW64_AS) -c\ + $(flags) $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ + -Wp,-MD,$(dep) -Wp,-MT,$(obj) -Wp,-MP\ + -o $(obj)\ + $(abspath $(source)) +endef + + +## Link library +# @param $(target) Normalized main target name. +# @param $(out) Library name. +# @param $(objs) Object files to put in the library. +# @param $(flags) Flags. +# @param $(dirdep) Directory creation dependency. +# @param $(deps) Other dependencies. +# +# @param $(outbase) Output basename (full). Use this for list files and such. +TOOL_MINGWW64_LINK_LIBRARY_OUTPUT = $(out).ar-script +TOOL_MINGWW64_LINK_LIBRARY_DEPEND = $(othersrc) +TOOL_MINGWW64_LINK_LIBRARY_DEPORD = +define TOOL_MINGWW64_LINK_LIBRARY_CMDS + $(QUIET)$(APPEND) $(out).ar-script 'CREATE $(out)' + $(QUIET)$(APPEND) -n $(out).ar-script \ + $(foreach o,$(objs), 'ADDMOD $(o)') \ + $(foreach o,$(othersrc), 'ADDLIB $(o)') + $(QUIET)$(APPEND) $(out).ar-script 'SAVE' + $(QUIET)$(APPEND) $(out).ar-script 'END' + $(QUIET)$(TOOL_MINGWW64_AR) -M < $(out).ar-script +endef + + + +## Link program +# @param $(target) Normalized main target name. +# @param $(out) Program name. +# @param $(objs) Object files to link together. +# @param $(libs) Libraries to search. +# @param $(libpath) Library search paths. +# @param $(flags) Flags. +# @param $(dirdep) Directory creation dependency. +# @param $(deps) Other dependencies. +# @param $(othersrc) Unhandled sources. +# @param $(custom_pre) Custom step invoked before linking. +# @param $(custom_post) Custom step invoked after linking. +# +# @param $(outbase) Output basename (full). Use this for list files and such. +TOOL_MINGWW64_LINK_PROGRAM_OUTPUT = +TOOL_MINGWW64_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) +TOOL_MINGWW64_LINK_PROGRAM_DEPORD = +define TOOL_MINGWW64_LINK_PROGRAM_CMDS + $(QUIET)$(TOOL_MINGWW64_LD) $(flags) -o $(out) $(objs)\ + $(foreach p,$(libpath), -L$(p))\ + $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib))) +endef + + +## Link DLL. +# @param $(target) Normalized main target name. +# @param $(out) DLL name. +# @param $(objs) Object files to link together. +# @param $(libs) Libraries to search. +# @param $(libpath) Library search paths. +# @param $(flags) Flags. +# @param $(dirdep) Directory creation dependency. +# @param $(deps) Other dependencies. +# @param $(othersrc) Unhandled sources. +# @param $(custom_pre) Custom step invoked before linking. +# @param $(custom_post) Custom step invoked after linking. +# @param $(outbase) Output basename (full). Use this for list files and such. +TOOL_MINGWW64_LINK_DLL_OUTPUT = +TOOL_MINGWW64_LINK_DLL_OUTPUT_MAYBE = $(outbase).a $(outbase).exp $(PATH_STAGE_LIB)/$(notdir $(outbase)).exp $(PATH_STAGE_LIB)/$(notdir $(outbase)).a +## @todo Find a better solution for installing the extra files (.a, .exp, .pdb, etc). +TOOL_MINGWW64_LINK_DLL_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib)))\ + $(filter %.def %.res,$(othersrc)) +TOOL_MINGWW64_LINK_DLL_DEPORD = $(call DIRDEP,$(PATH_STAGE_LIB)) +define TOOL_MINGWW64_LINK_DLL_CMDS + $(QUIET)$(REDIRECT) -C "$(dir $(out))" -- $(TOOL_MINGWW64_DLLWRAP) $(flags)\ + --dllname=$(notdir $(out))\ + --output-exp=$(outbase).exp\ + --output-lib=$(outbase).a\ + $(foreach def,$(filter %.def,$(othersrc)), --def $(def))\ + $(filter %.res,$(othersrc))\ + $(objs)\ + $(foreach p,$(libpath), -L$(p))\ + $(foreach lib,$(libs), $(if $(findstring $(lib),$(subst /,x,$(lib))), -l$(patsubst lib%,%,$(basename $(lib))), $(lib))) + $(QUIET)$(CP) $(outbase).exp $(outbase).a $(PATH_STAGE_LIB)/ +endef +## @todo separate install stuff! diff --git a/kBuild/tools/OPENWATCOM-WL.kmk b/kBuild/tools/OPENWATCOM-WL.kmk index 25556ac..7d28629 100644 --- a/kBuild/tools/OPENWATCOM-WL.kmk +++ b/kBuild/tools/OPENWATCOM-WL.kmk @@ -1,4 +1,4 @@ -# $Id: OPENWATCOM-WL.kmk 2572 2012-04-27 13:19:55Z bird $ +# $Id: OPENWATCOM-WL.kmk 2663 2012-10-15 13:13:45Z bird $ ## @file # kBuild Tool Config - Open Watcom v1.4 and later, using wlink. # @@ -49,11 +49,11 @@ TOOL_OPENWATCOM-WL_LINK_PROGRAM_DEPORD = define TOOL_OPENWATCOM-WL_LINK_PROGRAM_CMDS $(QUIET)$(APPEND) -tn $(outbase).rsp \ $(if $(flags),'$(flags)',) \ - 'Name $(call TOOL_OPENWATCOM_FIX_SLASHES,$(out)$(if $(suffix $(out)),,.))' \ - 'Option Map=$(call TOOL_OPENWATCOM_FIX_SLASHES,$(outbase)).map' \ - $(foreach p,$(call TOOL_OPENWATCOM_FIX_SLASHES,$(libpath)),'LIBPath $p') \ - $(foreach o,$(call TOOL_OPENWATCOM_FIX_SLASHES,$(filter-out %.res,$(objs)) $(othersrc)),'$(if $(filter %.lib %.a,$l),LIB,)File $o') \ - $(foreach l,$(call TOOL_OPENWATCOM_FIX_SLASHES,$(libs)),'Library $l') + 'Name $(call TOOL_OPENWATCOM_FIX_SLASHES_SQ,$(out)$(if $(suffix $(out)),,.))' \ + 'Option Map=$(call TOOL_OPENWATCOM_FIX_SLASHES_SQ,$(outbase)).map' \ + $(foreach p,$(call TOOL_OPENWATCOM_FIX_SLASHES_SQ,$(libpath)),'LIBPath $p') \ + $(foreach o,$(call TOOL_OPENWATCOM_FIX_SLASHES_SQ,$(filter-out %.res,$(objs)) $(othersrc)),'$(if $(filter %.lib %.a,$l),LIB,)File $o') \ + $(foreach l,$(call TOOL_OPENWATCOM_FIX_SLASHES_SQ,$(libs)),'Library $l') $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP) \ $(TOOL_OPENWATCOM_WLINK) @$(outbase).rsp $(if $(filter %.res,$(objs)), $(QUIET)$(call TOOL_OPENWATCOM_ENV_SETUP) \ diff --git a/kBuild/tools/OPENWATCOM.kmk b/kBuild/tools/OPENWATCOM.kmk index 9d361bb..bbfdc46 100644 --- a/kBuild/tools/OPENWATCOM.kmk +++ b/kBuild/tools/OPENWATCOM.kmk @@ -1,4 +1,4 @@ -# $Id: OPENWATCOM.kmk 2576 2012-05-31 15:07:00Z bird $ +# $Id: OPENWATCOM.kmk 2663 2012-10-15 13:13:45Z bird $ ## @file # kBuild Tool Config - Open Watcom v1.4 and later. # @@ -147,10 +147,13 @@ else endif +# Functions for changing slashes (SQ = single quoted). if1of ($(KBUILD_HOST), os2 win) TOOL_OPENWATCOM_FIX_SLASHES = $(subst /,\\,$1) + TOOL_OPENWATCOM_FIX_SLASHES_SQ = $(subst /,\,$1) else TOOL_OPENWATCOM_FIX_SLASHES = $1 + TOOL_OPENWATCOM_FIX_SLASHES_SQ = $1 endif # General Properties used by kBuild diff --git a/kBuild/tools/VCC100.kmk b/kBuild/tools/VCC100.kmk index a16807a..fdacfa1 100644 --- a/kBuild/tools/VCC100.kmk +++ b/kBuild/tools/VCC100.kmk @@ -1,4 +1,4 @@ -# $Id: VCC100.kmk 2557 2011-12-13 12:48:32Z bird $ +# $Id: VCC100.kmk 2677 2013-02-01 15:04:53Z bird $ ## @file # kBuild Tool Config - Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting $(KBUILD_TARGET). # @@ -73,20 +73,32 @@ ifneq ($(PATH_TOOL_VCC100),) TOOL_VCC100_CC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/cl.exe TOOL_VCC100_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/cl.exe TOOL_VCC100_AS ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/ml64.exe - TOOL_VCC100_RC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN.x86)/rc.exe TOOL_VCC100_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/lib.exe TOOL_VCC100_LD ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/link.exe - TOOL_VCC100_MT ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN.x86)/mt.exe + TOOL_VCC100_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/dumpbin.exe + TOOL_VCC100_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100_BIN)/editbin.exe else # Pathless, relies on the environment. TOOL_VCC100_CC ?= $(EXEC_X86_WIN32) cl.exe TOOL_VCC100_CXX ?= $(EXEC_X86_WIN32) cl.exe TOOL_VCC100_AS ?= $(EXEC_X86_WIN32) ml64.exe - TOOL_VCC100_RC ?= $(EXEC_X86_WIN32) rc.exe TOOL_VCC100_AR ?= $(EXEC_X86_WIN32) lib.exe TOOL_VCC100_LD ?= $(EXEC_X86_WIN32) link.exe - TOOL_VCC100_MT ?= $(EXEC_X86_WIN32) mt.exe + TOOL_VCC100_DUMPBIN ?= $(EXEC_X86_WIN32) dumpbin.exe + TOOL_VCC100_EDITBIN ?= $(EXEC_X86_WIN32) editbin.exe endif +TOOL_VCC100_RC ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,rc.exe,[Rr][Cc].[Ee][Xx][Ee],TOOL_VCC100_RC_CACHED) +TOOL_VCC100_MT ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,mt.exe,[Mm][Tt].[Ee][Xx][Ee],TOOL_VCC100_MT_CACHED) + +# The following in duplicated in VCC100.kmk and VCC100X86.kmk. +TOOL_VCC100_FN_FIND_SDK_TOOL_SUB = $(eval $3 := $(firstword \ + $(if-expr defined(PATH_SDK_WINPSDK71_BIN), $(wildcard $(PATH_SDK_WINPSDK71_BIN)/$2)) \ + $(if-expr defined(PATH_SDK_WINPSDK_BIN) , $(wildcard $(PATH_SDK_WINPSDK_BIN)/$2)) \ + $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST)/sdk/*/[Bb][Ii][Nn]/$2)) \ + $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST_ALT)/sdk/*/[Bb][Ii][Nn]/$2)) \ + $1)) +TOOL_VCC100_FN_FIND_SDK_TOOL = $(if-expr !defined($3),$(TOOL_VCC100_FN_FIND_SDK_TOOL_SUB),)$($3) + ## Disabled fast DEP_IDB based dependencies. #VCC100_OLD_DEPS = 1 @@ -96,16 +108,18 @@ endif TOOL_VCC100_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2) TOOL_VCC100_COBJSUFF ?= .obj -TOOL_VCC100_CFLAGS ?= -TC -c -nologo -TOOL_VCC100_CFLAGS.debug ?= -Od -Zi +TOOL_VCC100_CFLAGS ?= -TC -nologo +TOOL_VCC100_CFLAGS.debug ?= -Zi +TOOL_VCC100_CFLAGS.dbgopt ?= -O2 -Zi TOOL_VCC100_CFLAGS.release ?= -O2 TOOL_VCC100_CFLAGS.profile ?= -O2 TOOL_VCC100_CINCS ?= $(PATH_TOOL_VCC100_INC) TOOL_VCC100_CDEFS ?= TOOL_VCC100_CXXOBJSUFF ?= .obj -TOOL_VCC100_CXXFLAGS ?= -TP -c -nologo -TOOL_VCC100_CXXFLAGS.debug ?= -Od -Zi +TOOL_VCC100_CXXFLAGS ?= -TP -nologo +TOOL_VCC100_CXXFLAGS.debug ?= -Zi +TOOL_VCC100_CXXFLAGS.dbgopt ?= -O2 -Zi TOOL_VCC100_CXXFLAGS.release ?= -O2 TOOL_VCC100_CXXFLAGS.profile ?= -O2 TOOL_VCC100_CXXINCS ?= $(PATH_TOOL_VCC100_INC) $(PATH_TOOL_VCC100_ATLMFC_INC) @@ -125,6 +139,8 @@ TOOL_VCC100_LDFLAGS.amd64 ?= -machine:amd64 TOOL_VCC100_LDFLAGS.x86 ?= -machine:x86 TOOL_VCC100_LDFLAGS ?= -nologo TOOL_VCC100_LDFLAGS.debug ?= -debug +TOOL_VCC100_LDFLAGS.dbgopt ?= -debug +TOOL_VCC100_LDFLAGS.profile ?= -debug TOOL_VCC100_LDFLAGS.release ?= TOOL_VCC100_LIBPATH.amd64 ?= $(PATH_TOOL_VCC100_LIB.amd64) $(PATH_TOOL_VCC100_ATLMFC_LIB.amd64) TOOL_VCC100_LIBPATH.x86 ?= $(PATH_TOOL_VCC100_LIB.x86) $(PATH_TOOL_VCC100_ATLMFC_LIB.x86) @@ -146,6 +162,25 @@ TOOL_VCC100_LIBPATH.x86 ?= $(PATH_TOOL_VCC100_LIB.x86) $(PATH_TOOL_VCC100_A # @param $(objsuff) Object suffix. TOOL_VCC100_COMPILE_C_DEPEND = TOOL_VCC100_COMPILE_C_DEPORD = +ifdef KBUILD_USE_KOBJCACHE +TOOL_VCC100_COMPILE_C_USES_KOBJCACHE = 1 +TOOL_VCC100_COMPILE_C_OUTPUT = $(outbase).i +TOOL_VCC100_COMPILE_C_OUTPUT_MAYBE = +define TOOL_VCC100_COMPILE_C_CMDS + $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\ + --make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\ + --kObjCache-cpp $(outbase).i\ + $(TOOL_VCC100_CC) -E\ + $(subst -Zi,-Z7,$(flags))\ + $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ + $(subst /,\\,$(abspath $(source))) \ + --kObjCache-cc $(obj)\ + $(TOOL_VCC100_CC) -c\ + $(subst -Zi,-Z7,$(flags))\ + -Fo$(obj)\ + $(outbase).i +endef +else # !KBUILD_USE_KOBJCACHE TOOL_VCC100_COMPILE_C_OUTPUT = $(call TOOL_VCC100_PDB, $(outbase)-obj,idb) TOOL_VCC100_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC100_PDB, $(outbase)-obj,pdb) define TOOL_VCC100_COMPILE_C_CMDS @@ -157,6 +192,7 @@ define TOOL_VCC100_COMPILE_C_CMDS $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100_PDB,$(outbase)-obj,idb) endef +endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. @@ -174,6 +210,25 @@ endef # @param $(objsuff) Object suffix. TOOL_VCC100_COMPILE_CXX_DEPEND = TOOL_VCC100_COMPILE_CXX_DEPORD = +ifdef KBUILD_USE_KOBJCACHE +TOOL_VCC100_COMPILE_CXX_USES_KOBJCACHE = 1 +TOOL_VCC100_COMPILE_CXX_OUTPUT = $(outbase).ii +TOOL_VCC100_COMPILE_CXX_OUTPUT_MAYBE = +define TOOL_VCC100_COMPILE_CXX_CMDS + $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\ + --make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\ + --kObjCache-cpp $(outbase).ii\ + $(TOOL_VCC100_CXX) -E\ + $(subst -Zi,-Z7,$(flags))\ + $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ + $(subst /,\\,$(abspath $(source))) \ + --kObjCache-cc $(obj)\ + $(TOOL_VCC100_CXX) -c\ + $(subst -Zi,-Z7,$(flags))\ + -Fo$(obj)\ + $(outbase).ii +endef +else # !KBUILD_USE_KOBJCACHE TOOL_VCC100_COMPILE_CXX_OUTPUT = $(call TOOL_VCC100_PDB, $(outbase)-obj,idb) TOOL_VCC100_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC100_PDB, $(outbase)-obj,pdb) define TOOL_VCC100_COMPILE_CXX_CMDS @@ -185,7 +240,9 @@ define TOOL_VCC100_COMPILE_CXX_CMDS $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100_PDB,$(outbase)-obj,idb) endef +endif # !KBUILD_USE_KOBJCACHE +## @todo configure the assembler template. ## Compile resource source. # @param $(target) Normalized main target name. @@ -255,7 +312,7 @@ endef TOOL_VCC100_LINK_PROGRAM_DEPEND = $(foreach lib,$(libs),$(if $(findstring $(lib),$(subst /,x,$(lib))),, $(lib))) $(othersrc) TOOL_VCC100_LINK_PROGRAM_DEPORD = TOOL_VCC100_LINK_PROGRAM_OUTPUT = $(outbase).map $(outbase).rsp -TOOL_VCC100_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).map $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest +TOOL_VCC100_LINK_PROGRAM_OUTPUT_MAYBE = $(outbase).lib $(outbase).exp $(outbase).ilk $(out).manifest TOOL_VCC100_LINK_PROGRAM_OUTPUT_DEBUG = $(outbase).pdb TOOL_VCC100_LINK_PROGRAM_DEBUG_INSTALL_FN = $(2).pdb=>$(basename $(3)).pdb define TOOL_VCC100_LINK_PROGRAM_CMDS diff --git a/kBuild/tools/VCC100AMD64.kmk b/kBuild/tools/VCC100AMD64.kmk index 43e7ecd..0a06a4d 100644 --- a/kBuild/tools/VCC100AMD64.kmk +++ b/kBuild/tools/VCC100AMD64.kmk @@ -1,4 +1,4 @@ -# $Id: VCC100AMD64.kmk 2557 2011-12-13 12:48:32Z bird $ +# $Id: VCC100AMD64.kmk 2625 2012-08-07 20:26:48Z bird $ ## @file # kBuild Tool Config - Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting AMD64. # @@ -68,10 +68,22 @@ PATH_TOOL_VCC100AMD64_ATLMFC_LIB ?= $(PATH_TOOL_VCC100AMD64_ATLMFC)/lib/amd64 TOOL_VCC100AMD64_CC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/cl.exe TOOL_VCC100AMD64_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/cl.exe TOOL_VCC100AMD64_AS ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/ml64.exe -TOOL_VCC100AMD64_RC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/../rc.exe TOOL_VCC100AMD64_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/lib.exe TOOL_VCC100AMD64_LD ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/link.exe -TOOL_VCC100AMD64_MT ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/../mt.exe +TOOL_VCC100AMD64_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/dumpbin.exe +TOOL_VCC100AMD64_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/editbin.exe +TOOL_VCC100AMD64_RC ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,rc.exe,[Rr][Cc].[Ee][Xx][Ee],TOOL_VCC100_RC_CACHED) +TOOL_VCC100AMD64_MT ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,mt.exe,[Mm][Tt].[Ee][Xx][Ee],TOOL_VCC100_MT_CACHED) + +# The following in duplicated in VCC100.kmk and VCC100X86.kmk. +TOOL_VCC100_FN_FIND_SDK_TOOL_SUB = $(eval $3 := $(firstword \ + $(if-expr defined(PATH_SDK_WINPSDK71_BIN), $(wildcard $(PATH_SDK_WINPSDK71_BIN)/$2)) \ + $(if-expr defined(PATH_SDK_WINPSDK_BIN) , $(wildcard $(PATH_SDK_WINPSDK_BIN)/$2)) \ + $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST)/sdk/*/[Bb][Ii][Nn]/$2)) \ + $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST_ALT)/sdk/*/[Bb][Ii][Nn]/$2)) \ + $1)) +TOOL_VCC100_FN_FIND_SDK_TOOL = $(if-expr !defined($3),$(TOOL_VCC100_FN_FIND_SDK_TOOL_SUB),)$($3) + ## Disabled fast DEP_IDB based dependencies. #VCC100AMD64_OLD_DEPS = 1 @@ -81,16 +93,18 @@ TOOL_VCC100AMD64_MT ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100AMD64_BIN)/../mt.exe TOOL_VCC100AMD64_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2) TOOL_VCC100AMD64_COBJSUFF ?= .obj -TOOL_VCC100AMD64_CFLAGS ?= -TC -c -nologo -TOOL_VCC100AMD64_CFLAGS.debug ?= -Od -Zi +TOOL_VCC100AMD64_CFLAGS ?= -TC -nologo +TOOL_VCC100AMD64_CFLAGS.debug ?= -Zi +TOOL_VCC100AMD64_CFLAGS.dbgopt ?= -O2 -Zi TOOL_VCC100AMD64_CFLAGS.release ?= -O2 TOOL_VCC100AMD64_CFLAGS.profile ?= -O2 TOOL_VCC100AMD64_CINCS ?= $(PATH_TOOL_VCC100AMD64_INC) TOOL_VCC100AMD64_CDEFS ?= TOOL_VCC100AMD64_CXXOBJSUFF ?= .obj -TOOL_VCC100AMD64_CXXFLAGS ?= -TP -c -nologo -TOOL_VCC100AMD64_CXXFLAGS.debug ?= -Od -Zi +TOOL_VCC100AMD64_CXXFLAGS ?= -TP -nologo +TOOL_VCC100AMD64_CXXFLAGS.debug ?= -Zi +TOOL_VCC100AMD64_CXXFLAGS.dbgopt ?= -O2 -Zi TOOL_VCC100AMD64_CXXFLAGS.release ?= -O2 TOOL_VCC100AMD64_CXXFLAGS.profile ?= -O2 TOOL_VCC100AMD64_CXXINCS ?= $(PATH_TOOL_VCC100AMD64_INC) $(PATH_TOOL_VCC100AMD64_ATLMFC_INC) @@ -106,6 +120,8 @@ TOOL_VCC100AMD64_ARLIBSUFF ?= .lib TOOL_VCC100AMD64_LDFLAGS ?= -nologo -machine:amd64 TOOL_VCC100AMD64_LDFLAGS.debug ?= -debug +TOOL_VCC100AMD64_LDFLAGS.dbgopt ?= -debug +TOOL_VCC100AMD64_LDFLAGS.profile ?= -debug TOOL_VCC100AMD64_LDFLAGS.release ?= @@ -125,6 +141,25 @@ TOOL_VCC100AMD64_LDFLAGS.release ?= # @param $(objsuff) Object suffix. TOOL_VCC100AMD64_COMPILE_C_DEPEND = TOOL_VCC100AMD64_COMPILE_C_DEPORD = +ifdef KBUILD_USE_KOBJCACHE +TOOL_VCC100AMD64_COMPILE_C_USES_KOBJCACHE = 1 +TOOL_VCC100AMD64_COMPILE_C_OUTPUT = $(outbase).i +TOOL_VCC100AMD64_COMPILE_C_OUTPUT_MAYBE = +define TOOL_VCC100AMD64_COMPILE_C_CMDS + $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\ + --make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\ + --kObjCache-cpp $(outbase).i\ + $(TOOL_VCC100AMD64_CC) -E\ + $(subst -Zi,-Z7,$(flags))\ + $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ + $(subst /,\\,$(abspath $(source))) \ + --kObjCache-cc $(obj)\ + $(TOOL_VCC100AMD64_CC) -c\ + $(subst -Zi,-Z7,$(flags))\ + -Fo$(obj)\ + $(outbase).i +endef +else # !KBUILD_USE_KOBJCACHE TOOL_VCC100AMD64_COMPILE_C_OUTPUT = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,idb) TOOL_VCC100AMD64_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,pdb) define TOOL_VCC100AMD64_COMPILE_C_CMDS @@ -136,6 +171,7 @@ define TOOL_VCC100AMD64_COMPILE_C_CMDS $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100AMD64_PDB,$(outbase)-obj,idb) endef +endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. @@ -155,44 +191,22 @@ TOOL_VCC100AMD64_COMPILE_CXX_DEPEND = TOOL_VCC100AMD64_COMPILE_CXX_DEPORD = ifdef KBUILD_USE_KOBJCACHE TOOL_VCC100AMD64_COMPILE_CXX_USES_KOBJCACHE = 1 -TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,idb) $(outbase).ii -TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,pdb) -if 1 +TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT = $(outbase).ii +TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT_MAYBE = define TOOL_VCC100AMD64_COMPILE_CXX_CMDS - $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -r\ - --named-pipe-compile $(subst /,\\,//./pipe/kObjCache/$(translate $(outbase),:,_)/$(notdir $(source)))\ + $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\ + --make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\ --kObjCache-cpp $(outbase).ii\ $(TOOL_VCC100AMD64_CXX) -E\ - $(flags)\ + $(subst -Zi,-Z7,$(flags))\ $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ $(subst /,\\,$(abspath $(source))) \ --kObjCache-cc $(obj)\ - windbg $(TOOL_VCC100AMD64_CXX) -c -TP\ - $(flags)\ - -Fd$(outbase)-obj.pdb \ - -FD\ - -Fo$(obj)\ - $(subst /,\\,//./pipe/kObjCache/$(translate $(outbase),:,_)/$(notdir $(source))) - $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100AMD64_PDB,$(outbase)-obj,idb) -endef -else -define TOOL_VCC100AMD64_COMPILE_CXX_CMDS - $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -r\ - --kObjCache-cpp $(outbase).ii\ - $(TOOL_VCC100AMD64_CXX) -E\ - $(flags)\ - $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ - $(subst /,\\,$(abspath $(source))) \ - --kObjCache-cc $(obj)\ - $(TOOL_VCC100AMD64_CXX) -c -TP\ - $(flags)\ - -Fd$(outbase)-obj.pdb \ - -FD\ + $(TOOL_VCC100AMD64_CXX) -c\ + $(subst -Zi,-Z7,$(flags))\ -Fo$(obj)\ $(outbase).ii - $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100AMD64_PDB,$(outbase)-obj,idb) endef -endif else # !KBUILD_USE_KOBJCACHE TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,idb) TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC100AMD64_PDB, $(outbase)-obj,pdb) @@ -207,6 +221,8 @@ define TOOL_VCC100AMD64_COMPILE_CXX_CMDS endef endif # !KBUILD_USE_KOBJCACHE +## @todo configure the assembler template. + ## Compile resource source. # @param $(target) Normalized main target name. # @param $(source) Source filename (relative). diff --git a/kBuild/tools/VCC100X86.kmk b/kBuild/tools/VCC100X86.kmk index 1ec1f57..3aa31cd 100644 --- a/kBuild/tools/VCC100X86.kmk +++ b/kBuild/tools/VCC100X86.kmk @@ -1,4 +1,4 @@ -# $Id: VCC100X86.kmk 2557 2011-12-13 12:48:32Z bird $ +# $Id: VCC100X86.kmk 2625 2012-08-07 20:26:48Z bird $ ## @file # kBuild Tool Config - Visual C++ 10.0 (aka Visual 2010 and MSC v16), targeting x86. # @@ -67,10 +67,22 @@ PATH_TOOL_VCC100X86_ATLMFC_LIB ?= $(PATH_TOOL_VCC100X86_ATLMFC)/lib TOOL_VCC100X86_CC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/cl.exe TOOL_VCC100X86_CXX ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/cl.exe TOOL_VCC100X86_AS ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/ml.exe -TOOL_VCC100X86_RC ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/rc.exe TOOL_VCC100X86_AR ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/lib.exe TOOL_VCC100X86_LD ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/link.exe -TOOL_VCC100X86_MT ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/mt.exe +TOOL_VCC100X86_DUMPBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/dumpbin.exe +TOOL_VCC100X86_EDITBIN ?= $(EXEC_X86_WIN32) $(PATH_TOOL_VCC100X86_BIN)/editbin.exe +TOOL_VCC100X86_RC ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,rc.exe,[Rr][Cc].[Ee][Xx][Ee],TOOL_VCC100_RC_CACHED) +TOOL_VCC100X86_MT ?= $(EXEC_X86_WIN32) $(call TOOL_VCC100_FN_FIND_SDK_TOOL,mt.exe,[Mm][Tt].[Ee][Xx][Ee],TOOL_VCC100_MT_CACHED) + +# The following in duplicated in VCC100.kmk and VCC100X86.kmk. +TOOL_VCC100_FN_FIND_SDK_TOOL_SUB = $(eval $3 := $(firstword \ + $(if-expr defined(PATH_SDK_WINPSDK71_BIN), $(wildcard $(PATH_SDK_WINPSDK71_BIN)/$2)) \ + $(if-expr defined(PATH_SDK_WINPSDK_BIN) , $(wildcard $(PATH_SDK_WINPSDK_BIN)/$2)) \ + $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST)/sdk/*/[Bb][Ii][Nn]/$2)) \ + $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST_ALT)/sdk/*/[Bb][Ii][Nn]/$2)) \ + $1)) +TOOL_VCC100_FN_FIND_SDK_TOOL = $(if-expr !defined($3),$(TOOL_VCC100_FN_FIND_SDK_TOOL_SUB),)$($3) + ## Disabled fast DEP_IDB based dependencies. #VCC100X86_OLD_DEPS = 1 @@ -82,16 +94,18 @@ TOOL_VCC100X86_PDB = $(dir $(1))$(tolower $(notdir $(1))).$(2) # General Properties used by kBuild TOOL_VCC100X86_COBJSUFF ?= .obj -TOOL_VCC100X86_CFLAGS ?= -TC -c -nologo +TOOL_VCC100X86_CFLAGS ?= -TC -nologo TOOL_VCC100X86_CFLAGS.debug ?= -Zi +TOOL_VCC100X86_CFLAGS.dbgopt ?= -O2 -Zi TOOL_VCC100X86_CFLAGS.release ?= -O2 TOOL_VCC100X86_CFLAGS.profile ?= -O2 TOOL_VCC100X86_CINCS ?= $(PATH_TOOL_VCC100X86_INC) TOOL_VCC100X86_CDEFS ?= TOOL_VCC100X86_CXXOBJSUFF ?= .obj -TOOL_VCC100X86_CXXFLAGS ?= -TP -c -nologo +TOOL_VCC100X86_CXXFLAGS ?= -TP -nologo TOOL_VCC100X86_CXXFLAGS.debug ?= -Zi +TOOL_VCC100X86_CXXFLAGS.dbgopt ?= -O2 -Zi TOOL_VCC100X86_CXXFLAGS.release ?= -O2 TOOL_VCC100X86_CXXFLAGS.profile ?= -O2 TOOL_VCC100X86_CXXINCS ?= $(PATH_TOOL_VCC100X86_INC) $(PATH_TOOL_VCC100X86_ATLMFC_INC) @@ -107,6 +121,8 @@ TOOL_VCC100X86_ARLIBSUFF ?= .lib TOOL_VCC100X86_LDFLAGS ?= -nologo -machine:x86 TOOL_VCC100X86_LDFLAGS.debug ?= -debug +TOOL_VCC100X86_LDFLAGS.dbgopt ?= -debug +TOOL_VCC100X86_LDFLAGS.profile ?= -debug TOOL_VCC100X86_LDFLAGS.release ?= @@ -126,6 +142,25 @@ TOOL_VCC100X86_LDFLAGS.release ?= # @param $(objsuff) Object suffix. TOOL_VCC100X86_COMPILE_C_DEPEND = TOOL_VCC100X86_COMPILE_C_DEPORD = +ifdef KBUILD_USE_KOBJCACHE +TOOL_VCC100X86_COMPILE_C_USES_KOBJCACHE = 1 +TOOL_VCC100X86_COMPILE_C_OUTPUT = $(outbase).i +TOOL_VCC100AMD64_COMPILE_C_OUTPUT_MAYBE = +define TOOL_VCC100X86_COMPILE_C_CMDS + $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\ + --make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\ + --kObjCache-cpp $(outbase).i\ + $(TOOL_VCC100X86_CC) -E\ + $(subst -Zi,-Z7,$(flags))\ + $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ + $(subst /,\\,$(abspath $(source))) \ + --kObjCache-cc $(obj)\ + $(TOOL_VCC100X86_CC) -c\ + $(subst -Zi,-Z7,$(flags))\ + -Fo$(obj)\ + $(outbase).i +endef +else # !KBUILD_USE_KOBJCACHE TOOL_VCC100X86_COMPILE_C_OUTPUT = $(call TOOL_VCC100X86_PDB, $(outbase)-obj,idb) TOOL_VCC100X86_COMPILE_C_OUTPUT_MAYBE = $(call TOOL_VCC100X86_PDB, $(outbase)-obj,pdb) define TOOL_VCC100X86_COMPILE_C_CMDS @@ -137,6 +172,7 @@ define TOOL_VCC100X86_COMPILE_C_CMDS $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100X86_PDB,$(outbase)-obj,idb) endef +endif # !KBUILD_USE_KOBJCACHE ## Compile C++ source. @@ -154,6 +190,25 @@ endef # @param $(objsuff) Object suffix. TOOL_VCC100X86_COMPILE_CXX_DEPEND = TOOL_VCC100X86_COMPILE_CXX_DEPORD = +ifdef KBUILD_USE_KOBJCACHE +TOOL_VCC100X86_COMPILE_CXX_USES_KOBJCACHE = 1 +TOOL_VCC100X86_COMPILE_CXX_OUTPUT = $(outbase).ii +TOOL_VCC100AMD64_COMPILE_CXX_OUTPUT_MAYBE = +define TOOL_VCC100X86_COMPILE_CXX_CMDS + $(QUIET)$(KOBJCACHE) -f $(outbase).koc -d $(PATH_OBJCACHE) -t $(bld_trg).$(bld_trg_arch) -O2 -r\ + --make-dep-fix-case --make-dep-gen-stubs --make-dep-quiet --make-dep-file $(dep)\ + --kObjCache-cpp $(outbase).ii\ + $(TOOL_VCC100X86_CXX) -E\ + $(subst -Zi,-Z7,$(flags))\ + $(addprefix -I, $(incs)) $(addprefix -D, $(defs))\ + $(subst /,\\,$(abspath $(source))) \ + --kObjCache-cc $(obj)\ + $(TOOL_VCC100X86_CXX) -c\ + $(subst -Zi,-Z7,$(flags))\ + -Fo$(obj)\ + $(outbase).ii +endef +else # !KBUILD_USE_KOBJCACHE TOOL_VCC100X86_COMPILE_CXX_OUTPUT = $(call TOOL_VCC100X86_PDB, $(outbase)-obj,idb) TOOL_VCC100X86_COMPILE_CXX_OUTPUT_MAYBE = $(call TOOL_VCC100X86_PDB, $(outbase)-obj,pdb) define TOOL_VCC100X86_COMPILE_CXX_CMDS @@ -165,6 +220,7 @@ define TOOL_VCC100X86_COMPILE_CXX_CMDS $(subst /,\\,$(abspath $(source))) $(QUIET)$(DEP_IDB) -f -s -q -o $(dep) -t $(obj) $(call TOOL_VCC100X86_PDB,$(outbase)-obj,idb) endef +endif # !KBUILD_USE_KOBJCACHE ## @todo configure the assembler template. diff --git a/kBuild/tools/YASM.kmk b/kBuild/tools/YASM.kmk index 8f958f0..8963f14 100644 --- a/kBuild/tools/YASM.kmk +++ b/kBuild/tools/YASM.kmk @@ -1,10 +1,10 @@ -# $Id: YASM.kmk 2413 2010-09-11 17:43:04Z bird $ +# $Id: YASM.kmk 2694 2013-07-22 13:39:36Z bird $ ## @file # kBuild Tool Config - YASM 0.4.0 or later. # # -# Copyright (c) 2006-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# Copyright (c) 2006-2013 knut st. osmundsen <bird-kBuild-spamx@anduin.net> # # This file is part of kBuild. # @@ -67,18 +67,36 @@ TOOL_YASM_ASFLAGS ?= # @param $(objsuff) Object suffix. # TOOL_YASM_COMPILE_AS_OUTPUT = $(outbase).lst +TOOL_YASM_COMPILE_AS_OUTPUT_MAYBE = $(obj).map TOOL_YASM_COMPILE_AS_DEPEND = TOOL_YASM_COMPILE_AS_DEPORD = define TOOL_YASM_COMPILE_AS_CMDS $(QUIET)$(TOOL_YASM_AS)\ - $(flags) $(addsuffix /,$(addprefix -I, $(incs))) $(addprefix -D, $(defs))\ + $(patsubst --mapfile%,--mapfile=$(obj).map,$(flags))\ + $(addsuffix /,$(addprefix -I, $(incs))) $(addprefix -D, $(defs))\ -l $(outbase).lst\ -o $(obj)\ $(abspath $(source)) - $(QUIET)$(REDIRECT) -wo $(dep) -- $(TOOL_YASM_AS)\ - $(flags) $(addsuffix /,$(addprefix -I, $(incs))) $(addprefix -D, $(defs))\ + $(QUIET)$(REDIRECT) -wo $(dep) -- $(TOOL_YASM_AS) -DKBUILD_GENERATING_MAKEFILE_DEPENDENCIES\ + $(patsubst --mapfile%,--mapfile=$(obj).map,$(flags))\ + $(addsuffix /,$(addprefix -I, $(incs))) $(addprefix -D, $(defs))\ -o $(obj) \ $(abspath $(source)) \ -M + if1of ($(KBUILD_HOST), win nt os2) + $(QUIET)$(SED) -e 's/\\\(.\)/\/\1/g' --output "$(dep).tmp" "$(dep)" + else + $(QUIET)$(CP) -f -- "$(dep)" "$(dep).tmp" + endif + $(QUIET)$(APPEND) -n "$(dep).tmp" "" "" + $(QUIET)$(SED) $(if $(intersects $(KBUILD_HOST), win nt os2), -e 's/\\\(.\)/\/\1/g',)\ + -e 's/^[^ ]*: / /'\ + -e 's/ *\\$$(DOLLAR)//'\ + -e 's/^ *//'\ + -e 's/ */\n/g'\ + -e 's/ *\([^ \n][^ \n]*\)/\1:\n/g'\ + --append "$(dep).tmp"\ + "$(dep)" + $(QUIET)$(MV) -f -- "$(dep).tmp" "$(dep)" endef diff --git a/src/kObjCache/Makefile.kmk b/src/kObjCache/Makefile.kmk index 81e2c3d..d2fcae3 100644 --- a/src/kObjCache/Makefile.kmk +++ b/src/kObjCache/Makefile.kmk @@ -1,4 +1,4 @@ -# $Id: Makefile.kmk 2413 2010-09-11 17:43:04Z bird $ +# $Id: Makefile.kmk 2618 2012-08-02 03:34:40Z bird $ ## @file # Sub-makefile for kObjCache. # @@ -28,8 +28,11 @@ include $(PATH_KBUILD)/subheader.kmk PROGRAMS += kObjCache kObjCache_TEMPLATE = BIN +kObjCache_DEFS.release = NASSERT kObjCache_SOURCES = kObjCache.c -kObjCache_LIBS = $(LIB_KUTIL) +kObjCache_LIBS = \ + $(LIB_KDEP) \ + $(LIB_KUTIL) include $(KBUILD_PATH)/subfooter.kmk diff --git a/src/kObjCache/kObjCache.c b/src/kObjCache/kObjCache.c index 0713b1a..d6badb7 100644 --- a/src/kObjCache/kObjCache.c +++ b/src/kObjCache/kObjCache.c @@ -1,10 +1,10 @@ -/* $Id: kObjCache.c 2568 2012-03-18 17:59:32Z bird $ */ +/* $Id: kObjCache.c 2627 2012-08-09 14:12:12Z bird $ */ /** @file * kObjCache - Object Cache. */ /* - * Copyright (c) 2007-2011 knut st. osmundsen <bird-kBuild-spamx@anduin.net> + * Copyright (c) 2007-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> * * This file is part of kBuild. * @@ -29,6 +29,7 @@ #if 0 # define ELECTRIC_HEAP # include "../kmk/electric.h" +# include "../kmk/electric.c" #endif #include <string.h> #include <stdlib.h> @@ -79,6 +80,7 @@ #include "crc32.h" #include "md5.h" +#include "kDep.h" /******************************************************************************* @@ -109,6 +111,12 @@ # define STDERR_FILENO 2 #endif +#define MY_IS_BLANK(a_ch) ((a_ch) == ' ' || (a_ch) == '\t') + +#define KOC_BUF_MIN KOC_BUF_ALIGNMENT +#define KOC_BUF_INCR KOC_BUF_ALIGNMENT +#define KOC_BUF_ALIGNMENT (4U*1024U*1024U) + /******************************************************************************* * Global Variables * @@ -121,6 +129,11 @@ static char g_szErrorPrefix[128]; /** Read buffer shared by the cache components. */ static char g_szLine[KOBJCACHE_MAX_LINE_LEN + 16]; +/** How many times we've moved memory around. */ +static size_t g_cMemMoves = 0; +/** How much memory we've moved. */ +static size_t g_cbMemMoved = 0; + /******************************************************************************* * Internal Functions * @@ -128,9 +141,9 @@ static char g_szLine[KOBJCACHE_MAX_LINE_LEN + 16]; static char *MakePathFromDirAndFile(const char *pszName, const char *pszDir); static char *CalcRelativeName(const char *pszPath, const char *pszDir); static FILE *FOpenFileInDir(const char *pszName, const char *pszDir, const char *pszMode); -static int UnlinkFileInDir(const char *pszName, const char *pszDir); -static int RenameFileInDir(const char *pszOldName, const char *pszNewName, const char *pszDir); -static int DoesFileInDirExist(const char *pszName, const char *pszDir); +static int UnlinkFileInDir(const char *pszName, const char *pszDir); +static int RenameFileInDir(const char *pszOldName, const char *pszNewName, const char *pszDir); +static int DoesFileInDirExist(const char *pszName, const char *pszDir); static void *ReadFileInDir(const char *pszName, const char *pszDir, size_t *pcbFile); @@ -756,13 +769,992 @@ static void AppendArgs(int *pcArgs, char ***ppapszArgs, const char *pszCmdLine, } +/** + * Dependency collector state. + */ +typedef struct KOCDEP +{ + /** The statemachine for processing the preprocessed code stream. */ + enum KOCDEPSTATE + { + kOCDepState_Invalid = 0, + kOCDepState_NeedNewLine, + kOCDepState_NeedHash, + kOCDepState_NeedLine_l, + kOCDepState_NeedLine_l_HaveSpace, + kOCDepState_NeedLine_i, + kOCDepState_NeedLine_n, + kOCDepState_NeedLine_e, + kOCDepState_NeedSpaceBeforeDigit, + kOCDepState_NeedFirstDigit, + kOCDepState_NeedMoreDigits, + kOCDepState_NeedQuote, + kOCDepState_NeedEndQuote + } enmState; + /** Current offset into the filename buffer. */ + uint32_t offFilename; + /** The amount of space currently allocated for the filename buffer. */ + uint32_t cbFilenameAlloced; + /** Pointer to the filename buffer. */ + char *pszFilename; + /** The current dependency file. */ + PDEP pCurDep; +} KOCDEP; +/** Pointer to a KOCDEP. */ +typedef KOCDEP *PKOCDEP; + + +/** + * Initializes the dependency collector state. + * + * @param pDepState The dependency collector state. + */ +static void kOCDepInit(PKOCDEP pDepState) +{ + pDepState->enmState = kOCDepState_NeedHash; + pDepState->offFilename = 0; + pDepState->cbFilenameAlloced = 0; + pDepState->pszFilename = NULL; + pDepState->pCurDep = NULL; +} + + +/** + * Deletes the dependency collector state, releasing all resources. + * + * @param pDepState The dependency collector state. + */ +static void kOCDepDelete(PKOCDEP pDepState) +{ + pDepState->enmState = kOCDepState_Invalid; + free(pDepState->pszFilename); + pDepState->pszFilename = NULL; + depCleanup(); +} + + +/** + * Unescapes a string in place. + * + * @returns The new string length. + * @param psz The string to unescape (input and output). + */ +static size_t kOCDepUnescape(char *psz) +{ + char *pszSrc = psz; + char *pszDst = psz; + char ch; + + while ((ch = *pszSrc++) != '\0') + { + if (ch == '\\') + { + char ch2 = *pszSrc; + if (ch2) + { + pszSrc++; + ch = ch2; + } + /* else: cannot happen / just ignore */ + } + *pszDst++ = ch; + } + + *pszDst = '\0'; + return pszDst - psz; +} + + +/** + * Checks if the character at @a offChar is escaped or not. + * + * @returns 1 if escaped, 0 if not. + * @param pach The string (not terminated). + * @param offChar The offset of the character in question. + */ +static int kOCDepIsEscaped(char *pach, size_t offChar) +{ + while (offChar > 0 && pach[offChar - 1] == '\\') + { + if ( offChar == 1 + || pach[offChar - 2] != '\\') + return 1; + offChar -= 2; + } + return 0; +} + + +static void kOCDepEnter(PKOCDEP pDepState, const char *pszUnescFilename, size_t cchFilename) +{ + if (cchFilename + 1 >= pDepState->cbFilenameAlloced) + { + pDepState->cbFilenameAlloced = (cchFilename + 1 + 15) & ~15; + pDepState->pszFilename = (char *)xrealloc(pDepState->pszFilename, pDepState->cbFilenameAlloced); + } + + memcpy(pDepState->pszFilename, pszUnescFilename, cchFilename); + pDepState->pszFilename[cchFilename] = '\0'; + cchFilename = kOCDepUnescape(pDepState->pszFilename); + + if ( !pDepState->pCurDep + || cchFilename != pDepState->pCurDep->cchFilename + || strcmp(pDepState->pszFilename, pDepState->pCurDep->szFilename)) + pDepState->pCurDep = depAdd(pDepState->pszFilename, cchFilename); +} + + +/** + * This consumes the preprocessor output and generate dependencies from it. + * + * The trick is to look at the line directives and which files get listed there. + * + * @returns The new state. This is a convenience for saving code space and it + * isn't really meant to be of any use to the caller. + * @param pDepState The dependency collector state. + * @param pszInput The input. + * @param cchInput The input length. + */ +static enum KOCDEPSTATE +kOCDepConsumer(PKOCDEP pDepState, const char *pszInput, size_t cchInput) +{ + enum KOCDEPSTATE enmState = pDepState->enmState; + const char *psz; + + while (cchInput > 0) + { + switch (enmState) + { + case kOCDepState_NeedNewLine: + psz = (const char *)memchr(pszInput, '\n', cchInput); + if (!psz) + return enmState; + psz++; + cchInput -= psz - pszInput; + pszInput = psz; + + case kOCDepState_NeedHash: + while (cchInput > 0 && MY_IS_BLANK(*pszInput)) + cchInput--, pszInput++; + if (!cchInput) + return pDepState->enmState = kOCDepState_NeedHash; + + if (*pszInput != '#') + break; + pszInput++; + cchInput--; + enmState = kOCDepState_NeedLine_l; + + case kOCDepState_NeedLine_l: + case kOCDepState_NeedLine_l_HaveSpace: + while (cchInput > 0 && MY_IS_BLANK(*pszInput)) + { + enmState = kOCDepState_NeedLine_l_HaveSpace; + cchInput--, pszInput++; + } + if (!cchInput) + return pDepState->enmState = enmState; + + if (*pszInput != 'l') + { + /* # <digit> "<file>" */ + if (enmState != kOCDepState_NeedLine_l_HaveSpace || !isdigit(*pszInput)) + break; + pszInput++; + cchInput--; + enmState = kOCDepState_NeedMoreDigits; + continue; + } + pszInput++; + if (!--cchInput) + return pDepState->enmState = kOCDepState_NeedLine_i; + + case kOCDepState_NeedLine_i: + if (*pszInput != 'i') + break; + pszInput++; + if (!--cchInput) + return pDepState->enmState = kOCDepState_NeedLine_n; + + case kOCDepState_NeedLine_n: + if (*pszInput != 'n') + break; + pszInput++; + if (!--cchInput) + return pDepState->enmState = kOCDepState_NeedLine_e; + + case kOCDepState_NeedLine_e: + if (*pszInput != 'e') + break; + pszInput++; + if (!--cchInput) + return pDepState->enmState = kOCDepState_NeedSpaceBeforeDigit; + + case kOCDepState_NeedSpaceBeforeDigit: + if (!MY_IS_BLANK(*pszInput)) + break; + pszInput++; + cchInput--; + + case kOCDepState_NeedFirstDigit: + while (cchInput > 0 && MY_IS_BLANK(*pszInput)) + cchInput--, pszInput++; + if (!cchInput) + return pDepState->enmState = kOCDepState_NeedFirstDigit; + + if (!isdigit(*pszInput)) + break; + pszInput++; + cchInput--; + + case kOCDepState_NeedMoreDigits: + while (cchInput > 0 && isdigit(*pszInput)) + cchInput--, pszInput++; + if (!cchInput) + return pDepState->enmState = kOCDepState_NeedMoreDigits; + + case kOCDepState_NeedQuote: + while (cchInput > 0 && MY_IS_BLANK(*pszInput)) + cchInput--, pszInput++; + if (!cchInput) + return pDepState->enmState = kOCDepState_NeedQuote; + + if (*pszInput != '"') + break; + pszInput++; + cchInput--; + + case kOCDepState_NeedEndQuote: + { + uint32_t off = pDepState->offFilename; + for (;;) + { + char ch; + + if (!cchInput) + { + pDepState->offFilename = off; + return pDepState->enmState = kOCDepState_NeedEndQuote; + } + + if (off + 1 >= pDepState->cbFilenameAlloced) + { + if (!pDepState->cbFilenameAlloced) + pDepState->cbFilenameAlloced = 32; + else + pDepState->cbFilenameAlloced *= 2; + pDepState->pszFilename = (char *)xrealloc(pDepState->pszFilename, pDepState->cbFilenameAlloced); + } + pDepState->pszFilename[off] = ch = *pszInput++; + cchInput--; + + if ( ch == '"' + && ( off == 0 + || pDepState->pszFilename[off - 1] != '\\' + || !kOCDepIsEscaped(pDepState->pszFilename, off))) + { + /* Done, unescape and add the file. */ + size_t cchFilename; + + pDepState->pszFilename[off] = '\0'; + cchFilename = kOCDepUnescape(pDepState->pszFilename); + + if ( !pDepState->pCurDep + || cchFilename != pDepState->pCurDep->cchFilename + || strcmp(pDepState->pszFilename, pDepState->pCurDep->szFilename)) + pDepState->pCurDep = depAdd(pDepState->pszFilename, cchFilename); + pDepState->offFilename = 0; + break; + } + + off++; + } + } + } + + /* next newline */ + enmState = kOCDepState_NeedNewLine; + } + + return pDepState->enmState = enmState; +} + + +/** + * Writes the dependencies to the specified file. + * + * @param pDepState The dependency collector state. + * @param pszFilename The name of the dependency file. + * @param pszObjFile The object file name, relative to @a pszObjDir. + * @param pszObjDir The object file directory. + * @param fFixCase Whether to fix the case of dependency files. + * @param fQuiet Whether to be quiet about the dependencies. + * @param fGenStubs Whether to generate stubs. + */ +static void kOCDepWriteToFile(PKOCDEP pDepState, const char *pszFilename, const char *pszObjFile, const char *pszObjDir, + int fFixCase, int fQuiet, int fGenStubs) +{ + char *pszObjFileAbs; + char *psz; + FILE *pFile = fopen(pszFilename, "w"); + if (!pFile) + FatalMsg("Failed to open dependency file '%s': %s\n", pszFilename, strerror(errno)); + + depOptimize(fFixCase, fQuiet); + + /* Make object file name with unix slashes. */ + pszObjFileAbs = MakePathFromDirAndFile(pszObjFile, pszObjDir); + psz = pszObjFileAbs; + while ((psz = strchr(psz, '\\')) != NULL) + *psz++ = '/'; + + fprintf(pFile, "%s:", pszObjFileAbs); + free(pszObjFileAbs); + depPrint(pFile); + if (fGenStubs) + depPrintStubs(pFile); + + if (fclose(pFile) != 0) + FatalMsg("Failed to write dependency file '%s': %s\n", pszFilename, strerror(errno)); +} + + +/** + * Preprocessor output reader state. + */ +typedef struct KOCCPPRD +{ + /** Pointer to the preprocessor output. */ + char *pszBuf; + /** Allocated buffer size. */ + size_t cbBufAlloc; + /** Amount preprocessor output that we've completed optimizations for. */ + size_t cchDstOptimized; + /** Offset to the start of the unoptimized source. */ + size_t offSrcUnoptimized; + /** The offset of the next bits to process. */ + size_t offSrcCur; + /** The offset where to put more raw preprocessor output. */ + size_t offSrcRead; + /** The line number corresponding to offOptimized. */ + uint32_t uOptLineNo; + /** The current line number. */ + uint32_t uCurLineNo; + /** Set if we're done, clear if we're expecting more preprocessor output. */ + int fDone; + /** The saved character at cchOptimized. */ + char chSaved; + /** Whether the optimizations are enabled. */ + int fOptimize; + + /** Buffer holding the current file name (unescaped). */ + char *pszFileNmBuf; + /** The size of the file name buffer. */ + size_t cbFileNmBuf; + /** The length of the current file string. */ + size_t cchCurFileNm; + + /** Line directive / new line sequence buffer. */ + char *pszLineBuf; + /** The size of the buffer pointed to by pszLineBuf. */ + size_t cbLineBuf; + + /** Set if we should work the dependency generator as well. */ + PKOCDEP pDepState; +} KOCCPPRD; +/** Pointer to a preprocessor reader state. */ +typedef KOCCPPRD *PKOCCPPRD; + + +/** + * Allocate the initial C preprocessor output buffer. + * + * @param pCppRd The C preprocessor reader instance. + * @param cbOldCpp The size of the output the last time. This is 0 if + * there was not previous run. + * @param fOptimize Whether optimizations are enabled. + * @param pDepState Pointer to the dependency generator. Must only be set + * if @a fOptimize is also set. + */ +static void kOCCppRdInit(PKOCCPPRD pCppRd, size_t cbOldCpp, int fOptimize, PKOCDEP pDepState) +{ + assert(!pDepState || fOptimize); + + pCppRd->cbBufAlloc = cbOldCpp ? (cbOldCpp + KOC_BUF_INCR) & ~(KOC_BUF_ALIGNMENT - 1) : KOC_BUF_MIN; + pCppRd->pszBuf = xmalloc(pCppRd->cbBufAlloc); + pCppRd->cchCurFileNm = 0; + pCppRd->cchDstOptimized = 0; + pCppRd->offSrcUnoptimized = 0; + pCppRd->offSrcCur = 0; + pCppRd->offSrcRead = 0; + pCppRd->uOptLineNo = 1; + pCppRd->uCurLineNo = 1; + pCppRd->fDone = 0; + pCppRd->chSaved = 0; + pCppRd->fOptimize = fOptimize; + + pCppRd->pszFileNmBuf = NULL; + pCppRd->cbFileNmBuf = 0; + pCppRd->cchCurFileNm = 0; + + pCppRd->pszLineBuf = NULL; + pCppRd->cbLineBuf = 0; + + pCppRd->pDepState = pDepState; +} + + +static void kOCCppRdDelete(PKOCCPPRD pCppRd) +{ + free(pCppRd->pszBuf); + pCppRd->pszBuf = NULL; + + free(pCppRd->pszFileNmBuf); + pCppRd->pszFileNmBuf = NULL; + + free(pCppRd->pszLineBuf); + pCppRd->pszLineBuf = NULL; +} + + +/** + * Allocate more buffer space for the C preprocessor output. + * + * @param pCppRd The C preprocessor reader instance. + */ +static size_t kOCCppRdGrowBuffer(PKOCCPPRD pCppRd) +{ + pCppRd->cbBufAlloc += KOC_BUF_INCR; + pCppRd->pszBuf = xrealloc(pCppRd->pszBuf, pCppRd->cbBufAlloc); + + return pCppRd->cbBufAlloc - pCppRd->offSrcRead; +} + + +static size_t kOCCppRdOptInsert(PKOCCPPRD pCppRd, size_t cchSrcReplaced, const char *pchInsert, size_t cchInsert) +{ + size_t offDelta = 0; + size_t cchAvail; + + pCppRd->offSrcUnoptimized += cchSrcReplaced; + assert(pCppRd->offSrcUnoptimized <= pCppRd->offSrcCur); + cchAvail = pCppRd->offSrcUnoptimized - pCppRd->cchDstOptimized; + if (cchAvail < cchInsert) + { + size_t const cbToMove = pCppRd->offSrcRead - pCppRd->offSrcUnoptimized; + assert(cbToMove <= pCppRd->offSrcRead); + offDelta = cchInsert - cchAvail; + + while (pCppRd->offSrcRead + offDelta >= pCppRd->cbBufAlloc) + kOCCppRdGrowBuffer(pCppRd); + + g_cMemMoves++; + g_cbMemMoved += cbToMove + 1; + memmove(pCppRd->pszBuf + pCppRd->offSrcUnoptimized + offDelta, + pCppRd->pszBuf + pCppRd->offSrcUnoptimized, + cbToMove + 1); + + pCppRd->offSrcRead += offDelta; + pCppRd->offSrcUnoptimized += offDelta; + pCppRd->offSrcCur += offDelta; + assert(pCppRd->offSrcRead < 1 || pCppRd->pszBuf[pCppRd->offSrcRead - 1] != '\0'); + } + + memcpy(pCppRd->pszBuf + pCppRd->cchDstOptimized, pchInsert, cchInsert); + pCppRd->cchDstOptimized += cchInsert; + + return offDelta; +} + + +static void kOCCppRdOptCommit(PKOCCPPRD pCppRd) +{ + size_t cchToCommit = pCppRd->offSrcCur - pCppRd->offSrcUnoptimized; + assert(pCppRd->offSrcUnoptimized <= pCppRd->offSrcCur); + + if (cchToCommit) + { + memmove(pCppRd->pszBuf + pCppRd->cchDstOptimized, pCppRd->pszBuf + pCppRd->offSrcUnoptimized, cchToCommit); + pCppRd->cchDstOptimized += cchToCommit; + pCppRd->offSrcUnoptimized = pCppRd->offSrcCur; + } + + pCppRd->uOptLineNo = pCppRd->uCurLineNo; +} + + + +static char *kOCCppRdOptGetEol(PKOCCPPRD pCppRd, char *pszCur, size_t cbLeft) +{ + char *pszEol = memchr(pszCur, '\n', cbLeft); + if (pszEol) + { + if (pszCur != pszEol && pszEol[-1] == '\r') + pszEol--; + } + else if (pCppRd->fDone && cbLeft) + pszEol = pszCur + cbLeft; + return pszEol; +} + +static void kOCCppRdOptSetFile(PKOCCPPRD pCppRd, const char *pchFile, size_t cchFile) +{ + if (cchFile >= pCppRd->cbFileNmBuf) + { + pCppRd->cbFileNmBuf = (cchFile + 15 + 1) & ~(size_t)15; + pCppRd->pszFileNmBuf = xrealloc(pCppRd->pszFileNmBuf, pCppRd->cbFileNmBuf); + } + memcpy(pCppRd->pszFileNmBuf, pchFile, cchFile); + pCppRd->pszFileNmBuf[cchFile] = '\0'; + pCppRd->cchCurFileNm = cchFile; +} + + +static size_t kOCCppRdOptFmtLine(PKOCCPPRD pCppRd, uint32_t uLine, const char *pchFile, size_t cchFile) +{ + size_t cchUsed; + size_t cbNeeded; + + /* Make sure we've got enough buffer space. */ + cbNeeded = sizeof("#line 4888222111 \"\"\n") + cchFile; + if (cbNeeded > pCppRd->cbLineBuf) + { + pCppRd->cbLineBuf = (cbNeeded + 32 + 15) & ~(size_t)15; + pCppRd->pszLineBuf = xrealloc(pCppRd->pszLineBuf, pCppRd->cbLineBuf); + } + + /* Do the formatting. */ + cchUsed = sprintf(pCppRd->pszLineBuf, "#line %lu", (unsigned long)uLine); + if (cchFile) + { + pCppRd->pszLineBuf[cchUsed++] = ' '; + pCppRd->pszLineBuf[cchUsed++] = '"'; + memcpy(&pCppRd->pszLineBuf[cchUsed], pchFile, cchFile); + cchUsed += cchFile; + pCppRd->pszLineBuf[cchUsed++] = '"'; + } + pCppRd->pszLineBuf[cchUsed++] = '\n'; + pCppRd->pszLineBuf[cchUsed] = '\0'; + + return cchUsed; +} + + +static size_t kOCCppRdOptFmtNewLines(PKOCCPPRD pCppRd, uint32_t cNewLines) +{ + if (cNewLines + 1 > pCppRd->cbLineBuf) + { + pCppRd->cbLineBuf = (cNewLines + 1 + 32 + 15) & ~(size_t)15; + pCppRd->pszLineBuf = xrealloc(pCppRd->pszLineBuf, pCppRd->cbLineBuf); + } + + memset(pCppRd->pszLineBuf, '\n', cNewLines); + pCppRd->pszLineBuf[cNewLines] = '\0'; + return cNewLines; +} + + +static size_t kOCCppRdOptFlush(PKOCCPPRD pCppRd, size_t offSrcCur, int fLineDirNext) +{ + size_t offDelta = 0; + size_t const offSrcUnoptimized = pCppRd->offSrcUnoptimized; + assert(offSrcUnoptimized <= offSrcCur); + + if (offSrcCur > offSrcUnoptimized) + { + /* + * We've got unflushed whitelines. + */ + size_t const cchSrcInQuestion = offSrcCur - offSrcUnoptimized; + uint32_t const cLinesInQuestion = pCppRd->uCurLineNo - pCppRd->uOptLineNo; + size_t cchLineDir; + + if ( cLinesInQuestion <= 7 + || (cchLineDir = kOCCppRdOptFmtLine(pCppRd, pCppRd->uCurLineNo, NULL, 0)) >= cLinesInQuestion) + cchLineDir = kOCCppRdOptFmtNewLines(pCppRd, cLinesInQuestion); + + offDelta = kOCCppRdOptInsert(pCppRd, cchSrcInQuestion, pCppRd->pszLineBuf, cchLineDir); + } + + (void)fLineDirNext; /* Use later if required. */ + return offDelta; +} + + +static int kOCCppRdOptParseLine(PKOCCPPRD pCppRd, char *pszCur, char *pszEol, + uint32_t *puNewLineNo, char **ppszNewFile, size_t *pcchNewFile) +{ + char *psz = pszCur; + uint32_t uNewLineNo; + int fIsShort; + + /* + * Check if it's a #line directive of some kind and parse it. + */ + if (*psz != '#') + return 0; + psz++; + + fIsShort = MY_IS_BLANK(*psz); + while (MY_IS_BLANK(*psz)) + psz++; + + if ( psz[0] == 'l' + && psz[1] == 'i' + && psz[2] == 'n' + && psz[3] == 'e' + && MY_IS_BLANK(psz[4]) ) + { + fIsShort = 0; + psz += 5; + while (MY_IS_BLANK(*psz)) + psz++; + } + else if (fIsShort && isdigit(*psz)) + fIsShort = 1; + else + return 0; + + /* Parse the line number. */ + if (!isdigit(*psz)) + return 0; + + uNewLineNo = *psz++ - '0'; + while (isdigit(*psz)) + { + uNewLineNo *= 10; + uNewLineNo += *psz++ - '0'; + } + if ( psz != pszEol + && !MY_IS_BLANK(*psz)) + return 0; + + /* + * The file name part is optional. + */ + while (MY_IS_BLANK(*psz)) + psz++; + + if ( psz != pszEol + && *psz == '"') + { + *ppszNewFile = ++psz; + while ( psz != pszEol + && ( *psz != '"' + || ( psz[-1] == '\\' + && kOCDepIsEscaped(psz, psz - *ppszNewFile)) ) + ) + psz++; + if (psz == pszEol) + { + /** @todo complain? */ + return 0; + } + *pcchNewFile = psz - *ppszNewFile; + + do + psz++; + while (psz != pszEol && MY_IS_BLANK(*psz)); + } + else + { + /* No file given => Same as the current. */ + *ppszNewFile = pCppRd->cchCurFileNm ? pCppRd->pszFileNmBuf : NULL; + *pcchNewFile = pCppRd->cchCurFileNm; + } + if (psz != pszEol) + { + /** @todo complain? */ + return 0; + } + + *puNewLineNo = uNewLineNo; + return 1; +} + + +static char *kOCCppRdOptHandleLine(PKOCCPPRD pCppRd, char *pszCur, size_t *pcbLeft, int *pfEmptyLine, char *pszEol) +{ + size_t const offSrcLine = pCppRd->offSrcCur; + size_t const cchSrcLine = pszEol - pCppRd->pszBuf - (pCppRd->fOptimize & 2 ? pCppRd->offSrcUnoptimized : pCppRd->offSrcCur); + size_t const cbLeftAssert = *pcbLeft; + char *pszNewFile; + size_t cchNewFile; + uint32_t uNewLineNo; + assert(*pszEol == '\r' || *pszEol == '\n' || *pszEol == '\0'); + + /* Advance to the end of the line before we do anything. This can be a + little confusing but it saves effort and avoid trouble in the end. */ + pCppRd->offSrcCur = pszEol - pCppRd->pszBuf; + *pcbLeft -= pszEol - pszCur; + assert(*pcbLeft <= cbLeftAssert); (void)cbLeftAssert; + + /* + * Try parse the directive a '#line' one.... + */ + if (!kOCCppRdOptParseLine(pCppRd, pszCur, pszEol, &uNewLineNo, &pszNewFile, &cchNewFile)) + { + /* + * No line directive. Flush pending optimizations and indicate that + * the line isn't empty and needs to be commited at EOL. + */ + kOCCppRdOptFlush(pCppRd, offSrcLine, 0); + *pfEmptyLine = 0; + } + else + { + char *pszCurFile = pCppRd->cchCurFileNm ? pCppRd->pszFileNmBuf : NULL; + if ( pszNewFile == pszCurFile + || ( cchNewFile == pCppRd->cchCurFileNm + && !memcmp(pszNewFile, pszCurFile, cchNewFile)) ) + { + /* + * A #line directive specifying the same file. + */ + if (uNewLineNo >= pCppRd->uCurLineNo) + *pfEmptyLine = 1; + else + { + /* + * It went backwards, so we need to flush the old section of + * the file and emit another directive for starting the new one. + */ + size_t cchLineDir; + if (!(pCppRd->fOptimize & 2)) + kOCCppRdOptFlush(pCppRd, offSrcLine, 1); + + cchLineDir = kOCCppRdOptFmtLine(pCppRd, uNewLineNo, NULL, 0) - 1; /* sans \n */ + kOCCppRdOptInsert(pCppRd, cchSrcLine, pCppRd->pszLineBuf, cchLineDir); + + *pfEmptyLine = 0; + } + } + else + { + /* + * The #line directive changed the file. + */ + size_t cchLineDir; + + kOCCppRdOptSetFile(pCppRd, pszNewFile, cchNewFile); /* save to do this early */ + if (!(pCppRd->fOptimize & 2)) + kOCCppRdOptFlush(pCppRd, offSrcLine, 1); + + cchLineDir = kOCCppRdOptFmtLine(pCppRd, uNewLineNo, pCppRd->pszFileNmBuf, cchNewFile) - 1; /* sans \n */ + kOCCppRdOptInsert(pCppRd, cchSrcLine, pCppRd->pszLineBuf, cchLineDir); + + if (pCppRd->pDepState) + kOCDepEnter(pCppRd->pDepState, pCppRd->pszFileNmBuf, cchNewFile); + + *pfEmptyLine = 0; + } + + pCppRd->uCurLineNo = uNewLineNo - 1; + } + + return pCppRd->pszBuf + pCppRd->offSrcCur; +} + + +static void kOCCppRdOpt(PKOCCPPRD pCppRd) +{ + size_t cch; + char *pszEol; + char *pszCur = pCppRd->pszBuf + pCppRd->offSrcCur; + size_t cbTodo = pCppRd->offSrcRead - pCppRd->offSrcCur; + int fEmptyLine = 1; + + while (cbTodo > 0) + { + switch (*pszCur) + { + case ' ': + case '\t': + break; + + case '\n': + pCppRd->offSrcCur = pszCur - pCppRd->pszBuf + 1; + pCppRd->uCurLineNo++; + if (!fEmptyLine) + kOCCppRdOptCommit(pCppRd); + fEmptyLine = 1; + break; + + case '\r': /* "\r\n" -> "\n" */ + if (cbTodo <= 1 && !pCppRd->fDone) + return; + if (pszCur[1] == '\n' && !fEmptyLine) + { + /* Commit the part up to the '\r' first, replace '\r\n' with '\n'. */ + pCppRd->offSrcCur = pszCur - pCppRd->pszBuf; + kOCCppRdOptCommit(pCppRd); + + pCppRd->offSrcCur += 2; + kOCCppRdOptInsert(pCppRd, 2, "\n", 1); + + assert(cbTodo >= 2); + cbTodo -= 2; + pszCur += 2; + + fEmptyLine = 1; + continue; + } + break; + + case '#': + pszEol = kOCCppRdOptGetEol(pCppRd, pszCur + 1, cbTodo - 1); + if (!pszEol) + return; + pszCur = kOCCppRdOptHandleLine(pCppRd, pszCur, &cbTodo, &fEmptyLine, pszEol); + continue; + + default: + /* + * Some non-white stuff encountered, flush pending white + * line optimizations and skip to the end of the line. + */ + fEmptyLine = 0; + pszEol = kOCCppRdOptGetEol(pCppRd, pszCur + 1, cbTodo - 1); + if (!pszEol) + return; + cch = pszEol - pszCur; + + pszCur += kOCCppRdOptFlush(pCppRd, pCppRd->offSrcCur, 0); + + assert(cch <= cbTodo); + cbTodo -= cch; + pszCur += cch; + continue; + } + + cbTodo--; + pszCur++; + } +} + + +static void kOCCppRdOptFinalize(PKOCCPPRD pCppRd) +{ + pCppRd->fDone = 1; + assert(pCppRd->offSrcRead < 1 || pCppRd->pszBuf[pCppRd->offSrcRead - 1] != '\0'); + pCppRd->pszBuf[pCppRd->offSrcRead] = '\0'; + kOCCppRdOpt(pCppRd); + + assert(pCppRd->offSrcCur == pCppRd->offSrcRead); + kOCCppRdOptFlush(pCppRd, pCppRd->offSrcCur, 0); +} + + + +/** + * Read C preprocessor output from the given file descriptor, optionally + * optimzing it. + * + * @returns Number of bytes read. 0 indicates end of file. + * + * @param pCppRd The C preprocessor reader instance. + * @param fdIn The file descriptor to read the raw preprocessor output + * from. + * @param ppszRet Where to return the pointer to the output. + * + * @remarks Won't return on error, calls FatalDie on those occasions. + */ +static long kOCCppRdRead(PKOCCPPRD pCppRd, int fdIn, const char **ppszRet) +{ + size_t cbLeft; + long cbRead; + + if (pCppRd->fOptimize) + { + /* + * Optimize the C preprocessor output on the way thru. + */ + size_t const cchOldOptimized = pCppRd->cchDstOptimized; + if (pCppRd->chSaved) + pCppRd->pszBuf[pCppRd->cchDstOptimized] = pCppRd->chSaved; + + do + { + /* Read more raw C preprocessor output. */ + cbLeft = pCppRd->cbBufAlloc - pCppRd->offSrcRead; + if (cbLeft <= 1) + cbLeft = kOCCppRdGrowBuffer(pCppRd); + + do + cbRead = read(fdIn, pCppRd->pszBuf + pCppRd->offSrcRead, (long)(cbLeft - 1)); + while (cbRead < 0 && errno == EINTR); + if (cbRead < 0) + FatalDie("kOCCppRdRead - read(%d,,%ld) failed: %s\n", + fdIn, (long)(cbLeft - 1), strerror(errno)); + pCppRd->offSrcRead += cbRead; + + /* Optimize it. */ + if (!cbRead) + { + kOCCppRdOptFinalize(pCppRd); + break; + } + kOCCppRdOpt(pCppRd); + } while (pCppRd->cchDstOptimized == cchOldOptimized); + + *ppszRet = &pCppRd->pszBuf[cchOldOptimized]; + pCppRd->chSaved = pCppRd->pszBuf[pCppRd->cchDstOptimized]; + pCppRd->pszBuf[pCppRd->cchDstOptimized] = '\0'; + cbRead = (long)(pCppRd->cchDstOptimized - cchOldOptimized); + } + else + { + /* + * Pass thru. + */ + char *pszBuf; + cbLeft = pCppRd->cbBufAlloc - pCppRd->offSrcRead; + if (cbLeft <= 1) + cbLeft = kOCCppRdGrowBuffer(pCppRd); + pszBuf = pCppRd->pszBuf + pCppRd->offSrcRead; + + do + cbRead = read(fdIn, pszBuf, (long)(cbLeft - 1)); + while (cbRead < 0 && errno == EINTR); + if (cbRead < 0) + FatalDie("kOCCppRdRead - read(%d,,%ld) failed: %s\n", + fdIn, (long)(cbLeft - 1), strerror(errno)); + + *ppszRet = pszBuf; + pCppRd->offSrcRead += cbRead; + pszBuf[cbRead] = '\0'; + } + + return cbRead; +} + + +/** + * Grabs the output buffer from the C preprocessor reader. + * + * @param pCppRd The C preprocessor reader instance. + * @param ppszRet Where to return the pointer to the output. + * @param pcbRet Where to return the size of the output. + */ +static void kOCCppRdGrabOutput(PKOCCPPRD pCppRd, char **ppszRet, size_t *pcbRet) +{ + assert(pCppRd->offSrcRead < 1 || pCppRd->pszBuf[pCppRd->offSrcRead - 1] != '\0'); + *ppszRet = pCppRd->pszBuf; + *pcbRet = pCppRd->fOptimize ? pCppRd->cchDstOptimized : pCppRd->offSrcRead; + pCppRd->pszBuf = NULL; + pCppRd->offSrcRead = 0; +} + + + /** A checksum list entry. - * We keep a list checksums (of precompiler output) that matches, The planned - * matching algorithm doesn't require the precompiler output to be indentical, - * only to produce the same object files. + * We keep a list checksums (of preprocessor output) that matches. + * + * The matching algorithm doesn't require the preprocessor output to be + * indentical, only to produce the same object files. */ typedef struct KOCSUM { @@ -782,8 +1774,7 @@ typedef const KOCSUM *PCKOCSUM; /** - * Temporary context record used when calculating - * the checksum of some data. + * Temporary context record used when calculating the checksum of some data. */ typedef struct KOCSUMCTX { @@ -1079,28 +2070,41 @@ typedef struct KOCENTRY char *pszAbsPath; /** Set if the object needs to be (re)compiled. */ unsigned fNeedCompiling; - /** Whether the precompiler runs in piped mode. If clear it's file + /** Whether the preprocessor runs in piped mode. If clear it's file * mode (it could be redirected stdout, but that's essentially the * same from our point of view). */ unsigned fPipedPreComp; - /** Whether the compiler runs in piped mode (precompiler output on stdin). */ + /** Whether the compiler runs in piped mode (preprocessor output on stdin). */ unsigned fPipedCompile; - /** The name of the pipe that we're feeding the precompiled output to the + /** The name of the pipe that we're feeding the preprocessed output to the * compiler via. This is a Windows thing. */ char *pszNmPipeCompile; + /** Name of the dependency file (generated from #line statements in the + * preprocessor output). */ + char *pszMakeDepFilename; + /** Whether to fix the case of the make depedencies. */ + int fMakeDepFixCase; + /** Whether to do the make dependencies quietly. */ + int fMakeDepQuiet; + /** Whether to generate stubs for headers files. */ + int fMakeDepGenStubs; + /** The dependency collector state. */ + KOCDEP DepState; + /** Whether the optimizations are enabled. */ + int fOptimizeCpp; /** Cache entry key that's used for some quick digest validation. */ uint32_t uKey; /** The file data. */ struct KOCENTRYDATA { - /** The name of file containing the precompiler output. */ + /** The name of file containing the preprocessor output. */ char *pszCppName; - /** Pointer to the precompiler output. */ + /** Pointer to the preprocessor output. */ char *pszCppMapping; - /** The size of the precompiler output. 0 if not determined. */ + /** The size of the preprocessor output. 0 if not determined. */ size_t cbCpp; - /** The precompiler output checksums that will produce the cached object. */ + /** The preprocessor output checksums that will produce the cached object. */ KOCSUM SumHead; /** The number of milliseconds spent precompiling. */ uint32_t cMsCpp; @@ -1116,6 +2120,7 @@ typedef struct KOCENTRY /** The number of milliseconds spent compiling. */ uint32_t cMsCompile; /** @todo need a list of additional output files for MSC. */ + /** @todo need compiler output (warnings). */ /** The target os/arch identifier. */ char *pszTarget; @@ -1147,6 +2152,8 @@ static PKOCENTRY kOCEntryCreate(const char *pszFilename) */ pEntry = xmallocz(sizeof(*pEntry)); + kOCDepInit(&pEntry->DepState); + kOCSumInit(&pEntry->New.SumHead); kOCSumInit(&pEntry->Old.SumHead); @@ -1180,6 +2187,9 @@ static void kOCEntryDestroy(PKOCENTRY pEntry) free(pEntry->pszDir); free(pEntry->pszAbsPath); free(pEntry->pszNmPipeCompile); + free(pEntry->pszMakeDepFilename); + + kOCDepDelete(&pEntry->DepState); kOCSumDeleteChain(&pEntry->New.SumHead); kOCSumDeleteChain(&pEntry->Old.SumHead); @@ -1217,14 +2227,19 @@ static void kOCEntryDestroy(PKOCENTRY pEntry) * @param pEntry The cache entry. * @param papszArgv The argument vector. * @param cArgc The number of entries in the vector. - * @param pszIgnorePath Path to ignore when encountered at the end of arguments. - * (Not quite safe for simple file names, but what the heck.) + * @param pszIgnorePath1 Path to ignore when encountered at the end of + * arguments. (Not quite safe for simple file names, + * but what the heck.) + * @param pszIgnorePath2 Path to ignore when encountered at the end of + * arguments. (Not quite safe for simple file names, + * but what the heck.) * @param pSum Where to store the check sum. */ static void kOCEntryCalcArgvSum(PKOCENTRY pEntry, const char * const *papszArgv, unsigned cArgc, - const char *pszIgnorePath, PKOCSUM pSum) + const char *pszIgnorePath1, const char *pszIgnorePath2, PKOCSUM pSum) { - size_t cchIgnorePath = strlen(pszIgnorePath); + size_t cchIgnorePath1 = strlen(pszIgnorePath1); + size_t cchIgnorePath2 = pszIgnorePath2 ? strlen(pszIgnorePath2) : ~(size_t)0; KOCSUMCTX Ctx; unsigned i; @@ -1232,8 +2247,10 @@ static void kOCEntryCalcArgvSum(PKOCENTRY pEntry, const char * const *papszArgv, for (i = 0; i < cArgc; i++) { size_t cch = strlen(papszArgv[i]); - if ( cch < cchIgnorePath - || !ArePathsIdenticalN(papszArgv[i] + cch - cchIgnorePath, pszIgnorePath, cch)) + if ( ( cch < cchIgnorePath1 + || !ArePathsIdenticalN(papszArgv[i] + cch - cchIgnorePath1, pszIgnorePath1, cch)) + && ( cch < cchIgnorePath2 + || !ArePathsIdenticalN(papszArgv[i] + cch - cchIgnorePath2, pszIgnorePath2, cch)) ) kOCSumUpdate(pSum, &Ctx, papszArgv[i], cch + 1); } kOCSumFinalize(pSum, &Ctx); @@ -1410,7 +2427,8 @@ static void kOCEntryRead(PKOCENTRY pEntry) { KOCSUM Sum; kOCEntryCalcArgvSum(pEntry, (const char * const *)pEntry->Old.papszArgvCompile, - pEntry->Old.cArgvCompile, pEntry->Old.pszObjName, &Sum); + pEntry->Old.cArgvCompile, pEntry->Old.pszObjName, pEntry->Old.pszCppName, + &Sum); fBad = !kOCSumIsEqual(&pEntry->Old.SumCompArgv, &Sum); } if (fBad) @@ -1597,7 +2615,8 @@ static void kOCEntrySetCompileArgv(PKOCENTRY pEntry, const char * const *papszAr pEntry->New.papszArgvCompile[i] = xstrdup(papszArgvCompile[i]); pEntry->New.papszArgvCompile[i] = NULL; /* for exev/spawnv */ - kOCEntryCalcArgvSum(pEntry, papszArgvCompile, cArgvCompile, pEntry->New.pszObjName, &pEntry->New.SumCompArgv); + kOCEntryCalcArgvSum(pEntry, papszArgvCompile, cArgvCompile, pEntry->New.pszObjName, pEntry->New.pszCppName, + &pEntry->New.SumCompArgv); kOCSumInfo(&pEntry->New.SumCompArgv, 4, "comp-argv"); /* @@ -1634,11 +2653,11 @@ static void kOCEntrySetTarget(PKOCENTRY pEntry, const char *pszTarget) /** - * Sets the precompiler output filename. - * We don't generally care if this matches the old name or not. + * Sets the preprocessor output filename. We don't generally care if this + * matches the old name or not. * * @param pEntry The cache entry. - * @param pszCppName The precompiler output filename. + * @param pszCppName The preprocessor output filename. */ static void kOCEntrySetCppName(PKOCENTRY pEntry, const char *pszCppName) { @@ -1648,10 +2667,10 @@ static void kOCEntrySetCppName(PKOCENTRY pEntry, const char *pszCppName) /** - * Sets the piped mode of the precompiler and compiler. + * Sets the piped mode of the preprocessor and compiler. * * @param pEntry The cache entry. - * @param fRedirPreCompStdOut Whether the precompiler is in piped mode. + * @param fRedirPreCompStdOut Whether the preprocessor is in piped mode. * @param fRedirCompileStdIn Whether the compiler is in piped mode. * @param pszNmPipeCompile The name of the named pipe to use to feed * the microsoft compiler. @@ -1666,6 +2685,37 @@ static void kOCEntrySetPipedMode(PKOCENTRY pEntry, int fRedirPreCompStdOut, int /** + * Sets the dependency file. + * + * @param pEntry The cache entry. + * @param pszMakeDepFilename The dependency filename. + * @param fMakeDepFixCase Whether to fix the case of dependency files. + * @param fMakeDepQuiet Whether to be quiet about the dependencies. + * @param fMakeDepGenStubs Whether to generate stubs. + */ +static void kOCEntrySetDepFilename(PKOCENTRY pEntry, const char *pszMakeDepFilename, + int fMakeDepFixCase, int fMakeDepQuiet, int fMakeDepGenStubs) +{ + pEntry->pszMakeDepFilename = xstrdup(pszMakeDepFilename); + pEntry->fMakeDepFixCase = fMakeDepFixCase; + pEntry->fMakeDepQuiet = fMakeDepQuiet; + pEntry->fMakeDepGenStubs = fMakeDepGenStubs; +} + + +/** + * Configures the preprocessor output optimizations. + * + * @param pEntry The cache entry. + * @param fOptimizeCpp The one and only flag, so far. + */ +static void kOCEntrySetOptimizations(PKOCENTRY pEntry, int fOptimizeCpp) +{ + pEntry->fOptimizeCpp = fOptimizeCpp; +} + + +/** * Spawns a child in a synchronous fashion. * Terminating on failure. * @@ -1824,17 +2874,17 @@ static pid_t kOCEntrySpawnChild(PCKOCENTRY pEntry, uint32_t *pcMs, const char * pid = _spawnvp(_P_NOWAIT, papszArgv[0], papszArgv); # endif if (pid == -1) - FatalDie("precompile - _spawnvp failed: %s\n", strerror(errno)); + FatalDie("preprocess - _spawnvp failed: %s\n", strerror(errno)); #else pid = fork(); if (!pid) { execvp(papszArgv[0], (char **)papszArgv); - FatalDie("precompile - execvp failed: %s\n", strerror(errno)); + FatalDie("preprocess - execvp failed: %s\n", strerror(errno)); } if (pid == -1) - FatalDie("precompile - fork() failed: %s\n", strerror(errno)); + FatalDie("preprocess - fork() failed: %s\n", strerror(errno)); #endif /* @@ -1902,13 +2952,14 @@ static void kOCEntryWaitChild(PCKOCENTRY pEntry, uint32_t *pcMs, pid_t pid, cons * Creates a pipe for setting up redirected stdin/stdout. * * @param pEntry The cache entry. - * @param pFDs Where to store the two file descriptors. + * @param paFDs Where to store the two file descriptors. * @param pszMsg The operation message for info/error messages. * @param pszPipeName The pipe name if it is supposed to be named. (Windows only.) + * @param fText Whether to read text mode or binary mode. */ -static void kOCEntryCreatePipe(PKOCENTRY pEntry, int *pFDs, const char *pszPipeName, const char *pszMsg) +static void kOCEntryCreatePipe(PKOCENTRY pEntry, int *paFDs, const char *pszPipeName, const char *pszMsg, int fText) { - pFDs[0] = pFDs[1] = -1; + paFDs[0] = paFDs[1] = -1; #if defined(__WIN__) if (pszPipeName) { @@ -1924,18 +2975,19 @@ static void kOCEntryCreatePipe(PKOCENTRY pEntry, int *pFDs, const char *pszPipeN if (hPipe == INVALID_HANDLE_VALUE) FatalDie("%s - CreateNamedPipe(%s) failed: %d\n", pszMsg, pszPipeName, GetLastError()); - pFDs[1 /* write */] = _open_osfhandle((intptr_t)hPipe, _O_WRONLY | _O_TEXT | _O_NOINHERIT); - if (pFDs[1 /* write */] == -1) + paFDs[1 /* write */] = _open_osfhandle((intptr_t)hPipe, _O_WRONLY | _O_TEXT | _O_NOINHERIT); + if (paFDs[1 /* write */] == -1) FatalDie("%s - _open_osfhandle failed: %d\n", pszMsg, strerror(errno)); } - else if (_pipe(pFDs, 0, _O_NOINHERIT | _O_BINARY) < 0) + else if ( _pipe(paFDs, 256*1024, _O_NOINHERIT | (fText ? _O_TEXT : _O_BINARY)) < 0 + && _pipe(paFDs, 0, _O_NOINHERIT | (fText ? _O_TEXT : _O_BINARY)) < 0) #else - if (pipe(pFDs) < 0) + if (pipe(paFDs) < 0) #endif FatalDie("%s - pipe failed: %s\n", pszMsg, strerror(errno)); #if !defined(__WIN__) - fcntl(pFDs[0], F_SETFD, FD_CLOEXEC); - fcntl(pFDs[1], F_SETFD, FD_CLOEXEC); + fcntl(paFDs[0], F_SETFD, FD_CLOEXEC); + fcntl(paFDs[1], F_SETFD, FD_CLOEXEC); #endif (void)pEntry; @@ -1957,7 +3009,7 @@ static void kOCEntrySpawnProducer(PKOCENTRY pEntry, const char * const *papszArg int fds[2]; pid_t pid; - kOCEntryCreatePipe(pEntry, fds, NULL, pszMsg); + kOCEntryCreatePipe(pEntry, fds, NULL, pszMsg, pEntry->fOptimizeCpp); pid = kOCEntrySpawnChild(pEntry, &pEntry->New.cMsCpp, papszArgv, cArgv, -1, fds[1 /* write */], pszMsg); pfnConsumer(pEntry, fds[0 /* read */]); @@ -1981,7 +3033,7 @@ static void kOCEntrySpawnConsumer(PKOCENTRY pEntry, const char * const *papszArg int fds[2]; pid_t pid; - kOCEntryCreatePipe(pEntry, fds, pEntry->pszNmPipeCompile, pszMsg); + kOCEntryCreatePipe(pEntry, fds, pEntry->pszNmPipeCompile, pszMsg, 0 /*fText*/); pid = kOCEntrySpawnChild(pEntry, &pEntry->New.cMsCompile, papszArgv, cArgv, fds[0 /* read */], -1, pszMsg); #ifdef __WIN__ if (pEntry->pszNmPipeCompile && !ConnectNamedPipe((HANDLE)_get_osfhandle(fds[1 /* write */]), NULL)) @@ -2015,14 +3067,14 @@ static void kOCEntrySpawnTee(PKOCENTRY pEntry, const char * const *papszProdArgv /* * The producer. */ - kOCEntryCreatePipe(pEntry, fds, NULL, pszMsg); + kOCEntryCreatePipe(pEntry, fds, NULL, pszMsg, pEntry->fOptimizeCpp); pidConsumer = kOCEntrySpawnChild(pEntry, &pEntry->New.cMsCpp, papszProdArgv, cProdArgv, -1, fds[1 /* write */], pszMsg); fdIn = fds[0 /* read */]; /* * The consumer. */ - kOCEntryCreatePipe(pEntry, fds, pEntry->pszNmPipeCompile, pszMsg); + kOCEntryCreatePipe(pEntry, fds, pEntry->pszNmPipeCompile, pszMsg, 0 /*fText*/); pidProducer = kOCEntrySpawnChild(pEntry, &pEntry->New.cMsCompile, papszConsArgv, cConsArgv, fds[0 /* read */], -1, pszMsg); fdOut = fds[1 /* write */]; @@ -2040,7 +3092,7 @@ static void kOCEntrySpawnTee(PKOCENTRY pEntry, const char * const *papszProdArgv /** - * Reads the output from the precompiler. + * Reads the output from the preprocessor. * * @param pEntry The cache entry. New.cbCpp and New.pszCppMapping will be updated. * @param pWhich Specifies what to read (old/new). @@ -2059,14 +3111,14 @@ static int kOCEntryReadCppOutput(PKOCENTRY pEntry, struct KOCENTRYDATA *pWhich, return -1; } - InfoMsg(3, "precompiled file is %lu bytes long\n", (unsigned long)pWhich->cbCpp); + InfoMsg(3, "preprocessed file is %lu bytes long\n", (unsigned long)pWhich->cbCpp); return 0; } /** - * Worker for kOCEntryPreCompile and calculates the checksum of - * the precompiler output. + * Worker for kOCEntryPreProcess and calculates the checksum of + * the preprocessor output. * * @param pEntry The cache entry. NewSum will be updated. */ @@ -2081,62 +3133,42 @@ static void kOCEntryCalcChecksum(PKOCENTRY pEntry) /** - * This consumes the precompiler output and checksums it. + * This consumes the preprocessor output and checksums it. * * @param pEntry The cache entry. - * @param fdIn The precompiler output pipe. + * @param fdIn The preprocessor output pipe. * @param fdOut The compiler input pipe, -1 if no compiler. */ -static void kOCEntryPreCompileConsumer(PKOCENTRY pEntry, int fdIn) +static void kOCEntryPreProcessConsumer(PKOCENTRY pEntry, int fdIn) { KOCSUMCTX Ctx; - long cbLeft; - long cbAlloc; - char *psz; + KOCCPPRD CppRd; kOCSumInitWithCtx(&pEntry->New.SumHead, &Ctx); - cbAlloc = pEntry->Old.cbCpp ? ((long)pEntry->Old.cbCpp + 4*1024*1024 + 4096) & ~(4*1024*1024 - 1) : 4*1024*1024; - cbLeft = cbAlloc; - pEntry->New.pszCppMapping = psz = xmalloc(cbAlloc); + kOCCppRdInit(&CppRd, pEntry->Old.cbCpp, pEntry->fOptimizeCpp, + pEntry->pszMakeDepFilename ? &pEntry->DepState : NULL); + for (;;) { /* * Read data from the pipe. */ - long cbRead = read(fdIn, psz, cbLeft - 1); + const char *psz; + long cbRead = kOCCppRdRead(&CppRd, fdIn, &psz); if (!cbRead) break; - if (cbRead < 0) - { - if (errno == EINTR) - continue; - FatalDie("precompile - read(%d,,%ld) failed: %s\n", - fdIn, (long)cbLeft, strerror(errno)); - } /* * Process the data. */ - psz[cbRead] = '\0'; kOCSumUpdate(&pEntry->New.SumHead, &Ctx, psz, cbRead); - - /* - * Advance. - */ - psz += cbRead; - cbLeft -= cbRead; - if (cbLeft <= 1) - { - size_t off = psz - pEntry->New.pszCppMapping; - cbLeft += 4*1024*1024; - cbAlloc += 4*1024*1024; - pEntry->New.pszCppMapping = xrealloc(pEntry->New.pszCppMapping, cbAlloc); - psz = pEntry->New.pszCppMapping + off; - } + if (pEntry->pszMakeDepFilename && !pEntry->fOptimizeCpp) + kOCDepConsumer(&pEntry->DepState, psz, cbRead); } close(fdIn); - pEntry->New.cbCpp = cbAlloc - cbLeft; + kOCCppRdGrabOutput(&CppRd, &pEntry->New.pszCppMapping, &pEntry->New.cbCpp); + kOCCppRdDelete(&CppRd); kOCSumFinalize(&pEntry->New.SumHead, &Ctx); kOCSumInfo(&pEntry->New.SumHead, 4, "cpp (pipe)"); } @@ -2145,24 +3177,25 @@ static void kOCEntryPreCompileConsumer(PKOCENTRY pEntry, int fdIn) /** - * Run the precompiler and calculate the checksum of the output. + * Run the preprocessor and calculate the checksum of the output. * * @param pEntry The cache entry. - * @param papszArgvPreComp The argument vector for executing precompiler. The cArgvPreComp'th argument must be NULL. + * @param papszArgvPreComp The argument vector for executing preprocessor. + * The cArgvPreComp'th argument must be NULL. * @param cArgvPreComp The number of arguments. */ -static void kOCEntryPreCompile(PKOCENTRY pEntry, const char * const *papszArgvPreComp, unsigned cArgvPreComp) +static void kOCEntryPreProcess(PKOCENTRY pEntry, const char * const *papszArgvPreComp, unsigned cArgvPreComp) { /* - * If we're executing the precompiler in piped mode, it's relatively simple. + * If we're executing the preprocessor in piped mode, it's relatively simple. */ if (pEntry->fPipedPreComp) - kOCEntrySpawnProducer(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", - kOCEntryPreCompileConsumer); + kOCEntrySpawnProducer(pEntry, papszArgvPreComp, cArgvPreComp, "preprocess", + kOCEntryPreProcessConsumer); else { /* - * Rename the old precompiled output to '-old' so the precompiler won't + * Rename the old preprocessed output to '-old' so the preprocessor won't * overwrite it when we execute it. */ if ( pEntry->Old.pszCppName @@ -2183,19 +3216,25 @@ static void kOCEntryPreCompile(PKOCENTRY pEntry, const char * const *papszArgvPr } /* - * Precompile it and calculate the checksum on the output. + * Preprocess it and calculate the checksum on the output. */ InfoMsg(3, "precompiling -> '%s'...\n", pEntry->New.pszCppName); - kOCEntrySpawn(pEntry, &pEntry->New.cMsCpp, papszArgvPreComp, cArgvPreComp, "precompile", NULL); + kOCEntrySpawn(pEntry, &pEntry->New.cMsCpp, papszArgvPreComp, cArgvPreComp, "preprocess", NULL); kOCEntryReadCppOutput(pEntry, &pEntry->New, 0 /* fatal */); kOCEntryCalcChecksum(pEntry); + if (pEntry->pszMakeDepFilename) + kOCDepConsumer(&pEntry->DepState, pEntry->New.pszCppMapping, pEntry->New.cbCpp); } + + if (pEntry->pszMakeDepFilename) + kOCDepWriteToFile(&pEntry->DepState, pEntry->pszMakeDepFilename, pEntry->New.pszObjName, pEntry->pszDir, + pEntry->fMakeDepFixCase, pEntry->fMakeDepQuiet, pEntry->fMakeDepGenStubs); } /** * Worker function for kOCEntryTeeConsumer and kOCEntryCompileIt that - * writes the precompiler output to disk. + * writes the preprocessor output to disk. * * @param pEntry The cache entry. * @param fFreeIt Whether we can free it after writing it or not. @@ -2256,8 +3295,8 @@ static void kOCEntryWriteCppOutput(PKOCENTRY pEntry, int fFreeIt) /** - * kOCEntrySpawnConsumer callback that passes the precompiler - * output to the compiler and writes it to the disk (latter only when necesary). + * kOCEntrySpawnConsumer callback that passes the preprocessor output to the + * compiler and writes it to the disk (latter only when necesary). * * @param pEntry The cache entry. * @param fdOut The pipe handle connected to the childs stdin. @@ -2345,11 +3384,11 @@ static void kOCEntryCompileIt(PKOCENTRY pEntry) /** * kOCEntrySpawnTee callback that works sort of like 'tee'. * - * It will calculate the precompiled output checksum and + * It will calculate the preprocessed output checksum and * write it to disk while the compiler is busy compiling it. * * @param pEntry The cache entry. - * @param fdIn The input handle (connected to the precompiler). + * @param fdIn The input handle (connected to the preprocessor). * @param fdOut The output handle (connected to the compiler). */ static void kOCEntryTeeConsumer(PKOCENTRY pEntry, int fdIn, int fdOut) @@ -2358,41 +3397,34 @@ static void kOCEntryTeeConsumer(PKOCENTRY pEntry, int fdIn, int fdOut) unsigned fConnectedToCompiler = fdOut == -1 || pEntry->pszNmPipeCompile == NULL; #endif KOCSUMCTX Ctx; - long cbLeft; - long cbAlloc; - char *psz; + KOCCPPRD CppRd; kOCSumInitWithCtx(&pEntry->New.SumHead, &Ctx); - cbAlloc = pEntry->Old.cbCpp ? ((long)pEntry->Old.cbCpp + 4*1024*1024 + 4096) & ~(4*1024*1024 - 1) : 4*1024*1024; - cbLeft = cbAlloc; - pEntry->New.pszCppMapping = psz = xmalloc(cbAlloc); - InfoMsg(3, "precompiler|compile - starting passhtru...\n"); + kOCCppRdInit(&CppRd, pEntry->Old.cbCpp, pEntry->fOptimizeCpp, + pEntry->pszMakeDepFilename ? &pEntry->DepState : NULL); + InfoMsg(3, "preprocessor|compile - starting passhtru...\n"); for (;;) { /* * Read data from the pipe. */ - long cbRead = read(fdIn, psz, cbLeft - 1); + const char *psz; + long cbRead = kOCCppRdRead(&CppRd, fdIn, &psz); if (!cbRead) break; - if (cbRead < 0) - { - if (errno == EINTR) - continue; - FatalDie("precompile|compile - read(%d,,%ld) failed: %s\n", - fdIn, (long)cbLeft, strerror(errno)); - } - InfoMsg(3, "precompiler|compile - read %d\n", cbRead); + InfoMsg(3, "preprocessor|compile - read %d\n", cbRead); /* * Process the data. */ - psz[cbRead] = '\0'; kOCSumUpdate(&pEntry->New.SumHead, &Ctx, psz, cbRead); + if (pEntry->pszMakeDepFilename && !pEntry->fOptimizeCpp) + kOCDepConsumer(&pEntry->DepState, psz, cbRead); + #ifdef __WIN__ if ( !fConnectedToCompiler && !(fConnectedToCompiler = ConnectNamedPipe((HANDLE)_get_osfhandle(fdOut), NULL))) - FatalDie("precompile|compile - ConnectNamedPipe failed: %d\n", GetLastError()); + FatalDie("preprocess|compile - ConnectNamedPipe failed: %d\n", GetLastError()); #endif do { @@ -2401,35 +3433,24 @@ static void kOCEntryTeeConsumer(PKOCENTRY pEntry, int fdIn, int fdOut) { if (errno == EINTR) continue; - FatalDie("precompile|compile - write(%d,,%ld) failed: %s\n", fdOut, cbRead, strerror(errno)); + FatalDie("preprocess|compile - write(%d,,%ld) failed: %s\n", fdOut, cbRead, strerror(errno)); } psz += cbWritten; cbRead -= cbWritten; - cbLeft -= cbWritten; } while (cbRead > 0); - /* - * Expand the buffer? - */ - if (cbLeft <= 1) - { - size_t off = psz - pEntry->New.pszCppMapping; - cbLeft = 4*1024*1024; - cbAlloc += cbLeft; - pEntry->New.pszCppMapping = xrealloc(pEntry->New.pszCppMapping, cbAlloc); - psz = pEntry->New.pszCppMapping + off; - } } - InfoMsg(3, "precompiler|compile - done passhtru\n"); + InfoMsg(3, "preprocessor|compile - done passhtru\n"); close(fdIn); close(fdOut); - pEntry->New.cbCpp = cbAlloc - cbLeft; + kOCCppRdGrabOutput(&CppRd, &pEntry->New.pszCppMapping, &pEntry->New.cbCpp); + kOCCppRdDelete(&CppRd); kOCSumFinalize(&pEntry->New.SumHead, &Ctx); kOCSumInfo(&pEntry->New.SumHead, 4, "cpp (tee)"); /* - * Write the precompiler output to disk and free the memory it + * Write the preprocessor output to disk and free the memory it * occupies while the compiler is busy compiling. */ kOCEntryWriteCppOutput(pEntry, 1 /* free it */); @@ -2440,10 +3461,11 @@ static void kOCEntryTeeConsumer(PKOCENTRY pEntry, int fdIn, int fdOut) * Performs pre-compile and compile in one go (typical clean build scenario). * * @param pEntry The cache entry. - * @param papszArgvPreComp The argument vector for executing precompiler. The cArgvPreComp'th argument must be NULL. + * @param papszArgvPreComp The argument vector for executing preprocessor. + * The cArgvPreComp'th argument must be NULL. * @param cArgvPreComp The number of arguments. */ -static void kOCEntryPreCompileAndCompile(PKOCENTRY pEntry, const char * const *papszArgvPreComp, unsigned cArgvPreComp) +static void kOCEntryPreProcessAndCompile(PKOCENTRY pEntry, const char * const *papszArgvPreComp, unsigned cArgvPreComp) { if ( pEntry->fPipedCompile && pEntry->fPipedPreComp) @@ -2461,15 +3483,18 @@ static void kOCEntryPreCompileAndCompile(PKOCENTRY pEntry, const char * const *p UnlinkFileInDir(pEntry->New.pszCppName, pEntry->pszDir); /* - * Do the actual compile and write the precompiler output to disk. + * Do the actual compile and write the preprocessor output to disk. */ kOCEntrySpawnTee(pEntry, papszArgvPreComp, cArgvPreComp, (const char * const *)pEntry->New.papszArgvCompile, pEntry->New.cArgvCompile, - "precompile|compile", kOCEntryTeeConsumer); + "preprocess|compile", kOCEntryTeeConsumer); + if (pEntry->pszMakeDepFilename) + kOCDepWriteToFile(&pEntry->DepState, pEntry->pszMakeDepFilename, pEntry->New.pszObjName, pEntry->pszDir, + pEntry->fMakeDepFixCase, pEntry->fMakeDepQuiet, pEntry->fMakeDepGenStubs); } else { - kOCEntryPreCompile(pEntry, papszArgvPreComp, cArgvPreComp); + kOCEntryPreProcess(pEntry, papszArgvPreComp, cArgvPreComp); kOCEntryCompileIt(pEntry); } } @@ -2562,7 +3587,7 @@ static const char *kOCEntryFindFileStatement(const char *pszStart, const char *p /** * Worker for kOCEntryCompareOldAndNewOutput() that compares the - * precompiled output using a fast but not very good method. + * preprocessed output using a fast but not very good method. * * @returns 1 if matching, 0 if not matching. * @param pEntry The entry containing the names of the files to compare. @@ -2612,7 +3637,7 @@ static int kOCEntryCompareFast(PCKOCENTRY pEntry) * Since we might be skipping a few new empty headers, it is * possible that we will omit this header from the dependencies * when using VCC. This might not be a problem, since it seems - * we'll have to use the precompiler output to generate the deps + * we'll have to use the preprocessor output to generate the deps * anyway. */ const char *psz; @@ -2778,7 +3803,7 @@ static int kOCEntryCompareFast(PCKOCENTRY pEntry) /** * Worker for kOCEntryCompileIfNeeded that compares the - * precompiled output. + * preprocessed output. * * @returns 1 if matching, 0 if not matching. * @param pEntry The entry containing the names of the files to compare. @@ -2809,15 +3834,23 @@ static void kOCEntryCalcRecompile(PKOCENTRY pEntry) return; /* - * Check if the precompiler output differ in any significant way? + * Check if the preprocessor output differ in any significant way? */ if (!kOCSumHasEqualInChain(&pEntry->Old.SumHead, &pEntry->New.SumHead)) { - InfoMsg(2, "no checksum match - comparing output\n"); - if (!kOCEntryCompareOldAndNewOutput(pEntry)) + if (pEntry->fOptimizeCpp & 2) + { + InfoMsg(2, "no checksum match - no need to compare output, -O2.\n"); pEntry->fNeedCompiling = 1; + } else - kOCSumAddChain(&pEntry->New.SumHead, &pEntry->Old.SumHead); + { + InfoMsg(2, "no checksum match - comparing output\n"); + if (!kOCEntryCompareOldAndNewOutput(pEntry)) + pEntry->fNeedCompiling = 1; + else + kOCSumAddChain(&pEntry->New.SumHead, &pEntry->Old.SumHead); + } } } @@ -2835,6 +3868,45 @@ static int kOCEntryNeedsCompiling(PCKOCENTRY pEntry) /** + * Tries to hardlink a file. + * + * @returns 1 if it succeeded, 0 if it didn't. + * @param pszLink The name of the hardlink. + * @param pszLinkTo The file to hardlinkg @a pszDst to. + */ +static int kOCEntryTryHardlink(const char *pszLink, const char *pszLinkTo) +{ +#ifdef __WIN__ + typedef BOOL (WINAPI *PFNCREATEHARDLINKA)(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES); + static PFNCREATEHARDLINKA s_pfnCreateHardLinkA = NULL; + static int s_fTried = FALSE; + + /* The API was introduced in Windows 2000, so resolve it dynamically. */ + if (!s_pfnCreateHardLinkA) + { + if (!s_fTried) + { + HMODULE hmod = LoadLibrary("KERNEL32.DLL"); + if (hmod) + *(FARPROC *)&s_pfnCreateHardLinkA = GetProcAddress(hmod, "CreateHardLinkA"); + s_fTried = TRUE; + } + if (!s_pfnCreateHardLinkA) + return 0; + } + + if (!s_pfnCreateHardLinkA(pszLink, pszLinkTo, NULL)) + return 0; +#else + if (link(pszLinkTo, pszLink) != 0) + return 0; +#endif + return 1; +} + + + +/** * Worker function for kOCEntryCopy. * * @param pEntry The entry we're coping to, which pszTo is relative to. @@ -2844,60 +3916,63 @@ static int kOCEntryNeedsCompiling(PCKOCENTRY pEntry) static void kOCEntryCopyFile(PCKOCENTRY pEntry, const char *pszTo, char *pszSrc) { char *pszDst = MakePathFromDirAndFile(pszTo, pEntry->pszDir); - char *pszBuf = xmalloc(256 * 1024); - char *psz; - int fdSrc; - int fdDst; - - /* - * Open the files. - */ - fdSrc = open(pszSrc, O_RDONLY | O_BINARY); - if (fdSrc == -1) - FatalDie("failed to open '%s': %s\n", pszSrc, strerror(errno)); - unlink(pszDst); - fdDst = open(pszDst, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); - if (fdDst == -1) - FatalDie("failed to create '%s': %s\n", pszDst, strerror(errno)); - - /* - * Copy them. - */ - for (;;) + if (!kOCEntryTryHardlink(pszDst, pszSrc)) { - /* read a chunk. */ - long cbRead = read(fdSrc, pszBuf, 256*1024); - if (cbRead < 0) - { - if (errno == EINTR) - continue; - FatalDie("read '%s' failed: %s\n", pszSrc, strerror(errno)); - } - if (!cbRead) - break; /* eof */ + char *pszBuf = xmalloc(256 * 1024); + char *psz; + int fdSrc; + int fdDst; - /* write the chunk. */ - psz = pszBuf; - do + /* + * Open the files. + */ + fdSrc = open(pszSrc, O_RDONLY | O_BINARY); + if (fdSrc == -1) + FatalDie("failed to open '%s': %s\n", pszSrc, strerror(errno)); + + fdDst = open(pszDst, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + if (fdDst == -1) + FatalDie("failed to create '%s': %s\n", pszDst, strerror(errno)); + + /* + * Copy them. + */ + for (;;) { - long cbWritten = write(fdDst, psz, cbRead); - if (cbWritten < 0) + /* read a chunk. */ + long cbRead = read(fdSrc, pszBuf, 256*1024); + if (cbRead < 0) { if (errno == EINTR) continue; - FatalDie("write '%s' failed: %s\n", pszSrc, strerror(errno)); + FatalDie("read '%s' failed: %s\n", pszSrc, strerror(errno)); } - psz += cbWritten; - cbRead -= cbWritten; - } while (cbRead > 0); - } + if (!cbRead) + break; /* eof */ - /* cleanup */ - if (close(fdDst) != 0) - FatalDie("closing '%s' failed: %s\n", pszDst, strerror(errno)); - close(fdSrc); - free(pszBuf); + /* write the chunk. */ + psz = pszBuf; + do + { + long cbWritten = write(fdDst, psz, cbRead); + if (cbWritten < 0) + { + if (errno == EINTR) + continue; + FatalDie("write '%s' failed: %s\n", pszSrc, strerror(errno)); + } + psz += cbWritten; + cbRead -= cbWritten; + } while (cbRead > 0); + } + + /* cleanup */ + if (close(fdDst) != 0) + FatalDie("closing '%s' failed: %s\n", pszDst, strerror(errno)); + close(fdSrc); + free(pszBuf); + } free(pszDst); free(pszSrc); } @@ -2956,7 +4031,7 @@ typedef struct KOCDIGEST uint32_t uKey; /** The checksum of the compile argument vector. */ KOCSUM SumCompArgv; - /** The list of precompiler output checksums that's . */ + /** The list of preprocessor output checksums that's . */ KOCSUM SumHead; } KOCDIGEST; /** Pointer to a file digest. */ @@ -3831,7 +4906,7 @@ static int usage(FILE *pOut) " <-f|--file <local-cache-file>>\n" " <-t|--target <target-name>>\n" " [-r|--redir-stdout] [-p|--passthru] [--named-pipe-compile <pipename>]\n" - " --kObjCache-cpp <filename> <precompiler + args>\n" + " --kObjCache-cpp <filename> <preprocessor + args>\n" " --kObjCache-cc <object> <compiler + args>\n" " [--kObjCache-both [args]]\n" ); @@ -3870,6 +4945,12 @@ int main(int argc, char **argv) int fRedirCompileStdIn = 0; const char *pszNmPipeCompile = NULL; + const char *pszMakeDepFilename = NULL; + int fMakeDepFixCase = 0; + int fMakeDepGenStubs = 0; + int fMakeDepQuiet = 0; + int fOptimizePreprocessorOutput = 0; + const char *pszTarget = NULL; enum { kOC_Options, kOC_CppArgv, kOC_CcArgv, kOC_BothArgv } enmMode = kOC_Options; @@ -3910,7 +4991,7 @@ int main(int argc, char **argv) if (!pszObjName) { if (++i >= argc) - return SyntaxError("--kObjCache-cc requires an precompiler output filename!\n"); + return SyntaxError("--kObjCache-cc requires an preprocessor output filename!\n"); pszObjName = argv[i]; } } @@ -3974,6 +5055,22 @@ int main(int argc, char **argv) pszNmPipeCompile = argv[++i]; fRedirCompileStdIn = 0; } + else if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--make-dep-file")) + { + if (i + 1 >= argc) + return SyntaxError("%s requires a filename!\n", argv[i]); + pszMakeDepFilename = argv[++i]; + } + else if (!strcmp(argv[i], "--make-dep-fix-case")) + fMakeDepFixCase = 1; + else if (!strcmp(argv[i], "--make-dep-gen-stubs")) + fMakeDepGenStubs = 1; + else if (!strcmp(argv[i], "--make-dep-quiet")) + fMakeDepQuiet = 1; + else if (!strcmp(argv[i], "-O1") || !strcmp(argv[i], "--optimize-1")) + fOptimizePreprocessorOutput = 1; + else if (!strcmp(argv[i], "-O2") || !strcmp(argv[i], "--optimize-2")) + fOptimizePreprocessorOutput = 1 | 2; else if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "--passthru")) fRedirPreCompStdOut = fRedirCompileStdIn = 1; else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--redir-stdout")) @@ -3990,8 +5087,8 @@ int main(int argc, char **argv) } else if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) { - printf("kObjCache - kBuild version %d.%d.%d ($Revision: 2568 $)\n" - "Copyright (c) 2007-2011 knut st. osmundsen\n", + printf("kObjCache - kBuild version %d.%d.%d ($Revision: 2627 $)\n" + "Copyright (c) 2007-2012 knut st. osmundsen\n", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH); return 0; } @@ -4005,7 +5102,7 @@ int main(int argc, char **argv) if (!cArgvCompile) return SyntaxError("No compiler arguments (--kObjCache-cc)!\n"); if (!cArgvPreComp) - return SyntaxError("No precompiler arguments (--kObjCache-cc)!\n"); + return SyntaxError("No preprocessor arguments (--kObjCache-cc)!\n"); /* * Calc the cache file name. @@ -4025,7 +5122,7 @@ int main(int argc, char **argv) psz = strrchr(pszCacheName, '.'); if (!psz || psz <= pszCacheName) psz = (char *)pszCacheName + cch; - memcpy(psz, ".koc", sizeof(".koc") - 1); + memcpy(psz, ".koc", sizeof(".koc")); } pszCacheFile = MakePathFromDirAndFile(pszCacheName, pszCacheDir); } @@ -4042,11 +5139,13 @@ int main(int argc, char **argv) pEntry = kOCEntryCreate(pszEntryFile); kOCEntryRead(pEntry); + kOCEntrySetCppName(pEntry, pszPreCompName); kOCEntrySetCompileObjName(pEntry, pszObjName); kOCEntrySetCompileArgv(pEntry, papszArgvCompile, cArgvCompile); kOCEntrySetTarget(pEntry, pszTarget); - kOCEntrySetCppName(pEntry, pszPreCompName); kOCEntrySetPipedMode(pEntry, fRedirPreCompStdOut, fRedirCompileStdIn, pszNmPipeCompile); + kOCEntrySetDepFilename(pEntry, pszMakeDepFilename, fMakeDepFixCase, fMakeDepQuiet, fMakeDepGenStubs); + kOCEntrySetOptimizations(pEntry, fOptimizePreprocessorOutput); /* * Open (& lock) the two files and do validity checks and such. @@ -4061,16 +5160,16 @@ int main(int argc, char **argv) */ kObjCacheUnlock(pCache); InfoMsg(1, "doing full compile\n"); - kOCEntryPreCompileAndCompile(pEntry, papszArgvPreComp, cArgvPreComp); + kOCEntryPreProcessAndCompile(pEntry, papszArgvPreComp, cArgvPreComp); kObjCacheLock(pCache); } else { /* - * Do the precompile (don't need to lock the cache file for this). + * Do the preprocess (don't need to lock the cache file for this). */ kObjCacheUnlock(pCache); - kOCEntryPreCompile(pEntry, papszArgvPreComp, cArgvPreComp); + kOCEntryPreProcess(pEntry, papszArgvPreComp, cArgvPreComp); /* * Check if we need to recompile. If we do, try see if the is a cache entry first. @@ -4111,6 +5210,12 @@ int main(int argc, char **argv) kOCEntryWrite(pEntry); kObjCacheUnlock(pCache); kObjCacheDestroy(pCache); + if (fOptimizePreprocessorOutput) + { + InfoMsg(3, "g_cbMemMoved=%#x (%d)\n", g_cbMemMoved, g_cbMemMoved); + InfoMsg(3, "g_cMemMoves=%#x (%d)\n", g_cMemMoves, g_cMemMoves); + } + return 0; } diff --git a/src/kash/Makefile.kmk b/src/kash/Makefile.kmk index 6dd8028..f378c8e 100644 --- a/src/kash/Makefile.kmk +++ b/src/kash/Makefile.kmk @@ -1,4 +1,4 @@ -# $Id: Makefile.kmk 2546 2011-10-01 19:49:54Z bird $ +# $Id: Makefile.kmk 2652 2012-09-09 17:21:48Z bird $ ## @file # Sub-makefile for kash. # @@ -41,10 +41,11 @@ kash_DEFS.linux = BSD kash_DEFS.solaris = BSD ## @todo bring over PC_SLASHES? kash_DEFS.win = \ - BSD PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS YY_NO_UNISTD_H SH_DEAL_WITH_CRLF + BSD YY_NO_UNISTD_H \ + SH_DEAL_WITH_CRLF PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS EXEC_HASH_BANG_SCRIPT kash_DEFS.os2 = \ - HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME \ - EXEC_HASH_BANG_SCRIPT PC_OS2_LIBPATHS PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS + HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME PC_OS2_LIBPATHS \ + SH_DEAL_WITH_CRLF PC_PATH_SEP PC_DRIVE_LETTERS PC_EXE_EXTS EXEC_HASH_BANG_SCRIPT kash_DEFS.darwin = \ HAVE_SYS_SIGNAME HAVE_SYSCTL_H HAVE_SETPROGNAME kash_DEFS.dragonfly = \ @@ -61,6 +62,7 @@ if "$(USER)" == "bird" && "$(KBUILD_TARGET)" != "win" kash_CFLAGS += -std=gnu99 endif kash_CFLAGS.win.amd64 = -GS- +kash_LDFLAGS.win = -DYNAMICBASE:NO kash_SOURCES = \ main.c \ alias.c \ diff --git a/src/kash/bltin/printf.c b/src/kash/bltin/printf.c index a50a8ec..4a6a952 100644 --- a/src/kash/bltin/printf.c +++ b/src/kash/bltin/printf.c @@ -54,6 +54,7 @@ __RCSID("$NetBSD: printf.c,v 1.31 2005/03/22 23:55:46 dsl Exp $"); #include <stdlib.h> #include <string.h> #include <unistd.h> +#include "shinstance.h" #ifdef __GNUC__ #define ESCAPE '\e' @@ -646,7 +647,7 @@ check_conversion(const char *s, const char *ep) warnx("%s: not completely converted", s); rval = 1; } else if (errno == ERANGE) { - warnx("%s: %s", s, strerror(ERANGE)); + warnx("%s: %s", s, sh_strerror(psh, ERANGE)); rval = 1; } } diff --git a/src/kash/cd.c b/src/kash/cd.c index 8267554..49fd157 100644 --- a/src/kash/cd.c +++ b/src/kash/cd.c @@ -391,7 +391,7 @@ find_curdir(shinstance *psh, int noerror) if (errno == ERANGE) continue; if (!noerror) - error(psh, "getcwd() failed: %s", strerror(errno)); + error(psh, "getcwd() failed: %s", sh_strerror(psh, errno)); return; } #else diff --git a/src/kash/error.c b/src/kash/error.c index aa7d39c..7afa91f 100644 --- a/src/kash/error.c +++ b/src/kash/error.c @@ -137,7 +137,7 @@ exvwarning(shinstance *psh, int sv_errno, const char *msg, va_list ap) outfmt(&psh->errout, ": "); } if (sv_errno >= 0) - outfmt(&psh->errout, "%s", strerror(sv_errno)); + outfmt(&psh->errout, "%s", sh_strerror(psh, sv_errno)); out2c(psh, '\n'); flushout(&psh->errout); } @@ -155,8 +155,15 @@ exverror(shinstance *psh, int cond, const char *msg, va_list ap) #ifdef DEBUG if (msg) { + va_list va2; TRACE((psh, "exverror(%d, \"", cond)); - TRACEV((psh, msg, ap)); +# ifdef va_copy /* MSC 2010 still doesn't have va_copy. sigh. */ + va_copy(va2, ap); +# else + va2 = ap; +# endif + TRACEV((psh, msg, va2)); + va_end(va2); TRACE((psh, "\") pid=%d\n", sh_getpid(psh))); } else TRACE((psh, "exverror(%d, NULL) pid=%d\n", cond, sh_getpid(psh))); diff --git a/src/kash/eval.c b/src/kash/eval.c index 665e0bf..d96c2a3 100644 --- a/src/kash/eval.c +++ b/src/kash/eval.c @@ -676,7 +676,7 @@ evalcommand(shinstance *psh, union node *cmd, int flags, struct backcmd *backcmd char **argv; int argc; char **envp; - int varflag; + int numvars; struct strlist *sp; int mode; int pip[2]; @@ -706,37 +706,28 @@ evalcommand(shinstance *psh, union node *cmd, int flags, struct backcmd *backcmd psh->back_exitstatus = 0; arglist.lastp = &arglist.list; - varflag = 1; /* Expand arguments, ignoring the initial 'name=value' ones */ - for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { - char *p = argp->narg.text; - if (varflag && is_name(*p)) { - do { - p++; - } while (is_in_name(*p)); - if (*p == '=') - continue; - } - expandarg(psh, argp, &arglist, EXP_FULL | EXP_TILDE); - varflag = 0; + for (argp = cmd->ncmd.args, numvars = 0 ; argp ; argp = argp->narg.next, numvars++) { + char *p = argp->narg.text; + char ch = *p; + if (is_name(ch)) { + do ch = *++p; + while (is_in_name(ch)); + if (ch == '=') + continue; + } + break; } + for (/*continue on argp from above. */ ; argp ; argp = argp->narg.next) + expandarg(psh, argp, &arglist, EXP_FULL | EXP_TILDE); *arglist.lastp = NULL; expredir(psh, cmd->ncmd.redirect); /* Now do the initial 'name=value' ones we skipped above */ varlist.lastp = &varlist.list; - for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { - char *p = argp->narg.text; - if (!is_name(*p)) - break; - do - p++; - while (is_in_name(*p)); - if (*p != '=') - break; + for (argp = cmd->ncmd.args ; numvars > 0 && argp ; argp = argp->narg.next, numvars--) expandarg(psh, argp, &varlist, EXP_VARTILDE); - } *varlist.lastp = NULL; argc = 0; diff --git a/src/kash/exec.c b/src/kash/exec.c index 30a9f0f..d76bf2a 100644 --- a/src/kash/exec.c +++ b/src/kash/exec.c @@ -227,8 +227,21 @@ tryexec(shinstance *psh, char *cmd, char **argv, char **envp, int vforked, int h errno = e; } - #ifdef EXEC_HASH_BANG_SCRIPT + +/* + * Checks if NAME is the (base) name of the shell executable or something + * very similar. + */ +STATIC int +is_shell_exe_name(const char *name) +{ + return equal(name, "kmk_ash") + || equal(name, "kmk_sh") + || equal(name, "kash") + || equal(name, "sh"); +} + /* * Execute an interpreter introduced by "#!", for systems where this * feature has not been built into the kernel. If the interpreter is @@ -239,7 +252,7 @@ tryexec(shinstance *psh, char *cmd, char **argv, char **envp, int vforked, int h * reading any input. It would benefit from a rewrite. */ -#define NEWARGS 5 +#define NEWARGS 16 STATIC void execinterp(shinstance *psh, char **argv, char **envp) @@ -251,10 +264,11 @@ execinterp(shinstance *psh, char **argv, char **envp) char *p; char **ap; char *newargs[NEWARGS]; - int i; + intptr_t i; char **ap2; char **new; + /* Split the string into arguments. */ n = psh->parsenleft - 2; inp = psh->parsenextc + 2; ap = newargs; @@ -275,22 +289,35 @@ bad: error(psh, "Bad #! line"); n++, inp--; *ap++ = grabstackstr(psh, outp); } - if (ap == newargs + 1) { /* if no args, maybe no exec is needed */ - p = newargs[0]; - for (;;) { - if (equal(p, "sh") || equal(p, "ash")) { - TRACE((psh, "hash bang self\n")); - return; - } - while (*p != '/') { - if (*p == '\0') - goto break2; - p++; - } - p++; + + /* /usr/bin/env emulation, very common with kash/kmk_ash. */ + i = ap - newargs; + if (i > 1 && equal(newargs[0], "/usr/bin/env")) { + if ( !strchr(newargs[1], '=') + && newargs[1][0] != '-') { + /* shellexec below searches the PATH for us, so just + drop /usr/bin/env. */ + TRACE((psh, "hash bang /usr/bin/env utility, dropping /usr/bin/env\n")); + ap--; + i--; + for (n = 0; n < i; n++) + newargs[n] = newargs[n + 1]; + } /* else: complicated invocation */ + } + + /* If the interpreter is the shell or a similar shell, there is + no need to exec. */ + if (i == 1) { + p = strrchr(newargs[0], '/'); + if (!p) + p = newargs[0]; + if (is_shell_exe_name(p)) { + TRACE((psh, "hash bang self\n")); + return; } -break2:; } + + /* Combine the two argument lists and exec. */ i = (char *)ap - (char *)newargs; /* size in bytes */ if (i == 0) error(psh, "Bad #! line"); @@ -300,13 +327,14 @@ break2:; while ((i -= sizeof (char **)) >= 0) *ap2++ = *ap++; ap = argv; - while (*ap2++ = *ap++); + while ((*ap2++ = *ap++)) + /* nothing*/; TRACE((psh, "hash bang '%s'\n", new[0])); shellexec(psh, new, envp, pathval(psh), 0, 0); /* NOTREACHED */ } -#endif +#endif /* EXEC_HASH_BANG_SCRIPT */ /* @@ -1141,7 +1169,7 @@ typecmd(shinstance *psh, int argc, char **argv) } else { if (!v_flag) out1fmt(psh, ": %s\n", - strerror(errno)); + sh_strerror(psh, errno)); else err = 126; } diff --git a/src/kash/expand.c b/src/kash/expand.c index 7b90cee..61f5ab3 100644 --- a/src/kash/expand.c +++ b/src/kash/expand.c @@ -142,6 +142,7 @@ expandarg(shinstance *psh, union node *arg, struct arglist *arglist, int flag) } STPUTC(psh, '\0', psh->expdest); p = grabstackstr(psh, psh->expdest); + TRACE2((psh, "expandarg: p='%s'\n", p)); psh->exparg.lastp = &psh->exparg.list; /* * TODO - EXP_REDIR @@ -1203,6 +1204,7 @@ expmeta(shinstance *psh, char *enddir, char *name) } if (metaflag == 0 || shfile_lstat(&psh->fdtab, psh->expdir, &statb) >= 0) addfname(psh, psh->expdir); + TRACE2((psh, "expandarg: return #1 (metaflag=%d)\n", metaflag)); return; } endname = p; @@ -1224,8 +1226,10 @@ expmeta(shinstance *psh, char *enddir, char *name) cp = psh->expdir; enddir[-1] = '\0'; } - if ((dirp = shfile_opendir(&psh->fdtab, cp)) == NULL) + if ((dirp = shfile_opendir(&psh->fdtab, cp)) == NULL) { + TRACE2((psh, "expandarg: return #2 (shfile_opendir(,%s) failed)\n", cp)); return; + } if (enddir != psh->expdir) enddir[-1] = '/'; if (*endname == 0) { diff --git a/src/kash/generated/init.c b/src/kash/generated/init.c index 46bb96a..2ba447e 100644 --- a/src/kash/generated/init.c +++ b/src/kash/generated/init.c @@ -267,8 +267,10 @@ initshellproc(shinstance *psh) { for (i = 0; psh->optlist[i].name; i++) psh->optlist[i].val = 0; +# if DEBUG == 2 + debug(psh) = 1; +# endif optschanged(psh); - } /* from /Volumes/ScratchHFS/bird/kBuild/svn/trunk/src/kash/redir.c: */ diff --git a/src/kash/input.c b/src/kash/input.c index 3c9e34e..c3036fa 100644 --- a/src/kash/input.c +++ b/src/kash/input.c @@ -171,12 +171,9 @@ pgetc(shinstance *psh) static int -preadfd(shinstance *psh) +preadfd_inner(shinstance *psh, char *buf, int bufsize) { int nr; - char *buf = psh->parsefile->buf; - psh->parsenextc = buf; - retry: #ifndef SMALL if (psh->parsefile->fd == 0 && psh->el) { @@ -189,8 +186,8 @@ retry: nr = 0; else { nr = el_len; - if (nr > BUFSIZ - 8) - nr = BUFSIZ - 8; + if (nr > bufsize) + nr = bufsize; memcpy(buf, rl_cp, nr); if (nr != el_len) { el_len -= nr; @@ -201,7 +198,7 @@ retry: } else #endif - nr = shfile_read(&psh->fdtab, psh->parsefile->fd, buf, BUFSIZ - 8); + nr = shfile_read(&psh->fdtab, psh->parsefile->fd, buf, bufsize); if (nr <= 0) { @@ -220,22 +217,51 @@ retry: } } nr = -1; - } else { + } + return nr; +} + + + +static int +preadfd(shinstance *psh) +{ + int nr; + char *buf = psh->parsefile->buf; + psh->parsenextc = buf; + #ifdef SH_DEAL_WITH_CRLF + /* Convert CRLF to LF. */ + nr = preadfd_inner(psh, buf, BUFSIZ - 9); + if (nr > 0) { char *cr = memchr(buf, '\r', nr); while (cr) { size_t left = nr - (cr - buf); + if (left > 1 && cr[1] == '\n') { left--; nr--; memmove(cr, cr + 1, left); cr = memchr(cr, '\r', left); + } else if (left == 1) { + /* Special case: \r at buffer end. Read one more char. Screw \r\r\n sequences. */ + int nr2 = preadfd_inner(psh, cr + 1, 1); + if (nr2 != 1) + break; + if (cr[1] == '\n') { + *cr = '\n'; + } else { + nr++; + } + break; } else { cr = memchr(cr + 1, '\r', left); } } -#endif } +#else + nr = preadfd_inner(psh, buf, BUFSIZ - 8); +#endif return nr; } diff --git a/src/kash/jobs.c b/src/kash/jobs.c index c4fcefc..13a758d 100644 --- a/src/kash/jobs.c +++ b/src/kash/jobs.c @@ -149,17 +149,17 @@ out: setsignal(psh, SIGTTIN, 0); if (sh_getpgid(psh, 0) != psh->rootpid && sh_setpgid(psh, 0, psh->rootpid) == -1) error(psh, "Cannot set process group (%s) at %d", - strerror(errno), __LINE__); + sh_strerror(psh, errno), __LINE__); if (sh_tcsetpgrp(psh, psh->ttyfd, psh->rootpid) == -1) error(psh, "Cannot set tty process group (%s) at %d", - strerror(errno), __LINE__); + sh_strerror(psh, errno), __LINE__); } else { /* turning job control off */ if (sh_getpgid(psh, 0) != psh->initialpgrp && sh_setpgid(psh, 0, psh->initialpgrp) == -1) error(psh, "Cannot set process group (%s) at %d", - strerror(errno), __LINE__); + sh_strerror(psh, errno), __LINE__); if (sh_tcsetpgrp(psh, psh->ttyfd, psh->initialpgrp) == -1) error(psh, "Cannot set tty process group (%s) at %d", - strerror(errno), __LINE__); + sh_strerror(psh, errno), __LINE__); shfile_close(&psh->fdtab, psh->ttyfd); psh->ttyfd = -1; setsignal(psh, SIGTSTP, 0); @@ -208,7 +208,7 @@ fgcmd(shinstance *psh, int argc, char **argv) if (i >= jp->nprocs) { error(psh, "Cannot set tty process group (%s) at %d", - strerror(errno), __LINE__); + sh_strerror(psh, errno), __LINE__); } restartjob(psh, jp); INTOFF; @@ -300,7 +300,7 @@ restartjob(shinstance *psh, struct job *jp) if (sh_killpg(psh, jp->ps[i].pid, SIGCONT) != -1) break; if (i >= jp->nprocs) - error(psh, "Cannot continue job (%s)", strerror(errno)); + error(psh, "Cannot continue job (%s)", sh_strerror(psh, errno)); for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) { if (WIFSTOPPED(ps->status)) { ps->status = -1; @@ -484,7 +484,7 @@ showjobs(shinstance *psh, struct output *out, int mode) if (mflag(psh) && gotpid != -1 && sh_tcgetpgrp(psh, psh->ttyfd) != sh_getpid(psh)) { if (sh_tcsetpgrp(psh, psh->ttyfd, sh_getpid(psh)) == -1) error(psh, "Cannot set tty process group (%s) at %d", - strerror(errno), __LINE__); + sh_strerror(psh, errno), __LINE__); TRACE((psh, "repaired tty process group\n")); silent = 1; } @@ -853,7 +853,7 @@ forkchild(shinstance *psh, struct job *jp, union node *n, int mode, int vforked) if (mode == FORK_FG) { if (sh_tcsetpgrp(psh, psh->ttyfd, pgrp) == -1) error(psh, "Cannot set tty process group (%s) at %d", - strerror(errno), __LINE__); + sh_strerror(psh, errno), __LINE__); } setsignal(psh, SIGTSTP, vforked); setsignal(psh, SIGTTOU, vforked); @@ -926,7 +926,7 @@ waitforjob(shinstance *psh, struct job *jp) if (jp->jobctl) { if (sh_tcsetpgrp(psh, psh->ttyfd, mypgrp) == -1) error(psh, "Cannot set tty process group (%s) at %d", - strerror(errno), __LINE__); + sh_strerror(psh, errno), __LINE__); } if (jp->state == JOBSTOPPED && psh->curjob != jp - psh->jobtab) set_curjob(psh, jp, 2); diff --git a/src/kash/memalloc.c b/src/kash/memalloc.c index 7f2d387..d4a2fec 100644 --- a/src/kash/memalloc.c +++ b/src/kash/memalloc.c @@ -88,7 +88,7 @@ char * savestr(struct shinstance *psh, const char *s) { char *p; - size_t len = strlen(s); + size_t len = strlen(s); p = ckmalloc(psh, len + 1); memcpy(p, s, len + 1); diff --git a/src/kash/miscbltin.c b/src/kash/miscbltin.c index 446a314..882c0e1 100644 --- a/src/kash/miscbltin.c +++ b/src/kash/miscbltin.c @@ -423,7 +423,7 @@ ulimitcmd(shinstance *psh, int argc, char **argv) if (how & SOFT) limit.rlim_cur = val; if (sh_setrlimit(psh, l->cmd, &limit) < 0) - error(psh, "error setting limit (%s)", strerror(errno)); + error(psh, "error setting limit (%s)", sh_strerror(psh, errno)); } else { if (how & SOFT) val = limit.rlim_cur; diff --git a/src/kash/options.c b/src/kash/options.c index ed0f66a..9b258b4 100644 --- a/src/kash/options.c +++ b/src/kash/options.c @@ -260,8 +260,10 @@ SHELLPROC { for (i = 0; psh->optlist[i].name; i++) psh->optlist[i].val = 0; +# if DEBUG == 2 + debug(psh) = 1; +# endif optschanged(psh); - } #endif diff --git a/src/kash/options.h b/src/kash/options.h index 6e63085..5a2c75b 100644 --- a/src/kash/options.h +++ b/src/kash/options.h @@ -57,14 +57,14 @@ struct optent { /* Those marked [U] are required by posix, but have no effect! */ #ifdef DEBUG -# define NOPTS 21 -#else # define NOPTS 20 +#else +# define NOPTS 19 #endif #ifdef DEFINE_OPTIONS # define DEF_OPTS(name, letter, opt_set) {name, letter, opt_set, 0}, -const struct optent ro_optlist[NOPTS] = { +const struct optent ro_optlist[NOPTS + 1] = { #else # define DEF_OPTS(name, letter, opt_set) #endif diff --git a/src/kash/parser.c b/src/kash/parser.c index 5fede2b..b0dbad7 100644 --- a/src/kash/parser.c +++ b/src/kash/parser.c @@ -766,7 +766,7 @@ out: if (!alreadyseen) TRACE((psh, "token %s %s\n", tokname[t], t == TWORD ? psh->wordtext : "")); else - TRACE((psh, "reread token %s %s\n", tokname[t], t == TWORD ? psh->wordtext : "")); + TRACE((psh, "reread token %s \"%s\"\n", tokname[t], t == TWORD ? psh->wordtext : "")); #endif return (t); } @@ -1614,8 +1614,12 @@ synexpect(shinstance *psh, int token) SH_NORETURN_1 STATIC void synerror(shinstance *psh, const char *msg) { - if (psh->commandname) + if (psh->commandname) { + TRACE((psh, "synerror: %s: %d: Syntax error: %s", psh->commandname, psh->startlinno, msg)); outfmt(&psh->errout, "%s: %d: ", psh->commandname, psh->startlinno); + } else { + TRACE((psh, "synerror: Syntax error: %s\n", msg)); + } outfmt(&psh->errout, "Syntax error: %s\n", msg); error(psh, (char *)NULL); /* NOTREACHED */ diff --git a/src/kash/redir.c b/src/kash/redir.c index 21b3e84..04ab8dd 100644 --- a/src/kash/redir.c +++ b/src/kash/redir.c @@ -143,7 +143,7 @@ again: /* FALLTHROUGH*/ default: INTON; - error(psh, "%d: %s", fd, strerror(errno)); + error(psh, "%d: %s", fd, sh_strerror(psh, errno)); /* NOTREACHED */ } } @@ -376,7 +376,7 @@ copyfd(shinstance *psh, int from, int to) if (newfd < 0) { if (errno == EMFILE) return EMPTY; - error(psh, "%d: %s", from, strerror(errno)); + error(psh, "%d: %s", from, sh_strerror(psh, errno)); } return newfd; } @@ -397,7 +397,7 @@ movefd(shinstance *psh, int from, int to) if (newfd < 0) { if (errno == EMFILE) return EMPTY; - error(psh, "%d: %s", from, strerror(errno)); + error(psh, "%d: %s", from, sh_strerror(psh, errno)); } return newfd; } @@ -418,7 +418,7 @@ movefd_above(shinstance *psh, int from, int to) if (newfd < 0) { if (errno == EMFILE) return EMPTY; - error(psh, "%d: %s", from, strerror(errno)); + error(psh, "%d: %s", from, sh_strerror(psh, errno)); } return newfd; } diff --git a/src/kash/shfile.c b/src/kash/shfile.c index 0d1cbae..84511ca 100644 --- a/src/kash/shfile.c +++ b/src/kash/shfile.c @@ -1,4 +1,4 @@ -/* $Id: shfile.c 2553 2011-11-25 21:44:21Z bird $ */ +/* $Id: shfile.c 2681 2013-04-14 18:41:58Z bird $ */ /** @file * * File management. @@ -163,14 +163,14 @@ static PFN_RtlUnicodeStringToAnsiString g_pfnRtlUnicodeStringToAnsiString = NULL */ static void shfile_native_close(intptr_t native, unsigned flags) { -#if K_OS == K_OS_WINDOWS +# if K_OS == K_OS_WINDOWS BOOL fRc = CloseHandle((HANDLE)native); assert(fRc); (void)fRc; -#else +# else int s = errno; close(native); errno = s; -#endif +# endif (void)flags; } @@ -288,7 +288,7 @@ static int shfile_insert(shfdtab *pfdtab, intptr_t native, unsigned oflags, unsi return fd; } -#if K_OS != K_OS_WINDOWS +# if K_OS != K_OS_WINDOWS /** * Makes a copy of the native file, closes the original, and inserts the copy * into the descriptor table. @@ -317,7 +317,7 @@ static int shfile_copy_insert_and_close(shfdtab *pfdtab, int *pnative, unsigned fd = shfile_insert(pfdtab, native_copy, oflags, shflags, fdMin, who); return fd; } -#endif /* !K_OS_WINDOWS */ +# endif /* !K_OS_WINDOWS */ /** * Gets a file descriptor and lock the file descriptor table. @@ -384,13 +384,13 @@ int shfile_make_path(shfdtab *pfdtab, const char *path, char *buf) return -1; } if ( *path == '/' -#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 +# if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 || *path == '\\' || ( *path && path[1] == ':' && ( (*path >= 'A' && *path <= 'Z') || (*path >= 'a' && *path <= 'z'))) -#endif +# endif ) { memcpy(buf, path, path_len + 1); @@ -418,16 +418,67 @@ int shfile_make_path(shfdtab *pfdtab, const char *path, char *buf) memcpy(buf + cwd_len, path, path_len + 1); } -#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 +# if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 if (!strcmp(buf, "/dev/null")) strcpy(buf, "NUL"); -#endif +# endif return 0; } # if K_OS == K_OS_WINDOWS /** + * Adjusts the file name if it ends with a trailing directory slash. + * + * Windows APIs doesn't like trailing slashes. + * + * @returns 1 if it has a directory slash, 0 if not. + * + * @param abspath The path to adjust (SHFILE_MAX_PATH). + */ +static int shfile_trailing_slash_hack(char *abspath) +{ + /* + * Anything worth adjust here? + */ + size_t path_len = strlen(abspath); + if ( path_len == 0 + || ( abspath[path_len - 1] != '/' +# if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 + && abspath[path_len - 1] != '\\' +# endif + ) + ) + return 0; + + /* + * Ok, make the adjustment. + */ + if (path_len + 2 <= SHFILE_MAX_PATH) + { + /* Add a '.' to the end. */ + abspath[path_len++] = '.'; + abspath[path_len] = '\0'; + } + else + { + /* No space for a dot, remove the slash if it's alone or just remove + one and add a dot like above. */ + if ( abspath[path_len - 2] != '/' +# if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 + && abspath[path_len - 2] != '\\' +# endif + ) + abspath[--path_len] = '\0'; + else + abspath[path_len - 1] = '.'; + } + + return 1; +} + + +/** * Converts a DOS(/Windows) error code to errno, * assigning it to errno. * @@ -527,6 +578,21 @@ DWORD shfile_query_handle_access_mask(HANDLE h, PACCESS_MASK pMask) #endif /* SHFILE_IN_USE */ /** + * Converts DOS slashes to UNIX slashes if necessary. + * + * @param pszPath The path to fix. + */ +static void shfile_fix_slashes(char *pszPath) +{ +#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2 + while ((pszPath = strchr(pszPath, '\\'))) + *pszPath++ = '/'; +#else + (void)pszPath; +#endif +} + +/** * Initializes the global variables in this file. */ static void shfile_init_globals(void) @@ -569,9 +635,12 @@ int shfile_init(shfdtab *pfdtab, shfdtab *inherit) if (!rc) { #ifdef SHFILE_IN_USE + /* Get CWD with unix slashes. */ char buf[SHFILE_MAX_PATH]; if (getcwd(buf, sizeof(buf))) { + shfile_fix_slashes(buf); + pfdtab->cwd = sh_strdup(NULL, buf); if (!inherit) { @@ -763,6 +832,50 @@ int shfile_init(shfdtab *pfdtab, shfdtab *inherit) #if K_OS == K_OS_WINDOWS && defined(SHFILE_IN_USE) /** + * Changes the inheritability of a file descriptro, taking console handles into + * account. + * + * @note This MAY change the native handle for the entry. + * + * @returns The native handle. + * @param pfd The file descriptor to change. + * @param set If set, make child processes inherit the handle, if clear + * make them not inherit it. + */ +static HANDLE shfile_set_inherit_win(shfile *pfd, int set) +{ + HANDLE hFile = (HANDLE)pfd->native; + if (!SetHandleInformation(hFile, HANDLE_FLAG_INHERIT, set ? HANDLE_FLAG_INHERIT : 0)) + { + /* SetHandleInformation doesn't work for console handles, + so we have to duplicate the handle to change the + inheritability. */ + DWORD err = GetLastError(); + if ( err == ERROR_INVALID_PARAMETER + && DuplicateHandle(GetCurrentProcess(), + hFile, + GetCurrentProcess(), + &hFile, + 0, + set ? TRUE : FALSE /* bInheritHandle */, + DUPLICATE_SAME_ACCESS)) + { + TRACE2((NULL, "shfile_set_inherit_win: %p -> %p (set=%d)\n", pfd->native, hFile, set)); + if (!CloseHandle((HANDLE)pfd->native)) + assert(0); + pfd->native = (intptr_t)hFile; + } + else + { + err = GetLastError(); + assert(0); + hFile = (HANDLE)pfd->native; + } + } + return hFile; +} + +/** * Helper for shfork. * * @param pfdtab The file descriptor table. @@ -774,7 +887,6 @@ void shfile_fork_win(shfdtab *pfdtab, int set, intptr_t *hndls) { shmtxtmp tmp; unsigned i; - DWORD fFlag = set ? HANDLE_FLAG_INHERIT : 0; shmtx_enter(&pfdtab->mtx, &tmp); TRACE2((NULL, "shfile_fork_win: set=%d\n", set)); @@ -784,17 +896,10 @@ void shfile_fork_win(shfdtab *pfdtab, int set, intptr_t *hndls) { if (pfdtab->tab[i].fd == i) { - HANDLE hFile = (HANDLE)pfdtab->tab[i].native; + shfile_set_inherit_win(&pfdtab->tab[i], set); if (set) TRACE2((NULL, " #%d: native=%#x oflags=%#x shflags=%#x\n", - i, hFile, pfdtab->tab[i].oflags, pfdtab->tab[i].shflags)); - if (!SetHandleInformation(hFile, HANDLE_FLAG_INHERIT, fFlag)) - { -#if 0 /* Seems to happen for console handles, ignore it. */ - DWORD err = GetLastError(); - assert(0); -#endif - } + i, pfdtab->tab[i].native, pfdtab->tab[i].oflags, pfdtab->tab[i].shflags)); } } @@ -860,17 +965,9 @@ void *shfile_exec_win(shfdtab *pfdtab, int prepare, unsigned short *sizep, intpt if ( pfdtab->tab[i].fd == i && !(pfdtab->tab[i].shflags & SHFILE_FLAGS_CLOSE_ON_EXEC)) { - HANDLE hFile = (HANDLE)pfdtab->tab[i].native; + HANDLE hFile = shfile_set_inherit_win(&pfdtab->tab[i], 1); TRACE2((NULL, " #%d: native=%#x oflags=%#x shflags=%#x\n", i, hFile, pfdtab->tab[i].oflags, pfdtab->tab[i].shflags)); - - if (!SetHandleInformation(hFile, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) - { -#if 0 /* Seems to fail for console handles, ignore. */ - DWORD err = GetLastError(); - assert(0); -#endif - } paf[i] = FOPEN; if (pfdtab->tab[i].oflags & _O_APPEND) paf[i] |= FAPPEND; @@ -913,14 +1010,7 @@ void *shfile_exec_win(shfdtab *pfdtab, int prepare, unsigned short *sizep, intpt { if ( pfdtab->tab[i].fd == i && !(pfdtab->tab[i].shflags & SHFILE_FLAGS_CLOSE_ON_EXEC)) - { - HANDLE hFile = (HANDLE)pfdtab->tab[i].native; - if (!SetHandleInformation(hFile, HANDLE_FLAG_INHERIT, 0)) - { - DWORD err = GetLastError(); - assert(0); - } - } + shfile_set_inherit_win(&pfdtab->tab[i], 0); } pvRet = NULL; } @@ -1200,7 +1290,10 @@ int shfile_movefd(shfdtab *pfdtab, int fdfrom, int fdto) return rc; #else - return dup2(fdfrom, fdto); + int fdnew = dup2(fdfrom, fdto); + if (fdnew >= 0) + close(fdfrom); + return fdnew; #endif } @@ -1355,30 +1448,25 @@ long shfile_write(shfdtab *pfdtab, int fd, const void *buf, size_t len) else rc = -1; +# ifdef DEBUG + if (fd != shthread_get_shell()->tracefd) + TRACE2((NULL, "shfile_write(%d,,%d) -> %d [%d]\n", fd, len, rc, errno)); +# endif + #else if (fd != shthread_get_shell()->tracefd) { + int iSavedErrno = errno; struct stat s; int x; x = fstat(fd, &s); TRACE2((NULL, "shfile_write(%d) - %lu bytes (%d) - pos %lu - before; %o\n", fd, (long)s.st_size, x, (long)lseek(fd, 0, SEEK_CUR), s.st_mode )); - errno = 0; + errno = iSavedErrno; } rc = write(fd, buf, len); #endif - -#ifdef DEBUG - if (fd != shthread_get_shell()->tracefd) - { - struct stat s; - int x; - TRACE2((NULL, "shfile_write(%d,,%d) -> %d [%d]\n", fd, len, rc, errno)); - x=fstat(fd, &s); - TRACE2((NULL, "shfile_write(%d) - %lu bytes (%d) - pos %lu - after\n", fd, (long)s.st_size, x, (long)lseek(fd, 0, SEEK_CUR) )); - } -#endif return rc; } @@ -1502,7 +1590,7 @@ int shfile_fcntl(shfdtab *pfdtab, int fd, int cmd, int arg) { case F_GETFL: TRACE2((NULL, "shfile_fcntl(%d,F_GETFL,ignored=%d) -> %d [%d]\n", fd, arg, rc, errno)); break; case F_SETFL: TRACE2((NULL, "shfile_fcntl(%d,F_SETFL,newflags=%#x) -> %d [%d]\n", fd, arg, rc, errno)); break; - case F_DUPFD: TRACE2((NULL, "shfile_fcntl(%d,F_DUPFS,minfd=%d) -> %d [%d]\n", fd, arg, rc, errno)); break; + case F_DUPFD: TRACE2((NULL, "shfile_fcntl(%d,F_DUPFD,minfd=%d) -> %d [%d]\n", fd, arg, rc, errno)); break; default: TRACE2((NULL, "shfile_fcntl(%d,%d,%d) -> %d [%d]\n", fd, cmd, arg, rc, errno)); break; } return rc; @@ -1517,7 +1605,13 @@ int shfile_stat(shfdtab *pfdtab, const char *path, struct stat *pst) if (!rc) { # if K_OS == K_OS_WINDOWS + int dir_slash = shfile_trailing_slash_hack(abspath); rc = stat(abspath, pst); /** @todo re-implement stat. */ + if (!rc && dir_slash && !S_ISDIR(pst->st_mode)) + { + rc = -1; + errno = ENOTDIR; + } # else rc = stat(abspath, pst); # endif @@ -1539,7 +1633,13 @@ int shfile_lstat(shfdtab *pfdtab, const char *path, struct stat *pst) if (!rc) { # if K_OS == K_OS_WINDOWS - rc = stat(abspath, pst); /** @todo implement lstat. */ + int dir_slash = shfile_trailing_slash_hack(abspath); + rc = stat(abspath, pst); /** @todo re-implement stat. */ + if (!rc && dir_slash && !S_ISDIR(pst->st_mode)) + { + rc = -1; + errno = ENOTDIR; + } # else rc = lstat(abspath, pst); # endif @@ -1566,12 +1666,13 @@ int shfile_chdir(shfdtab *pfdtab, const char *path) { char *abspath_copy = sh_strdup(psh, abspath); char *free_me = abspath_copy; - rc = chdir(path); + rc = chdir(abspath); if (!rc) { shmtxtmp tmp; shmtx_enter(&pfdtab->mtx, &tmp); + shfile_fix_slashes(abspath_copy); free_me = pfdtab->cwd; pfdtab->cwd = abspath_copy; @@ -1769,6 +1870,8 @@ shdir *shfile_opendir(shfdtab *pfdtab, const char *dir) #if defined(SHFILE_IN_USE) && K_OS == K_OS_WINDOWS shdir *pdir = NULL; + TRACE2((NULL, "shfile_opendir: dir='%s'\n", dir)); + shfile_init_globals(); if (g_pfnNtQueryDirectoryFile) { char abspath[SHFILE_MAX_PATH]; @@ -1801,13 +1904,17 @@ shdir *shfile_opendir(shfdtab *pfdtab, const char *dir) CloseHandle(hFile); } else - shfile_dos2errno(GetLastError()); + { + errno = shfile_dos2errno(GetLastError()); + TRACE2((NULL, "shfile_opendir: CreateFileA(%s) -> %d/%d\n", abspath, GetLastError(), errno)); + } } } else errno = ENOSYS; return pdir; #else + TRACE2((NULL, "shfile_opendir: dir='%s'\n", dir)); return (shdir *)opendir(dir); #endif } diff --git a/src/kash/shinstance.c b/src/kash/shinstance.c index 1eeb0db..b105130 100644 --- a/src/kash/shinstance.c +++ b/src/kash/shinstance.c @@ -1,4 +1,4 @@ -/* $Id: shinstance.c 2546 2011-10-01 19:49:54Z bird $ */ +/* $Id: shinstance.c 2652 2012-09-09 17:21:48Z bird $ */ /** @file * The shell instance methods. */ @@ -43,6 +43,9 @@ # include <Windows.h> extern pid_t shfork_do(shinstance *psh); /* shforkA-win.asm */ #endif +#if !defined(HAVE_SYS_SIGNAME) && defined(DEBUG) +extern void init_sys_signame(void); +#endif /******************************************************************************* @@ -587,14 +590,28 @@ int sh_sigaction(shinstance *psh, int signo, const struct shsigaction *newp, str g_sig_state[signo].sa.sa_handler = SIG_DFL; g_sig_state[signo].sa.sa_flags = psh->sigactions[signo].sh_flags & SA_RESTART; +#if !defined(HAVE_SYS_SIGNAME) && defined(DEBUG) + init_sys_signame(); +#endif TRACE2((psh, "sh_sigaction: setting signo=%d:%s to {.sa_handler=%p, .sa_flags=%#x}\n", - signo, sys_signame[signo], g_sig_state[signo].sa.sa_handler, g_sig_state[signo].sa.sa_flags)); + signo, sys_signame[signo], g_sig_state[signo].sa.sa_handler, g_sig_state[signo].sa.sa_flags)); #ifdef _MSC_VER if (signal(signo, g_sig_state[signo].sa.sa_handler) == SIG_ERR) + { + TRACE2((psh, "sh_sigaction: SIG_ERR, errno=%d signo=%d\n", errno, signo)); + if ( signo != SIGHUP /* whatever */ + && signo != SIGQUIT + && signo != SIGPIPE + && signo != SIGTTIN + && signo != SIGTSTP + && signo != SIGTTOU + && signo != SIGCONT) + assert(0); + } #else if (sigaction(signo, &g_sig_state[signo].sa, NULL)) -#endif assert(0); +#endif shmtx_leave(&g_sh_mtx, &tmp); } @@ -1174,6 +1191,21 @@ int sh_execve(shinstance *psh, const char *exe, const char * const *argv, const } errno = EINVAL; } + else + { + DWORD dwErr = GetLastError(); + switch (dwErr) + { + case ERROR_FILE_NOT_FOUND: errno = ENOENT; break; + case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; + case ERROR_BAD_EXE_FORMAT: errno = ENOEXEC; break; + case ERROR_INVALID_EXE_SIGNATURE: errno = ENOEXEC; break; + default: + errno = EINVAL; + break; + } + TRACE2((psh, "sh_execve: dwErr=%d -> errno=%d\n", dwErr, errno)); + } shfile_exec_win(&psh->fdtab, 0 /* done */, NULL, NULL); } @@ -1410,3 +1442,15 @@ int sh_setrlimit(shinstance *psh, int resid, const shrlimit *limp) return rc; } + +/* Wrapper for strerror that makes sure it doesn't return NULL and causes the + caller or fprintf routines to crash. */ +const char *sh_strerror(shinstance *psh, int error) +{ + char *err = strerror(error); + if (!err) + return "strerror return NULL!"; + (void)psh; + return err; +} + diff --git a/src/kash/shinstance.h b/src/kash/shinstance.h index 11dac28..14829c8 100644 --- a/src/kash/shinstance.h +++ b/src/kash/shinstance.h @@ -1,4 +1,4 @@ -/* $Id: shinstance.h 2546 2011-10-01 19:49:54Z bird $ */ +/* $Id: shinstance.h 2657 2012-09-10 20:57:58Z bird $ */ /** @file * The shell instance and it's methods. */ @@ -38,7 +38,7 @@ #endif #include <errno.h> #ifdef _MSC_VER -# define EWOULDBLOCK 512 +# define EWOULDBLOCK 140 #endif #include "shtypes.h" @@ -445,7 +445,7 @@ int sh_add_child(shinstance *psh, pid_t pid, void *hChild); #else # include <sys/wait.h> # ifdef __HAIKU__ -# define WCOREDUMP(x) (0) /** @todo check the haiku headers and see if this information is available or not... */ +# define WCOREDUMP(x) WIFCORED(x) # endif #endif pid_t sh_fork(shinstance *); @@ -493,13 +493,15 @@ int sh_tcsetpgrp(shinstance *, int, pid_t); int sh_getrlimit(shinstance *, int, shrlimit *); int sh_setrlimit(shinstance *, int, const shrlimit *); +/* string.h */ +const char *sh_strerror(shinstance *, int); #ifdef DEBUG # define TRACE2(param) trace param # define TRACE2V(param) tracev param #else -# define TRACE2(param) -# define TRACE2V(param) +# define TRACE2(param) do { } while (0) +# define TRACE2V(param) do { } while (0) #endif #endif diff --git a/src/kash/var.c b/src/kash/var.c index cf73e8d..51e1001 100644 --- a/src/kash/var.c +++ b/src/kash/var.c @@ -68,11 +68,6 @@ extern APIRET #endif -#if defined(_MSC_VER) || defined(_WIN32) - /* On Windows the PATH variable is called "Path". */ -# define PC_MIXED_PATH_VAR_NAME -#endif - /* @@ -363,6 +358,19 @@ setvareq(shinstance *psh, char *s, int flags) struct var *vp, **vpp; int nlen; +#if defined(_MSC_VER) || defined(_WIN32) + /* On Windows PATH is often spelled 'Path', correct this here. */ + if ( s[0] == 'P' + && s[1] == 'a' + && s[2] == 't' + && s[3] == 'h' + && (s[4] == '\0' || s[4] == '=') ) { + s[1] = 'A'; + s[2] = 'T'; + s[3] = 'H'; + } +#endif + if (aflag(psh)) flags |= VEXPORT; vp = find_var(psh, s, &vpp, &nlen); @@ -400,19 +408,6 @@ setvareq(shinstance *psh, char *s, int flags) if (flags & VNOSET) return; -#ifdef PC_MIXED_PATH_VAR_NAME - if ( nlen == 4 - && (s[0] == 'p' || s[0] == 'P') - && (s[1] == 'a' || s[1] == 'A') - && (s[2] == 't' || s[2] == 'T') - && (s[3] == 'h' || s[3] == 'H') ) { - s[0] = 'P'; - s[1] = 'A'; - s[2] = 'T'; - s[3] = 'H'; - } -#endif - vp = ckmalloc(psh, sizeof (*vp)); vp->flags = flags & ~VNOFUNC; vp->text = s; @@ -927,22 +922,6 @@ find_var(shinstance *psh, const char *name, struct var ***vppp, int *lenp) hashval = 2 * hashval + (unsigned char)*p++; len = (int)(p - name); -#ifdef PC_MIXED_PATH_VAR_NAME - /* On Windows the PATH variable is called "Path". */ - if ( len == 4 - && (name[0] == 'p' || name[0] == 'P') - && (name[1] == 'a' || name[1] == 'A') - && (name[2] == 't' || name[2] == 'T') - && (name[3] == 'h' || name[3] == 'H') ) - { - name = "PATH"; - hashval = (unsigned char)'P'; - hashval = hashval * 2 + (unsigned char)'A'; - hashval = hashval * 2 + (unsigned char)'T'; - hashval = hashval * 2 + (unsigned char)'H'; - } -#endif - if (lenp) *lenp = len; vpp = &psh->vartab[hashval % VTABSIZE]; diff --git a/src/kash/var.h b/src/kash/var.h index 7bec49c..ce17bab 100644 --- a/src/kash/var.h +++ b/src/kash/var.h @@ -107,9 +107,9 @@ extern struct var vhistsize; #define mailval(psh) ((psh)->vmail.text + 5) #define mpathval(psh) ((psh)->vmpath.text + 9) #ifdef _MSC_VER -#define pathval(psh) ((psh)->vpath.text[5] ? &(psh)->vpath.text[5] : &(psh)->vpath2.text[5]) +# define pathval(psh) ((psh)->vpath.text[5] || !(psh)->vpath2.text ? &(psh)->vpath.text[5] : &(psh)->vpath2.text[5]) #else -#define pathval(psh) ((psh)->vpath.text + 5) +# define pathval(psh) ((psh)->vpath.text + 5) #endif #define ps1val(psh) ((psh)->vps1.text + 4) #define ps2val(psh) ((psh)->vps2.text + 4) diff --git a/src/kmk/AUTHORS b/src/kmk/AUTHORS index 647e577..8de80e6 100644 --- a/src/kmk/AUTHORS +++ b/src/kmk/AUTHORS @@ -66,8 +66,8 @@ With suggestions/comments/bug reports from a cast of ... well ... hundreds, anyway :) ------------------------------------------------------------------------------- -Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 -Free Software Foundation, Inc. +Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/ChangeLog b/src/kmk/ChangeLog index d923a80..d135d1c 100644 --- a/src/kmk/ChangeLog +++ b/src/kmk/ChangeLog @@ -1,3 +1,842 @@ +2010-07-28 Paul Smith <psmith@gnu.org> + + Version 3.82 released. + + * configure.in: Change release version. + * NEWS: Change the date. + + * read.c (parse_file_seq): Remove GLOB_NOSORT for + backward-compatibility. We'll add it back in next release. + * NEWS: Note it. + +2010-07-24 Eli Zaretskii <eliz@gnu.org> + + * job.c (pid2str) [WINDOWS32]: Fix CPP conditionals for using %Id + format. + +2010-07-18 Paul Smith <psmith@gnu.org> + + * configure.in: Switch bsd_signal to AC_CHECK_DECLS() to make sure + we have a declaration. Fixes Savannah bug #25713 (maybe?) + * doc/make.texi (Complex Makefile): Cleanup variable assignments. + (One Shell): New subsection for the .ONESHELL special target. + + Patches by Ozkan Sezer <sezeroz@gmail.com>: + + * misc.c (strncasecmp): Local implementation for systems without. + * config.h.W32.template (HAVE_STRNICMP): Define on Windows. + * configure.in: Check for strncasecmp/strncmpi/strnicmp. + * job.c [WINDOWS32]: Don't define dup2 on Windows. + (pid2str): Use "%Id" even with MSVC + (exec_command): Cast to pid_t when calling pid2str(). + * w32/subproc/sub_proc.c [WINDOWS32]: Include config.h first. + Use stddef.h on MSVC to get intptr_t. + * w32/subproc/misc.c [WINDOWS32]: Include config.h first. + * w32/compat/dirent.c [WINDOWS32]: Include config.h first. + (readdir): Cast -1 to correct type for d_ino. + * w32/pathstuff.c [WINDOWS32]: Ensure make.h is included first. + * make.h [WINDOWS32]: Don't prototype alloca() on Windows. + Add configuration for strncasecmp(). + * main.c (ADD_SIG) [WINDOWS32]: Avoid warnings in MSVC. + * config.h.W32.template [WINDOWS32]: Don't warn on unsafe + functions or variables. + * NMakefile.template [WINDOWS32]: Remove /MACHINE:I386. + * main.c (clean_jobserver): Cast due to MSVC brokenness. + (decode_switches): Ditto. + * vpath.c (construct_vpath_list): Ditto. + * rule.c (freerule): Ditto. + * ar.c (ar_glob): Ditto. + +2010-07-16 Boris Kolpackov <boris@codesynthesis.com> + + * misc.c (concat): Fix buffer overrun. + +2010-07-12 Paul Smith <psmith@gnu.org> + + Update copyrights to add 2010. + + * build_w32.bat: Support for MSVC Windows x86_64 builds. + * job.c: Don't define execve() on MSVC/64bit. + Patch by Viktor Szakats. Fixes Savannah bug #27590. + +2010-07-12 Eli Zaretskii <eliz@gnu.org> + + * make.h (alloca) [!__GNUC__]: Don't define prototype. + (int w32_kill): Use pid_t for process ID argument. + Fixes Savannah bug #27809. + +2010-07-12 Paul Smith <psmith@gnu.org> + + Integrated new .ONESHELL feature. + Patch by David Boyce <dsb@boyski.com>. Modified by me. + + * NEWS: Add a note about the new feature. + * job.c (is_bourne_compatible_shell): Determine whether we're + using a standard POSIX shell or not. + (start_job_command): Accept '-ec' as POSIX shell flags. + (construct_command_argv_internal): If one_shell is set and we are + using a POSIX shell, remove "interior" prefix characters such as + "@", "+", "-". Also treat "\n" as a special character when + choosing the slow path, if ONESHELL is set. + * job.h (is_bourne_compatible_argv): Define the new function. + + * make.h (one_shell): New global variable to remember setting. + * main.c: Declare it. + * read.c (record_files): Set it. + * commands.c (chop_commands): If one_shell is set, don't chop + commands into multiple lines; just keep one line. + +2010-07-09 Eli Zaretskii <eliz@gnu.org> + + * w32/subproc/sub_proc.c: Include stdint.h. + (sub_process_t): Use intptr_t for file handles and pid_t for + process ID. + (process_pipes, process_init_fd, process_begin): Use intptr_t for + file handles and pid_t for process ID. Fixes Savannah bug #27809. + Patch by Ozkan Sezer <sezeroz@gmail.com> + + * function.c (abspath): Support absolute file names in UNC format. + Fixes Savannah bug #30312. + + * job.c (pid2str) [WINDOWS32]: Don't use %Id with GCC < 4.x. + (exec_command) [WINDOWS32]: Use pid2str instead of non-portable + %Id. + + * main.c (handle_runtime_exceptions): Use %p to print addresses, + to DTRT on both 32-bit and 64-bit hosts. Savannah bug #27809. + + * job.c (w32_kill, start_job_command, create_batch_file): Use + pid_t for process IDs and intptr_t for the 1st arg of + _open_osfhandle. + * function.c (windows32_openpipe): Use pid_t for process IDs and + intptr_t for the 1st arg of _open_osfhandle. + (func_shell): Use pid_t for process IDs. + * main.c (main) [WINDOWS32]: Pacify the compiler. + * config.h.W32.template (pid_t): Add a definition for 64-bit + Windows builds that don't use GCC. Fixes Savannah bug #27809. + Patch by Ozkan Sezer <sezeroz@gmail.com> + +2010-07-07 Paul Smith <psmith@gnu.org> + + * configure.in: Bump to a new prerelease version 3.81.91. + +2010-07-06 Paul Smith <psmith@gnu.org> + + * main.c (main): Set a default value of "-c" for .SHELLFLAGS. + * NEWS: Mention the new behavior of .POSIX and the new .SHELLFLAGS + variable. + * job.c (construct_command_argv): Retrieve the .SHELLFLAGS value + and pass it to construct_command_argv_internal(). + (construct_command_argv_internal): If .SHELLFLAGS is non-standard + use the slow path. Use that value instead of hard-coded "-c". + +2010-07-05 Paul Smith <psmith@gnu.org> + + * implicit.c (pattern_search): lastslash can be const. + * dir.c (downcase): Remove unused variable. + * hash.c (hash_init): Cast sizeof for error message. + * arscan.c (ar_scan): Cast to char* for WINDOWS32. + (ar_member_touch): Ditto. + * ar.c (glob_pattern_p): Avoid symbol collision: open -> opened + * signame.c (strsignal): Ditto: signal -> sig + * job.c (create_batch_file): Ditto: error -> error_string + (pid2str): Portably convert a pid_t into a string + (reap_children): Use it. + (start_waiting_job): Use it. + Savannah bug #27809. Patch by Ozkan Sezer <sezeroz@gmail.com> + +2010-07-03 Paul Smith <psmith@gnu.org> + + * read.c (parse_file_seq): All archive groups must end with ')' as + the LAST character in a word. If there is no word ending in ')' + then it's not an archive group. Fixes Savannah bug #28525. + +2010-07-01 Paul Smith <psmith@gnu.org> + + * main.c (main): Append optional features using separate calls. + Not as efficient but not all compilers allow conditionals inside + macro calls. Fixes Savannah bug #29244. + +2010-01-10 Paul Smith <psmith@gnu.org> + + * make.h (patheq): Rename strieq() to patheq() for clarity. + * dir.c (dir_contents_file_exists_p): Use it. + + * dir.c (file_impossible): Convert xmalloc/memset to xcalloc. + * file.c (enter_file): Ditto. + * job.c (new_job): Ditto. + +2009-12-11 Eli Zaretskii <eliz@gnu.org> + + * job.c (construct_command_argv_internal) <sh_cmds_dos> + [WINDOWS32]: Add "echo." and a few more commands that are built + into cmd.exe. Fixes Savannah bug #28126. + + * file.c (lookup_file) [HAVE_DOS_PATHS]: Treat '\\' like we do + with '/'. + +2009-11-15 Paul Smith <psmith@gnu.org> + + Patches for VMS provided by Hartmut Becker <Hartmut.Becker@hp.com> + + * vmsjobs.c (ctrlYPressed) [VMS]: Deal with CTRL-Y. + (vmsHandleChildTerm) [VMS]: Ditto. + (astYHandler) [VMS]: Ditto. + (tryToSetupYAst) [VMS]: Ditto. + (child_execute_job) [VMS]: Ditto. + + * vmsify.c (trnlog) [VMS]: Fix const errors. + (vmsify) [VMS]: Ditto. + + * readme.vms [VMS]: Update with notes for 3.82. + + * job.h (comname) [VMS]: Remember the temporary command filename + + * dir.c (vmsify) [VMS]: Fix const errors. + (vms_hash) [VMS]: Ditto. + (vmsstat_dir) [VMS]: Ditto. + (find_directory) [VMS]: Fix case-insensitive option for VMS + (dir_contents_file_exists_p) [VMS]: Ditto. + (file_impossible) [VMS]: Ditto. + + * config.h-vms.template (HAVE_FDOPEN) [VMS]: Have it. + (HAVE_STRCASECMP) [VMS]: Ditto. + + * arscan.c (VMS_get_member_info) [VMS]: Fix timezone computation. + (ar_scan) [VMS]: Fix const error. + +2009-11-12 Boris Kolpackov <boris@codesynthesis.com> + + * vpath.c (vpath_search, selective_vpath_search): Add index arguments + which allows the caller to get the index of the matching directory. + + * make.h (vpath_search): Update prototype. + + * remake.c (library_search): Implement linker-compatible library + search. Use the new VPATH_SEARCH index functionality to keep track + of the directory index for each match. Select the match with the + lowest directory index. + + * implicit.c (pattern_search): Pass NULL for the index arguments in + the VPATH_SEARCH call. + + * doc/make.texi (Directory Search for Link Libraries): Describe the + new search behavior. + + * NEWS: Add a note about the new behavior. + +2009-10-25 Paul Smith <psmith@gnu.org> + + * AUTHORS, et.al.: Update copyright years. + + * implicit.c (stemlen_compare): Fix qsort() compare bug that + caused implicit rules with equal stem lengths to be sorted + indeterminately. + +2009-10-24 Paul Smith <psmith@gnu.org> + + * main.c (usage): Add --eval to the usage string. + (switches): Add the --eval switch. + (main): If --eval is given, add them to the simply-expanded variable + -*-eval-flags-*- (necessary to allow recursion to work properly). + (define_makeflags): Add -*-eval-flags-*- to MAKEFLAGS. + + * NEWS: Describe the new --eval command line argument. + * doc/make.texi (Options Summary): Document --eval. + + * dep.h: eval_buffer() returns void. + * read.c (eval_buffer): Ditto. + (eval): Ditto. + + * variable.h (define_variable_cname): New macro for constant + variable names. + * default.c (set_default_suffixes): Use it. + * main.c (main): Ditto. + (handle_non_switch_argument): Ditto. + (define_makeflags): Ditto. + * read.c (read_all_makefiles): Ditto. + * variable.c (define_automatic_variables): Ditto. + + * commands.c (dep_hash_cmp): Avoid casts. + (dep_hash_1): Ditto. + (dep_hash_2): Ditto. + +2009-10-22 Boris Kolpackov <boris@codesynthesis.com> + + * read.c (read_all_makefiles): Mark the default makefile dependency + dontcare. + +2009-10-07 Boris Kolpackov <boris@codesynthesis.com> + + * read.c (do_undefine): Free the expanded variable name. + + * commands.c (dep_hash_cmp, set_file_variables): Move the order-only + to normal upgrade logic from dep_hash_cmp to set_file_variables. + +2009-10-06 Boris Kolpackov <boris@codesynthesis.com> + + * dep.h (uniquize_deps): Remove. + + * read.c (uniquize_deps): Merge into set_file_variables in + commands.c. + (dep_hash_1, dep_hash_2, dep_hash_cmp): Move to commands.c. + + * commands.c (set_file_variables): Avoid modifying the dep + chain to achieve uniqueness. Fixes savannah bug 25780. + + * implicit.c (pattern_search): Instead of re-setting all automatic + variables for each rule we try, just update $*. + +2009-10-06 Boris Kolpackov <boris@codesynthesis.com> + + * variable.h (undefine_variable_in_set): New function declaration. + (undefine_variable_global): New macro. + + * variable.c (undefine_variable_in_set): New function implementation. + + * read.c (vmodifiers): Add undefine_v modifier. + (parse_var_assignment): Parse undefine. + (do_undefine): Handle the undefine directive. + (eval): Call do_undefine if undefine_v is set. + + * main.c (.FEATURES): Add a keyword to indicate the new feature. + + * doc/make.texi (Undefine Directive): Describe the new directive. + + * NEWS: Add a note about the new directive. + +2009-10-05 Boris Kolpackov <boris@codesynthesis.com> + + * implicit.c (pattern_search): Initialize file variables only + if we need to parse a rule that requires the second expansion. + +2009-10-03 Paul Smith <psmith@gnu.org> + + * make.h: Include <alloca.h> even on systems where __GNUC__ is + defined. Not sure why it was done the other way. + Requested by David Boyce <dsb@boyski.com>. + +2009-09-30 Boris Kolpackov <boris@codesynthesis.com> + + * dep.h (dep): Add the DONTCARE bitfield. + + * filedef.h (file):Add the NO_DIAG bitfield. + + * read.c (eval_makefile): Set the DONTCARE flag in struct dep, + not struct file (a file can be a dependency of many targets, + some don't care, some do). + + * remake.c (update_goal_chain): Propagate DONTCARE from struct + dep to struct file before updating the goal and restore it + afterwards. + (update_file): Don't prune the dependency graph if this target + has failed but the diagnostics hasn't been issued. + (complain): Scan the file's dependency graph to find the file + that caused the failure. + (update_file_1): Use NO_DIAG instead of DONTCARE to decide + whether to print diagnostics. + + Fixes Savannah bugs #15110, #25493, #12686, and #17740. + +2009-09-28 Paul Smith <psmith@gnu.org> + + * doc/make.texi (Pattern Intro): Move the match algorithm + discussion into the "Pattern Match" node. + (Pattern Match): Expand on the pattern rule matching algorithm. + +2009-09-28 Andreas Buening <andreas.buening@nexgo.de> + + * job.c (construct_command_argv_internal) [OS2]: Don't eat too + much of the command line on a single pass. + +2009-09-28 Boris Kolpackov <boris@codesynthesis.com> + + * varible.c (create_pattern_var): Insert variables into the + PATTERN_VARS list in the shortest patterns first order. + + * implicit.c (tryrule): Add STEMLEN and ORDER members. These are + used to sort the rules. + (stemlen_compare): Compare two tryrule elements. + (pattern_search): Sort the rules so that they are in the shortest + stem first order. + + * main.c (.FEATURES): Add a keyword to indicate the new behavior. + + * doc/make.texi (Pattern-specific Variable Values): Describe the + new pattern-specific variables application order. + (Introduction to Pattern Rules): Describe the new pattern rules + search order. + + * NEWS: Add a note about the new behavior. + +2009-09-27 Paul Smith <psmith@gnu.org> + + * doc/make.texi (Double-Colon): Mention that pattern rules with + double-colons have a different meaning. Savannah bug #27497. + +2009-09-27 Juan Manuel Guerrero <juan.guerrero@gmx.de> + + * configh.dos.template: Remove unconditional definition of + SYS_SIGLIST_DECLARED. + Include <sys/version.h> because ports of GCC 4.3.0 and later no + longer include it, so macros like __DJGPP_MINOR__ are no longer + defined automatically. + + * Makefile.DOS.template (INCLUDES): Use $(prefix) and the + corresponding variables to define LIBDIR, INCLUDEDIR and LOCALEDIR + instead of using the hardcoded ones. + (SUBDIRS): doc subdir added. + (INFO_DEPS, DVIS): Values changed to 'make.info' and 'make.dvi'. + (TEXI2HTML, TEXI2HTML_FLAGS): Removed. Use makeinfo --html to + create html formated docs. texi2html may not be ported to DOS. + (make.info, make.dvi, make.ps, make.html): Make targets depend on + 'make.texi'. + (.texi.info, .texi, .texi.dvi): Now invoked recursively. Change + -I switch to look in ./ instead of ./doc. + (html): Target depend on html-recursive instead of make_1.html. + (make_1.html): Removed. + (mostlyclean-aminfo): Use $(srcdir)/doc instead of ./ as prefix. + (all-recursive): Allow for more than one subdir in the build + process. + (mostlyclean-recursive, clean-recursive, distclean-recursive) + (maintainer-clean-recursive, check-recursive): Enter in doc/ too. + (tags-recursive): Allow for more than one subdir in the build + process. + (info-recursive, dvi-recursive, ps-recursive, html-recursive): New + targets. Enter into doc/ to produce the targets. + (all-am): $(INFO_DEPS) replaced by info. + +2009-09-26 Paul Smith <psmith@gnu.org> + + * read.c (record_files): Use free_ns() to free struct nameseq. + (eval): Ditto. + + * rule.c (freerule): Use free_dep_chain(). + + * read.c (record_files): Free FILENAMES chain for implicit rules. + (eval): Static pattern targets go into the string cache. + + * function.c (string_glob): Free NAME in the nameseq chain. + +2009-09-25 Boris Kolpackov <boris@codesynthesis.com> + + * implicit.c (pattern_search): Terminate early if we haven't + found any rules to try (performance improvement). + +2009-09-25 Boris Kolpackov <boris@codesynthesis.com> + + * implicit.c (pattern_search): Merge three parallel arrays, + TRYRULES, MATCHES, and CHECKED_LASTSLASH, into one array + of struct TRYRULE. In the old version the latter two arrays + had insufficient length. + +2009-09-24 Paul Smith <psmith@gnu.org> + + * implicit.c (pattern_search): Add back support for order-only + prerequisites for secondary expansion implicit rules, that were + accidentally dropped. If we find a "|", enable order-only mode + and set IGNORE_MTIME on all deps that are seen afterward. + (pattern_search): Fix memory leaks: for intermediate files where + we've already set the file variable and pattern variable sets, be + sure to either save or free them as appropriate. + +2009-09-23 Paul Smith <psmith@gnu.org> + + Rework the way secondary expansion is stored, for efficiency. + This changes secondary expansion so that ONLY WHEN we know we have + a possibility of needing secondary expansion, do we defer the + secondary expansion. This means more parsing the deps but we use + a lot less memory (due to the strcache). Also, this fixes + Savannah bug #18622. + + * read.c (eval): Don't parse the dep string here anymore. + (record_files): Take the dep argument as an unparsed string. If + secondary expansion is enabled AND the prereq string has a '$' in + it, then set NEED_2ND_EXPANSION and keep the entire string. + Otherwise, parse the dep string here to construct the dep list + with the names in the strcache. + + * misc.c (copy_dep_chain): For NEED_2ND_EXPANSION, we need to + duplicate the name string (others are in the strcache). + + * implicit.c: Remove struct idep and free_idep_chain(): unused. + (struct patdeps): New structure to store prereq information. + (pattern_search): Use the NEED_2ND_EXPANSION flag to determine + which prerequisites need expansion, and expand only those. + + * file.c (split_prereqs): Break parse_prereqs() into two parts: this + and enter_prereqs(). split_prereqs() takes a fully-expanded string + and splits it into a DEP list, handling order-only prereqs. + (enter_prereqs): This function enters a list of DEPs into the file + database. If there's a stem defined, expand any pattern chars. + (expand_deps): Only try to expand DEPs which have NEED_2ND_EXPANSION + set. Use the above functions. + (snap_deps): Only perform second expansion on prereqs that need it, + as defined by the NEED_2ND_EXPANSION flag. + (print_prereqs): New function to print the prereqs + (print_file): Call print_prereqs() rather than print inline. + + * hash.h (STRING_COMPARE): Take advantage of strcache() by + comparing pointers. + (STRING_N_COMPARE): Ditto. + (ISTRING_COMPARE): Ditto. + + * dep.h (PARSE_FILE_SEQ): New macro to reduce casts. + (parse_file_seq): Return void* + * read.c (parse_file_seq): Return void*. + (eval): Invoke macroized version of parse_file_seq() + * default.c (set_default_suffixes): Ditto. + * file.c (split_prereqs): Ditto. + * function.c (string_glob): Ditto. + * main.c (main): Ditto. + * rule.c (install_pattern_rule): Ditto. + + * filedef.h: Add split_prereqs(), enter_prereqs(), etc. + +2009-09-16 Paul Smith <psmith@gnu.org> + + * misc.c (alloc_dep, free_dep): Now that we have xcalloc(), + convert to macros. + * dep.h: Create alloc_dep() / free_dep() macros. + + * implicit.c (pattern_search): Take advantage of the new + parse_file_seq() to add the directory prefix to each prereq. + + * dep.h: Remove multi_glob() and enhance parse_file_seq() to do it + all. Avoid reversing chains. Support adding prefixes. + * read.c (parse_file_seq): Rewrite to support globbing. Allow for + cached/non-cached results. + (eval): Remove multi_glob() & invoke new parse_file_seq(). + * rule.c (install_pattern_rule): Ditto. + * main.c (main): Ditto. + * implicit.c (pattern_search): Ditto. + * function.c (string_glob): Ditto. + * file.c (parse_prereqs): Ditto. + * default.c (set_default_suffixes): Ditto. + + * variable.c (parse_variable_definition): Don't run off the end of + the string if it ends in whitespace (found with valgrind). + + * commands.c (set_file_variables): Keep space for all targets in + $? if -B is given (found with valgrind). + +2009-09-15 Paul Smith <psmith@gnu.org> + + * misc.c (concat): Make concat() variadic so it takes >3 arguments. + (xcalloc): Add new function. + * make.h: New declarations. + + * ar.c (ar_glob_match): New calling method for concat(). + * main.c (main): Ditto. + (decode_env_switches): Ditto. + * read.c (eval_makefile): Ditto. + (tilde_expand): Ditto. + (parse_file_seq): Ditto. + * variable.c (target_environment): Ditto. + (sync_Path_environment): Ditto. + + * ar.c (ar_glob_match): Use xcalloc(). + * dir.c (file_impossible): Ditto. + * file.c (enter_file): Ditto. + * job.c (new_job): Ditto. + * read.c (parse_file_seq): Ditto. + * vmsfunctions.c (opendir): Ditto. + +2009-09-14 Rafi Einstein <rafi.einstein@gmail.com> (tiny patch) + + * w32/subproc/sub_proc.c (process_begin): Check *ep non-NULL + inside the loop that looks up environment for PATH. + +2009-08-31 Eli Zaretskii <eliz@gnu.org> + + * function.c (windows32_openpipe): Update envp after calling + sync_Path_environment. + +2009-08-02 Paul Smith <psmith@gnu.org> + + * remake.c (notice_finished_file): Ensure file->cmds is not null + before looping through them. Fixes Savannah bug #21824. + + * doc/make.texi (Wildcard Examples): Clarify when objects is + wildcard-expanded. Fixes Savannah bug #24509. Patch by Martin Dorey. + (Include): Clarify the behavior of -include. + Fixes Savannah bug #18963. + +2009-08-01 Paul Smith <psmith@gnu.org> + + * doc/make.texi (Catalogue of Rules): Clarify where -c, -F, + etc. come on the command line. Fixes Savannah bug #27093. + + * expand.c (expand_argument): If the argument is large enough use + xmalloc() instead of alloca(). Fixes Savannah bug #27143. + + * variable.c (do_variable_definition): Avoid using alloca() to + hold values, which can be large. Fixes Savannah bug #23960. + + * job.c (new_job): Use memmove() instead of strcpy() since both + pointers are in the same memory block. Fixes Savannah bug #27148. + Patch by Petr Machata. + +2009-07-29 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * job.c (construct_command_argv_internal): Add "ulimit" and + "unset" to the sh_cmds for Unixy shells. + +2009-07-29 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * configure.in: Move side-effects outside AC_CACHE_VAL arguments + that set make_cv_sys_gnu_glob, so they are also correctly set + when the cache has been populated before. + +2009-07-04 Eli Zaretskii <eliz@gnu.org> + + * function.c (func_realpath) [!HAVE_REALPATH]: Require the file to + exist, as realpath(3) does where it's supported. + +2006-07-04 Eli Zaretskii <eliz@gnu.org> + + * function.c (IS_ABSOLUTE, ROOT_LEN): New macros. + (abspath): Support systems that define HAVE_DOS_PATHS (have + drive letters in their file names). Use IS_PATHSEP instead of a + literal '/' comparison. Fixes Savannah bug #26886. + +2009-06-14 Paul Smith <psmith@gnu.org> + + * remake.c (update_file_1): Remember the original file we marked + as updating, so we can clear that flag again. If we find a target + via vpath, FILE might change. + (check_dep): Ditto. Fixes Savannah bug #13529. + Patch by Reid Madsen <reid.madsen@tek.com>. + +2009-06-13 Paul Smith <psmith@gnu.org> + + * doc/make.texi (MAKEFILES Variable): Be explicit that files + included by MAKEFILES cannot give default goals. + * read.c (eval): If set_default is not set, pass the no-default-goal + value when we read included makefiles. Fixes Savannah bug #13401. + + * ar.c (ar_name): Ensure that targets with empty parens aren't + considered archive member references: archive members must have a + non-empty "member" string. Fixes Savannah bug #18435. + + * function.c (string_glob): Rely on multi_glob() to determine + whether files exist or not. Remove call to file_exists_p() which + is not always correct. Fixes Savannah bug #21231. + * read.c (multi_glob): Add a new argument EXISTS_ONLY; if true + then only files that really exist will be returned. + * dep.h: Add new argument to multi_glob(). + * rule.c (install_pattern_rule): Ditto. + * read.c (eval): Ditto. + * main.c (main): Ditto. + * implicit.c (pattern_search): Ditto. + * file.c (parse_prereqs): Ditto. + * default.c (set_default_suffixes): Ditto. + +2009-06-09 Paul Smith <psmith@gnu.org> + + * commands.c (set_file_variables): If always_make_flag is set, + always add the prereq to $?. Fixes Savannah bug #17825. + + * remake.c (update_file_1): When rebuilding deps of FILE, also try + to rebuild the deps of all the also_make targets for that file. + Fixes Savannah bug #19108. + + * implicit.c (pattern_search): Undo test for is_target, added by + BorisK on 21 Sep 2004. This goes against step 5c in the "Implicit + Rule Search Algorithm". Fixes Savannah bug #17752. + + * main.c (clean_jobserver): Clear the jobserver_fds options and + set job_slots to the default when we clean up. + (define_makeflags): Return the new MAKEFLAGS value. + (main): Reset MAKEFLAGS in the environment when we re-exec. + Fixes Savannah bug #18124. + +2009-06-08 Paul Smith <psmith@gnu.org> + + * read.c (eval): Collapse continuations post-semicolon on target- + specific variables. Fixes Savannah bug #17521. + +2009-06-07 Paul Smith <psmith@gnu.org> + + * job.c (reap_children): For older systems without waitpid() (are + there any of these left?) run wait(2) inside EINTRLOOP to handle + EINTR errors. Fixes Savannah bug #16401. + + * (various): Debug message cleanup. Fixes Savannah bug #16469. + + * main.c: Fix bsd_signal() typedef. Fixes Savannah bug #16473. + + * file.c (snap_deps): Set SNAPPED_DEPS at the start of snapping, + not the end, to catch second expansion $(eval ...) defining new + target/prereq relationships during snap_deps. + Fixes Savannah bug #24622. + + * read.c (record_files): The second-expansion "f->updating" hack + was not completely correct: if assumed that the target with + commands always had prerequisites; if one didn't then the ordering + was messed up. Fixed for now to use f->updating to decide whether + to preserve the last element in the deps list... but this whole + area of constructing and reversing the deps list is too confusing + and needs to be reworked. Fixes Savannah bug #21198. + +2009-06-06 Paul Smith <psmith@gnu.org> + + * hash.c (hash_insert): Remove useless test for NULL. + Fixes Savannah bug #21823. + + * make.h: Move SET_STACK_SIZE determination to make.h. + * main.c (main): New global variable, STACK_LIMIT, holds the + original stack limit when make was started. + * job.c (start_job_command): Reset the stack limit, if we changed it. + Fixes Savannah bug #22010. + + * remake.c (check_dep): Only set the target's state to not-started + if it's not already running. Found this while testing -j10 builds + of glibc: various targets were being rebuilt multiple times. + Fix from Knut St. Osmundsen; fixes a problem reported in Savannah + bug #15919. + + * read.c (multi_glob): Don't pass GLOB_NOCHECK to glob(3); instead + handle the GLOB_NOMATCH error. This is to work around Sourceware.org + Bugzilla bug 10246. + +2009-06-04 Paul Smith <psmith@gnu.org> + + * read.c (eval): Skip initial whitespace (ffeed, vtab, etc.) + + * maintMakefile: Modify access of config and gnulib Savannah + modules to use GIT instead of CVS. + + * main.c (main): Initialize the LENGTH field in SHELL_VAR. + Fixes Savannah bug #24655. + + * read.c (eval_buffer): Don't dereference reading_file if it's NULL; + this can happen during some invocations of $(eval ...) for example. + Fixes Savannah bug #24588. Patch by Lars Jessen <ljessen@ljessen.dk> + +2009-06-02 Paul Smith <psmith@gnu.org> + + * configure.in: Check for fileno() + * read.c (eval_makefile): If fileno() is available, set CLOSE_ON_EXEC + for the makefile file so invocations of $(shell ...) don't inherit it. + Fixes Savannah bug #24277. + +2009-06-01 Paul Smith <psmith@gnu.org> + + * main.c (main): The previous fix for .DEFAULT_GOAL had issues; + expansion was handled incorrectly. Rework the default goal + handling to save the variable only. Remove default_goal_file and + default_goal_name. + * read.c (eval): Check default_goal_var, not default_goal_name. + * read.c (record_target_var): Don't check default_goal_file here. + +2009-05-31 Paul Smith <psmith@gnu.org> + + * main.c (main): Expand the .DEFAULT_GOAL variable before using + it, and if the multi_glob() returns nothing (say it expanded to + nothing but spaces) then don't crash. Fixes Savannah bug #25697. + + * doc/make.texi (Quick Reference): Add $(if ..), $(or ..), and + $(and ..) to the reference. Fixes Savannah bug #25694. + + * make.1: Be clear that some recipes will be executed even with -n. + * doc/make.texi: Ditto. Fixes Savannah bug #25460. + + * doc/make.texi (Override Directive): Make more clear how + overrides and appends interact. + Elucidates part of Savannah bug #26207. + + * read.c (record_target_var): Don't reset the origin on + target-specific variables; try_variable_definition() will handle + this correctly. Fixes Savannah bug #26207. + + * maintMakefile (do-po-update): Copy PO files into $(top_srcdir). + Fixes Savannah bug #25712. + + * implicit.c (pattern_search): Keep a pointer to the beginning of + the filename and save that instead of the constructed pointer. + Fixes Savannah bug #26593. + Patch by Mark Seaborn <mrs@mythic-beasts.com> + +2009-05-30 Paul Smith <psmith@gnu.org> + + * doc/make.texi (Multi-Line): Add a description of the new abilities + of define/endef. Rename "Sequences" to "Multi-Line" and fix some + "command sequence" vs. "recipe" syntax. + * read.c (do_define): Modify to allow assignment tokens (=, :=, etc.) + after a define, to create variables with those flavors. + +2009-05-25 Paul Smith <psmith@gnu.org> + + Reworked the parser for variable assignments to allow multiple + modifiers, and in any order. Also allows variable and + prerequisites to be modifier names ('export', 'private', etc.) + + * NEWS: Add notes about user-visible changes. + + * read.c (struct vmodifiers): Remember what modifiers were seen. + (parse_var_assignment): New function to parse variable assignments. + (eval): Call the new function. Handle variable assignments earlier. + + * variable.c (parse_variable_definition): Only parse; don't create var. + (assign_variable_definition): Call parse, then create the var. + +2009-05-24 Paul Smith <psmith@gnu.org> + + * doc/make.texi: Fix the ISBN for the GNU make manual. Incorrect + value noticed by Hans Stol <hans.stol@nc3a.nato.int>. + +2009-03-14 Eli Zaretskii <eliz@gnu.org> + + * w32/pathstuff.c (convert_Path_to_windows32): Fix last change. + Fixes Savannah bug #25412. + + * w32/subproc/sub_proc.c <top level>: Update Copyright years. Add + prototype for xmalloc. + (find_file): Accept 3 arguments PATH_VAR, FULL_FNAME, and FULL_LEN + instead of an LPOFSTRUCT pointer. Use xmalloc instead of malloc. + Loop over an array of extensions, instead of duplicating the same + code inline. Use SearchPath followed by CreateFile, instead of + the obsolete OpenFile. Fixes Savannah bug #17277. + (process_begin): Find $(PATH) in `envp', and pass a pointer to it + to `find_file'. Fixes Savannah bug #25662. + +2009-03-07 Eli Zaretskii <eliz@gnu.org> + + * function.c (func_shell): Don't close pipedes[1] if it is -1. + Fixes Savannah bug #20495. + +2009-02-28 Ralf Wildenhues <address@hidden> + + * doc/make.texi (Instead of Execution): Document interaction of + -t with phony targets. + +2009-02-23 Ramon Garcia <ramon.garcia.f@gmail.com> + + Introduce a new keyword "private" which applies to target-specific + variables and prevents their values from being inherited. + + * variable.h (struct variable): Add private_var flag to each variable. + Add a flag to specify which list entry switches to the parent target. + * variable.c (define_variable_in_set): Initialize private_var flag. + (lookup_variable): Skip private variables in parent contexts. + (initialize_file_variables): Set next_is_parent appropriately. + (print_variable): Show the private_var flag. + * read.c (eval): Recognize the private keyword. + (record_target_var): Set private_var. + * doc/make.texi (Suppressing Inheritance): Add documentation. + +2008-10-26 Paul Smith <psmith@gnu.org> + + * configure.in: Check for strndup(). + * misc.c (xstrndup): Rename savestring to xstrndup. Use strndup + if it's available. + * make.h: Rename savestring to xstrndup. + * commands.c (chop_commands): Ditto. + * function.c (func_foreach): Ditto. + * read.c (eval, record_files): Ditto. + * variable.c (define_variable_in_set): Ditto. + 2008-09-30 Eli Zaretskii <eliz@gnu.org> * build_w32.bat (GCCBuild): Use "-gdwarf-2 -g3" instead of @@ -815,7 +1654,7 @@ 2005-12-12 Paul D. Smith <psmith@gnu.org> * make.1: Fix some display errors and document all existing options. - Patch provided by Mike Frysinger <vapier@gentoo.org>. + Patch by Mike Frysinger <vapier@gentoo.org>. 2005-12-11 Paul D. Smith <psmith@gnu.org> @@ -3162,8 +4001,8 @@ See ChangeLog.2, available in the CVS repository at: for earlier changes. -Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free +Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/ChangeLog.1 b/src/kmk/ChangeLog.1 index 5fa10f5..793d8e5 100644 --- a/src/kmk/ChangeLog.1 +++ b/src/kmk/ChangeLog.1 @@ -4982,8 +4982,8 @@ Fri Jul 15 21:01:44 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007 Free Software Foundation, -Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009 Free +Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/Makefile.DOS.template b/src/kmk/Makefile.DOS.template index 97b78a6..a42e588 100644 --- a/src/kmk/Makefile.DOS.template +++ b/src/kmk/Makefile.DOS.template @@ -2,7 +2,7 @@ # Makefile.in generated automatically by automake 1.2 from Makefile.am # # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, -# 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +# 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under @@ -85,13 +85,13 @@ make_LDADD = glob/libglob.a man_MANS = make.1 -INCLUDES = -I$(srcdir)/glob -DLIBDIR=\"c:/djgpp/lib\" -DINCLUDEDIR=\"c:/djgpp/include\" -DLOCALEDIR=\"$(localedir)\" +INCLUDES = -I$(srcdir)/glob -DLIBDIR=\"$(prefix)$(libdir)\" -DINCLUDEDIR=\"$(prefix)$(includedir)\" -DLOCALEDIR=\"$(prefix)$(localedir)\" BUILT_SOURCES = README build.sh-in EXTRA_DIST = $(BUILT_SOURCES) $(man_MANS) README.customs remote-cstms.c make-stds.texi texinfo.tex SCOPTIONS SMakefile Makefile.ami README.Amiga config.ami amiga.c amiga.h NMakefile README.DOS configh.dos configure.bat makefile.com README.W32 build_w32.bat config.h-W32 subproc.bat make.lnk config.h-vms makefile.vms readme.vms vmsdir.h vmsfunctions.c vmsify.c -SUBDIRS = glob +SUBDIRS = glob doc mkinstalldirs = ${exec_prefix}/bin/gmkdir -p CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = build.sh @@ -115,16 +115,13 @@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ TEXI2DVI = texi2dvi TEXINFO_TEX = $(srcdir)/config/texinfo.tex -INFO_DEPS = make.info -DVIS = make.dvi +INFO_DEPS = doc/make.info +DVIS = doc/make.dvi TEXINFOS = doc/make.texi noinst_TEXINFOS = doc/fdl.texi doc/make-stds.texi man1dir = $(mandir)/man1 MANS = $(man_MANS) -TEXI2HTML = texi2html -TEXI2HTML_FLAGS = -split_chapter - NROFF = nroff DIST_COMMON = README ABOUT-NLS AUTHORS COPYING ChangeLog INSTALL Makefile.am Makefile.in NEWS acconfig.h aclocal.m4 alloca.c build.sh-in config.h-in configure configure.in getloadavg.c @@ -191,8 +188,10 @@ make$(EXEEXT): $(make_OBJECTS) $(make_DEPENDENCIES) # Documentation -make.info: doc/make.texi -make.dvi: doc/make.texi +make.info: make.texi +make.dvi: make.texi +make.ps: make.dvi make.texi +make.html: make.texi DVIPS = dvips @@ -200,32 +199,33 @@ DVIPS = dvips .texi.info: @command.com /c if exist make.info* del make.info* @command.com /c if exist make.i* del make.i* - $(MAKEINFO) -I$(srcdir)/doc --no-split $< -o ./$@ + $(MAKEINFO) -I$(srcdir) --no-split $< -o ./$@ .texi: @command.com /c if exist make.info* del make.info* @command.com /c if exist make.i* del make.i* - $(MAKEINFO) -I$(srcdir)/doc --no-split $< -o ./$@ + $(MAKEINFO) -I$(srcdir) --no-split $< -o ./$@ .texi.dvi: - TEXINPUTS="$(srcdir)/doc;$$TEXINPUTS" MAKEINFO='$(MAKEINFO) -I $(srcdir)/doc' $(TEXI2DVI) $< + TEXINPUTS="$(srcdir);$$TEXINPUTS" MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $< .dvi.ps: $(DVIPS) $< -o $@ # Other documentation formats -html: make_1.html +html: html-recursive -make_1.html: $(TEXINFOS) $(noinst_TEXINFOS) - $(TEXI2HTML) $(TEXI2HTML_FLAGS) $(srcdir)/doc/make.texi +.texi.html: + @command.com /c if exist make.html* del make.html* + $(MAKEINFO) --html -I$(srcdir) --no-split $< -o ./$@ install-info-am: $(INFO_DEPS) @$(NORMAL_INSTALL) $(mkinstalldirs) $(DESTDIR)$(infodir) - @for file in $(INFO_DEPS); do d=$(srcdir); for ifile in `cd $$d && echo $$file`; do if test -f $$d/$$ifile; then echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; else : ; fi; done; done + @for file in $(INFO_DEPS); do iifile=`echo $$file | sed "s|doc/||"`; d=$(srcdir); for ifile in `cd $$d && echo $$file`; do if test -f $$d/$$ifile; then echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$iifile"; $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$iifile; else : ; fi; done; done @$(POST_INSTALL) - @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then for file in $(INFO_DEPS); do echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file"; install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :; done; else : ; fi + @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then for file in $(INFO_DEPS); do iifile=`echo $$file | sed "s|doc/||"`; echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$iifile"; install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$iifile || :; done; else : ; fi uninstall-info: $(PRE_UNINSTALL) @@ -237,9 +237,12 @@ dist-info: $(INFO_DEPS) for base in $(INFO_DEPS); do d=$(srcdir); for file in `cd $$d && eval echo $$base*`; do test -f $(distdir)/$$file || ln $$d/$$file $(distdir)/$$file 2> /dev/null || cp -p $$d/$$file $(distdir)/$$file; done; done mostlyclean-aminfo: - -rm -f make.aux make.cp make.cps make.dvi make.fn make.fns make.ky \ - make.kys make.ps make.log make.pg make.toc make.tp make.tps \ - make.vr make.vrs make.op make.tr make.cv make.cn + -rm -f $(srcdir)/doc/make.aux $(srcdir)/doc/make.cp $(srcdir)/doc/make.cps $(srcdir)/doc/make.dvi \ + $(srcdir)/doc/make.fn $(srcdir)/doc/make.fns $(srcdir)/doc/make.ky $(srcdir)/doc/make.kys \ + $(srcdir)/doc/make.ps $(srcdir)/doc/make.log $(srcdir)/doc/make.pg $(srcdir)/doc/make.toc \ + $(srcdir)/doc/make.tp $(srcdir)/doc/make.tps $(srcdir)/doc/make.vr $(srcdir)/doc/make.vrs \ + $(srcdir)/doc/make.op $(srcdir)/doc/make.tr $(srcdir)/doc/make.cv $(srcdir)/doc/make.cn \ + $(srcdir)/doc/make.html clean-aminfo: @@ -291,13 +294,10 @@ uninstall-man: # but do a sanity check: if $SUBDIRS will ever have more than # a single directory, yell bloody murder. all-recursive: -ifeq ($(words $(SUBDIRS)), 1) +ifeq ($(findstring glob, $(SUBDIRS)), glob) @command.com /c if not exist glob\\nul md glob - @echo Making all in $(SUBDIRS) - $(MAKE) -C $(SUBDIRS) -f ../Makefile INCLUDES='-I$(srcdir) -I$(srcdir)/glob' DEFS='-I.. -I$(srcdir)' VPATH=$(srcdir)/glob libglob.a -else - @echo FATAL: There is more than one directory in "($(SUBDIRS))" - @$(EXIT_FAIL) + @echo Making all in glob + $(MAKE) -C glob -f ../Makefile INCLUDES='-I$(srcdir) -I$(srcdir)/glob' DEFS='-I.. -I$(srcdir)' VPATH=$(srcdir)/glob libglob.a endif $(SUBDIRS): @@ -310,11 +310,13 @@ libglob.a: $(libglob_a_OBJECTS) mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive check-recursive: -ifeq ($(words $(SUBDIRS)), 1) - @echo Making $(shell echo $@ | sed s/-recursive//) in $(SUBDIRS) - $(MAKE) -C $(SUBDIRS) -f ../Makefile $(shell echo $@ | sed s/-recursive//)-am +ifeq ($(words $(SUBDIRS)), 2) + @echo Making $(shell echo $@ | sed s/-recursive//) in glob + $(MAKE) -C glob -f ../Makefile $(shell echo $@ | sed s/-recursive//)-am + @echo Making $(shell echo $@ | sed s/-recursive//) in doc + $(MAKE) -C doc -f ../Makefile $(shell echo $@ | sed s/-recursive//)-am else - @echo FATAL: There is more than one directory in "($(SUBDIRS))" + @echo FATAL: There is more than two directory in "($(SUBDIRS))" @$(EXIT_FAIL) endif @@ -322,10 +324,10 @@ tags-in-glob: $(libglob_a_SOURCES) etags $(addprefix $(srcdir)/,$^) -o ./glob/TAGS tags-recursive: -ifeq ($(words $(SUBDIRS)), 1) +ifeq ($(words $(SUBDIRS)), 2) $(MAKE) tags-in-glob else - @echo FATAL: There is more than one directory in "($(SUBDIRS))" + @echo FATAL: There is more than two directory in "($(SUBDIRS))" @$(EXIT_FAIL) endif @@ -376,15 +378,44 @@ distdir: $(DISTFILES) $(MAKE) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-info $(MAKE) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook -info: $(INFO_DEPS) info-recursive -dvi: $(DVIS) dvi-recursive +info: info-recursive +info-recursive: +ifeq ($(findstring doc, $(SUBDIRS)), doc) + @command.com /c if not exist doc\\nul md doc + @echo Making all in doc + $(MAKE) -C doc -f ../Makefile VPATH=$(srcdir)/doc make.info +endif + +dvi: dvi-recursive +dvi-recursive: +ifeq ($(findstring doc, $(SUBDIRS)), doc) + @command.com /c if not exist doc\\nul md doc + @echo Making all in doc + $(MAKE) -C doc -f ../Makefile VPATH=$(srcdir)/doc make.dvi +endif + +ps: ps-recursive +ps-recursive: +ifeq ($(findstring doc, $(SUBDIRS)), doc) + @command.com /c if not exist doc\\nul md doc + @echo Making all in doc + $(MAKE) -C doc -f ../Makefile VPATH=$(srcdir)/doc make.ps +endif + +html-recursive: +ifeq ($(findstring doc, $(SUBDIRS)), doc) + @command.com /c if not exist doc\\nul md doc + @echo Making all in doc + $(MAKE) -C doc -f ../Makefile VPATH=$(srcdir)/doc make.html +endif + check: all-am check-recursive check-local @: installcheck: installcheck-recursive all-recursive-am: config.h $(MAKE) all-recursive -all-am: Makefile $(INFO_DEPS) $(PROGRAMS) config.h +all-am: Makefile $(PROGRAMS) config.h info install-exec-am: install-binPROGRAMS diff --git a/src/kmk/Makefile.am b/src/kmk/Makefile.am index a1cd887..e588fb6 100644 --- a/src/kmk/Makefile.am +++ b/src/kmk/Makefile.am @@ -1,7 +1,7 @@ # This is a -*-Makefile-*-, or close enough # # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -# 2007 Free Software Foundation, Inc. +# 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/Makefile.ami b/src/kmk/Makefile.ami index 64e7668..8cc67df 100644 --- a/src/kmk/Makefile.ami +++ b/src/kmk/Makefile.ami @@ -4,7 +4,7 @@ # `build.sh' instead. # # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2007 Free Software Foundation, Inc. +# 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/Makefile.kmk b/src/kmk/Makefile.kmk index b00de69..84c6e9f 100644 --- a/src/kmk/Makefile.kmk +++ b/src/kmk/Makefile.kmk @@ -1,4 +1,4 @@ -# $Id: Makefile.kmk 2548 2011-11-08 21:28:16Z bird $ +# $Id: Makefile.kmk 2667 2012-11-25 19:52:26Z bird $ ## @file # Sub-makefile for kmk / GNU Make. # @@ -130,7 +130,8 @@ kmkmissing_SOURCES.win += \ w32/subproc/sub_proc.c \ w32/subproc/w32err.c \ w32/compat/dirent.c \ - w32/pathstuff.c + w32/pathstuff.c \ + w32/imagecache.c # # kmk @@ -377,6 +378,8 @@ kmk_redirect_TEMPLATE = BIN-KMK kmk_redirect_DEFS = kmk_builtin_redirect=main kmk_redirect_SOURCES = \ kmkbuiltin/redirect.c +kmk_redirect_SOURCES.win = \ + ../lib/startuphacks-win.c kmk_rmdir_TEMPLATE = BIN-KMK kmk_rmdir_DEFS = kmk_builtin_rmdir=main diff --git a/src/kmk/NEWS b/src/kmk/NEWS index 15d3d6e..523c9a7 100644 --- a/src/kmk/NEWS +++ b/src/kmk/NEWS @@ -1,6 +1,6 @@ GNU make NEWS -*-indented-text-*- History of user-visible changes. - 1 April 2006 + 28 July 2010 See the end of this file for copyrights and conditions. @@ -9,17 +9,110 @@ manual, which is contained in this distribution as the file doc/make.texi. See the README file and the GNU make manual for instructions for reporting bugs. -Version 3.81.90 +Version 3.82 + +A complete list of bugs fixed in this version is available here: + +http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=104&set=custom * Compiling GNU make now requires a conforming ISO C 1989 compiler and standard runtime library. +* WARNING: Future backward-incompatibility! + Wildcards are not documented as returning sorted values, but up to and + including this release the results have been sorted and some makefiles are + apparently depending on that. In the next release of GNU make, for + performance reasons, we may remove that sorting. If your makefiles + require sorted results from wildcard expansions, use the $(sort ...) + function to request it explicitly. + +* WARNING: Backward-incompatibility! + The POSIX standard for make was changed in the 2008 version in a + fundamentally incompatible way: make is required to invoke the shell as if + the '-e' flag were provided. Because this would break many makefiles that + have been written to conform to the original text of the standard, the + default behavior of GNU make remains to invoke the shell with simply '-c'. + However, any makefile specifying the .POSIX special target will follow the + new POSIX standard and pass '-e' to the shell. See also .SHELLFLAGS + below. + +* WARNING: Backward-incompatibility! + The '$?' variable now contains all prerequisites that caused the target to + be considered out of date, even if they do not exist (previously only + existing targets were provided in $?). + +* WARNING: Backward-incompatibility! + As a result of parser enhancements, three backward-compatibility issues + exist: first, a prerequisite containing an "=" cannot be escaped with a + backslash any longer. You must create a variable containing an "=" and + use that variable in the prerequisite. Second, variable names can no + longer contain whitespace, unless you put the whitespace in a variable and + use the variable. Third, in previous versions of make it was sometimes + not flagged as an error for explicit and pattern targets to appear in the + same rule. Now this is always reported as an error. + +* WARNING: Backward-incompatibility! + The pattern-specific variables and pattern rules are now applied in the + shortest stem first order instead of the definition order (variables + and rules with the same stem length are still applied in the definition + order). This produces the usually-desired behavior where more specific + patterns are preferred. To detect this feature search for 'shortest-stem' + in the .FEATURES special variable. + +* WARNING: Backward-incompatibility! + The library search behavior has changed to be compatible with the standard + linker behavior. Prior to this version for prerequisites specified using + the -lfoo syntax make first searched for libfoo.so in the current + directory, vpath directories, and system directories. If that didn't yield + a match, make then searched for libfoo.a in these directories. Starting + with this version make searches first for libfoo.so and then for libfoo.a + in each of these directories in order. + +* New command line option: --eval=STRING causes STRING to be evaluated as + makefile syntax (akin to using the $(eval ...) function). The evaluation + is performed after all default rules and variables are defined, but before + any makefiles are read. + * New special variable: .RECIPEPREFIX allows you to reset the recipe introduction character from the default (TAB) to something else. The first character of this variable value is the new recipe introduction - character. If the variable is set to the empty string, TAB is used - again. It can be set and reset at will; rules will be parsed - according to the current value. + character. If the variable is set to the empty string, TAB is used again. + It can be set and reset at will; recipes will use the value active when + they were first parsed. To detect this feature check the value of + $(.RECIPEPREFIX). + +* New special variable: .SHELLFLAGS allows you to change the options passed + to the shell when it invokes recipes. By default the value will be "-c" + (or "-ec" if .POSIX is set). + +* New special target: .ONESHELL instructs make to invoke a single instance + of the shell and provide it with the entire recipe, regardless of how many + lines it contains. As a special feature to allow more straightforward + conversion of makefiles to use .ONESHELL, any recipe line control + characters ('@', '+', or '-') will be removed from the second and + subsequent recipe lines. This happens _only_ if the SHELL value is deemed + to be a standard POSIX-style shell. If not, then no interior line control + characters are removed (as they may be part of the scripting language used + with the alternate SHELL). + +* New variable modifier 'private': prefixing a variable assignment with the + modifier 'private' suppresses inheritance of that variable by + prerequisites. This is most useful for target- and pattern-specific + variables. + +* New make directive: 'undefine' allows you to undefine a variable so that + it appears as if it was never set. Both $(flavor) and $(origin) functions + will return 'undefined' for such a variable. To detect this feature search + for 'undefine' in the .FEATURES special variable. + +* The parser for variable assignments has been enhanced to allow multiple + modifiers ('export', 'override', 'private') on the same line as variables, + including define/endef variables, and in any order. Also, it is possible + to create variables and targets named as these modifiers. + +* The 'define' make directive now allows a variable assignment operator + after the variable name, to allow for simple, conditional, or appending + multi-line variable assignment. Version 3.81 @@ -57,7 +150,6 @@ Version 3.81 of this SysV feature you will need to update them. * WARNING: Backward-incompatibility! - In order to comply with POSIX, the way in which GNU make processes backslash-newline sequences in recipes has changed. If your makefiles use backslash-newline sequences inside of single-quoted strings in @@ -1005,9 +1097,8 @@ Version 3.05 ------------------------------------------------------------------------------- Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. -This file is part of GNU Make. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/kmk/NMakefile.template b/src/kmk/NMakefile.template index 80dda17..35fafbe 100644 --- a/src/kmk/NMakefile.template +++ b/src/kmk/NMakefile.template @@ -4,7 +4,7 @@ # run 'build_w32.bat' instead. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -# 2006, 2007 Free Software Foundation, Inc. +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under @@ -33,10 +33,9 @@ CFLAGS_debug = $(CFLAGS_any) /Od /D DEBUG /D _DEBUG /FR.\WinDebug/ /Fp.\WinDebug CFLAGS_release = $(CFLAGS_any) /O2 /D NDEBUG /FR.\WinRel/ /Fp.\WinRel/make.pch /Fo.\WinRel/ LDFLAGS_debug = w32\subproc\WinDebug\subproc.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:no /PDB:WinDebug/make.pdb /MACHINE:I386 \ - /OUT:WinDebug/make.exe /DEBUG + /INCREMENTAL:no /PDB:WinDebug/make.pdb /OUT:WinDebug/make.exe /DEBUG LDFLAGS_release = w32\subproc\WinRel\subproc.lib /NOLOGO /SUBSYSTEM:console\ - /INCREMENTAL:no /MACHINE:I386 /OUT:WinRel/make.exe + /INCREMENTAL:no /OUT:WinRel/make.exe all: config.h subproc Release Debug diff --git a/src/kmk/README.Amiga b/src/kmk/README.Amiga index d16f3e7..091b8b4 100644 --- a/src/kmk/README.Amiga +++ b/src/kmk/README.Amiga @@ -62,7 +62,7 @@ If you plan to use recursive makes, install make resident: ------------------------------------------------------------------------------- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -2005, 2006, 2007 Free Software Foundation, Inc. +2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/README.DOS.template b/src/kmk/README.DOS.template index ac6a423..794214b 100644 --- a/src/kmk/README.DOS.template +++ b/src/kmk/README.DOS.template @@ -325,7 +325,7 @@ Bug reports: ------------------------------------------------------------------------------- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/README.OS2.template b/src/kmk/README.OS2.template index 69eab57..0da6385 100644 --- a/src/kmk/README.OS2.template +++ b/src/kmk/README.OS2.template @@ -160,7 +160,8 @@ from the make source tree. ------------------------------------------------------------------------------- -Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/README.W32.template b/src/kmk/README.W32.template index 6175dde..c73bcf4 100644 --- a/src/kmk/README.W32.template +++ b/src/kmk/README.W32.template @@ -273,7 +273,7 @@ Bug reports: ------------------------------------------------------------------------------- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007, 2008 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/README.customs b/src/kmk/README.customs index 37198ac..0ad1837 100644 --- a/src/kmk/README.customs +++ b/src/kmk/README.customs @@ -96,8 +96,8 @@ SunOS 4.1.x: ------------------------------------------------------------------------------- -Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free -Software Foundation, Inc. +Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/README.cvs b/src/kmk/README.cvs index 8cd49b6..75d54de 100644 --- a/src/kmk/README.cvs +++ b/src/kmk/README.cvs @@ -1,8 +1,8 @@ -*-text-*- ------------------------------------------------------------------------------- -Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. -This file is part of GNU Make. +Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free +Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -210,6 +210,10 @@ make update make make check +Or, for a debugging version: + +autoreconf -i && ./configure CFLAGS=-g && make update && make && make check + Or, all-in-one: autoreconf -i && ./configure && make update && make && make check diff --git a/src/kmk/README.template b/src/kmk/README.template index 25a2928..c746488 100644 --- a/src/kmk/README.template +++ b/src/kmk/README.template @@ -172,8 +172,8 @@ at the right README! ------------------------------------------------------------------------------- Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/SMakefile.template b/src/kmk/SMakefile.template index c91e015..7e9229e 100644 --- a/src/kmk/SMakefile.template +++ b/src/kmk/SMakefile.template @@ -4,7 +4,7 @@ # run 'build.sh' instead. # # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2007 Free Software Foundation, Inc. +# 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/TODO.private b/src/kmk/TODO.private index 5c224fd..5b43d11 100644 --- a/src/kmk/TODO.private +++ b/src/kmk/TODO.private @@ -65,10 +65,7 @@ The Rest of the List what does that mean? 3) Multi-token pattern rule matching (allow %1/%2.c : %1/obj/%2.o, - etc., or something like that). I have an implementation of this - already, it just needs some refinement... maybe. Additionally I - think it only works for static pattern rules; it might need to be - fixed up to work with normal pattern rules, too. + etc., or something like that). Maybe using regex? 4) Provide a .TARGETS variable, containing the names of the targets defined in the makefile. @@ -128,8 +125,8 @@ The Rest of the List ------------------------------------------------------------------------------- -Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 -Free Software Foundation, Inc. +Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, +2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/acinclude.m4 b/src/kmk/acinclude.m4 index bd35fc5..0e56441 100644 --- a/src/kmk/acinclude.m4 +++ b/src/kmk/acinclude.m4 @@ -1,8 +1,8 @@ dnl acinclude.m4 -- Extra macros needed for GNU make. dnl dnl Automake will incorporate this into its generated aclocal.m4. -dnl Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 -dnl Free Software Foundation, Inc. +dnl Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +dnl 2008, 2009, 2010 Free Software Foundation, Inc. dnl This file is part of GNU Make. dnl dnl GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/alloccache.c b/src/kmk/alloccache.c index 82202c7..267a726 100644 --- a/src/kmk/alloccache.c +++ b/src/kmk/alloccache.c @@ -1,4 +1,4 @@ -/* $Id: alloccache.c 2413 2010-09-11 17:43:04Z bird $ */ +/* $Id: alloccache.c 2633 2012-09-08 23:18:59Z bird $ */ /** @file * alloccache - Fixed sized allocation cache. * @@ -53,18 +53,22 @@ void alloccache_free (struct alloccache *cache, void *item) { +#ifndef CONFIG_WITH_ALLOCCACHE_DEBUG struct alloccache_free_ent *f = (struct alloccache_free_ent *)item; -#if 0 /*ndef NDEBUG*/ +# if 0 /*ndef NDEBUG*/ struct alloccache_free_ent *c; unsigned int i = 0; for (c = cache->free_head; c != NULL; c = c->next, i++) MY_ASSERT_MSG (c != f && i < 0x10000000, ("i=%u total_count=%u\n", i, cache->total_count)); -#endif +# endif f->next = cache->free_head; cache->free_head = f; MAKE_STATS(cache->free_count++;); +#else + free(item); +#endif } /* Default allocator. */ @@ -78,21 +82,25 @@ alloccache_default_grow_alloc(void *ignore, unsigned int size) struct alloccache_free_ent * alloccache_alloc_grow (struct alloccache *cache) { +#ifndef CONFIG_WITH_ALLOCCACHE_DEBUG void *item; unsigned int items = (64*1024 - 32) / cache->size; cache->free_start = cache->grow_alloc (cache->grow_arg, items * cache->size); cache->free_end = cache->free_start + items * cache->size; cache->total_count+= items; -#ifndef NDEBUG /* skip the first item so the heap can detect free(). */ +# ifndef NDEBUG /* skip the first item so the heap can detect free(). */ cache->total_count--; cache->free_start += cache->size; -#endif +# endif item = cache->free_start; cache->free_start += cache->size; /* caller counts */ return (struct alloccache_free_ent *)item; +#else + return (struct alloccache_free_ent *)xmalloc(cache->size); +#endif } /* List of alloc caches, for printing. */ diff --git a/src/kmk/amiga.c b/src/kmk/amiga.c index 9170e54..6e70f65 100644 --- a/src/kmk/amiga.c +++ b/src/kmk/amiga.c @@ -1,6 +1,6 @@ /* Running commands on Amiga Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -2005, 2006, 2007 Free Software Foundation, Inc. +2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/amiga.h b/src/kmk/amiga.h index 26932c7..ee2aa32 100644 --- a/src/kmk/amiga.h +++ b/src/kmk/amiga.h @@ -1,6 +1,6 @@ /* Definitions for amiga specific things Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -2005, 2006, 2007 Free Software Foundation, Inc. +2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/ar.c b/src/kmk/ar.c index bb9c9ed..95dcbbb 100644 --- a/src/kmk/ar.c +++ b/src/kmk/ar.c @@ -1,7 +1,8 @@ /* Interface to `ar' archives for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. + This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -24,8 +25,9 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ #include "dep.h" #include <fnmatch.h> -/* Return nonzero if NAME is an archive-member reference, zero if not. - An archive-member reference is a name like `lib(member)'. +/* Return nonzero if NAME is an archive-member reference, zero if not. An + archive-member reference is a name like `lib(member)' where member is a + non-empty string. If a name like `lib((entry))' is used, a fatal error is signaled at the attempt to use this unsupported feature. */ @@ -39,7 +41,7 @@ ar_name (const char *name) return 0; end = p + strlen (p) - 1; - if (*end != ')') + if (*end != ')' || end == p + 1) return 0; if (p[1] == '(' && end[-1] == ')') @@ -195,9 +197,8 @@ ar_glob_match (int desc UNUSED, const char *mem, int truncated UNUSED, if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0) { /* We have a match. Add it to the chain. */ - struct nameseq *new = xmalloc (state->size); - memset (new, '\0', state->size); - new->name = strcache_add (concat (state->arname, mem, ")")); + struct nameseq *new = xcalloc (state->size); + new->name = strcache_add (concat (4, state->arname, "(", mem, ")")); new->next = state->chain; state->chain = new; ++state->n; @@ -212,7 +213,7 @@ static int glob_pattern_p (const char *pattern, int quote) { const char *p; - int open = 0; + int opened = 0; for (p = pattern; *p != '\0'; ++p) switch (*p) @@ -227,11 +228,11 @@ glob_pattern_p (const char *pattern, int quote) break; case '[': - open = 1; + opened = 1; break; case ']': - if (open) + if (opened) return 1; break; } @@ -248,7 +249,6 @@ ar_glob (const char *arname, const char *member_pattern, unsigned int size) struct ar_glob_state state; struct nameseq *n; const char **names; - char *name; unsigned int i; if (! glob_pattern_p (member_pattern, 1)) @@ -256,12 +256,7 @@ ar_glob (const char *arname, const char *member_pattern, unsigned int size) /* Scan the archive for matches. ar_glob_match will accumulate them in STATE.chain. */ - i = strlen (arname); - name = alloca (i + 2); - memcpy (name, arname, i); - name[i] = '('; - name[i + 1] = '\0'; - state.arname = name; + state.arname = arname; state.pattern = member_pattern; state.size = size; state.chain = 0; @@ -278,7 +273,8 @@ ar_glob (const char *arname, const char *member_pattern, unsigned int size) names[i++] = n->name; /* Sort them alphabetically. */ - qsort (names, i, sizeof (*names), alpha_compare); + /* MSVC erroneously warns without a cast here. */ + qsort ((void *)names, i, sizeof (*names), alpha_compare); /* Put them back into the chain in the sorted order. */ i = 0; diff --git a/src/kmk/arscan.c b/src/kmk/arscan.c index eb3b500..71d38a6 100644 --- a/src/kmk/arscan.c +++ b/src/kmk/arscan.c @@ -1,7 +1,7 @@ /* Library function for scanning an archive file. Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -66,7 +66,7 @@ VMS_get_member_info (struct dsc$descriptor_s *module, unsigned long *rfa) &bufdesc.dsc$w_length, 0); if (! (status & 1)) { - error (NILF, _("lbr$set_module failed to extract module info, status = %d"), + error (NILF, _("lbr$set_module() failed to extract module info, status = %d"), status); lbr$close (&VMS_lib_idx); @@ -81,7 +81,28 @@ VMS_get_member_info (struct dsc$descriptor_s *module, unsigned long *rfa) * but that decc$fix_time() isn't documented to work this way. Let me * know if this causes problems in other VMS environments. */ - val = decc$fix_time (&mhd->mhd$l_datim) + timezone - daylight*3600; + { + /* Modified by M. Gehre at 11-JAN-2008 because old formula is wrong: + * val = decc$fix_time (&mhd->mhd$l_datim) + timezone - daylight*3600; + * a) daylight specifies, if the timezone has daylight saving enabled, not + * if it is active + * b) what we need is the information, if daylight saving was active, if + * the library module was replaced. This information we get using the + * localtime function + */ + + struct tm *tmp; + + /* Conversion from VMS time to C time */ + val = decc$fix_time (&mhd->mhd$l_datim); + + /* + * Conversion from local time (stored in library) to GMT (needed for gmake) + * Note: The tm_gmtoff element is a VMS extension to the ANSI standard. + */ + tmp = localtime (&val); + val -= tmp->tm_gmtoff; + } #endif for (i = 0; i < module->dsc$w_length; i++) @@ -151,11 +172,12 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg) if (! (status & 1)) { - error (NILF, _("lbr$ini_control failed with status = %d"),status); + error (NILF, _("lbr$ini_control() failed with status = %d"), status); return -2; } - libdesc.dsc$a_pointer = archive; + /* there is no such descriptor with "const char *dsc$a_pointer" */ + libdesc.dsc$a_pointer = (char *)archive; libdesc.dsc$w_length = strlen (archive); status = lbr$open (&VMS_lib_idx, &libdesc, 0, 0, 0, 0, 0); @@ -250,6 +272,7 @@ struct ar_hdr char ar_fmag[2]; /* Always contains ARFMAG. */ }; # endif +# define TOCHAR(_m) (_m) #else /* These should allow us to read Windows (VC++) libraries (according to Frank * Libbrecht <frankl@abzx.belgium.hp.com>) @@ -266,6 +289,8 @@ struct ar_hdr # define ar_date Date # define ar_uid UserID # define ar_gid GroupID +/* In Windows the member names have type BYTE so we must cast them. */ +# define TOCHAR(_m) ((char *)(_m)) #endif /* Cray's <ar.h> apparently defines this. */ @@ -608,8 +633,8 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg) } #ifndef M_XENIX - sscanf (member_header.ar_mode, "%o", &eltmode); - eltsize = atol (member_header.ar_size); + sscanf (TOCHAR (member_header.ar_mode), "%o", &eltmode); + eltsize = atol (TOCHAR (member_header.ar_size)); #else /* Xenix. */ eltmode = (unsigned short int) member_header.ar_mode; eltsize = member_header.ar_size; @@ -619,9 +644,9 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg) (*function) (desc, name, ! long_name, member_offset, member_offset + AR_HDR_SIZE, eltsize, #ifndef M_XENIX - atol (member_header.ar_date), - atoi (member_header.ar_uid), - atoi (member_header.ar_gid), + atol (TOCHAR (member_header.ar_date)), + atoi (TOCHAR (member_header.ar_uid)), + atoi (TOCHAR (member_header.ar_gid)), #else /* Xenix. */ member_header.ar_date, member_header.ar_uid, @@ -790,7 +815,7 @@ ar_member_touch (const char *arname, const char *memname) /* Advance member's time to that time */ for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++) ar_hdr.ar_date[ui] = ' '; - sprintf (ar_hdr.ar_date, "%ld", (long int) statbuf.st_mtime); + sprintf (TOCHAR (ar_hdr.ar_date), "%ld", (long int) statbuf.st_mtime); #ifdef AIAMAG ar_hdr.ar_date[strlen(ar_hdr.ar_date)] = ' '; #endif diff --git a/src/kmk/build.template b/src/kmk/build.template index 85d346a..46a7246 100644 --- a/src/kmk/build.template +++ b/src/kmk/build.template @@ -3,7 +3,7 @@ # @configure_input@ # Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/build_w32.bat b/src/kmk/build_w32.bat index 7f4a8a7..de758b0 100644 --- a/src/kmk/build_w32.bat +++ b/src/kmk/build_w32.bat @@ -1,205 +1,6 @@ -<<<<<<< .working
@echo off
rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-rem 2006 Free Software Foundation, Inc.
-rem This file is part of GNU Make.
-
-rem GNU Make is free software; you can redistribute it and/or modify it under the
-rem terms of the GNU General Public License as published by the Free Software
-rem Foundation; either version 2, or (at your option) any later version.
-
-rem GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
-rem WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-rem A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-rem You should have received a copy of the GNU General Public License along with
-rem GNU Make; see the file COPYING. If not, write to the Free Software
-rem Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-if not exist config.h copy config.h.W32 config.h
-cd w32\subproc
-echo "Creating the subproc library"
-%ComSpec% /c build.bat %1
-cd ..\..
-
-if exist link.dbg del link.dbg
-if exist link.rel del link.rel
-echo "Creating GNU Make for Windows 9X/NT/2K/XP"
-if "%1" == "gcc" GoTo GCCBuild
-set make=gnumake
-echo on
-if not exist .\WinDebug\nul mkdir .\WinDebug
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D TIVOLI /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c variable.c
-echo WinDebug\variable.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c rule.c
-echo WinDebug\rule.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c remote-stub.c
-echo WinDebug\remote-stub.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c commands.c
-echo WinDebug\commands.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c file.c
-echo WinDebug\file.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getloadavg.c
-echo WinDebug\getloadavg.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c default.c
-echo WinDebug\default.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c signame.c
-echo WinDebug\signame.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c expand.c
-echo WinDebug\expand.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c dir.c
-echo WinDebug\dir.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c main.c
-echo WinDebug\main.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getopt1.c
-echo WinDebug\getopt1.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c job.c
-echo WinDebug\job.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c read.c
-echo WinDebug\read.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c version.c
-echo WinDebug\version.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getopt.c
-echo WinDebug\getopt.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c arscan.c
-echo WinDebug\arscan.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c hash.c
-echo WinDebug\hash.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c strcache.c
-echo WinDebug\strcache.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c remake.c
-echo WinDebug\remake.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c misc.c
-echo WinDebug\misc.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c ar.c
-echo WinDebug\ar.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c function.c
-echo WinDebug\function.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c vpath.c
-echo WinDebug\vpath.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c implicit.c
-echo WinDebug\implicit.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\w32\compat\dirent.c
-echo WinDebug\dirent.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\glob\glob.c
-echo WinDebug\glob.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\glob\fnmatch.c
-echo WinDebug\fnmatch.obj >>link.dbg
-cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\w32\pathstuff.c
-echo WinDebug\pathstuff.obj >>link.dbg
-echo off
-echo "Linking WinDebug/%make%.exe"
-rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /MACHINE:I386 /OUT:.\WinDebug/%make%.exe .\WinDebug/variable.obj .\WinDebug/rule.obj .\WinDebug/remote-stub.obj .\WinDebug/commands.obj .\WinDebug/file.obj .\WinDebug/getloadavg.obj .\WinDebug/default.obj .\WinDebug/signame.obj .\WinDebug/expand.obj .\WinDebug/dir.obj .\WinDebug/main.obj .\WinDebug/getopt1.obj .\WinDebug/job.obj .\WinDebug/read.obj .\WinDebug/version.obj .\WinDebug/getopt.obj .\WinDebug/arscan.obj .\WinDebug/remake.obj .\WinDebug/hash.obj .\WinDebug/strcache.obj .\WinDebug/misc.obj .\WinDebug/ar.obj .\WinDebug/function.obj .\WinDebug/vpath.obj .\WinDebug/implicit.obj .\WinDebug/dirent.obj .\WinDebug/glob.obj .\WinDebug/fnmatch.obj .\WinDebug/pathstuff.obj
-echo kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib >>link.dbg
-link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /MACHINE:I386 /OUT:.\WinDebug/%make%.exe @link.dbg
-if not exist .\WinDebug/%make%.exe echo "WinDebug build failed"
-if exist .\WinDebug/%make%.exe echo "WinDebug build succeeded!"
-if not exist .\WinRel\nul mkdir .\WinRel
-echo on
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /D TIVOLI /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c variable.c
-echo WinRel\variable.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c rule.c
-echo WinRel\rule.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c remote-stub.c
-echo WinRel\remote-stub.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c commands.c
-echo WinRel\commands.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c file.c
-echo WinRel\file.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getloadavg.c
-echo WinRel\getloadavg.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c default.c
-echo WinRel\default.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c signame.c
-echo WinRel\signame.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c expand.c
-echo WinRel\expand.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c dir.c
-echo WinRel\dir.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c main.c
-echo WinRel\main.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getopt1.c
-echo WinRel\getopt1.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c job.c
-echo WinRel\job.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c read.c
-echo WinRel\read.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c version.c
-echo WinRel\version.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getopt.c
-echo WinRel\getopt.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c arscan.c
-echo WinRel\arscan.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c remake.c
-echo WinRel\remake.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c hash.c
-echo WinRel\hash.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c strcache.c
-echo WinRel\strcache.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c misc.c
-echo WinRel\misc.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c ar.c
-echo WinRel\ar.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c function.c
-echo WinRel\function.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c vpath.c
-echo WinRel\vpath.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c implicit.c
-echo WinRel\implicit.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\w32\compat\dirent.c
-echo WinRel\dirent.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\glob\glob.c
-echo WinRel\glob.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\glob\fnmatch.c
-echo WinRel\fnmatch.obj >>link.rel
-cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\w32\pathstuff.c
-echo WinRel\pathstuff.obj >>link.rel
-echo off
-echo "Linking WinRel/%make%.exe"
-rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /MACHINE:I386 /OUT:.\WinRel/%make%.exe .\WinRel/variable.obj .\WinRel/rule.obj .\WinRel/remote-stub.obj .\WinRel/commands.obj .\WinRel/file.obj .\WinRel/getloadavg.obj .\WinRel/default.obj .\WinRel/signame.obj .\WinRel/expand.obj .\WinRel/dir.obj .\WinRel/main.obj .\WinRel/getopt1.obj .\WinRel/job.obj .\WinRel/read.obj .\WinRel/version.obj .\WinRel/getopt.obj .\WinRel/arscan.obj .\WinRel/remake.obj .\WinRel/misc.obj .\WinRel/hash.obj .\WinRel/strcache.obj .\WinRel/ar.obj .\WinRel/function.obj .\WinRel/vpath.obj .\WinRel/implicit.obj .\WinRel/dirent.obj .\WinRel/glob.obj .\WinRel/fnmatch.obj .\WinRel/pathstuff.obj
-echo kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib >>link.rel
-link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /MACHINE:I386 /OUT:.\WinRel/%make%.exe @link.rel
-if not exist .\WinRel/%make%.exe echo "WinRel build failed"
-if exist .\WinRel/%make%.exe echo "WinRel build succeeded!"
-set make=
-GoTo BuildEnd
-:GCCBuild
-echo on
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c variable.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c rule.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remote-stub.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c commands.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c file.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getloadavg.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c default.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c signame.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c expand.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c dir.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c main.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt1.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c job.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c read.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c version.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c arscan.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remake.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c hash.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c strcache.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c misc.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ar.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c function.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c vpath.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c implicit.c
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/glob.c -o glob.o
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/fnmatch.c -o fnmatch.o
-gcc -mthreads -Wall -gstabs+ -ggdb3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./w32/pathstuff.c -o pathstuff.o
-gcc -mthreads -gstabs+ -ggdb3 -o gnumake.exe variable.o rule.o remote-stub.o commands.o file.o getloadavg.o default.o signame.o expand.o dir.o main.o getopt1.o job.o read.o version.o getopt.o arscan.o remake.o misc.o hash.o strcache.o ar.o function.o vpath.o implicit.o glob.o fnmatch.o pathstuff.o w32_misc.o sub_proc.o w32err.o -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32
-:BuildEnd
-echo on
-=======
-@echo off
-rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-rem 2006, 2007 Free Software Foundation, Inc.
+rem 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
rem This file is part of GNU Make.
rem
rem GNU Make is free software; you can redistribute it and/or modify it under
@@ -293,9 +94,9 @@ cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D echo WinDebug\pathstuff.obj >>link.dbg
echo off
echo "Linking WinDebug/%make%.exe"
-rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /MACHINE:I386 /OUT:.\WinDebug/%make%.exe .\WinDebug/variable.obj .\WinDebug/rule.obj .\WinDebug/remote-stub.obj .\WinDebug/commands.obj .\WinDebug/file.obj .\WinDebug/getloadavg.obj .\WinDebug/default.obj .\WinDebug/signame.obj .\WinDebug/expand.obj .\WinDebug/dir.obj .\WinDebug/main.obj .\WinDebug/getopt1.obj .\WinDebug/job.obj .\WinDebug/read.obj .\WinDebug/version.obj .\WinDebug/getopt.obj .\WinDebug/arscan.obj .\WinDebug/remake.obj .\WinDebug/hash.obj .\WinDebug/strcache.obj .\WinDebug/misc.obj .\WinDebug/ar.obj .\WinDebug/function.obj .\WinDebug/vpath.obj .\WinDebug/implicit.obj .\WinDebug/dirent.obj .\WinDebug/glob.obj .\WinDebug/fnmatch.obj .\WinDebug/pathstuff.obj
+rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /OUT:.\WinDebug/%make%.exe .\WinDebug/variable.obj .\WinDebug/rule.obj .\WinDebug/remote-stub.obj .\WinDebug/commands.obj .\WinDebug/file.obj .\WinDebug/getloadavg.obj .\WinDebug/default.obj .\WinDebug/signame.obj .\WinDebug/expand.obj .\WinDebug/dir.obj .\WinDebug/main.obj .\WinDebug/getopt1.obj .\WinDebug/job.obj .\WinDebug/read.obj .\WinDebug/version.obj .\WinDebug/getopt.obj .\WinDebug/arscan.obj .\WinDebug/remake.obj .\WinDebug/hash.obj .\WinDebug/strcache.obj .\WinDebug/misc.obj .\WinDebug/ar.obj .\WinDebug/function.obj .\WinDebug/vpath.obj .\WinDebug/implicit.obj .\WinDebug/dirent.obj .\WinDebug/glob.obj .\WinDebug/fnmatch.obj .\WinDebug/pathstuff.obj
echo kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib >>link.dbg
-link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /MACHINE:I386 /OUT:.\WinDebug/%make%.exe @link.dbg
+link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /OUT:.\WinDebug/%make%.exe @link.dbg
if not exist .\WinDebug/%make%.exe echo "WinDebug build failed"
if exist .\WinDebug/%make%.exe echo "WinDebug build succeeded!"
if not exist .\WinRel\nul mkdir .\WinRel
@@ -360,9 +161,9 @@ cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WIND echo WinRel\pathstuff.obj >>link.rel
echo off
echo "Linking WinRel/%make%.exe"
-rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /MACHINE:I386 /OUT:.\WinRel/%make%.exe .\WinRel/variable.obj .\WinRel/rule.obj .\WinRel/remote-stub.obj .\WinRel/commands.obj .\WinRel/file.obj .\WinRel/getloadavg.obj .\WinRel/default.obj .\WinRel/signame.obj .\WinRel/expand.obj .\WinRel/dir.obj .\WinRel/main.obj .\WinRel/getopt1.obj .\WinRel/job.obj .\WinRel/read.obj .\WinRel/version.obj .\WinRel/getopt.obj .\WinRel/arscan.obj .\WinRel/remake.obj .\WinRel/misc.obj .\WinRel/hash.obj .\WinRel/strcache.obj .\WinRel/ar.obj .\WinRel/function.obj .\WinRel/vpath.obj .\WinRel/implicit.obj .\WinRel/dirent.obj .\WinRel/glob.obj .\WinRel/fnmatch.obj .\WinRel/pathstuff.obj
+rem link.exe kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /OUT:.\WinRel/%make%.exe .\WinRel/variable.obj .\WinRel/rule.obj .\WinRel/remote-stub.obj .\WinRel/commands.obj .\WinRel/file.obj .\WinRel/getloadavg.obj .\WinRel/default.obj .\WinRel/signame.obj .\WinRel/expand.obj .\WinRel/dir.obj .\WinRel/main.obj .\WinRel/getopt1.obj .\WinRel/job.obj .\WinRel/read.obj .\WinRel/version.obj .\WinRel/getopt.obj .\WinRel/arscan.obj .\WinRel/remake.obj .\WinRel/misc.obj .\WinRel/hash.obj .\WinRel/strcache.obj .\WinRel/ar.obj .\WinRel/function.obj .\WinRel/vpath.obj .\WinRel/implicit.obj .\WinRel/dirent.obj .\WinRel/glob.obj .\WinRel/fnmatch.obj .\WinRel/pathstuff.obj
echo kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib >>link.rel
-link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /MACHINE:I386 /OUT:.\WinRel/%make%.exe @link.rel
+link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /OUT:.\WinRel/%make%.exe @link.rel
if not exist .\WinRel/%make%.exe echo "WinRel build failed"
if exist .\WinRel/%make%.exe echo "WinRel build succeeded!"
set make=
@@ -400,4 +201,3 @@ gcc -mthreads -Wall -gdwarf-2 -g3 -O2 -I. -I./glob -I./w32/include -DWINDOWS32 - gcc -mthreads -gdwarf-2 -g3 -o gnumake.exe variable.o rule.o remote-stub.o commands.o file.o getloadavg.o default.o signame.o expand.o dir.o main.o getopt1.o job.o read.o version.o getopt.o arscan.o remake.o misc.o hash.o strcache.o ar.o function.o vpath.o implicit.o glob.o fnmatch.o pathstuff.o w32_misc.o sub_proc.o w32err.o -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32
:BuildEnd
echo on
->>>>>>> .merge-right.r1992
diff --git a/src/kmk/commands.c b/src/kmk/commands.c index 679557e..bc74e18 100644 --- a/src/kmk/commands.c +++ b/src/kmk/commands.c @@ -1,7 +1,7 @@ /* Command processing for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -42,6 +42,123 @@ int remote_kill (int id, int sig); int getpid (); #endif +#ifndef CONFIG_WITH_STRCACHE2 + +static unsigned long +dep_hash_1 (const void *key) +{ + const struct dep *d = key; + return_STRING_HASH_1 (dep_name (d)); +} + +static unsigned long +dep_hash_2 (const void *key) +{ + const struct dep *d = key; + return_STRING_HASH_2 (dep_name (d)); +} + +static int +dep_hash_cmp (const void *x, const void *y) +{ + const struct dep *dx = x; + const struct dep *dy = y; + return strcmp (dep_name (dx), dep_name (dy)); +} + + +#else /* CONFIG_WITH_STRCACHE2 */ + +/* Exploit the fact that all names are in the string cache. This means equal + names shall have the same storage and there is no need for hashing or + comparing. Use the address as the first hash, avoiding any touching of + the name, and the length as the second. */ + +static unsigned long +dep_hash_1 (const void *key) +{ + const char *name = dep_name ((struct dep const *) key); + assert (strcache2_is_cached (&file_strcache, name)); + return (size_t) name / sizeof(void *); +} + +static unsigned long +dep_hash_2 (const void *key) +{ + const char *name = dep_name ((struct dep const *) key); + return strcache2_get_len (&file_strcache, name); +} + +static int +dep_hash_cmp (const void *x, const void *y) +{ + struct dep *dx = (struct dep *) x; + struct dep *dy = (struct dep *) y; + const char *dxname = dep_name (dx); + const char *dyname = dep_name (dy); + int cmp = dxname == dyname ? 0 : 1; + + /* check preconds: both cached and the cache contains no duplicates. */ + assert (strcache2_is_cached (&file_strcache, dxname)); + assert (strcache2_is_cached (&file_strcache, dyname)); + assert (cmp == 0 || strcmp (dxname, dyname) != 0); + + /* If the names are the same but ignore_mtimes are not equal, one of these + is an order-only prerequisite and one isn't. That means that we should + remove the one that isn't and keep the one that is. */ + + if (!cmp && dx->ignore_mtime != dy->ignore_mtime) + dx->ignore_mtime = dy->ignore_mtime = 0; + + return cmp; +} + +#endif /* CONFIG_WITH_STRCACHE2 */ + +#ifdef CONFIG_WITH_LAZY_DEPS_VARS +/* Create as copy of DEPS without duplicates, similar to what + set_file_variables does. Used by func_deps. */ + +struct dep *create_uniqute_deps_chain (struct dep *deps) +{ + struct dep *d; + struct dep *head = NULL; + struct dep **ppnext= &head; + struct hash_table dep_hash; + void **slot; + + hash_init (&dep_hash, 500, dep_hash_1, dep_hash_2, dep_hash_cmp); + + for (d = deps; d != 0; d = d->next) + { + if (d->need_2nd_expansion) + continue; + + slot = hash_find_slot (&dep_hash, d); + if (HASH_VACANT (*slot)) + { + struct dep *n = alloc_dep(); + *n = *d; + n->next = NULL; + *ppnext = n; + ppnext = &n->next; + hash_insert_at (&dep_hash, n, slot); + } + else + { + /* Upgrade order only if a normal dep exists. + Note! Elected not to upgrade the original, only the sanitized + list, need to check that out later. FIXME TODO */ + struct dep *d2 = (struct dep *)*slot; + if (d->ignore_mtime != d2->ignore_mtime) + d->ignore_mtime = d2->ignore_mtime = 0; + } + } + + return head; +} +#endif /* CONFIG_WITH_LAZY_DEPS_VARS */ + /* Set FILE's automatic variables up. */ void @@ -51,7 +168,7 @@ set_file_variables (struct file *file, int called_early) set_file_variables (struct file *file) #endif { - const struct dep *d; + struct dep *d; const char *at, *percent, *star, *less; #ifdef CONFIG_WITH_STRCACHE2 const char *org_stem = file->stem; @@ -136,7 +253,8 @@ set_file_variables (struct file *file) for (d = file->deps; d != 0; d = d->next) if (!d->ignore_mtime) { - less = dep_name (d); + if (!d->need_2nd_expansion) + less = dep_name (d); break; } @@ -212,27 +330,46 @@ set_file_variables (struct file *file) char *bp; unsigned int len; + struct hash_table dep_hash; + void **slot; + /* Compute first the value for $+, which is supposed to contain duplicate dependencies as they were listed in the makefile. */ plus_len = 0; + bar_len = 0; for (d = file->deps; d != 0; d = d->next) - if (! d->ignore_mtime) + { + if (!d->need_2nd_expansion) + { + if (d->ignore_mtime) +#ifndef CONFIG_WITH_STRCACHE2 + bar_len += strlen (dep_name (d)) + 1; +#else + bar_len += strcache2_get_len (&file_strcache, dep_name (d)) + 1; +#endif + else #ifndef CONFIG_WITH_STRCACHE2 - plus_len += strlen (dep_name (d)) + 1; + plus_len += strlen (dep_name (d)) + 1; #else - plus_len += strcache2_get_len (&file_strcache, dep_name (d)) + 1; + plus_len += strcache2_get_len (&file_strcache, dep_name (d)) + 1; #endif + } + } + + if (bar_len == 0) + bar_len++; if (plus_len == 0) plus_len++; if (plus_len > plus_max) plus_value = xrealloc (plus_value, plus_max = plus_len); + cp = plus_value; qmark_len = plus_len + 1; /* Will be this or less. */ for (d = file->deps; d != 0; d = d->next) - if (! d->ignore_mtime) + if (! d->ignore_mtime && ! d->need_2nd_expansion) { const char *c = dep_name (d); @@ -253,7 +390,7 @@ set_file_variables (struct file *file) memcpy (cp, c, len); cp += len; *cp++ = FILE_LIST_SEPARATOR; - if (! d->changed) + if (! (d->changed || always_make_flag)) qmark_len -= len + 1; /* Don't space in $? for this one. */ } @@ -262,23 +399,6 @@ set_file_variables (struct file *file) cp[cp > plus_value ? -1 : 0] = '\0'; DEFINE_VARIABLE ("+", 1, plus_value); - /* Make sure that no dependencies are repeated. This does not - really matter for the purpose of updating targets, but it - might make some names be listed twice for $^ and $?. */ - - uniquize_deps (file->deps); - - bar_len = 0; - for (d = file->deps; d != 0; d = d->next) - if (d->ignore_mtime) -#ifndef CONFIG_WITH_STRCACHE2 - bar_len += strlen (dep_name (d)) + 1; -#else - bar_len += strcache2_get_len (&file_strcache, dep_name (d)) + 1; -#endif - if (bar_len == 0) - bar_len++; - /* Compute the values for $^, $?, and $|. */ cp = caret_value = plus_value; /* Reuse the buffer; it's big enough. */ @@ -291,12 +411,43 @@ set_file_variables (struct file *file) bar_value = xrealloc (bar_value, bar_max = bar_len); bp = bar_value; + /* Make sure that no dependencies are repeated in $^, $?, and $|. It + would be natural to combine the next two loops but we can't do it + because of a situation where we have two dep entries, the first + is order-only and the second is normal (see below). */ + + hash_init (&dep_hash, 500, dep_hash_1, dep_hash_2, dep_hash_cmp); + + for (d = file->deps; d != 0; d = d->next) + { + if (d->need_2nd_expansion) + continue; + + slot = hash_find_slot (&dep_hash, d); + if (HASH_VACANT (*slot)) + hash_insert_at (&dep_hash, d, slot); + else + { + /* Check if the two prerequisites have different ignore_mtime. + If so then we need to "upgrade" one that is order-only. */ + + struct dep* hd = (struct dep*) *slot; + + if (d->ignore_mtime != hd->ignore_mtime) + d->ignore_mtime = hd->ignore_mtime = 0; + } + } + for (d = file->deps; d != 0; d = d->next) { - const char *c = dep_name (d); + const char *c; + if (d->need_2nd_expansion || hash_find_item (&dep_hash, d) != d) + continue; + + c = dep_name (d); #ifndef NO_ARCHIVES - if (ar_name (c)) + if (ar_name (c)) { c = strchr (c, '(') + 1; len = strlen (c) - 1; @@ -311,16 +462,16 @@ set_file_variables (struct file *file) if (d->ignore_mtime) { - memcpy (bp, c, len); + memcpy (bp, c, len); bp += len; *bp++ = FILE_LIST_SEPARATOR; } else - { + { memcpy (cp, c, len); cp += len; *cp++ = FILE_LIST_SEPARATOR; - if (d->changed) + if (d->changed || always_make_flag) { memcpy (qp, c, len); qp += len; @@ -329,6 +480,8 @@ set_file_variables (struct file *file) } } + hash_free (&dep_hash, 0); + /* Kill the last spaces and define the variables. */ cp[cp > caret_value ? -1 : 0] = '\0'; @@ -340,19 +493,6 @@ set_file_variables (struct file *file) bp[bp > bar_value ? -1 : 0] = '\0'; DEFINE_VARIABLE ("|", 1, bar_value); } -#ifdef CONFIG_WITH_LAZY_DEPS_VARS - else - { - /* Make a copy of the current dependency chain for later use in - potential $(dep-pluss $@) calls. Then drop duplicate deps. */ - - /* assert (file->org_deps == NULL); - FIXME? */ - free_dep_chain (file->org_deps); - file->org_deps = copy_dep_chain (file->deps); - - uniquize_deps (file->deps); - } -#endif /* CONFIG_WITH_LAZY_DEPS_VARS */ #undef DEFINE_VARIABLE } @@ -362,7 +502,6 @@ set_file_variables (struct file *file) void chop_commands (struct commands *cmds) { - const char *p; unsigned int nlines, idx; char **lines; @@ -372,50 +511,68 @@ chop_commands (struct commands *cmds) if (!cmds || cmds->command_lines != 0) return; - /* Chop CMDS->commands up into lines in CMDS->command_lines. - Also set the corresponding CMDS->lines_flags elements, - and the CMDS->any_recurse flag. */ + /* Chop CMDS->commands up into lines in CMDS->command_lines. */ - nlines = 5; - lines = xmalloc (5 * sizeof (char *)); - idx = 0; - p = cmds->commands; - while (*p != '\0') + if (one_shell) { - const char *end = p; - find_end:; - end = strchr (end, '\n'); - if (end == 0) - end = p + strlen (p); - else if (end > p && end[-1] == '\\') + int l = strlen (cmds->commands); + + nlines = 1; + lines = xmalloc (nlines * sizeof (char *)); + lines[0] = xstrdup (cmds->commands); + + /* Strip the trailing newline. */ + if (l > 0 && lines[0][l-1] == '\n') + lines[0][l-1] = '\0'; + } + else + { + const char *p; + + nlines = 5; + lines = xmalloc (nlines * sizeof (char *)); + idx = 0; + p = cmds->commands; + while (*p != '\0') { - int backslash = 1; - const char *b; - for (b = end - 2; b >= p && *b == '\\'; --b) - backslash = !backslash; - if (backslash) + const char *end = p; + find_end:; + end = strchr (end, '\n'); + if (end == 0) + end = p + strlen (p); + else if (end > p && end[-1] == '\\') + { + int backslash = 1; + const char *b; + for (b = end - 2; b >= p && *b == '\\'; --b) + backslash = !backslash; + if (backslash) + { + ++end; + goto find_end; + } + } + + if (idx == nlines) { - ++end; - goto find_end; + nlines += 2; + lines = xrealloc (lines, nlines * sizeof (char *)); } + lines[idx++] = xstrndup (p, end - p); + p = end; + if (*p != '\0') + ++p; } - if (idx == nlines) + if (idx != nlines) { - nlines += 2; + nlines = idx; lines = xrealloc (lines, nlines * sizeof (char *)); } - lines[idx++] = savestring (p, end - p); - p = end; - if (*p != '\0') - ++p; } - if (idx != nlines) - { - nlines = idx; - lines = xrealloc (lines, nlines * sizeof (char *)); - } + /* Finally, set the corresponding CMDS->lines_flags elements and the + CMDS->any_recurse flag. */ cmds->ncommand_lines = nlines; cmds->command_lines = lines; @@ -426,18 +583,14 @@ chop_commands (struct commands *cmds) #else cmds->lines_flags = xmalloc (nlines * sizeof (cmds->lines_flags[0])); #endif + for (idx = 0; idx < nlines; ++idx) { int flags = 0; + const char *p = lines[idx]; - for (p = lines[idx]; -#ifndef CONFIG_WITH_COMMANDS_FUNC - isblank ((unsigned char)*p) || *p == '-' || *p == '@' || *p == '+'; -#else - isblank ((unsigned char)*p) || *p == '-' || *p == '@' || *p == '+' || *p == '%'; -#endif - ++p) - switch (*p) + while (isblank (*p) || *p == '-' || *p == '@' || *p == '+' IF_WITH_COMMANDS_FUNC(|| *p == '%')) + switch (*(p++)) { case '+': flags |= COMMANDS_RECURSE; diff --git a/src/kmk/commands.h b/src/kmk/commands.h index 1e5f6ee..df4ab4c 100644 --- a/src/kmk/commands.h +++ b/src/kmk/commands.h @@ -1,7 +1,7 @@ /* Definition of data structures describing shell commands for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -61,3 +61,7 @@ void set_file_variables (struct file *file, int called_early); #else void set_file_variables (struct file *file); #endif +#ifdef CONFIG_WITH_LAZY_DEPS_VARS +struct dep *create_uniqute_deps_chain (struct dep *deps); +#endif + diff --git a/src/kmk/config.ami.template b/src/kmk/config.ami.template index 1048067..3a5a29e 100644 --- a/src/kmk/config.ami.template +++ b/src/kmk/config.ami.template @@ -1,6 +1,6 @@ /* config.h -- hand-massaged for Amiga -*-C-*- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -2005, 2006, 2007 Free Software Foundation, Inc. +2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/config.h-vms.template b/src/kmk/config.h-vms.template index 8543758..337e234 100644 --- a/src/kmk/config.h-vms.template +++ b/src/kmk/config.h-vms.template @@ -1,7 +1,7 @@ /* config.h-vms. Generated by hand by Klaus Kämpf <kkaempf@rmi.de> -*-C-*- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -76,6 +76,9 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ /* Define to 1 if you don't have vprintf but do have _doprnt. */ /* #undef HAVE_DOPRNT */ +/* Define to 1 if you have the fdopen function. */ +#define HAVE_FDOPEN 1 + /* Define to 1 if your system has a working fnmatch function. */ /* #undef HAVE_FNMATCH */ @@ -289,7 +292,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ /* #undef HAVE_SOCKET */ /* Define to 1 if you have the strcasecmp function. */ -/* #undef HAVE_STRCASECMP */ +#define HAVE_STRCASECMP 1 /* Define to 1 if you have the strcmpi function. */ /* #undef HAVE_STRCMPI */ diff --git a/src/kmk/config.h.W32.template b/src/kmk/config.h.W32.template index 533ec82..03d50fc 100644 --- a/src/kmk/config.h.W32.template +++ b/src/kmk/config.h.W32.template @@ -1,7 +1,7 @@ /* config.h.W32 -- hand-massaged config.h file for Windows builds -*-C-*- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -24,6 +24,8 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ # pragma warning(disable:4127) /* conditional expression is constant */ # pragma warning(disable:4131) /* uses old-style declarator */ # pragma warning(disable:4702) /* unreachable code */ +# define _CRT_SECURE_NO_WARNINGS /* function or variable may be unsafe */ +# define _CRT_NONSTDC_NO_WARNINGS /* functions w/o a leading underscore */ #endif /* Define to 1 if the `closedir' function returns void instead of `int'. */ @@ -227,10 +229,19 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ /* #undef HAVE_STRCASECMP */ /* Define to 1 if you have the `strcmpi' function. */ -#define HAVE_STRCMPI 1 +/* #undef HAVE_STRCMPI */ /* Define to 1 if you have the `stricmp' function. */ -/* #undef HAVE_STRICMP */ +#define HAVE_STRICMP 1 + +/* Define to 1 if you have the `strncasecmp' function. */ +/* #undef HAVE_STRNCASECMP */ + +/* Define to 1 if you have the `strncmpi' function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the `strnicmp' function. */ +#define HAVE_STRNICMP 1 /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 @@ -426,8 +437,12 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ /* Define to `int' if <sys/types.h> does not define. */ /* GCC 4.x reportedly defines pid_t. */ #ifndef _PID_T_ +#ifdef _WIN64 +#define pid_t __int64 +#else #define pid_t int #endif +#endif /* Define to `int' if <sys/types.h> doesn't define. */ #define uid_t int diff --git a/src/kmk/config.h.darwin b/src/kmk/config.h.darwin index b817fec..2ef96a9 100644 --- a/src/kmk/config.h.darwin +++ b/src/kmk/config.h.darwin @@ -40,6 +40,7 @@ /* Define to 1 if you have the `bsd_signal' function. */ #define HAVE_BSD_SIGNAL 1 +#define HAVE_DECL_BSD_SIGNAL 1 /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ @@ -78,6 +79,9 @@ /* Define to 1 if you have the `fdopen' function. */ #define HAVE_FDOPEN 1 +/* Define to 1 if you have the `fileno' function. */ +#define HAVE_FILENO 1 + /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 @@ -201,6 +205,15 @@ /* Define to 1 if you have the `strcmpi' function. */ /* #undef HAVE_STRCMPI */ +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the `strncmpi' function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the `strncmp' function. */ +/* #undef HAVE_STRNICMP */ + /* Define to 1 if you have the `strcoll' function and it is properly defined. */ #define HAVE_STRCOLL 1 @@ -208,6 +221,9 @@ /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 +/* Define to 1 if you have the `strndup' function. */ +/* #undef HAVE_STRNDUP */ + /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 @@ -314,13 +330,13 @@ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU make 3.81.90" +#define PACKAGE_STRING "GNU make 3.82" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" /* Define to the version of this package. */ -#define PACKAGE_VERSION "3.81.90" +#define PACKAGE_VERSION "3.82" /* Define to the character that separates directories in PATH. */ #define PATH_SEPARATOR_CHAR ':' @@ -373,7 +389,7 @@ /* #undef UMAX4_3 */ /* Version number of package */ -#define VERSION "3.81.90" +#define VERSION "3.82" /* Use platform specific coding */ /* #undef WINDOWS32 */ diff --git a/src/kmk/config.h.freebsd b/src/kmk/config.h.freebsd index d2e53b4..8fa99cc 100644 --- a/src/kmk/config.h.freebsd +++ b/src/kmk/config.h.freebsd @@ -318,13 +318,13 @@ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU make 3.81.90" +#define PACKAGE_STRING "GNU make 3.82" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" /* Define to the version of this package. */ -#define PACKAGE_VERSION "3.81.90" +#define PACKAGE_VERSION "3.82" /* Define to the character that separates directories in PATH. */ #define PATH_SEPARATOR_CHAR ':' @@ -377,7 +377,7 @@ /* #undef UMAX4_3 */ /* Version number of package */ -#define VERSION "3.81.90" +#define VERSION "3.82" /* Use platform specific coding */ /* #undef WINDOWS32 */ diff --git a/src/kmk/config.h.haiku b/src/kmk/config.h.haiku index 4ea9ae8..3580374 100644 --- a/src/kmk/config.h.haiku +++ b/src/kmk/config.h.haiku @@ -38,14 +38,15 @@ /* Define to 1 if you have the `atexit' function. */ #define HAVE_ATEXIT 1 -/* Define to 1 if you have the `bsd_signal' function. */ -/* #undef HAVE_BSD_SIGNAL */ - /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ /* Define to 1 if you have the clock_gettime function. */ -/* #undef HAVE_CLOCK_GETTIME */ +#define HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the declaration of `bsd_signal', and to 0 if you + don't. */ +#define HAVE_DECL_BSD_SIGNAL 0 /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ @@ -78,6 +79,9 @@ /* Define to 1 if you have the `fdopen' function. */ #define HAVE_FDOPEN 1 +/* Define to 1 if you have the `fileno' function. */ +#define HAVE_FILENO 1 + /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 @@ -220,6 +224,18 @@ /* Define to 1 if you have the <string.h> header file. */ #define HAVE_STRING_H 1 +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the `strncmpi' function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the `strndup' function. */ +#define HAVE_STRNDUP 1 + +/* Define to 1 if you have the `strnicmp' function. */ +/* #undef HAVE_STRNICMP */ + /* Define to 1 if you have the `strsignal' function. */ #define HAVE_STRSIGNAL 1 @@ -314,7 +330,7 @@ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU make 3.81.90" +#define PACKAGE_STRING "GNU make 3.82" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" @@ -323,7 +339,7 @@ #define PACKAGE_URL "http://www.gnu.org/software/make/" /* Define to the version of this package. */ -#define PACKAGE_VERSION "3.81.90" +#define PACKAGE_VERSION "3.82" /* Define to the character that separates directories in PATH. */ #define PATH_SEPARATOR_CHAR ':' @@ -390,7 +406,7 @@ /* Version number of package */ -#define VERSION "3.81.90" +#define VERSION "3.82" /* Use platform specific coding */ /* #undef WINDOWS32 */ @@ -398,6 +414,11 @@ /* Define if using the dmalloc debugging malloc package */ /* #undef WITH_DMALLOC */ +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ diff --git a/src/kmk/config.h.linux b/src/kmk/config.h.linux index 73583e6..47de647 100644 --- a/src/kmk/config.h.linux +++ b/src/kmk/config.h.linux @@ -38,15 +38,16 @@ /* Define to 1 if you have the `atexit' function. */ #define HAVE_ATEXIT 1 -/* Define to 1 if you have the `bsd_signal' function. */ -#define HAVE_BSD_SIGNAL 1 - /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ /* Define to 1 if you have the clock_gettime function. */ #define HAVE_CLOCK_GETTIME 1 +/* Define to 1 if you have the declaration of `bsd_signal', and to 0 if you + don't. */ +#define HAVE_DECL_BSD_SIGNAL 1 + /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ #define HAVE_DECL_SYS_SIGLIST 1 @@ -78,6 +79,9 @@ /* Define to 1 if you have the `fdopen' function. */ #define HAVE_FDOPEN 1 +/* Define to 1 if you have the `fileno' function. */ +#define HAVE_FILENO 1 + /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 @@ -220,10 +224,22 @@ /* Define to 1 if you have the <string.h> header file. */ #define HAVE_STRING_H 1 +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the `strncmpi' function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the `strndup' function. */ +#define HAVE_STRNDUP 1 + +/* Define to 1 if you have the `strnicmp' function. */ +/* #undef HAVE_STRNICMP */ + /* Define to 1 if you have the `strsignal' function. */ #define HAVE_STRSIGNAL 1 -/* Define to 1 if `n_un.n_name' is member of `struct nlist'. */ +/* Define to 1 if `n_un.n_name' is a member of `struct nlist'. */ /* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */ /* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'. @@ -314,13 +330,16 @@ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU make 3.81.90" +#define PACKAGE_STRING "GNU make 3.82" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" +/* Define to the home page for this package. */ +#define PACKAGE_URL "http://kbuild.org/" + /* Define to the version of this package. */ -#define PACKAGE_VERSION "3.81.90" +#define PACKAGE_VERSION "3.82" /* Define to the character that separates directories in PATH. */ #define PATH_SEPARATOR_CHAR ':' @@ -372,8 +391,31 @@ <sys/cpustats.h>. */ /* #undef UMAX4_3 */ + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + + /* Version number of package */ -#define VERSION "3.81.90" +#define VERSION "3.82" /* Use platform specific coding */ /* #undef WINDOWS32 */ @@ -416,6 +458,9 @@ /* Define to `int' if <sys/types.h> does not define. */ /* #undef pid_t */ +/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ + /* Define to `int' if <sys/types.h> doesn't define. */ /* #undef uid_t */ diff --git a/src/kmk/config.h.os2 b/src/kmk/config.h.os2 index 55cbb7d..32b919c 100644 --- a/src/kmk/config.h.os2 +++ b/src/kmk/config.h.os2 @@ -42,12 +42,13 @@ /* Define to 1 if you have the `atexit' function. */ #define HAVE_ATEXIT 1 -/* Define to 1 if you have the `bsd_signal' function. */ -#define HAVE_BSD_SIGNAL 1 - /* Use case insensitive file names */ /* #undef HAVE_CASE_INSENSITIVE_FS */ +/* Define to 1 if you have the declaration of `bsd_signal', and to 0 if you + don't. */ +#define HAVE_DECL_BSD_SIGNAL 1 + /* Define if you have the clock_gettime function. */ /* #undef HAVE_CLOCK_GETTIME */ @@ -237,9 +238,21 @@ /* Define to 1 if you have the <string.h> header file. */ #define HAVE_STRING_H 1 +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the `strncmpi' function. */ +/* #undef HAVE_STRNCMPI */ + /* Define to 1 if you have the `strsignal' function. */ #define HAVE_STRSIGNAL 1 +/* Define to 1 if you have the `strndup' function. */ +#define HAVE_STRNDUP 1 + +/* Define to 1 if you have the `strnicmp' function. */ +#define HAVE_STRNICMP 1 + /* Define to 1 if `n_un.n_name' is member of `struct nlist'. */ /* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */ @@ -331,13 +344,13 @@ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU make 3.81" +#define PACKAGE_STRING "GNU make 3.82" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" /* Define to the version of this package. */ -#define PACKAGE_VERSION "3.81" +#define PACKAGE_VERSION "3.82" /* Define to 1 if the C compiler supports function prototypes. */ #define PROTOTYPES 1 diff --git a/src/kmk/config.h.solaris b/src/kmk/config.h.solaris index 37b42a7..aebf10a 100644 --- a/src/kmk/config.h.solaris +++ b/src/kmk/config.h.solaris @@ -314,13 +314,13 @@ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU make 3.81.90" +#define PACKAGE_STRING "GNU make 3.82" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" /* Define to the version of this package. */ -#define PACKAGE_VERSION "3.81.90" +#define PACKAGE_VERSION "3.82" /* Define to the character that separates directories in PATH. */ #define PATH_SEPARATOR_CHAR ':' @@ -373,7 +373,7 @@ /* #undef UMAX4_3 */ /* Version number of package */ -#define VERSION "3.81.90" +#define VERSION "3.82" /* Use platform specific coding */ /* #undef WINDOWS32 */ diff --git a/src/kmk/config.h.win b/src/kmk/config.h.win index d1fd7b3..394dcc8 100644 --- a/src/kmk/config.h.win +++ b/src/kmk/config.h.win @@ -343,13 +343,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #define PACKAGE_NAME "GNU make" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU make 3.81.90" +#define PACKAGE_STRING "GNU make 3.82" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "make" /* Define to the version of this package. */ -#define PACKAGE_VERSION "3.81.90" +#define PACKAGE_VERSION "3.82" /* Define to 1 if the C compiler supports function prototypes. */ #define PROTOTYPES 1 @@ -399,7 +399,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ /* #undef UMAX4_3 */ /* Version number of package */ -#define VERSION "3.81.90" +#define VERSION "3.82" /* Define if using the dmalloc debugging malloc package */ /* #undef WITH_DMALLOC */ @@ -522,10 +522,16 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #undef BATCH_MODE_ONLY_SHELL #endif -/* bird hacks */ +/* bird hacks - similar in mscfakes.h */ #include <sys/stat.h> -extern int my_stat(const char *, struct stat *); -#define stat(_path, _st) my_stat(_path, _st) +#include <io.h> +#include <direct.h> +#ifndef STAT_REDEFINED_ALREADY +# define STAT_REDEFINED_ALREADY +# undef stat +# define stat(_path, _st) bird_w32_stat(_path, _st) +extern int bird_w32_stat(const char *, struct stat *); +#endif /* cygwin sucks to much in one end or the other. */ #define BATCH_MODE_ONLY_SHELL diff --git a/src/kmk/config/ChangeLog b/src/kmk/config/ChangeLog index 0d884b4..aed4694 100644 --- a/src/kmk/config/ChangeLog +++ b/src/kmk/config/ChangeLog @@ -28,7 +28,8 @@ * Makefile.am: New file. -Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software +Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/config/Makefile.am b/src/kmk/config/Makefile.am index bf0567d..203a5ee 100644 --- a/src/kmk/config/Makefile.am +++ b/src/kmk/config/Makefile.am @@ -1,6 +1,6 @@ # -*-Makefile-*-, or close enough -# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, -# Inc. +# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free +# Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/config/dospaths.m4 b/src/kmk/config/dospaths.m4 index cf2bd3b..da544f8 100644 --- a/src/kmk/config/dospaths.m4 +++ b/src/kmk/config/dospaths.m4 @@ -2,7 +2,7 @@ # By Paul Smith <psmith@gnu.org>. Based on dos.m4 by Jim Meyering. # # Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/configh.dos.template b/src/kmk/configh.dos.template index b2add06..99500fd 100644 --- a/src/kmk/configh.dos.template +++ b/src/kmk/configh.dos.template @@ -1,7 +1,7 @@ /* configh.dos -- hand-massaged config.h file for MS-DOS builds -*-C-*- Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, -2004, 2005, 2006, 2007 Free Software Foundation, Inc. +2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -16,12 +16,16 @@ A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +/* Include this header to make __DJGPP_MINOR__ available because DJGPP ports + of GCC 4.3.0 and later no longer do it automatically. */ +#include <sys/version.h> + /* Many things are defined already by a system header. */ #include <sys/config.h> #if __DJGPP__ > 2 || __DJGPP_MINOR__ > 1 -/* Define to 1 if `sys_siglist' is declared by <signal.h>. */ +/* Define to 1 if `sys_siglist' is declared by <signal.h> or <unistd.h>. */ # define SYS_SIGLIST_DECLARED 1 /* Define to 1 if the C library defines the variable `_sys_siglist'. */ @@ -107,9 +111,6 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ /* Define to 1 if the C compiler supports function prototypes. */ #define PROTOTYPES 1 -/* Define to 1 if `sys_siglist' is declared by <signal.h> or <unistd.h>. */ -#define SYS_SIGLIST_DECLARED 1 - /* Version number of package */ #define VERSION "%VERSION%" diff --git a/src/kmk/configure.bat b/src/kmk/configure.bat index 9163297..c7b4591 100644 --- a/src/kmk/configure.bat +++ b/src/kmk/configure.bat @@ -1,70 +1,6 @@ -<<<<<<< .working
@echo off
rem Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-rem 2004, 2005, 2006 Free Software Foundation, Inc.
-rem This file is part of GNU Make.
-
-rem GNU Make is free software; you can redistribute it and/or modify it under
-rem the terms of the GNU General Public License as published by the Free
-rem Software Foundation; either version 2, or (at your option) any later
-rem version.
-
-rem GNU Make is distributed in the hope that it will be useful, but WITHOUT
-rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-rem more details.
-
-rem You should have received a copy of the GNU General Public License along
-rem with GNU Make; see the file COPYING. If not, write to the Free Software
-rem Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-echo Configuring MAKE for DJGPP
-
-rem The SmallEnv trick protects against too small environment block,
-rem in which case the values will be truncated and the whole thing
-rem goes awry. COMMAND.COM will say "Out of environment space", but
-rem many people don't care, so we force them to care by refusing to go.
-
-rem Where is the srcdir?
-set XSRC=.
-if not "%XSRC%"=="." goto SmallEnv
-if "%1%"=="" goto SrcDone
-set XSRC=%1
-if not "%XSRC%"=="%1" goto SmallEnv
-
-:SrcDone
-
-update %XSRC%/configh.dos ./config.h
-
-rem Do they have Make?
-redir -o junk.$$$ -eo make -n -f NUL
-rem REDIR will return 1 if it cannot run Make.
-rem If it can run Make, it will usually return 2,
-rem but 0 is also OK with us.
-if errorlevel 2 goto MakeOk
-if not errorlevel 1 goto MakeOk
-if exist junk.$$$ del junk.$$$
-echo No Make program found--use DOSBUILD.BAT to build Make.
-goto End
-
-rem They do have Make. Generate the Makefile.
-
-:MakeOk
-del junk.$$$
-update %XSRC%/Makefile.DOS ./Makefile
-echo Done.
-if not "%XSRC%"=="." echo Invoke Make thus: "make srcdir=%XSRC%"
-goto End
-
-:SmallEnv
-echo Your environment is too small. Please enlarge it and run me again.
-
-:End
-set XRSC=
-=======
-@echo off
-rem Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-rem 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+rem 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
rem This file is part of GNU Make.
rem
rem GNU Make is free software; you can redistribute it and/or modify it under
@@ -123,4 +59,3 @@ echo Your environment is too small. Please enlarge it and run me again. :End
set XRSC=
->>>>>>> .merge-right.r1992
diff --git a/src/kmk/configure.in b/src/kmk/configure.in index e976bc7..854edc3 100644 --- a/src/kmk/configure.in +++ b/src/kmk/configure.in @@ -1,7 +1,7 @@ # Process this file with autoconf to produce a configure script. # # Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under @@ -17,10 +17,10 @@ # You should have received a copy of the GNU General Public License along with # this program. If not, see <http://www.gnu.org/licenses/>. -AC_INIT([GNU make],[3.81.90],[bug-make@gnu.org]) +AC_INIT([GNU make],[3.82],[bug-make@gnu.org]) AC_PREREQ(2.59) -AC_REVISION([[$Id: configure.in,v 1.148 2007/07/04 19:35:17 psmith Exp $]]) +AC_REVISION([[$Id: configure.in,v 1.156 2010/07/28 05:39:50 psmith Exp $]]) # Autoconf setup AC_CONFIG_AUX_DIR(config) @@ -148,18 +148,23 @@ if test "$ac_cv_func_gettimeofday" = yes; then [Define to 1 if you have a standard gettimeofday function]) fi -AC_CHECK_FUNCS( strdup mkstemp mktemp fdopen \ - bsd_signal dup2 getcwd realpath sigsetmask sigaction \ +AC_CHECK_FUNCS( strdup strndup mkstemp mktemp fdopen fileno \ + dup2 getcwd realpath sigsetmask sigaction \ getgroups seteuid setegid setlinebuf setreuid setregid \ getrlimit setrlimit setvbuf pipe strerror strsignal \ lstat readlink atexit) +# We need to check declarations, not just existence, because on Tru64 this +# function is not declared without special flags, which themselves cause +# other problems. We'll just use our own. +AC_CHECK_DECLS([bsd_signal], [], [], [[#include <signal.h>]]) + AC_FUNC_SETVBUF_REVERSED # Rumor has it that strcasecmp lives in -lresolv on some odd systems. # It doesn't hurt much to use our own if we can't find it so I don't # make the effort here. -AC_CHECK_FUNCS(strcasecmp strcmpi stricmp) +AC_CHECK_FUNCS(strcasecmp strncasecmp strcmpi strncmpi stricmp strnicmp) # strcoll() is used by the GNU glob library AC_FUNC_STRCOLL @@ -348,7 +353,6 @@ rm -f s.conftest conftoast # Check the system to see if it provides GNU glob. If not, use our # local version. - AC_MSG_CHECKING(if system libc has GNU glob) AC_CACHE_VAL(make_cv_sys_gnu_glob, [ AC_EGREP_CPP(gnu glob,[ @@ -365,9 +369,14 @@ AC_CACHE_VAL(make_cv_sys_gnu_glob, [ #endif ], [AC_MSG_RESULT(yes) make_cv_sys_gnu_glob=yes], [AC_MSG_RESULT([no; using local copy]) -AC_SUBST(GLOBINC) GLOBINC='-I$(srcdir)/glob' -AC_SUBST(GLOBLIB) GLOBLIB=glob/libglob.a make_cv_sys_gnu_glob=no])]) +if test "$make_cv_sys_gnu_glob" = no; then + GLOBINC='-I$(srcdir)/glob' + GLOBLIB=glob/libglob.a +fi +AC_SUBST(GLOBINC) +AC_SUBST(GLOBLIB) + # Tell automake about this, so it can build the right .c files. AM_CONDITIONAL(USE_LOCAL_GLOB, test "$make_cv_sys_gnu_glob" = no) diff --git a/src/kmk/debug.h b/src/kmk/debug.h index 79b6fae..a5c62fd 100644 --- a/src/kmk/debug.h +++ b/src/kmk/debug.h @@ -1,6 +1,6 @@ /* Debugging macros and interface. -Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free -Software Foundation, Inc. +Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/default.c b/src/kmk/default.c index c9850ba..dec90bb 100644 --- a/src/kmk/default.c +++ b/src/kmk/default.c @@ -1,7 +1,7 @@ /* Data base of default implicit rules for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -548,18 +548,14 @@ set_default_suffixes (void) suffix_file = enter_file (strcache_add (".SUFFIXES")); if (no_builtin_rules_flag) - define_variable ("SUFFIXES", 8, "", o_default, 0); + define_variable_cname ("SUFFIXES", "", o_default, 0); else { char *p = default_suffixes; - suffix_file->deps = (struct dep *) -#ifndef CONFIG_WITH_ALLOC_CACHES - multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1), - sizeof (struct dep)); -#else - multi_glob (parse_file_seq (&p, '\0', &dep_cache, 1), &dep_cache); -#endif - define_variable ("SUFFIXES", 8, default_suffixes, o_default, 0); + suffix_file->deps = enter_prereqs(PARSE_FILE_SEQ (&p, struct dep, '\0', + NULL, 0), + NULL); + define_variable_cname ("SUFFIXES", default_suffixes, o_default, 0); } } diff --git a/src/kmk/dep.h b/src/kmk/dep.h index 5819fe7..17df101 100644 --- a/src/kmk/dep.h +++ b/src/kmk/dep.h @@ -1,7 +1,7 @@ /* Definitions of dependency data structures for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -43,6 +43,8 @@ struct dep unsigned int ignore_mtime : 1; unsigned int staticpattern : 1; unsigned int need_2nd_expansion : 1; + unsigned int dontcare : 1; + #ifdef CONFIG_WITH_INCLUDEDEP unsigned int includedep : 1; #endif @@ -58,53 +60,61 @@ struct nameseq }; +#define PARSEFS_NONE (0x0000) +#define PARSEFS_NOSTRIP (0x0001) +#define PARSEFS_NOAR (0x0002) +#define PARSEFS_NOGLOB (0x0004) +#define PARSEFS_EXISTS (0x0008) +#define PARSEFS_NOCACHE (0x0010) + #ifndef CONFIG_WITH_ALLOC_CACHES -struct nameseq *multi_glob (struct nameseq *chain, unsigned int size); +#define PARSE_FILE_SEQ(_s,_t,_c,_p,_f) \ + (_t *)parse_file_seq ((_s),sizeof (_t),(_c),(_p),(_f)) #else -struct nameseq *multi_glob (struct nameseq *chain, struct alloccache *cache); +# define PARSE_FILE_SEQ(_s,_t,_c,_p,_f) \ + (_t *)parse_file_seq ((_s),sizeof (_t),(_c),(_p),(_f), \ + &PARSE_FILE_SEQ_IGNORE_ ## _t ## _cache) +# define PARSE_FILE_SEQ_IGNORE_struct #endif + #ifdef VMS -struct nameseq *parse_file_seq (); +void *parse_file_seq (); #else -# ifndef CONFIG_WITH_ALLOC_CACHES -struct nameseq *parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip); -# else -struct nameseq *parse_file_seq (char **stringp, int stopchar, struct alloccache *cache, int strip); -# endif +void *parse_file_seq (char **stringp, unsigned int size, + int stopchar, const char *prefix, int flags + IF_WITH_ALLOC_CACHES_PARAM(struct alloccache *cache)); #endif + char *tilde_expand (const char *name); #ifndef NO_ARCHIVES struct nameseq *ar_glob (const char *arname, const char *member_pattern, unsigned int size); #endif -#define dep_name(d) ((d)->name == 0 ? (d)->file->name : (d)->name) +#define dep_name(d) ((d)->name == 0 ? (d)->file->name : (d)->name) + + +#ifndef CONFIG_WITH_ALLOC_CACHES +#define alloc_dep() (xcalloc (sizeof (struct dep))) +#define free_ns(_n) free (_n) +#define free_dep(_d) free_ns (_d) +#else +#define alloc_dep() alloccache_calloc (&dep_cache) +#define free_ns(_n) alloccache_free (&nameseq_cache, _n) +#define free_dep(_d) alloccache_free (&dep_cache, _d) +#endif -struct dep *alloc_dep (void); -void free_dep (struct dep *d); struct dep *copy_dep_chain (const struct dep *d); void free_dep_chain (struct dep *d); void free_ns_chain (struct nameseq *n); struct dep *read_all_makefiles (const char **makefiles); -#ifndef CONFIG_WITH_VALUE_LENGTH -int eval_buffer (char *buffer); -#else -int eval_buffer (char *buffer, char *eos); -#endif +void eval_buffer (char *buffer IF_WITH_VALUE_LENGTH(COMMA char *eos)); int update_goal_chain (struct dep *goals); -void uniquize_deps (struct dep *); #ifdef CONFIG_WITH_INCLUDEDEP /* incdep.c */ enum incdep_op { incdep_read_it, incdep_queue, incdep_flush }; void eval_include_dep (const char *name, struct floc *f, enum incdep_op op); void incdep_flush_and_term (void); - -/* read.c */ -void record_files (struct nameseq *filenames, const char *pattern, - const char *pattern_percent, struct dep *deps, - unsigned int cmds_started, char *commands, - unsigned int commands_idx, int two_colon, - const struct floc *flocp); #endif diff --git a/src/kmk/dir.c b/src/kmk/dir.c index f55b2a5..fae0a7b 100644 --- a/src/kmk/dir.c +++ b/src/kmk/dir.c @@ -1,7 +1,7 @@ /* Directory hashing for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -23,7 +23,8 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ # include <dirent.h> # define NAMLEN(dirent) strlen((dirent)->d_name) # ifdef VMS -char *vmsify (char *name, int type); +/* its prototype is in vmsdir.h, which is not needed for HAVE_DIRENT_H */ +const char *vmsify (const char *name, int type); # endif #else # define dirent direct @@ -131,14 +132,11 @@ downcase (const char *filename) { static PATH_VAR (new_filename); char *df; - int i; if (filename == 0) return 0; df = new_filename; - - /* First, transform the name part. */ while (*filename != '\0') { *df++ = tolower ((unsigned char)*filename); @@ -154,7 +152,7 @@ downcase (const char *filename) #ifdef VMS static int -vms_hash (char *name) +vms_hash (const char *name) { int h = 0; int g; @@ -180,7 +178,7 @@ vms_hash (char *name) /* fake stat entry for a directory */ static int -vmsstat_dir (char *name, struct stat *st) +vmsstat_dir (const char *name, struct stat *st) { char *s; int h; @@ -193,6 +191,7 @@ vmsstat_dir (char *name, struct stat *st) s = strchr (name, ':'); /* find device */ if (s) { + /* to keep the compiler happy we said "const char *name", now we cheat */ *s++ = 0; st->st_dev = (char *)vms_hash (name); h = vms_hash (s); @@ -201,8 +200,7 @@ vmsstat_dir (char *name, struct stat *st) else { st->st_dev = 0; - s = name; - h = vms_hash (s); + h = vms_hash (name); } st->st_ino[0] = h & 0xff; @@ -492,7 +490,11 @@ find_directory (const char *name) dir_slot = (struct directory **) hash_find_slot (&directories, &dir_key); #else p = name + strlen (name); +# if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) + dir_key.name = strcache_add_len (downcase(name), p - name); +# else dir_key.name = strcache_add_len (name, p - name); +# endif dir_slot = (struct directory **) hash_find_slot_strcached (&directories, &dir_key); #endif dir = *dir_slot; @@ -512,10 +514,14 @@ find_directory (const char *name) dir = alloccache_alloc (&directories_cache); #endif #ifndef CONFIG_WITH_STRCACHE2 - dir->name = strcache_add_len (name, p - name); +#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) + dir->name = strcache_add_len (downcase(name), p - name); #else - dir->name = dir_key.name; + dir->name = strcache_add_len (name, p - name); #endif +#else /* CONFIG_WITH_STRCACHE2 */ + dir->name = dir_key.name; +#endif /* CONFIG_WITH_STRCACHE2 */ hash_insert_at (&directories, dir, dir_slot); /* The directory is not in the name hash table. Find its device and inode numbers, and look it up by them. */ @@ -821,7 +827,11 @@ dir_contents_file_exists_p (struct directory_contents *dir, dirfile_key.length = len; dirfile_slot = (struct dirfile **) hash_find_slot (&dir->dirfiles, &dirfile_key); #else +# if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) + dirfile_key.name = strcache_add_len (downcase(d->d_name), len); +# else dirfile_key.name = strcache_add_len (d->d_name, len); +# endif dirfile_key.length = len; dirfile_slot = (struct dirfile **) hash_find_slot_strcached (&dir->dirfiles, &dirfile_key); #endif @@ -839,17 +849,21 @@ dir_contents_file_exists_p (struct directory_contents *dir, df = alloccache_alloc (&dirfile_cache); #endif #ifndef CONFIG_WITH_STRCACHE2 - df->name = strcache_add_len (d->d_name, len); +#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) + df->name = strcache_add_len (downcase(d->d_name), len); #else - df->name = dirfile_key.name; + df->name = strcache_add_len (d->d_name, len); #endif +#else /* CONFIG_WITH_STRCACHE2 */ + df->name = dirfile_key.name; +#endif /* CONFIG_WITH_STRCACHE2 */ df->length = len; df->impossible = 0; hash_insert_at (&dir->dirfiles, df, dirfile_slot); } /* Check if the name matches the one we're searching for. */ #ifndef CONFIG_WITH_STRCACHE2 - if (filename != 0 && strieq (d->d_name, filename)) + if (filename != 0 && patheq (d->d_name, filename)) #else if (filename != 0 && dirfile_key.name == filename) #endif @@ -1003,16 +1017,13 @@ file_impossible (const char *filename) } if (dir->contents == 0) - { - /* The directory could not be stat'd. We allocate a contents - structure for it, but leave it out of the contents hash table. */ + /* The directory could not be stat'd. We allocate a contents + structure for it, but leave it out of the contents hash table. */ #ifndef CONFIG_WITH_ALLOC_CACHES - dir->contents = xmalloc (sizeof (struct directory_contents)); + dir->contents = xcalloc (sizeof (struct directory_contents)); #else - dir->contents = alloccache_alloc (&directory_contents_cache); + dir->contents = alloccache_calloc (&directory_contents_cache); #endif - memset (dir->contents, '\0', sizeof (struct directory_contents)); - } if (dir->contents->dirfiles.ht_vec == 0) { @@ -1033,7 +1044,11 @@ file_impossible (const char *filename) new = alloccache_alloc (&dirfile_cache); #endif new->length = strlen (filename); +#if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) + new->name = strcache_add_len (downcase(filename), new->length); +#else new->name = strcache_add_len (filename, new->length); +#endif new->impossible = 1; #ifndef CONFIG_WITH_STRCACHE2 hash_insert (&dir->contents->dirfiles, new); diff --git a/src/kmk/doc/Makefile.am b/src/kmk/doc/Makefile.am index 9c8c6c4..67eec3a 100644 --- a/src/kmk/doc/Makefile.am +++ b/src/kmk/doc/Makefile.am @@ -1,6 +1,6 @@ # -*-Makefile-*-, or close enough -# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -# Foundation, Inc. +# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +# 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/dosbuild.bat b/src/kmk/dosbuild.bat index e0e6ded..c911e18 100644 --- a/src/kmk/dosbuild.bat +++ b/src/kmk/dosbuild.bat @@ -1,6 +1,6 @@ @echo off
-rem Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-rem Free Software Foundation, Inc.
+rem Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+rem 2008, 2009, 2010 Free Software Foundation, Inc.
rem This file is part of GNU Make.
rem
rem GNU Make is free software; you can redistribute it and/or modify it under
diff --git a/src/kmk/electric.c b/src/kmk/electric.c index c8d0235..21a4b11 100644 --- a/src/kmk/electric.c +++ b/src/kmk/electric.c @@ -1,4 +1,4 @@ -/* $Id: electric.c 2413 2010-09-11 17:43:04Z bird $ */ +/* $Id: electric.c 2626 2012-08-09 14:11:47Z bird $ */ /** @file * A simple electric heap implementation. */ @@ -158,11 +158,11 @@ xmalloc (unsigned int size) } void * -xcalloc (size_t size, size_t items) +xcalloc (unsigned size) { void *result; - result = xmalloc (size * items); - return memset (result, 0, size * items); + result = xmalloc (size); + return memset (result, 0, size); } void * @@ -183,9 +183,13 @@ xrealloc (void *ptr, unsigned int size) char * xstrdup (const char *ptr) { - size_t size = strlen (ptr) + 1; - char *result = xmalloc (size); - return memcpy (result, ptr, size); + if (ptr) + { + size_t size = strlen (ptr) + 1; + char *result = xmalloc (size); + return memcpy (result, ptr, size); + } + return NULL; } #else /* !ELECTRIC_HEAP */ diff --git a/src/kmk/electric.h b/src/kmk/electric.h index eb39082..2983819 100644 --- a/src/kmk/electric.h +++ b/src/kmk/electric.h @@ -1,4 +1,4 @@ -/* $Id: electric.h 2413 2010-09-11 17:43:04Z bird $ */ +/* $Id: electric.h 2591 2012-06-17 20:45:31Z bird $ */ /** @file * A simple electric heap implementation, wrapper header. */ @@ -32,13 +32,13 @@ #include <string.h> /* strdup */ void xfree (void *); -void *xcalloc (size_t, size_t); +void *xcalloc (unsigned int); void *xmalloc (unsigned int); void *xrealloc (void *, unsigned int); char *xstrdup (const char *); #define free(a) xfree(a) -#define calloc(a,b) xcalloc((a),(b)) +#define calloc(a,b) xcalloc((a) * (b)) #define malloc(a) xmalloc(a) #define realloc(a,b) xrealloc((a),(b)) #define strdup(a) xstrdup(a) diff --git a/src/kmk/expand.c b/src/kmk/expand.c index d4912dd..c93e197 100644 --- a/src/kmk/expand.c +++ b/src/kmk/expand.c @@ -1,7 +1,7 @@ /* Variable expansion functions for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -536,8 +536,8 @@ variable_expand_string (char *line, const char *string, long length) if (*p == '\0') break; - else - ++p; + + ++p; } if (abuf) @@ -840,7 +840,8 @@ char * expand_argument (const char *str, const char *end) { #ifndef CONFIG_WITH_VALUE_LENGTH - char *tmp; + char *tmp, *alloc = NULL; + char *r; #endif if (str == end) @@ -850,11 +851,20 @@ expand_argument (const char *str, const char *end) if (!end || *end == '\0') return allocated_variable_expand (str); - tmp = alloca (end - str + 1); + if (end - str + 1 > 1000) + tmp = alloc = xmalloc (end - str + 1); + else + tmp = alloca (end - str + 1); + memcpy (tmp, str, end - str); tmp[end - str] = '\0'; - return allocated_variable_expand (tmp); + r = allocated_variable_expand (tmp); + + if (alloc) + free (alloc); + + return r; #else /* CONFIG_WITH_VALUE_LENGTH */ if (!end) return allocated_variable_expand_2 (str, ~0U, NULL); @@ -1095,11 +1105,6 @@ allocated_variable_expand_for_file (const char *line, struct file *file) value = variable_expand_for_file (line, file); -#if 0 - /* Waste a little memory and save time. */ - value = xrealloc (value, strlen (value)) -#endif - variable_buffer = obuf; variable_buffer_length = olen; diff --git a/src/kmk/file.c b/src/kmk/file.c index f43ead4..16b0fe5 100644 --- a/src/kmk/file.c +++ b/src/kmk/file.c @@ -1,7 +1,7 @@ /* Target file management for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -118,10 +118,20 @@ lookup_file_common (const char *name, int cached) while (name[0] == '[' && name[1] == ']' && name[2] != '\0') name += 2; #endif - while (name[0] == '.' && name[1] == '/' && name[2] != '\0') + while (name[0] == '.' +#ifdef HAVE_DOS_PATHS + && (name[1] == '/' || name[1] == '\\') +#else + && name[1] == '/' +#endif + && name[2] != '\0') { name += 2; - while (*name == '/') + while (*name == '/' +#ifdef HAVE_DOS_PATHS + || *name == '\\' +#endif + ) /* Skip following slashes: ".//foo" is "foo", not "/foo". */ ++name; } @@ -229,8 +239,7 @@ enter_file (const char *name) return f; #ifndef CONFIG_WITH_ALLOC_CACHES - new = xmalloc (sizeof (struct file)); - memset (new, '\0', sizeof (struct file)); + new = xcalloc (sizeof (struct file)); #else new = alloccache_calloc (&file_cache); #endif @@ -351,6 +360,29 @@ rehash_file (struct file *from_file, const char *to_hname) } } +#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET + /* Merge multi target attributes and considerations. */ + if (from_file->multi_head) + { + if (to_file->multi_head) + fatal (NILF, _("can't rename/merge multi target '%s' with multi target '%s'"), + from_file->name, to_hname); + + to_file->multi_maybe = from_file->multi_maybe; + to_file->multi_next = from_file->multi_next; + to_file->multi_head = f = from_file->multi_head; + if (f == from_file) + for (; f != 0; f = f->multi_next) + f->multi_head = to_file; + else + { + while (f->multi_next != from_file) + f = f->multi_next; + f->multi_next = to_file; + } + } +#endif + /* Merge the dependencies of the two files. */ if (to_file->deps == 0) @@ -506,17 +538,13 @@ remove_intermediates (int sig) } } +/* Given a string containing prerequisites (fully expanded), break it up into + a struct dep list. Enter each of these prereqs into the file database. + */ struct dep * -parse_prereqs (char *p) +split_prereqs (char *p) { -#ifndef CONFIG_WITH_ALLOC_CACHES - struct dep *new = (struct dep *) - multi_glob (parse_file_seq (&p, '|', sizeof (struct dep), 1), - sizeof (struct dep)); -#else - struct dep *new = (struct dep *) - multi_glob (parse_file_seq (&p, '|', &dep_cache, 1), &dep_cache); -#endif + struct dep *new = PARSE_FILE_SEQ (&p, struct dep, '|', NULL, 0); if (*p) { @@ -525,14 +553,7 @@ parse_prereqs (char *p) struct dep *ood; ++p; -#ifndef CONFIG_WITH_ALLOC_CACHES - ood = (struct dep *) - multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1), - sizeof (struct dep)); -#else - ood = (struct dep *) - multi_glob (parse_file_seq (&p, '\0', &dep_cache, 1), &dep_cache); -#endif + ood = PARSE_FILE_SEQ (&p, struct dep, '\0', NULL, 0); if (! new) new = ood; @@ -551,6 +572,85 @@ parse_prereqs (char *p) return new; } +/* Given a list of prerequisites, enter them into the file database. + If STEM is set then first expand patterns using STEM. */ +struct dep * +enter_prereqs (struct dep *deps, const char *stem) +{ + struct dep *d1; + + if (deps == 0) + return 0; + + /* If we have a stem, expand the %'s. We use patsubst_expand to translate + the prerequisites' patterns into plain prerequisite names. */ + if (stem) + { + const char *pattern = "%"; + char *buffer = variable_expand (""); + struct dep *dp = deps, *dl = 0; + + while (dp != 0) + { + char *percent; + int nl = strlen (dp->name) + 1; + char *nm = alloca (nl); + memcpy (nm, dp->name, nl); + percent = find_percent (nm); + if (percent) + { + char *o; + + /* We have to handle empty stems specially, because that + would be equivalent to $(patsubst %,dp->name,) which + will always be empty. */ + if (stem[0] == '\0') + { + memmove (percent, percent+1, strlen (percent)); + o = variable_buffer_output (buffer, nm, strlen (nm) + 1); + } + else + o = patsubst_expand_pat (buffer, stem, pattern, nm, + pattern+1, percent+1); + + /* If the name expanded to the empty string, ignore it. */ + if (buffer[0] == '\0') + { + struct dep *df = dp; + if (dp == deps) + dp = deps = deps->next; + else + dp = dl->next = dp->next; + free_dep (df); + continue; + } + + /* Save the name. */ + dp->name = strcache_add_len (buffer, o - buffer); + } + dp->stem = stem; + dp->staticpattern = 1; + dl = dp; + dp = dp->next; + } + } + + /* Enter them as files, unless they need a 2nd expansion. */ + for (d1 = deps; d1 != 0; d1 = d1->next) + { + if (d1->need_2nd_expansion) + continue; + + d1->file = lookup_file (d1->name); + if (d1->file == 0) + d1->file = enter_file (d1->name); + d1->staticpattern = 0; + d1->name = 0; + } + + return deps; +} + /* Set the intermediate flag. */ static void @@ -565,238 +665,125 @@ static void expand_deps (struct file *f) { struct dep *d; - struct dep *old = f->deps; + struct dep **dp; const char *file_stem = f->stem; - unsigned int last_dep_has_cmds = f->updating; int initialized = 0; f->updating = 0; - f->deps = 0; - for (d = old; d != 0; d = d->next) + /* Walk through the dependencies. For any dependency that needs 2nd + expansion, expand it then insert the result into the list. */ + dp = &f->deps; + d = f->deps; + while (d != 0) { - struct dep *new, *d1; char *p; -#ifdef CONFIG_WITH_STRCACHE2 - unsigned int len; -#endif + struct dep *new, *next; + char *name = (char *)d->name; - if (! d->name) - continue; + if (! d->name || ! d->need_2nd_expansion) + { + /* This one is all set already. */ + dp = &d->next; + d = d->next; + continue; + } #ifdef CONFIG_WITH_INCLUDEDEP /* Dependencies loaded by includedep are ready for use and we skip - the expensive parsing and globbing for them. To avoid wasting - lots of time walking the f->deps chain, we will advance D and - process all subsequent includedep records. */ + the expensive parsing and globbing for them. */ if (d->includedep) { - new = d1 = alloc_dep(); - d1->staticpattern = 0; - d1->need_2nd_expansion = 0; - d1->includedep = 1; - d1->file = lookup_file (d->name); - if (d1->file == 0) - d1->file = enter_file (d->name); - - while (d->next && d->next->includedep) - { - d = d->next; - d1 = d1->next = alloc_dep(); - d1->staticpattern = 0; - d1->need_2nd_expansion = 0; - d1->includedep = 1; - d1->file = lookup_file (d->name); - if (d1->file == 0) - d1->file = enter_file (d->name); - } + d->need_2nd_expansion = 0; + d->file = lookup_file (name); + if (d->file == 0) + d->file = enter_file (name); + d->name = 0; + free(name); + + dp = &d->next; + d = d->next; + continue; } - else - { -#endif +#endif /* CONFIG_WITH_INCLUDEDEP */ - /* Create the dependency list. - If we're not doing 2nd expansion, then it's just the name. We will - still need to massage it though. */ - if (! d->need_2nd_expansion) + /* If it's from a static pattern rule, convert the patterns into + "$*" so they'll expand properly. */ + if (d->staticpattern) { - p = variable_expand (""); + char *o; + d->name = o = variable_expand (""); + o = subst_expand (o, name, "%", "$*", 1, 2, 0); + *o = '\0'; #ifndef CONFIG_WITH_STRCACHE2 - variable_buffer_output (p, d->name, strlen (d->name) + 1); + free (name); + d->name = name = xstrdup (variable_buffer); /* bird not d->name, can be reallocated */ #else - len = strcache2_get_len (&file_strcache, d->name); - variable_buffer_output (p, d->name, len + 1); + d->name = strcache2_add (&file_strcache, variable_buffer, o - variable_buffer); #endif - p = variable_buffer; + d->staticpattern = 0; } - else - { - /* If it's from a static pattern rule, convert the patterns into - "$*" so they'll expand properly. */ - if (d->staticpattern) - { - char *o; - char *buffer = variable_expand (""); - o = subst_expand (buffer, d->name, "%", "$*", 1, 2, 0); - buffer = variable_buffer; /* bird - variable_buffer may have been reallocated. */ - - d->name = strcache_add_len (variable_buffer, - o - variable_buffer); - d->staticpattern = 0; /* Clear staticpattern so that we don't - re-expand %s below. */ - } - - /* We are going to do second expansion so initialize file variables - for the file. Since the stem for static pattern rules comes from - individual dep lines, we will temporarily set f->stem to d->stem. - */ - if (!initialized) - { - initialize_file_variables (f, 0); - initialized = 1; - } + /* We're going to do second expansion so initialize file variables for + the file. Since the stem for static pattern rules comes from + individual dep lines, we will temporarily set f->stem to d->stem. */ + if (!initialized) + { + initialize_file_variables (f, 0); + initialized = 1; + } - if (d->stem != 0) - f->stem = d->stem; + if (d->stem != 0) + f->stem = d->stem; #if defined(CONFIG_WITH_COMMANDS_FUNC) || defined (CONFIG_WITH_DOT_MUST_MAKE) - set_file_variables (f, 0 /* real call, f->deps == 0 so we're ok. */); + set_file_variables (f, 0 /* real call, f->deps == 0 so we're ok. */); #else - set_file_variables (f); + set_file_variables (f); #endif -#if !defined (CONFIG_WITH_VALUE_LENGTH) || !defined (CONFIG_WITH_STRCACHE2) - p = variable_expand_for_file (d->name, f); -#else - len = strcache2_get_len (&file_strcache, d->name); - p = variable_expand_for_file_2 (NULL, d->name, len, f, &len); -#endif + p = variable_expand_for_file (d->name, f); - if (d->stem != 0) - f->stem = file_stem; - } + if (d->stem != 0) + f->stem = file_stem; - /* Parse the prerequisites. */ - new = parse_prereqs (p); + /* At this point we don't need the name anymore: free it. */ + free (name); - /* If this dep list was from a static pattern rule, expand the %s. We - use patsubst_expand to translate the prerequisites' patterns into - plain prerequisite names. */ - if (new && d->staticpattern) - { - const char *pattern = "%"; - char *buffer = variable_expand (""); - struct dep *dp = new, *dl = 0; - - while (dp != 0) - { - char *percent; -#ifndef KMK - int nl = strlen (dp->name) + 1; - char *nm = alloca (nl); - memcpy (nm, dp->name, nl); - percent = find_percent (nm); -#else /* KMK - don't make a stack copy unless it's actually required! */ - unsigned int nl = strcache2_get_len (&file_strcache, dp->name); - char *nm; - percent = memchr (dp->name, '%', nl); - if (percent) - { - nm = alloca (nl + 1); - memcpy (nm, dp->name, nl + 1); - percent = find_percent (nm); - } -#endif /* KMK */ - if (percent) - { - char *o; - - /* We have to handle empty stems specially, because that - would be equivalent to $(patsubst %,dp->name,) which - will always be empty. */ - if (d->stem[0] == '\0') - { - memmove (percent, percent+1, strlen (percent)); - o = variable_buffer_output (buffer, nm, strlen (nm) + 1); - } - else - { - o = patsubst_expand_pat (buffer, d->stem, pattern, nm, - pattern+1, percent+1); - o = variable_buffer_output (o, "", 1); /* bird fix - patsubst_expand_pat doesn't terminate, - the if case does and strcache would appreciate it. */ - } - buffer = variable_buffer; /* bird fix - variable_buffer may have been reallocated. */ - - - /* If the name expanded to the empty string, ignore it. */ - if (buffer[0] == '\0') - { - struct dep *df = dp; - if (dp == new) - dp = new = new->next; - else - dp = dl->next = dp->next; - free_dep (df); - continue; - } - - /* Save the name. */ - dp->name = strcache_add_len (buffer, o - buffer - 1); /* bird fix - don't include the terminator. */ - } - dl = dp; - dp = dp->next; - } - } + /* Parse the prerequisites and enter them into the file database. */ + new = enter_prereqs (split_prereqs (p), d->stem); - /* Enter them as files. */ - for (d1 = new; d1 != 0; d1 = d1->next) + /* If there were no prereqs here (blank!) then throw this one out. */ + if (new == 0) { - d1->file = lookup_file (d1->name); - if (d1->file == 0) - d1->file = enter_file (d1->name); - d1->name = 0; - d1->staticpattern = 0; - d1->need_2nd_expansion = 0; + *dp = d->next; + free_dep (d); + d = *dp; + continue; } -#ifdef CONFIG_WITH_INCLUDEDEP - } + /* Add newly parsed prerequisites. */ + next = d->next; +#ifdef KMK /* bird: memory leak */ + assert(new != d); + free_dep (d); #endif - - /* Add newly parsed deps to f->deps. If this is the last dependency - line and this target has commands then put it in front so the - last dependency line (the one with commands) ends up being the - first. This is important because people expect $< to hold first - prerequisite from the rule with commands. If it is not the last - dependency line or the rule does not have commands then link it - at the end so it appears in makefile order. */ - - if (new != 0) - { - if (d->next == 0 && last_dep_has_cmds) - { - struct dep **d_ptr; - for (d_ptr = &new; *d_ptr; d_ptr = &(*d_ptr)->next) - ; - - *d_ptr = f->deps; - f->deps = new; - } - else - { - struct dep **d_ptr; - for (d_ptr = &f->deps; *d_ptr; d_ptr = &(*d_ptr)->next) - ; - - *d_ptr = new; - } - } + *dp = new; + for (dp = &new->next, d = new->next; d != 0; dp = &d->next, d = d->next) + ; + *dp = next; + d = *dp; } +} + +/* Reset the updating flag. */ - free_dep_chain (old); +static void +reset_updating (const void *item) +{ + struct file *f = (struct file *) item; + f->updating = 0; } /* For each dependency of each file, make the `struct dep' point @@ -811,15 +798,10 @@ snap_deps (void) struct file *f; struct file *f2; struct dep *d; - struct file **file_slot_0; - struct file **file_slot; - struct file **file_end; - /* Perform second expansion and enter each dependency name as a file. */ - - /* Expand .SUFFIXES first; it's dependencies are used for $$* calculation. */ - for (f = lookup_file (".SUFFIXES"); f != 0; f = f->prev) - expand_deps (f); + /* Remember that we've done this. Once we start snapping deps we can no + longer define new targets. */ + snapped_deps = 1; #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION /* Perform 2nd target expansion on files which requires this. This will @@ -827,6 +809,7 @@ snap_deps (void) hash_dump(). */ if (second_target_expansion) { + struct file **file_slot_0, **file_end, **file_slot; # ifdef KMK /* turn on warnings here. */ int save = warn_undefined_variables_flag; warn_undefined_variables_flag = 1; @@ -857,35 +840,55 @@ snap_deps (void) incdep_flush_and_term (); #endif /* CONFIG_WITH_INCLUDEDEP */ - /* For every target that's not .SUFFIXES, expand its dependencies. - We must use hash_dump (), because within this loop we might add new files - to the table, possibly causing an in-situ table expansion. */ - file_slot_0 = (struct file **) hash_dump (&files, 0, 0); - file_end = file_slot_0 + files.ht_fill; - for (file_slot = file_slot_0; file_slot < file_end; file_slot++) - for (f = *file_slot; f != 0; f = f->prev) -#ifndef CONFIG_WITH_STRCACHE2 - if (strcmp (f->name, ".SUFFIXES") != 0) -#else - if (f->name != suffixes_strcached) -#endif + /* Perform second expansion and enter each dependency name as a file. We + must use hash_dump() here because within these loops we likely add new + files to the table, possibly causing an in-situ table expansion. + + We only need to do this if second_expansion has been defined; if it + hasn't then all deps were expanded as the makefile was read in. If we + ever change make to be able to unset .SECONDARY_EXPANSION this will have + to change. */ + + if (second_expansion) + { + struct file **file_slot_0 = (struct file **) hash_dump (&files, 0, 0); + struct file **file_end = file_slot_0 + files.ht_fill; + struct file **file_slot; + const char *suffixes; + + /* Expand .SUFFIXES: its prerequisites are used for $$* calc. */ + f = lookup_file (".SUFFIXES"); + suffixes = f ? f->name : 0; + for (; f != 0; f = f->prev) expand_deps (f); + #ifdef KMK - /* This is a HACK to work around the still broken test #9 in - features/double_colon. It produces the wrong result if the build is - parallel because of changed evaluation order. Just make these - problematic rules execute in single field till a proper fix is - forthcomming... */ - - for (file_slot = file_slot_0; file_slot < file_end; file_slot++) - if ( (f = *file_slot) != 0 - && f->double_colon - && ( f->double_colon != f - || f->last != f)) - for (f2 = f->double_colon; f2 != 0; f2 = f2->prev) - f2->command_flags |= COMMANDS_NOTPARALLEL; + /* This is a HACK to work around the still broken test #9 in + features/double_colon. It produces the wrong result if the build is + parallel because of changed evaluation order. Just make these + problematic rules execute in single field till a proper fix is + forthcomming... */ + + for (file_slot = file_slot_0; file_slot < file_end; file_slot++) + if ( (f = *file_slot) != 0 + && f->double_colon + && ( f->double_colon != f + || f->last != f)) + for (f2 = f->double_colon; f2 != 0; f2 = f2->prev) + f2->command_flags |= COMMANDS_NOTPARALLEL; #endif /* KMK */ - free (file_slot_0); + + /* For every target that's not .SUFFIXES, expand its prerequisites. */ + + for (file_slot = file_slot_0; file_slot < file_end; file_slot++) + for (f = *file_slot; f != 0; f = f->prev) + if (f->name != suffixes) + expand_deps (f); + free (file_slot_0); + } + else + /* We're not doing second expansion, so reset updating. */ + hash_map (&files, reset_updating); /* Now manage all the special targets. */ @@ -980,12 +983,9 @@ snap_deps (void) /* If .POSIX was defined, remove OUTPUT_OPTION to comply. */ /* This needs more work: what if the user sets this in the makefile? if (posix_pedantic) - define_variable (STRING_SIZE_TUPLE("OUTPUT_OPTION"), "", o_default, 1); + define_variable_cname ("OUTPUT_OPTION", "", o_default, 1); */ #endif - - /* Remember that we've done this. */ - snapped_deps = 1; } /* Set the `command_state' member of FILE and all its `also_make's. */ @@ -1112,12 +1112,34 @@ file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts) /* Print the data base of files. */ +void +print_prereqs (const struct dep *deps) +{ + const struct dep *ood = 0; + + /* Print all normal dependencies; note any order-only deps. */ + for (; deps != 0; deps = deps->next) + if (! deps->ignore_mtime) + printf (" %s", dep_name (deps)); + else if (! ood) + ood = deps; + + /* Print order-only deps, if we have any. */ + if (ood) + { + printf (" | %s", dep_name (ood)); + for (ood = ood->next; ood != 0; ood = ood->next) + if (ood->ignore_mtime) + printf (" %s", dep_name (ood)); + } + + putchar ('\n'); +} + static void print_file (const void *item) { const struct file *f = item; - struct dep *d; - struct dep *ood = 0; putchar ('\n'); if (!f->is_target) @@ -1140,7 +1162,10 @@ print_file (const void *item) f2->name); multi_maybe = f2->multi_maybe; } - putchar (':'); + if (f->deps) + printf (": \\\n\t"); + else + putchar (':'); } else printf ("%s:%s", f->name, f->double_colon ? ":" : ""); @@ -1149,23 +1174,7 @@ print_file (const void *item) #endif printf ("%s:%s", f->name, f->double_colon ? ":" : ""); - /* Print all normal dependencies; note any order-only deps. */ - for (d = f->deps; d != 0; d = d->next) - if (! d->ignore_mtime) - printf (" %s", dep_name (d)); - else if (! ood) - ood = d; - - /* Print order-only deps, if we have any. */ - if (ood) - { - printf (" | %s", dep_name (ood)); - for (d = ood->next; d != 0; d = d->next) - if (d->ignore_mtime) - printf (" %s", dep_name (d)); - } - - putchar ('\n'); + print_prereqs (f->deps); #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET if (f->multi_head && f->multi_head != f) @@ -1197,6 +1206,7 @@ print_file (const void *item) puts (_("# File is an intermediate prerequisite.")); if (f->also_make != 0) { + const struct dep *d; fputs (_("# Also makes:"), stdout); for (d = f->also_make; d != 0; d = d->next) printf (" %s", dep_name (d)); @@ -1290,7 +1300,7 @@ print_file_stats (void) #define VERIFY_CACHED(_p,_n) \ do{\ if (_p->_n && _p->_n[0] && !strcache_iscached (_p->_n)) \ - printf ("%s: Field %s not cached: %s\n", _p->name, # _n, _p->_n); \ + error (NULL, "%s: Field '%s' not cached: %s\n", _p->name, # _n, _p->_n); \ }while(0) static void @@ -1307,7 +1317,8 @@ verify_file (const void *item) /* Check the deps. */ for (d = f->deps; d != 0; d = d->next) { - VERIFY_CACHED (d, name); + if (! d->need_2nd_expansion) + VERIFY_CACHED (d, name); VERIFY_CACHED (d, stem); } } diff --git a/src/kmk/filedef.h b/src/kmk/filedef.h index 15a127b..a4eeb35 100644 --- a/src/kmk/filedef.h +++ b/src/kmk/filedef.h @@ -1,7 +1,7 @@ /* Definition of target file data structures for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -30,8 +30,8 @@ struct file const char *vpath; /* VPATH/vpath pathname */ struct dep *deps; /* all dependencies, including duplicates */ #ifdef CONFIG_WITH_LAZY_DEPS_VARS - struct dep *org_deps; /* original dependencies before - duplicates were dropped. */ + struct dep *deps_no_dupes; /* dependencies without duplicates, created on + demaned by func_deps. */ #endif struct commands *cmds; /* Commands to execute for this target. */ int command_flags; /* Flags OR'd in for cmds; see commands.h. */ @@ -106,6 +106,9 @@ struct file pattern-specific variables. */ unsigned int considered:1; /* equal to 'considered' if file has been considered on current scan of goal chain */ + unsigned int no_diag:1; /* True if the file failed to update and no + diagnostics has been issued (dontcare). */ + #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET unsigned int multi_maybe:1; /* Nonzero if this file isn't always updated by the explicit multi target rule. */ @@ -116,12 +119,10 @@ struct file can receive this is decided at parse time, and the expanding done in snap_deps. */ #endif - }; -extern struct file *default_goal_file, *suffix_file, *default_file; -extern char **default_goal_name; +extern struct file *suffix_file, *default_file; struct file *lookup_file (const char *name); @@ -129,7 +130,8 @@ struct file *lookup_file (const char *name); struct file *lookup_file_cached (const char *name); #endif struct file *enter_file (const char *name); -struct dep *parse_prereqs (char *prereqs); +struct dep *split_prereqs (char *prereqstr); +struct dep *enter_prereqs (struct dep *prereqs, const char *stem); void remove_intermediates (int sig); void snap_deps (void); void rename_file (struct file *file, const char *name); @@ -138,6 +140,8 @@ void set_command_state (struct file *file, enum cmd_state state); void notice_finished_file (struct file *file); void init_hash_files (void); char *build_target_list (char *old_list); +void print_prereqs (const struct dep *deps); +void print_file_data_base (void); #if FILE_TIMESTAMP_HI_RES # define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \ diff --git a/src/kmk/function.c b/src/kmk/function.c index 0cb5c2c..2af48c6 100644 --- a/src/kmk/function.c +++ b/src/kmk/function.c @@ -1,7 +1,7 @@ /* Builtin function expansion for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -81,6 +81,10 @@ static math_int math_int_from_string (const char *str); /** Checks if the @a_cch characters (bytes) in @a a_psz equals @a a_szConst. */ # define STR_N_EQUALS(a_psz, a_cch, a_szConst) \ ( (a_cch) == sizeof (a_szConst) - 1 && !strncmp ((a_psz), (a_szConst), sizeof (a_szConst) - 1) ) + +# ifdef _MSC_VER +# include "kmkbuiltin/mscfakes.h" +# endif #endif @@ -507,23 +511,11 @@ string_glob (char *line) struct nameseq *chain; unsigned int idx; -#ifndef CONFIG_WITH_ALLOC_CACHES - chain = multi_glob (parse_file_seq - (&line, '\0', sizeof (struct nameseq), - /* We do not want parse_file_seq to strip `./'s. - That would break examples like: - $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */ - 0), - sizeof (struct nameseq)); -#else /* CONFIG_WITH_ALLOC_CACHES */ - chain = multi_glob (parse_file_seq - (&line, '\0', &nameseq_cache, - /* We do not want parse_file_seq to strip `./'s. - That would break examples like: - $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */ - 0), - &nameseq_cache); -#endif /* CONFIG_WITH_ALLOC_CACHES */ + chain = PARSE_FILE_SEQ (&line, struct nameseq, '\0', NULL, + /* We do not want parse_file_seq to strip `./'s. + That would break examples like: + $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */ + PARSEFS_NOSTRIP|PARSEFS_NOCACHE|PARSEFS_EXISTS); if (result == 0) { @@ -534,30 +526,26 @@ string_glob (char *line) idx = 0; while (chain != 0) { - const char *name = chain->name; - unsigned int len = strlen (name); - struct nameseq *next = chain->next; + unsigned int len = strlen (chain->name); + + if (idx + len + 1 > length) + { + length += (len + 1) * 2; + result = xrealloc (result, length); + } + memcpy (&result[idx], chain->name, len); + idx += len; + result[idx++] = ' '; + + /* Because we used PARSEFS_NOCACHE above, we have to free() NAME. */ + free ((char *)chain->name); #ifndef CONFIG_WITH_ALLOC_CACHES free (chain); #else alloccache_free (&nameseq_cache, chain); #endif chain = next; - - /* multi_glob will pass names without globbing metacharacters - through as is, but we want only files that actually exist. */ - if (file_exists_p (name)) - { - if (idx + len + 1 > length) - { - length += (len + 1) * 2; - result = xrealloc (result, length); - } - memcpy (&result[idx], name, len); - idx += len; - result[idx++] = ' '; - } } /* Kill the last space and terminate the string. */ @@ -1338,7 +1326,7 @@ func_foreach (char *o, char **argv, const char *funcname UNUSED) char *result = 0; free (var->value); - var->value = savestring (p, len); + var->value = xstrndup (p, len); result = allocated_variable_expand (body); @@ -2210,7 +2198,7 @@ int shell_function_pid = 0, shell_function_completed; void -windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) +windows32_openpipe (int *pipedes, pid_t *pid_p, char **command_argv, char **envp) { SECURITY_ATTRIBUTES saAttr; HANDLE hIn; @@ -2231,7 +2219,7 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { - fatal (NILF, _("create_child_process: DuplicateHandle(In) failed (e=%ld)\n"), + fatal (NILF, _("windows32_openpipe(): DuplicateHandle(In) failed (e=%ld)\n"), GetLastError()); } @@ -2242,7 +2230,7 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { - fatal (NILF, _("create_child_process: DuplicateHandle(Err) failed (e=%ld)\n"), + fatal (NILF, _("windows32_open_pipe(): DuplicateHandle(Err) failed (e=%ld)\n"), GetLastError()); } @@ -2252,23 +2240,26 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) hProcess = process_init_fd(hIn, hChildOutWr, hErr); if (!hProcess) - fatal (NILF, _("windows32_openpipe (): process_init_fd() failed\n")); + fatal (NILF, _("windows32_openpipe(): process_init_fd() failed\n")); /* make sure that CreateProcess() has Path it needs */ sync_Path_environment(); + /* `sync_Path_environment' may realloc `environ', so take note of + the new value. */ + envp = environ; if (!process_begin(hProcess, command_argv, envp, command_argv[0], NULL)) { /* register process for wait */ process_register(hProcess); /* set the pid for returning to caller */ - *pid_p = (int) hProcess; + *pid_p = (pid_t) hProcess; /* set up to read data from child */ - pipedes[0] = _open_osfhandle((long) hChildOutRd, O_RDONLY); + pipedes[0] = _open_osfhandle((intptr_t) hChildOutRd, O_RDONLY); /* this will be closed almost right away */ - pipedes[1] = _open_osfhandle((long) hChildOutWr, O_APPEND); + pipedes[1] = _open_osfhandle((intptr_t) hChildOutWr, O_APPEND); } else { /* reap/cleanup the failed process */ process_cleanup(hProcess); @@ -2283,7 +2274,7 @@ windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) /* set status for return */ pipedes[0] = pipedes[1] = -1; - *pid_p = -1; + *pid_p = (pid_t)-1; } } #endif @@ -2356,7 +2347,7 @@ msdos_openpipe (int* pipedes, int *pidp, char *text) #else #ifndef _AMIGA static char * -func_shell (char *o, char **argv, const char *funcname UNUSED) +func_shell (char * volatile o, char **argv, const char *funcname UNUSED) { char *batch_filename = NULL; @@ -2364,10 +2355,10 @@ func_shell (char *o, char **argv, const char *funcname UNUSED) FILE *fpipe; #endif char **command_argv; - const char *error_prefix; + const char * volatile error_prefix; /* bird: this volatile and the 'o' one, is for shutting up gcc warnings */ char **envp; int pipedes[2]; - int pid; + pid_t pid; #ifndef __MSDOS__ /* Construct the argument list. */ @@ -2457,11 +2448,11 @@ func_shell (char *o, char **argv, const char *funcname UNUSED) free (command_argv[0]); free (command_argv); - /* Close the write side of the pipe. */ -# ifdef _MSC_VER /* Avoid annoying msvcrt when debugging. (bird) */ - if (pipedes[1] != -1) -# endif - close (pipedes[1]); + /* Close the write side of the pipe. We test for -1, since + pipedes[1] is -1 on MS-Windows, and some versions of MS + libraries barf when `close' is called with -1. */ + if (pipedes[1] >= 0) + close (pipedes[1]); #endif /* Set up and read from the pipe. */ @@ -2997,7 +2988,7 @@ func_translate (char *o, char **argv, const char *funcname UNUSED) /* Implements $^ and $+. - The first is somes with with FUNCNAME 'deps', the second as 'deps-all'. + The first comes with FUNCNAME 'deps', the second as 'deps-all'. If no second argument is given, or if it's empty, or if it's zero, all dependencies will be returned. If the second argument is non-zero @@ -3033,9 +3024,16 @@ func_deps (char *o, char **argv, const char *funcname) file = lookup_file (argv[0]); if (file) { - struct dep *deps = funcname[4] != '\0' && file->org_deps - ? file->org_deps : file->deps; + struct dep *deps; struct dep *d; + if (funcname[4] == '\0') + { + deps = file->deps_no_dupes; + if (!deps && file->deps) + deps = file->deps = create_uniqute_deps_chain (file->deps); + } + else + deps = file->deps; if ( file->double_colon && ( file->double_colon != file @@ -3424,6 +3422,14 @@ func_defined (char *o, char **argv, const char *funcname UNUSED) #endif /* CONFIG_WITH_DEFINED*/ +#ifdef HAVE_DOS_PATHS +#define IS_ABSOLUTE(n) (n[0] && n[1] == ':') +#define ROOT_LEN 3 +#else +#define IS_ABSOLUTE(n) (n[0] == '/') +#define ROOT_LEN 1 +#endif + /* Return the absolute name of file NAME which does not contain any `.', `..' components nor any repeated path separators ('/'). */ #ifdef KMK @@ -3435,6 +3441,7 @@ abspath (const char *name, char *apath) { char *dest; const char *start, *end, *apath_limit; + unsigned long root_len = ROOT_LEN; if (name[0] == '\0' || apath == NULL) return NULL; @@ -3461,18 +3468,7 @@ abspath (const char *name, char *apath) #else /* !WINDOWS32 && !__OS2__ */ apath_limit = apath + GET_PATH_MAX; -#ifdef HAVE_DOS_PATHS /* bird added this */ - if (isalpha(name[0]) && name[1] == ':') - { - /* drive spec */ - apath[0] = toupper(name[0]); - apath[1] = ':'; - apath[2] = '/'; - name += 2; - } - else -#endif /* HAVE_DOS_PATHS */ - if (name[0] != '/') + if (!IS_ABSOLUTE(name)) { /* It is unlikely we would make it until here but just to make sure. */ if (!starting_directory) @@ -3480,12 +3476,47 @@ abspath (const char *name, char *apath) strcpy (apath, starting_directory); +#ifdef HAVE_DOS_PATHS + if (IS_PATHSEP(name[0])) + { + if (IS_PATHSEP(name[1])) + { + /* A UNC. Don't prepend a drive letter. */ + apath[0] = name[0]; + apath[1] = name[1]; + root_len = 2; + } + /* We have /foo, an absolute file name except for the drive + letter. Assume the missing drive letter is the current + drive, which we can get if we remove from starting_directory + everything past the root directory. */ + apath[root_len] = '\0'; + } +#endif + dest = strchr (apath, '\0'); } else { - apath[0] = '/'; - dest = apath + 1; + strncpy (apath, name, root_len); + apath[root_len] = '\0'; + dest = apath + root_len; + /* Get past the root, since we already copied it. */ + name += root_len; +#ifdef HAVE_DOS_PATHS + if (!IS_PATHSEP(apath[2])) + { + /* Convert d:foo into d:./foo and increase root_len. */ + apath[2] = '.'; + apath[3] = '/'; + dest++; + root_len++; + /* strncpy above copied one character too many. */ + name--; + } + else + apath[2] = '/'; /* make sure it's a forward slash */ +#endif } for (start = end = name; *start != '\0'; start = end) @@ -3493,11 +3524,11 @@ abspath (const char *name, char *apath) unsigned long len; /* Skip sequence of multiple path-separators. */ - while (*start == '/') + while (IS_PATHSEP(*start)) ++start; /* Find end of path component. */ - for (end = start; *end != '\0' && *end != '/'; ++end) + for (end = start; *end != '\0' && !IS_PATHSEP(*end); ++end) ; len = end - start; @@ -3509,12 +3540,12 @@ abspath (const char *name, char *apath) else if (len == 2 && start[0] == '.' && start[1] == '.') { /* Back up to previous component, ignore if at root already. */ - if (dest > apath + 1) - while ((--dest)[-1] != '/'); + if (dest > apath + root_len) + for (--dest; !IS_PATHSEP(dest[-1]); --dest); } else { - if (dest[-1] != '/') + if (!IS_PATHSEP(dest[-1])) *dest++ = '/'; if (dest + len >= apath_limit) @@ -3528,11 +3559,7 @@ abspath (const char *name, char *apath) #endif /* !WINDOWS32 && !__OS2__ */ /* Unless it is root strip trailing separator. */ -#ifdef HAVE_DOS_PATHS /* bird (is this correct? what about UNC?) */ - if (dest > apath + 1 + (apath[0] != '/') && dest[-1] == '/') -#else - if (dest > apath + 1 && dest[-1] == '/') -#endif + if (dest > apath + root_len && IS_PATHSEP(dest[-1])) --dest; *dest = '\0'; @@ -3549,6 +3576,9 @@ func_realpath (char *o, char **argv, const char *funcname UNUSED) const char *path = 0; int doneany = 0; unsigned int len = 0; +#ifndef HAVE_REALPATH + struct stat st; +#endif PATH_VAR (in); PATH_VAR (out); @@ -3563,7 +3593,7 @@ func_realpath (char *o, char **argv, const char *funcname UNUSED) #ifdef HAVE_REALPATH realpath (in, out) #else - abspath (in, out) + abspath (in, out) && stat (out, &st) == 0 #endif ) { diff --git a/src/kmk/getloadavg.c b/src/kmk/getloadavg.c index 38107e6..f9d7964 100644 --- a/src/kmk/getloadavg.c +++ b/src/kmk/getloadavg.c @@ -1,7 +1,7 @@ /* Get the system load averages. Copyright (C) 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, -1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 -Free Software Foundation, Inc. +1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +2008, 2009, 2010 Free Software Foundation, Inc. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/src/kmk/getopt.c b/src/kmk/getopt.c index 2956a65..eea1146 100644 --- a/src/kmk/getopt.c +++ b/src/kmk/getopt.c @@ -4,8 +4,8 @@ NOTE: getopt is now part of the C library, so if you don't know what before changing it! Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, -1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. @@ -679,16 +679,18 @@ _getopt_internal (int argc, char *const *argv, const char *optstring, else { if (opterr) - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - _("%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); - else - /* +option or -option */ - fprintf (stderr, - _("%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], pfound->name); + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + } nextchar += strlen (nextchar); diff --git a/src/kmk/getopt.h b/src/kmk/getopt.h index 6350974..dff9998 100644 --- a/src/kmk/getopt.h +++ b/src/kmk/getopt.h @@ -1,7 +1,7 @@ /* Declarations for getopt. Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, -1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, -Inc. +1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free +Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. diff --git a/src/kmk/getopt1.c b/src/kmk/getopt1.c index 0af66e8..429ad4a 100644 --- a/src/kmk/getopt1.c +++ b/src/kmk/getopt1.c @@ -1,7 +1,7 @@ /* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. diff --git a/src/kmk/gettext.h b/src/kmk/gettext.h index a98d1b5..e8b8b3a 100644 --- a/src/kmk/gettext.h +++ b/src/kmk/gettext.h @@ -1,6 +1,6 @@ /* Convenience header for conditional use of GNU <libintl.h>. Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/glob/ChangeLog b/src/kmk/glob/ChangeLog index a6675e0..8f0739c 100644 --- a/src/kmk/glob/ChangeLog +++ b/src/kmk/glob/ChangeLog @@ -1,6 +1,12 @@ +2008-09-28 Juan Manuel Guerrero <juan.guerrero@gmx.de> + + * glob.c (my_realloc) [__DJGPP__]: Don't define, and don't + redefine realloc to call it, since the DJGPP's realloc handles + NULL pointers correctly. + 2007-12-22 Juan Manuel Guerrero <juan.guerrero@gmx.de> (tiny change) - * glob/glob.c [__GNU_LIBRARY__ && __DJGPP__]: Add a realloc + * glob.c [__GNU_LIBRARY__ && __DJGPP__]: Add a realloc declaration that matches the one in the DJGPP libc. 2006-02-24 Eli Zaretskii <eliz@gnu.org> diff --git a/src/kmk/glob/glob.c b/src/kmk/glob/glob.c index ee282c0..a948e41 100644 --- a/src/kmk/glob/glob.c +++ b/src/kmk/glob/glob.c @@ -182,7 +182,7 @@ extern void bcopy (); # define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len) #endif -#if !defined(__GNU_LIBRARY__) && !defined(ELECTRIC_HEAP) && !defined(__APPLE__) /* bird (last two) */ +#if !defined __GNU_LIBRARY__ && !defined __DJGPP__ && !defined ELECTRIC_HEAP && !defined __APPLE__ /* bird (last two) */ # ifdef __GNUC__ __inline # endif @@ -191,9 +191,6 @@ __inline # include <malloc.h> static void * my_realloc (void *p, unsigned int n) -# elif defined(__DJGPP__) -static void * -my_realloc (void *p, size_t n) # else static char * my_realloc (p, n) @@ -209,7 +206,7 @@ my_realloc (p, n) } # define realloc my_realloc # endif /* __SASC */ -#endif /* __GNU_LIBRARY__ */ +#endif /* __GNU_LIBRARY__ || __DJGPP__ */ #if !defined __alloca && !defined __GNU_LIBRARY__ @@ -388,7 +385,7 @@ glob (pattern, flags, errfunc, pglob) { /* Allocate working buffer large enough for our work. Note that we have at least an opening and closing brace. */ - size_t firstc; + size_t firstc; /* bird: correct type. */ char *alt_start; const char *p; const char *next; diff --git a/src/kmk/hash.c b/src/kmk/hash.c index d2c7aa4..1cd44ab 100644 --- a/src/kmk/hash.c +++ b/src/kmk/hash.c @@ -1,5 +1,5 @@ /* hash.c -- hash table maintenance -Copyright (C) 1995, 1999, 2002 Free Software Foundation, Inc. +Copyright (C) 1995, 1999, 2002, 2010 Free Software Foundation, Inc. Written by Greg McGary <gkm@gnu.org> <greg@mcgary.org> GNU Make is free software; you can redistribute it and/or modify it under the @@ -50,8 +50,8 @@ hash_init (struct hash_table *ht, unsigned long size, ht->ht_vec = (void**) CALLOC (struct token *, ht->ht_size); if (ht->ht_vec == 0) { - fprintf (stderr, _("can't allocate %ld bytes for hash table: memory exhausted"), - ht->ht_size * sizeof(struct token *)); + fprintf (stderr, _("can't allocate %lu bytes for hash table: memory exhausted"), + ht->ht_size * (unsigned long) sizeof (struct token *)); exit (1); } @@ -251,7 +251,7 @@ void * hash_insert (struct hash_table *ht, const void *item) { void **slot = hash_find_slot (ht, item); - const void *old_item = slot ? *slot : 0; + const void *old_item = *slot; hash_insert_at (ht, item, slot); return (void *)((HASH_VACANT (old_item)) ? 0 : old_item); } diff --git a/src/kmk/hash.h b/src/kmk/hash.h index 4ca9278..5b54d17 100644 --- a/src/kmk/hash.h +++ b/src/kmk/hash.h @@ -1,5 +1,5 @@ /* hash.h -- decls for hash table -Copyright (C) 1995, 1999, 2002 Free Software Foundation, Inc. +Copyright (C) 1995, 1999, 2002, 2010 Free Software Foundation, Inc. Written by Greg McGary <gkm@gnu.org> <greg@mcgary.org> GNU Make is free software; you can redistribute it and/or modify it under the @@ -96,6 +96,9 @@ extern void *hash_deleted_item; /* hash and comparison macros for case-sensitive string keys. */ +/* Due to the strcache, it's not uncommon for the string pointers to + be identical. Take advantage of that to short-circuit string compares. */ + #define STRING_HASH_1(KEY, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ while (*++_key_) \ @@ -119,10 +122,10 @@ extern void *hash_deleted_item; } while (0) #define STRING_COMPARE(X, Y, RESULT) do { \ - RESULT = strcmp ((X), (Y)); \ + RESULT = (X) == (Y) ? 0 : strcmp ((X), (Y)); \ } while (0) #define return_STRING_COMPARE(X, Y) do { \ - return strcmp ((X), (Y)); \ + return (X) == (Y) ? 0 : strcmp ((X), (Y)); \ } while (0) @@ -155,10 +158,10 @@ extern void *hash_deleted_item; } while (0) #define STRING_N_COMPARE(X, Y, N, RESULT) do { \ - RESULT = strncmp ((X), (Y), (N)); \ + RESULT = (X) == (Y) ? 0 : strncmp ((X), (Y), (N)); \ } while (0) #define return_STRING_N_COMPARE(X, Y, N) do { \ - return strncmp ((X), (Y), (N)); \ + return (X) == (Y) ? 0 : strncmp ((X), (Y), (N)); \ } while (0) #ifdef HAVE_CASE_INSENSITIVE_FS @@ -188,10 +191,10 @@ extern void *hash_deleted_item; } while (0) #define ISTRING_COMPARE(X, Y, RESULT) do { \ - RESULT = strcasecmp ((X), (Y)); \ + RESULT = (X) == (Y) ? 0 : strcasecmp ((X), (Y)); \ } while (0) #define return_ISTRING_COMPARE(X, Y) do { \ - return strcasecmp ((X), (Y)); \ + return (X) == (Y) ? 0 : strcasecmp ((X), (Y)); \ } while (0) #else diff --git a/src/kmk/implicit.c b/src/kmk/implicit.c index 81a4fc4..0f55b81 100644 --- a/src/kmk/implicit.c +++ b/src/kmk/implicit.c @@ -1,7 +1,7 @@ /* Implicit rule searching for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -47,7 +47,7 @@ try_implicit_rule (struct file *file, unsigned int depth) if (pattern_search (file, 0, depth, 0)) return 1; -#ifndef NO_ARCHIVES +#ifndef NO_ARCHIVES /* If this is an archive member reference, use just the archive member name to search for implicit rules. */ if (ar_name (file->name)) @@ -55,7 +55,7 @@ try_implicit_rule (struct file *file, unsigned int depth) DBF (DB_IMPLICIT, _("Looking for archive-member implicit rule for `%s'.\n")); if (pattern_search (file, 1, depth, 0)) - return 1; + return 1; } #endif @@ -63,44 +63,11 @@ try_implicit_rule (struct file *file, unsigned int depth) } -#ifdef CONFIG_WITH_ALLOC_CACHES -struct alloccache idep_cache; -#endif - -/* Struct idep captures information about implicit prerequisites - that come from implicit rules. */ -struct idep -{ - struct idep *next; /* struct dep -compatible interface */ - const char *name; /* name of the prerequisite */ - struct file *intermediate_file; /* intermediate file, 0 otherwise */ - const char *intermediate_pattern; /* pattern for intermediate file */ - unsigned char had_stem; /* had % substituted with stem */ - unsigned char ignore_mtime; /* ignore_mtime flag */ -}; - -static void -free_idep_chain (struct idep *p) -{ - struct idep *n; - - for (; p != 0; p = n) - { - n = p->next; -#ifndef CONFIG_WITH_ALLOC_CACHES - free (p); -#else - alloccache_free (&idep_cache, p); -#endif - } -} - - /* Scans the BUFFER for the next word with whitespace as a separator. Returns the pointer to the beginning of the word. LENGTH hold the length of the word. */ -static char * +static const char * get_next_word (const char *buffer, unsigned int *length) { const char *p = buffer, *beg; @@ -178,7 +145,49 @@ get_next_word (const char *buffer, unsigned int *length) if (length) *length = p - beg; - return (char *)beg; + return beg; +} + +/* This structure stores information about the expanded prerequisites for a + pattern rule. NAME is always set to the strcache'd name of the prereq. + FILE and PATTERN will be set for intermediate files only. IGNORE_MTIME is + copied from the prerequisite we expanded. + */ +struct patdeps + { + const char *name; + const char *pattern; + struct file *file; + unsigned int ignore_mtime : 1; + }; + +/* This structure stores information about pattern rules that we need + to try. +*/ +struct tryrule + { + struct rule *rule; + + /* Index of the target in this rule that matched the file. */ + unsigned int matches; + + /* Stem length for this match. */ + unsigned int stemlen; + + /* Definition order of this rule. Used to implement stable sort.*/ + unsigned int order; + + /* Nonzero if the LASTSLASH logic was used in matching this rule. */ + char checked_lastslash; + }; + +int +stemlen_compare (const void *v1, const void *v2) +{ + const struct tryrule *r1 = v1; + const struct tryrule *r2 = v2; + int r = r1->stemlen - r2->stemlen; + return r != 0 ? r : (int)(r1->order - r2->order); } /* Search the pattern rules for a rule with an existing dependency to make @@ -206,20 +215,20 @@ pattern_search (struct file *file, int archive, unsigned int namelen = strlen (filename); /* The last slash in FILENAME (or nil if there is none). */ - char *lastslash; + const char *lastslash; /* This is a file-object used as an argument in recursive calls. It never contains any data except during a recursive call. */ - struct file *intermediate_file = 0; + struct file *int_file = 0; - /* This linked list records all the prerequisites actually - found for a rule along with some other useful information - (see struct idep for details). */ - struct idep* deps = 0; + /* List of dependencies found recursively. */ + struct patdeps *deplist + = xmalloc (max_pattern_deps * sizeof (struct patdeps)); + struct patdeps *pat = deplist; - /* 1 if we need to remove explicit prerequisites, 0 otherwise. */ - unsigned int remove_explicit_deps = 0; + /* All the prerequisites actually found for a rule, after expansion. */ + struct dep *deps; /* Names of possible dependencies are constructed in this buffer. */ char *depname = alloca (namelen + max_pattern_dep_length); @@ -230,78 +239,70 @@ pattern_search (struct file *file, int archive, unsigned int fullstemlen = 0; /* Buffer in which we store all the rules that are possibly applicable. */ - struct rule **tryrules = xmalloc (num_pattern_rules * max_pattern_targets - * sizeof (struct rule *)); + struct tryrule *tryrules = xmalloc (num_pattern_rules * max_pattern_targets + * sizeof (struct tryrule)); /* Number of valid elements in TRYRULES. */ unsigned int nrules; - /* The numbers of the rule targets of each rule - in TRYRULES that matched the target file. */ - unsigned int *matches = alloca (num_pattern_rules * sizeof (unsigned int)); - - /* Each element is nonzero if LASTSLASH was used in - matching the corresponding element of TRYRULES. */ - char *checked_lastslash = alloca (num_pattern_rules * sizeof (char)); - /* The index in TRYRULES of the rule we found. */ unsigned int foundrule; /* Nonzero if should consider intermediate files as dependencies. */ int intermed_ok; + /* Nonzero if we have initialized file variables for this target. */ + int file_vars_initialized = 0; + /* Nonzero if we have matched a pattern-rule target that is not just `%'. */ int specific_rule_matched = 0; + struct dep dep_simple; + unsigned int ri; /* uninit checks OK */ struct rule *rule; - struct dep *dep, *expl_d; - struct idep *d; - struct idep **id_ptr; - struct dep **d_ptr; + char *pathdir = NULL; + unsigned long pathlen; PATH_VAR (stem_str); /* @@ Need to get rid of stem, stemlen, etc. */ -#ifdef CONFIG_WITH_ALLOC_CACHES - if (!idep_cache.size) - alloccache_init (&idep_cache, sizeof (struct idep), "idep", NULL, NULL); -#endif - -#ifndef NO_ARCHIVES +#ifndef NO_ARCHIVES if (archive || ar_name (filename)) lastslash = 0; else #endif { /* Set LASTSLASH to point at the last slash in FILENAME - but not counting any slash at the end. (foo/bar/ counts as - bar/ in directory foo/, not empty in directory foo/bar/.) */ + but not counting any slash at the end. (foo/bar/ counts as + bar/ in directory foo/, not empty in directory foo/bar/.) */ #ifdef VMS lastslash = strrchr (filename, ']'); if (lastslash == 0) - lastslash = strrchr (filename, ':'); + lastslash = strrchr (filename, ':'); #else lastslash = strrchr (filename, '/'); #ifdef HAVE_DOS_PATHS /* Handle backslashes (possibly mixed with forward slashes) - and the case of "d:file". */ + and the case of "d:file". */ { - char *bslash = strrchr (filename, '\\'); - if (lastslash == 0 || bslash > lastslash) - lastslash = bslash; - if (lastslash == 0 && filename[0] && filename[1] == ':') - lastslash = (char *)filename + 1; + char *bslash = strrchr (filename, '\\'); + if (lastslash == 0 || bslash > lastslash) + lastslash = bslash; + if (lastslash == 0 && filename[0] && filename[1] == ':') + lastslash = filename + 1; } #endif #endif if (lastslash != 0 && lastslash[1] == '\0') - lastslash = 0; + lastslash = 0; } - /* First see which pattern rules match this target - and may be considered. Put them in TRYRULES. */ + pathlen = lastslash - filename + 1; + + /* First see which pattern rules match this target and may be considered. + Put them in TRYRULES. */ nrules = 0; for (rule = pattern_rules; rule != 0; rule = rule->next) @@ -309,41 +310,41 @@ pattern_search (struct file *file, int archive, unsigned int ti; /* If the pattern rule has deps but no commands, ignore it. - Users cancel built-in rules by redefining them without commands. */ + Users cancel built-in rules by redefining them without commands. */ if (rule->deps != 0 && rule->cmds == 0) - continue; + continue; /* If this rule is in use by a parent pattern_search, - don't use it here. */ + don't use it here. */ if (rule->in_use) - { - DBS (DB_IMPLICIT, (_("Avoiding implicit rule recursion.\n"))); - continue; - } + { + DBS (DB_IMPLICIT, (_("Avoiding implicit rule recursion.\n"))); + continue; + } for (ti = 0; ti < rule->num; ++ti) - { - const char *target = rule->targets[ti]; - const char *suffix = rule->suffixes[ti]; - int check_lastslash; + { + const char *target = rule->targets[ti]; + const char *suffix = rule->suffixes[ti]; + int check_lastslash; - /* Rules that can match any filename and are not terminal - are ignored if we're recursing, so that they cannot be - intermediate files. */ - if (recursions > 0 && target[1] == '\0' && !rule->terminal) - continue; + /* Rules that can match any filename and are not terminal + are ignored if we're recursing, so that they cannot be + intermediate files. */ + if (recursions > 0 && target[1] == '\0' && !rule->terminal) + continue; - if (rule->lens[ti] > namelen) - /* It can't possibly match. */ - continue; + if (rule->lens[ti] > namelen) + /* It can't possibly match. */ + continue; - /* From the lengths of the filename and the pattern parts, - find the stem: the part of the filename that matches the %. */ - stem = filename + (suffix - target - 1); - stemlen = namelen - rule->lens[ti] + 1; + /* From the lengths of the filename and the pattern parts, + find the stem: the part of the filename that matches the %. */ + stem = filename + (suffix - target - 1); + stemlen = namelen - rule->lens[ti] + 1; - /* Set CHECK_LASTSLASH if FILENAME contains a directory - prefix and the target pattern does not contain a slash. */ + /* Set CHECK_LASTSLASH if FILENAME contains a directory + prefix and the target pattern does not contain a slash. */ check_lastslash = 0; if (lastslash) @@ -363,487 +364,491 @@ pattern_search (struct file *file, int archive, #endif #endif } - if (check_lastslash) - { - /* If so, don't include the directory prefix in STEM here. */ - unsigned int difference = lastslash - filename + 1; - if (difference > stemlen) - continue; - stemlen -= difference; - stem += difference; - } - - /* Check that the rule pattern matches the text before the stem. */ - if (check_lastslash) - { - if (stem > (lastslash + 1) - && !strneq (target, lastslash + 1, stem - lastslash - 1)) - continue; - } - else if (stem > filename - && !strneq (target, filename, stem - filename)) - continue; - - /* Check that the rule pattern matches the text after the stem. - We could test simply use streq, but this way we compare the - first two characters immediately. This saves time in the very - common case where the first character matches because it is a - period. */ - if (*suffix != stem[stemlen] - || (*suffix != '\0' && !streq (&suffix[1], &stem[stemlen + 1]))) - continue; - - /* Record if we match a rule that not all filenames will match. */ - if (target[1] != '\0') - specific_rule_matched = 1; - - /* A rule with no dependencies and no commands exists solely to set - specific_rule_matched when it matches. Don't try to use it. */ - if (rule->deps == 0 && rule->cmds == 0) - continue; - - /* Record this rule in TRYRULES and the index of the matching - target in MATCHES. If several targets of the same rule match, - that rule will be in TRYRULES more than once. */ - tryrules[nrules] = rule; - matches[nrules] = ti; - checked_lastslash[nrules] = check_lastslash; - ++nrules; - } + if (check_lastslash) + { + /* If so, don't include the directory prefix in STEM here. */ + if (pathlen > stemlen) + continue; + stemlen -= pathlen; + stem += pathlen; + } + + /* Check that the rule pattern matches the text before the stem. */ + if (check_lastslash) + { + if (stem > (lastslash + 1) + && !strneq (target, lastslash + 1, stem - lastslash - 1)) + continue; + } + else if (stem > filename + && !strneq (target, filename, stem - filename)) + continue; + + /* Check that the rule pattern matches the text after the stem. + We could test simply use streq, but this way we compare the + first two characters immediately. This saves time in the very + common case where the first character matches because it is a + period. */ + if (*suffix != stem[stemlen] + || (*suffix != '\0' && !streq (&suffix[1], &stem[stemlen + 1]))) + continue; + + /* Record if we match a rule that not all filenames will match. */ + if (target[1] != '\0') + specific_rule_matched = 1; + + /* A rule with no dependencies and no commands exists solely to set + specific_rule_matched when it matches. Don't try to use it. */ + if (rule->deps == 0 && rule->cmds == 0) + continue; + + /* Record this rule in TRYRULES and the index of the matching + target in MATCHES. If several targets of the same rule match, + that rule will be in TRYRULES more than once. */ + tryrules[nrules].rule = rule; + tryrules[nrules].matches = ti; + tryrules[nrules].stemlen = stemlen + (check_lastslash ? pathlen : 0); + tryrules[nrules].order = nrules; + tryrules[nrules].checked_lastslash = check_lastslash; + ++nrules; + } } + /* Bail out early if we haven't found any rules. */ + if (nrules == 0) + goto done; + + /* Sort the rules to place matches with the shortest stem first. This + way the most specific rules will be tried first. */ + if (nrules > 1) + qsort (tryrules, nrules, sizeof (struct tryrule), stemlen_compare); + /* If we have found a matching rule that won't match all filenames, retroactively reject any non-"terminal" rules that do always match. */ if (specific_rule_matched) for (ri = 0; ri < nrules; ++ri) - if (!tryrules[ri]->terminal) - { - unsigned int j; - for (j = 0; j < tryrules[ri]->num; ++j) - if (tryrules[ri]->targets[j][1] == '\0') + if (!tryrules[ri].rule->terminal) + { + unsigned int j; + for (j = 0; j < tryrules[ri].rule->num; ++j) + if (tryrules[ri].rule->targets[j][1] == '\0') { - tryrules[ri] = 0; + tryrules[ri].rule = 0; break; } - } - - /* We are going to do second expansion so initialize file variables - for the rule. */ - initialize_file_variables (file, 0); + } /* Try each rule once without intermediate files, then once with them. */ - for (intermed_ok = 0; intermed_ok == !!intermed_ok; ++intermed_ok) + for (intermed_ok = 0; intermed_ok < 2; ++intermed_ok) { - /* Try each pattern rule till we find one that applies. - If it does, expand its dependencies (as substituted) - and chain them in DEPS. */ + pat = deplist; + /* Try each pattern rule till we find one that applies. If it does, + expand its dependencies (as substituted) and chain them in DEPS. */ for (ri = 0; ri < nrules; ri++) - { - struct file *f; + { + struct dep *dep; + int check_lastslash; unsigned int failed = 0; - int check_lastslash; int file_variables_set = 0; + unsigned int deps_found = 0; + /* NPTR points to the part of the prereq we haven't processed. */ + const char *nptr = 0; + const char *dir = NULL; + int order_only = 0; + unsigned int matches; + + rule = tryrules[ri].rule; + + /* RULE is nil when we discover that a rule, already placed in + TRYRULES, should not be applied. */ + if (rule == 0) + continue; + + /* Reject any terminal rules if we're looking to make intermediate + files. */ + if (intermed_ok && rule->terminal) + continue; + + /* From the lengths of the filename and the matching pattern parts, + find the stem: the part of the filename that matches the %. */ + matches = tryrules[ri].matches; + stem = filename + (rule->suffixes[matches] + - rule->targets[matches]) - 1; + stemlen = (namelen - rule->lens[matches]) + 1; + check_lastslash = tryrules[ri].checked_lastslash; + if (check_lastslash) + { + stem += pathlen; + stemlen -= pathlen; + + /* We need to add the directory prefix, so set it up. */ + if (! pathdir) + { + pathdir = alloca (pathlen + 1); + memcpy (pathdir, filename, pathlen); + pathdir[pathlen] = '\0'; + } + dir = pathdir; + } - rule = tryrules[ri]; - - remove_explicit_deps = 0; - - /* RULE is nil when we discover that a rule, - already placed in TRYRULES, should not be applied. */ - if (rule == 0) - continue; - - /* Reject any terminal rules if we're - looking to make intermediate files. */ - if (intermed_ok && rule->terminal) - continue; - - /* Mark this rule as in use so a recursive - pattern_search won't try to use it. */ - rule->in_use = 1; - - /* From the lengths of the filename and the matching pattern parts, - find the stem: the part of the filename that matches the %. */ - stem = filename - + (rule->suffixes[matches[ri]] - rule->targets[matches[ri]]) - 1; - stemlen = namelen - rule->lens[matches[ri]] + 1; - check_lastslash = checked_lastslash[ri]; - if (check_lastslash) - { - stem += lastslash - filename + 1; - stemlen -= (lastslash - filename) + 1; - } - - DBS (DB_IMPLICIT, (_("Trying pattern rule with stem `%.*s'.\n"), + DBS (DB_IMPLICIT, (_("Trying pattern rule with stem `%.*s'.\n"), (int) stemlen, stem)); strncpy (stem_str, stem, stemlen); stem_str[stemlen] = '\0'; + /* If there are no prerequisites, then this rule matches. */ + if (rule->deps == 0) + break; + /* Temporary assign STEM to file->stem (needed to set file variables below). */ file->stem = stem_str; - /* Try each dependency; see if it "exists". */ + /* Mark this rule as in use so a recursive pattern_search won't try + to use it. */ + rule->in_use = 1; - for (dep = rule->deps; dep != 0; dep = dep->next) - { - unsigned int len; - char *p; - char *p2; - unsigned int order_only = 0; /* Set if '|' was seen. */ - - /* In an ideal world we would take the dependency line, - substitute the stem, re-expand the whole line and chop it - into individual prerequisites. Unfortunately this won't work - because of the "check_lastslash" twist. Instead, we will - have to go word by word, taking $()'s into account, for each - word we will substitute the stem, re-expand, chop it up, and, - if check_lastslash != 0, add the directory part to each - resulting prerequisite. */ + /* Try each prerequisite; see if it exists or can be created. We'll + build a list of prereq info in DEPLIST. Due to 2nd expansion we + may have to process multiple prereqs for a single dep entry. */ - p = get_next_word (dep->name, &len); + pat = deplist; + dep = rule->deps; + nptr = dep_name (dep); + while (1) + { + struct dep *dl, *d; + char *p; - while (1) + /* If we're out of name to parse, start the next prereq. */ + if (! nptr) { - int add_dir = 0; - int had_stem = 0; + dep = dep->next; + if (dep == 0) + break; + nptr = dep_name (dep); + } + /* If we don't need a second expansion, just replace the %. */ + if (! dep->need_2nd_expansion) + { + dep_simple = *dep; + dep_simple.next = 0; + p = strchr (nptr, '%'); if (p == 0) - break; /* No more words */ - - /* Is there a pattern in this prerequisite? */ - - for (p2 = p; p2 < p + len && *p2 != '%'; ++p2) - ; - - if (dep->need_2nd_expansion) + dep_simple.name = nptr; + else { - /* If the dependency name has %, substitute the stem. + char *o = depname; + if (check_lastslash) + { + memcpy (o, filename, pathlen); + o += pathlen; + } + memcpy (o, nptr, p - nptr); + o += p - nptr; + memcpy (o, stem_str, stemlen); + o += stemlen; + strcpy (o, p + 1); + dep_simple.name = strcache_add (depname); + } + dl = &dep_simple; - Watch out, we are going to do something tricky - here. If we just replace % with the stem value, - later, when we do the second expansion, we will - re-expand this stem value once again. This is not - good especially if you have certain characters in - your stem (like $). + /* We've used up this dep, so next time get a new one. */ + nptr = 0; + ++deps_found; + } - Instead, we will replace % with $* and allow the - second expansion to take care of it for us. This way - (since $* is a simple variable) there won't be - additional re-expansion of the stem. */ + /* We have to perform second expansion on this prereq. In an + ideal world we would take the dependency line, substitute the + stem, re-expand the whole line and chop it into individual + prerequisites. Unfortunately this won't work because of the + "check_lastslash" twist. Instead, we will have to go word by + word, taking $()'s into account. For each word we will + substitute the stem, re-expand, chop it up, and, if + check_lastslash != 0, add the directory part to each + resulting prerequisite. */ + else + { + int add_dir = 0; + unsigned int len; - if (p2 < p + len) - { - unsigned int i = p2 - p; - memcpy (depname, p, i); - memcpy (depname + i, "$*", 2); - memcpy (depname + i + 2, p2 + 1, len - i - 1); - depname[len + 2 - 1] = '\0'; + nptr = get_next_word (nptr, &len); + if (nptr == 0) + continue; - if (check_lastslash) - add_dir = 1; + /* See this is a transition to order-only prereqs. */ + if (! order_only && len == 1 && nptr[0] == '|') + { + order_only = 1; + nptr += len; + continue; + } - had_stem = 1; - } - else - { - memcpy (depname, p, len); - depname[len] = '\0'; - } + /* If the dependency name has %, substitute the stem. If we + just replace % with the stem value then later, when we do + the 2nd expansion, we will re-expand this stem value + again. This is not good if you have certain characters + in your stem (like $). - /* Set file variables. Note that we cannot do it once - at the beginning of the function because of the stem - value. */ - if (!file_variables_set) - { -#if defined(CONFIG_WITH_COMMANDS_FUNC) || defined (CONFIG_WITH_DOT_MUST_MAKE) - set_file_variables (file, 0 /* real call */); -#else - set_file_variables (file); -#endif - file_variables_set = 1; - } + Instead, we will replace % with $* and allow the second + expansion to take care of it for us. This way (since $* + is a simple variable) there won't be additional + re-expansion of the stem. */ - p2 = variable_expand_for_file (depname, file); + p = lindex (nptr, nptr + len, '%'); + if (p == 0) + { + memcpy (depname, nptr, len); + depname[len] = '\0'; } else { - if (p2 < p + len) - { - unsigned int i = p2 - p; - memcpy (depname, p, i); - memcpy (depname + i, stem_str, stemlen); - memcpy (depname + i + stemlen, p2 + 1, len - i - 1); - depname[len + stemlen - 1] = '\0'; - - if (check_lastslash) - add_dir = 1; - - had_stem = 1; - } - else - { - memcpy (depname, p, len); - depname[len] = '\0'; - } - - p2 = depname; + unsigned int i = p - nptr; + memcpy (depname, nptr, i); + memcpy (depname + i, "$*", 2); + memcpy (depname + i + 2, p + 1, len - i - 1); + depname[len + 2 - 1] = '\0'; + + if (check_lastslash) + add_dir = 1; } - /* Parse the dependencies. */ - - while (1) + /* Initialize and set file variables if we haven't already + done so. */ + if (!file_vars_initialized) { - id_ptr = &deps; - - for (; *id_ptr; id_ptr = &(*id_ptr)->next) - ; - -#ifndef CONFIG_WITH_ALLOC_CACHES - *id_ptr = (struct idep *) - multi_glob ( - parse_file_seq (&p2, - order_only ? '\0' : '|', - sizeof (struct idep), - 1), sizeof (struct idep)); + initialize_file_variables (file, 0); +#if defined(CONFIG_WITH_COMMANDS_FUNC) || defined (CONFIG_WITH_DOT_MUST_MAKE) + set_file_variables (file, 0 /* real call */); #else - *id_ptr = (struct idep *) - multi_glob ( - parse_file_seq (&p2, - order_only ? '\0' : '|', - &idep_cache, 1), - &idep_cache); + set_file_variables (file); #endif + file_vars_initialized = 1; + } + /* Update the stem value in $* for this rule. */ + else if (!file_variables_set) + { + define_variable_for_file ( + "*", 1, file->stem, o_automatic, 0, file); + file_variables_set = 1; + } - /* @@ It would be nice to teach parse_file_seq or - multi_glob to add prefix. This would save us some - reallocations. */ - - if (order_only || add_dir || had_stem) - { - unsigned long l = lastslash - filename + 1; - - for (d = *id_ptr; d != 0; d = d->next) - { - if (order_only) - d->ignore_mtime = 1; - - if (add_dir) - { - char *n = alloca (strlen (d->name) + l + 1); - memcpy (n, filename, l); - memcpy (n+l, d->name, strlen (d->name) + 1); - d->name = strcache_add (n); - } - - if (had_stem) - d->had_stem = 1; - } - } + /* Perform the 2nd expansion. */ + p = variable_expand_for_file (depname, file); - if (!order_only && *p2) - { - ++p2; - order_only = 1; - continue; - } + /* Parse the expanded string. */ + dl = PARSE_FILE_SEQ (&p, struct dep, order_only ? '\0' : '|', + add_dir ? dir : NULL, 0); - break; + for (d = dl; d != NULL; d = d->next) + { + ++deps_found; + if (order_only) + d->ignore_mtime = 1; } - p += len; - p = get_next_word (p, &len); + /* Set up for the next word. */ + nptr += len; } - } - - /* Reset the stem in FILE. */ - - file->stem = 0; - /* @@ This loop can be combined with the previous one. I do - it separately for now for transparency.*/ + /* If there are more than max_pattern_deps prerequisites (due to + 2nd expansion), reset it and realloc the arrays. */ - for (d = deps; d != 0; d = d->next) - { - const char *name = d->name; + if (deps_found > max_pattern_deps) + { + unsigned int l = pat - deplist; + deplist = xrealloc (deplist, + deps_found * sizeof (struct patdeps)); + pat = deplist + l; + max_pattern_deps = deps_found; + } - if (file_impossible_p (name)) + /* Go through the nameseq and handle each as a prereq name. */ + for (d = dl; d != 0; d = d->next) { - /* If this dependency has already been ruled "impossible", - then the rule fails and don't bother trying it on the - second pass either since we know that will fail too. */ - DBS (DB_IMPLICIT, - (d->had_stem - ? _("Rejecting impossible implicit prerequisite `%s'.\n") - : _("Rejecting impossible rule prerequisite `%s'.\n"), - name)); - tryrules[ri] = 0; + struct dep *expl_d; + int is_rule = d->name == dep_name (dep); - failed = 1; - break; - } + if (file_impossible_p (d->name)) + { + /* If this prereq has already been ruled "impossible", + then the rule fails. Don't bother trying it on the + second pass either since we know that will fail. */ + DBS (DB_IMPLICIT, + (is_rule + ? _("Rejecting impossible rule prerequisite `%s'.\n") + : _("Rejecting impossible implicit prerequisite `%s'.\n"), + d->name)); + tryrules[ri].rule = 0; + + failed = 1; + break; + } - DBS (DB_IMPLICIT, - (d->had_stem - ? _("Trying implicit prerequisite `%s'.\n") - : _("Trying rule prerequisite `%s'.\n"), name)); + memset (pat, '\0', sizeof (struct patdeps)); + pat->ignore_mtime = d->ignore_mtime; - /* If this prerequisite also happened to be explicitly mentioned - for FILE skip all the test below since it it has to be built - anyway, no matter which implicit rule we choose. */ + DBS (DB_IMPLICIT, + (is_rule + ? _("Trying rule prerequisite `%s'.\n") + : _("Trying implicit prerequisite `%s'.\n"), d->name)); - for (expl_d = file->deps; expl_d != 0; expl_d = expl_d->next) - if (streq (dep_name (expl_d), name)) - break; - if (expl_d != 0) - continue; + /* If this prereq is also explicitly mentioned for FILE, + skip all tests below since it must be built no matter + which implicit rule we choose. */ - /* The DEP->changed flag says that this dependency resides in a - nonexistent directory. So we normally can skip looking for - the file. However, if CHECK_LASTSLASH is set, then the - dependency file we are actually looking for is in a different - directory (the one gotten by prepending FILENAME's directory), - so it might actually exist. */ - - /* @@ dep->changed check is disabled. */ - if (((f = lookup_file (name)) != 0 && f->is_target) - /*|| ((!dep->changed || check_lastslash) && */ - || file_exists_p (name)) - continue; + for (expl_d = file->deps; expl_d != 0; expl_d = expl_d->next) + if (streq (dep_name (expl_d), d->name)) + break; + if (expl_d != 0) + { + (pat++)->name = d->name; + continue; + } - /* This code, given FILENAME = "lib/foo.o", dependency name - "lib/foo.c", and VPATH=src, searches for "src/lib/foo.c". */ - { - const char *vname = vpath_search (name, 0); - if (vname) + /* The DEP->changed flag says that this dependency resides + in a nonexistent directory. So we normally can skip + looking for the file. However, if CHECK_LASTSLASH is + set, then the dependency file we are actually looking for + is in a different directory (the one gotten by prepending + FILENAME's directory), so it might actually exist. */ + + /* @@ dep->changed check is disabled. */ + if (lookup_file (d->name) != 0 + /*|| ((!dep->changed || check_lastslash) && */ + || file_exists_p (d->name)) + { + (pat++)->name = d->name; + continue; + } + + /* This code, given FILENAME = "lib/foo.o", dependency name + "lib/foo.c", and VPATH=src, searches for + "src/lib/foo.c". */ { - DBS (DB_IMPLICIT, - (_("Found prerequisite `%s' as VPATH `%s'\n"), - name, vname)); - continue; + const char *vname = vpath_search (d->name, 0, NULL, NULL); + if (vname) + { + DBS (DB_IMPLICIT, + (_("Found prerequisite `%s' as VPATH `%s'\n"), + d->name, vname)); + (pat++)->name = d->name; + continue; + } } - } + /* We could not find the file in any place we should look. + Try to make this dependency as an intermediate file, but + only on the second pass. */ - /* We could not find the file in any place we should look. Try - to make this dependency as an intermediate file, but only on - the second pass. */ - - if (intermed_ok) - { - if (intermediate_file == 0) - intermediate_file = alloca (sizeof (struct file)); - - DBS (DB_IMPLICIT, - (_("Looking for a rule with intermediate file `%s'.\n"), - name)); - - memset (intermediate_file, '\0', sizeof (struct file)); - intermediate_file->name = name; - if (pattern_search (intermediate_file, - 0, - depth + 1, - recursions + 1)) + if (intermed_ok) { - d->intermediate_pattern = intermediate_file->name; - intermediate_file->name = strcache_add (name); - d->intermediate_file = intermediate_file; - intermediate_file = 0; + DBS (DB_IMPLICIT, + (_("Looking for a rule with intermediate file `%s'.\n"), + d->name)); + + if (int_file == 0) + int_file = alloca (sizeof (struct file)); + memset (int_file, '\0', sizeof (struct file)); + int_file->name = d->name; + + if (pattern_search (int_file, + 0, + depth + 1, + recursions + 1)) + { + pat->pattern = int_file->name; + int_file->name = d->name; + pat->file = int_file; + (pat++)->name = d->name; + int_file = 0; + continue; + } - continue; + /* If we have tried to find P as an intermediate file + and failed, mark that name as impossible so we won't + go through the search again later. */ + if (int_file->variables) + free_variable_set (int_file->variables); + if (int_file->pat_variables) + free_variable_set (int_file->pat_variables); + file_impossible (d->name); } - /* If we have tried to find P as an intermediate - file and failed, mark that name as impossible - so we won't go through the search again later. */ - if (intermediate_file->variables) - free_variable_set (intermediate_file->variables); - file_impossible (name); + /* A dependency of this rule does not exist. Therefore, this + rule fails. */ + failed = 1; + break; } - /* A dependency of this rule does not exist. Therefore, - this rule fails. */ - failed = 1; - break; + /* Free the ns chain. */ + if (dl != &dep_simple) + free_dep_chain (dl); + + if (failed) + break; } + /* Reset the stem in FILE. */ + + file->stem = 0; + /* This rule is no longer `in use' for recursive searches. */ - rule->in_use = 0; + rule->in_use = 0; - if (failed) - { - /* This pattern rule does not apply. If some of its - dependencies succeeded, free the data structure - describing them. */ - free_idep_chain (deps); - deps = 0; - } - else - /* This pattern rule does apply. Stop looking for one. */ - break; - } + if (! failed) + /* This pattern rule does apply. Stop looking for one. */ + break; - /* If we found an applicable rule without - intermediate files, don't try with them. */ + /* This pattern rule does not apply. If some of its dependencies + succeeded, free the data structure describing them. */ + /* free_idep_chain (deps); */ + deps = 0; + } + + /* If we found an applicable rule without intermediate files, don't try + with them. */ if (ri < nrules) - break; + break; rule = 0; } - /* RULE is nil if the loop went all the way - through the list and everything failed. */ + /* RULE is nil if the loop went through the list but everything failed. */ if (rule == 0) goto done; foundrule = ri; - /* If we are recursing, store the pattern that matched - FILENAME in FILE->name for use in upper levels. */ + /* If we are recursing, store the pattern that matched FILENAME in + FILE->name for use in upper levels. */ if (recursions > 0) /* Kludge-o-matic */ - file->name = rule->targets[matches[foundrule]]; - - /* FOUND_FILES lists the dependencies for the rule we found. - This includes the intermediate files, if any. - Convert them into entries on the deps-chain of FILE. */ - - if (remove_explicit_deps) - { - /* Remove all the dependencies that didn't come from - this implicit rule. */ + file->name = rule->targets[tryrules[foundrule].matches]; - dep = file->deps; - while (dep != 0) - { - struct dep *next = dep->next; - free_dep (dep); - dep = next; - } - file->deps = 0; - } + /* DEPLIST lists the prerequisites for the rule we found. This includes the + intermediate files, if any. Convert them into entries on the deps-chain + of FILE. */ - expl_d = file->deps; /* We will add them at the end. */ - d_ptr = &file->deps; - - for (d = deps; d != 0; d = d->next) + while (pat-- > deplist) { + struct dep *dep; const char *s; - if (d->intermediate_file != 0) - { - /* If we need to use an intermediate file, - make sure it is entered as a target, with the info that was - found for it in the recursive pattern_search call. - We know that the intermediate file did not already exist as - a target; therefore we can assume that the deps and cmds - of F below are null before we change them. */ + if (pat->file != 0) + { + /* If we need to use an intermediate file, make sure it is entered + as a target, with the info that was found for it in the recursive + pattern_search call. We know that the intermediate file did not + already exist as a target; therefore we can assume that the deps + and cmds of F below are null before we change them. */ - struct file *imf = d->intermediate_file; - register struct file *f = lookup_file (imf->name); + struct file *imf = pat->file; + struct file *f = lookup_file (imf->name); /* We don't want to delete an intermediate file that happened to be a prerequisite of some (other) target. Mark it as @@ -851,67 +856,64 @@ pattern_search (struct file *file, int archive, if (f != 0) f->precious = 1; else - f = enter_file (strcache_add (imf->name)); - - f->deps = imf->deps; - f->cmds = imf->cmds; - f->stem = imf->stem; + f = enter_file (imf->name); + + f->deps = imf->deps; + f->cmds = imf->cmds; + f->stem = imf->stem; + f->variables = imf->variables; + f->pat_variables = imf->pat_variables; + f->pat_searched = imf->pat_searched; f->also_make = imf->also_make; f->is_target = 1; + f->intermediate = 1; + f->tried_implicit = 1; - if (!f->precious) + imf = lookup_file (pat->pattern); + if (imf != 0 && imf->precious) + f->precious = 1; + + for (dep = f->deps; dep != 0; dep = dep->next) { - imf = lookup_file (d->intermediate_pattern); - if (imf != 0 && imf->precious) - f->precious = 1; + dep->file = enter_file (dep->name); + dep->name = 0; + dep->file->tried_implicit |= dep->changed; } - - f->intermediate = 1; - f->tried_implicit = 1; - for (dep = f->deps; dep != 0; dep = dep->next) - { - dep->file = enter_file (dep->name); - dep->name = 0; - dep->file->tried_implicit |= dep->changed; - } - } + } dep = alloc_dep (); - dep->ignore_mtime = d->ignore_mtime; - s = d->name; /* Hijacking the name. */ - d->name = 0; - if (recursions == 0) - { - dep->file = lookup_file (s); - if (dep->file == 0) - dep->file = enter_file (s); - } - else + dep->ignore_mtime = pat->ignore_mtime; + s = strcache_add (pat->name); + if (recursions) dep->name = s; + else + { + dep->file = lookup_file (s); + if (dep->file == 0) + dep->file = enter_file (s); + } - if (d->intermediate_file == 0 && tryrules[foundrule]->terminal) - { - /* If the file actually existed (was not an intermediate file), - and the rule that found it was a terminal one, then we want - to mark the found file so that it will not have implicit rule - search done for it. If we are not entering a `struct file' for - it now, we indicate this with the `changed' flag. */ - if (dep->file == 0) - dep->changed = 1; - else - dep->file->tried_implicit = 1; - } - - *d_ptr = dep; - d_ptr = &dep->next; - } + if (pat->file == 0 && tryrules[foundrule].rule->terminal) + { + /* If the file actually existed (was not an intermediate file), and + the rule that found it was a terminal one, then we want to mark + the found file so that it will not have implicit rule search done + for it. If we are not entering a `struct file' for it now, we + indicate this with the `changed' flag. */ + if (dep->file == 0) + dep->changed = 1; + else + dep->file->tried_implicit = 1; + } - *d_ptr = expl_d; + dep->next = file->deps; + file->deps = dep; + } - if (!checked_lastslash[foundrule]) + if (!tryrules[foundrule].checked_lastslash) { - /* Always allocate new storage, since STEM might be - on the stack for an intermediate file. */ + /* Always allocate new storage, since STEM might be on the stack for an + intermediate file. */ file->stem = strcache_add_len (stem, stemlen); fullstemlen = stemlen; } @@ -921,7 +923,7 @@ pattern_search (struct file *file, int archive, char *sp; /* We want to prepend the directory from - the original FILENAME onto the stem. */ + the original FILENAME onto the stem. */ fullstemlen = dirlen + stemlen; sp = alloca (fullstemlen + 1); memcpy (sp, filename, dirlen); @@ -939,7 +941,7 @@ pattern_search (struct file *file, int archive, /* Set precious flag. */ { - struct file *f = lookup_file (rule->targets[matches[foundrule]]); + struct file *f = lookup_file (rule->targets[tryrules[foundrule].matches]); if (f && f->precious) file->precious = 1; } @@ -949,40 +951,41 @@ pattern_search (struct file *file, int archive, if (rule->num > 1) for (ri = 0; ri < rule->num; ++ri) - if (ri != matches[foundrule]) - { - char *p = alloca (rule->lens[ri] + fullstemlen + 1); - struct file *f; - struct dep *new = alloc_dep (); - - /* GKM FIMXE: handle '|' here too */ - memcpy (p, rule->targets[ri], + if (ri != tryrules[foundrule].matches) + { + char *nm = alloca (rule->lens[ri] + fullstemlen + 1); + char *p = nm; + struct file *f; + struct dep *new = alloc_dep (); + + /* GKM FIMXE: handle '|' here too */ + memcpy (p, rule->targets[ri], rule->suffixes[ri] - rule->targets[ri] - 1); - p += rule->suffixes[ri] - rule->targets[ri] - 1; - memcpy (p, file->stem, fullstemlen); - p += fullstemlen; - memcpy (p, rule->suffixes[ri], + p += rule->suffixes[ri] - rule->targets[ri] - 1; + memcpy (p, file->stem, fullstemlen); + p += fullstemlen; + memcpy (p, rule->suffixes[ri], rule->lens[ri] - (rule->suffixes[ri] - rule->targets[ri])+1); - new->name = strcache_add (p); - new->file = enter_file (new->name); - new->next = file->also_make; + new->name = strcache_add (nm); + new->file = enter_file (new->name); + new->next = file->also_make; - /* Set precious flag. */ - f = lookup_file (rule->targets[ri]); - if (f && f->precious) + /* Set precious flag. */ + f = lookup_file (rule->targets[ri]); + if (f && f->precious) new->file->precious = 1; - /* Set the is_target flag so that this file is not treated - as intermediate by the pattern rule search algorithm and + /* Set the is_target flag so that this file is not treated as + intermediate by the pattern rule search algorithm and file_exists_p cannot pick it up yet. */ new->file->is_target = 1; - file->also_make = new; - } + file->also_make = new; + } done: - free_idep_chain (deps); free (tryrules); + free (deplist); return rule != 0; } diff --git a/src/kmk/incdep.c b/src/kmk/incdep.c index 4ea55eb..ae9aae7 100644 --- a/src/kmk/incdep.c +++ b/src/kmk/incdep.c @@ -1,5 +1,5 @@ #ifdef CONFIG_WITH_INCLUDEDEP -/* $Id: incdep.c 2546 2011-10-01 19:49:54Z bird $ */ +/* $Id: incdep.c 2591 2012-06-17 20:45:31Z bird $ */ /** @file * incdep - Simple dependency files. */ @@ -113,19 +113,13 @@ struct incdep_variable_def int target_var; }; -struct incdep_recorded_files +struct incdep_recorded_file { - struct incdep_recorded_files *next; + struct incdep_recorded_file *next; /* the parameters */ struct strcache2_entry *filename_entry; /* dep strcache; converted to a nameseq record. */ - const char *pattern; /* NULL */ - const char *pattern_percent; /* NULL */ struct dep *deps; /* All the names are dep strcache entries. */ - unsigned int cmds_started; /* 0 */ - char *commands; /* NULL */ - unsigned int commands_idx; /* 0 */ - int two_colon; /* 0 */ const struct floc *flocp; /* NILF */ }; @@ -148,8 +142,8 @@ struct incdep struct incdep_variable_def *recorded_variable_defs_head; struct incdep_variable_def *recorded_variable_defs_tail; - struct incdep_recorded_files *recorded_files_head; - struct incdep_recorded_files *recorded_files_tail; + struct incdep_recorded_file *recorded_file_head; + struct incdep_recorded_file *recorded_file_tail; #endif char name[1]; @@ -231,6 +225,8 @@ static malloc_zone_t *incdep_zone; *******************************************************************************/ static void incdep_flush_it (struct floc *); static void eval_include_dep_file (struct incdep *, struct floc *); +static void incdep_commit_recorded_file (const char *filename, struct dep *deps, + const struct floc *flocp); /* xmalloc wrapper. @@ -500,7 +496,7 @@ incdep_freeit (struct incdep *cur) #ifdef PARSE_IN_WORKER assert (!cur->recorded_variables_in_set_head); assert (!cur->recorded_variable_defs_head); - assert (!cur->recorded_files_head); + assert (!cur->recorded_file_head); #endif incdep_xfree (cur, cur->file_base); @@ -726,8 +722,8 @@ incdep_init (struct floc *f) unsigned rec_size = sizeof (struct incdep_variable_in_set); if (rec_size < sizeof (struct incdep_variable_def)) rec_size = sizeof (struct incdep_variable_def); - if (rec_size < sizeof (struct incdep_recorded_files)) - rec_size = sizeof (struct incdep_recorded_files); + if (rec_size < sizeof (struct incdep_recorded_file)) + rec_size = sizeof (struct incdep_recorded_file); alloccache_init (&incdep_rec_caches[i], rec_size, "incdep rec", incdep_cache_allocator, (void *)(size_t)i); alloccache_init (&incdep_dep_caches[i], sizeof(struct dep), "incdep dep", @@ -848,7 +844,7 @@ incdep_flush_recorded_instructions (struct incdep *cur) { struct incdep_variable_in_set *rec_vis; struct incdep_variable_def *rec_vd; - struct incdep_recorded_files *rec_f; + struct incdep_recorded_file *rec_f; /* define_variable_in_set */ @@ -897,31 +893,20 @@ incdep_flush_recorded_instructions (struct incdep *cur) /* record_files */ - rec_f = cur->recorded_files_head; - cur->recorded_files_head = cur->recorded_files_tail = NULL; + rec_f = cur->recorded_file_head; + cur->recorded_file_head = cur->recorded_file_tail = NULL; if (rec_f) do { void *free_me = rec_f; struct dep *dep; - struct nameseq *filenames; for (dep = rec_f->deps; dep; dep = dep->next) dep->name = incdep_flush_strcache_entry ((struct strcache2_entry *)dep->name); - filenames = (struct nameseq *) alloccache_alloc (&nameseq_cache); - filenames->next = 0; - filenames->name = incdep_flush_strcache_entry (rec_f->filename_entry); - - record_files (filenames, - rec_f->pattern, - rec_f->pattern_percent, - rec_f->deps, - rec_f->cmds_started, - rec_f->commands, - rec_f->commands_idx, - rec_f->two_colon, - rec_f->flocp); + incdep_commit_recorded_file (incdep_flush_strcache_entry (rec_f->filename_entry), + rec_f->deps, + rec_f->flocp); rec_f = rec_f->next; incdep_free_rec (cur, free_me); @@ -1073,45 +1058,85 @@ incdep_record_variable_def (struct incdep *cur, #endif } -/* Record files.*/ +/* Similar to record_files in read.c, only much much simpler. */ static void -incdep_record_files (struct incdep *cur, - const char *filename, const char *pattern, - const char *pattern_percent, struct dep *deps, - unsigned int cmds_started, char *commands, - unsigned int commands_idx, int two_colon, - const struct floc *flocp) +incdep_commit_recorded_file (const char *filename, struct dep *deps, + const struct floc *flocp) { - if (cur->worker_tid == -1) + struct file *f; + + /* Perform some validations. */ + if (filename[0] == '.' + && ( streq(filename, ".POSIX") + || streq(filename, ".EXPORT_ALL_VARIABLES") + || streq(filename, ".INTERMEDIATE") + || streq(filename, ".LOW_RESOLUTION_TIME") + || streq(filename, ".NOTPARALLEL") + || streq(filename, ".ONESHELL") + || streq(filename, ".PHONY") + || streq(filename, ".PRECIOUS") + || streq(filename, ".SECONDARY") + || streq(filename, ".SECONDTARGETEXPANSION") + || streq(filename, ".SILENT") + || streq(filename, ".SHELLFLAGS") + || streq(filename, ".SUFFIXES") + ) + ) + { + error (flocp, _("reserved filename '%s' used in dependency file, ignored"), filename); + return; + } + + /* Lookup or create an entry in the database. */ + f = enter_file (filename); + if (f->double_colon) + { + error (flocp, _("dependency file '%s' has a double colon entry already, ignoring"), filename); + return; + } + f->is_target = 1; + + /* Append dependencies. */ + deps = enter_prereqs (deps, NULL); + if (deps) { - struct nameseq *filenames = (struct nameseq *) alloccache_alloc (&nameseq_cache); - filenames->next = 0; - filenames->name = filename; - record_files (filenames, pattern, pattern_percent, deps, cmds_started, - commands, commands_idx, two_colon, flocp); + struct dep *last = f->deps; + if (!last) + f->deps = deps; + else + { + while (last->next) + last = last->next; + last->next = deps; + } } +} + +/* Record a file.*/ +static void +incdep_record_file (struct incdep *cur, + const char *filename, + struct dep *deps, + const struct floc *flocp) +{ + if (cur->worker_tid == -1) + incdep_commit_recorded_file (filename, deps, flocp); #ifdef PARSE_IN_WORKER else { - struct incdep_recorded_files *rec = - (struct incdep_recorded_files *) incdep_alloc_rec (cur); + struct incdep_recorded_file *rec = + (struct incdep_recorded_file *) incdep_alloc_rec (cur); rec->filename_entry = (struct strcache2_entry *)filename; - rec->pattern = pattern; - rec->pattern_percent = pattern_percent; rec->deps = deps; - rec->cmds_started = cmds_started; - rec->commands = commands; - rec->commands_idx = commands_idx; - rec->two_colon = two_colon; rec->flocp = flocp; rec->next = NULL; - if (cur->recorded_files_tail) - cur->recorded_files_tail->next = rec; + if (cur->recorded_file_tail) + cur->recorded_file_tail->next = rec; else - cur->recorded_files_head = rec; - cur->recorded_files_tail = rec; + cur->recorded_file_head = rec; + cur->recorded_file_tail = rec; } #endif } @@ -1530,8 +1555,7 @@ eval_include_dep_file (struct incdep *curdep, struct floc *f) } /* enter the file with its dependencies. */ - incdep_record_files (curdep, - filename, NULL, NULL, deps, 0, NULL, 0, 0, f); + incdep_record_file (curdep, filename, deps, f); } } } @@ -1629,8 +1653,8 @@ eval_include_dep (const char *names, struct floc *f, enum incdep_op op) cur->recorded_variables_in_set_tail = NULL; cur->recorded_variable_defs_head = NULL; cur->recorded_variable_defs_tail = NULL; - cur->recorded_files_head = NULL; - cur->recorded_files_tail = NULL; + cur->recorded_file_head = NULL; + cur->recorded_file_tail = NULL; #endif cur->next = NULL; diff --git a/src/kmk/job.c b/src/kmk/job.c index 2cb7468..46c5939 100644 --- a/src/kmk/job.c +++ b/src/kmk/job.c @@ -1,7 +1,7 @@ /* Job execution and handling for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -181,7 +181,7 @@ int wait (); #endif /* Don't have `union wait'. */ -#ifndef HAVE_UNISTD_H +#if !defined(HAVE_UNISTD_H) && !defined(WINDOWS32) # ifndef _MSC_VER /* bird */ int dup2 (); int execve (); @@ -195,6 +195,22 @@ int getgid (); # endif #endif +/* Different systems have different requirements for pid_t. + Plus we have to support gettext string translation... Argh. */ +static const char * +pid2str (pid_t pid) +{ + static char pidstring[100]; +#if defined(WINDOWS32) && (__GNUC__ > 3 || _MSC_VER > 1300) + /* %Id is only needed for 64-builds, which were not supported by + older versions of Windows compilers. */ + sprintf (pidstring, "%Id", pid); +#else + sprintf (pidstring, "%lu", (unsigned long) pid); +#endif + return pidstring; +} + int getloadavg (double loadavg[], int nelem); int start_remote_job (char **argv, char **envp, int stdin_fd, int *is_remote, int *id_ptr, int *used_stdin); @@ -245,7 +261,7 @@ unsigned int jobserver_tokens = 0; * The macro which references this function is defined in make.h. */ int -w32_kill(int pid, int sig) +w32_kill(pid_t pid, int sig) { return ((process_kill((HANDLE)pid, sig) == TRUE) ? 0 : -1); } @@ -258,7 +274,7 @@ static char * create_batch_file (char const *base, int unixy, int *fd) { const char *const ext = unixy ? "sh" : "bat"; - const char *error = NULL; + const char *error_string = NULL; char temp_path[MAXPATHLEN]; /* need to know its length */ unsigned path_size = GetTempPath(sizeof temp_path, temp_path); int path_is_dot = 0; @@ -304,7 +320,7 @@ create_batch_file (char const *base, int unixy, int *fd) else { - error = map_windows32_error_to_string (er); + error_string = map_windows32_error_to_string (er); break; } } @@ -313,7 +329,7 @@ create_batch_file (char const *base, int unixy, int *fd) const unsigned final_size = path_size + size + 1; char *const path = xmalloc (final_size); memcpy (path, temp_path, final_size); - *fd = _open_osfhandle ((long)h, 0); + *fd = _open_osfhandle ((intptr_t)h, 0); if (unixy) { char *p; @@ -327,9 +343,9 @@ create_batch_file (char const *base, int unixy, int *fd) } *fd = -1; - if (error == NULL) - error = _("Cannot create a temporary file\n"); - fatal (NILF, error); + if (error_string == NULL) + error_string = _("Cannot create a temporary file\n"); + fatal (NILF, error_string); /* not reached */ return NULL; @@ -380,6 +396,53 @@ _is_unixy_shell (const char *path) } #endif /* __EMX__ */ +/* determines whether path looks to be a Bourne-like shell. */ +int +is_bourne_compatible_shell (const char *path) +{ + /* list of known unix (Bourne-like) shells */ + const char *unix_shells[] = { + "sh", + "bash", + "ksh", + "rksh", + "zsh", + "ash", + "dash", + NULL + }; + unsigned i, len; + + /* find the rightmost '/' or '\\' */ + const char *name = strrchr (path, '/'); + char *p = strrchr (path, '\\'); + + if (name && p) /* take the max */ + name = (name > p) ? name : p; + else if (p) /* name must be 0 */ + name = p; + else if (!name) /* name and p must be 0 */ + name = path; + + if (*name == '/' || *name == '\\') name++; + + /* this should be able to deal with extensions on Windows-like systems */ + for (i = 0; unix_shells[i] != NULL; i++) { + len = strlen(unix_shells[i]); +#if defined(WINDOWS32) || defined(__MSDOS__) + if ((strncasecmp (name, unix_shells[i], len) == 0) && + (strlen(name) >= len && (name[len] == '\0' || name[len] == '.'))) +#else + if ((strncmp (name, unix_shells[i], len) == 0) && + (strlen(name) >= len && name[len] == '\0')) +#endif + return 1; /* a known unix-style shell */ + } + + /* if not on the list, assume it's not a Bourne-like shell */ + return 0; +} + /* Write an error message describing the exit status given in EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME. @@ -532,16 +595,16 @@ reap_children (int block, int err) if (c->has_status) { completed_child = c; - DB (DB_JOBS, (_("builtin child 0x%08lx (%s) PID %ld %s Status %ld\n"), - (unsigned long int) c, c->file->name, - (long) c->pid, c->remote ? _(" (remote)") : "", + DB (DB_JOBS, (_("builtin child %p (%s) PID %s %s Status %ld\n"), + (void *)c, c->file->name, + pid2str (c->pid), c->remote ? _(" (remote)") : "", (long) c->status)); } else #endif - DB (DB_JOBS, (_("Live child 0x%08lx (%s) PID %ld %s\n"), - (unsigned long int) c, c->file->name, - (long) c->pid, c->remote ? _(" (remote)") : "")); + DB (DB_JOBS, (_("Live child %p (%s) PID %s %s\n"), + (void *)c, c->file->name, pid2str (c->pid), + c->remote ? _(" (remote)") : "")); #ifdef VMS break; #endif @@ -676,8 +739,7 @@ reap_children (int block, int err) e, map_windows32_error_to_string(e)); } else - DB (DB_VERBOSE, ("Main thread handle = 0x%08lx\n", - (unsigned long)main_thread)); + DB (DB_VERBOSE, ("Main thread handle = %p\n", main_thread)); } /* wait for anything to finish */ @@ -740,10 +802,9 @@ reap_children (int block, int err) continue; DB (DB_JOBS, (child_failed - ? _("Reaping losing child 0x%08lx PID %ld %s\n") - : _("Reaping winning child 0x%08lx PID %ld %s\n"), - (unsigned long int) c, (long) c->pid, - c->remote ? _(" (remote)") : "")); + ? _("Reaping losing child %p PID %s %s\n") + : _("Reaping winning child %p PID %s %s\n"), + (void *)c, pid2str (c->pid), c->remote ? _(" (remote)") : "")); if (c->sh_batch_file) { DB (DB_JOBS, (_("Cleaning up temp batch file %s\n"), @@ -854,9 +915,8 @@ reap_children (int block, int err) update_status to its also_make files. */ notice_finished_file (c->file); - DB (DB_JOBS, (_("Removing child 0x%08lx PID %ld%s from chain.\n"), - (unsigned long int) c, (long) c->pid, - c->remote ? _(" (remote)") : "")); + DB (DB_JOBS, (_("Removing child %p PID %s%s from chain.\n"), + (void *)c, pid2str (c->pid), c->remote ? _(" (remote)") : "")); /* Block fatal signals while frobnicating the list, so that children and job_slots_used are always consistent. Otherwise @@ -902,8 +962,8 @@ free_child (struct child *child) print_job_time (child); #endif if (!jobserver_tokens) - fatal (NILF, "INTERNAL: Freeing child 0x%08lx (%s) but no tokens left!\n", - (unsigned long int) child, child->file->name); + fatal (NILF, "INTERNAL: Freeing child %p (%s) but no tokens left!\n", + (void *)child, child->file->name); /* If we're using the jobserver and this child is not the only outstanding job, put a token back into the pipe for it. */ @@ -919,8 +979,8 @@ free_child (struct child *child) if (r != 1) pfatal_with_name (_("write jobserver")); - DB (DB_JOBS, (_("Released token for child 0x%08lx (%s).\n"), - (unsigned long int) child, child->file->name)); + DB (DB_JOBS, (_("Released token for child %p (%s).\n"), + (void *)child, child->file->name)); } --jobserver_tokens; @@ -1024,7 +1084,7 @@ set_child_handler_action_flags (int set_handler, int set_alarm) #if defined SIGCLD && SIGCLD != SIGCHLD rval = sigaction (SIGCLD, &sa, NULL); #endif - if (rval != 0) + if (rval != 0) fprintf (stderr, "sigaction: %s (%d)\n", strerror (errno), errno); #if defined SIGALRM if (set_alarm) @@ -1055,12 +1115,17 @@ start_job_command (struct child *child) #if !defined(_AMIGA) && !defined(WINDOWS32) static int bad_stdin = -1; #endif - register char *p; - int flags; + char *p; + /* Must be volatile to silence bogus GCC warning about longjmp/vfork. */ + /*volatile*/ int flags; #ifdef VMS char *argv; #else char **argv; +# if !defined(__MSDOS__) && !defined(_AMIGA) && !defined(WINDOWS32) && !defined(VMS) + char ** volatile volatile_argv; + int volatile volatile_flags; +# endif #endif /* If we have a completely empty commandset, stop now. */ @@ -1222,10 +1287,13 @@ start_job_command (struct child *child) #if defined __MSDOS__ || defined (__EMX__) unixy_shell /* the test is complicated and we already did it */ #else - (argv[0] && !strcmp (argv[0], "/bin/sh")) + (argv[0] && is_bourne_compatible_shell(argv[0])) #endif - && (argv[1] - && argv[1][0] == '-' && argv[1][1] == 'c' && argv[1][2] == '\0') + && (argv[1] && argv[1][0] == '-' + && + ((argv[1][1] == 'c' && argv[1][2] == '\0') + || + (argv[1][1] == 'e' && argv[1][2] == 'c' && argv[1][3] == '\0'))) && (argv[2] && argv[2][0] == ':' && argv[2][1] == '\0') && argv[3] == NULL) { @@ -1428,9 +1496,12 @@ start_job_command (struct child *child) fcntl (job_rfd, F_SETFD, 0); #else /* !__EMX__ */ + volatile_argv = argv; /* shut up gcc */ + volatile_flags = flags; /* ditto */ child->pid = vfork (); environ = parent_environ; /* Restore value child may have clobbered. */ + argv = volatile_argv; /* shut up gcc */ if (child->pid == 0) { /* We are the child side. */ @@ -1438,7 +1509,7 @@ start_job_command (struct child *child) /* If we aren't running a recursive command and we have a jobserver pipe, close it before exec'ing. */ - if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0) + if (!(volatile_flags & COMMANDS_RECURSE) && job_fds[0] >= 0) { close (job_fds[0]); close (job_fds[1]); @@ -1446,6 +1517,12 @@ start_job_command (struct child *child) if (job_rfd >= 0) close (job_rfd); +#ifdef SET_STACK_SIZE + /* Reset limits, if necessary. */ + if (stack_limit.rlim_cur) + setrlimit (RLIMIT_STACK, &stack_limit); +#endif + child_execute_job (child->good_stdin ? 0 : bad_stdin, 1, argv, child->environment); } @@ -1546,7 +1623,7 @@ start_job_command (struct child *child) hPID = process_easy(argv, child->environment); if (hPID != INVALID_HANDLE_VALUE) - child->pid = (int) hPID; + child->pid = (pid_t) hPID; else { int i; unblock_sigs(); @@ -1668,9 +1745,9 @@ start_waiting_job (struct child *c) { case cs_running: c->next = children; - DB (DB_JOBS, (_("Putting child 0x%08lx (%s) PID %ld%s on the chain.\n"), - (unsigned long int) c, c->file->name, - (long) c->pid, c->remote ? _(" (remote)") : "")); + DB (DB_JOBS, (_("Putting child %p (%s) PID %s%s on the chain.\n"), + (void *)c, c->file->name, pid2str (c->pid), + c->remote ? _(" (remote)") : "")); children = c; /* One more job slot is in use. */ ++job_slots_used; @@ -1813,7 +1890,7 @@ new_job (struct file *file) /* There are no more references in this line to worry about. Copy the remaining uninteresting text to the output. */ if (out != in) - strcpy (out, in); + memmove (out, in, strlen (in) + 1); /* Finally, expand the line. */ lines[i] = allocated_variable_expand_for_file (cmds->command_lines[i], @@ -1823,8 +1900,7 @@ new_job (struct file *file) /* Start the command sequence, record it in a new `struct child', and add that to the chain. */ - c = xmalloc (sizeof (struct child)); - memset (c, '\0', sizeof (struct child)); + c = xcalloc (sizeof (struct child)); c->file = file; c->command_lines = lines; c->sh_batch_file = NULL; @@ -1928,8 +2004,8 @@ new_job (struct file *file) /* If we got one, we're done here. */ if (got_token == 1) { - DB (DB_JOBS, (_("Obtained token for child 0x%08lx (%s).\n"), - (unsigned long int) c, c->file->name)); + DB (DB_JOBS, (_("Obtained token for child %p (%s).\n"), + (void *)c, c->file->name)); break; } @@ -2278,7 +2354,7 @@ exec_command (char **argv, char **envp) { int i; fprintf(stderr, - _("process_easy() failed failed to launch process (e=%ld)\n"), + _("process_easy() failed to launch process (e=%ld)\n"), process_last_err(hPID)); for (i = 0; argv[i]; i++) fprintf(stderr, "%s ", argv[i]); @@ -2307,9 +2383,14 @@ exec_command (char **argv, char **envp) if (hWaitPID == hPID) break; else + { + char *pidstr = xstrdup (pid2str ((pid_t)hWaitPID)); + fprintf(stderr, - _("make reaped child pid %ld, still waiting for pid %ld\n"), - (DWORD)hWaitPID, (DWORD)hPID); + _("make reaped child pid %s, still waiting for pid %s\n"), + pidstr, pid2str ((pid_t)hPID)); + free (pidstr); + } } /* return child's exit code as our exit code */ @@ -2467,7 +2548,7 @@ void clean_tmp (void) static char ** construct_command_argv_internal (char *line, char **restp, char *shell, - char *ifs, int flags, + char *shellflags, char *ifs, int flags, char **batch_filename_ptr) { #ifdef __MSDOS__ @@ -2508,7 +2589,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell, "for", "case", "if", ":", ".", "break", "continue", "export", "read", "readonly", "shift", "times", "trap", "switch", "unset", - 0 }; + "ulimit", 0 }; char *sh_chars; char **sh_cmds; @@ -2550,12 +2631,15 @@ construct_command_argv_internal (char *line, char **restp, char *shell, 0 }; #elif defined (WINDOWS32) static char sh_chars_dos[] = "\"|&<>"; - static char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls", - "copy", "ctty", "date", "del", "dir", "echo", - "erase", "exit", "for", "goto", "if", "if", "md", - "mkdir", "path", "pause", "prompt", "rd", "rem", - "ren", "rename", "rmdir", "set", "shift", "time", - "type", "ver", "verify", "vol", ":", 0 }; + static char *sh_cmds_dos[] = { "assoc", "break", "call", "cd", "chcp", + "chdir", "cls", "color", "copy", "ctty", + "date", "del", "dir", "echo", "echo.", + "endlocal", "erase", "exit", "for", "ftype", + "goto", "if", "if", "md", "mkdir", "path", + "pause", "prompt", "rd", "rem", "ren", + "rename", "rmdir", "set", "setlocal", + "shift", "time", "title", "type", "ver", + "verify", "vol", ":", 0 }; static char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^"; static char *sh_cmds_sh[] = { "cd", "eval", "exec", "exit", "login", "logout", "set", "umask", "wait", "while", "for", @@ -2577,7 +2661,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell, "eval", "exec", "exit", "export", "for", "if", "login", "logout", "read", "readonly", "set", "shift", "switch", "test", "times", "trap", - "umask", "wait", "while", 0 }; + "ulimit", "umask", "unset", "wait", "while", 0 }; # ifdef HAVE_DOS_PATHS /* This is required if the MSYS/Cygwin ports (which do not define WINDOWS32) are compiled with HAVE_DOS_PATHS defined, which uses @@ -2717,6 +2801,12 @@ construct_command_argv_internal (char *line, char **restp, char *shell, if (*ap != ' ' && *ap != '\t' && *ap != '\n') goto slow; + if (shellflags != 0) + if (shellflags[0] != '-' + || ((shellflags[1] != 'c' || shellflags[2] != '\0') + && (shellflags[1] != 'e' || shellflags[2] != 'c' || shellflags[3] != '\0'))) + goto slow; + i = strlen (line) + 1; /* More than 1 arg per character is impossible. */ @@ -2799,6 +2889,9 @@ construct_command_argv_internal (char *line, char **restp, char *shell, /* Not inside a string, but it's a special char. */ goto slow; #endif /* !KMK */ + else if (one_shell && *p == '\n') + /* In .ONESHELL mode \n is a separator like ; or && */ + goto slow; #ifdef __MSDOS__ else if (*p == '.' && p[1] == '.' && p[2] == '.' && p[3] != '.') /* `...' is a wildcard in DJGPP. */ @@ -3021,34 +3114,97 @@ construct_command_argv_internal (char *line, char **restp, char *shell, if (*line == '\0') return 0; #endif /* WINDOWS32 */ + { /* SHELL may be a multi-word command. Construct a command line - "SHELL -c LINE", with all special chars in LINE escaped. + "$(SHELL) $(.SHELLFLAGS) LINE", with all special chars in LINE escaped. Then recurse, expanding this command line to get the final argument list. */ unsigned int shell_len = strlen (shell); -#ifndef VMS - static char minus_c[] = " -c "; -#else - static char minus_c[] = ""; -#endif unsigned int line_len = strlen (line); - - char *new_line = alloca (shell_len + (sizeof (minus_c)-1) - + (line_len*2) + 1); + unsigned int sflags_len = strlen (shellflags); char *command_ptr = NULL; /* used for batch_mode_shell mode */ + char *new_line; # ifdef __EMX__ /* is this necessary? */ if (!unixy_shell) - minus_c[1] = '/'; /* " /c " */ + shellflags[0] = '/'; /* "/c" */ # endif + /* In .ONESHELL mode we are allowed to throw the entire current + recipe string at a single shell and trust that the user + has configured the shell and shell flags, and formatted + the string, appropriately. */ + if (one_shell) + { + /* If the shell is Bourne compatible, we must remove and ignore + interior special chars [@+-] because they're meaningless to + the shell itself. If, however, we're in .ONESHELL mode and + have changed SHELL to something non-standard, we should + leave those alone because they could be part of the + script. In this case we must also leave in place + any leading [@+-] for the same reason. */ + + /* Remove and ignore interior prefix chars [@+-] because they're + meaningless given a single shell. */ +#if defined __MSDOS__ || defined (__EMX__) + if (unixy_shell) /* the test is complicated and we already did it */ +#else + if (is_bourne_compatible_shell(shell)) +#endif + { + const char *f = line; + char *t = line; + + /* Copy the recipe, removing and ignoring interior prefix chars + [@+-]: they're meaningless in .ONESHELL mode. */ + while (f[0] != '\0') + { + int esc = 0; + + /* This is the start of a new recipe line. + Skip whitespace and prefix characters. */ + while (isblank (*f) || *f == '-' || *f == '@' || *f == '+') + ++f; + + /* Copy until we get to the next logical recipe line. */ + while (*f != '\0') + { + *(t++) = *(f++); + if (f[-1] == '\\') + esc = !esc; + else + { + /* On unescaped newline, we're done with this line. */ + if (f[-1] == '\n' && ! esc) + break; + + /* Something else: reset the escape sequence. */ + esc = 0; + } + } + } + *t = '\0'; + } + + new_argv = xmalloc (4 * sizeof (char *)); + new_argv[0] = xstrdup(shell); + new_argv[1] = xstrdup(shellflags); + new_argv[2] = line; + new_argv[3] = NULL; + return new_argv; + } + + new_line = alloca (shell_len + 1 + sflags_len + 1 + + (line_len*2) + 1); ap = new_line; memcpy (ap, shell, shell_len); ap += shell_len; - memcpy (ap, minus_c, sizeof (minus_c) - 1); - ap += sizeof (minus_c) - 1; + *(ap++) = ' '; + memcpy (ap, shellflags, sflags_len); + ap += sflags_len; + *(ap++) = ' '; command_ptr = ap; for (p = line; *p != '\0'; ++p) { @@ -3098,7 +3254,7 @@ construct_command_argv_internal (char *line, char **restp, char *shell, #endif *ap++ = *p; } - if (ap == new_line + shell_len + sizeof (minus_c) - 1) + if (ap == new_line + shell_len + sflags_len + 2) /* Line was empty. */ return 0; *ap = '\0'; @@ -3150,8 +3306,10 @@ construct_command_argv_internal (char *line, char **restp, char *shell, new_argv[2] = NULL; } else #endif /* WINDOWS32 */ + if (unixy_shell) - new_argv = construct_command_argv_internal (new_line, 0, 0, 0, flags, 0); + new_argv = construct_command_argv_internal (new_line, 0, 0, 0, 0, flags, 0); + #ifdef __EMX__ else if (!unixy_shell) { @@ -3162,8 +3320,11 @@ construct_command_argv_internal (char *line, char **restp, char *shell, char *p = new_line; char *q = new_line; memcpy (new_line, line, line_len + 1); - /* replace all backslash-newline combination and also following tabs */ - while (*q != '\0') + /* Replace all backslash-newline combination and also following tabs. + Important: stop at the first '\n' because that's what the loop above + did. The next line starting at restp[0] will be executed during the + next call of this function. */ + while (*q != '\0' && *q != '\n') { if (q[0] == '\\' && q[1] == '\n') q += 2; /* remove '\\' and '\n' */ @@ -3224,10 +3385,10 @@ construct_command_argv_internal (char *line, char **restp, char *shell, instead of recursively calling ourselves, because we cannot backslash-escape the special characters (see above). */ new_argv = xmalloc (sizeof (char *)); - line_len = strlen (new_line) - shell_len - sizeof (minus_c) + 1; + line_len = strlen (new_line) - shell_len - sflags_len - 2; new_argv[0] = xmalloc (line_len + 1); strncpy (new_argv[0], - new_line + shell_len + sizeof (minus_c) - 1, line_len); + new_line + shell_len + sflags_len + 2, line_len); new_argv[0][line_len] = '\0'; } #else @@ -3259,7 +3420,7 @@ char ** construct_command_argv (char *line, char **restp, struct file *file, int cmd_flags, char **batch_filename_ptr) { - char *shell, *ifs; + char *shell, *ifs, *shellflags; char **argv; #ifdef VMS @@ -3364,6 +3525,7 @@ construct_command_argv (char *line, char **restp, struct file *file, } #endif /* __EMX__ */ + shellflags = allocated_variable_expand_for_file ("$(.SHELLFLAGS)", file); ifs = allocated_variable_expand_for_file ("$(IFS)", file); warn_undefined_variables_flag = save; @@ -3389,7 +3551,7 @@ construct_command_argv (char *line, char **restp, struct file *file, # endif unixy_shell = 1; batch_mode_shell = 0; - argv = construct_command_argv_internal (line, restp, shell, ifs, + argv = construct_command_argv_internal (line, restp, shell, shellflags, ifs, cmd_flags, batch_filename_ptr); batch_mode_shell = saved_batch_mode_shell; unixy_shell = saved_unixy_shell; @@ -3399,10 +3561,11 @@ construct_command_argv (char *line, char **restp, struct file *file, } else #endif /* CONFIG_WITH_KMK_BUILTIN */ - argv = construct_command_argv_internal (line, restp, shell, ifs, + argv = construct_command_argv_internal (line, restp, shell, shellflags, ifs, cmd_flags, batch_filename_ptr); free (shell); + free (shellflags); free (ifs); #endif /* !VMS */ return argv; @@ -3425,7 +3588,7 @@ dup2 (int old, int new) return fd; } -#endif /* !HAPE_DUP2 && !_AMIGA */ +#endif /* !HAVE_DUP2 && !_AMIGA */ #ifdef CONFIG_WITH_PRINT_TIME_SWITCH /* Prints the time elapsed while executing the commands for the given job. */ diff --git a/src/kmk/job.h b/src/kmk/job.h index d6275bd..8bd44ce 100644 --- a/src/kmk/job.h +++ b/src/kmk/job.h @@ -1,6 +1,7 @@ /* Definitions for managing subprocesses in GNU Make. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -53,6 +54,7 @@ struct child #ifdef VMS int efn; /* Completion event flag number */ int cstatus; /* Completion status */ + char *comname; /* Temporary command file name */ #endif char *sh_batch_file; /* Script file for shell commands */ #ifdef CONFIG_WITH_KMK_BUILTIN @@ -73,6 +75,7 @@ struct child extern struct child *children; +int is_bourne_compatible_shell(const char *path); void new_job (struct file *file); void reap_children (int block, int err); void start_waiting_jobs (void); diff --git a/src/kmk/kmkbuiltin.c b/src/kmk/kmkbuiltin.c index 1926a85..30c4509 100644 --- a/src/kmk/kmkbuiltin.c +++ b/src/kmk/kmkbuiltin.c @@ -1,4 +1,4 @@ -/* $Id: kmkbuiltin.c 2413 2010-09-11 17:43:04Z bird $ */ +/* $Id: kmkbuiltin.c 2591 2012-06-17 20:45:31Z bird $ */ /** @file * kMk Builtin command execution. */ @@ -119,7 +119,7 @@ int kmk_builtin_command(const char *pszCmd, char ***ppapszArgvToSpawn, pid_t *pP argv[argc] = malloc(cch + 1); if (!argv[argc]) { - printf("kmk_builtin: out of memory. argc=%d len=%d\n", argc, pszEnd - pszCmd + 1); + printf("kmk_builtin: out of memory. argc=%d len=%d\n", argc, (int)(pszEnd - pszCmd + 1)); break; } memcpy(argv[argc], pszCmd, cch); diff --git a/src/kmk/kmkbuiltin/cmp_util.c b/src/kmk/kmkbuiltin/cmp_util.c index fc1b3dd..905ac13 100644 --- a/src/kmk/kmkbuiltin/cmp_util.c +++ b/src/kmk/kmkbuiltin/cmp_util.c @@ -362,11 +362,11 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1, blk_sz = length; bytes_read = read(fd1, b1, blk_sz); - if (bytes_read != blk_sz) + if (bytes_read != (off_t)blk_sz) goto l_read_error; bytes_read = read(fd2, b2, blk_sz); - if (bytes_read != blk_sz) + if (bytes_read != (off_t)blk_sz) goto l_read_error; blk_cnt = blk_sz; diff --git a/src/kmk/kmkbuiltin/darwin.c b/src/kmk/kmkbuiltin/darwin.c index bc35e68..583d6e1 100644 --- a/src/kmk/kmkbuiltin/darwin.c +++ b/src/kmk/kmkbuiltin/darwin.c @@ -1,4 +1,4 @@ -/* $Id: darwin.c 2413 2010-09-11 17:43:04Z bird $ */ +/* $Id: darwin.c 2591 2012-06-17 20:45:31Z bird $ */ /** @file * Missing BSD functions on Darwin / Mac OS X. */ @@ -28,6 +28,7 @@ *******************************************************************************/ #include "config.h" #include <sys/stat.h> +#include <sys/time.h> #include <unistd.h> diff --git a/src/kmk/kmkbuiltin/echo.c b/src/kmk/kmkbuiltin/echo.c index 2a6f2a6..77591fe 100644 --- a/src/kmk/kmkbuiltin/echo.c +++ b/src/kmk/kmkbuiltin/echo.c @@ -38,7 +38,7 @@ static char const copyright[] = static char sccsid[] = "@(#)echo.c 8.1 (Berkeley) 5/31/93"; #endif /* not lint */ #include <sys/cdefs.h> -//__FBSDID("$FreeBSD: src/bin/echo/echo.c,v 1.17 2004/04/06 20:06:46 markm Exp $"); +/*__FBSDID("$FreeBSD: src/bin/echo/echo.c,v 1.17 2004/04/06 20:06:46 markm Exp $");*/ #endif #include "config.h" diff --git a/src/kmk/kmkbuiltin/expr.c b/src/kmk/kmkbuiltin/expr.c index a2d26aa..a16e28c 100644 --- a/src/kmk/kmkbuiltin/expr.c +++ b/src/kmk/kmkbuiltin/expr.c @@ -280,6 +280,9 @@ nexttoken(int pat) return; } +#ifdef __GNUC__ +__attribute__((noreturn)) +#endif static void error(void) { diff --git a/src/kmk/kmkbuiltin/haikufakes.h b/src/kmk/kmkbuiltin/haikufakes.h index 70a8cdd..eff20bb 100644 --- a/src/kmk/kmkbuiltin/haikufakes.h +++ b/src/kmk/kmkbuiltin/haikufakes.h @@ -1,10 +1,10 @@ -/* $Id: haikufakes.h 2546 2011-10-01 19:49:54Z bird $ */ +/* $Id: haikufakes.h 2656 2012-09-10 20:39:16Z bird $ */ /** @file * Unix/BSD fakes for Haiku. */ /* - * Copyright (c) 2005-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net> + * Copyright (c) 2005-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> * * This file is part of kBuild. * @@ -36,5 +36,7 @@ #define lutimes(path, tvs) utimes(path, tvs) #define lchmod haiku_lchmod +extern int haiku_lchmod(const char *pszPath, mode_t mode); + #endif diff --git a/src/kmk/kmkbuiltin/install.c b/src/kmk/kmkbuiltin/install.c index 799effe..13bec72 100644 --- a/src/kmk/kmkbuiltin/install.c +++ b/src/kmk/kmkbuiltin/install.c @@ -1021,7 +1021,13 @@ install_dir(char *path) int ch; for (p = path;; ++p) - if (!*p || (p != path && IS_SLASH(*p))) { + if ( !*p + || ( p != path + && IS_SLASH(*p) +#if defined(_MSC_VER) /* stat("C:") fails (VC++ v10). Just skip it since it's unnecessary. */ + && (p - path != 2 || p[-1] != ':') +#endif + )) { ch = *p; *p = '\0'; if (stat(path, &sb)) { diff --git a/src/kmk/kmkbuiltin/kDepObj.c b/src/kmk/kmkbuiltin/kDepObj.c index 6f6bfc6..649d9e7 100644 --- a/src/kmk/kmkbuiltin/kDepObj.c +++ b/src/kmk/kmkbuiltin/kDepObj.c @@ -1,4 +1,4 @@ -/* $Id: kDepObj.c 2413 2010-09-11 17:43:04Z bird $ */ +/* $Id: kDepObj.c 2591 2012-06-17 20:45:31Z bird $ */ /** @file * kDepObj - Extract dependency information from an object file. */ @@ -273,7 +273,7 @@ int kDepObjOMFParse(const KU8 *pbFile, KSIZE cbFile) uData.pv = pHdr + 1; /* process selected record types. */ - dprintf(("%#07x: %#04x %#05x\n", (const KU8*)pHdr - pbFile, pHdr->bType, pHdr->cbRec)); + dprintf(("%#07" KUPTR_PRI ": %#04x %#05x\n", (const KU8*)pHdr - pbFile, pHdr->bType, pHdr->cbRec)); switch (pHdr->bType) { /* @@ -691,7 +691,7 @@ int kDepObjCOFFParseCV8SymbolSection(const KU8 *pbSyms, KSIZE cbSyms) */ if (off + 8 > cbSrcFiles) { - fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrcFiles=%#" KSIZE_PRI "\n", + fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrcFiles=%#" KX32_PRI "\n", argv0, off, cbSrcFiles); return 1; } @@ -700,7 +700,7 @@ int kDepObjCOFFParseCV8SymbolSection(const KU8 *pbSyms, KSIZE cbSyms) cbSrc = u16Type == 0x0110 ? 6 + 16 + 2 : 6 + 2; if (off + cbSrc > cbSrcFiles) { - fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrc=%#" KX32_PRI " cbSrcFiles=%#" KSIZE_PRI "\n", + fprintf(stderr, "%s: CV source file entry at %08" KX32_PRI " is too long; cbSrc=%#" KX32_PRI " cbSrcFiles=%#" KX32_PRI "\n", argv0, off, cbSrc, cbSrcFiles); return 1; } diff --git a/src/kmk/kmkbuiltin/kbuild_version.c b/src/kmk/kmkbuiltin/kbuild_version.c index ec0613b..29d514d 100644 --- a/src/kmk/kmkbuiltin/kbuild_version.c +++ b/src/kmk/kmkbuiltin/kbuild_version.c @@ -1,4 +1,4 @@ -/* $Id: kbuild_version.c 2413 2010-09-11 17:43:04Z bird $ */ +/* $Id: kbuild_version.c 2591 2012-06-17 20:45:31Z bird $ */ /** @file * kbuild_version(), helper function. */ @@ -52,7 +52,7 @@ int kbuild_version(const char *argv0) tmp = strchr(argv0, '\0'); printf("%.*s - kBuild version %d.%d.%d (r%u)\n", - tmp - argv0, argv0, + (int)(tmp - argv0), argv0, KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_SVN_REV); return 0; diff --git a/src/kmk/kmkbuiltin/mscfakes.c b/src/kmk/kmkbuiltin/mscfakes.c index 7d040ff..3f472c9 100644 --- a/src/kmk/kmkbuiltin/mscfakes.c +++ b/src/kmk/kmkbuiltin/mscfakes.c @@ -1,4 +1,4 @@ -/* $Id: mscfakes.c 2484 2011-07-21 19:01:08Z bird $ */ +/* $Id: mscfakes.c 2645 2012-09-09 02:29:23Z bird $ */ /** @file * Fake Unix stuff for MSC. */ @@ -477,13 +477,15 @@ int writev(int fd, const struct iovec *vector, int count) intmax_t strtoimax(const char *nptr, char **endptr, int base) { - return strtol(nptr, endptr, base); /** @todo fix this. */ + if (*nptr != '-') + return _strtoui64(nptr, endptr, base); + return -(intmax_t)_strtoui64(nptr + 1, endptr, base); } uintmax_t strtoumax(const char *nptr, char **endptr, int base) { - return strtoul(nptr, endptr, base); /** @todo fix this. */ + return _strtoui64(nptr, endptr, base); } @@ -532,13 +534,12 @@ int vasprintf(char **strp, const char *fmt, va_list va) } -#undef stat /* * Workaround for directory names with trailing slashes. - * Added by bird reasons stated. */ +#undef stat int -my_other_stat(const char *path, struct stat *st) +bird_w32_stat(const char *path, struct stat *st) { int rc = stat(path, st); if ( rc != 0 @@ -563,6 +564,13 @@ my_other_stat(const char *path, struct stat *st) } } } +#ifdef KMK_PRF + { + int err = errno; + fprintf(stderr, "stat(%s,) -> %d/%d\n", path, rc, errno); + errno = err; + } +#endif return rc; } diff --git a/src/kmk/kmkbuiltin/mscfakes.h b/src/kmk/kmkbuiltin/mscfakes.h index 705a3dc..ec0edb5 100644 --- a/src/kmk/kmkbuiltin/mscfakes.h +++ b/src/kmk/kmkbuiltin/mscfakes.h @@ -1,4 +1,4 @@ -/* $Id: mscfakes.h 2413 2010-09-11 17:43:04Z bird $ */ +/* $Id: mscfakes.h 2592 2012-06-17 22:50:38Z bird $ */ /** @file * Unix fakes for MSC. */ @@ -34,19 +34,25 @@ #include <malloc.h> #include "getopt.h" +/* Note: Duplicated it config.h.win */ +#include <sys/stat.h> +#include <io.h> +#include <direct.h> #if defined(MSC_DO_64_BIT_IO) && _MSC_VER >= 1400 /* We want 64-bit file lengths here when possible. */ # define off_t __int64 +# undef stat # define stat _stat64 # define fstat _fstat64 # define lseek _lseeki64 #else -# undef stat -# define stat(_path, _st) my_other_stat(_path, _st) -extern int my_other_stat(const char *, struct stat *); +# ifndef STAT_REDEFINED_ALREADY +# define STAT_REDEFINED_ALREADY +# undef stat +# define stat(_path, _st) bird_w32_stat(_path, _st) +extern int bird_w32_stat(const char *, struct stat *); +# endif #endif - - #ifndef S_ISDIR # define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) #endif diff --git a/src/kmk/kmkbuiltin/osdep.c b/src/kmk/kmkbuiltin/osdep.c index d8201df..e9f1a77 100644 --- a/src/kmk/kmkbuiltin/osdep.c +++ b/src/kmk/kmkbuiltin/osdep.c @@ -1,4 +1,4 @@ -/* $Id: osdep.c 2421 2010-10-17 21:27:53Z bird $ */ +/* $Id: osdep.c 2656 2012-09-10 20:39:16Z bird $ */ /** @file * Include all the OS dependent bits when bootstrapping. */ @@ -41,5 +41,8 @@ #elif defined(__OpenBSD__) # include "openbsd.c" +#elif defined(__HAIKU__) +# include "haikufakes.c" + #endif diff --git a/src/kmk/kmkbuiltin/printf.c b/src/kmk/kmkbuiltin/printf.c index d307d1c..36150e2 100644 --- a/src/kmk/kmkbuiltin/printf.c +++ b/src/kmk/kmkbuiltin/printf.c @@ -206,7 +206,7 @@ char *kmk_builtin_func_printf(char *o, char **argv, const char *funcname) (void)funcname; if (rc != 0) - fatal (NILF, _("$(%s): failure rc=%d\n"), rc); + fatal (NILF, _("$(%s): failure rc=%d\n"), funcname, rc); return o; } #endif @@ -637,15 +637,21 @@ mklong(const char *str, int ch) static char copy[64]; size_t len; - len = strlen(str) + 2; - if (len > sizeof copy) { + len = strlen(str) - 1; + if (len > sizeof(copy) - 5) { warnx("format %s too complex\n", str); len = 4; } - (void)memmove(copy, str, len - 3); - copy[len - 3] = 'j'; - copy[len - 2] = ch; - copy[len - 1] = '\0'; + (void)memmove(copy, str, len); +#ifndef _MSC_VER + copy[len++] = 'j'; +#else + copy[len++] = 'I'; + copy[len++] = '6'; + copy[len++] = '4'; +#endif + copy[len++] = ch; + copy[len] = '\0'; return copy; } diff --git a/src/kmk/kmkbuiltin/redirect.c b/src/kmk/kmkbuiltin/redirect.c index c3f3cda..fee7828 100644 --- a/src/kmk/kmkbuiltin/redirect.c +++ b/src/kmk/kmkbuiltin/redirect.c @@ -1,10 +1,10 @@ -/* $Id: redirect.c 2413 2010-09-11 17:43:04Z bird $ */ +/* $Id: redirect.c 2684 2013-06-19 11:01:48Z bird $ */ /** @file * kmk_redirect - Do simple program <-> file redirection (++). */ /* - * Copyright (c) 2007-2010 knut st. osmundsen <bird-kBuild-spamx@anduin.net> + * Copyright (c) 2007-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> * * This file is part of kBuild. * @@ -49,6 +49,121 @@ #endif +#if defined(_MSC_VER) +/** + * Replaces arguments in need of quoting. + * + * This will "leak" the original and/or the replacement string, depending on + * how you look at it. + * + * For details on how MSC parses the command line, see "Parsing C Command-Line + * Arguments": http://msdn.microsoft.com/en-us/library/a1y7w461.aspx + * + * @param argc The argument count. + * @param argv The argument vector. + */ +static void quoteArguments(int argc, char **argv) +{ + int i; + for (i = 0; i < argc; i++) + { + const char *pszOrg = argv[i]; + size_t cchOrg = strlen(pszOrg); + const char *pszQuotes = (const char *)memchr(pszOrg, '"', cchOrg); + if ( pszQuotes + || cchOrg == 0 + || memchr(pszOrg, '&', cchOrg) + || memchr(pszOrg, '>', cchOrg) + || memchr(pszOrg, '<', cchOrg) + || memchr(pszOrg, '|', cchOrg) + || memchr(pszOrg, '%', cchOrg) + ) + { + char ch; + int fComplicated = pszQuotes || (cchOrg > 0 && pszOrg[cchOrg - 1] == '\\'); + size_t cchNew = fComplicated ? cchOrg * 2 + 2 : cchOrg + 2; + char *pszNew = (char *)malloc(cchNew + 1); + + argv[i] = pszNew; + + *pszNew++ = '"'; + if (fComplicated) + { + while ((ch = *pszOrg++) != '\0') + { + if (ch == '"') + { + *pszNew++ = '\\'; + *pszNew++ = '"'; + } + else if (ch == '\\') + { + /* Backslashes are a bit complicated, they depends on + whether a quotation mark follows them or not. They + only require escaping if one does. */ + unsigned cSlashes = 1; + while ((ch = *pszOrg) == '\\') + { + pszOrg++; + cSlashes++; + } + if (ch == '"' || ch == '\0') /* We put a " at the EOS. */ + { + while (cSlashes-- > 0) + { + *pszNew++ = '\\'; + *pszNew++ = '\\'; + } + } + else + while (cSlashes-- > 0) + *pszNew++ = '\\'; + } + else + *pszNew++ = ch; + } + } + else + { + memcpy(pszNew, pszOrg, cchOrg); + pszNew += cchOrg; + } + *pszNew++ = '"'; + *pszNew = '\0'; + } + } + + /*for (i = 0; i < argc; i++) printf("argv[%u]=%s;;\n", i, argv[i]); */ +} +#endif /* _MSC_VER */ + + +#ifdef _MSC_VER +/** Used by safeCloseFd. */ +static void __cdecl ignore_invalid_parameter(const wchar_t *a, const wchar_t *b, const wchar_t *c, unsigned d, uintptr_t e) +{ +} +#endif + + +/** + * Safely works around MS CRT's pedantic close() function. + * + * @param fd The file handle. + */ +static void safeCloseFd(int fd) +{ +#ifdef _MSC_VER + _invalid_parameter_handler pfnOld = _get_invalid_parameter_handler(); + _set_invalid_parameter_handler(ignore_invalid_parameter); + close(fd); + _set_invalid_parameter_handler(pfnOld); +#else + close(fd); +#endif +} + + static const char *name(const char *pszName) { const char *psz = strrchr(pszName, '/'); @@ -86,10 +201,10 @@ static int usage(FILE *pOut, const char *argv0) "The -C switch is for changing the current directory. This takes immediate\n" "effect, so be careful where you put it.\n" "\n" - "This command is really just a quick hack to avoid invoking the shell\n" + "This command was originally just a quick hack to avoid invoking the shell\n" "on Windows (cygwin) where forking is very expensive and has exhibited\n" - "stability issues on SMP machines. This tool may be retired when kBuild\n" - "starts using the kmk_kash shell.\n" + "stability issues on SMP machines. It has since grown into something like\n" + "/usr/bin/env on steroids.\n" , argv0, argv0, argv0); return 1; @@ -153,7 +268,7 @@ int main(int argc, char **argv, char **envp) if (*psz == 'V') { printf("kmk_redirect - kBuild version %d.%d.%d (r%u)\n" - "Copyright (C) 2007-2009 knut st. osmundsen\n", + "Copyright (C) 2007-2012 knut st. osmundsen\n", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_SVN_REV); return 0; @@ -307,7 +422,7 @@ int main(int argc, char **argv, char **envp) return 1; } /** @todo deal with stderr */ - close(fd); + safeCloseFd(fd); continue; } @@ -512,7 +627,7 @@ int main(int argc, char **argv, char **envp) /* * Close and open the new file descriptor. */ - close(fd); + safeCloseFd(fd); #if defined(_MSC_VER) if (!strcmp(psz, "/dev/null")) psz = (char *)"nul"; @@ -557,11 +672,8 @@ int main(int argc, char **argv, char **envp) pStdErr = NULL; } - /** @todo - * We'll have to find the '--' in the commandline and pass that - * on to CreateProcess or spawn. Otherwise, the argument qouting - * is gonna be messed up. - */ + /* MSC is a PITA since it refuses to quote the arguments... */ + quoteArguments(argc - i, &argv[i]); rc = _spawnvp(_P_WAIT, argv[i], &argv[i]); if (rc == -1 && pStdErr) { diff --git a/src/kmk/main.c b/src/kmk/main.c index 528ce60..a1e8a63 100644 --- a/src/kmk/main.c +++ b/src/kmk/main.c @@ -1,7 +1,7 @@ /* Argument parsing and main program of GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -80,7 +80,6 @@ RETSIGTYPE fatal_error_signal (int sig); void print_variable_data_base (void); void print_dir_data_base (void); void print_rule_data_base (void); -void print_file_data_base (void); void print_vpath_data_base (void); void verify_file_data_base (void); @@ -109,7 +108,7 @@ static void print_data_base (void); static void print_version (void); static void decode_switches (int argc, char **argv, int env); static void decode_env_switches (char *envar, unsigned int len); -static void define_makeflags (int all, int makefile); +static const char *define_makeflags (int all, int makefile); static char *quote_for_env (char *out, const char *in); static void initialize_global_hash_tables (void); @@ -263,6 +262,13 @@ int print_version_flag = 0; static struct stringlist *makefiles = 0; +/* Size of the stack when we started. */ + +#ifdef SET_STACK_SIZE +struct rlimit stack_limit; +#endif + + /* Number of job slots (commands that can be run at once). */ unsigned int job_slots = 1; @@ -308,6 +314,9 @@ static struct stringlist *old_files = 0; static struct stringlist *new_files = 0; +/* List of strings to be eval'd. */ +static struct stringlist *eval_strings = 0; + /* If nonzero, we should just print usage and exit. */ static int print_usage_flag = 0; @@ -380,6 +389,8 @@ static const char *const usage[] = -e, --environment-overrides\n\ Environment variables override makefiles.\n"), N_("\ + --eval=STRING Evaluate STRING as a makefile statement.\n"), + N_("\ -f FILE, --file=FILE, --makefile=FILE\n\ Read FILE as a makefile.\n"), N_("\ @@ -541,6 +552,7 @@ static const struct command_switch switches[] = { 'W', filename, &new_files, 0, 0, 0, 0, 0, "what-if" }, { CHAR_MAX+5, flag, &warn_undefined_variables_flag, 1, 1, 0, 0, 0, "warn-undefined-variables" }, + { CHAR_MAX+6, string, &eval_strings, 1, 0, 0, 0, 0, "eval" }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; @@ -592,15 +604,13 @@ char *starting_directory; unsigned int makelevel; -/* First file defined in the makefile whose name does not - start with `.'. This is the default to remake if the - command line does not specify. */ - -struct file *default_goal_file; +/* Pointer to the value of the .DEFAULT_GOAL special variable. + The value will be the name of the goal to remake if the command line + does not override it. It can be set by the makefile, or else it's + the first target defined in the makefile whose name does not start + with '.'. */ -/* Pointer to the value of the .DEFAULT_GOAL special - variable. */ -char ** default_goal_name; +struct variable * default_goal_var; /* Pointer to structure for the file .DEFAULT whose commands are used for any file that has none of its own. @@ -618,6 +628,12 @@ int posix_pedantic; int second_expansion; +/* Nonzero if we have seen the '.ONESHELL' target. + This causes the entire recipe to be handed to SHELL + as a single string, potentially containing newlines. */ + +int one_shell; + #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION /* Nonzero if we have seen the '.SECONDTARGETEXPANSION' target. This turns on secondary expansion of targets. */ @@ -626,6 +642,7 @@ int second_target_expansion; #endif #ifndef CONFIG_WITH_EXTENDED_NOTPARALLEL + /* Nonzero if we have seen the `.NOTPARALLEL' target. This turns off parallel builds for this invocation of make. */ @@ -662,11 +679,11 @@ int fatal_signal_mask; # endif #endif -#if !defined HAVE_BSD_SIGNAL && !defined bsd_signal +#if !HAVE_DECL_BSD_SIGNAL && !defined bsd_signal # if !defined HAVE_SIGACTION # define bsd_signal signal # else -typedef RETSIGTYPE (*bsd_signal_ret_t) (); +typedef RETSIGTYPE (*bsd_signal_ret_t) (int); static bsd_signal_ret_t bsd_signal (int sig, bsd_signal_ret_t func) @@ -871,7 +888,7 @@ set_make_priority_and_affinity (void) error = set_thread_priority (find_thread (NULL), iNewPriority); if (error != B_OK) fprintf (stderr, "warning: set_thread_priority (,%d) failed: %s\n", - newPriority, strerror (error)); + iNewPriority, strerror (error)); # else /*#elif HAVE_NICE */ int nice_level = 0; @@ -919,24 +936,24 @@ handle_runtime_exceptions( struct _EXCEPTION_POINTERS *exinfo ) if (! ISDB (DB_VERBOSE)) { sprintf(errmsg, - _("%s: Interrupt/Exception caught (code = 0x%lx, addr = 0x%lx)\n"), - prg, exrec->ExceptionCode, (DWORD)exrec->ExceptionAddress); + _("%s: Interrupt/Exception caught (code = 0x%lx, addr = 0x%p)\n"), + prg, exrec->ExceptionCode, exrec->ExceptionAddress); fprintf(stderr, errmsg); exit(255); } sprintf(errmsg, - _("\nUnhandled exception filter called from program %s\nExceptionCode = %lx\nExceptionFlags = %lx\nExceptionAddress = %lx\n"), + _("\nUnhandled exception filter called from program %s\nExceptionCode = %lx\nExceptionFlags = %lx\nExceptionAddress = 0x%p\n"), prg, exrec->ExceptionCode, exrec->ExceptionFlags, - (DWORD)exrec->ExceptionAddress); + exrec->ExceptionAddress); if (exrec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && exrec->NumberParameters >= 2) sprintf(&errmsg[strlen(errmsg)], (exrec->ExceptionInformation[0] - ? _("Access violation: write operation at address %lx\n") - : _("Access violation: read operation at address %lx\n")), - exrec->ExceptionInformation[1]); + ? _("Access violation: write operation at address 0x%p\n") + : _("Access violation: read operation at address 0x%p\n")), + (PVOID)exrec->ExceptionInformation[1]); /* turn this on if we want to put stuff in the event log too */ #ifdef USE_EVENT_LOG @@ -1010,8 +1027,8 @@ find_and_set_default_shell (const char *token) unixy_shell = 0; sprintf (sh_path, "%s", search_token); default_shell = xstrdup (w32ify (sh_path, 0)); - DB (DB_VERBOSE, - (_("find_and_set_shell setting default_shell = %s\n"), default_shell)); + DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"), + default_shell)); sh_found = 1; } else if (!no_default_sh_exe && (token == NULL || !strcmp (search_token, default_shell))) { @@ -1021,8 +1038,8 @@ find_and_set_default_shell (const char *token) /* search token path was found */ sprintf (sh_path, "%s", search_token); default_shell = xstrdup (w32ify (sh_path, 0)); - DB (DB_VERBOSE, - (_("find_and_set_shell setting default_shell = %s\n"), default_shell)); + DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"), + default_shell)); sh_found = 1; } else { char *p; @@ -1063,7 +1080,7 @@ find_and_set_default_shell (const char *token) if (sh_found) DB (DB_VERBOSE, - (_("find_and_set_shell path search set default_shell = %s\n"), + (_("find_and_set_shell() path search set default_shell = %s\n"), default_shell)); } } @@ -1378,11 +1395,15 @@ main (int argc, char **argv, char **envp) struct rlimit rlim; /* Set the stack limit huge so that alloca does not fail. */ - if (getrlimit (RLIMIT_STACK, &rlim) == 0) + if (getrlimit (RLIMIT_STACK, &rlim) == 0 + && rlim.rlim_cur > 0 && rlim.rlim_cur < rlim.rlim_max) { + stack_limit = rlim; rlim.rlim_cur = rlim.rlim_max; setrlimit (RLIMIT_STACK, &rlim); } + else + stack_limit.rlim_cur = 0; } #endif @@ -1397,7 +1418,6 @@ main (int argc, char **argv, char **envp) init_kbuild (argc, argv); #endif - default_goal_file = 0; reading_file = 0; #if defined (__MSDOS__) && !defined (_POSIX_SOURCE) @@ -1414,9 +1434,11 @@ main (int argc, char **argv, char **envp) /* Set up gettext/internationalization support. */ setlocale (LC_ALL, ""); + /* The cast to void shuts up compiler warnings on systems that + disable NLS. */ #ifdef LOCALEDIR /* bird */ - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); + (void)bindtextdomain (PACKAGE, LOCALEDIR); + (void)textdomain (PACKAGE); #endif #ifdef POSIX @@ -1427,7 +1449,7 @@ main (int argc, char **argv, char **envp) fatal_signal_mask = 0; #define ADD_SIG(sig) fatal_signal_mask |= sigmask (sig) #else -#define ADD_SIG(sig) +#define ADD_SIG(sig) (void)sig /* Needed to avoid warnings in MSVC. */ #endif #endif @@ -1582,34 +1604,36 @@ main (int argc, char **argv, char **envp) #endif /* Initialize the special variables. */ - define_variable (".VARIABLES", 10, "", o_default, 0)->special = 1; - /* define_variable (".TARGETS", 8, "", o_default, 0)->special = 1; */ - define_variable (".RECIPEPREFIX", 13, "", o_default, 0)->special = 1; - - /* Set up .FEATURES */ - define_variable (".FEATURES", 9, - "target-specific order-only second-expansion else-if", - o_default, 0); + define_variable_cname (".VARIABLES", "", o_default, 0)->special = 1; + /* define_variable_cname (".TARGETS", "", o_default, 0)->special = 1; */ + define_variable_cname (".RECIPEPREFIX", "", o_default, 0)->special = 1; + define_variable_cname (".SHELLFLAGS", "-c", o_default, 0); + + /* Set up .FEATURES + We must do this in multiple calls because define_variable_cname() is + a macro and some compilers (MSVC) don't like conditionals in macros. */ + { + const char *features = "target-specific order-only second-expansion" + " else-if shortest-stem undefine" #ifndef NO_ARCHIVES - do_variable_definition (NILF, ".FEATURES", "archives", - o_default, f_append, 0); + " archives" #endif #ifdef MAKE_JOBSERVER - do_variable_definition (NILF, ".FEATURES", "jobserver", - o_default, f_append, 0); + " jobserver" #endif #ifdef MAKE_SYMLINKS - do_variable_definition (NILF, ".FEATURES", "check-symlink", - o_default, f_append, 0); + " check-symlink" #endif #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - do_variable_definition (NILF, ".FEATURES", "explicit-multitarget", - o_default, f_append, 0); + " explicit-multitarget" #endif #ifdef CONFIG_WITH_PREPEND_ASSIGNMENT - do_variable_definition (NILF, ".FEATURES", "prepend-assignment", - o_default, f_append, 0); + " prepend-assignment" #endif + ; + + define_variable_cname (".FEATURES", features, o_default, 0); + } #ifdef KMK /* Initialize the default number of jobs to the cpu/core/smt count. */ @@ -1670,14 +1694,13 @@ main (int argc, char **argv, char **envp) #else shell_var.name = v->name; #endif - shell_var.length = 5; /* bird - gotta set the length too! */ + shell_var.length = 5; #ifndef CONFIG_WITH_VALUE_LENGTH shell_var.value = xstrdup (ep + 1); #else - shell_var.value = savestring (v->value, v->value_length); + shell_var.value = xstrndup (v->value, v->value_length); shell_var.value_length = v->value_length; #endif - } /* If MAKE_RESTARTS is set, remember it but don't export it. */ @@ -1694,9 +1717,8 @@ main (int argc, char **argv, char **envp) * either the first mispelled value or an empty string */ if (!unix_path) - define_variable("PATH", 4, - windows32_path ? windows32_path : "", - o_env, 1)->export = v_export; + define_variable_cname ("PATH", windows32_path ? windows32_path : "", + o_env, 1)->export = v_export; #endif #else /* For Amiga, read the ENV: device, ignoring all dirs */ { @@ -1742,7 +1764,9 @@ main (int argc, char **argv, char **envp) decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS")); #endif #endif /* !KMK */ + decode_switches (argc, argv, 0); + #ifdef WINDOWS32 if (suspend_flag) { fprintf(stderr, "%s (pid = %ld)\n", argv[0], GetCurrentProcessId()); @@ -1810,7 +1834,7 @@ main (int argc, char **argv, char **envp) && (strchr (argv[0], '/') != 0 || strchr (argv[0], '\\') != 0) # endif ) - argv[0] = xstrdup (concat (current_directory, "/", argv[0])); + argv[0] = xstrdup (concat (3, current_directory, "/", argv[0])); #else /* !__MSDOS__ */ if (current_directory[0] != '\0' && argv[0] != 0 && argv[0][0] != '/' && strchr (argv[0], '/') != 0 @@ -1819,15 +1843,15 @@ main (int argc, char **argv, char **envp) && strchr (argv[0], '\\') != 0 #endif ) - argv[0] = xstrdup (concat (current_directory, "/", argv[0])); + argv[0] = xstrdup (concat (3, current_directory, "/", argv[0])); #endif /* !__MSDOS__ */ #endif /* WINDOWS32 */ #endif /* The extra indirection through $(MAKE_COMMAND) is done for hysterical raisins. */ - (void) define_variable ("MAKE_COMMAND", 12, argv[0], o_default, 0); - (void) define_variable ("MAKE", 4, "$(MAKE_COMMAND)", o_default, 1); + define_variable_cname ("MAKE_COMMAND", argv[0], o_default, 0); + define_variable_cname ("MAKE", "$(MAKE_COMMAND)", o_default, 1); #ifdef KMK (void) define_variable ("KMK", 3, argv[0], o_default, 1); #endif @@ -1868,8 +1892,7 @@ main (int argc, char **argv, char **envp) /* Define an unchangeable variable with a name that no POSIX.2 makefile could validly use for its own variable. */ - (void) define_variable ("-*-command-variables-*-", 23, - value, o_automatic, 0); + define_variable_cname ("-*-command-variables-*-", value, o_automatic, 0); /* Define the variable; this will not override any user definition. Normally a reference to this variable is written into the value of @@ -1878,11 +1901,11 @@ main (int argc, char **argv, char **envp) allow the user's setting of MAKEOVERRIDES to affect MAKEFLAGS, so a reference to this hidden variable is written instead. */ #ifdef KMK - (void) define_variable ("KMK_OVERRIDES", 13, - "${-*-command-variables-*-}", o_env, 1); + define_variable_cname ("KMK_OVERRIDES", "${-*-command-variables-*-}", + o_env, 1); #else - (void) define_variable ("MAKEOVERRIDES", 13, - "${-*-command-variables-*-}", o_env, 1); + define_variable_cname ("MAKEOVERRIDES", "${-*-command-variables-*-}", + o_env, 1); #endif } @@ -2053,7 +2076,7 @@ main (int argc, char **argv, char **envp) starting_directory = current_directory; } - (void) define_variable ("CURDIR", 6, current_directory, o_file, 0); + define_variable_cname ("CURDIR", current_directory, o_file, 0); /* Read any stdin makefiles into temporary files. */ @@ -2193,10 +2216,44 @@ main (int argc, char **argv, char **envp) default_file = enter_file (strcache_add (".DEFAULT")); - { - struct variable *v = define_variable (".DEFAULT_GOAL", 13, "", o_file, 0); - default_goal_name = &v->value; - } + default_goal_var = define_variable_cname (".DEFAULT_GOAL", "", o_file, 0); + + /* Evaluate all strings provided with --eval. + Also set up the $(-*-eval-flags-*-) variable. */ + + if (eval_strings) + { + char *p, *value; + unsigned int i; + unsigned int len = sizeof ("--eval=") * eval_strings->idx; + + for (i = 0; i < eval_strings->idx; ++i) + { +#ifndef CONFIG_WITH_VALUE_LENGTH + p = xstrdup (eval_strings->list[i]); + len += 2 * strlen (p); + eval_buffer (p); +#else + unsigned int sub_len = strlen(eval_strings->list[i]); + p = xstrndup (eval_strings->list[i], sub_len); + len += 2 * sub_len; + eval_buffer (p, p + sub_len); +#endif + free (p); + } + + p = value = alloca (len); + for (i = 0; i < eval_strings->idx; ++i) + { + strcpy (p, "--eval="); + p += strlen (p); + p = quote_for_env (p, eval_strings->list[i]); + *(p++) = ' '; + } + p[-1] = '\0'; + + define_variable_cname ("-*-eval-flags-*-", value, o_automatic, 0); + } /* Read all the makefiles. */ @@ -2259,60 +2316,60 @@ main (int argc, char **argv, char **envp) /* If the jobserver-fds option is seen, make sure that -j is reasonable. */ if (jobserver_fds) - { - const char *cp; - unsigned int ui; + { + const char *cp; + unsigned int ui; - for (ui=1; ui < jobserver_fds->idx; ++ui) - if (!streq (jobserver_fds->list[0], jobserver_fds->list[ui])) - fatal (NILF, _("internal error: multiple --jobserver-fds options")); + for (ui=1; ui < jobserver_fds->idx; ++ui) + if (!streq (jobserver_fds->list[0], jobserver_fds->list[ui])) + fatal (NILF, _("internal error: multiple --jobserver-fds options")); - /* Now parse the fds string and make sure it has the proper format. */ + /* Now parse the fds string and make sure it has the proper format. */ - cp = jobserver_fds->list[0]; + cp = jobserver_fds->list[0]; - if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2) - fatal (NILF, - _("internal error: invalid --jobserver-fds string `%s'"), cp); + if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2) + fatal (NILF, + _("internal error: invalid --jobserver-fds string `%s'"), cp); - DB (DB_JOBS, - (_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1])); + DB (DB_JOBS, + (_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1])); - /* The combination of a pipe + !job_slots means we're using the - jobserver. If !job_slots and we don't have a pipe, we can start - infinite jobs. If we see both a pipe and job_slots >0 that means the - user set -j explicitly. This is broken; in this case obey the user - (ignore the jobserver pipe for this make) but print a message. */ + /* The combination of a pipe + !job_slots means we're using the + jobserver. If !job_slots and we don't have a pipe, we can start + infinite jobs. If we see both a pipe and job_slots >0 that means the + user set -j explicitly. This is broken; in this case obey the user + (ignore the jobserver pipe for this make) but print a message. */ - if (job_slots > 0) - error (NILF, - _("warning: -jN forced in submake: disabling jobserver mode.")); + if (job_slots > 0) + error (NILF, + _("warning: -jN forced in submake: disabling jobserver mode.")); - /* Create a duplicate pipe, that will be closed in the SIGCHLD - handler. If this fails with EBADF, the parent has closed the pipe - on us because it didn't think we were a submake. If so, print a - warning then default to -j1. */ + /* Create a duplicate pipe, that will be closed in the SIGCHLD + handler. If this fails with EBADF, the parent has closed the pipe + on us because it didn't think we were a submake. If so, print a + warning then default to -j1. */ - else if ((job_rfd = dup (job_fds[0])) < 0) - { - if (errno != EBADF) - pfatal_with_name (_("dup jobserver")); + else if ((job_rfd = dup (job_fds[0])) < 0) + { + if (errno != EBADF) + pfatal_with_name (_("dup jobserver")); - error (NILF, - _("warning: jobserver unavailable: using -j1. Add `+' to parent make rule.")); - job_slots = 1; - } + error (NILF, + _("warning: jobserver unavailable: using -j1. Add `+' to parent make rule.")); + job_slots = 1; + } - if (job_slots > 0) - { - close (job_fds[0]); - close (job_fds[1]); - job_fds[0] = job_fds[1] = -1; - free (jobserver_fds->list); - free (jobserver_fds); - jobserver_fds = 0; - } - } + if (job_slots > 0) + { + close (job_fds[0]); + close (job_fds[1]); + job_fds[0] = job_fds[1] = -1; + free (jobserver_fds->list); + free (jobserver_fds); + jobserver_fds = 0; + } + } /* If we have >1 slot but no jobserver-fds, then we're a top-level make. Set up the pipe and install the fds option for our children. */ @@ -2430,8 +2487,8 @@ main (int argc, char **argv, char **envp) FILE_TIMESTAMP *makefile_mtimes = 0; unsigned int mm_idx = 0; - char **nargv = argv; - int nargc = argc; + char **nargv; + int nargc; int orig_db_level = db_level; int status; @@ -2600,24 +2657,26 @@ main (int argc, char **argv, char **envp) for (i = 1; i < argc; ++i) if (strneq (argv[i], "-f", 2)) /* XXX */ { - char *p = &argv[i][2]; - if (*p == '\0') + if (argv[i][2] == '\0') /* This cast is OK since we never modify argv. */ argv[++i] = (char *) makefiles->list[j]; else - argv[i] = xstrdup (concat ("-f", makefiles->list[j], "")); + argv[i] = xstrdup (concat (2, "-f", makefiles->list[j])); ++j; } } /* Add -o option for the stdin temporary file, if necessary. */ + nargc = argc; if (stdin_nm) { nargv = xmalloc ((nargc + 2) * sizeof (char *)); memcpy (nargv, argv, argc * sizeof (char *)); - nargv[nargc++] = xstrdup (concat ("-o", stdin_nm, "")); + nargv[nargc++] = xstrdup (concat (2, "-o", stdin_nm)); nargv[nargc] = 0; } + else + nargv = argv; if (directories != 0 && directories->idx > 0) { @@ -2635,6 +2694,14 @@ main (int argc, char **argv, char **envp) ++restarts; + /* Reset makeflags in case they were changed. */ + { + const char *pv = define_makeflags (1, 1); + char *p = alloca (sizeof ("MAKEFLAGS=") + strlen (pv) + 1); + sprintf (p, "MAKEFLAGS=%s", pv); + putenv (p); + } + if (ISDB (DB_BASIC)) { char **p; @@ -2753,71 +2820,73 @@ main (int argc, char **argv, char **envp) if (stdin_nm && unlink (stdin_nm) < 0 && errno != ENOENT) perror_with_name (_("unlink (temporary file): "), stdin_nm); - { - int status; - - /* If there were no command-line goals, use the default. */ - if (goals == 0) - { - if (**default_goal_name != '\0') - { - if (default_goal_file == 0 || - strcmp (*default_goal_name, default_goal_file->name) != 0) - { - default_goal_file = lookup_file (*default_goal_name); + /* If there were no command-line goals, use the default. */ + if (goals == 0) + { + char *p; - /* In case user set .DEFAULT_GOAL to a non-existent target - name let's just enter this name into the table and let - the standard logic sort it out. */ - if (default_goal_file == 0) - { - struct nameseq *ns; - char *p = *default_goal_name; + if (default_goal_var->recursive) + p = variable_expand (default_goal_var->value); + else + { + p = variable_buffer_output (variable_buffer, default_goal_var->value, + strlen (default_goal_var->value)); + *p = '\0'; + p = variable_buffer; + } -#ifndef CONFIG_WITH_ALLOC_CACHES - ns = multi_glob ( - parse_file_seq (&p, '\0', sizeof (struct nameseq), 1), - sizeof (struct nameseq)); -#else - ns = multi_glob ( - parse_file_seq (&p, '\0', &nameseq_cache, 1), - &nameseq_cache); -#endif + if (*p != '\0') + { + struct file *f = lookup_file (p); - /* .DEFAULT_GOAL should contain one target. */ - if (ns->next != 0) - fatal (NILF, _(".DEFAULT_GOAL contains more than one target")); + /* If .DEFAULT_GOAL is a non-existent target, enter it into the + table and let the standard logic sort it out. */ + if (f == 0) + { + struct nameseq *ns; + ns = PARSE_FILE_SEQ (&p, struct nameseq, '\0', NULL, 0); + if (ns) + { + /* .DEFAULT_GOAL should contain one target. */ + if (ns->next != 0) + fatal (NILF, _(".DEFAULT_GOAL contains more than one target")); #ifndef CONFIG_WITH_VALUE_LENGTH - default_goal_file = enter_file (strcache_add (ns->name)); + f = enter_file (strcache_add (ns->name)); #else - default_goal_file = enter_file (ns->name); + f = enter_file (ns->name); #endif - ns->name = 0; /* It was reused by enter_file(). */ - free_ns_chain (ns); - } - } + ns->name = 0; /* It was reused by enter_file(). */ + free_ns_chain (ns); + } + } - goals = alloc_dep (); - goals->file = default_goal_file; - } - } - else - lastgoal->next = 0; + if (f) + { + goals = alloc_dep (); + goals->file = f; + } + } + } + else + lastgoal->next = 0; - if (!goals) - { - if (read_makefiles == 0) - fatal (NILF, _("No targets specified and no makefile found")); + if (!goals) + { + if (read_makefiles == 0) + fatal (NILF, _("No targets specified and no makefile found")); - fatal (NILF, _("No targets")); - } + fatal (NILF, _("No targets")); + } - /* Update the goals. */ + /* Update the goals. */ - DB (DB_BASIC, (_("Updating goal targets....\n"))); + DB (DB_BASIC, (_("Updating goal targets....\n"))); + + { + int status; switch (update_goal_chain (goals)) { @@ -2927,11 +2996,7 @@ handle_non_switch_argument (char *arg, int env) if (arg[0] == '-' && arg[1] == '\0') /* Ignore plain `-' for compatibility. */ return; -#ifndef CONFIG_WITH_VALUE_LENGTH - v = try_variable_definition (0, arg, o_command, 0); -#else - v = try_variable_definition (0, arg, NULL, o_command, 0); -#endif + v = try_variable_definition (0, arg IF_WITH_VALUE_LENGTH_PARAM(NULL), o_command, 0); if (v != 0) { /* It is indeed a variable definition. If we don't already have this @@ -2993,7 +3058,7 @@ handle_non_switch_argument (char *arg, int env) memcpy (&vp[oldlen + 1], f->name, newlen + 1); value = vp; } - define_variable ("MAKECMDGOALS", 12, value, o_default, 0); + define_variable_cname ("MAKECMDGOALS", value, o_default, 0); } } } @@ -3104,8 +3169,16 @@ decode_switches (int argc, char **argv, int env) optarg = xstrdup (cs->noarg_value); else if (*optarg == '\0') { - error (NILF, _("the `-%c' option requires a non-empty string argument"), - cs->c); + char opt[2] = "c"; + const char *op = opt; + + if (short_option (cs->c)) + opt[0] = cs->c; + else + op = cs->long_name; + + error (NILF, _("the `%s%s' option requires a non-empty string argument"), + short_option (cs->c) ? "-" : "--", op); bad = 1; } @@ -3122,7 +3195,8 @@ decode_switches (int argc, char **argv, int env) else if (sl->idx == sl->max - 1) { sl->max += 5; - sl->list = xrealloc ((void *)sl->list, /* bird */ + /* MSVC erroneously warns without a cast here. */ + sl->list = xrealloc ((void *)sl->list, sl->max * sizeof (char *)); } if (cs->type == filename) @@ -3269,7 +3343,7 @@ decode_env_switches (char *envar, unsigned int len) definition. Add a dash and pass it along to decode_switches. We need permanent storage for this in case decode_switches saves pointers into the value. */ - argv[1] = xstrdup (concat ("-", argv[1], "")); + argv[1] = xstrdup (concat (2, "-", argv[1])); /* Parse those words. */ decode_switches (argc, argv, 1); @@ -3300,16 +3374,17 @@ quote_for_env (char *out, const char *in) command switches. Include options with args if ALL is nonzero. Don't include options with the `no_makefile' flag set if MAKEFILE. */ -static void +static const char * define_makeflags (int all, int makefile) { #ifdef KMK static const char ref[] = "$(KMK_OVERRIDES)"; #else - static const char ref[] = "$(MAKEOVERRIDES)"; + static /*<- bird*/ const char ref[] = "$(MAKEOVERRIDES)"; #endif - static const char posixref[] = "$(-*-command-variables-*-)"; - register const struct command_switch *cs; + static /*<- bird*/ const char posixref[] = "$(-*-command-variables-*-)"; + static /*<- bird*/ const char evalref[] = "$(-*-eval-flags-*-)"; + const struct command_switch *cs; char *flagstring; register char *p; unsigned int words; @@ -3330,7 +3405,7 @@ define_makeflags (int all, int makefile) unsigned int flagslen = 0; #define ADD_FLAG(ARG, LEN) \ do { \ - struct flag *new = alloca (sizeof (struct flag)); \ + struct flag *new = alloca (sizeof (struct flag)); \ new->cs = cs; \ new->arg = (ARG); \ new->next = flags; \ @@ -3338,7 +3413,8 @@ define_makeflags (int all, int makefile) if (new->arg == 0) \ ++flagslen; /* Just a single flag letter. */ \ else \ - flagslen += 1 + 1 + 1 + 1 + 3 * (LEN); /* " -x foo" */ \ + /* " -x foo", plus space to expand "foo". */ \ + flagslen += 1 + 1 + 1 + 1 + (3 * (LEN)); \ if (!short_option (cs->c)) \ /* This switch has no single-letter version, so we use the long. */ \ flagslen += 2 + strlen (cs->long_name); \ @@ -3427,7 +3503,8 @@ define_makeflags (int all, int makefile) abort (); } - flagslen += 4 + sizeof posixref; /* Four more for the possible " -- ". */ + /* Four more for the possible " -- ". */ + flagslen += 4 + sizeof (posixref) + sizeof (evalref); #undef ADD_FLAG @@ -3500,9 +3577,22 @@ define_makeflags (int all, int makefile) #ifdef KMK /* Since MFLAGS is not parsed for flags, there is no reason to override any makefile redefinition. */ - (void) define_variable ("MFLAGS", 6, flagstring, o_env, 1); + define_variable_cname ("MFLAGS", flagstring, o_env, 1); #endif /* !KMK */ + /* Write a reference to -*-eval-flags-*-, which contains all the --eval + flag options. */ + if (eval_strings) + { + if (p == &flagstring[1]) + /* No flags written, so elide the leading dash already written. */ + p = flagstring; + else + *p++ = ' '; + memcpy (p, evalref, sizeof (evalref) - 1); + p += sizeof (evalref) - 1; + } + if (all && command_variables != 0) { /* Now write a reference to $(MAKEOVERRIDES), which contains all the @@ -3528,13 +3618,13 @@ define_makeflags (int all, int makefile) /* Copy in the string. */ if (posix_pedantic) { - memcpy (p, posixref, sizeof posixref - 1); - p += sizeof posixref - 1; + memcpy (p, posixref, sizeof (posixref) - 1); + p += sizeof (posixref) - 1; } else { - memcpy (p, ref, sizeof ref - 1); - p += sizeof ref - 1; + memcpy (p, ref, sizeof (ref) - 1); + p += sizeof (ref) - 1; } } else if (p == &flagstring[1]) @@ -3548,37 +3638,31 @@ define_makeflags (int all, int makefile) /* Terminate the string. */ *p = '\0'; + /* If there are switches, omit the leading dash unless it is a single long + option with two leading dashes. */ + if (flagstring[0] == '-' && flagstring[1] != '-') + ++flagstring; + #ifdef KMK - v = define_variable ("KMK_FLAGS", 9, - /* If there are switches, omit the leading dash - unless it is a single long option with two - leading dashes. */ - &flagstring[(flagstring[0] == '-' - && flagstring[1] != '-') - ? 1 : 0], - /* This used to use o_env, but that lost when a - makefile defined MAKEFLAGS. Makefiles set - MAKEFLAGS to add switches, but we still want - to redefine its value with the full set of - switches. Of course, an override or command - definition will still take precedence. */ - o_file, 1); + v = define_variable_cname ("KMK_FLAGS", flagstring, + /* This used to use o_env, but that lost when a + makefile defined MAKEFLAGS. Makefiles set + MAKEFLAGS to add switches, but we still want + to redefine its value with the full set of + switches. Of course, an override or command + definition will still take precedence. */ + o_file, 1); #else - v = define_variable ("MAKEFLAGS", 9, - /* If there are switches, omit the leading dash - unless it is a single long option with two - leading dashes. */ - &flagstring[(flagstring[0] == '-' - && flagstring[1] != '-') - ? 1 : 0], - /* This used to use o_env, but that lost when a - makefile defined MAKEFLAGS. Makefiles set - MAKEFLAGS to add switches, but we still want - to redefine its value with the full set of - switches. Of course, an override or command - definition will still take precedence. */ - o_file, 1); + v = define_variable_cname ("MAKEFLAGS", flagstring, + /* This used to use o_env, but that lost when a + makefile defined MAKEFLAGS. Makefiles set + MAKEFLAGS to add switches, but we still want + to redefine its value with the full set of + switches. Of course, an override or command + definition will still take precedence. */ + o_file, 1); #endif + if (! all) /* The first time we are called, set MAKEFLAGS to always be exported. We should not do this again on the second call, because that is @@ -3590,31 +3674,27 @@ define_makeflags (int all, int makefile) { char val[32]; sprintf (val, "%u", job_slots); - define_variable ("KMK_OPTS_JOBS", sizeof("KMK_OPTS_JOBS") - 1, - val, o_default, 1); - define_variable ("KMK_OPTS_KEEP_GOING", sizeof("KMK_OPTS_KEEP_GOING") - 1, - keep_going_flag ? "1" : "0", o_default, 1); - define_variable ("KMK_OPTS_JUST_PRINT", sizeof("KMK_OPTS_JUST_PRINT") - 1, - just_print_flag ? "1" : "0", o_default, 1); - define_variable ("KMK_OPTS_PRETTY_COMMAND_PRINTING", sizeof("KMK_OPTS_PRETTY_COMMAND_PRINTING") - 1, - pretty_command_printing ? "1" : "0", o_default, 1); + define_variable_cname ("KMK_OPTS_JOBS", val, o_default, 1); + define_variable_cname ("KMK_OPTS_KEEP_GOING", keep_going_flag ? "1" : "0", o_default, 1); + define_variable_cname ("KMK_OPTS_JUST_PRINT", just_print_flag ? "1" : "0", o_default, 1); + define_variable_cname ("KMK_OPTS_PRETTY_COMMAND_PRINTING", + pretty_command_printing ? "1" : "0", o_default, 1); sprintf (val, "%u", process_priority); - define_variable ("KMK_OPTS_PRORITY", sizeof("KMK_OPTS_PRORITY") - 1, - val, o_default, 1); + define_variable_cname ("KMK_OPTS_PRORITY", val, o_default, 1); sprintf (val, "%u", process_affinity); - define_variable ("KMK_OPTS_AFFINITY", sizeof("KMK_OPTS_AFFINITY") - 1, - val, o_default, 1); -#if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) - define_variable ("KMK_OPTS_STATISTICS", sizeof("KMK_OPTS_STATISTICS") - 1, - make_expensive_statistics ? "1" : "0", o_default, 1); + define_variable_cname ("KMK_OPTS_AFFINITY", val, o_default, 1); +# if defined (CONFIG_WITH_MAKE_STATS) || defined (CONFIG_WITH_MINIMAL_STATS) + define_variable_cname ("KMK_OPTS_STATISTICS", make_expensive_statistics ? "1" : "0", + o_default, 1); # endif -#ifdef CONFIG_WITH_PRINT_TIME_SWITCH +# ifdef CONFIG_WITH_PRINT_TIME_SWITCH sprintf (val, "%u", print_time_min); - define_variable ("KMK_OPTS_PRINT_TIME", sizeof("KMK_OPTS_PRINT_TIME") - 1, - val, o_default, 1); -#endif + define_variable_cname ("KMK_OPTS_PRINT_TIME", val, o_default, 1); +# endif } #endif + + return v->value; } /* Print version information. */ @@ -3653,7 +3733,7 @@ print_version (void) year, and none of the rest of it should be translated (including the word "Copyright", so it hardly seems worth it. */ - printf ("%sCopyright (C) 2007 Free Software Foundation, Inc.\n", precede); + printf ("%sCopyright (C) 2010 Free Software Foundation, Inc.\n", precede); printf (_("%sLicense GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\ %sThis is free software: you are free to change and redistribute it.\n\ @@ -3810,6 +3890,18 @@ clean_jobserver (int status) tcnt, master_job_slots); close (job_fds[0]); + + /* Clean out jobserver_fds so we don't pass this information to any + sub-makes. Also reset job_slots since it will be put on the command + line, not in MAKEFLAGS. */ + job_slots = default_job_slots; + if (jobserver_fds) + { + /* MSVC erroneously warns without a cast here. */ + free ((void *)jobserver_fds->list); + free (jobserver_fds); + jobserver_fds = 0; + } } } @@ -3873,7 +3965,11 @@ die (int status) directory. Must wait until after remove_intermediates(), or unlinks of relative pathnames fail. */ if (directory_before_chdir != 0) - chdir (directory_before_chdir); + { + /* If it fails we don't care: shut up GCC. */ + int _x; + _x = chdir (directory_before_chdir); + } #ifdef CONFIG_WITH_PRINT_TIME_SWITCH if (print_time_min != -1) diff --git a/src/kmk/maintMakefile b/src/kmk/maintMakefile index 5b27cab..56eb584 100644 --- a/src/kmk/maintMakefile +++ b/src/kmk/maintMakefile @@ -147,14 +147,12 @@ do-po-update: && mkdir "$$tmppo" \ && (cd "$$tmppo" \ && $(WGET) -r -l1 -nd --no-parent -A '*.po' $(po_repo)) \ - && cp "$$tmppo"/*.po po && rm -rf "$$tmppo" + && cp "$$tmppo"/*.po $(top_srcdir)/po && rm -rf "$$tmppo" cd po && $(MAKE) update-po $(MAKE) po-check po-update: - if test -d "po"; then \ - $(MAKE) do-po-update; \ - fi + [ -d "po" ] && $(MAKE) do-po-update # -------------------------- # # Updating GNU build files. # @@ -164,29 +162,30 @@ po-update: # with each of the files that belongs to some other package and is # regularly updated from the specified URL. -savannah-url = http://savannah.gnu.org/cgi-bin/viewcvs/~checkout~ +cvs-url = http://savannah.gnu.org/cgi-bin/viewcvs/~checkout~ +git-url = http://git.savannah.gnu.org/cgit target = $(patsubst get-%,%,$@) -config-url = $(savannah-url)/config/config/$(patsubst get-config/%,%,$@) +config-url = $(git-url)/config.git/plain/$(patsubst get-config/%,%,$@) get-config/config.guess get-config/config.sub: @echo $(WGET) $(config-url) -O $(target) \ && $(WGET) $(config-url) -O $(target).t \ && $(move_if_change) -gnulib-url = $(savannah-url)/gnulib/gnulib/build-aux/$(patsubst get-config/%,%,$@) +gnulib-url = $(git-url)/gnulib.git/plain/build-aux/$(patsubst get-config/%,%,$@) get-config/texinfo.tex: @echo $(WGET) $(gnulib-url) -O $(target) \ && $(WGET) $(gnulib-url) -O $(target).t \ && $(move_if_change) -gnustandards-url = $(savannah-url)/gnustandards/gnustandards/$(patsubst get-doc/%,%,$@) +gnustandards-url = $(cvs-url)/gnustandards/gnustandards/$(patsubst get-doc/%,%,$@) get-doc/make-stds.texi get-doc/fdl.texi: @echo $(WGET) $(gnustandards-url) -O $(target) \ && $(WGET) $(gnustandards-url) -O $(target).t \ && $(move_if_change) -.PHONY: cvs-update -cvs-update: get-config/texinfo.tex get-config/config.guess get-config/config.sub get-doc/make-stds.texi get-doc/fdl.texi +.PHONY: scm-update +scm-update: get-config/texinfo.tex get-config/config.guess get-config/config.sub get-doc/make-stds.texi get-doc/fdl.texi # --------------------- # @@ -194,7 +193,7 @@ cvs-update: get-config/texinfo.tex get-config/config.guess get-config/config.sub # --------------------- # .PHONY: update -update: po-update cvs-update +update: po-update scm-update ## --------------- ## @@ -208,7 +207,7 @@ local-check: po-check changelog-check # copyright-check writable-files changelog-check: - if head ChangeLog | grep 'Version $(VERSION)' >/dev/null; then \ + if head $(top_srcdir)/ChangeLog | grep 'Version $(VERSION)' >/dev/null; then \ :; \ else \ echo "$(VERSION) not in ChangeLog" 1>&2; \ @@ -250,7 +249,7 @@ distsign: $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE) %.directive.asc: % @echo "Creating directive file '$@':" @( \ - echo 'verstion: 1.1'; \ + echo 'version: 1.1'; \ echo 'directory: make'; \ echo 'filename: $*'; \ echo 'comment: Official upload of GNU make version $(VERSION)'; \ @@ -261,16 +260,18 @@ distsign: $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE) # Upload the artifacts FTPPUT = ncftpput -gnu-url = ftp-upload.gnu.org /incoming +gnu-upload-host = ftp-upload.gnu.org +gnu-upload-dir = /incoming + UPLOADS = upload-alpha upload-ftp .PHONY: $(UPLOADS) $(UPLOADS): $(DIST_ARCHIVES) $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE) - $(FTPPUT) "$(gnu-url)/$(@:upload-%=%)" $^ + $(FTPPUT) "$(gnu-upload-host)" "$(gnu-upload-dir)/$(@:upload-%=%)" $^ # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -# 2007 Free Software Foundation, Inc. +# 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/make.1 b/src/kmk/make.1 index e91707c..c76ce25 100644 --- a/src/kmk/make.1 +++ b/src/kmk/make.1 @@ -223,7 +223,8 @@ With no argument, removes a previous load limit. Use the latest mtime between symlinks and target. .TP 0.5i .BR \-n , " \-\-just\-print" , " \-\-dry\-run" , " \-\-recon" -Print the commands that would be executed, but do not execute them. +Print the commands that would be executed, but do not execute them (except in +certain circumstances). .TP 0.5i \fB\-o\fR \fIfile\fR, \fB\-\-old\-file\fR=\fIfile\fR, \fB\-\-assume\-old\fR=\fIfile\fR Do not remake the file diff --git a/src/kmk/make.h b/src/kmk/make.h index b12c65f..9b5dc98 100644 --- a/src/kmk/make.h +++ b/src/kmk/make.h @@ -1,7 +1,7 @@ /* Miscellaneous global declarations and portability cruft for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -23,30 +23,27 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ #undef HAVE_CONFIG_H #define HAVE_CONFIG_H 1 +/* Specify we want GNU source code. This must be defined before any + system headers are included. */ + +#define _GNU_SOURCE 1 + /* AIX requires this to be the first thing in the file. */ -#ifndef __GNUC__ -# if HAVE_ALLOCA_H -# include <alloca.h> -# else -# ifdef _AIX +#if HAVE_ALLOCA_H +# include <alloca.h> +#else +# ifdef _AIX #pragma alloca -# else +# else +# if !defined(__GNUC__) && !defined(WINDOWS32) # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif -#elif defined(__sun__) && defined (HAVE_ALLOCA_H) /* bird: kill warnings. */ -# include <alloca.h> #endif -/* Specify we want GNU source code. This must be defined before any - system headers are included. */ - -#define _GNU_SOURCE 1 - - #ifdef CRAY /* This must happen before #include <signal.h> so that the declaration therein is changed. */ @@ -239,6 +236,34 @@ extern unsigned long make_stats_ht_collisions; # define MAKE_STATS(expr) do { } while (0) #endif +/* bird - start */ +#define COMMA , +#ifdef CONFIG_WITH_VALUE_LENGTH +# define IF_WITH_VALUE_LENGTH(a_Expr) a_Expr +# define IF_WITH_VALUE_LENGTH_PARAM(a_Expr) , a_Expr +#else +# define IF_WITH_VALUE_LENGTH(a_Expr) +# define IF_WITH_VALUE_LENGTH_PARAM(a_Expr) +#endif + +#ifdef CONFIG_WITH_ALLOC_CACHES +# define IF_WITH_ALLOC_CACHES(a_Expr) a_Expr +# define IF_WITH_ALLOC_CACHES_PARAM(a_Expr) , a_Expr +#else +# define IF_WITH_ALLOC_CACHES(a_Expr) +# define IF_WITH_ALLOC_CACHES_PARAM(a_Expr) +#endif + +#ifdef CONFIG_WITH_COMMANDS_FUNC +# define IF_WITH_COMMANDS_FUNC(a_Expr) a_Expr +# define IF_WITH_COMMANDS_FUNC_PARAM(a_Expr) , a_Expr +#else +# define IF_WITH_COMMANDS_FUNC(a_Expr) +# define IF_WITH_COMMANDS_FUNC_PARAM(a_Expr) +#endif + +/* bird - end */ + #ifndef CHAR_BIT # define CHAR_BIT 8 @@ -362,23 +387,23 @@ char *strsignal (int signum); host does not conform to POSIX. */ #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) -#ifndef iAPX286 -# define streq(a, b) \ +/* Test if two strings are equal. Is this worthwhile? Should be profiled. */ +#define streq(a, b) \ ((a) == (b) || \ (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1)))) -# ifdef HAVE_CASE_INSENSITIVE_FS -# define strieq(a, b) \ + +/* Test if two strings are equal, but match case-insensitively on systems + which have case-insensitive filesystems. Should only be used for + filenames! */ +#ifdef HAVE_CASE_INSENSITIVE_FS +# define patheq(a, b) \ ((a) == (b) \ || (tolower((unsigned char)*(a)) == tolower((unsigned char)*(b)) \ && (*(a) == '\0' || !strcasecmp ((a) + 1, (b) + 1)))) -# else -# define strieq(a, b) streq(a, b) -# endif #else -/* Buggy compiler can't handle this. */ -# define streq(a, b) (strcmp ((a), (b)) == 0) -# define strieq(a, b) (strcmp ((a), (b)) == 0) +# define patheq(a, b) streq(a, b) #endif + #define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0) #if (defined(__GNUC__) || defined(ENUM_BITFIELDS)) && !defined(NO_ENUM_BITFIELDS) @@ -424,7 +449,7 @@ char *strsignal (int signum); # define kill(_pid,_sig) w32_kill((_pid),(_sig)) void sync_Path_environment (void); -int w32_kill (int pid, int sig); +int w32_kill (pid_t pid, int sig); char *end_of_token_w32 (const char *s, char stopchar); int find_and_set_default_shell (const char *token); @@ -435,6 +460,14 @@ extern int no_default_sh_exe; extern int unixy_shell; #endif /* WINDOWS32 */ +#if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) +# define SET_STACK_SIZE +#endif +#ifdef SET_STACK_SIZE +# include <sys/resource.h> +struct rlimit stack_limit; +#endif + struct floc { const char *filenm; @@ -473,6 +506,7 @@ typedef uint64_t big_uint; #endif #if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H +const char *concat (unsigned int, ...); void message (int prefix, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))); void error (const struct floc *flocp, const char *fmt, ...) @@ -480,6 +514,7 @@ void error (const struct floc *flocp, const char *fmt, ...) void fatal (const struct floc *flocp, const char *fmt, ...) __attribute__ ((noreturn, __format__ (__printf__, 2, 3))); #else +const char *concat (); void message (); void error (); void fatal (); @@ -489,11 +524,11 @@ void die (int) __attribute__ ((noreturn)); void log_working_directory (int); void pfatal_with_name (const char *) __attribute__ ((noreturn)); void perror_with_name (const char *, const char *); -char *savestring (const char *, unsigned int); -char *concat (const char *, const char *, const char *); void *xmalloc (unsigned int); +void *xcalloc (unsigned int); void *xrealloc (void *, unsigned int); char *xstrdup (const char *); +char *xstrndup (const char *, unsigned int); #ifdef CONFIG_WITH_PRINT_STATS_SWITCH void print_heap_stats (void); #endif @@ -551,7 +586,8 @@ void install_default_implicit_rules (void); void build_vpath_lists (void); void construct_vpath_list (char *pattern, char *dirpath); -const char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr); +const char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr, + unsigned int* vpath_index, unsigned int* path_index); int gpath_search (const char *file, unsigned int len); void construct_include_path (const char **arg_dirs); @@ -601,7 +637,9 @@ void alloccache_free (struct alloccache *cache, void *item); MY_INLINE void * alloccache_alloc (struct alloccache *cache) { - struct alloccache_free_ent *f = cache->free_head; + struct alloccache_free_ent *f; +# ifndef CONFIG_WITH_ALLOCCACHE_DEBUG + f = cache->free_head; if (f) cache->free_head = f->next; else if (cache->free_start != cache->free_end) @@ -610,6 +648,7 @@ alloccache_alloc (struct alloccache *cache) cache->free_start += cache->size; } else +# endif f = alloccache_alloc_grow (cache); MAKE_STATS(cache->alloc_count++;); return f; @@ -694,6 +733,17 @@ int strcasecmp (const char *s1, const char *s2); # endif #endif +#if !HAVE_STRNCASECMP +# if HAVE_STRNICMP +# define strncasecmp strnicmp +# elif HAVE_STRNCMPI +# define strncasecmp strncmpi +# else +/* Create our own, in misc.c */ +int strncasecmp (const char *s1, const char *s2, int n); +# endif +#endif + extern const struct floc *reading_file; extern const struct floc **expanding_var; @@ -707,6 +757,8 @@ extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag; extern int print_version_flag, print_directory_flag, check_symlink_flag; extern int warn_undefined_variables_flag, posix_pedantic, not_parallel; extern int second_expansion, clock_skew_detected, rebuilding_makefiles; +extern int one_shell; + #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION extern int second_target_expansion; #endif diff --git a/src/kmk/makefile.com b/src/kmk/makefile.com index be735d0..d2d05d1 100644 --- a/src/kmk/makefile.com +++ b/src/kmk/makefile.com @@ -139,7 +139,7 @@ $ endsubroutine : compileit $! $!----------------------------------------------------------------------------- $!Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -$!2006, 2007 Free Software Foundation, Inc. +$!2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. $!This file is part of GNU Make. $! $!GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/makefile.vms b/src/kmk/makefile.vms index 2243541..1e6a88e 100644 --- a/src/kmk/makefile.vms +++ b/src/kmk/makefile.vms @@ -1,7 +1,7 @@ # -*-Makefile-*- to build GNU make on VMS # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -# 2006, 2007 Free Software Foundation, Inc. +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/misc.c b/src/kmk/misc.c index 8701bb3..0e285b6 100644 --- a/src/kmk/misc.c +++ b/src/kmk/misc.c @@ -1,7 +1,7 @@ /* Miscellaneous generic support functions for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -164,11 +164,13 @@ collapse_continuations (char *line, unsigned int linelen) /* Skip the newline. */ ++in; - /* If the newline is quoted, discard following whitespace - and any preceding whitespace; leave just one space. */ + /* If the newline is escaped, discard following whitespace leaving just + one space. POSIX requires that each backslash/newline/following + whitespace sequence be reduced to a single space. */ if (backslash) { in = next_token (in); + /* Removing this loop will fix Savannah bug #16670: do we want to? */ while (out > line && isblank ((unsigned char)out[-1])) --out; *out++ = ' '; @@ -214,31 +216,57 @@ print_spaces (unsigned int n) } -/* Return a string whose contents concatenate those of s1, s2, s3. +/* Return a string whose contents concatenate the NUM strings provided This string lives in static, re-used memory. */ -char * -concat (const char *s1, const char *s2, const char *s3) +const char * +#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H +concat (unsigned int num, ...) +#else +concat (num, va_alist) + unsigned int num; + va_dcl +#endif { - unsigned int len1, len2, len3; static unsigned int rlen = 0; static char *result = NULL; + unsigned int ri = 0; /* bird: must be unsigned */ - len1 = (s1 && *s1 != '\0') ? strlen (s1) : 0; - len2 = (s2 && *s2 != '\0') ? strlen (s2) : 0; - len3 = (s3 && *s3 != '\0') ? strlen (s3) : 0; +#if USE_VARIADIC + va_list args; +#endif - if (len1 + len2 + len3 + 1 > rlen) - result = xrealloc (result, (rlen = len1 + len2 + len3 + 10)); + VA_START (args, num); - if (len1) - memcpy (result, s1, len1); - if (len2) - memcpy (result + len1, s2, len2); - if (len3) - memcpy (result + len1 + len2, s3, len3); + while (num-- > 0) + { + const char *s = va_arg (args, const char *); + unsigned int l = s ? strlen (s) : 0; + + if (l == 0) + continue; + + if (ri + l > rlen) + { + rlen = ((rlen ? rlen : 60) + l) * 2; + result = xrealloc (result, rlen); + } + + memcpy (result + ri, s, l); + ri += l; + } + + VA_END (args); + + /* Get some more memory if we don't have enough space for the + terminating '\0'. */ + if (ri == rlen) + { + rlen = (rlen ? rlen : 60) * 2; + result = xrealloc (result, rlen); + } - result[len1+len2+len3] = '\0'; + result[ri] = '\0'; return result; } @@ -391,13 +419,14 @@ pfatal_with_name (const char *name) #if !defined(HAVE_DMALLOC_H) && !defined(ELECTRIC_HEAP) /* bird */ #undef xmalloc +#undef xcalloc #undef xrealloc #undef xstrdup void * xmalloc (unsigned int size) { - /* Make sure we don't allocate 0, for pre-ANSI libraries. */ + /* Make sure we don't allocate 0, for pre-ISO implementations. */ void *result = malloc (size ? size : 1); if (result == 0) fatal (NILF, _("virtual memory exhausted")); @@ -414,6 +443,17 @@ xmalloc (unsigned int size) void * +xcalloc (unsigned int size) +{ + /* Make sure we don't allocate 0, for pre-ISO implementations. */ + void *result = calloc (size ? size : 1, 1); + if (result == 0) + fatal (NILF, _("virtual memory exhausted")); + return result; +} + + +void * xrealloc (void *ptr, unsigned int size) { void *result; @@ -426,7 +466,7 @@ xrealloc (void *ptr, unsigned int size) make_stats_allocations++; #endif - /* Some older implementations of realloc() don't conform to ANSI. */ + /* Some older implementations of realloc() don't conform to ISO. */ if (! size) size = 1; result = ptr ? realloc (ptr, size) : malloc (size); @@ -474,13 +514,22 @@ xstrdup (const char *ptr) #endif /* HAVE_DMALLOC_H */ char * -savestring (const char *str, unsigned int length) +xstrndup (const char *str, unsigned int length) { - char *out = xmalloc (length + 1); + char *result; + +#if defined(HAVE_STRNDUP) && !defined(KMK) + result = strndup (str, length); + if (result == 0) + fatal (NILF, _("virtual memory exhausted")); +#else + result = xmalloc (length + 1); if (length > 0) - memcpy (out, str, length); - out[length] = '\0'; - return out; + strncpy (result, str, length); + result[length] = '\0'; +#endif + + return result; } @@ -777,35 +826,7 @@ find_next_token_eos (const char **ptr, const char *eos, unsigned int *lengthptr) #endif /* KMK */ -/* Allocate a new `struct dep' with all fields initialized to 0. */ - -struct dep * -alloc_dep () -{ -#ifndef CONFIG_WITH_ALLOC_CACHES - struct dep *d = xmalloc (sizeof (struct dep)); - memset (d, '\0', sizeof (struct dep)); - return d; -#else - return (struct dep *) alloccache_calloc (&dep_cache); -#endif -} - - -/* Free `struct dep' along with `name' and `stem'. */ - -void -free_dep (struct dep *d) -{ -#ifndef CONFIG_WITH_ALLOC_CACHES - free (d); -#else - alloccache_free (&dep_cache, d); -#endif -} - -/* Copy a chain of `struct dep', making a new chain - with the same contents as the old one. */ +/* Copy a chain of `struct dep'. For 2nd expansion deps, dup the name. */ struct dep * copy_dep_chain (const struct dep *d) @@ -818,10 +839,14 @@ copy_dep_chain (const struct dep *d) #ifndef CONFIG_WITH_ALLOC_CACHES struct dep *c = xmalloc (sizeof (struct dep)); #else - struct dep *c = (struct dep *) alloccache_alloc (&dep_cache); + struct dep *c = alloccache_alloc(&dep_cache); #endif memcpy (c, d, sizeof (struct dep)); + /** @todo KMK: Check if we need this duplication! */ + if (c->need_2nd_expansion) + c->name = xstrdup (c->name); + c->next = 0; if (firstnew == 0) firstnew = lastnew = c; @@ -843,11 +868,7 @@ free_dep_chain (struct dep *d) { struct dep *df = d; d = d->next; -#ifndef CONFIG_WITH_ALLOC_CACHES free_dep (df); -#else - alloccache_free (&dep_cache, df); -#endif } } @@ -895,6 +916,34 @@ strcasecmp (const char *s1, const char *s2) } } #endif + +#if !HAVE_STRNCASECMP && !HAVE_STRNICMP && !HAVE_STRNCMPI + +/* If we don't have strncasecmp() (from POSIX), or anything that can + substitute for it, define our own version. */ + +int +strncasecmp (const char *s1, const char *s2, int n) +{ + while (n-- > 0) + { + int c1 = (int) *(s1++); + int c2 = (int) *(s2++); + + if (isalpha (c1)) + c1 = tolower (c1); + if (isalpha (c2)) + c2 = tolower (c2); + + if (c1 != '\0' && c1 == c2) + continue; + + return (c1 - c2); + } + + return 0; +} +#endif #ifdef GETLOADAVG_PRIVILEGED @@ -1221,12 +1270,14 @@ print_heap_stats (void) malloc_statistics_t s; malloc_zone_statistics (NULL, &s); - printf (_("\n# CRT Heap: %zu bytes in use, in %u blocks, avg %zu bytes/block\n"), - s.size_in_use, s.blocks_in_use, s.size_in_use / s.blocks_in_use); - printf (_("# %zu bytes max in use (high water mark)\n"), - s.max_size_in_use); - printf (_("# %zu bytes reserved, %zu bytes free (estimate)\n"), - s.size_allocated, s.size_allocated - s.size_in_use); + printf (_("\n# CRT Heap: %u bytes in use, in %u blocks, avg %u bytes/block\n"), + (unsigned)s.size_in_use, (unsigned)s.blocks_in_use, + (unsigned)(s.size_in_use / s.blocks_in_use)); + printf (_("# %u bytes max in use (high water mark)\n"), + (unsigned)s.max_size_in_use); + printf (_("# %u bytes reserved, %u bytes free (estimate)\n"), + (unsigned)s.size_allocated, + (unsigned)(s.size_allocated - s.size_in_use)); # endif /* __APPLE__ */ /* MSC / Windows */ @@ -1361,7 +1412,7 @@ nano_timestamp (void) int format_elapsed_nano (char *buf, size_t size, big_int ts) { - int sz; + unsigned sz; if (ts < 1000) sz = sprintf (buf, "%uns", (unsigned)ts); else if (ts < 100000) @@ -1394,8 +1445,8 @@ format_elapsed_nano (char *buf, size_t size, big_int ts) } } if (sz >= size) - fatal (NILF, _("format_elapsed_nano buffer overflow: %d written, %d buffer"), - sz, size); + fatal (NILF, _("format_elapsed_nano buffer overflow: %u written, %lu buffer"), + sz, (unsigned long)size); return sz; } #endif /* CONFIG_WITH_PRINT_TIME_SWITCH */ diff --git a/src/kmk/po/ChangeLog b/src/kmk/po/ChangeLog index fe77970..dbc21b4 100644 --- a/src/kmk/po/ChangeLog +++ b/src/kmk/po/ChangeLog @@ -1,3 +1,7 @@ +2009-09-16 Paul Smith <psmith@gnu.org> + + * LINGUAS: Added new translation for Italian (it). + 2008-05-17 Paul Smith <psmith@gnu.org> * LINGUAS: Added new translation for Lithuanian (lt). @@ -61,7 +65,8 @@ * POTFILES.in, LINGUAS, Makevars: Created. -Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software +Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/po/LINGUAS b/src/kmk/po/LINGUAS index b54908b..6774713 100644 --- a/src/kmk/po/LINGUAS +++ b/src/kmk/po/LINGUAS @@ -1,5 +1,5 @@ -# Set of available languages: 23 languages +# Set of available languages: 24 languages -be da de es fi fr ga gl he hr id ja ko lt nl pl pt_BR ru sv tr uk vi zh_CN +be da de es fi fr ga gl he hr id it ja ko lt nl pl pt_BR ru sv tr uk vi zh_CN # Can't seem to get en@quot and en@boldquot to build properly? diff --git a/src/kmk/po/Makevars b/src/kmk/po/Makevars index 21f587c..2103ce8 100644 --- a/src/kmk/po/Makevars +++ b/src/kmk/po/Makevars @@ -1,6 +1,6 @@ # This is a -*-Makefile-*- -# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, -# Inc. +# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free +# Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/po/POTFILES.in b/src/kmk/po/POTFILES.in index f4f8b9d..d8f34c8 100644 --- a/src/kmk/po/POTFILES.in +++ b/src/kmk/po/POTFILES.in @@ -1,6 +1,6 @@ # List of source files containing translatable strings. -# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -# Foundation, Inc. +# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +# 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/read.c b/src/kmk/read.c index 8d8087e..ebc6a63 100644 --- a/src/kmk/read.c +++ b/src/kmk/read.c @@ -1,7 +1,7 @@ /* Reading and parsing of makefiles for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -61,6 +61,18 @@ struct ebuffer struct floc floc; /* Info on the file in fp (if any). */ }; +/* Track the modifiers we can have on variable assignments */ + +struct vmodifiers + { + unsigned int assign_v:1; + unsigned int define_v:1; + unsigned int undefine_v:1; + unsigned int export_v:1; + unsigned int override_v:1; + unsigned int private_v:1; + }; + /* Types of "words" that can be read in a makefile. */ enum make_word_type { @@ -148,25 +160,26 @@ const struct floc *reading_file = 0; static struct dep *read_makefiles = 0; static int eval_makefile (const char *filename, int flags); -static int eval (struct ebuffer *buffer, int flags); +static void eval (struct ebuffer *buffer, int flags); static long readline (struct ebuffer *ebuf); -static void do_define (char *name, unsigned int namelen, - enum variable_origin origin, struct ebuffer *ebuf); +static void do_undefine (char *name, enum variable_origin origin, + struct ebuffer *ebuf); +static struct variable *do_define (char *name IF_WITH_VALUE_LENGTH_PARAM(char *eos), + enum variable_origin origin, struct ebuffer *ebuf); #ifndef CONFIG_WITH_VALUE_LENGTH static int conditional_line (char *line, int len, const struct floc *flocp); #else static int conditional_line (char *line, char *eol, int len, const struct floc *flocp); #endif -#ifndef CONFIG_WITH_INCLUDEDEP static void record_files (struct nameseq *filenames, const char *pattern, - const char *pattern_percent, struct dep *deps, + const char *pattern_percent, char *depstr, unsigned int cmds_started, char *commands, unsigned int commands_idx, int two_colon, const struct floc *flocp); -#endif /* !KMK */ static void record_target_var (struct nameseq *filenames, char *defn, - enum variable_origin origin, int enabled, + enum variable_origin origin, + struct vmodifiers *vmod, const struct floc *flocp); static enum make_word_type get_next_mword (char *buffer, char *delim, char **startp, unsigned int *length); @@ -195,6 +208,13 @@ find_char_unquote (char *string, int stop1, int stop2, int blank, int ignorevars return find_char_unquote_2 (string, stop1, stop2, blank, ignorevars, 0); } #endif /* CONFIG_WITH_VALUE_LENGTH */ + + +/* Compare a word, both length and contents. + P must point to the word to be tested, and WLEN must be the length. +*/ +#define word1eq(s) (wlen == sizeof(s)-1 && strneq (s, p, sizeof(s)-1)) + /* Read in all the makefiles and return the chain of their names. */ @@ -206,7 +226,7 @@ read_all_makefiles (const char **makefiles) /* Create *_LIST variables, to hold the makefiles, targets, and variables we will be reading. */ - define_variable ("MAKEFILE_LIST", sizeof ("MAKEFILE_LIST")-1, "", o_file, 0); + define_variable_cname ("MAKEFILE_LIST", "", o_file, 0); DB (DB_BASIC, (_("Reading makefiles...\n"))); @@ -318,7 +338,7 @@ read_all_makefiles (const char **makefiles) { struct dep *d = alloc_dep (); d->file = enter_file (strcache_add (*p)); - d->file->dontcare = 1; + d->dontcare = 1; /* Tell update_goal_chain to bail out as soon as this file is made, and main not to die if we can't make this file. */ d->changed = RM_DONTCARE; @@ -384,7 +404,6 @@ eval_makefile (const char *filename, int flags) const struct floc *curfile; char *expanded = 0; int makefile_errno; - int r; filename = strcache_add (filename); ebuf.floc.filenm = filename; @@ -427,7 +446,8 @@ eval_makefile (const char *filename, int flags) unsigned int i; for (i = 0; include_directories[i] != 0; ++i) { - const char *included = concat (include_directories[i], "/", filename); + const char *included = concat (3, include_directories[i], + "/", filename); ebuf.fp = fopen (included, "r"); if (ebuf.fp) { @@ -451,7 +471,7 @@ eval_makefile (const char *filename, int flags) filename = deps->file->name; deps->changed = flags; if (flags & RM_DONTCARE) - deps->file->dontcare = 1; + deps->dontcare = 1; if (expanded) free (expanded); @@ -467,6 +487,12 @@ eval_makefile (const char *filename, int flags) return 0; } + /* Set close-on-exec to avoid leaking the makefile to children, such as + $(shell ...). */ +#ifdef HAVE_FILENO + CLOSE_ON_EXEC (fileno (ebuf.fp)); +#endif + /* Add this makefile to the list. */ do_variable_definition (&ebuf.floc, "MAKEFILE_LIST", filename, o_file, f_append, 0); @@ -502,7 +528,7 @@ eval_makefile (const char *filename, int flags) curfile = reading_file; reading_file = &ebuf.floc; - r = eval (&ebuf, !(flags & RM_NO_DEFAULT_GOAL)); + eval (&ebuf, !(flags & RM_NO_DEFAULT_GOAL)); reading_file = curfile; @@ -515,10 +541,11 @@ eval_makefile (const char *filename, int flags) #endif free (ebuf.bufstart); alloca (0); - return r; + + return 1; } -int +void #ifndef CONFIG_WITH_VALUE_LENGTH eval_buffer (char *buffer) #else @@ -529,7 +556,6 @@ eval_buffer (char *buffer, char *eos) struct conditionals *saved; struct conditionals new; const struct floc *curfile; - int r; /* Evaluate the buffer */ @@ -543,30 +569,105 @@ eval_buffer (char *buffer, char *eos) ebuf.buffer = ebuf.bufnext = ebuf.bufstart = buffer; ebuf.fp = NULL; - ebuf.floc = *reading_file; + if (reading_file) + ebuf.floc = *reading_file; + else + ebuf.floc.filenm = NULL; curfile = reading_file; reading_file = &ebuf.floc; saved = install_conditionals (&new); - r = eval (&ebuf, 1); + eval (&ebuf, 1); restore_conditionals (saved); reading_file = curfile; alloca (0); - return r; } + +/* Check LINE to see if it's a variable assignment or undefine. + + It might use one of the modifiers "export", "override", "private", or it + might be one of the conditional tokens like "ifdef", "include", etc. + + If it's not a variable assignment or undefine, VMOD.V_ASSIGN is 0. + Returns LINE. + + Returns a pointer to the first non-modifier character, and sets VMOD + based on the modifiers found if any, plus V_ASSIGN is 1. + */ +static char * +parse_var_assignment (const char *line, struct vmodifiers *vmod) +{ + const char *p; + memset (vmod, '\0', sizeof (*vmod)); + + /* Find the start of the next token. If there isn't one we're done. */ + line = next_token (line); + if (*line == '\0') + return (char *)line; + + p = line; + while (1) + { + int wlen; + const char *p2; + enum variable_flavor flavor; + + p2 = parse_variable_definition (p, &flavor); + + /* If this is a variable assignment, we're done. */ + if (p2) + break; + + /* It's not a variable; see if it's a modifier. */ + p2 = end_of_token (p); + wlen = p2 - p; + + if (word1eq ("export")) + vmod->export_v = 1; + else if (word1eq ("override")) + vmod->override_v = 1; + else if (word1eq ("private")) + vmod->private_v = 1; + else if (word1eq ("define")) + { + /* We can't have modifiers after 'define' */ + vmod->define_v = 1; + p = next_token (p2); + break; + } + else if (word1eq ("undefine")) + { + /* We can't have modifiers after 'undefine' */ + vmod->undefine_v = 1; + p = next_token (p2); + break; + } + else + /* Not a variable or modifier: this is not a variable assignment. */ + return (char *)line; + /* It was a modifier. Try the next word. */ + p = next_token (p2); + if (*p == '\0') + return (char *)line; + } + + /* Found a variable assignment or undefine. */ + vmod->assign_v = 1; + return (char *)p; +} + /* Read file FILENAME as a makefile and add its contents to the data base. SET_DEFAULT is true if we are allowed to set the default goal. */ - -static int +static void eval (struct ebuffer *ebuf, int set_default) { char *collapsed = 0; @@ -578,7 +679,7 @@ eval (struct ebuffer *ebuf, int set_default) int ignoring = 0, in_ignored_define = 0; int no_targets = 0; /* Set when reading a rule without targets. */ struct nameseq *filenames = 0; - struct dep *deps = 0; + char *depstr = 0; long nlines = 0; int two_colon = 0; const char *pattern = 0; @@ -599,11 +700,11 @@ eval (struct ebuffer *ebuf, int set_default) if (filenames != 0) \ { \ fi.lineno = tgts_started; \ - record_files (filenames, pattern, pattern_percent, deps, \ + record_files (filenames, pattern, pattern_percent, depstr, \ cmds_started, commands, commands_idx, two_colon, \ &fi); \ + filenames = 0; \ } \ - filenames = 0; \ commands_idx = 0; \ no_targets = 0; \ pattern = 0; \ @@ -637,7 +738,9 @@ eval (struct ebuffer *ebuf, int set_default) unsigned int wlen; char *p; char *p2; + struct vmodifiers vmod; + /* At the top of this loop, we are starting a brand new line. */ /* Grab the next line to be evaluated */ ebuf->floc.lineno += nlines; nlines = readline (ebuf); @@ -667,7 +770,7 @@ eval (struct ebuffer *ebuf, int set_default) continue; /* If there is no preceding rule line, don't treat this line - as a command, even though it begins with a tab character. + as a command, even though it begins with a recipe prefix. SunOS 4 make appears to behave this way. */ if (filenames != 0) @@ -706,7 +809,7 @@ eval (struct ebuffer *ebuf, int set_default) } } - /* This line is not a shell command line. Don't worry about tabs. + /* This line is not a shell command line. Don't worry about whitespace. Get more space if we need it; we don't need to preserve the current contents of the buffer. */ @@ -715,6 +818,7 @@ eval (struct ebuffer *ebuf, int set_default) collapsed_length = linelen+1; if (collapsed) free (collapsed); + /* Don't need xrealloc: we don't need to preserve the content. */ collapsed = xmalloc (collapsed_length); } #ifndef CONFIG_WITH_VALUE_LENGTH @@ -731,127 +835,90 @@ eval (struct ebuffer *ebuf, int set_default) assert (strchr (collapsed, '\0') == eol); #endif - /* Compare a word, both length and contents. */ -#define word1eq(s) (wlen == sizeof(s)-1 && strneq (s, p, sizeof(s)-1)) + /* Get rid if starting space (including formfeed, vtab, etc.) */ p = collapsed; while (isspace ((unsigned char)*p)) - ++p; + ++p; - if (*p == '\0') - /* This line is completely empty--ignore it. */ - continue; + /* See if this is a variable assignment. We need to do this early, to + allow variables with names like 'ifdef', 'export', 'private', etc. */ + p = parse_var_assignment(p, &vmod); + if (vmod.assign_v) + { + struct variable *v; + enum variable_origin origin = vmod.override_v ? o_override : o_file; - /* Find the end of the first token. Note we don't need to worry about - * ":" here since we compare tokens by length (so "export" will never - * be equal to "export:"). - */ - for (p2 = p+1; *p2 != '\0' && !isspace ((unsigned char)*p2); ++p2) - ; - wlen = p2 - p; + /* If we're ignoring then we're done now. */ + if (ignoring) + { + if (vmod.define_v) + in_ignored_define = 1; + continue; + } - /* Find the start of the second token. If it looks like a target or - variable definition it can't be a preprocessor token so skip - them--this allows variables/targets named `ifdef', `export', etc. */ - while (isspace ((unsigned char)*p2)) - ++p2; + if (vmod.undefine_v) + { + do_undefine (p, origin, ebuf); - if ((p2[0] == ':' || p2[0] == '+' || p2[0] == '=') && p2[1] == '\0') - { - /* It can't be a preprocessor token so skip it if we're ignoring */ - if (ignoring) - continue; + /* This line has been dealt with. */ + goto rule_complete; + } + else if (vmod.define_v) + v = do_define (p IF_WITH_VALUE_LENGTH_PARAM(NULL), origin, ebuf); + else + v = try_variable_definition (fstart, p IF_WITH_VALUE_LENGTH_PARAM(NULL), origin, 0); - goto skip_conditionals; - } + assert (v != NULL); - /* We must first check for conditional and `define' directives before - ignoring anything, since they control what we will do with - following lines. */ + if (vmod.export_v) + v->export = v_export; + if (vmod.private_v) + v->private_var = 1; - if (!in_ignored_define) - { -#ifndef CONFIG_WITH_VALUE_LENGTH - int i = conditional_line (p, wlen, fstart); -#else - int i = conditional_line (p, eol, wlen, fstart); -#endif - if (i != -2) - { - if (i == -1) - fatal (fstart, _("invalid syntax in conditional")); + /* This line has been dealt with. */ + goto rule_complete; + } - ignoring = i; - continue; - } - } + /* If this line is completely empty, ignore it. */ + if (*p == '\0') + continue; - if (word1eq ("endef")) - { - if (!in_ignored_define) - fatal (fstart, _("extraneous `endef'")); - in_ignored_define = 0; - continue; - } + p2 = end_of_token (p); + wlen = p2 - p; + p2 = next_token (p2); - if (word1eq ("define")) + /* If we're in an ignored define, skip this line (but maybe get out). */ + if (in_ignored_define) { - if (ignoring) - in_ignored_define = 1; - else - { - if (*p2 == '\0') - fatal (fstart, _("empty variable name")); - - /* Let the variable name be the whole rest of the line, - with trailing blanks stripped (comments have already been - removed), so it could be a complex variable/function - reference that might contain blanks. */ - p = strchr (p2, '\0'); - while (isblank ((unsigned char)p[-1])) - --p; - do_define (p2, p - p2, o_file, ebuf); - } + /* See if this is an endef line (plus optional comment). */ + if (word1eq ("endef") && (*p2 == '\0' || *p2 == '#')) + in_ignored_define = 0; + continue; } - if (word1eq ("override")) - { - if (*p2 == '\0') - error (fstart, _("empty `override' directive")); - - if (strneq (p2, "define", 6) - && (isblank ((unsigned char)p2[6]) || p2[6] == '\0')) - { - if (ignoring) - in_ignored_define = 1; - else - { - p2 = next_token (p2 + 6); - if (*p2 == '\0') - fatal (fstart, _("empty variable name")); - - /* Let the variable name be the whole rest of the line, - with trailing blanks stripped (comments have already been - removed), so it could be a complex variable/function - reference that might contain blanks. */ - p = strchr (p2, '\0'); - while (isblank ((unsigned char)p[-1])) - --p; - do_define (p2, p - p2, o_override, ebuf); - } - } - else if (!ignoring + /* Check for conditional state changes. */ + { #ifndef CONFIG_WITH_VALUE_LENGTH - && !try_variable_definition (fstart, p2, o_override, 0)) + int i = conditional_line (p, wlen, fstart); #else - && !try_variable_definition (fstart, p2, eol, o_override, 0)) + int i = conditional_line (p, eol, wlen, fstart); #endif - error (fstart, _("invalid `override' directive")); + if (i != -2) + { + if (i == -1) + fatal (fstart, _("invalid syntax in conditional")); - continue; - } -#ifdef CONFIG_WITH_LOCAL_VARIABLES + ignoring = i; + continue; + } + } + /* Nothing to see here... move along. */ + if (ignoring) + continue; + +#ifdef CONFIG_WITH_LOCAL_VARIABLES if (word1eq ("local")) { if (*p2 == '\0') @@ -875,26 +942,17 @@ eval (struct ebuffer *ebuf, int set_default) p = strchr (p2, '\0'); while (isblank ((unsigned char)p[-1])) --p; - do_define (p2, p - p2, o_local, ebuf); + do_define (p2 IF_WITH_VALUE_LENGTH_PARAM(p), o_local, ebuf); } } else if (!ignoring -# ifndef CONFIG_WITH_VALUE_LENGTH - && !try_variable_definition (fstart, p2, o_local, 0)) -# else - && !try_variable_definition (fstart, p2, eol, o_local, 0)) -# endif + && !try_variable_definition (fstart, p2 IF_WITH_VALUE_LENGTH_PARAM(eol), o_local, 0)) error (fstart, _("invalid `local' directive")); continue; } #endif /* CONFIG_WITH_LOCAL_VARIABLES */ - if (ignoring) - /* Ignore the line. We continue here so conditionals - can appear in the middle of a rule. */ - continue; - #ifdef KMK /* Check for the kBuild language extensions. */ if ( wlen >= sizeof("kBuild-define") - 1 @@ -913,69 +971,24 @@ eval (struct ebuffer *ebuf, int set_default) } #endif /* KMK */ - if (word1eq ("export")) - { - /* 'export' by itself causes everything to be exported. */ - if (*p2 == '\0') - export_all_variables = 1; - else - { - struct variable *v; - -#ifndef CONFIG_WITH_VALUE_LENGTH - v = try_variable_definition (fstart, p2, o_file, 0); -#else - v = try_variable_definition (fstart, p2, eol, o_file, 0); -#endif - if (v != 0) - v->export = v_export; - else - { - unsigned int l; - const char *cp; - char *ap; - - /* Expand the line so we can use indirect and constructed - variable names in an export command. */ -#ifndef CONFIG_WITH_VALUE_LENGTH - cp = ap = allocated_variable_expand (p2); -#else - unsigned int buf_len; - cp = ap = allocated_variable_expand_3 (p2, eol - p2, NULL, &buf_len); -#endif - - for (p = find_next_token (&cp, &l); p != 0; - p = find_next_token (&cp, &l)) - { - v = lookup_variable (p, l); - if (v == 0) - v = define_variable_loc (p, l, "", o_file, 0, fstart); - v->export = v_export; - } - -#ifndef CONFIG_WITH_VALUE_LENGTH - free (ap); -#else - recycle_variable_buffer (ap, buf_len); -#endif - } - } - goto rule_complete; - } - if (word1eq ("unexport")) + /* Manage the "export" keyword used outside of variable assignment + as well as "unexport". */ + if (word1eq ("export") || word1eq ("unexport")) { + int exporting = *p == 'u' ? 0 : 1; + + /* (un)export by itself causes everything to be (un)exported. */ if (*p2 == '\0') - export_all_variables = 0; + export_all_variables = exporting; else { unsigned int l; - struct variable *v; const char *cp; char *ap; /* Expand the line so we can use indirect and constructed - variable names in an unexport command. */ + variable names in an (un)export command. */ #ifndef CONFIG_WITH_VALUE_LENGTH cp = ap = allocated_variable_expand (p2); #else @@ -986,11 +999,10 @@ eval (struct ebuffer *ebuf, int set_default) for (p = find_next_token (&cp, &l); p != 0; p = find_next_token (&cp, &l)) { - v = lookup_variable (p, l); + struct variable *v = lookup_variable (p, l); if (v == 0) v = define_variable_loc (p, l, "", o_file, 0, fstart); - - v->export = v_noexport; + v->export = exporting ? v_export : v_noexport; } #ifndef CONFIG_WITH_VALUE_LENGTH @@ -1002,7 +1014,7 @@ eval (struct ebuffer *ebuf, int set_default) goto rule_complete; } - skip_conditionals: + /* Handle the special syntax for vpath. */ if (word1eq ("vpath")) { const char *cp; @@ -1012,7 +1024,7 @@ eval (struct ebuffer *ebuf, int set_default) p = find_next_token (&cp, &l); if (p != 0) { - vpat = savestring (p, l); + vpat = xstrndup (p, l); p = find_next_token (&cp, &l); /* No searchpath means remove all previous selective VPATH's with the same pattern. */ @@ -1064,6 +1076,7 @@ eval (struct ebuffer *ebuf, int set_default) } #endif /* CONFIG_WITH_INCLUDEDEP */ + /* Handle include and variants. */ if (word1eq ("include") || word1eq ("-include") || word1eq ("sinclude")) { /* We have found an `include' line specifying a nested @@ -1093,17 +1106,10 @@ eval (struct ebuffer *ebuf, int set_default) continue; } - /* Parse the list of file names. */ + /* Parse the list of file names. Don't expand archive references! */ p2 = p; -#ifndef CONFIG_WITH_ALLOC_CACHES - files = multi_glob (parse_file_seq (&p2, '\0', - sizeof (struct nameseq), - 1), - sizeof (struct nameseq)); -#else - files = multi_glob (parse_file_seq (&p2, '\0', &nameseq_cache, 1), - &nameseq_cache); -#endif + files = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL, + PARSEFS_NOAR); #ifndef CONFIG_WITH_VALUE_LENGTH free (p); #else @@ -1125,15 +1131,13 @@ eval (struct ebuffer *ebuf, int set_default) const char *name = files->name; int r; -#ifndef CONFIG_WITH_ALLOC_CACHES - free (files); -#else - alloccache_free (&nameseq_cache, files); -#endif + free_ns (files); files = next; - r = eval_makefile (name, (RM_INCLUDED | RM_NO_TILDE - | (noerror ? RM_DONTCARE : 0))); + r = eval_makefile (name, + (RM_INCLUDED | RM_NO_TILDE + | (noerror ? RM_DONTCARE : 0) + | (set_default ? 0 : RM_NO_DEFAULT_GOAL))); if (!r && !noerror) error (fstart, "%s: %s", name, strerror (errno)); } @@ -1144,14 +1148,6 @@ eval (struct ebuffer *ebuf, int set_default) goto rule_complete; } -#ifndef CONFIG_WITH_VALUE_LENGTH - if (try_variable_definition (fstart, p, o_file, 0)) -#else - if (try_variable_definition (fstart, p, eol, o_file, 0)) -#endif - /* This line has been dealt with. */ - goto rule_complete; - /* This line starts with a tab but was not caught above because there was no preceding target, and the line might have been usable as a variable definition. But now we know it is definitely lossage. */ @@ -1170,8 +1166,6 @@ eval (struct ebuffer *ebuf, int set_default) { enum make_word_type wtype; - enum variable_origin v_origin; - int exported; char *cmdleft, *semip, *lb_next; unsigned int plen = 0; char *colonp; @@ -1342,15 +1336,7 @@ eval (struct ebuffer *ebuf, int set_default) /* Make the colon the end-of-string so we know where to stop looking for targets. */ *colonp = '\0'; -#ifndef CONFIG_WITH_ALLOC_CACHES - filenames = multi_glob (parse_file_seq (&p2, '\0', - sizeof (struct nameseq), - 1), - sizeof (struct nameseq)); -#else - filenames = multi_glob (parse_file_seq (&p2, '\0', &nameseq_cache, 1), - &nameseq_cache); -#endif + filenames = PARSE_FILE_SEQ (&p2, struct nameseq, '\0', NULL, 0); *p2 = ':'; if (!filenames) @@ -1381,31 +1367,8 @@ eval (struct ebuffer *ebuf, int set_default) p2 = variable_buffer + l; } - /* See if it's an "override" or "export" keyword; if so see if what - comes after it looks like a variable definition. */ - - wtype = get_next_mword (p2, NULL, &p, &wlen); - - v_origin = o_file; - exported = 0; - if (wtype == w_static) - { - if (word1eq ("override")) - { - v_origin = o_override; - wtype = get_next_mword (p+wlen, NULL, &p, &wlen); - } - else if (word1eq ("export")) - { - exported = 1; - wtype = get_next_mword (p+wlen, NULL, &p, &wlen); - } - } - - if (wtype != w_eol) - wtype = get_next_mword (p+wlen, NULL, NULL, NULL); - - if (wtype == w_varassign) + p2 = parse_var_assignment (p2, &vmod); + if (vmod.assign_v) { /* If there was a semicolon found, add it back, plus anything after it. */ @@ -1413,11 +1376,18 @@ eval (struct ebuffer *ebuf, int set_default) { unsigned int l = p - variable_buffer; *(--semip) = ';'; +#ifndef CONFIG_WITH_VALUE_LENGTH + collapse_continuations (semip); +#else + collapse_continuations (semip, strlen(semip)); /** @todo fix this */ +#endif variable_buffer_output (p2 + strlen (p2), semip, strlen (semip)+1); p = variable_buffer + l; } - record_target_var (filenames, p, v_origin, exported, fstart); + record_target_var (filenames, p2, + vmod.override_v ? o_override : o_file, + &vmod, fstart); filenames = 0; continue; } @@ -1458,8 +1428,8 @@ eval (struct ebuffer *ebuf, int set_default) p = strchr (p2, ':'); while (p != 0 && p[-1] == '\\') { - register char *q = &p[-1]; - register int backslash = 0; + char *q = &p[-1]; + int backslash = 0; while (*q-- == '\\') backslash = !backslash; if (backslash) @@ -1502,11 +1472,8 @@ eval (struct ebuffer *ebuf, int set_default) if (p != 0) { struct nameseq *target; -#ifndef CONFIG_WITH_ALLOC_CACHES - target = parse_file_seq (&p2, ':', sizeof (struct nameseq), 1); -#else - target = parse_file_seq (&p2, ':', &nameseq_cache, 1); -#endif + target = PARSE_FILE_SEQ (&p2, struct nameseq, ':', NULL, + PARSEFS_NOGLOB); ++p2; if (target == 0) fatal (fstart, _("missing target pattern")); @@ -1516,11 +1483,7 @@ eval (struct ebuffer *ebuf, int set_default) pattern = target->name; if (pattern_percent == 0) fatal (fstart, _("target pattern contains no `%%' (target `%s')"), target->name); /* bird */ -#ifndef CONFIG_WITH_ALLOC_CACHES - free (target); -#else - alloccache_free (&nameseq_cache, target); -#endif + free_ns (target); } else pattern = 0; @@ -1530,25 +1493,11 @@ eval (struct ebuffer *ebuf, int set_default) end = beg + strlen (beg) - 1; strip_whitespace (&beg, &end); + /* Put all the prerequisites here; they'll be parsed later. */ if (beg <= end && *beg != '\0') - { - /* Put all the prerequisites here; they'll be parsed later. */ - deps = alloc_dep (); -#ifndef CONFIG_WITH_VALUE_LENGTH - deps->name = strcache_add_len (beg, end - beg + 1); -#else /* CONFIG_WITH_VALUE_LENGTH */ - { - /* Make sure the strcache_add_len input is terminated so it - doesn't have to make a temporary copy on the stack. */ - char saved = end[1]; - ((char *)end)[1] = '\0'; - deps->name = strcache_add_len (beg, end - beg + 1); - ((char *)end)[1] = saved; - } -#endif /* CONFIG_WITH_VALUE_LENGTH */ - } + depstr = xstrndup (beg, end - beg + 1); else - deps = 0; + depstr = 0; commands_idx = 0; if (cmdleft != 0) @@ -1582,10 +1531,9 @@ eval (struct ebuffer *ebuf, int set_default) Because the target is not recorded until after ifeq directive is evaluated the .DEFAULT_GOAL does not contain foo yet as one - would expect. Because of this we have to move some of the logic - here. */ + would expect. Because of this we have to move the logic here. */ - if (**default_goal_name == '\0' && set_default) + if (set_default && default_goal_var->value[0] == '\0') { const char *name; struct dep *d; @@ -1675,8 +1623,6 @@ eval (struct ebuffer *ebuf, int set_default) if (collapsed) free (collapsed); free (commands); - - return 1; } @@ -1752,42 +1698,83 @@ remove_comments (char *line, char *eol) } #endif /* CONFIG_WITH_VALUE_LENGTH */ +/* Execute a `undefine' directive. + The undefine line has already been read, and NAME is the name of + the variable to be undefined. */ + +static void +do_undefine (char *name, enum variable_origin origin, struct ebuffer *ebuf) +{ + char *p, *var; + + /* Expand the variable name and find the beginning (NAME) and end. */ + var = allocated_variable_expand (name); + name = next_token (var); + if (*name == '\0') + fatal (&ebuf->floc, _("empty variable name")); + p = name + strlen (name) - 1; + while (p > name && isblank ((unsigned char)*p)) + --p; + p[1] = '\0'; + + undefine_variable_global (name, p - name + 1, origin); + free (var); +} + /* Execute a `define' directive. The first line has already been read, and NAME is the name of the variable to be defined. The following lines remain to be read. */ -static void -do_define (char *name, unsigned int namelen, +static struct variable * +do_define (char *name IF_WITH_VALUE_LENGTH_PARAM(char *eos), enum variable_origin origin, struct ebuffer *ebuf) { + struct variable *v; + enum variable_flavor flavor; struct floc defstart; - long nlines = 0; int nlevels = 1; unsigned int length = 100; char *definition = xmalloc (length); unsigned int idx = 0; - char *p; - - /* Expand the variable name. */ - char *var = alloca (namelen + 1); - memcpy (var, name, namelen); - var[namelen] = '\0'; - var = variable_expand (var); + char *p, *var; defstart = ebuf->floc; + p = parse_variable_definition (name, &flavor); + if (p == NULL) + /* No assignment token, so assume recursive. */ + flavor = f_recursive; + else + { + if (*(next_token (p)) != '\0') + error (&defstart, _("extraneous text after `define' directive")); + + /* Chop the string before the assignment token to get the name. */ + p[flavor == f_recursive ? -1 : -2] = '\0'; + } + + /* Expand the variable name and find the beginning (NAME) and end. */ + var = allocated_variable_expand (name); + name = next_token (var); + if (*name == '\0') + fatal (&defstart, _("empty variable name")); + p = name + strlen (name) - 1; + while (p > name && isblank ((unsigned char)*p)) + --p; + p[1] = '\0'; + + /* Now read the value of the variable. */ while (1) { unsigned int len; char *line; + long nlines = readline (ebuf); - nlines = readline (ebuf); - ebuf->floc.lineno += nlines; - - /* If there is nothing left to eval, we're done. */ + /* If there is nothing left to be eval'd, there's no 'endef'!! */ if (nlines < 0) - break; + fatal (&defstart, _("missing `endef', unterminated `define'")); + ebuf->floc.lineno += nlines; line = ebuf->buffer; #ifndef CONFIG_WITH_VALUE_LENGTH @@ -1797,9 +1784,7 @@ do_define (char *name, unsigned int namelen, #endif /* If the line doesn't begin with a tab, test to see if it introduces - another define, or ends one. */ - - /* Stop if we find an 'endef' */ + another define, or ends one. Stop if we find an 'endef' */ if (line[0] != cmd_prefix) { p = next_token (line); @@ -1826,28 +1811,16 @@ do_define (char *name, unsigned int namelen, #else ebuf->eol = remove_comments (p, ebuf->eol); #endif - if (*next_token (p) != '\0') + if (*(next_token (p)) != '\0') error (&ebuf->floc, - _("Extraneous text after `endef' directive")); + _("extraneous text after `endef' directive")); if (--nlevels == 0) - { - /* Define the variable. */ - if (idx == 0) - definition[0] = '\0'; - else - definition[idx - 1] = '\0'; - - /* Always define these variables in the global set. */ - define_variable_global (var, strlen (var), definition, - origin, 1, &defstart); - free (definition); - return; - } + break; } } - /* Otherwise add this line to the variable definition. */ + /* Add this line to the variable definition. */ #ifndef CONFIG_WITH_VALUE_LENGTH len = strlen (line); #else @@ -1866,11 +1839,16 @@ do_define (char *name, unsigned int namelen, definition[idx++] = '\n'; } - /* No `endef'!! */ - fatal (&defstart, _("missing `endef', unterminated `define'")); + /* We've got what we need; define the variable. */ + if (idx == 0) + definition[0] = '\0'; + else + definition[idx - 1] = '\0'; - /* NOTREACHED */ - return; + v = do_variable_definition (&defstart, name, definition, origin, flavor, 0); + free (definition); + free (var); + return (v); } /* Interpret conditional commands "ifdef", "ifndef", "ifeq", @@ -2259,119 +2237,6 @@ conditional_line (char *line, char *eol, int len, const struct floc *flocp) return 0; } -/* Remove duplicate dependencies in CHAIN. */ -#ifndef CONFIG_WITH_STRCACHE2 - -static unsigned long -dep_hash_1 (const void *key) -{ - return_STRING_HASH_1 (dep_name ((struct dep const *) key)); -} - -static unsigned long -dep_hash_2 (const void *key) -{ - return_STRING_HASH_2 (dep_name ((struct dep const *) key)); -} - -static int -dep_hash_cmp (const void *x, const void *y) -{ - struct dep *dx = (struct dep *) x; - struct dep *dy = (struct dep *) y; - int cmp = strcmp (dep_name (dx), dep_name (dy)); - - /* If the names are the same but ignore_mtimes are not equal, one of these - is an order-only prerequisite and one isn't. That means that we should - remove the one that isn't and keep the one that is. */ - - if (!cmp && dx->ignore_mtime != dy->ignore_mtime) - dx->ignore_mtime = dy->ignore_mtime = 0; - - return cmp; -} - -#else /* CONFIG_WITH_STRCACHE2 */ - -/* Exploit the fact that all names are in the string cache. This means equal - names shall have the same storage and there is no need for hashing or - comparing. Use the address as the first hash, avoiding any touching of - the name, and the length as the second. */ - -static unsigned long -dep_hash_1 (const void *key) -{ - const char *name = dep_name ((struct dep const *) key); - assert (strcache2_is_cached (&file_strcache, name)); - return (size_t) name / sizeof(void *); -} - -static unsigned long -dep_hash_2 (const void *key) -{ - const char *name = dep_name ((struct dep const *) key); - return strcache2_get_len (&file_strcache, name); -} - -static int -dep_hash_cmp (const void *x, const void *y) -{ - struct dep *dx = (struct dep *) x; - struct dep *dy = (struct dep *) y; - const char *dxname = dep_name (dx); - const char *dyname = dep_name (dy); - int cmp = dxname == dyname ? 0 : 1; - - /* check preconds: both cached and the cache contains no duplicates. */ - assert (strcache2_is_cached (&file_strcache, dxname)); - assert (strcache2_is_cached (&file_strcache, dyname)); - assert (cmp == 0 || strcmp (dxname, dyname) != 0); - - /* If the names are the same but ignore_mtimes are not equal, one of these - is an order-only prerequisite and one isn't. That means that we should - remove the one that isn't and keep the one that is. */ - - if (!cmp && dx->ignore_mtime != dy->ignore_mtime) - dx->ignore_mtime = dy->ignore_mtime = 0; - - return cmp; -} - -#endif /* CONFIG_WITH_STRCACHE2 */ - -void -uniquize_deps (struct dep *chain) -{ - struct hash_table deps; - register struct dep **depp; - - hash_init (&deps, 500, dep_hash_1, dep_hash_2, dep_hash_cmp); - - /* Make sure that no dependencies are repeated. This does not - really matter for the purpose of updating targets, but it - might make some names be listed twice for $^ and $?. */ - - depp = &chain; - while (*depp) - { - struct dep *dep = *depp; - struct dep **dep_slot = (struct dep **) hash_find_slot (&deps, dep); - if (HASH_VACANT (*dep_slot)) - { - hash_insert_at (&deps, dep, dep_slot); - depp = &dep->next; - } - else - { - /* Don't bother freeing duplicates. - It's dangerous and little benefit accrues. */ - *depp = dep->next; - } - } - - hash_free (&deps, 0); -} - /* Record target-specific variable values for files FILENAMES. TWO_COLON is nonzero if a double colon was used. @@ -2383,7 +2248,7 @@ uniquize_deps (struct dep *chain) static void record_target_var (struct nameseq *filenames, char *defn, - enum variable_origin origin, int exported, + enum variable_origin origin, struct vmodifiers *vmod, const struct floc *flocp) { struct nameseq *nextf; @@ -2403,11 +2268,7 @@ record_target_var (struct nameseq *filenames, char *defn, struct pattern_var *p; nextf = filenames->next; -#ifndef CONFIG_WITH_ALLOC_CACHES - free (filenames); -#else - alloccache_free (&nameseq_cache, filenames); -#endif + free_ns (filenames); /* If it's a pattern target, then add it to the pattern-specific variable list. */ @@ -2419,13 +2280,10 @@ record_target_var (struct nameseq *filenames, char *defn, p->variable.fileinfo = *flocp; /* I don't think this can fail since we already determined it was a variable definition. */ -#ifndef CONFIG_WITH_VALUE_LENGTH - v = parse_variable_definition (&p->variable, defn); -#else - v = parse_variable_definition (&p->variable, defn, NULL); -#endif + v = assign_variable_definition (&p->variable, defn IF_WITH_VALUE_LENGTH_PARAM(NULL)); assert (v != 0); + v->origin = origin; if (v->flavor == f_simple) v->value = allocated_variable_expand (v->value); else @@ -2459,24 +2317,20 @@ record_target_var (struct nameseq *filenames, char *defn, fname = f->name; current_variable_set_list = f->variables; -#ifndef CONFIG_WITH_VALUE_LENGTH - v = try_variable_definition (flocp, defn, origin, 1); -#else - v = try_variable_definition (flocp, defn, NULL, origin, 1); -#endif + v = try_variable_definition (flocp, defn IF_WITH_VALUE_LENGTH_PARAM(NULL), origin, 1); if (!v) - error (flocp, _("Malformed target-specific variable definition")); + fatal (flocp, _("Malformed target-specific variable definition")); current_variable_set_list = global; } /* Set up the variable to be *-specific. */ - v->origin = origin; v->per_target = 1; - v->export = exported ? v_export : v_default; + v->private_var = vmod->private_v; + v->export = vmod->export_v ? v_export : v_default; /* If it's not an override, check to see if there was a command-line setting. If so, reset the value. */ - if (origin != o_override) + if (v->origin != o_override) { struct variable *gv; #ifndef CONFIG_WITH_STRCACHE2 @@ -2498,7 +2352,7 @@ record_target_var (struct nameseq *filenames, char *defn, #ifndef CONFIG_WITH_VALUE_LENGTH v->value = xstrdup (gv->value); #else - v->value = savestring (gv->value, gv->value_length); + v->value = xstrndup (gv->value, gv->value_length); v->value_length = gv->value_length; #endif v->origin = gv->origin; @@ -2520,27 +2374,22 @@ record_target_var (struct nameseq *filenames, char *defn, The links of FILENAMES are freed, and so are any names in it that are not incorporated into other data structures. */ -#ifndef CONFIG_WITH_INCLUDEDEP static void -#else -void -#endif record_files (struct nameseq *filenames, const char *pattern, - const char *pattern_percent, struct dep *deps, + const char *pattern_percent, char *depstr, unsigned int cmds_started, char *commands, unsigned int commands_idx, int two_colon, const struct floc *flocp) { - struct nameseq *nextf; - int implicit = 0; - unsigned int max_targets = 0, target_idx = 0; - const char **targets = 0, **target_percents = 0; - struct commands *cmds; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET struct file *prev_file = 0; enum multitarget_mode { m_unsettled, m_no, m_yes, m_yes_maybe } multi_mode = !two_colon && !pattern ? m_unsettled : m_no; #endif + struct commands *cmds; + struct dep *deps; + const char *implicit_percent; + const char *name; /* If we've already snapped deps, that means we're in an eval being resolved after the makefiles have been read in. We can't add more rules @@ -2549,6 +2398,11 @@ record_files (struct nameseq *filenames, const char *pattern, if (snapped_deps) fatal (flocp, _("prerequisites cannot be defined in recipes")); + /* Determine if this is a pattern rule or not. */ + name = filenames->name; + implicit_percent = find_percent_cached (&name); + + /* If there's a recipe, set up a struct for it. */ if (commands_idx > 0) { #ifndef CONFIG_WITH_ALLOC_CACHES @@ -2558,71 +2412,117 @@ record_files (struct nameseq *filenames, const char *pattern, #endif cmds->fileinfo.filenm = flocp->filenm; cmds->fileinfo.lineno = cmds_started; - cmds->commands = savestring (commands, commands_idx); + cmds->commands = xstrndup (commands, commands_idx); cmds->command_lines = 0; #ifdef CONFIG_WITH_MEMORY_OPTIMIZATIONS cmds->refs = 0; #endif } else - cmds = 0; + cmds = 0; - for (; filenames != 0; filenames = nextf) + /* If there's a prereq string then parse it--unless it's eligible for 2nd + expansion: if so, snap_deps() will do it. */ + if (depstr == 0) + deps = 0; + else if (second_expansion && strchr (depstr, '$')) { - const char *name = filenames->name; + deps = alloc_dep (); + deps->name = depstr; + deps->need_2nd_expansion = 1; + deps->staticpattern = pattern != 0; + } + else + { + deps = split_prereqs (depstr); + free (depstr); + + /* We'll enter static pattern prereqs later when we have the stem. We + don't want to enter pattern rules at all so that we don't think that + they ought to exist (make manual "Implicit Rule Search Algorithm", + item 5c). */ + if (! pattern && ! implicit_percent) + deps = enter_prereqs (deps, NULL); + } + + /* For implicit rules, _all_ the targets must have a pattern. That means we + can test the first one to see if we're working with an implicit rule; if + so we handle it specially. */ + + if (implicit_percent) + { + struct nameseq *nextf; + const char **targets, **target_pats; + unsigned int c; + + if (pattern != 0) + fatal (flocp, _("mixed implicit and static pattern rules")); + + /* Count the targets to create an array of target names. + We already have the first one. */ + nextf = filenames->next; + free_ns (filenames); + filenames = nextf; + + for (c = 1; nextf; ++c, nextf = nextf->next) + ; + targets = xmalloc (c * sizeof (const char *)); + target_pats = xmalloc (c * sizeof (const char *)); + + targets[0] = name; + target_pats[0] = implicit_percent; + + c = 1; + while (filenames) + { + name = filenames->name; + implicit_percent = find_percent_cached (&name); + + if (implicit_percent == 0) + fatal (flocp, _("mixed implicit and normal rules")); + + targets[c] = name; + target_pats[c] = implicit_percent; + ++c; + + nextf = filenames->next; + free_ns (filenames); + filenames = nextf; + } + + create_pattern_rule (targets, target_pats, c, two_colon, deps, cmds, 1); + + return; + } + + + /* Walk through each target and create it in the database. + We already set up the first target, above. */ + while (1) + { + struct nameseq *nextf = filenames->next; struct file *f; struct dep *this = 0; - const char *implicit_percent; - nextf = filenames->next; -#ifndef CONFIG_WITH_ALLOC_CACHES - free (filenames); -#else - alloccache_free (&nameseq_cache, filenames); -#endif + free_ns (filenames); /* Check for special targets. Do it here instead of, say, snap_deps() so that we can immediately use the value. */ - if (streq (name, ".POSIX")) - posix_pedantic = 1; + { + posix_pedantic = 1; + define_variable_cname (".SHELLFLAGS", "-ec", o_default, 0); + } else if (streq (name, ".SECONDEXPANSION")) second_expansion = 1; #ifdef CONFIG_WITH_2ND_TARGET_EXPANSION else if (streq (name, ".SECONDTARGETEXPANSION")) second_target_expansion = 1; #endif - - implicit_percent = find_percent_cached (&name); - implicit |= implicit_percent != 0; - - if (implicit) - { - if (pattern != 0) - fatal (flocp, _("mixed implicit and static pattern rules")); - - if (implicit_percent == 0) - fatal (flocp, _("mixed implicit and normal rules")); - - if (targets == 0) - { - max_targets = 5; - targets = xmalloc (5 * sizeof (char *)); - target_percents = xmalloc (5 * sizeof (char *)); - target_idx = 0; - } - else if (target_idx == max_targets - 1) - { - max_targets += 5; - targets = xrealloc ((void *)targets, max_targets * sizeof (char *)); - target_percents = xrealloc ((void *)target_percents, - max_targets * sizeof (char *)); - } - targets[target_idx] = name; - target_percents[target_idx] = implicit_percent; - ++target_idx; - continue; - } +#if !defined(WINDOWS32) && !defined (__MSDOS__) && !defined (__EMX__) + else if (streq (name, ".ONESHELL")) + one_shell = 1; +#endif #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET /* Check for the explicit multitarget mode operators. For this to be @@ -2660,7 +2560,7 @@ record_files (struct nameseq *filenames, const char *pattern, } } multi_mode = name[1] == '\0' ? m_yes : m_yes_maybe; - continue; + goto l_next; } } else if (multi_mode == m_unsettled && prev_file) @@ -2668,30 +2568,26 @@ record_files (struct nameseq *filenames, const char *pattern, #endif /* If this is a static pattern rule: - `targets: target%pattern: dep%pattern; cmds', + `targets: target%pattern: prereq%pattern; recipe', make sure the pattern matches this target name. */ if (pattern && !pattern_matches (pattern, pattern_percent, name)) error (flocp, _("target `%s' doesn't match the target pattern"), name); else if (deps) - { - /* If there are multiple filenames, copy the chain DEPS for all but - the last one. It is not safe for the same deps to go in more - than one place in the database. */ - this = nextf != 0 ? copy_dep_chain (deps) : deps; - this->need_2nd_expansion = (second_expansion - && strchr (this->name, '$')); - } + /* If there are multiple targets, copy the chain DEPS for all but the + last one. It is not safe for the same deps to go in more than one + place in the database. */ + this = nextf != 0 ? copy_dep_chain (deps) : deps; + /* Find or create an entry in the file database for this target. */ if (!two_colon) { - /* Single-colon. Combine these dependencies - with others in file's existing record, if any. */ + /* Single-colon. Combine this rule with the file's existing record, + if any. */ #ifndef KMK f = enter_file (strcache_add (name)); #else /* KMK - the name is already in the cache, don't waste time. */ f = enter_file (name); #endif - if (f->double_colon) fatal (flocp, _("target file `%s' has both : and :: entries"), f->name); @@ -2716,8 +2612,6 @@ record_files (struct nameseq *filenames, const char *pattern, f->name); } - f->is_target = 1; - /* Defining .DEFAULT with no deps or cmds clears it. */ if (f == default_file && this == 0 && cmds == 0) f->cmds = 0; @@ -2750,68 +2644,6 @@ record_files (struct nameseq *filenames, const char *pattern, free_dep_chain (f->deps); f->deps = 0; } - else if (this != 0) - { - /* Add the file's old deps and the new ones in THIS together. */ - - if (f->deps != 0) - { - struct dep **d_ptr = &f->deps; - - while ((*d_ptr)->next != 0) - d_ptr = &(*d_ptr)->next; - - if (cmds != 0) - /* This is the rule with commands, so put its deps - last. The rationale behind this is that $< expands to - the first dep in the chain, and commands use $< - expecting to get the dep that rule specifies. However - the second expansion algorithm reverses the order thus - we need to make it last here. */ - (*d_ptr)->next = this; - else - { - /* This is the rule without commands. Put its - dependencies at the end but before dependencies from - the rule with commands (if any). This way everything - appears in makefile order. */ - - if (f->cmds != 0) - { -#ifndef KMK /* bugfix: Don't chop the chain! */ - this->next = *d_ptr; - *d_ptr = this; -#else /* KMK */ - struct dep *this_last = this; - while (this_last->next) - this_last = this_last->next; - this_last->next = *d_ptr; - *d_ptr = this; -#endif /* KMK */ - } - else - (*d_ptr)->next = this; - } - } - else - f->deps = this; - - /* This is a hack. I need a way to communicate to snap_deps() - that the last dependency line in this file came with commands - (so that logic in snap_deps() can put it in front and all - this $< -logic works). I cannot simply rely on file->cmds - being not 0 because of the cases like the following: - - foo: bar - foo: - ... - - I am going to temporarily "borrow" UPDATING member in - `struct file' for this. */ - - if (cmds != 0) - f->updating = 1; - } } else { @@ -2822,11 +2654,12 @@ record_files (struct nameseq *filenames, const char *pattern, f = lookup_file_cached (name); #endif /* CONFIG_WITH_STRCACHE2 */ - /* Check for both : and :: rules. Check is_target so - we don't lose on default suffix rules or makefiles. */ + /* Check for both : and :: rules. Check is_target so we don't lose + on default suffix rules or makefiles. */ if (f != 0 && f->is_target && !f->double_colon) fatal (flocp, _("target file `%s' has both : and :: entries"), f->name); + #ifndef KMK f = enter_file (strcache_add (name)); #else /* KMK - the name is already in the cache, don't waste time. */ @@ -2840,14 +2673,15 @@ record_files (struct nameseq *filenames, const char *pattern, /* This is the first entry for this name, so we must set its double_colon pointer to itself. */ f->double_colon = f; - f->is_target = 1; - f->deps = this; + f->cmds = cmds; } + f->is_target = 1; + /* If this is a static pattern rule, set the stem to the part of its name that matched the `%' in the pattern, so you can use $* in the - commands. */ + commands. If we didn't do it before, enter the prereqs now. */ if (pattern) { static const char *percent = "%"; @@ -2859,26 +2693,57 @@ record_files (struct nameseq *filenames, const char *pattern, f->stem = strcache_add_len (buffer, o - buffer); if (this) { - this->staticpattern = 1; - this->stem = f->stem; + if (! this->need_2nd_expansion) + this = enter_prereqs (this, f->stem); + else + this->stem = f->stem; + } + } + + /* Add the dependencies to this file entry. */ + if (this != 0) + { + /* Add the file's old deps and the new ones in THIS together. */ + if (f->deps == 0) + f->deps = this; + else if (cmds != 0) + { + struct dep *d = this; + + /* If this rule has commands, put these deps first. */ + while (d->next != 0) + d = d->next; + + d->next = f->deps; + f->deps = this; + } + else + { + struct dep *d = f->deps; + + /* A rule without commands: put its prereqs at the end. */ + while (d->next != 0) + d = d->next; + + d->next = this; } } name = f->name; - /* If this target is a default target, update DEFAULT_GOAL_FILE. */ - if (streq (*default_goal_name, name) - && (default_goal_file == 0 - || ! streq (default_goal_file->name, name))) - default_goal_file = f; - } +#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET +l_next: +#endif + /* All done! Set up for the next one. */ + if (nextf == 0) + break; - if (implicit) - { - if (deps) - deps->need_2nd_expansion = second_expansion; - create_pattern_rule (targets, target_percents, target_idx, - two_colon, deps, cmds, 1); + filenames = nextf; + + /* Reduce escaped percents. If there are any unescaped it's an error */ + name = filenames->name; + if (find_percent_cached (&name)) + fatal (flocp, _("mixed implicit and normal rules")); } } @@ -3099,270 +2964,6 @@ find_percent_cached (const char **string) return (*p == '\0') ? NULL : p; } -/* Parse a string into a sequence of filenames represented as a - chain of struct nameseq's in reverse order and return that chain. - - The string is passed as STRINGP, the address of a string pointer. - The string pointer is updated to point at the first character - not parsed, which either is a null char or equals STOPCHAR. - - SIZE is how big to construct chain elements. - This is useful if we want them actually to be other structures - that have room for additional info. - - If STRIP is nonzero, strip `./'s off the beginning. */ - -#ifndef CONFIG_WITH_ALLOC_CACHES -struct nameseq * -parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip) -#else -struct nameseq * -parse_file_seq (char **stringp, int stopchar, struct alloccache *cache, int strip) -#endif -{ - struct nameseq *new = 0; - struct nameseq *new1; -#ifndef NO_ARCHIVES /* bird: MSC warning */ - struct nameseq *lastnew1; -#endif - char *p = *stringp; - -#ifdef VMS -# define VMS_COMMA ',' -#else -# define VMS_COMMA 0 -#endif - - while (1) - { - const char *name; - char *q; - - /* Skip whitespace; see if any more names are left. */ - p = next_token (p); - if (*p == '\0') - break; - if (*p == stopchar) - break; - - /* There are, so find the end of the next name. */ - q = p; - p = find_char_unquote (q, stopchar, VMS_COMMA, 1, 0); -#ifdef VMS - /* convert comma separated list to space separated */ - if (p && *p == ',') - *p =' '; -#endif -#ifdef _AMIGA - if (stopchar == ':' && p && *p == ':' - && !(isspace ((unsigned char)p[1]) || !p[1] - || isspace ((unsigned char)p[-1]))) - p = find_char_unquote (p+1, stopchar, VMS_COMMA, 1, 0); -#endif -#ifdef HAVE_DOS_PATHS - /* For DOS paths, skip a "C:\..." or a "C:/..." until we find the - first colon which isn't followed by a slash or a backslash. - Note that tokens separated by spaces should be treated as separate - tokens since make doesn't allow path names with spaces */ - if (stopchar == ':') - while (p != 0 && !isspace ((unsigned char)*p) && - (p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1])) - p = find_char_unquote (p + 1, stopchar, VMS_COMMA, 1, 0); -#endif - if (p == 0) - p = q + strlen (q); - - if (strip) -#ifdef VMS - /* Skip leading `[]'s. */ - while (p - q > 2 && q[0] == '[' && q[1] == ']') -#else - /* Skip leading `./'s. */ - while (p - q > 2 && q[0] == '.' && q[1] == '/') -#endif - { - q += 2; /* Skip "./". */ - while (q < p && *q == '/') - /* Skip following slashes: ".//foo" is "foo", not "/foo". */ - ++q; - } - - /* Extract the filename just found, and skip it. */ - - if (q == p) - /* ".///" was stripped to "". */ -#if defined(VMS) - continue; -#elif defined(_AMIGA) - name = ""; -#else - name = "./"; -#endif - else -#ifdef VMS -/* VMS filenames can have a ':' in them but they have to be '\'ed but we need - * to remove this '\' before we can use the filename. - * Savestring called because q may be read-only string constant. - */ - { - char *qbase = xstrdup (q); - char *pbase = qbase + (p-q); - char *q1 = qbase; - char *q2 = q1; - char *p1 = pbase; - - while (q1 != pbase) - { - if (*q1 == '\\' && *(q1+1) == ':') - { - q1++; - p1--; - } - *q2++ = *q1++; - } - name = strcache_add_len (qbase, p1 - qbase); - free (qbase); - } -#elif !defined (CONFIG_WITH_VALUE_LENGTH) || defined (CONFIG_WITH_STRCACHE2) - name = strcache_add_len (q, p - q); -#else /* CONFIG_WITH_VALUE_LENGTH */ - { - /* Make sure it's terminated, strcache_add_len has to make a - temp copy on the stack otherwise. */ - char saved = *p; - if (!saved) - *p = '\0'; - name = strcache_add_len (q, p - q); - if (saved) - *p = saved; - } -#endif /* CONFIG_WITH_VALUE_LENGTH */ - - /* Add it to the front of the chain. */ -#ifndef CONFIG_WITH_ALLOC_CACHES - new1 = xmalloc (size); - memset (new1, '\0', size); -#else - new1 = (struct nameseq *) alloccache_calloc (cache); -#endif - new1->name = name; - new1->next = new; - new = new1; - } - -#ifndef NO_ARCHIVES - - /* Look for multi-word archive references. - They are indicated by a elt ending with an unmatched `)' and - an elt further down the chain (i.e., previous in the file list) - with an unmatched `(' (e.g., "lib(mem"). */ - - new1 = new; - lastnew1 = 0; - while (new1 != 0) - if (new1->name[0] != '(' /* Don't catch "(%)" and suchlike. */ - && new1->name[strlen (new1->name) - 1] == ')' - && strchr (new1->name, '(') == 0) - { - /* NEW1 ends with a `)' but does not contain a `('. - Look back for an elt with an opening `(' but no closing `)'. */ - - struct nameseq *n = new1->next, *lastn = new1; - char *paren = 0; - while (n != 0 && (paren = strchr (n->name, '(')) == 0) - { - lastn = n; - n = n->next; - } - if (n != 0 - /* Ignore something starting with `(', as that cannot actually - be an archive-member reference (and treating it as such - results in an empty file name, which causes much lossage). */ - && n->name[0] != '(') - { - /* N is the first element in the archive group. - Its name looks like "lib(mem" (with no closing `)'). */ - - char *libname; - - /* Copy "lib(" into LIBNAME. */ - ++paren; - libname = alloca (paren - n->name + 1); - memcpy (libname, n->name, paren - n->name); - libname[paren - n->name] = '\0'; - - if (*paren == '\0') - { - /* N was just "lib(", part of something like "lib( a b)". - Edit it out of the chain and free its storage. */ - lastn->next = n->next; -#ifndef CONFIG_WITH_ALLOC_CACHES - free (n); -#else - alloccache_free (cache, n); -#endif - /* LASTN->next is the new stopping elt for the loop below. */ - n = lastn->next; - } - else - { - /* Replace N's name with the full archive reference. */ - n->name = strcache_add (concat (libname, paren, ")")); - } - - if (new1->name[1] == '\0') - { - /* NEW1 is just ")", part of something like "lib(a b )". - Omit it from the chain and free its storage. */ - if (lastnew1 == 0) - new = new1->next; - else - lastnew1->next = new1->next; - lastn = new1; - new1 = new1->next; -#ifndef CONFIG_WITH_ALLOC_CACHES - free (lastn); -#else - alloccache_free (cache, lastn); -#endif - } - else - { - /* Replace also NEW1->name, which already has closing `)'. */ - new1->name = strcache_add (concat (libname, new1->name, "")); - new1 = new1->next; - } - - /* Trace back from NEW1 (the end of the list) until N - (the beginning of the list), rewriting each name - with the full archive reference. */ - - while (new1 != n) - { - new1->name = strcache_add (concat (libname, new1->name, ")")); - lastnew1 = new1; - new1 = new1->next; - } - } - else - { - /* No frobnication happening. Just step down the list. */ - lastnew1 = new1; - new1 = new1->next; - } - } - else - { - lastnew1 = new1; - new1 = new1->next; - } - -#endif - - *stringp = p; - return new; -} - /* Find the next line of text in an eval buffer, combining continuation lines into one line. Return the number of actual lines read (> 1 if continuation lines). @@ -3399,16 +3000,16 @@ readstring (struct ebuffer *ebuf) while (1) { int backslash = 0; - char *bol = eol; - char *p; + const char *bol = eol; + const char *p; /* Find the next newline. At EOS, stop. */ #ifndef CONFIG_WITH_VALUE_LENGTH - eol = p = strchr (eol , '\n'); + p = eol = strchr (eol , '\n'); #else p = (char *)memchr (eol, '\n', end - eol); assert (!memchr (eol, '\0', p != 0 ? p - eol : end - eol)); - eol = p; + eol = (char *)p; #endif if (!eol) { @@ -3917,7 +3518,7 @@ tilde_expand (const char *name) # endif /* !AMIGA && !WINDOWS32 */ if (home_dir != 0) { - char *new = xstrdup (concat (home_dir, "", name + 1)); + char *new = xstrdup (concat (2, home_dir, name + 1)); if (is_variable) free (home_dir); return new; @@ -3936,7 +3537,7 @@ tilde_expand (const char *name) if (userend == 0) return xstrdup (pwent->pw_dir); else - return xstrdup (concat (pwent->pw_dir, "/", userend + 1)); + return xstrdup (concat (3, pwent->pw_dir, "/", userend + 1)); } else if (userend != 0) *userend = '/'; @@ -3945,163 +3546,378 @@ tilde_expand (const char *name) #endif /* !VMS */ return 0; } + +/* Parse a string into a sequence of filenames represented as a chain of + struct nameseq's and return that chain. Optionally expand the strings via + glob(). -/* Given a chain of struct nameseq's describing a sequence of filenames, - in reverse of the intended order, return a new chain describing the - result of globbing the filenames. The new chain is in forward order. - The links of the old chain are freed or used in the new chain. - Likewise for the names in the old chain. + The string is passed as STRINGP, the address of a string pointer. + The string pointer is updated to point at the first character + not parsed, which either is a null char or equals STOPCHAR. SIZE is how big to construct chain elements. This is useful if we want them actually to be other structures - that have room for additional info. */ + that have room for additional info. + PREFIX, if non-null, is added to the beginning of each filename. + + FLAGS allows one or more of the following bitflags to be set: + PARSEFS_NOSTRIP - Do no strip './'s off the beginning + PARSEFS_NOAR - Do not check filenames for archive references + PARSEFS_NOGLOB - Do not expand globbing characters + PARSEFS_EXISTS - Only return globbed files that actually exist + (cannot also set NOGLOB) + PARSEFS_NOCACHE - Do not add filenames to the strcache (caller frees) + */ + +void * +parse_file_seq (char **stringp, unsigned int size, int stopchar, + const char *prefix, int flags + IF_WITH_ALLOC_CACHES_PARAM(struct alloccache *alloc_cache) ) +{ + extern void dir_setup_glob (glob_t *glob); + + /* tmp points to tmpbuf after the prefix, if any. + tp is the end of the buffer. */ + static char *tmpbuf = NULL; + static int tmpbuf_len = 0; + + int cachep = (! (flags & PARSEFS_NOCACHE)); + + struct nameseq *new = 0; + struct nameseq **newp = &new; #ifndef CONFIG_WITH_ALLOC_CACHES -struct nameseq * -multi_glob (struct nameseq *chain, unsigned int size) +#define NEWELT(_n) do { \ + const char *__n = (_n); \ + *newp = xcalloc (size); \ + (*newp)->name = (cachep ? strcache_add (__n) : xstrdup (__n)); \ + newp = &(*newp)->next; \ + } while(0) #else -struct nameseq * -multi_glob (struct nameseq *chain, struct alloccache *cache) +# define NEWELT(_n) do { \ + const char *__n = (_n); \ + *newp = alloccache_calloc (alloc_cache); \ + (*newp)->name = (cachep ? strcache_add (__n) : xstrdup (__n)); \ + newp = &(*newp)->next; \ + } while(0) #endif -{ - void dir_setup_glob (glob_t *); - struct nameseq *new = 0; - struct nameseq *old; - struct nameseq *nexto; + + char *p; glob_t gl; -#if defined(KMK) || defined(__EMX__) /* speed optimization */ - int rc; + char *tp; + +#ifdef VMS +# define VMS_COMMA ',' +#else +# define VMS_COMMA 0 #endif - dir_setup_glob (&gl); + if (size < sizeof (struct nameseq)) + size = sizeof (struct nameseq); + + if (! (flags & PARSEFS_NOGLOB)) + dir_setup_glob (&gl); - for (old = chain; old != 0; old = nexto) + /* Get enough temporary space to construct the largest possible target. */ + { + int l = strlen (*stringp) + 1; + if (l > tmpbuf_len) + { + tmpbuf = xrealloc (tmpbuf, l); + tmpbuf_len = l; + } + } + tp = tmpbuf; + + /* Parse STRING. P will always point to the end of the parsed content. */ + p = *stringp; + while (1) { - const char *gname; + const char *name; + const char **nlist = 0; + char *tildep = 0; #ifndef NO_ARCHIVES char *arname = 0; char *memname = 0; #endif - nexto = old->next; - gname = old->name; + char *s; + int nlen; + int i; - if (gname[0] == '~') - { - char *newname = tilde_expand (old->name); - if (newname != 0) - gname = newname; - } + /* Skip whitespace; at the end of the string or STOPCHAR we're done. */ + p = next_token (p); + if (*p == '\0' || *p == stopchar) + break; -#ifndef NO_ARCHIVES - if (ar_name (gname)) - { - /* OLD->name is an archive member reference. Replace it with the - archive file name, and save the member name in MEMNAME. We will - glob on the archive name and then reattach MEMNAME later. */ - ar_parse_name (gname, &arname, &memname); - gname = arname; - } -#endif /* !NO_ARCHIVES */ + /* There are names left, so find the end of the next name. + Throughout this iteration S points to the start. */ + s = p; + p = find_char_unquote (p, stopchar, VMS_COMMA, 1, 0); +#ifdef VMS + /* convert comma separated list to space separated */ + if (p && *p == ',') + *p =' '; +#endif +#ifdef _AMIGA + if (stopchar == ':' && p && *p == ':' + && !(isspace ((unsigned char)p[1]) || !p[1] + || isspace ((unsigned char)p[-1]))) + p = find_char_unquote (p+1, stopchar, VMS_COMMA, 1, 0); +#endif +#ifdef HAVE_DOS_PATHS + /* For DOS paths, skip a "C:\..." or a "C:/..." until we find the + first colon which isn't followed by a slash or a backslash. + Note that tokens separated by spaces should be treated as separate + tokens since make doesn't allow path names with spaces */ + if (stopchar == ':') + while (p != 0 && !isspace ((unsigned char)*p) && + (p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1])) + p = find_char_unquote (p + 1, stopchar, VMS_COMMA, 1, 0); +#endif + if (p == 0) + p = s + strlen (s); + + /* Strip leading "this directory" references. */ + if (! (flags & PARSEFS_NOSTRIP)) +#ifdef VMS + /* Skip leading `[]'s. */ + while (p - s > 2 && s[0] == '[' && s[1] == ']') +#else + /* Skip leading `./'s. */ + while (p - s > 2 && s[0] == '.' && s[1] == '/') +#endif + { + /* Skip "./" and all following slashes. */ + s += 2; + while (*s == '/') + ++s; + } -#if defined(KMK) || defined(__EMX__) /* speed optimization */ - if (!strpbrk(gname, "*?[")) + /* Extract the filename just found, and skip it. + Set NAME to the string, and NLEN to its length. */ + + if (s == p) { - gl.gl_pathc = 1; - gl.gl_pathv = (char **)&gname; - rc = 0; + /* The name was stripped to empty ("./"). */ +#if defined(VMS) + continue; +#elif defined(_AMIGA) + /* PDS-- This cannot be right!! */ + tp[0] = '\0'; + nlen = 0; +#else + tp[0] = '.'; + tp[1] = '/'; + tp[2] = '\0'; + nlen = 2; +#endif } else - rc = glob (gname, GLOB_NOCHECK|GLOB_ALTDIRFUNC, NULL, &gl); - switch (rc) + { +#ifdef VMS +/* VMS filenames can have a ':' in them but they have to be '\'ed but we need + * to remove this '\' before we can use the filename. + * xstrdup called because S may be read-only string constant. + */ + char *n = tp; + while (s < p) + { + if (s[0] == '\\' && s[1] == ':') + ++s; + *(n++) = *(s++); + } + n[0] = '\0'; + nlen = strlen (tp); #else - switch (glob (gname, GLOB_NOCHECK|GLOB_ALTDIRFUNC, NULL, &gl)) + nlen = p - s; + memcpy (tp, s, nlen); + tp[nlen] = '\0'; +#endif + } + + /* At this point, TP points to the element and NLEN is its length. */ + +#ifndef NO_ARCHIVES + /* If this is the start of an archive group that isn't complete, set up + to add the archive prefix for future files. A file list like: + "libf.a(x.o y.o z.o)" needs to be expanded as: + "libf.a(x.o) libf.a(y.o) libf.a(z.o)" + + TP == TMP means we're not already in an archive group. Ignore + something starting with `(', as that cannot actually be an + archive-member reference (and treating it as such results in an empty + file name, which causes much lossage). Also if it ends in ")" then + it's a complete reference so we don't need to treat it specially. + + Finally, note that archive groups must end with ')' as the last + character, so ensure there's some word ending like that before + considering this an archive group. */ + if (! (flags & PARSEFS_NOAR) + && tp == tmpbuf && tp[0] != '(' && tp[nlen-1] != ')') + { + char *n = strchr (tp, '('); + if (n) + { + /* This looks like the first element in an open archive group. + A valid group MUST have ')' as the last character. */ + const char *e = p + nlen; + do + { + e = next_token (e); + /* Find the end of this word. We don't want to unquote and + we don't care about quoting since we're looking for the + last char in the word. */ + while (*e != '\0' && *e != stopchar && *e != VMS_COMMA + && ! isblank ((unsigned char) *e)) + ++e; + if (e[-1] == ')') + { + /* Found the end, so this is the first element in an + open archive group. It looks like "lib(mem". + Reset TP past the open paren. */ + nlen -= (n + 1) - tp; + tp = n + 1; + + /* If we have just "lib(", part of something like + "lib( a b)", go to the next item. */ + if (! nlen) + continue; + + /* We can stop looking now. */ + break; + } + } + while (*e != '\0'); + } + } + + /* If we are inside an archive group, make sure it has an end. */ + if (tp > tmpbuf) + { + if (tp[nlen-1] == ')') + { + /* This is the natural end; reset TP. */ + tp = tmpbuf; + + /* This is just ")", something like "lib(a b )": skip it. */ + if (nlen == 1) + continue; + } + else + { + /* Not the end, so add a "fake" end. */ + tp[nlen++] = ')'; + tp[nlen] = '\0'; + } + } #endif + + /* If we're not globbing we're done: add it to the end of the chain. + Go to the next item in the string. */ + if (flags & PARSEFS_NOGLOB) + { + NEWELT (concat (2, prefix, tp)); + continue; + } + + /* If we get here we know we're doing glob expansion. + TP is a string in tmpbuf. NLEN is no longer used. + We may need to do more work: after this NAME will be set. */ + name = tp; + + /* Expand tilde if applicable. */ + if (tp[0] == '~') { - case 0: /* Success. */ - { - int i = gl.gl_pathc; - while (i-- > 0) - { + tildep = tilde_expand (tp); + if (tildep != 0) + name = tildep; + } + #ifndef NO_ARCHIVES - if (memname != 0) - { - /* Try to glob on MEMNAME within the archive. */ - struct nameseq *found - = ar_glob (gl.gl_pathv[i], memname, size); - if (! found) - { - /* No matches. Use MEMNAME as-is. */ - unsigned int alen = strlen (gl.gl_pathv[i]); - unsigned int mlen = strlen (memname); - char *name; - struct nameseq *elt = xmalloc (size); - memset (elt, '\0', size); - - name = alloca (alen + 1 + mlen + 2); - memcpy (name, gl.gl_pathv[i], alen); - name[alen] = '('; - memcpy (name+alen+1, memname, mlen); - name[alen + 1 + mlen] = ')'; - name[alen + 1 + mlen + 1] = '\0'; - elt->name = strcache_add (name); - elt->next = new; - new = elt; - } - else - { - /* Find the end of the FOUND chain. */ - struct nameseq *f = found; - while (f->next != 0) - f = f->next; - - /* Attach the chain being built to the end of the FOUND - chain, and make FOUND the new NEW chain. */ - f->next = new; - new = found; - } - } - else + /* If NAME is an archive member reference replace it with the archive + file name, and save the member name in MEMNAME. We will glob on the + archive name and then reattach MEMNAME later. */ + if (! (flags & PARSEFS_NOAR) && ar_name (name)) + { + ar_parse_name (name, &arname, &memname); + name = arname; + } #endif /* !NO_ARCHIVES */ - { -#ifndef CONFIG_WITH_ALLOC_CACHES - struct nameseq *elt = xmalloc (size); - memset (elt, '\0', size); -#else - struct nameseq *elt = alloccache_calloc (cache); -#endif - elt->name = strcache_add (gl.gl_pathv[i]); - elt->next = new; - new = elt; - } - } -#if defined(KMK) || defined(__EMX__) /* speed optimization */ - if (gl.gl_pathv != (char **)&gname) -#endif - globfree (&gl); -#ifndef CONFIG_WITH_ALLOC_CACHES - free (old); -#else - alloccache_free (cache, old); -#endif - break; - } + switch (glob (name, GLOB_NOSORT|GLOB_ALTDIRFUNC, NULL, &gl)) + { case GLOB_NOSPACE: fatal (NILF, _("virtual memory exhausted")); - break; + + case 0: + /* Success. */ + i = gl.gl_pathc; + nlist = (const char **)gl.gl_pathv; + break; + + case GLOB_NOMATCH: + /* If we want only existing items, skip this one. */ + if (flags & PARSEFS_EXISTS) + { + i = 0; + break; + } + /* FALLTHROUGH */ default: - old->next = new; - new = old; - break; + /* By default keep this name. */ + i = 1; + nlist = &name; + break; } + /* For each matched element, add it to the list. */ + while (i-- > 0) +#ifndef NO_ARCHIVES + if (memname != 0) + { + /* Try to glob on MEMNAME within the archive. */ + struct nameseq *found = ar_glob (nlist[i], memname, size); + if (! found) + /* No matches. Use MEMNAME as-is. */ + NEWELT (concat (5, prefix, nlist[i], "(", memname, ")")); + else + { + /* We got a chain of items. Attach them. */ + (*newp)->next = found; + + /* Find and set the new end. Massage names if necessary. */ + while (1) + { + if (! cachep) + found->name = xstrdup (concat (2, prefix, name)); + else if (prefix) + found->name = strcache_add (concat (2, prefix, name)); + + if (found->next == 0) + break; + + found = found->next; + } + newp = &found->next; + } + } + else +#endif /* !NO_ARCHIVES */ + NEWELT (concat (2, prefix, nlist[i])); + + globfree (&gl); + #ifndef NO_ARCHIVES if (arname) free (arname); #endif + + if (tildep) + free (tildep); } + *stringp = p; return new; } diff --git a/src/kmk/readme.vms b/src/kmk/readme.vms index 88e35b5..ec3d624 100644 --- a/src/kmk/readme.vms +++ b/src/kmk/readme.vms @@ -1,16 +1,13 @@ This is the VMS version of GNU Make, updated by Hartmut Becker -Changes are based on GNU make 3.80. Latest changes are for OpenVMS/I64 -and new VMS CRTLs. +Changes are based on GNU make 3.82. -This version was tested on OpenVMS/I64 V8.2 (field test) with hp C -X7.1-024 OpenVMS/Alpha V7.3-2 with Compaq C V6.5-001 and OpenVMS/VAX 7.1 -with Compaq C V6.2-003 There are still some warning and informational -message issued by the compilers. +This version was built and tested on OpenVMS V7.3 (VAX), V7.3-2 (Alpha) and +V8.3-1H1 (I64). Build instructions Make a 1st version - $ @makefile.com + $ @makefile.com ! ignore any compiler and/or linker warning $ rena make.exe 1st-make.exe Use the 1st version to generate a 2nd version $ mc sys$disk:[]1st-make clean @@ -20,7 +17,89 @@ Verify your 2nd version $ mc sys$disk:[]2nd-make clean $ mc sys$disk:[]2nd-make -Changes: +Changes (3.81.90) + +Michael Gehre (at VISTEC-SEMI dot COM) supplied a fix for a problem with +timestamps of object modules in OLBs. The timestamps were not correctly +adjusted to GMT based time, if the local VMS time was using a daylight saving +algorithm and if daylight saving was switched off. + +John Eisenbraun (at HP dot COM) supplied fixes and and an enhancement to append +output redirection in action lines. + +Rework of ctrl+c and ctrl+y handling. + +Fix a problem with cached strings, which showed on case-insensitive file +systems. + +Build fixes for const-ified code in VMS specific sources. + +Build notes: +- Try to avoid HP C V7.2-001, which has an incompatible change +how __STDC__ is defined. This results at least in compile time warnings. + +- On V8.3-1H1, if you press Ctrl+C you may see a traceback, starting with +%SYSTEM-F-CONTROLC, operation completed under CTRL/C +%TRACE-F-TRACEBACK, symbolic stack dump follows +image module routine line rel PC abs PC + +DECC$SHR C$SIGNAL gsignal 27991 0000000000001180 +FFFFFFFF84AB2DA0 +DECC$SHR C$SIGNAL raise 28048 0000000000001280 +FFFFFFFF84AB2EA0 +DECC$SHR C$SIGPENDING decc$$deliver_signals + 12475 0000000000000890 +FFFFFFFF84C13690 +... +This looks like an incompatibility to the Alpha and VAX behavior, so it looks +like a problem in I64 VMS version(s). + +- There is no clean build on VAX. In the environment I tested, I had to use GNU +make's alloca which produced a couple of compile time warnings. It seems too +much effort to work on a clean build on VAX. + +A note on appending the redirected output. With this change, a simple mechanism +is implemented to make ">>" work in action lines. In VMS there is no simple +feature like ">>" to have DCL command or program output redirected and appended +to a file. GNU make for VMS already implements the redirection of output. If +such a redirection is detected, an ">" on the action line, GNU make creates a +DCL command procedure to execute the action and to redirect its output. Based +on that, now ">>" is also recognized and a similar but different command +procedure is created to implement the append. The main idea here is to create a +temporary file which collects the output and which is appended to the wanted +output file. Then the temporary file is deleted. This is all done in the +command procedure to keep changes in make small and simple. This obviously has +some limitations but it seems good enough compared with the current ">" +implementation. (And in my opinion, redirection is not really what GNU make has +to do.) With this approach, it may happen that the temporary file is not yet +appended and is left in SYS$SCRATCH. The temporary file names look like +"CMDxxxxx.". Any time the created command procedure can not complete, this +happens. Pressing Ctrl+Y to abort make is one case. In case of Ctrl+Y the +associated command procedure is left in SYS$SCRATCH as well. Its name is +CMDxxxxx.COM. + +Change in the Ctrl+Y handling + +Ctrl+Y was: The CtrlY handler called $forcex for the current child. + +Ctrl+Y changed: The CtrlY handler uses $delprc to delete all children. This way +also actions with DCL commands will be stopped. As before Ctrl+Y then sends +SIGQUIT to itself, which is handled in common code. + +Change in deleteing temporary command files + +Temporary command files were deleted in the main line, after returning from the +vms child termination handler. If Ctrl+C was pressed, the handler is called but +did not return to main line. + +Now, temporary command files are deleted in the vms child termination +handler. That deletes the them even if a Ctrl+C was pressed. + +The behavior of pressing Ctrl+C is not changed. It still has only an effect, +after the current action is terminated. If that doesn't happen or takes too +long, Ctrl+Y should be used instead. + +Changes (3.80) . In default.c define variable ARCH as IA64 for VMS on Itanium systems. @@ -297,7 +376,7 @@ Comma (',') as a separator is now allowed. See makefile.vms for an example. ------------------------------------------------------------------------------- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/remake.c b/src/kmk/remake.c index c465f0b..8855a2f 100644 --- a/src/kmk/remake.c +++ b/src/kmk/remake.c @@ -1,7 +1,7 @@ /* Basic dependency engine for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -88,7 +88,6 @@ int update_goal_chain (struct dep *goals) { int t = touch_flag, q = question_flag, n = just_print_flag; - unsigned int j = job_slots; int status = -1; #define MTIME(file) (rebuilding_makefiles ? file_mtime_no_search (file) \ @@ -140,6 +139,9 @@ update_goal_chain (struct dep *goals) { unsigned int ocommands_started; int x; + + file->dontcare = g->dontcare; + check_renamed (file); if (rebuilding_makefiles) { @@ -213,6 +215,8 @@ update_goal_chain (struct dep *goals) When they are all finished, the goal is finished. */ any_not_updated |= !file->updated; + file->dontcare = 0; + if (stop) break; } @@ -273,7 +277,6 @@ update_goal_chain (struct dep *goals) touch_flag = t; question_flag = q; just_print_flag = n; - job_slots = j; } return status; @@ -305,8 +308,14 @@ update_file (struct file *file, unsigned int depth) change is possible below here until then. */ if (f->considered == considered) { - DBF (DB_VERBOSE, _("Pruning file `%s'.\n")); - return f->command_state == cs_finished ? f->update_status : 0; + /* Check for the case where a target has been tried and failed but + the diagnostics hasn't been issued. If we need the diagnostics + then we will have to continue. */ + if (!(f->updated && f->update_status > 0 && !f->dontcare && f->no_diag)) + { + DBF (DB_VERBOSE, _("Pruning file `%s'.\n")); + return f->command_state == cs_finished ? f->update_status : 0; + } } /* This loop runs until we start commands for a double colon rule, or until @@ -323,7 +332,7 @@ update_file (struct file *file, unsigned int depth) /* If we got an error, don't bother with double_colon etc. */ if (status != 0 && !keep_going_flag) - return status; + return status; if (f->command_state == cs_running || f->command_state == cs_deps_running) @@ -354,65 +363,89 @@ update_file (struct file *file, unsigned int depth) /* Show a message stating the target failed to build. */ static void -complain (const struct file *file) +complain (struct file *file) { const char *msg_noparent = _("%sNo rule to make target `%s'%s"); const char *msg_parent = _("%sNo rule to make target `%s', needed by `%s'%s"); -#ifdef KMK - /* jokes */ - if (!keep_going_flag && file->parent == 0) + /* If this file has no_diag set then it means we tried to update it + before in the dontcare mode and failed. The target that actually + failed is not necessarily this file but could be one of its direct + or indirect dependencies. So traverse this file's dependencies and + find the one that actually caused the failure. */ + + struct dep *d; + + for (d = file->deps; d != 0; d = d->next) { - const char *msg_joke = 0; - extern struct dep *goals; - - /* classics */ - if (!strcmp (file->name, "fire") - || !strcmp (file->name, "Fire")) - msg_joke = "No matches.\n"; - else if (!strcmp (file->name, "love") - || !strcmp (file->name, "Love") - || !strcmp (file->name, "peace") - || !strcmp (file->name, "Peace")) - msg_joke = "Not war.\n"; - else if (!strcmp (file->name, "war")) - msg_joke = "Don't know how to make war.\n"; - - /* http://xkcd.com/149/ - GNU Make bug #23273. */ - else if (( !strcmp (file->name, "me") - && goals != 0 - && !strcmp (dep_name(goals), "me") - && goals->next != 0 - && !strcmp (dep_name(goals->next), "a") - && goals->next->next != 0) - || !strncmp (file->name, "me a ", 5)) - msg_joke = + if (d->file->updated && d->file->update_status > 0 && file->no_diag) + { + complain (d->file); + break; + } + } + + if (d == 0) + { + /* Didn't find any dependencies to complain about. */ + +#ifdef KMK + /* jokes */ + if (!keep_going_flag && file->parent == 0) + { + const char *msg_joke = 0; + extern struct dep *goals; + + /* classics */ + if (!strcmp (file->name, "fire") + || !strcmp (file->name, "Fire")) + msg_joke = "No matches.\n"; + else if (!strcmp (file->name, "love") + || !strcmp (file->name, "Love") + || !strcmp (file->name, "peace") + || !strcmp (file->name, "Peace")) + msg_joke = "Not war.\n"; + else if (!strcmp (file->name, "war")) + msg_joke = "Don't know how to make war.\n"; + + /* http://xkcd.com/149/ - GNU Make bug #23273. */ + else if (( !strcmp (file->name, "me") + && goals != 0 + && !strcmp (dep_name(goals), "me") + && goals->next != 0 + && !strcmp (dep_name(goals->next), "a") + && goals->next->next != 0) + || !strncmp (file->name, "me a ", 5)) + msg_joke = # ifdef HAVE_UNISTD_H getuid () == 0 ? "Okay.\n" : # endif - "What? Make it yourself!\n"; - if (msg_joke) - { - fputs (msg_joke, stderr); - die (2); + "What? Make it yourself!\n"; + if (msg_joke) + { + fputs (msg_joke, stderr); + die (2); + } } - } #endif /* KMK */ - if (!keep_going_flag) - { + if (!keep_going_flag) + { + if (file->parent == 0) + fatal (NILF, msg_noparent, "", file->name, ""); + + fatal (NILF, msg_parent, "", file->name, file->parent->name, ""); + } + if (file->parent == 0) - fatal (NILF, msg_noparent, "", file->name, ""); + error (NILF, msg_noparent, "*** ", file->name, "."); + else + error (NILF, msg_parent, "*** ", file->name, file->parent->name, "."); - fatal (NILF, msg_parent, "", file->name, file->parent->name, ""); + file->no_diag = 0; } - - if (file->parent == 0) - error (NILF, msg_noparent, "*** ", file->name, "."); - else - error (NILF, msg_parent, "*** ", file->name, file->parent->name, "."); } /* Consider a single `struct file' and update it as appropriate. */ @@ -420,12 +453,16 @@ complain (const struct file *file) static int update_file_1 (struct file *file, unsigned int depth) { - register FILE_TIMESTAMP this_mtime; + FILE_TIMESTAMP this_mtime; int noexist, must_make, deps_changed; int dep_status = 0; - register struct dep *d, *lastd; + struct file *ofile; + struct dep *d, *ad; + struct dep amake; int running = 0; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET + struct file *req_file = file; + struct file *org_file = file; struct file *f2, *f3; /* Always work on the primary multi target file. */ @@ -434,7 +471,7 @@ update_file_1 (struct file *file, unsigned int depth) { DBS (DB_VERBOSE, (_("Considering target file `%s' -> multi head `%s'.\n"), file->name, file->multi_head->name)); - file = file->multi_head; + org_file = file = file->multi_head; } else #endif /* CONFIG_WITH_EXPLICIT_MULTITARGET */ @@ -447,15 +484,12 @@ update_file_1 (struct file *file, unsigned int depth) DBF (DB_VERBOSE, _("Recently tried and failed to update file `%s'.\n")); - /* If the file we tried to make is marked dontcare then no message + /* If the file we tried to make is marked no_diag then no message was printed about it when it failed during the makefile rebuild. If we're trying to build it again in the normal rebuild, print a message now. */ - if (file->dontcare && !rebuilding_makefiles) - { - file->dontcare = 0; + if (file->no_diag && !file->dontcare) complain (file); - } return file->update_status; } @@ -479,11 +513,19 @@ update_file_1 (struct file *file, unsigned int depth) abort (); } + /* Determine whether the diagnostics will be issued should this update + fail. */ + file->no_diag = file->dontcare; + ++depth; /* Notice recursive update of the same file. */ start_updating (file); + /* We might change file if we find a different one via vpath; + remember this one to turn off updating. */ + ofile = file; + /* Looking at the file's modtime beforehand allows the possibility that its name may be changed by a VPATH search, and thus it may not need an implicit rule. If this were not done, the file @@ -508,6 +550,16 @@ update_file_1 (struct file *file, unsigned int depth) f3 = f2; } } + /** @todo this isn't sufficient, need to introduce a truly optional type and + * make |+ ignore mtime. let's hope that doesn't break too much... */ + /* If the requested file doesn't exist, always do a remake in the + hope that it is recreated even if it's "maybe" target. */ + else if (f2 == req_file && file_mtime (f2) == NONEXISTENT_MTIME) + { + this_mtime = NONEXISTENT_MTIME; + f3 = f2; + break; + } check_renamed (file); noexist = this_mtime == NONEXISTENT_MTIME; if (noexist) @@ -550,22 +602,32 @@ update_file_1 (struct file *file, unsigned int depth) file->cmds = default_file->cmds; } - /* Update all non-intermediate files we depend on, if necessary, - and see whether any of them is more recent than this file. - For explicit multitarget rules we must iterate all the output + /* Update all non-intermediate files we depend on, if necessary, and see + whether any of them is more recent than this file. We need to walk our + deps, AND the deps of any also_make targets to ensure everything happens + in the correct order. + + bird: For explicit multitarget rules we must iterate all the output files to get the correct picture. The special .MUST_MAKE - target variable call is also done from this context. */ + target variable call is also done from this context. */ #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - for (f2 = file; f2; f2 = f2->multi_next) - { - lastd = 0; - d = f2->deps; -#else - lastd = 0; - d = file->deps; + assert (file == org_file); + for (f2 = file; f2; file = f2 = f2->multi_next) + { #endif - while (d != 0) + amake.file = file; + amake.next = file->also_make; + ad = &amake; + while (ad) + { + struct dep *lastd = 0; + + /* Find the deps we're scanning */ + d = ad->file->deps; + ad = ad->next; + + while (d) { FILE_TIMESTAMP mtime; int maybe_make; @@ -580,7 +642,7 @@ update_file_1 (struct file *file, unsigned int depth) { #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET /* silently ignore the order-only dep hack. */ - if (f2->multi_maybe && d->file == file) + if (file->multi_maybe && d->file == org_file) { lastd = d; d = d->next; @@ -589,31 +651,19 @@ update_file_1 (struct file *file, unsigned int depth) #endif error (NILF, _("Circular %s <- %s dependency dropped."), -#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - f2->name, d->file->name); -#else file->name, d->file->name); -#endif /* We cannot free D here because our the caller will still have a reference to it when we were called recursively via check_dep below. */ if (lastd == 0) -#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - f2->deps = d->next; -#else file->deps = d->next; -#endif else lastd->next = d->next; d = d->next; continue; } -#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - d->file->parent = f2; -#else d->file->parent = file; -#endif maybe_make = must_make; /* Inherit dontcare flag from our parent. */ @@ -623,7 +673,6 @@ update_file_1 (struct file *file, unsigned int depth) d->file->dontcare = file->dontcare; } - dep_status |= check_dep (d->file, depth, this_mtime, &maybe_make); /* Restore original dontcare flag. */ @@ -660,11 +709,13 @@ update_file_1 (struct file *file, unsigned int depth) lastd = d; d = d->next; } + } #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - if (dep_status != 0 && !keep_going_flag) - break; - } + if (dep_status != 0 && !keep_going_flag) + break; + } + file = org_file; #endif #ifdef CONFIG_WITH_DOT_MUST_MAKE @@ -673,7 +724,7 @@ update_file_1 (struct file *file, unsigned int depth) # ifdef CONFIG_WITH_EXPLICIT_MULTITARGET if (!must_make) - for (f2 = file; f2 && !must_make; f2 = f2->multi_next) + for (f2 = org_file; f2 && !must_make; f2 = f2->multi_next) must_make = call_must_make_target_var (f2, depth); # else if (!must_make) @@ -687,22 +738,16 @@ update_file_1 (struct file *file, unsigned int depth) if (must_make || always_make_flag) { #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - for (f2 = file; f2; f2 = f2->multi_next) - for (d = f2->deps; d != 0; d = d->next) -#else - for (d = file->deps; d != 0; d = d->next) + for (file = f2 = org_file; f2; file = f2 = f2->multi_next) #endif + for (d = file->deps; d != 0; d = d->next) if (d->file->intermediate) { int dontcare = 0; FILE_TIMESTAMP mtime = file_mtime (d->file); check_renamed (d->file); -#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - d->file->parent = f2; -#else d->file->parent = file; -#endif /* Inherit dontcare flag from our parent. */ if (rebuilding_makefiles) @@ -737,16 +782,16 @@ update_file_1 (struct file *file, unsigned int depth) break; if (!running) -#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - d->changed = ((f2->phony && f2->cmds != 0) -#else d->changed = ((file->phony && file->cmds != 0) -#endif || file_mtime (d->file) != mtime); } +#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET + file = org_file; +#endif } finish_updating (file); + finish_updating (ofile); DBF (DB_VERBOSE, _("Finished prerequisites of target file `%s'.\n")); @@ -793,13 +838,13 @@ update_file_1 (struct file *file, unsigned int depth) deps_changed = 0; #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - for (f2 = file; f2; f2 = f2->multi_next) + for (file = f2 = org_file; f2; file = f2 = f2->multi_next) #endif for (d = file->deps; d != 0; d = d->next) { FILE_TIMESTAMP d_mtime = file_mtime (d->file); #ifdef CONFIG_WITH_EXPLICIT_MULTITARGET - if (d->file == file && f2->multi_maybe) + if (d->file == file && file->multi_maybe) continue; #endif check_renamed (d->file); @@ -854,6 +899,9 @@ update_file_1 (struct file *file, unsigned int depth) } } } +#ifdef CONFIG_WITH_EXPLICIT_MULTITARGET + file = org_file; +#endif /* Here depth returns to the value it had when we were called. */ depth--; @@ -1163,7 +1211,7 @@ notice_finished_file (struct file *file) really check the target's mtime again. Otherwise, assume the target would have been updated. */ - if (question_flag || just_print_flag || touch_flag) + if ((question_flag || just_print_flag || touch_flag) && file->cmds) { for (i = file->cmds->ncommand_lines; i > 0; --i) if (! (file->cmds->lines_flags[i-1] & COMMANDS_RECURSE)) @@ -1270,12 +1318,17 @@ static int check_dep (struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make_ptr) { + struct file *ofile; struct dep *d; int dep_status = 0; ++depth; start_updating (file); + /* We might change file if we find a different one via vpath; + remember this one to turn off updating. */ + ofile = file; + if (file->phony || !file->intermediate) { /* If this is a non-intermediate file, update it and record whether it @@ -1325,23 +1378,16 @@ check_dep (struct file *file, unsigned int depth, /* Otherwise, update all non-intermediate files we depend on, if necessary, and see whether any of them is more recent than the file on whose behalf we are checking. */ - struct dep *lastd; + struct dep *ld; int deps_running = 0; - /* Reset this target's state so that we check it fresh. It could be - that it's already been checked as part of an order-only - prerequisite and so wasn't rebuilt then, but should be now. - - bird: What if we're already running the recipe? We don't wish - it to be started once again do we? This happens with the - SECONDARY Test #9 here now... If the idea is to re-evaluate - the target regardless of whether it's running or no, then - perhaps saving and restoring is a better idea? - See bug #15919. */ - if (file->command_state != cs_running) /* bird */ + /* If this target is not running, set it's state so that we check it + fresh. It could be it was checked as part of an order-only + prerequisite and so wasn't rebuilt then, but should be now. */ + if (file->command_state != cs_running) set_command_state (file, cs_not_started); - lastd = 0; + ld = 0; d = file->deps; while (d != 0) { @@ -1351,7 +1397,7 @@ check_dep (struct file *file, unsigned int depth, { error (NILF, _("Circular %s <- %s dependency dropped."), file->name, d->file->name); - if (lastd == 0) + if (ld == 0) { file->deps = d->next; free_dep (d); @@ -1359,9 +1405,9 @@ check_dep (struct file *file, unsigned int depth, } else { - lastd->next = d->next; + ld->next = d->next; free_dep (d); - d = lastd->next; + d = ld->next; } continue; } @@ -1380,7 +1426,7 @@ check_dep (struct file *file, unsigned int depth, || d->file->command_state == cs_deps_running) deps_running = 1; - lastd = d; + ld = d; d = d->next; } @@ -1393,6 +1439,8 @@ check_dep (struct file *file, unsigned int depth, } finish_updating (file); + finish_updating (ofile); + return dep_status; } @@ -1577,7 +1625,7 @@ f_mtime (struct file *file, int search) if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath) { /* If name_mtime failed, search VPATH. */ - const char *name = vpath_search (file->name, &mtime); + const char *name = vpath_search (file->name, &mtime, NULL, NULL); if (name /* Last resort, is it a library (-lxxx)? */ || (file->name[0] == '-' && file->name[1] == 'l' @@ -1828,30 +1876,31 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr) 0 }; - static char *libpatterns = NULL; - - const char *libname = lib+2; /* Name without the '-l'. */ + const char *file = 0; + char *libpatterns; FILE_TIMESTAMP mtime; /* Loop variables for the libpatterns value. */ char *p; const char *p2; unsigned int len; + unsigned int liblen; - char **dp; + /* Information about the earliest (in the vpath sequence) match. */ + unsigned int best_vpath = 0, best_path = 0; /* bird: gcc maybe used uninitialized (both) */ + unsigned int std_dirs = 0; - /* If we don't have libpatterns, get it. */ - if (!libpatterns) - { - int save = warn_undefined_variables_flag; - warn_undefined_variables_flag = 0; + char **dp; - libpatterns = xstrdup (variable_expand ("$(strip $(.LIBPATTERNS))")); + libpatterns = xstrdup (variable_expand ("$(.LIBPATTERNS)")); - warn_undefined_variables_flag = save; - } + /* Skip the '-l'. */ + lib += 2; + liblen = strlen (lib); - /* Loop through all the patterns in .LIBPATTERNS, and search on each one. */ + /* Loop through all the patterns in .LIBPATTERNS, and search on each one. + To implement the linker-compatible behavior we have to search through + all entries in .LIBPATTERNS and choose the "earliest" one. */ p2 = libpatterns; while ((p = find_next_token (&p2, &len)) != 0) { @@ -1861,7 +1910,7 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr) char *libbuf = variable_expand (""); const size_t libbuf_offset = libbuf - variable_buffer; /* bird */ - /* Expand the pattern using LIBNAME as a replacement. */ + /* Expand the pattern using LIB as a replacement. */ { char c = p[len]; char *p3, *p4; @@ -1870,16 +1919,13 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr) p3 = find_percent (p); if (!p3) { - /* Give a warning if there is no pattern, then remove the - pattern so it's ignored next time. */ + /* Give a warning if there is no pattern. */ error (NILF, _(".LIBPATTERNS element `%s' is not a pattern"), p); - for (; len; --len, ++p) - *p = ' '; - *p = c; + p[len] = c; continue; } p4 = variable_buffer_output (libbuf, p, p3-p); - p4 = variable_buffer_output (p4, libname, strlen (libname)); + p4 = variable_buffer_output (p4, lib, liblen); p4 = variable_buffer_output (p4, p3+1, len - (p3-p)); p[len] = c; libbuf = variable_buffer + libbuf_offset; /* bird - variable_buffer may have been reallocated. */ @@ -1891,48 +1937,81 @@ library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr) { if (mtime_ptr != 0) *mtime_ptr = mtime; - return strcache_add (libbuf); + file = strcache_add (libbuf); + /* This by definition will have the best index, so stop now. */ + break; } /* Now try VPATH search on that. */ { - const char *file = vpath_search (libbuf, mtime_ptr); - if (file) - return file; + unsigned int vpath_index, path_index; + const char* f = vpath_search (libbuf, mtime_ptr ? &mtime : NULL, + &vpath_index, &path_index); + if (f) + { + /* If we have a better match, record it. */ + if (file == 0 || + vpath_index < best_vpath || + (vpath_index == best_vpath && path_index < best_path)) + { + file = f; + best_vpath = vpath_index; + best_path = path_index; + + if (mtime_ptr != 0) + *mtime_ptr = mtime; + } + } } /* Now try the standard set of directories. */ if (!buflen) - { - for (dp = dirs; *dp != 0; ++dp) - { - int l = strlen (*dp); - if (l > libdir_maxlen) - libdir_maxlen = l; - } - buflen = strlen (libbuf); - buf = xmalloc(libdir_maxlen + buflen + 2); - } + { + for (dp = dirs; *dp != 0; ++dp) + { + int l = strlen (*dp); + if (l > libdir_maxlen) + libdir_maxlen = l; + std_dirs++; + } + buflen = strlen (libbuf); + buf = xmalloc(libdir_maxlen + buflen + 2); + } else if (buflen < strlen (libbuf)) - { - buflen = strlen (libbuf); - buf = xrealloc (buf, libdir_maxlen + buflen + 2); - } + { + buflen = strlen (libbuf); + buf = xrealloc (buf, libdir_maxlen + buflen + 2); + } + + { + /* Use the last std_dirs index for standard directories. This + was it will always be greater than the VPATH index. */ + unsigned int vpath_index = ~((unsigned int)0) - std_dirs; + + for (dp = dirs; *dp != 0; ++dp) + { + sprintf (buf, "%s/%s", *dp, libbuf); + mtime = name_mtime (buf); + if (mtime != NONEXISTENT_MTIME) + { + if (file == 0 || vpath_index < best_vpath) + { + file = strcache_add (buf); + best_vpath = vpath_index; + + if (mtime_ptr != 0) + *mtime_ptr = mtime; + } + } + + vpath_index++; + } + } - for (dp = dirs; *dp != 0; ++dp) - { - sprintf (buf, "%s/%s", *dp, libbuf); - mtime = name_mtime (buf); - if (mtime != NONEXISTENT_MTIME) - { - if (mtime_ptr != 0) - *mtime_ptr = mtime; - return strcache_add (buf); - } - } } - return 0; + free (libpatterns); + return file; } diff --git a/src/kmk/remote-cstms.c b/src/kmk/remote-cstms.c index c8aab66..a0c5cb7 100644 --- a/src/kmk/remote-cstms.c +++ b/src/kmk/remote-cstms.c @@ -4,8 +4,8 @@ the Make maintainers. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/remote-stub.c b/src/kmk/remote-stub.c index 6b51c1d..e58b72c 100644 --- a/src/kmk/remote-stub.c +++ b/src/kmk/remote-stub.c @@ -1,7 +1,7 @@ /* Template for the remote job exportation interface to GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/rule.c b/src/kmk/rule.c index 0314232..881569d 100644 --- a/src/kmk/rule.c +++ b/src/kmk/rule.c @@ -1,7 +1,7 @@ /* Pattern and suffix rule internals for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -94,19 +94,20 @@ count_implicit_rule_limits (void) for (dep = rule->deps; dep != 0; dep = dep->next) { - unsigned int len = strlen (dep->name); + const char *dname = dep_name (dep); + unsigned int len = strlen (dname); #ifdef VMS - const char *p = strrchr (dep->name, ']'); + const char *p = strrchr (dname, ']'); const char *p2; if (p == 0) - p = strrchr (dep->name, ':'); - p2 = p != 0 ? strchr (dep->name, '%') : 0; + p = strrchr (dname, ':'); + p2 = p != 0 ? strchr (dname, '%') : 0; #else - const char *p = strrchr (dep->name, '/'); - const char *p2 = p != 0 ? strchr (dep->name, '%') : 0; + const char *p = strrchr (dname, '/'); + const char *p2 = p != 0 ? strchr (dname, '%') : 0; #endif - ndeps++; + ndeps++; if (len > max_pattern_dep_length) max_pattern_dep_length = len; @@ -115,15 +116,15 @@ count_implicit_rule_limits (void) { /* There is a slash before the % in the dep name. Extract the directory name. */ - if (p == dep->name) + if (p == dname) ++p; - if (p - dep->name > namelen) + if (p - dname > namelen) { - namelen = p - dep->name; + namelen = p - dname; name = xrealloc (name, namelen + 1); } - memcpy (name, dep->name, p - dep->name); - name[p - dep->name] = '\0'; + memcpy (name, dname, p - dname); + name[p - dname] = '\0'; /* In the deps of an implicit rule the `changed' flag actually indicates that the dependency is in a @@ -376,15 +377,7 @@ install_pattern_rule (struct pspec *p, int terminal) ++r->suffixes[0]; ptr = p->dep; -#ifndef CONFIG_WITH_ALLOC_CACHES - r->deps = (struct dep *) multi_glob (parse_file_seq (&ptr, '\0', - sizeof (struct dep), 1), - sizeof (struct dep)); -#else - r->deps = (struct dep *) multi_glob (parse_file_seq (&ptr, '\0', - &dep_cache, 1), - &dep_cache); -#endif + r->deps = PARSE_FILE_SEQ (&ptr, struct dep, '\0', NULL, 0); if (new_pattern_rule (r, 0)) { @@ -415,18 +408,12 @@ static void freerule (struct rule *rule, struct rule *lastrule) { struct rule *next = rule->next; - struct dep *dep; - dep = rule->deps; - while (dep) - { - struct dep *t = dep->next; - free_dep (dep); - dep = t; - } + free_dep_chain (rule->deps); - free (rule->targets); - free (rule->suffixes); + /* MSVC erroneously warns without a cast here. */ + free ((void *)rule->targets); + free ((void *)rule->suffixes); free (rule->lens); /* We can't free the storage for the commands because there @@ -499,7 +486,6 @@ static void /* Useful to call from gdb. */ print_rule (struct rule *r) { unsigned int i; - struct dep *d; for (i = 0; i < r->num; ++i) { @@ -509,9 +495,7 @@ print_rule (struct rule *r) if (r->terminal) putchar (':'); - for (d = r->deps; d != 0; d = d->next) - printf (" %s", dep_name (d)); - putchar ('\n'); + print_prereqs (r->deps); if (r->cmds != 0) print_commands (r->cmds); @@ -558,7 +542,7 @@ print_rule_data_base (void) /* This can happen if a fatal error was detected while reading the makefiles and thus count_implicit_rule_limits wasn't called yet. */ if (num_pattern_rules != 0) - fatal (NILF, _("BUG: num_pattern_rules wrong! %u != %u"), + fatal (NILF, _("BUG: num_pattern_rules is wrong! %u != %u"), num_pattern_rules, rules); } } diff --git a/src/kmk/rule.h b/src/kmk/rule.h index 868d12a..b119d21 100644 --- a/src/kmk/rule.h +++ b/src/kmk/rule.h @@ -1,7 +1,7 @@ /* Definitions for using pattern rules in GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/signame.c b/src/kmk/signame.c index dad58b2..6f3383d 100644 --- a/src/kmk/signame.c +++ b/src/kmk/signame.c @@ -1,6 +1,7 @@ /* Convert between signal names and numbers. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -228,7 +229,7 @@ signame_init (void) char * -strsignal (int signal) +strsignal (int sig) { static char buf[] = "Signal 12345678901234567890"; @@ -245,10 +246,10 @@ strsignal (int signal) # endif #endif - if (signal > 0 || signal < NSIG) - return (char *) sys_siglist[signal]; + if (sig > 0 || sig < NSIG) + return (char *) sys_siglist[sig]; - sprintf (buf, "Signal %d", signal); + sprintf (buf, "Signal %d", sig); return buf; } diff --git a/src/kmk/strcache.c b/src/kmk/strcache.c index 56b5495..90dceb6 100644 --- a/src/kmk/strcache.c +++ b/src/kmk/strcache.c @@ -1,5 +1,5 @@ /* Constant string caching for GNU Make. -Copyright (C) 2006, 2007 Free Software Foundation, Inc. +Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/subproc.bat b/src/kmk/subproc.bat index 38bacca..e5a0528 100644 --- a/src/kmk/subproc.bat +++ b/src/kmk/subproc.bat @@ -1,6 +1,6 @@ @echo off
rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-rem 2005, 2006, 2007 Free Software Foundation, Inc.
+rem 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
rem This file is part of GNU Make.
rem
rem GNU Make is free software; you can redistribute it and/or modify it under
diff --git a/src/kmk/testcase-kBuild-define.kmk b/src/kmk/testcase-kBuild-define.kmk index 970be89..c9edd18 100644 --- a/src/kmk/testcase-kBuild-define.kmk +++ b/src/kmk/testcase-kBuild-define.kmk @@ -1,10 +1,10 @@ -# $Id: testcase-kBuild-define.kmk 2549 2011-11-09 01:22:04Z bird $ +# $Id: testcase-kBuild-define.kmk 2658 2012-09-10 21:00:10Z bird $ ## @file # kBuild - testcase for the kBuild-define-* directives. # # -# Copyright (c) 2011 knut st. osmundsen <bird-kBuild-spamx@anduin.net> +# Copyright (c) 2011-2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> # # This file is part of kBuild. # @@ -26,31 +26,47 @@ DEPTH = ../.. #include $(PATH_KBUILD)/header.kmk -kBuild-define-target MyTarget +# object definition syntax: +# kobject <type> <name> [extends <object>] [object specific args...] +# endkobj [<type> [name]] +kobject kb-target MyTarget +.TOOL = GCC +.SOURCES = file.c +endobj -_TEMPLATE = MyTemplate -_SOURCES = MySourceFile.c +# accesses an already defined object. +# syntax: +# kaccess <type> <name> +# endkacc [<type> [name]] +kaccess kb-target MyTarget +.SOURCES += file2.c +endkacc -kBuild-endef-target MyTarget -$(if "$(MyTarget_TEMPLATE)" == "MyTemplate",,$(error MyTarget's _TEMPLATE wasn't set correctly in the global space)) -$(if "$(MyTarget_SOURCES)" == "MySourceFile.c",,$(error MyTarget's _TEMPLATE wasn't set correctly in the global space)) +# Referencing an object variable, the object must exist. +# syntax: [<type>@<name>].<property> +[kb-target@MyTarget].SOURCES += file3.c +$(info [kb-target@MyTarget].SOURCES is $([kb-target@MyTarget].SOURCES)) -INDIRECT_NAME = MyTarget$(strip $1) -kBuild-define-target $(call INDIRECT_NAME, 2) -local _TEMPLATE = MyTemplate2 -_SOURCES = MySourceFile2.c - -kBuild-endef-target $(call INDIRECT_NAME, 2) -$(if "$(_TEMPLATE)" == "",,$(error _TEMPLATE has leaked out into the global space)) +# Test #1 +kobject target BaseTarget with DUMMY as template +.SOURCES = BaseTargetSource.c +kendobj +$(if "$([target@BaseTarget].SOURCES)" == "BaseTargetSource.c",,$(error [target@BaseTarget].SOURCES is '$([target@BaseTarget].SOURCES)' not 'BaseTargetSource.c')) +$(if "$(BaseTarget_SOURCES)" == "BaseTargetSource.c",,$(error BaseTarget's _SOURCES wasn't set correctly in the global space)) +$(if "$([target@BaseTarget].TEMPLATE)" == "DUMMY",,$(error [target@BaseTarget].TEMPLATE is '$([target@BaseTarget].TEMPLATE)' not 'DUMMY')) +$(if "$(BaseTarget_TEMPLATE)" == "DUMMY",,$(error BaseTarget's _TEMPLATE wasn't set correctly in the global space)) +# Test #2 +kobject target TargetWithLocals +local .LOCAL_PROP = no global alias +kendobj +$(if "$([target@TargetWithLocals].LOCAL_PROP)" == "no global alias",,$(error [target@TargetWithLocals].LOCAL_PROP is '$([target@TargetWithLocals].LOCAL_PROP)' not 'no global alias')) +$(if "$(TargetWithLocals_LOCAL_PROP)" == "",,$(error TargetWithLocals_LOCAL_PROP's local property 'LOCAL_PROP' was exposed globally.)) all_recursive: #$(ECHO) "kBuild-define-xxxx works fine" - - - diff --git a/src/kmk/tests/ChangeLog b/src/kmk/tests/ChangeLog index d9a0488..d036568 100644 --- a/src/kmk/tests/ChangeLog +++ b/src/kmk/tests/ChangeLog @@ -1,3 +1,187 @@ +2010-07-28 Paul Smith <psmith@gnu.org> + + * scripts/targets/POSIX: Compatibility issues with Solaris (and + Tru64?); "false" returns different exit codes, and set -x shows + output with extra whitespace. Run the commands by hand first to + find out what the real shell would do, then compare what make does. + * scripts/variables/SHELL: Ditto. + +2010-07-12 Paul Smith <psmith@gnu.org> + + * test_driver.pl: Add a new $perl_name containing the path to Perl. + * run_make_tests.pl (run_make_test): Replace the special string + #PERL# in a makefile etc. with the path the Perl executable so + makefiles can use it. + + * scripts/targets/ONESHELL: Add a new set of regression tests for + the .ONESHELL feature. + +2010-07-06 Paul Smith <psmith@gnu.org> + + * scripts/variables/SHELL: Test the new .SHELLFLAGS variable. + + * scripts/targets/POSIX: New file. Test the .POSIX special target. + Verify that enabling .POSIX changes the shell flags to set -e. + +2010-07-01 Paul Smith <psmith@gnu.org> + + * scripts/features/recursion: Add a space to separate command-line + args. Fixes Savannah bug #29968. + +2009-11-12 Boris Kolpackov <boris@codesynthesis.com> + + * scripts/features/vpath3: Test for the new library search + behavior. + +2009-10-06 Boris Kolpackov <boris@codesynthesis.com> + + * scripts/features/se_explicit: Enable the test for now fixed + Savannah bug 25780. + +2009-10-06 Boris Kolpackov <boris@codesynthesis.com> + + * scripts/variables/undefine: Tests for the new undefine feature. + +2009-10-03 Paul Smith <psmith@gnu.org> + + * scripts/features/parallelism: Test for open Savannah bug #26846. + + * scripts/variables/MAKE: Rewrite for new run_make_test() format. + + * scripts/variables/MAKEFLAGS: Created. + Add test for Savannah bug #2216 (still open). + + * scripts/features/include: Test for Savannah bug #102 (still open). + +2009-09-30 Boris Kolpackov <boris@codesynthesis.com> + + * scripts/features/include: Add diagnostics issuing tests for + cases where targets have been updated and failed with the + dontcare flag. Savannah bugs #15110, #25493, #12686, #17740. + +2009-09-28 Paul Smith <psmith@gnu.org> + + * scripts/functions/shell: Add regression test for Savannah bug + #20513 (still open). + + * scripts/features/se_explicit: Add regression tests for Savannah + bug #25780 (still open). + + * run_make_tests.pl (valid_option): Add a new flag, -all([-_]?tests)? + that runs tests we know will fail. This allows us to add + regression tests to the test suite for bugs that haven't been + fixed yet. + +2009-09-28 Boris Kolpackov <boris@codesynthesis.com> + + * scripts/features/patspecific_vars: Add a test for the shortest + stem first order. + + * scripts/features/patternrules: Add a test for the shortest stem + first order. + +2009-09-24 Paul Smith <psmith@gnu.org> + + * scripts/features/se_implicit: Add a test for order-only + secondary expansion prerequisites. + +2009-09-23 Paul Smith <psmith@gnu.org> + + * scripts/features/patternrules: Test that we can remove pattern + rules, both single and multiple prerequisites. Savannah bug #18622. + + * scripts/features/echoing: Rework for run_make_test(). + +2009-06-14 Paul Smith <psmith@gnu.org> + + * scripts/features/vpath: Verify we don't get bogus circular + dependency warnings if we choose a different file via vpath during + update. Savannah bug #13529. + +2009-06-13 Paul Smith <psmith@gnu.org> + + * scripts/variables/MAKEFILES: Verify that MAKEFILES included + files (and files included by them) don't set the default goal. + Savannah bug #13401. + + * scripts/functions/wildcard: Test that wildcards with + non-existent glob matchers return empty. + +2009-06-09 Paul Smith <psmith@gnu.org> + + * scripts/options/dash-B: Test the $? works correctly with -B. + Savannah bug #17825. + + * scripts/features/patternrules: Test that dependencies of + "also_make" targets are created properly. Savannah bug #19108. + + * test_driver.pl (compare_output): Create a "run" file for failed + tests containing the command that was run. + (get_runfile): New function. + + * run_make_tests.pl (valid_option): Enhanced support for valgrind: + allow memcheck and massif tools. + + * scripts/features/patternrules: Have to comment out a line in the + first test due to backing out a change that broke the implicit + rule search algorithm. Savannah bug #17752. + * scripts/misc/general4: Remove a test that is redundant with + patternrules. + + * scripts/features/parallelism: Add a test for re-exec with + jobserver master override. Savannah bug #18124. + +2009-06-08 Paul Smith <psmith@gnu.org> + + * scripts/features/targetvars: Add a test for continued target + vars after a semicolon. Savannah bug #17521. + +2009-06-07 Paul Smith <psmith@gnu.org> + + * scripts/features/se_explicit: Make sure we catch defining + prereqs during snap_deps(). Savannah bug #24622. + + * scripts/variables/automatic: Check prereq ordering when the + target with the recipe has no prereqs. Savannah bug #21198. + + * scripts/variables/LIBPATTERNS: Add a new set of test for + $(.LIBPATTERNS) (previously untested!) + +2009-06-04 Paul Smith <psmith@gnu.org> + + * scripts/variables/SHELL: The export target-specific SHELL test + has an incorrect known-good-value. + + * scripts/misc/general4: Check for whitespace (ffeed, vtab, etc.) + + * scripts/features/se_explicit: Add tests for Savannah bug #24588. + +2009-05-31 Paul Smith <psmith@gnu.org> + + * scripts/variables/DEFAULT_GOAL: Add tests for Savannah bug #25697. + + * scripts/features/targetvars: Add tests of overrides for Savannah + bug #26207. + * scripts/features/patspecific_vars: Ditto. + + * scripts/features/patternrules: Add a test for Savannah bug #26593. + +2009-05-30 Paul Smith <psmith@gnu.org> + + * scripts/variables/flavors: Update with new variable flavor tests. + * scripts/variables/define: Create a new set of tests for + define/endef and move those aspects of the flavors suite here. + +2009-05-25 Paul Smith <psmith@gnu.org> + + * scripts/features/targetvars: Ditto. + + * scripts/features/export: Test new variable parsing abilities. + +2009-02-23 Ramon Garcia <ramon.garcia.f@gmail.com> + + * scripts/variables/private: Create a new suite of tests for 'private'. + 2007-11-04 Paul Smith <psmith@gnu.org> * scripts/functions/eval: Update error message for command -> recipe. @@ -879,7 +1063,7 @@ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/tests/NEWS b/src/kmk/tests/NEWS index 6d4fcbb..43971ec 100644 --- a/src/kmk/tests/NEWS +++ b/src/kmk/tests/NEWS @@ -163,7 +163,7 @@ Changes from 0.1 to 0.2 (5-4-92): ------------------------------------------------------------------------------- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/tests/README b/src/kmk/tests/README index 9791005..3860bdb 100644 --- a/src/kmk/tests/README +++ b/src/kmk/tests/README @@ -8,7 +8,7 @@ distributed under the following terms: ----------------------------------------------------------------------------- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/tests/mkshadow b/src/kmk/tests/mkshadow index 22eb447..d41b40e 100755 --- a/src/kmk/tests/mkshadow +++ b/src/kmk/tests/mkshadow @@ -4,7 +4,8 @@ # Typically you'd put the shadow in /tmp or another local disk # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/tests/run_make_tests.pl b/src/kmk/tests/run_make_tests.pl index 00dc41d..c8d7b55 100755 --- a/src/kmk/tests/run_make_tests.pl +++ b/src/kmk/tests/run_make_tests.pl @@ -12,7 +12,8 @@ # (and others) # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under @@ -28,10 +29,17 @@ # You should have received a copy of the GNU General Public License along with # this program. If not, see <http://www.gnu.org/licenses/>. + $valgrind = 0; # invoke make with valgrind -$valgrind_args = '--num-callers=15 --tool=memcheck --leak-check=full'; +$valgrind_args = ''; +$memcheck_args = '--num-callers=15 --tool=memcheck --leak-check=full'; +$massif_args = '--num-callers=15 --tool=massif --alloc-fn=xmalloc --alloc-fn=xcalloc --alloc-fn=xrealloc --alloc-fn=xstrdup --alloc-fn=xstrndup'; $pure_log = undef; +$command_string = ''; + +$all_tests = 0; + require "test_driver.pl"; # Some target systems might not have the POSIX module... @@ -43,20 +51,30 @@ sub valid_option { local($option) = @_; - if ($option =~ /^-make([-_]?path)?$/) - { - $make_path = shift @argv; - if (!-f $make_path) - { - print "$option $make_path: Not found.\n"; - exit 0; - } - return 1; + if ($option =~ /^-make([-_]?path)?$/i) { + $make_path = shift @argv; + if (!-f $make_path) { + print "$option $make_path: Not found.\n"; + exit 0; + } + return 1; + } + + if ($option =~ /^-all([-_]?tests)?$/i) { + $all_tests = 1; + return 1; + } + + if ($option =~ /^-(valgrind|memcheck)$/i) { + $valgrind = 1; + $valgrind_args = $memcheck_args; + return 1; } - if ($option =~ /^-valgrind$/i) { - $valgrind = 1; - return 1; + if ($option =~ /^-massif$/i) { + $valgrind = 1; + $valgrind_args = $massif_args; + return 1; } # This doesn't work--it _should_! Someone badly needs to fix this. @@ -105,6 +123,7 @@ sub run_make_test $makestring =~ s/#MAKEFILE#/$makefile/g; $makestring =~ s/#MAKEPATH#/$mkpath/g; $makestring =~ s/#MAKE#/$make_name/g; + $makestring =~ s/#PERL#/$perl_name/g; $makestring =~ s/#PWD#/$pwd/g; # Populate the makefile! @@ -119,6 +138,7 @@ sub run_make_test $answer =~ s/#MAKEFILE#/$makefile/g; $answer =~ s/#MAKEPATH#/$mkpath/g; $answer =~ s/#MAKE#/$make_name/g; + $answer =~ s/#PERL#/$perl_name/g; $answer =~ s/#PWD#/$pwd/g; run_make_with_options($makefile, $options, &get_logfile(0), @@ -148,6 +168,8 @@ sub run_make_with_options { $command .= " $options"; } + $command_string = "$command\n"; + if ($valgrind) { print VALGRIND "\n\nExecuting: $command\n"; } @@ -155,7 +177,10 @@ sub run_make_with_options { { my $old_timeout = $test_timeout; - $test_timeout = $timeout if $timeout; + $timeout and $test_timeout = $timeout; + + # If valgrind is enabled, turn off the timeout check + $valgrind and $test_timeout = 0; $code = &run_command_with_output($logname,$command); @@ -183,10 +208,12 @@ sub run_make_with_options { if ($code != $expected_code) { print "Error running $make_path (expected $expected_code; got $code): $command\n"; $test_passed = 0; + $runf = &get_runfile; + &create_file (&get_runfile, $command_string); # If it's a SIGINT, stop here if ($code & 127) { print STDERR "\nCaught signal ".($code & 127)."!\n"; - exit($code); + ($code & 127) == 2 and exit($code); } return 0; } @@ -195,19 +222,28 @@ sub run_make_with_options { system "add_profile $make_path"; } - 1; + return 1; } sub print_usage { &print_standard_usage ("run_make_tests", - "[-make_path make_pathname] [-valgrind]",); + "[-make_path make_pathname] [-memcheck] [-massif]",); } sub print_help { - &print_standard_help ("-make_path", - "\tYou may specify the pathname of the copy of make to run."); + &print_standard_help ( + "-make_path", + "\tYou may specify the pathname of the copy of make to run.", + "-valgrind", + "-memcheck", + "\tRun the test suite under valgrind's memcheck tool.", + "\tChange the default valgrind args with the VALGRIND_ARGS env var.", + "-massif", + "\tRun the test suite under valgrind's massif toool.", + "\tChange the default valgrind args with the VALGRIND_ARGS env var." + ); } sub get_this_pwd { @@ -335,11 +371,12 @@ sub set_more_defaults # Set up for valgrind, if requested. if ($valgrind) { + my $args = $valgrind_args; open(VALGRIND, "> valgrind.out") || die "Cannot open valgrind.out: $!\n"; # -q --leak-check=yes - exists $ENV{VALGRIND_ARGS} and $valgrind_args = $ENV{VALGRIND_ARGS}; - $make_path = "valgrind --log-fd=".fileno(VALGRIND)." $valgrind_args $make_path"; + exists $ENV{VALGRIND_ARGS} and $args = $ENV{VALGRIND_ARGS}; + $make_path = "valgrind --log-fd=".fileno(VALGRIND)." $args $make_path"; # F_SETFD is 2 fcntl(VALGRIND, 2, 0) or die "fcntl(setfd) failed: $!\n"; system("echo Starting on `date` 1>&".fileno(VALGRIND)); diff --git a/src/kmk/tests/scripts/features/echoing b/src/kmk/tests/scripts/features/echoing index 2e366cd..40debf5 100644 --- a/src/kmk/tests/scripts/features/echoing +++ b/src/kmk/tests/scripts/features/echoing @@ -1,87 +1,64 @@ -$description = "The following test creates a makefile to test command \n" - ."echoing. It tests that when a command line starts with \n" - ."a '\@', the echoing of that line is suppressed. It also \n" - ."tests the -n option which tells make to ONLY echo the \n" - ."commands and no execution happens. In this case, even \n" - ."the commands with '\@' are printed. Lastly, it tests the \n" - ."-s flag which tells make to prevent all echoing, as if \n" - ."all commands started with a '\@'."; - -$details = "This test is similar to the 'clean' test except that a '\@' has\n" - ."been placed in front of the delete command line. Four tests \n" - ."are run here. First, make is run normally and the first echo\n" - ."command should be executed. In this case there is no '\@' so \n" - ."we should expect make to display the command AND display the \n" - ."echoed message. Secondly, make is run with the clean target, \n" - ."but since there is a '\@' at the beginning of the command, we\n" - ."expect no output; just the deletion of a file which we check \n" - ."for. Third, we give the clean target again except this time\n" - ."we give make the -n option. We now expect the command to be \n" - ."displayed but not to be executed. In this case we need only \n" - ."to check the output since an error message would be displayed\n" - ."if it actually tried to run the delete command again and the \n" - ."file didn't exist. Lastly, we run the first test again with \n" - ."the -s option and check that make did not echo the echo \n" - ."command before printing the message."; +# -*-perl-*- +$description = "The following test creates a makefile to test command +echoing. It tests that when a command line starts with +a '\@', the echoing of that line is suppressed. It also +tests the -n option which tells make to ONLY echo the +commands and no execution happens. In this case, even +the commands with '\@' are printed. Lastly, it tests the +-s flag which tells make to prevent all echoing, as if +all commands started with a '\@'."; + +$details = "This test is similar to the 'clean' test except that a '\@' has +been placed in front of the delete command line. Four tests +are run here. First, make is run normally and the first echo +command should be executed. In this case there is no '\@' so +we should expect make to display the command AND display the +echoed message. Secondly, make is run with the clean target, +but since there is a '\@' at the beginning of the command, we +expect no output; just the deletion of a file which we check +for. Third, we give the clean target again except this time +we give make the -n option. We now expect the command to be +displayed but not to be executed. In this case we need only +to check the output since an error message would be displayed +if it actually tried to run the delete command again and the +file didn't exist. Lastly, we run the first test again with +the -s option and check that make did not echo the echo +command before printing the message.\n"; $example = "EXAMPLE_FILE"; -open(MAKEFILE,"> $makefile"); - -# The Contents of the MAKEFILE ... - -print MAKEFILE "all: \n"; -print MAKEFILE "\techo This makefile did not clean the dir... good\n"; -print MAKEFILE "clean: \n"; -print MAKEFILE "\t\@$delete_command $example\n"; - -# END of Contents of MAKEFILE - -close(MAKEFILE); - -&touch($example); +touch($example); # TEST #1 # ------- -&run_make_with_options($makefile,"",&get_logfile,0); -$answer = "echo This makefile did not clean the dir... good\n" - ."This makefile did not clean the dir... good\n"; -&compare_output($answer,&get_logfile(1)); - +run_make_test(" +all: +\techo This makefile did not clean the dir... good +clean: +\t\@$delete_command $example\n", + '', 'echo This makefile did not clean the dir... good +This makefile did not clean the dir... good'); # TEST #2 # ------- -&run_make_with_options($makefile,"clean",&get_logfile,0); +run_make_test(undef, 'clean', ''); if (-f $example) { $test_passed = 0; + unlink($example); } -&compare_output('',&get_logfile(1)); # TEST #3 # ------- -&run_make_with_options($makefile,"-n clean",&get_logfile,0); -$answer = "$delete_command $example\n"; -&compare_output($answer,&get_logfile(1)); +run_make_test(undef, '-n clean', "$delete_command $example\n"); # TEST #4 # ------- -&run_make_with_options($makefile,"-s",&get_logfile,0); -$answer = "This makefile did not clean the dir... good\n"; -&compare_output($answer,&get_logfile(1)); +run_make_test(undef, '-s', "This makefile did not clean the dir... good\n"); 1; - - - - - - - - - diff --git a/src/kmk/tests/scripts/features/export b/src/kmk/tests/scripts/features/export index 38efe11..81bff0c 100644 --- a/src/kmk/tests/scripts/features/export +++ b/src/kmk/tests/scripts/features/export @@ -6,12 +6,7 @@ $details = ""; # The test driver cleans out our environment for us so we don't have to worry # about that here. -open(MAKEFILE,"> $makefile"); - -# The Contents of the MAKEFILE ... - -print MAKEFILE <<'EOMAKE'; - +&run_make_test(' FOO = foo BAR = bar BOZ = boz @@ -40,76 +35,44 @@ endif all: @echo "FOO=$(FOO) BAR=$(BAR) BAZ=$(BAZ) BOZ=$(BOZ) BITZ=$(BITZ) BOTZ=$(BOTZ)" @echo "FOO=$$FOO BAR=$$BAR BAZ=$$BAZ BOZ=$$BOZ BITZ=$$BITZ BOTZ=$$BOTZ" - -EOMAKE - -close(MAKEFILE); - -# TEST 0: basics - -&run_make_with_options($makefile,"",&get_logfile,0); - -$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz -FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"; - -&compare_output($answer,&get_logfile(1)); +', + '', "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); # TEST 1: make sure vars inherited from the parent are exported $extraENV{FOO} = 1; -&run_make_with_options($makefile,"",&get_logfile,0); - -$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz -FOO=foo BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"; - -&compare_output($answer,&get_logfile(1)); +&run_make_test(undef, '', "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO=foo BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); # TEST 2: global export. Explicit unexport takes precedence. -&run_make_with_options($makefile,"EXPORT_ALL=1",&get_logfile,0); - -$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz -FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"; - -&compare_output($answer,&get_logfile(1)); +run_make_test(undef, "EXPORT_ALL=1" , + "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); # TEST 3: global unexport. Explicit export takes precedence. -&run_make_with_options($makefile,"UNEXPORT_ALL=1",&get_logfile,0); - -$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz -FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"; - -&compare_output($answer,&get_logfile(1)); +&run_make_test(undef, "UNEXPORT_ALL=1", + "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); # TEST 4: both: in the above makefile the unexport comes last so that rules. -&run_make_with_options($makefile,"EXPORT_ALL=1 UNEXPORT_ALL=1",&get_logfile,0); - -$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz -FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"; - -&compare_output($answer,&get_logfile(1)); +&run_make_test(undef, "EXPORT_ALL=1 UNEXPORT_ALL=1", + "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); # TEST 5: test the pseudo target. -&run_make_with_options($makefile,"EXPORT_ALL_PSEUDO=1",&get_logfile,0); - -$answer = "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz -FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"; - -&compare_output($answer,&get_logfile(1)); - +&run_make_test(undef, "EXPORT_ALL_PSEUDO=1", + "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz +FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); # TEST 6: Test the expansion of variables inside export -$makefile2 = &get_tmpfile; - -open(MAKEFILE, "> $makefile2"); - -print MAKEFILE <<'EOF'; - +&run_make_test(' foo = f-ok bar = b-ok @@ -125,24 +88,12 @@ export $(B)ar all: @echo foo=$(foo) bar=$(bar) @echo foo=$$foo bar=$$bar - -EOF - -close(MAKEFILE); - -&run_make_with_options($makefile2,"",&get_logfile,0); -$answer = "foo=f-ok bar=b-ok\nfoo=f-ok bar=b-ok\n"; -&compare_output($answer,&get_logfile(1)); - +', + "", "foo=f-ok bar=b-ok\nfoo=f-ok bar=b-ok\n"); # TEST 7: Test the expansion of variables inside unexport -$makefile3 = &get_tmpfile; - -open(MAKEFILE, "> $makefile3"); - -print MAKEFILE <<'EOF'; - +&run_make_test(' foo = f-ok bar = b-ok @@ -160,24 +111,12 @@ unexport $(B)ar all: @echo foo=$(foo) bar=$(bar) @echo foo=$$foo bar=$$bar - -EOF - -close(MAKEFILE); - -&run_make_with_options($makefile3,"",&get_logfile,0); -$answer = "foo=f-ok bar=b-ok\nfoo= bar=\n"; -&compare_output($answer,&get_logfile(1)); - +', + '', "foo=f-ok bar=b-ok\nfoo= bar=\n"); # TEST 7: Test exporting multiple variables on the same line -$makefile4 = &get_tmpfile; - -open(MAKEFILE, "> $makefile4"); - -print MAKEFILE <<'EOF'; - +&run_make_test(' A = a B = b C = c @@ -196,23 +135,14 @@ export F G H I J export D E $(SOME) all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J -EOF - -close(MAKEFILE); - -&run_make_with_options($makefile4,"",&get_logfile,0); -$answer = "A=a B=b C=c D=d E=e F=f G=g H=h I=i J=j\n"; -&compare_output($answer,&get_logfile(1)); - +', + '', "A=a B=b C=c D=d E=e F=f G=g H=h I=i J=j\n"); # TEST 8: Test unexporting multiple variables on the same line -$makefile5 = &get_tmpfile; - -open(MAKEFILE, "> $makefile5"); - -print MAKEFILE <<'EOF'; +@extraENV{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10); +&run_make_test(' A = a B = b C = c @@ -231,16 +161,26 @@ unexport F G H I J unexport D E $(SOME) all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J -EOF - -close(MAKEFILE); - -@extraENV{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10); - -&run_make_with_options($makefile5,"",&get_logfile,0); -$answer = "A= B= C= D= E= F= G= H= I= J=\n"; -&compare_output($answer,&get_logfile(1)); - +', + '', "A= B= C= D= E= F= G= H= I= J=\n"); + +# TEST 9: Check setting a variable named "export" + +&run_make_test(' +export = 123 +export export +export export = 456 +a: ; @echo "\$$(export)=$(export) / \$$export=$$export" +', + '', "\$(export)=456 / \$export=456\n"); + +# TEST 9: Check "export" as a target + +&run_make_test(' +a: export +export: ; @echo "$@" +', + '', "export\n"); # This tells the test driver that the perl test script executed properly. 1; diff --git a/src/kmk/tests/scripts/features/include b/src/kmk/tests/scripts/features/include index 196a987..ba8908c 100644 --- a/src/kmk/tests/scripts/features/include +++ b/src/kmk/tests/scripts/features/include @@ -90,8 +90,6 @@ all: ; @: foo: bar; @: ', '', ''); -1; - # Make sure that we don't die when the command fails but we dontcare. # (Savannah bug #13216). @@ -117,4 +115,65 @@ include -include sinclude', '', ''); + +# Test that the diagnostics is issued even if the target has been +# tried before with the dontcare flag (direct dependency case). +# +run_make_test(' +-include foo + +all: bar + +foo: baz +bar: baz +', +'', +"#MAKE#: *** No rule to make target `baz', needed by `bar'. Stop.\n", +512); + +# Test that the diagnostics is issued even if the target has been +# tried before with the dontcare flag (indirect dependency case). +# +run_make_test(' +-include foo + +all: bar + +foo: baz +bar: baz +baz: end +', +'', +"#MAKE#: *** No rule to make target `end', needed by `baz'. Stop.\n", +512); + +# Test that the diagnostics is issued even if the target has been +# tried before with the dontcare flag (include/-include case). +# +run_make_test(' +include bar +-include foo + +all: + +foo: baz +bar: baz +baz: end +', +'', +"#MAKEFILE#:2: bar: No such file or directory +#MAKE#: *** No rule to make target `end', needed by `baz'. Stop.\n", +512); + +if ($all_tests) { + # Test that include of a rebuild-able file doesn't show a warning + # Savannah bug #102 + run_make_test(q! +include foo +foo: ; @echo foo = bar > $@ +!, + '', "#MAKE#: `foo' is up to date.\n"); + rmfiles('foo'); +} + 1; diff --git a/src/kmk/tests/scripts/features/override b/src/kmk/tests/scripts/features/override index 23e4f2b..fff6c4e 100644 --- a/src/kmk/tests/scripts/features/override +++ b/src/kmk/tests/scripts/features/override @@ -1,34 +1,45 @@ -$description = "The following test creates a makefile to ..."; +# -*-perl-*- -$details = ""; - -open(MAKEFILE,"> $makefile"); - -# The Contents of the MAKEFILE ... - -print MAKEFILE "override define foo\n" - ."\@echo First comes the definition.\n" - ."\@echo Then comes the override.\n" - ."endef\n" - ."all: \n" - ."\t\$(foo)\n"; +$description = "Test the override directive on variable assignments."; -# END of Contents of MAKEFILE - -close(MAKEFILE); +$details = ""; -&run_make_with_options($makefile,"foo=Hello",&get_logfile); +# TEST 0: Basic override -# Create the answer to what should be produced by this Makefile -$answer = "First comes the definition.\n" - ."Then comes the override.\n"; +run_make_test(' +X = start +override recur = $(X) +override simple := $(X) +X = end +all: ; @echo "$(recur) $(simple)" +', + 'recur=I simple=J', "end start\n"); -&compare_output($answer,&get_logfile(1)); +# TEST 1: Override with append -1; +run_make_test(' +X += X1 +override X += X2 +override Y += Y1 +Y += Y2 +all: ; @echo "$(X) $(Y)" +', + '', "X1 X2 Y1\n"); +# TEST 2: Override with append to the command line +run_make_test(undef, 'X=C Y=C', "C X2 C Y1\n"); +# Test override of define/endef +run_make_test(' +override define foo +@echo First comes the definition. +@echo Then comes the override. +endef +all: ; $(foo) +', + 'foo=Hello', "First comes the definition.\nThen comes the override.\n"); +1; diff --git a/src/kmk/tests/scripts/features/parallelism b/src/kmk/tests/scripts/features/parallelism index 13827a4..d3d3489 100644 --- a/src/kmk/tests/scripts/features/parallelism +++ b/src/kmk/tests/scripts/features/parallelism @@ -43,7 +43,7 @@ all: 1 2; \@echo success "-j4", "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n"); -unlink('1.inc', '2.inc'); +rmfiles(qw(1.inc 2.inc)); # Test parallelism with included files--this time recurse first and make @@ -62,7 +62,7 @@ endif "-j4", "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n"); -unlink('1.inc', '2.inc'); +rmfiles(qw(1.inc 2.inc)); # Grant Taylor reports a problem where tokens can be lost (not written back # to the pipe when they should be): this happened when there is a $(shell ...) @@ -152,8 +152,83 @@ intermed: | phony ; touch $@ .PHONY: phony phony: ; : phony', '-rR -j', ': phony'); -unlink('target'); +rmfiles('target'); + +# TEST #10: Don't put --jobserver-fds into a re-exec'd MAKEFLAGS. +# We can't test this directly because there's no way a makefile can +# show the value of MAKEFLAGS we were re-exec'd with. We can intuit it +# by looking for "disabling jobserver mode" warnings; we should only +# get one from the original invocation and none from the re-exec. +# See Savannah bug #18124 + +run_make_test(q! +-include inc.mk +recur: +# @echo 'MAKEFLAGS = $(MAKEFLAGS)' + @rm -f inc.mk + @$(MAKE) -j2 -f #MAKEFILE# all +all: +# @echo 'MAKEFLAGS = $(MAKEFLAGS)' + @echo $@ +inc.mk: +# @echo 'MAKEFLAGS = $(MAKEFLAGS)' + @echo 'FOO = bar' > $@ +!, + '--no-print-directory -j2', "#MAKE#[1]: warning: -jN forced in submake: disabling jobserver mode.\nall\n"); + +rmfiles('inc.mk'); + +if ($all_tests) { + # Implicit files aren't properly recreated during parallel builds + # Savannah bug #26864 + + # The first run works fine + run_make_test(q! +%.bar: %.x foo.y ; cat $^ > $@ +%.x: ; touch $@ +foo.y: foo.y.in ; cp $< $@ +foo.y.in: ; touch $@ +!, + '-j2 main.bar', + "touch foo.y.in +touch main.x +cp foo.y.in foo.y +cat main.x foo.y > main.bar +rm main.x"); + + # Now we touch the .in file and make sure it still works + touch('foo.y.in'); + + run_make_test(undef, '-j2 main.bar', "cp foo.y.in foo.y +touch main.x +cat main.x foo.y > main.bar +rm main.x"); + + # Clean up + rmfiles(qw(foo.y foo.y.in main.bar)); +} + +if ($all_tests) { + # Jobserver FD handling is messed up in some way. + # Savannah bug #28189 + # It doesn't look like that bug anymore but this is the code it runs + run_make_test(q! +ifdef EXTRA +vpath %.dst / +xxx.dst: ; true +yyy.dst: ; true +endif + +M := $(MAKE) +xx: ; $M --no-print-directory -j2 -f $(MAKEFILE_LIST) xxx.dst yyy.dst EXTRA=1 +!, + '-j2', + '#MAKE#[1]: warning: -jN forced in submake: disabling jobserver mode. +true +true +'); +} # Make sure that all jobserver FDs are closed if we need to re-exec the # master copy. @@ -182,12 +257,12 @@ unlink('target'); # '-j2 INCL=false fdprint', # 'bar'); -# unlink('dependfile', 'output'); +# rmfiles(qw(dependfile output)); # # Do it again, this time where the include is done by the non-master make. # run_make_test(undef, '-j2 recurse INCL=false', 'bar'); -# unlink('dependfile', 'output'); +# rmfiles(qw(dependfile output)); 1; diff --git a/src/kmk/tests/scripts/features/patspecific_vars b/src/kmk/tests/scripts/features/patspecific_vars index 196f2f4..8f78ad0 100644 --- a/src/kmk/tests/scripts/features/patspecific_vars +++ b/src/kmk/tests/scripts/features/patspecific_vars @@ -120,5 +120,29 @@ run_make_test(undef, # reuse previous makefile 'normal: global: new $t pattern: good $t inherit: good $t; pattrn: global: new $t pattern: good $t inherit: good $t;'); +# TEST #8: override in pattern-specific variables + +run_make_test(' +a%: override FOO += f1 +a%: FOO += f2 +ab: ; @echo "$(FOO)" +', + '', "f1\n"); + +run_make_test(undef, 'FOO=C', "C f1\n"); + +# TEST #9: Test shortest stem selection in pattern-specific variables. + +run_make_test(' +%-mt.x: x := two +%.x: x := one + +all: foo.x foo-mt.x + +foo.x: ;@echo $x +foo-mt.x: ;@echo $x +', +'', +"one\ntwo"); 1; diff --git a/src/kmk/tests/scripts/features/patternrules b/src/kmk/tests/scripts/features/patternrules index 44355dc..e123954 100644 --- a/src/kmk/tests/scripts/features/patternrules +++ b/src/kmk/tests/scripts/features/patternrules @@ -15,11 +15,13 @@ $dir =~ s,.*/([^/]+)$,../$1,; # to match properly. # -run_make_test(' +run_make_test(q! .PHONY: all all: case.1 case.2 case.3 -a: void + +# We can't have this, due to "Implicit Rule Search Algorithm" step 5c +#xxx: void # 1 - existing file %.1: void @@ -41,9 +43,7 @@ a: void @exit 0 3.implicit-phony: -', -'', -''); +!, '', ''); # TEST #1: make sure files that are built via implicit rules are marked # as targets (Savannah bug #12202). @@ -149,5 +149,80 @@ echo foo.c foo.h >foo.o'); unlink('foo.in', 'foo.h', 'foo.c', 'foo.o'); +# TEST #5: make sure both prefix and suffix patterns work with multiple +# target patterns (Savannah bug #26593). +# +run_make_test(' +all: foo.s1 foo.s2 p1.foo p2.foo + +p1.% p2.%: %.orig + @echo $@ +%.s1 %.s2: %.orig + @echo $@ + +.PHONY: foo.orig +', + '', "foo.s1\np1.foo\n"); + +# TEST 6: Make sure that non-target files are still eligible to be created +# as part of implicit rule chaining. Savannah bug #17752. + +run_make_test(q! +BIN = xyz +COPY = $(BIN).cp +SRC = $(BIN).c +allbroken: $(COPY) $(BIN) ; @echo ok +$(SRC): ; @echo 'main(){}' > $@ +%.cp: % ; @cp $< $@ +% : %.c ; @cp $< $@ +clean: ; @rm -rf $(SRC) $(COPY) $(BIN) +!, + '', "ok\n"); + +unlink(qw(xyz xyz.cp xyz.c)); + +# TEST 7: Make sure that all prereqs of all "also_make" targets get created +# before any of the things that depend on any of them. Savannah bug #19108. + +run_make_test(q! +final: x ; @echo $@ +x: x.t1 x.t2 ; @echo $@ +x.t2: dep +dep: ; @echo $@ +%.t1 %.t2: ; @echo $*.t1 ; echo $*.t2 +!, + '', "dep\nx.t1\nx.t2\nx\nfinal\n"); + + +# TEST 8: Verify we can remove pattern rules. Savannah bug #18622. + +my @f = (qw(foo.w foo.ch)); +touch(@f); + +run_make_test(q! +CWEAVE := : + +# Disable builtin rules +%.tex : %.w +%.tex : %.w %.ch +!, + 'foo.tex', + "#MAKE#: *** No rule to make target `foo.tex'. Stop.", 512); + +unlink(@f); + +# TEST #9: Test shortest stem selection in pattern rules. + +run_make_test(' +%.x: ;@echo one +%-mt.x: ;@echo two + +all: foo.x foo-mt.x +', +'', +"one\ntwo"); + +1; + # This tells the test driver that the perl test script executed properly. 1; diff --git a/src/kmk/tests/scripts/features/recursion b/src/kmk/tests/scripts/features/recursion index bc50e0b..f9c0755 100644 --- a/src/kmk/tests/scripts/features/recursion +++ b/src/kmk/tests/scripts/features/recursion @@ -16,7 +16,7 @@ last: @echo MAKELEVEL = $('. (!$is_kmk ? 'MAKELEVEL' : 'KMK_LEVEL') .') @echo THE END ', - ('CFLAGS=-O -w' . ($parallel_jobs ? '-j 2' : '')), + ('CFLAGS=-O -w' . ($parallel_jobs ? ' -j 2' : '')), ($vos ? "#MAKE#: Entering directory `#PWD#' make 'CFLAGS=-O' -f #MAKEFILE# foo diff --git a/src/kmk/tests/scripts/features/se_explicit b/src/kmk/tests/scripts/features/se_explicit index d80b947..325d57c 100644 --- a/src/kmk/tests/scripts/features/se_explicit +++ b/src/kmk/tests/scripts/features/se_explicit @@ -26,9 +26,9 @@ run_make_test(undef, 'SE=1', "three\nfour\nbariz\nfoo\$bar : baraz bariz"); # TEST #1: automatic variables. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: -.DEFAULT: ; @echo $@ +.DEFAULT: ; @echo '$@' foo: bar baz @@ -41,7 +41,7 @@ foo: $$@.1 \ $$|.5 \ $$*.6 -', +!, '-j1', 'bar baz @@ -62,17 +62,16 @@ buz.5 # Test #2: target/pattern -specific variables. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: -.DEFAULT: ; @echo $@ +.DEFAULT: ; @echo '$@' foo.x: $$a $$b foo.x: a := bar %.x: b := baz - -', +!, '', 'bar baz @@ -81,39 +80,27 @@ baz # Test #3: order of prerequisites. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: -.DEFAULT: ; @echo $@ +.DEFAULT: ; @echo '$@' all: foo bar baz # Subtest #1 -# foo: foo.1; @: - foo: foo.2 - foo: foo.3 - # Subtest #2 -# bar: bar.2 - bar: bar.1; @: - bar: bar.3 - # Subtest #3 -# baz: baz.1 - baz: baz.2 - baz: ; @: - -', +!, '-j1', 'foo.1 foo.2 @@ -125,5 +112,47 @@ baz.1 baz.2 '); +# TEST #4: eval in a context where there is no reading_file +run_make_test(q! +.SECONDEXPANSION: +all : $$(eval $$(info test)) +!, + '', "test\n#MAKE#: Nothing to be done for `all'.\n"); + +# TEST #5: (NEGATIVE) catch eval in a prereq list trying to create new +# target/prereq relationships. + +run_make_test(q! +.SECONDEXPANSION: +proj1.exe : proj1.o $$(eval $$(test)) +define test +proj1.o : proj1.c +proj1.c: proj1.h +endef +!, + '', "#MAKE#: *** prerequisites cannot be defined in recipes. Stop.\n", 512); + + +# Automatic $$+ variable expansion issue. Savannah bug #25780 +run_make_test(q! +all : foo foo +.SECONDEXPANSION: +all : $$+ ; @echo '$+' +foo : ; +!, + '', "foo foo foo foo\n"); + + +# Automatic $$+ variable expansion issue. Savannah bug #25780 +run_make_test(q! +all : bar bar +bar : ; +q%x : ; +.SECONDEXPANSION: +a%l: q1x $$+ q2x ; @echo '$+' +!, + '', "q1x bar bar q2x bar bar\n"); + + # This tells the test driver that the perl test script executed properly. 1; diff --git a/src/kmk/tests/scripts/features/se_implicit b/src/kmk/tests/scripts/features/se_implicit index 8ab3c84..6dbe227 100644 --- a/src/kmk/tests/scripts/features/se_implicit +++ b/src/kmk/tests/scripts/features/se_implicit @@ -11,9 +11,9 @@ $dir =~ s,.*/([^/]+)$,../$1,; # Test #1: automatic variables. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: -.DEFAULT: ; @echo $@ +.DEFAULT: ; @echo '$@' foo.a: bar baz @@ -37,9 +37,9 @@ foo.%: 1.$$@ \ 4.biz \ 5.buz \ 6.a: - @echo $@ + @echo '$@' -', +!, '-j1', '1.foo.a 2.bar @@ -60,7 +60,7 @@ buz # Test #2: target/pattern -specific variables. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: foo.x: @@ -71,20 +71,16 @@ foo.x: x_a := bar %.x: x_b := baz -bar baz: ; @echo $@ - -', -'', -'bar -baz -'); +bar baz: ; @echo '$@' +!, + '', "bar\nbaz\n"); # Test #3: order of prerequisites. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: -.DEFAULT: ; @echo $@ +.DEFAULT: ; @echo '$@' all: foo bar baz @@ -97,7 +93,7 @@ foo: foo.2 foo: foo.3 -foo.1: ; @echo $@ +foo.1: ; @echo '$@' # Subtest #2 @@ -108,7 +104,7 @@ bar: bar.2 bar: bar.3 -bar.1: ; @echo $@ +bar.1: ; @echo '$@' # Subtest #3 @@ -118,9 +114,8 @@ baz: baz.1 baz: baz.2 %az: ; @: - -', -'-j1', +!, + '-j1', 'foo.1 foo.2 foo.3 @@ -134,20 +129,18 @@ baz.2 # Test #4: stem splitting logic. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: $(dir)/tmp/bar.o: -$(dir)/tmp/foo/bar.c: ; @echo $@ -$(dir)/tmp/bar/bar.c: ; @echo $@ -foo.h: ; @echo $@ +$(dir)/tmp/foo/bar.c: ; @echo '$@' +$(dir)/tmp/bar/bar.c: ; @echo '$@' +foo.h: ; @echo '$@' %.o: $$(addsuffix /%.c,foo bar) foo.h - @echo $@: {$<} $^ - -', -"dir=$dir", -"$dir/tmp/foo/bar.c + @echo '$@: {$<} $^' +!, + "dir=$dir", "$dir/tmp/foo/bar.c $dir/tmp/bar/bar.c foo.h $dir/tmp/bar.o: {$dir/tmp/foo/bar.c} $dir/tmp/foo/bar.c $dir/tmp/bar/bar.c foo.h @@ -156,18 +149,17 @@ $dir/tmp/bar.o: {$dir/tmp/foo/bar.c} $dir/tmp/foo/bar.c $dir/tmp/bar/bar.c foo.h # Test #5: stem splitting logic and order-only prerequisites. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: $(dir)/tmp/foo.o: $(dir)/tmp/foo.c -$(dir)/tmp/foo.c: ; @echo $@ -bar.h: ; @echo $@ +$(dir)/tmp/foo.c: ; @echo '$@' +bar.h: ; @echo '$@' %.o: %.c|bar.h - @echo $@: {$<} {$|} $^ + @echo '$@: {$<} {$|} $^' -', -"dir=$dir", -"$dir/tmp/foo.c +!, + "dir=$dir", "$dir/tmp/foo.c bar.h $dir/tmp/foo.o: {$dir/tmp/foo.c} {bar.h} $dir/tmp/foo.c "); @@ -175,58 +167,60 @@ $dir/tmp/foo.o: {$dir/tmp/foo.c} {bar.h} $dir/tmp/foo.c # Test #6: lack of implicit prerequisites. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: foo.o: foo.c -foo.c: ; @echo $@ +foo.c: ; @echo '$@' %.o: - @echo $@: {$<} $^ + @echo '$@: {$<} $^' +!, + '', "foo.c\nfoo.o: {foo.c} foo.c\n"); -', -'', -'foo.c -foo.o: {foo.c} foo.c -'); # Test #7: Test stem from the middle of the name. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: foobarbaz: foo%baz: % $$*.1 - @echo $* + @echo '$*' bar bar.1: - @echo $@ + @echo '$@' +!, + '', "bar\nbar.1\nbar\n"); -', -'', -'bar -bar.1 -bar -'); # Test #8: Make sure stem triple-expansion does not happen. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: foo$$bar: f%r: % $$*.1 - @echo \'$*\' + @echo '$*' oo$$ba oo$$ba.1: - @echo \'$@\' - -', -'', -'oo$ba + @echo '$@' +!, + '', 'oo$ba oo$ba.1 oo$ba '); +# Test #9: Check the value of $^ +run_make_test(q! +.SECONDEXPANSION: + +%.so: | $$(extra) ; @echo $^ + +foo.so: extra := foo.o +foo.so: +foo.o: +!, + '', "\n"); # This tells the test driver that the perl test script executed properly. 1; diff --git a/src/kmk/tests/scripts/features/se_statpat b/src/kmk/tests/scripts/features/se_statpat index 731b00b..828afa2 100644 --- a/src/kmk/tests/scripts/features/se_statpat +++ b/src/kmk/tests/scripts/features/se_statpat @@ -5,12 +5,12 @@ $details = ""; # Test #1: automatic variables. # -run_make_test(' +# bird: Had to add -j1 here earlier... +run_make_test(q! .SECONDEXPANSION: -.DEFAULT: ; @echo $@ +.DEFAULT: ; @echo '$@' foo.a foo.b: foo.%: bar.% baz.% - foo.a foo.b: foo.%: biz.% | buz.% foo.a foo.b: foo.%: $$@.1 \ @@ -19,10 +19,8 @@ foo.a foo.b: foo.%: $$@.1 \ $$(addsuffix .4,$$+) \ $$|.5 \ $$*.6 - -', -'-j1', -'bar.a +!, + '', 'bar.a baz.a biz.a buz.a @@ -41,61 +39,46 @@ a.6 # Test #2: target/pattern -specific variables. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: -.DEFAULT: ; @echo $@ +.DEFAULT: ; @echo '$@' foo.x foo.y: foo.%: $$(%_a) $$($$*_b) foo.x: x_a := bar %.x: x_b := baz - - -', -'', -'bar -baz -'); +!, + '', "bar\nbaz\n"); # Test #3: order of prerequisites. # -run_make_test(' +# bird: Had to add -j1 here earlier... +run_make_test(q! .SECONDEXPANSION: -.DEFAULT: ; @echo $@ +.DEFAULT: ; @echo '$@' all: foo.a bar.a baz.a # Subtest #1 -# foo.a foo.b: foo.%: foo.%.1; @: - foo.a foo.b: foo.%: foo.%.2 - foo.a foo.b: foo.%: foo.%.3 # Subtest #2 -# bar.a bar.b: bar.%: bar.%.2 - bar.a bar.b: bar.%: bar.%.1; @: - bar.a bar.b: bar.%: bar.%.3 # Subtest #3 -# baz.a baz.b: baz.%: baz.%.1 - baz.a baz.b: baz.%: baz.%.2 - baz.a baz.b: ; @: - -', -'-j1', -'foo.a.1 +!, + '', 'foo.a.1 foo.a.2 foo.a.3 bar.a.1 @@ -108,17 +91,15 @@ baz.a.2 # Test #4: Make sure stem triple-expansion does not happen. # -run_make_test(' +run_make_test(q! .SECONDEXPANSION: foo$$bar: f%r: % $$*.1 - @echo \'$*\' + @echo '$*' oo$$ba oo$$ba.1: - @echo \'$@\' - -', -'', -'oo$ba + @echo '$@' +!, + '', 'oo$ba oo$ba.1 oo$ba '); diff --git a/src/kmk/tests/scripts/features/targetvars b/src/kmk/tests/scripts/features/targetvars index fa365a2..ddd6c1f 100644 --- a/src/kmk/tests/scripts/features/targetvars +++ b/src/kmk/tests/scripts/features/targetvars @@ -6,9 +6,7 @@ Create a makefile containing various flavors of target-specific variable values, override and non-override, and using various variable expansion rules, semicolon interference, etc."; -open(MAKEFILE,"> $makefile"); - -print MAKEFILE <<'EOF'; +run_make_test(' SHELL = /bin/sh export FOO = foo export BAR = bar @@ -17,17 +15,17 @@ one two: ; @echo $(FOO) $(BAR) two: BAR = two three: ; BAR=1000 @echo $(FOO) $(BAR) -# Some things that shouldn't be target vars +# Some things that shouldn not be target vars funk : override funk : override adelic adelic override : ; echo $@ # Test per-target recursive variables four:FOO=x four:VAR$(FOO)=ok -four: ; @echo '$(FOO) $(VAR$(FOO)) $(VAR) $(VARx)' +four: ; @echo "$(FOO) $(VAR$(FOO)) $(VAR) $(VARx)" five:FOO=x five six : VAR$(FOO)=good -five six: ;@echo '$(FOO) $(VAR$(FOO)) $(VAR) $(VARx) $(VARfoo)' +five six: ;@echo "$(FOO) $(VAR$(FOO)) $(VAR) $(VARx) $(VARfoo)" # Test per-target variable inheritance seven: eight seven eight: ; @echo $@: $(FOO) $(BAR) @@ -41,8 +39,8 @@ nine-a: export BAZ = baz nine-a: ; @echo $$BAZ # Test = escaping EQ = = -ten: one\=two -ten: one \= two +ten: one$(EQ)two +ten: one $(EQ) two ten one$(EQ)two $(EQ):;@echo $@ .PHONY: one two three four five six seven eight nine ten $(EQ) one$(EQ)two # Test target-specific vars with pattern/suffix rules @@ -54,92 +52,58 @@ foo.q : RVAR += rvar %.r %.s %.t: ; @echo $(QVAR) $(RVAR) $(SVAR) $(TVAR) foo.r : RVAR += rvar foo.t : TVAR := $(QVAR) -EOF - -close(MAKEFILE); - -# TEST #1 - -&run_make_with_options($makefile, "-j1 one two three", &get_logfile); -$answer = "one bar\nfoo two\nBAR=1000\nfoo bar\n"; -&compare_output($answer,&get_logfile(1)); +', + "one two three", "one bar\nfoo two\nBAR=1000\nfoo bar\n"); # TEST #2 -&run_make_with_options($makefile, "-j1 one two FOO=1 BAR=2", &get_logfile); -$answer = "one 2\n1 2\n"; -&compare_output($answer,&get_logfile(1)); +run_make_test(undef, "one two FOO=1 BAR=2", "one 2\n1 2\n"); # TEST #3 -&run_make_with_options($makefile, "-j1 four", &get_logfile); -$answer = "x ok ok\n"; -&compare_output($answer,&get_logfile(1)); +run_make_test(undef, "four", "x ok ok\n"); # TEST #4 -&run_make_with_options($makefile, "-j1 seven", &get_logfile); -$answer = "eight: seven eight\nseven: seven seven\n"; -&compare_output($answer,&get_logfile(1)); +run_make_test(undef, "seven", "eight: seven eight\nseven: seven seven\n"); # TEST #5 -&run_make_with_options($makefile, "-j1 nine", &get_logfile); -$answer = "wallace bar wallace bar\n"; -&compare_output($answer,&get_logfile(1)); +run_make_test(undef, "nine", "wallace bar wallace bar\n"); # TEST #5-a -&run_make_with_options($makefile, "-j1 nine-a", &get_logfile); -$answer = "baz\n"; -&compare_output($answer,&get_logfile(1)); +run_make_test(undef, "nine-a", "baz\n"); # TEST #6 -&run_make_with_options($makefile, "-j1 ten", &get_logfile); -$answer = "one=two\none bar\n=\nfoo two\nten\n"; -&compare_output($answer,&get_logfile(1)); +run_make_test(undef, "ten", "one=two\none bar\n=\nfoo two\nten\n"); # TEST #6 -&run_make_with_options($makefile, "-j1 foo.q bar.q", &get_logfile); -$answer = "qvar = rvar\nqvar =\n"; -&compare_output($answer,&get_logfile(1)); +run_make_test(undef, "foo.q bar.q", "qvar = rvar\nqvar =\n"); # TEST #7 -&run_make_with_options($makefile, "-j1 foo.t bar.s", &get_logfile); -$answer = "qvar = qvar\nqvar =\n"; -&compare_output($answer,&get_logfile(1)); +run_make_test(undef, "foo.t bar.s", "qvar = qvar\nqvar =\n"); # TEST #8 # For PR/1378: Target-specific vars don't inherit correctly -$makefile2 = &get_tmpfile; - -open(MAKEFILE,"> $makefile2"); -print MAKEFILE <<'EOF'; +run_make_test(' foo: FOO = foo bar: BAR = bar foo: bar bar: baz baz: ; @echo $(FOO) $(BAR) -EOF -close(MAKEFILE); - -&run_make_with_options("$makefile2", "", &get_logfile); -$answer = "foo bar\n"; -&compare_output($answer, &get_logfile(1)); +', "", "foo bar\n"); # TEST #9 # For PR/1380: Using += assignment in target-specific variables sometimes fails # Also PR/1831 -$makefile3 = &get_tmpfile; - -open(MAKEFILE,"> $makefile3"); -print MAKEFILE <<'EOF'; +run_make_test(' .PHONY: all one all: FOO += baz all: one; @echo $(FOO) @@ -149,43 +113,27 @@ FOO = bar one: FOO += biz one: FOO += boz one: ; @echo $(FOO) -EOF -close(MAKEFILE); - -&run_make_with_options("$makefile3", "", &get_logfile); -$answer = "bar baz biz boz\nbar baz\n"; -&compare_output($answer, &get_logfile(1)); +', + '', "bar baz biz boz\nbar baz\n"); # Test #10 -&run_make_with_options("$makefile3", "one", &get_logfile); -$answer = "bar biz boz\n"; -&compare_output($answer, &get_logfile(1)); +run_make_test(undef, 'one', "bar biz boz\n"); # Test #11 # PR/1709: Test semicolons in target-specific variable values -$makefile4 = &get_tmpfile; - -open(MAKEFILE, "> $makefile4"); -print MAKEFILE <<'EOF'; +run_make_test(' foo : FOO = ; ok -foo : ; @echo '$(FOO)' -EOF -close(MAKEFILE); - -&run_make_with_options("$makefile4", "", &get_logfile); -$answer = "; ok\n"; -&compare_output($answer, &get_logfile(1)); +foo : ; @echo "$(FOO)" +', + '', "; ok\n"); # Test #12 # PR/2020: More hassles with += target-specific vars. I _really_ think # I nailed it this time :-/. -$makefile5 = &get_tmpfile; - -open(MAKEFILE, "> $makefile5"); -print MAKEFILE <<'EOF'; +run_make_test(' .PHONY: a BLAH := foo @@ -195,20 +143,13 @@ a: ; @$(COMMAND) a: BLAH := bar a: COMMAND += snafu $(BLAH) -EOF -close(MAKEFILE); - -&run_make_with_options("$makefile5", "", &get_logfile); -$answer = "bar snafu bar\n"; -&compare_output($answer, &get_logfile(1)); +', + '', "bar snafu bar\n"); # Test #13 # Test double-colon rules with target-specific variable values -$makefile6 = &get_tmpfile; - -open(MAKEFILE, "> $makefile6"); -print MAKEFILE <<'EOF'; +run_make_test(' W = bad X = bad foo: W = ok @@ -224,48 +165,30 @@ Z = nopat ifdef PATTERN fo% : Z = pat endif - -EOF -close(MAKEFILE); - -&run_make_with_options("$makefile6", "foo", &get_logfile); -$answer = "ok ok foo nopat\nok ok foo nopat\n"; -&compare_output($answer, &get_logfile(1)); +', + 'foo', "ok ok foo nopat\nok ok foo nopat\n"); # Test #14 # Test double-colon rules with target-specific variable values and # inheritance -&run_make_with_options("$makefile6", "bar", &get_logfile); -$answer = "ok ok bar nopat\nok ok bar nopat\n"; -&compare_output($answer, &get_logfile(1)); +run_make_test(undef, 'bar', "ok ok bar nopat\nok ok bar nopat\n"); # Test #15 # Test double-colon rules with pattern-specific variable values -&run_make_with_options("$makefile6", "foo PATTERN=yes", &get_logfile); -$answer = "ok ok foo pat\nok ok foo pat\n"; -&compare_output($answer, &get_logfile(1)); - +run_make_test(undef, 'foo PATTERN=yes', "ok ok foo pat\nok ok foo pat\n"); # Test #16 # Test target-specific variables with very long command line # (> make default buffer length) -$makefile7 = &get_tmpfile; - -open(MAKEFILE, "> $makefile7"); -print MAKEFILE <<'EOF'; +run_make_test(' base_metals_fmd_reports.sun5 base_metals_fmd_reports CreateRealPositions CreateMarginFunds deals_changed_since : BUILD_OBJ=$(shell if [ -f "build_information.generate" ]; then echo "$(OBJ_DIR)/build_information.o"; else echo "no build information"; fi ) deals_changed_since: ; @echo $(BUILD_OBJ) - -EOF -close(MAKEFILE); - -&run_make_with_options("$makefile7", '', &get_logfile); -$answer = "no build information\n"; -&compare_output($answer, &get_logfile(1)); +', + '', "no build information\n"); # TEST #17 @@ -286,8 +209,7 @@ foo.x: FOOVAR = bar rules.mk : MYVAR = foo .INTERMEDIATE: foo.x rules.mk ', - '-I t1', - 'MYVAR= FOOVAR=bar ALLVAR=xxx'); + '-I t1', 'MYVAR= FOOVAR=bar ALLVAR=xxx'); rmfiles('t1/rules.mk'); rmdir('t1'); @@ -297,11 +219,45 @@ rmdir('t1'); # Test appending to a simple variable containing a "$": avoid a # double-expansion. See Savannah bug #15913. -run_make_test(" -VAR := \$\$FOO +run_make_test(' +VAR := $$FOO foo: VAR += BAR -foo: ; \@echo '\$(VAR)'", - '', - '$FOO BAR'); +foo: ; @echo '."'".'$(VAR)'."'".' +', + '', '$FOO BAR'); + +# TEST #19: Override with append variables + +run_make_test(' +a: override FOO += f1 +a: FOO += f2 +a: ; @echo "$(FOO)" +', + '', "f1\n"); + +run_make_test(undef, 'FOO=C', "C f1\n"); + +# TEST #20: Check for continuation after semicolons + +run_make_test(q! +a: A = 'hello; \ +world' +a: ; @echo $(A) +!, + '', "hello; world\n"); + +# TEST #19: Test define/endef variables as target-specific vars + +# run_make_test(' +# define b +# @echo global +# endef +# a: define b +# @echo local +# endef + +# a: ; $(b) +# ', +# '', "local\n"); 1; diff --git a/src/kmk/tests/scripts/features/vpath b/src/kmk/tests/scripts/features/vpath index 6634c90..ced58f8 100644 --- a/src/kmk/tests/scripts/features/vpath +++ b/src/kmk/tests/scripts/features/vpath @@ -1,3 +1,5 @@ +# -*-perl-*- + $description = "The following test creates a makefile to test the \n" ."vpath directive which allows you to specify a search \n" ."path for a particular class of filenames, those that\n" @@ -60,4 +62,21 @@ if (&compare_output($answer,&get_logfile(1))) unlink @files_to_touch; } +# TEST 2: after vpath lookup ensure we don't get incorrect circular dependency +# warnings due to change of struct file ptr. Savannah bug #13529. + +mkdir('vpath-d', 0777); + +run_make_test(q! +vpath %.te vpath-d/ +.SECONDARY: +default: vpath-d/a vpath-d/b +vpath-d/a: fail.te +vpath-d/b : fail.te +vpath-d/fail.te: +!, + '', "#MAKE#: Nothing to be done for `default'.\n"); + +rmdir('vpath-d'); + 1; diff --git a/src/kmk/tests/scripts/features/vpath3 b/src/kmk/tests/scripts/features/vpath3 new file mode 100644 index 0000000..978c5ee --- /dev/null +++ b/src/kmk/tests/scripts/features/vpath3 @@ -0,0 +1,50 @@ +# -*-perl-*- + +$description = "Test the interaction of the -lfoo feature and vpath"; +$details = ""; + +open(MAKEFILE,"> $makefile"); + +# The Contents of the MAKEFILE ... + +print MAKEFILE "vpath %.a a1\n"; +print MAKEFILE "vpath %.so b1\n"; +print MAKEFILE "vpath % a2 b2\n"; +print MAKEFILE "vpath % b3\n"; +print MAKEFILE "all: -l1 -l2 -l3; \@echo \$^\n"; + +# END of Contents of MAKEFILE + +close(MAKEFILE); + +mkdir("a1", 0777); +mkdir("b1", 0777); +mkdir("a2", 0777); +mkdir("b2", 0777); +mkdir("b3", 0777); + +@files_to_touch = ("a1${pathsep}lib1.a", + "b1${pathsep}lib1.so", + "a2${pathsep}lib2.a", + "b2${pathsep}lib2.so", + "lib3.a", + "b3${pathsep}lib3.so"); + +&touch(@files_to_touch); + +&run_make_with_options($makefile,"",&get_logfile); + +# Create the answer to what should be produced by this Makefile +$answer = "a1${pathsep}lib1.a a2${pathsep}lib2.a lib3.a\n"; + +if (&compare_output($answer,&get_logfile(1))) +{ + unlink @files_to_touch; + rmdir("a1"); + rmdir("b1"); + rmdir("a2"); + rmdir("b2"); + rmdir("b3"); +} + +1; diff --git a/src/kmk/tests/scripts/functions/shell b/src/kmk/tests/scripts/functions/shell index ecea4cf..723cd0e 100644 --- a/src/kmk/tests/scripts/functions/shell +++ b/src/kmk/tests/scripts/functions/shell @@ -11,6 +11,15 @@ all: ; @echo $(shell echo hi) ','','hi'); +# Test unescaped comment characters in shells. Savannah bug #20513 +if ($all_tests) { + run_make_test(q! +FOO := $(shell echo '#') +foo: ; echo '$(FOO)' +!, + '', "#\n"); +} + # Test shells inside exported environment variables. # This is the test that fails if we try to put make exported variables into # the environment for a $(shell ...) call. diff --git a/src/kmk/tests/scripts/functions/wildcard b/src/kmk/tests/scripts/functions/wildcard index d61384e..2841f5d 100644 --- a/src/kmk/tests/scripts/functions/wildcard +++ b/src/kmk/tests/scripts/functions/wildcard @@ -81,14 +81,11 @@ if ((-f "example.1")||(-f "example.two")||(-f "example.3")||(-f "example.for")) &compare_output($answer,&get_logfile(1)); +# TEST #4: Verify that failed wildcards don't return the pattern -1; - - - - - - - - +run_make_test(q! +all: ; @echo $(wildcard xz--y*.7) +!, + '', "\n"); +1; diff --git a/src/kmk/tests/scripts/misc/general4 b/src/kmk/tests/scripts/misc/general4 index b86b16b..dd9475c 100644 --- a/src/kmk/tests/scripts/misc/general4 +++ b/src/kmk/tests/scripts/misc/general4 @@ -31,20 +31,6 @@ cc foo.o -o foo' : unlink('foo.c'); -# Test other implicit rule searching - -&touch('bar'); -run_make_test(' -test.foo: -%.foo : baz ; @echo done $< -%.foo : bar ; @echo done $< -fox: baz -', - '', - 'done bar'); -unlink('bar'); - - # Test implicit rules with '$' in the name (see se_implicit) run_make_test(q! @@ -83,4 +69,17 @@ dir/subdir/%.$$a: dir/subdir/%.$$b ; @echo 'cp $< $@' !, '', "mkdir -p dir/subdir\ntouch dir/subdir/file.\$b\ncp dir/subdir/file.\$b dir/subdir/file.\$a\n"); +# Test odd whitespace at the beginning of a line + +run_make_test(" +all: + \f + + \\ + \f \\ + \013 \\ +all: ; \@echo hi +", + '', "hi\n"); + 1; diff --git a/src/kmk/tests/scripts/options/dash-B b/src/kmk/tests/scripts/options/dash-B index 864a01f..e36842e 100644 --- a/src/kmk/tests/scripts/options/dash-B +++ b/src/kmk/tests/scripts/options/dash-B @@ -70,4 +70,16 @@ all'); rmfiles('foo.x', 'blah.x'); +# Test that $? is set properly with -B; all prerequisites will be newer! + +utouch(-10, 'x.b'); +touch('x.a'); + +run_make_test(q! +x.a: x.b ; @echo $? +!, + '-B', "x.b\n"); + +unlink(qw(x.a x.b)); + 1; diff --git a/src/kmk/tests/scripts/options/eval b/src/kmk/tests/scripts/options/eval new file mode 100644 index 0000000..06a035c --- /dev/null +++ b/src/kmk/tests/scripts/options/eval @@ -0,0 +1,19 @@ +# -*-perl-*- + +$description = "Test the --eval option."; + +$details = "Verify that --eval options take effect, +and are passed to sub-makes."; + +# Verify that --eval is evaluated first +run_make_test(q! +BAR = bar +all: ; @echo all +recurse: ; @$(MAKE) -f #MAKEFILE# && echo recurse!, + '--eval=\$\(info\ eval\) FOO=\$\(BAR\)', "eval\nall"); + +# Make sure that --eval is handled correctly during recursion +run_make_test(undef, '--no-print-directory --eval=\$\(info\ eval\) recurse', + "eval\neval\nall\nrecurse"); + +1; diff --git a/src/kmk/tests/scripts/targets/ONESHELL b/src/kmk/tests/scripts/targets/ONESHELL new file mode 100644 index 0000000..997423f --- /dev/null +++ b/src/kmk/tests/scripts/targets/ONESHELL @@ -0,0 +1,69 @@ +# -*-perl-*- + +$description = "Test the behaviour of the .ONESHELL target."; + +$details = ""; + + +# Simple + +run_make_test(q! +.ONESHELL: +all: + a=$$$$ + [ 0"$$a" -eq "$$$$" ] || echo fail +!, + '', 'a=$$ +[ 0"$a" -eq "$$" ] || echo fail +'); + +# Again, but this time with inner prefix chars + +run_make_test(q! +.ONESHELL: +all: + a=$$$$ + @-+ [ 0"$$a" -eq "$$$$" ] || echo fail +!, + '', 'a=$$ +[ 0"$a" -eq "$$" ] || echo fail +'); + +# This time with outer prefix chars + +run_make_test(q! +.ONESHELL: +all: + @a=$$$$ + [ 0"$$a" -eq "$$$$" ] || echo fail +!, + '', ''); + + +# This time with outer and inner prefix chars + +run_make_test(q! +.ONESHELL: +all: + @a=$$$$ + -@ +[ 0"$$a" -eq "$$$$" ] || echo fail +!, + '', ''); + + +# Now try using a different interpreter + +run_make_test(q! +.RECIPEPREFIX = > +.ONESHELL: +SHELL = #PERL# +.SHELLFLAGS = -e +all: +> @$$a=5 +> +7; +> @y=qw(a b c); +>print "a = $$a, y = (@y)\n"; +!, + '', "a = 12, y = (a b c)\n"); + +1; diff --git a/src/kmk/tests/scripts/targets/POSIX b/src/kmk/tests/scripts/targets/POSIX new file mode 100644 index 0000000..9c30e18 --- /dev/null +++ b/src/kmk/tests/scripts/targets/POSIX @@ -0,0 +1,33 @@ +# -*-perl-*- + +$description = "Test the behaviour of the .PHONY target."; + +$details = ""; + + +# Ensure turning on .POSIX enables the -e flag for the shell +# We can't assume the exit value of "false" because on different systems it's +# different. + +my $script = 'false; true'; +my $flags = '-ec'; +my $out = `/bin/sh $flags '$script' 2>&1`; +my $err = $? >> 8; +run_make_test(qq! +.POSIX: +all: ; \@$script +!, + '', "#MAKE#: *** [all] Error $err\n", 512); + +# User settings must override .POSIX +$flags = '-xc'; +$out = `/bin/sh $flags '$script' 2>&1`; +run_make_test(qq! +.SHELLFLAGS = $flags +.POSIX: +all: ; \@$script +!, + '', $out); + +# This tells the test driver that the perl test script executed properly. +1; diff --git a/src/kmk/tests/scripts/variables/DEFAULT_GOAL b/src/kmk/tests/scripts/variables/DEFAULT_GOAL index 897bd4a..1c06506 100644 --- a/src/kmk/tests/scripts/variables/DEFAULT_GOAL +++ b/src/kmk/tests/scripts/variables/DEFAULT_GOAL @@ -73,6 +73,15 @@ $(call make-rule) '', 'foo'); +# TEST #5: .DEFAULT_GOAL containing just whitespace (Savannah bug #25697) + +run_make_test(' +N = +.DEFAULT_GOAL = $N $N # Just whitespace + +foo: ; @echo "boo" +', + '', "#MAKE#: *** No targets. Stop.\n", 512); # This tells the test driver that the perl test script executed properly. 1; diff --git a/src/kmk/tests/scripts/variables/LIBPATTERNS b/src/kmk/tests/scripts/variables/LIBPATTERNS new file mode 100644 index 0000000..826f2fa --- /dev/null +++ b/src/kmk/tests/scripts/variables/LIBPATTERNS @@ -0,0 +1,38 @@ +# -*-perl-*- + +$description = "Test .LIBPATTERNS special variable."; + +$details = ""; + +# TEST 0: basics + +touch('mtest_foo.a'); + +run_make_test(' +.LIBPATTERNS = mtest_%.a +all: -lfoo ; @echo "build $@ from $<" +', + '', "build all from mtest_foo.a\n"); + +# TEST 1: Handle elements that are not patterns. + +run_make_test(' +.LIBPATTERNS = mtest_foo.a mtest_%.a +all: -lfoo ; @echo "build $@ from $<" +', + '', "#MAKE#: .LIBPATTERNS element `mtest_foo.a' is not a pattern +build all from mtest_foo.a\n"); + +# TEST 2: target-specific override + +# Uncomment this when we add support, see Savannah bug #25703 +# run_make_test(' +# .LIBPATTERNS = mbad_%.a +# all: .LIBPATTERNS += mtest_%.a +# all: -lfoo ; @echo "build $@ from $<" +# ', +# '', "build all from mtest_foo.a\n"); + +unlink('mtest_foo.a'); + +1; diff --git a/src/kmk/tests/scripts/variables/MAKE b/src/kmk/tests/scripts/variables/MAKE index 079c57e..d1081da 100644 --- a/src/kmk/tests/scripts/variables/MAKE +++ b/src/kmk/tests/scripts/variables/MAKE @@ -1,35 +1,24 @@ # -*-perl-*- -$description = "The following test creates a makefile to test MAKE \n" - ."(very generic)"; +$description = "Test proper behavior of the MAKE variable"; $details = "DETAILS"; -open(MAKEFILE,"> $makefile"); - -# The Contents of the MAKEFILE ... - -print MAKEFILE "TMP := \$(MAKE)\n"; -print MAKEFILE "MAKE := \$(subst X=\$(X),,\$(MAKE))\n\n"; -print MAKEFILE "all:\n"; -print MAKEFILE "\t\@echo \$(TMP)\n"; -print MAKEFILE "\t\$(MAKE) -f $makefile foo\n\n"; -print MAKEFILE "foo:\n"; -print MAKEFILE "\t\@echo \$(MAKE)\n"; - -# END of Contents of MAKEFILE - -close(MAKEFILE); - -# Create the answer to what should be produced by this Makefile -$answer = "$mkpath\n$mkpath -f $makefile foo\n" - . "${make_name}[1]: Entering directory `$pwd'\n" - . "$mkpath\n${make_name}[1]: Leaving directory `$pwd'\n"; - -&run_make_with_options($makefile,"",&get_logfile,0); - -&rmfiles("foo"); -# COMPARE RESULTS -&compare_output($answer,&get_logfile(1)); +run_make_test(q! +TMP := $(MAKE) +MAKE := $(subst X=$(X),,$(MAKE)) +all: + @echo $(TMP) + $(MAKE) -f #MAKEFILE# foo + +foo: + @echo $(MAKE) +!, + '', + "#MAKEPATH#\n#MAKEPATH# -f #MAKEFILE# foo\n" + . "#MAKE#[1]: Entering directory `#PWD#'\n" + . "#MAKEPATH#\n#MAKE#[1]: Leaving directory `#PWD#'\n"); + +rmfiles("foo"); 1; diff --git a/src/kmk/tests/scripts/variables/MAKEFILES b/src/kmk/tests/scripts/variables/MAKEFILES index 3be284b..b23da8e 100644 --- a/src/kmk/tests/scripts/variables/MAKEFILES +++ b/src/kmk/tests/scripts/variables/MAKEFILES @@ -31,4 +31,23 @@ close(MAKEFILE); $answer = "DEFAULT RULE: M2=m2 M3=m3\n"; &compare_output($answer,&get_logfile(1)); +# TEST 2: Verify that included makefiles don't set the default goal. +# See Savannah bug #13401. + +create_file('xx-inc.mk', ' +include_goal: ; @echo $@ +include xx-ind.mk +'); + +create_file('xx-ind.mk', ' +indirect_goal: ; @echo $@ +'); + +run_make_test(q! +top: ; @echo $@ +!, + 'MAKEFILES=xx-inc.mk', "top\n"); + +unlink(qw(xx-inc.mk xx-ind.mk)); + 1; diff --git a/src/kmk/tests/scripts/variables/MAKEFLAGS b/src/kmk/tests/scripts/variables/MAKEFLAGS new file mode 100644 index 0000000..0b567e8 --- /dev/null +++ b/src/kmk/tests/scripts/variables/MAKEFLAGS @@ -0,0 +1,43 @@ +# -*-perl-*- + +$description = "Test proper behavior of MAKEFLAGS"; + +$details = "DETAILS"; + +# Normal flags aren't prefixed with "-" +run_make_test(q! +all: ; @echo $(MAKEFLAGS) +!, + '-e -r -R', 'Rre'); + +# Long arguments mean everything is prefixed with "-" +run_make_test(q! +all: ; @echo $(MAKEFLAGS) +!, + '--no-print-directory -e -r -R', '--no-print-directory -Rre'); + + +if ($all_tests) { + # Recursive invocations of make should accumulate MAKEFLAGS values. + # Savannah bug #2216 + run_make_test(q! +MSG = Fails +all: + @echo '$@: MAKEFLAGS=$(MAKEFLAGS)' + @MSG=Works $(MAKE) -e -f #MAKEFILE# jump +jump: + @echo '$@: MAKEFLAGS=$(MAKEFLAGS)' + @$(MAKE) -f #MAKEFILE# print +print: + @echo '$@: MAKEFLAGS=$(MAKEFLAGS)' + @echo $(MSG) +.PHONY: all jump print +!, + '--no-print-directory', + 'all: MAKEFLAGS= --no-print-directory +jump: MAKEFLAGS= --no-print-directory -e +print: MAKEFLAGS= --no-print-directory -e +Works'); +} + +1; diff --git a/src/kmk/tests/scripts/variables/SHELL b/src/kmk/tests/scripts/variables/SHELL index 005115a..ca8e084 100644 --- a/src/kmk/tests/scripts/variables/SHELL +++ b/src/kmk/tests/scripts/variables/SHELL @@ -49,9 +49,39 @@ all:;@echo "$(SHELL) $$SHELL" $extraENV{SHELL} = $mshell; -# bird: This was wrong, see Savannah bug #24655. Fixed in kBuild. -run_make_test("all: export SHELL := /./$mshell\n".' -all:;@echo "$(SHELL) $$SHELL" -', '', "/./$mshell /./$mshell"); +# bird: This was wrong at some point, see Savannah bug #24655. Was first fixed in kBuild. +run_make_test(" +SHELL := /././$mshell +one: two +two: export SHELL := /./$mshell\n".' +one two:;@echo "$@: $(SHELL) $$SHELL" +', '', "two: /./$mshell /./$mshell\none: /././$mshell $mshell\n"); + +# Test .SHELLFLAGS + +# We don't know the output here: on Solaris for example, every line printed +# by the shell in -x mode has a trailing space (!!) +my $script = 'true; true'; +my $flags = '-xc'; +my $out = `/bin/sh $flags '$script' 2>&1`; + +run_make_test(qq! +.SHELLFLAGS = $flags +all: ; \@$script +!, + '', $out); + +# We can't just use "false" because on different systems it provides a +# different exit code--once again Solaris: false exits with 255 not 1 +$script = 'true; false; true'; +$flags = '-xec'; +$out = `/bin/sh $flags '$script' 2>&1`; +my $err = $? >> 8; + +run_make_test(qq! +.SHELLFLAGS = $flags +all: ; \@$script +!, + '', "$out#MAKE#: *** [all] Error $err\n", 512); 1; diff --git a/src/kmk/tests/scripts/variables/automatic b/src/kmk/tests/scripts/variables/automatic index 62bbcc1..2304fa0 100644 --- a/src/kmk/tests/scripts/variables/automatic +++ b/src/kmk/tests/scripts/variables/automatic @@ -107,4 +107,16 @@ bar: ;', unlink('foo'); +# TEST #4: ensure prereq ordering is correct when the commmand target has none +# See Savannah bug #21198 + +run_make_test(' +all : A B +all : ; @echo $@ -- $^ -- $< +all : C D +all : E F +A B C D E F G H : ; @: +', + '', "all -- A B C D E F -- A\n"); + 1; diff --git a/src/kmk/tests/scripts/variables/define b/src/kmk/tests/scripts/variables/define new file mode 100644 index 0000000..f91519e --- /dev/null +++ b/src/kmk/tests/scripts/variables/define @@ -0,0 +1,234 @@ +# -*-perl-*- + +$description = "Test define/endef variable assignments."; + +$details = ""; + +# TEST 0: old-style basic define/endef + +run_make_test(' +define multi +@echo hi +echo there +endef + +all: ; $(multi) +', + '', "hi\necho there\nthere\n"); + +# TEST 1: Various new-style define/endef + +run_make_test(' +FOO = foo + +define multi = +echo hi +@echo $(FOO) +endef # this is the end + +define simple := +@echo $(FOO) +endef + +append = @echo a + +define append += + +@echo b +endef + +define cond ?= # this is a conditional +@echo first +endef + +define cond ?= +@echo second +endef + +FOO = there + +all: ; $(multi) + $(simple) + $(append) + $(cond) +', + '', "echo hi\nhi\nthere\nfoo\na\nb\nfirst\n"); + +# TEST 2: define in true section of conditional (containing conditional) + +run_make_test(' +FOO = foo +NAME = def +def = +ifdef BOGUS + define $(subst e,e,$(NAME)) = + ifeq (1,1) + FOO = bar + endif + endef +endif + +$(eval $(def)) +all: ; @echo $(FOO) +', + 'BOGUS=1', "bar\n"); + +# TEST 3: define in false section of conditional (containing conditional) + +run_make_test(undef, '', "foo\n"); + +# TEST 4: nested define (supported?) + +run_make_test(' +define outer + define inner + A = B + endef +endef + +$(eval $(outer)) + +outer: ; @echo $(inner) +', + '', "A = B\n"); + +# TEST 5: NEGATIVE: Missing variable name + +run_make_test(' +NAME = +define $(NAME) = +ouch +endef +all: ; @echo ouch +', + '', "#MAKEFILE#:3: *** empty variable name. Stop.\n", 512); + +# TEST 6: NEGATIVE: extra text after define + +run_make_test(' +NAME = +define NAME = $(NAME) +ouch +endef +all: ; @echo ok +', + '', "#MAKEFILE#:3: extraneous text after `define' directive\nok\n"); + +# TEST 7: NEGATIVE: extra text after endef + +run_make_test(' +NAME = +define NAME = +ouch +endef $(NAME) +all: ; @echo ok +', + '', "#MAKEFILE#:5: extraneous text after `endef' directive\nok\n"); + +# TEST 8: NEGATIVE: missing endef + +run_make_test(' +NAME = +all: ; @echo ok +define NAME = +ouch +endef$(NAME) +', + '', "#MAKEFILE#:4: *** missing `endef', unterminated `define'. Stop.\n", 512); + +# ------------------------- +# Make sure that prefix characters apply properly to define/endef values. +# +# There's a bit of oddness here if you try to use a variable to hold the +# prefix character for a define. Even though something like this: +# +# define foo +# echo bar +# endef +# +# all: ; $(V)$(foo) +# +# (where V=@) can be seen by the user to be obviously different than this: +# +# define foo +# $(V)echo bar +# endef +# +# all: ; $(foo) +# +# and the user thinks it should behave the same as when the "@" is literal +# instead of in a variable, that can't happen because by the time make +# expands the variables for the command line and sees it begins with a "@" it +# can't know anymore whether the prefix character came before the variable +# reference or was included in the first line of the variable reference. + +# TEST #5 +# ------- + +run_make_test(' +define FOO +$(V1)echo hello +$(V2)echo world +endef +all: ; @$(FOO) +', '', 'hello +world'); + +# TEST #6 +# ------- + +run_make_test(undef, 'V1=@ V2=@', 'hello +world'); + +# TEST #7 +# ------- + +run_make_test(' +define FOO +$(V1)echo hello +$(V2)echo world +endef +all: ; $(FOO) +', 'V1=@', 'hello +echo world +world'); + +# TEST #8 +# ------- + +run_make_test(undef, 'V2=@', 'echo hello +hello +world'); + +# TEST #9 +# ------- + +run_make_test(undef, 'V1=@ V2=@', 'hello +world'); + +# TEST #10 +# ------- +# Test the basics; a "@" internally to the variable applies to only one line. +# A "@" before the variable applies to the entire variable. + +run_make_test(' +define FOO +@echo hello +echo world +endef +define BAR +echo hello +echo world +endef + +all: foo bar +foo: ; $(FOO) +bar: ; @$(BAR) +', '', 'hello +echo world +world +hello +world +'); + +1; diff --git a/src/kmk/tests/scripts/variables/flavors b/src/kmk/tests/scripts/variables/flavors index 4535898..92feed6 100644 --- a/src/kmk/tests/scripts/variables/flavors +++ b/src/kmk/tests/scripts/variables/flavors @@ -4,180 +4,73 @@ $description = "Test various flavors of make variable setting."; $details = ""; -open(MAKEFILE, "> $makefile"); +# TEST 0: Recursive -# The Contents of the MAKEFILE ... - -print MAKEFILE <<'EOF'; +run_make_test(' +ugh = Goodbye foo = $(bar) bar = ${ugh} ugh = Hello +all: ; @echo $(foo) +', + '', "Hello\n"); -all: multi ; @echo $(foo) - -multi: ; $(multi) - -x := foo -y := $(x) bar -x := later - -nullstring := -space := $(nullstring) $(nullstring) - -next: ; @echo $x$(space)$y - -define multi -@echo hi -echo there -endef - -ifdef BOGUS -define -@echo error -endef -endif - -define outer - define inner - A = B - endef -endef - -$(eval $(outer)) - -outer: ; @echo $(inner) - -EOF - -# END of Contents of MAKEFILE - -close(MAKEFILE); - -# TEST #1 -# ------- - -&run_make_with_options($makefile, "", &get_logfile); -$answer = "hi\necho there\nthere\nHello\n"; -&compare_output($answer, &get_logfile(1)); - -# TEST #2 -# ------- - -&run_make_with_options($makefile, "next", &get_logfile); -$answer = "later foo bar\n"; -&compare_output($answer, &get_logfile(1)); - -# TEST #3 -# ------- - -&run_make_with_options($makefile, "BOGUS=true", &get_logfile, 512); -$answer = "$makefile:24: *** empty variable name. Stop.\n"; -&compare_output($answer, &get_logfile(1)); - -# TEST #4 -# ------- - -&run_make_with_options($makefile, "outer", &get_logfile); -$answer = "A = B\n"; -&compare_output($answer, &get_logfile(1)); - -# Clean up from "old style" testing. If all the above tests are converted to -# run_make_test() syntax than this line can be removed. -$makefile = undef; - -# ------------------------- -# Make sure that prefix characters apply properly to define/endef values. -# -# There's a bit of oddness here if you try to use a variable to hold the -# prefix character for a define. Even though something like this: -# -# define foo -# echo bar -# endef -# -# all: ; $(V)$(foo) -# -# (where V=@) can be seen by the user to be obviously different than this: -# -# define foo -# $(V)echo bar -# endef -# -# all: ; $(foo) -# -# and the user thinks it should behave the same as when the "@" is literal -# instead of in a variable, that can't happen because by the time make -# expands the variables for the command line and sees it begins with a "@" it -# can't know anymore whether the prefix character came before the variable -# reference or was included in the first line of the variable reference. - -# TEST #5 -# ------- +# TEST 1: Simple run_make_test(' -define FOO -$(V1)echo hello -$(V2)echo world -endef -all: ; @$(FOO) -', '', 'hello -world'); - -# TEST #6 -# ------- - -run_make_test(undef, 'V1=@ V2=@', 'hello -world'); +bar = Goodbye +foo := $(bar) +bar = ${ugh} +ugh = Hello +all: ; @echo $(foo) +', + '', "Goodbye\n"); -# TEST #7 -# ------- +# TEST 2: Append to recursive run_make_test(' -define FOO -$(V1)echo hello -$(V2)echo world -endef -all: ; $(FOO) -', 'V1=@', 'hello -echo world -world'); +foo = Hello +ugh = Goodbye +foo += $(bar) +bar = ${ugh} +ugh = Hello +all: ; @echo $(foo) +', + '', "Hello Hello\n"); -# TEST #8 -# ------- +# TEST 3: Append to simple -run_make_test(undef, 'V2=@', 'echo hello -hello -world'); +run_make_test(' +foo := Hello +ugh = Goodbye +bar = ${ugh} +foo += $(bar) +ugh = Hello +all: ; @echo $(foo) +', + '', "Hello Goodbye\n"); -# TEST #9 -# ------- +# TEST 4: Conditional pre-set -run_make_test(undef, 'V1=@ V2=@', 'hello -world'); +run_make_test(' +foo = Hello +ugh = Goodbye +bar = ${ugh} +foo ?= $(bar) +ugh = Hello +all: ; @echo $(foo) +', + '', "Hello\n"); -# TEST #10 -# ------- -# Test the basics; a "@" internally to the variable applies to only one line. -# A "@" before the variable applies to the entire variable. +# TEST 5: Conditional unset run_make_test(' -define FOO -@echo hello -echo world -endef -define BAR -echo hello -echo world -endef - -all: foo bar -foo: ; $(FOO) -bar: ; @$(BAR) -', '-j1', 'hello -echo world -world -hello -world -'); +ugh = Goodbye +bar = ${ugh} +foo ?= $(bar) +ugh = Hello +all: ; @echo $(foo) +', + '', "Hello\n"); 1; diff --git a/src/kmk/tests/scripts/variables/private b/src/kmk/tests/scripts/variables/private new file mode 100644 index 0000000..b4baf5f --- /dev/null +++ b/src/kmk/tests/scripts/variables/private @@ -0,0 +1,78 @@ +# -*-perl-*- + +$description = "Test 'private' variables."; + +$details = ""; + +# 1: Simple verification that private variables are not inherited +&run_make_test(' +a: +F = g +a: F = a +b: private F = b + +a b c: ; @echo $@: F=$(F) +a: b +b: c +', + '', "c: F=a\nb: F=b\na: F=a\n"); + +# 2: Again, but this time we start with "b" so "a"'s variable is not in scope +&run_make_test(undef, 'b', "c: F=g\nb: F=b\n"); + +# 3: Verification with pattern-specific variables +&run_make_test(' +t.a: + +F1 = g +F2 = g +%.a: private F1 = a +%.a: F2 = a + +t.a t.b: ; @echo $@: F1=$(F1) / F2=$(F2) +t.a: t.b +', + '', "t.b: F1=g / F2=a\nt.a: F1=a / F2=a\n"); + +# 4: Test private global variables +&run_make_test(' +a: +private F = g +G := $(F) +a: +b: F = b + +a b: ; @echo $@: F=$(F) / G=$(G) +a: b +', + '', "b: F=b / G=g\na: F= / G=g\n"); + +# 5: Multiple conditions on the same variable. Test export. +delete $ENV{'_X'}; +&run_make_test(' +_X = x +a: export override private _X = a +a: ; @echo _X=$(_X) / _X=$$_X +', + '', "_X=a / _X=a"); + +# 6: Test override. +&run_make_test(undef, '_X=c', "_X=a / _X=a\n"); + +# 7: Ensure keywords still work as targets +&run_make_test(' +a: export override private foo bar +foo bar export override private: ; @echo $@ +', + '', "export\noverride\nprivate\nfoo\nbar\n"); + +# 8: Ensure keywords still work as variables +&run_make_test(' +private = g +a: private = a +a: b +a b: ; @echo $@=$(private) +', + '', "b=a\na=a\n"); + +1; diff --git a/src/kmk/tests/scripts/variables/undefine b/src/kmk/tests/scripts/variables/undefine new file mode 100644 index 0000000..38707b8 --- /dev/null +++ b/src/kmk/tests/scripts/variables/undefine @@ -0,0 +1,73 @@ +# -*-perl-*- + +$description = "Test variable undefine."; + +$details = ""; + +# TEST 0: basic undefine functionality + +run_make_test(' +a = a +b := b +define c +c +endef + +$(info $(flavor a) $(flavor b) $(flavor c)) + +n := b + +undefine a +undefine $n +undefine c + +$(info $(flavor a) $(flavor b) $(flavor c)) + + +all: ;@: +', +'', "recursive simple recursive\nundefined undefined undefined"); + + +# TEST 1: override + +run_make_test(' +undefine a +override undefine b + +$(info $(flavor a) $(flavor b)) + + +all: ;@: +', +'a=a b=b', "recursive undefined"); + +1; + +# TEST 2: undefine in eval (make sure we undefine from the global var set) + +run_make_test(' +define undef +$(eval undefine $$1) +endef + +a := a +$(call undef,a) +$(info $(flavor a)) + + +all: ;@: +', +'', "undefined"); + + +# TEST 3: Missing variable name + +run_make_test(' +a = +undefine $a +all: ;@echo ouch +', +'', "#MAKEFILE#:3: *** empty variable name. Stop.\n", 512); + +1; diff --git a/src/kmk/tests/test_driver.pl b/src/kmk/tests/test_driver.pl index 9d90418..c4c3ea6 100644 --- a/src/kmk/tests/test_driver.pl +++ b/src/kmk/tests/test_driver.pl @@ -6,7 +6,8 @@ # Modified 92-02-11 through 92-02-22 by Chris Arthur to further generalize. # # Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -# 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +# 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under @@ -29,7 +30,7 @@ # this routine controls the whole mess; each test suite sets up a few # variables and then calls &toplevel, which does all the real work. -# $Id: test_driver.pl,v 1.24 2007/11/04 21:54:02 psmith Exp $ +# $Id: test_driver.pl,v 1.30 2010/07/28 05:39:50 psmith Exp $ # The number of test categories we've run @@ -53,6 +54,8 @@ $test_passed = 1; # Timeout in seconds. If the test takes longer than this we'll fail it. $test_timeout = 5; +# Path to Perl +$perl_name = $^X; # %makeENV is the cleaned-out environment. %makeENV = (); @@ -238,9 +241,10 @@ sub toplevel sub get_osname { # Set up an initial value. In perl5 we can do it the easy way. - # $osname = defined($^O) ? $^O : ''; + # Find a path to Perl + # See if the filesystem supports long file names with multiple # dots. DOS doesn't. $short_filenames = 0; @@ -275,14 +279,14 @@ sub get_osname eval "chop (\$osname = `sh -c 'uname -nmsr 2>&1'`)"; if ($osname =~ /not found/i) { - $osname = "(something unixy with no uname)"; + $osname = "(something posixy with no uname)"; } elsif ($@ ne "" || $?) { eval "chop (\$osname = `sh -c 'uname -a 2>&1'`)"; if ($@ ne "" || $?) { - $osname = "(something unixy)"; + $osname = "(something posixy)"; } } $vos = 0; @@ -459,16 +463,19 @@ sub run_each_test $logext = 'l'; $diffext = 'd'; $baseext = 'b'; + $runext = 'r'; $extext = ''; } else { $logext = 'log'; $diffext = 'diff'; $baseext = 'base'; + $runext = 'run'; $extext = '.'; } $log_filename = "$testpath.$logext"; $diff_filename = "$testpath.$diffext"; $base_filename = "$testpath.$baseext"; + $run_filename = "$testpath.$runext"; $tmp_filename = "$testpath.$tmpfilesuffix"; &setup_for_test; # suite-defined @@ -482,6 +489,7 @@ sub run_each_test # Run the actual test! $tests_run = 0; $tests_passed = 0; + $code = do $perl_testname; $total_tests_run += $tests_run; @@ -715,6 +723,7 @@ sub compare_output print "DIFFERENT OUTPUT\n" if $debug; &create_file (&get_basefile, $answer); + &create_file (&get_runfile, $command_string); print "\nCreating Difference File ...\n" if $debug; @@ -722,6 +731,8 @@ sub compare_output local($command) = "diff -c " . &get_basefile . " " . $logfile; &run_command_with_output(&get_difffile,$command); + } else { + &rmfiles (); } $suite_passed = 0; @@ -815,7 +826,7 @@ sub _run_command eval { local $SIG{ALRM} = sub { die "timeout\n"; }; alarm $test_timeout; - $code = system @_; + $code = system(@_); alarm 0; }; if ($@) { @@ -852,7 +863,7 @@ sub run_command_with_output { my $filename = shift; - print "\nrun_command_with_output($filename): @_\n" if $debug; + print "\nrun_command_with_output($filename,$runname): @_\n" if $debug; &attach_default_output ($filename); my $code = _run_command(@_); &detach_default_output; @@ -1225,6 +1236,15 @@ sub get_difffile return ($diff_filename . &num_suffix ($num_of_logfiles)); } +# This subroutine returns a command filename with a number appended +# to the end corresponding to how many logfiles (and thus command files) +# have been created in the current running test. + +sub get_runfile +{ + return ($run_filename . &num_suffix ($num_of_logfiles)); +} + # just like logfile, only a generic tmp filename for use by the test. # they are automatically cleaned up unless -keep was used, or the test fails. # Pass an argument of 1 to return the same filename as the previous call. diff --git a/src/kmk/variable.c b/src/kmk/variable.c index 73ec34e..125b8a5 100644 --- a/src/kmk/variable.c +++ b/src/kmk/variable.c @@ -1,7 +1,7 @@ /* Internals of variables for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -46,28 +46,62 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ static struct pattern_var *pattern_vars; -/* Pointer to last struct in the chain, so we can add onto the end. */ +/* Pointer to the last struct in the pack of a specific size, from 1 to 255.*/ -static struct pattern_var *last_pattern_var; +static struct pattern_var *last_pattern_vars[256]; -/* Create a new pattern-specific variable struct. */ +/* Create a new pattern-specific variable struct. The new variable is + inserted into the PATTERN_VARS list in the shortest patterns first + order to support the shortest stem matching (the variables are + matched in the reverse order so the ones with the longest pattern + will be considered first). Variables with the same pattern length + are inserted in the definition order. */ struct pattern_var * create_pattern_var (const char *target, const char *suffix) { + register unsigned int len = strlen (target); register struct pattern_var *p = xmalloc (sizeof (struct pattern_var)); - if (last_pattern_var != 0) - last_pattern_var->next = p; + if (pattern_vars != 0) + { + if (len < 256 && last_pattern_vars[len] != 0) + { + p->next = last_pattern_vars[len]->next; + last_pattern_vars[len]->next = p; + } + else + { + /* Find the position where we can insert this variable. */ + register struct pattern_var **v; + + for (v = &pattern_vars; ; v = &(*v)->next) + { + /* Insert at the end of the pack so that patterns with the + same length appear in the order they were defined .*/ + + if (*v == 0 || (*v)->len > len) + { + p->next = *v; + *v = p; + break; + } + } + } + } else - pattern_vars = p; - last_pattern_var = p; - p->next = 0; + { + pattern_vars = p; + p->next = 0; + } p->target = target; - p->len = strlen (target); + p->len = len; p->suffix = suffix + 1; + if (len < 256) + last_pattern_vars[len] = p; + return p; } @@ -168,7 +202,7 @@ variable_hash_cmp (const void *xv, const void *yv) static struct variable_set global_variable_set; static struct variable_set_list global_setlist - = { 0, &global_variable_set }; + = { 0, &global_variable_set, 0 }; struct variable_set_list *current_variable_set_list = &global_setlist; /* Implement variables. */ @@ -341,7 +375,7 @@ define_variable_in_set (const char *name, unsigned int length, v = alloccache_alloc (&variable_cache); #endif #ifndef CONFIG_WITH_STRCACHE2 - v->name = savestring (name, length); + v->name = xstrndup (name, length); #else v->name = name; /* already cached. */ #endif @@ -384,6 +418,7 @@ define_variable_in_set (const char *name, unsigned int length, v->exp_count = 0; v->per_target = 0; v->append = 0; + v->private_var = 0; v->export = v_default; MAKE_STATS_2(v->changes = 0); MAKE_STATS_2(v->reallocs = 0); @@ -411,6 +446,51 @@ define_variable_in_set (const char *name, unsigned int length, return v; } + +/* Undefine variable named NAME in SET. LENGTH is the length of NAME, which + does not need to be null-terminated. ORIGIN specifies the origin of the + variable (makefile, command line or environment). */ + +static void +free_variable_name_and_value (const void *item); + +void +undefine_variable_in_set (const char *name, unsigned int length, + enum variable_origin origin, + struct variable_set *set) +{ + struct variable *v; + struct variable **var_slot; + struct variable var_key; + + if (set == NULL) + set = &global_variable_set; + + var_key.name = (char *) name; + var_key.length = length; + var_slot = (struct variable **) hash_find_slot (&set->table, &var_key); + + if (env_overrides && origin == o_env) + origin = o_env_override; + + v = *var_slot; + if (! HASH_VACANT (v)) + { + if (env_overrides && v->origin == o_env) + /* V came from in the environment. Since it was defined + before the switches were parsed, it wasn't affected by -e. */ + v->origin = o_env_override; + + /* If the definition is from a stronger source than this one, don't + undefine it. */ + if ((int) origin >= (int) v->origin) + { + hash_delete_at (&set->table, var_slot); + free_variable_name_and_value (v); + } + } +} + /* If the variable passed in is "special", handle its special nature. Currently there are two such variables, both used for introspection: .VARIABLES expands to a list of all the variables defined in this instance @@ -510,7 +590,7 @@ lookup_special_var (struct variable *var) } -#ifdef KMK /* bird: speed */ +#if 0 /*FIX THIS - def KMK*/ /* bird: speed */ MY_INLINE struct variable * lookup_cached_variable (const char *name) { @@ -641,12 +721,13 @@ lookup_variable_for_assert (const char *name, unsigned int length) struct variable * lookup_variable (const char *name, unsigned int length) { -#ifndef KMK +#if 1 /*FIX THIS - ndef KMK*/ const struct variable_set_list *setlist; struct variable var_key; #else /* KMK */ struct variable *v; #endif /* KMK */ + int is_parent = 0; #ifdef CONFIG_WITH_STRCACHE2 const char *cached_name; @@ -657,7 +738,7 @@ lookup_variable (const char *name, unsigned int length) return NULL; name = cached_name; #endif /* CONFIG_WITH_STRCACHE2 */ -#ifndef KMK +#if 1 /*FIX THIS - ndef KMK */ var_key.name = (char *) name; var_key.length = length; @@ -673,8 +754,10 @@ lookup_variable (const char *name, unsigned int length) # else /* CONFIG_WITH_STRCACHE2 */ v = (struct variable *) hash_find_item_strcached ((struct hash_table *) &set->table, &var_key); # endif /* CONFIG_WITH_STRCACHE2 */ - if (v) + if (v && (!is_parent || !v->private_var)) return v->special ? lookup_special_var (v) : v; + + is_parent |= setlist->next_is_parent; } #else /* KMK - need for speed */ @@ -742,9 +825,7 @@ lookup_variable (const char *name, unsigned int length) } #endif /* VMS */ -#if !defined (KMK) || defined(VMS) return 0; -#endif } /* Lookup a variable whose name is a string starting at NAME @@ -831,6 +912,7 @@ initialize_file_variables (struct file *file, int reading) { initialize_file_variables (file->double_colon, reading); l->next = file->double_colon->variables; + l->next_is_parent = 0; return; } @@ -841,6 +923,7 @@ initialize_file_variables (struct file *file, int reading) initialize_file_variables (file->parent, reading); l->next = file->parent->variables; } + l->next_is_parent = 1; /* If we're not reading makefiles and we haven't looked yet, see if we can find pattern variables for this target. */ @@ -893,6 +976,7 @@ initialize_file_variables (struct file *file, int reading) /* Also mark it as a per-target and copy export status. */ v->per_target = p->variable.per_target; v->export = p->variable.export; + v->private_var = p->variable.private_var; } while ((p = lookup_pattern_var (p, file->name)) != 0); @@ -906,7 +990,9 @@ initialize_file_variables (struct file *file, int reading) if (file->pat_variables != 0) { file->pat_variables->next = l->next; + file->pat_variables->next_is_parent = l->next_is_parent; l->next = file->pat_variables; + l->next_is_parent = 0; } } @@ -941,6 +1027,7 @@ create_new_variable_set (void) #endif setlist->set = set; setlist->next = current_variable_set_list; + setlist->next_is_parent = 0; return setlist; } @@ -1023,6 +1110,7 @@ pop_variable_scope (void) set = global_setlist.set; global_setlist.set = setlist->set; global_setlist.next = setlist->next; + global_setlist.next_is_parent = setlist->next_is_parent; } /* Free the one we no longer need. */ @@ -1158,7 +1246,7 @@ define_automatic_variables (void) #endif sprintf (buf, "%u", makelevel); - (void) define_variable (MAKELEVEL_NAME, MAKELEVEL_LENGTH, buf, o_env, 0); + define_variable_cname (MAKELEVEL_NAME, buf, o_env, 0); sprintf (buf, "%s%s%s", version_string, @@ -1167,30 +1255,25 @@ define_automatic_variables (void) (remote_description == 0 || remote_description[0] == '\0') ? "" : remote_description); #ifndef KMK - (void) define_variable ("MAKE_VERSION", 12, buf, o_default, 0); + define_variable_cname ("MAKE_VERSION", buf, o_default, 0); #else /* KMK */ /* Define KMK_VERSION to indicate kMk. */ - (void) define_variable ("KMK_VERSION", 11, buf, o_default, 0); + define_variable_cname ("KMK_VERSION", buf, o_default, 0); /* Define KBUILD_VERSION* */ sprintf (buf, "%d", KBUILD_VERSION_MAJOR); - define_variable ("KBUILD_VERSION_MAJOR", sizeof ("KBUILD_VERSION_MAJOR") - 1, - buf, o_default, 0); + define_variable_cname ("KBUILD_VERSION_MAJOR", buf, o_default, 0); sprintf (buf, "%d", KBUILD_VERSION_MINOR); - define_variable ("KBUILD_VERSION_MINOR", sizeof("KBUILD_VERSION_MINOR") - 1, - buf, o_default, 0); + define_variable_cname ("KBUILD_VERSION_MINOR", buf, o_default, 0); sprintf (buf, "%d", KBUILD_VERSION_PATCH); - define_variable ("KBUILD_VERSION_PATCH", sizeof ("KBUILD_VERSION_PATCH") - 1, - buf, o_default, 0); + define_variable_cname ("KBUILD_VERSION_PATCH", buf, o_default, 0); sprintf (buf, "%d", KBUILD_SVN_REV); - define_variable ("KBUILD_KMK_REVISION", sizeof ("KBUILD_KMK_REVISION") - 1, - buf, o_default, 0); + define_variable_cname ("KBUILD_KMK_REVISION", buf, o_default, 0); sprintf (buf, "%d.%d.%d-r%d", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH, KBUILD_SVN_REV); - define_variable ("KBUILD_VERSION", sizeof ("KBUILD_VERSION") - 1, - buf, o_default, 0); + define_variable_cname ("KBUILD_VERSION", buf, o_default, 0); /* The host defaults. The BUILD_* stuff will be replaced by KBUILD_* soon. */ envvar1 = lookup_variable (STRING_SIZE_TUPLE ("KBUILD_HOST")); @@ -1199,11 +1282,9 @@ define_automatic_variables (void) if (envvar1 && envvar2 && strcmp (envvar1->value, envvar2->value)) error (NULL, _("KBUILD_HOST and BUILD_PLATFORM differs, using KBUILD_HOST=%s."), val); if (!envvar1) - define_variable ("KBUILD_HOST", sizeof ("KBUILD_HOST") - 1, - val, o_default, 0); + define_variable_cname ("KBUILD_HOST", val, o_default, 0); if (!envvar2) - define_variable ("BUILD_PLATFORM", sizeof ("BUILD_PLATFORM") - 1, - val, o_default, 0); + define_variable_cname ("BUILD_PLATFORM", val, o_default, 0); envvar1 = lookup_variable (STRING_SIZE_TUPLE ("KBUILD_HOST_ARCH")); envvar2 = lookup_variable (STRING_SIZE_TUPLE ("BUILD_PLATFORM_ARCH")); @@ -1211,11 +1292,9 @@ define_automatic_variables (void) if (envvar1 && envvar2 && strcmp (envvar1->value, envvar2->value)) error (NULL, _("KBUILD_HOST_ARCH and BUILD_PLATFORM_ARCH differs, using KBUILD_HOST_ARCH=%s."), val); if (!envvar1) - define_variable ("KBUILD_HOST_ARCH", sizeof ("KBUILD_HOST_ARCH") - 1, - val, o_default, 0); + define_variable_cname ("KBUILD_HOST_ARCH", val, o_default, 0); if (!envvar2) - define_variable ("BUILD_PLATFORM_ARCH", sizeof ("BUILD_PLATFORM_ARCH") - 1, - val, o_default, 0); + define_variable_cname ("BUILD_PLATFORM_ARCH", val, o_default, 0); envvar1 = lookup_variable (STRING_SIZE_TUPLE ("KBUILD_HOST_CPU")); envvar2 = lookup_variable (STRING_SIZE_TUPLE ("BUILD_PLATFORM_CPU")); @@ -1223,11 +1302,9 @@ define_automatic_variables (void) if (envvar1 && envvar2 && strcmp (envvar1->value, envvar2->value)) error (NULL, _("KBUILD_HOST_CPU and BUILD_PLATFORM_CPU differs, using KBUILD_HOST_CPU=%s."), val); if (!envvar1) - define_variable ("KBUILD_HOST_CPU", sizeof ("KBUILD_HOST_CPU") - 1, - val, o_default, 0); + define_variable_cname ("KBUILD_HOST_CPU", val, o_default, 0); if (!envvar2) - define_variable ("BUILD_PLATFORM_CPU", sizeof ("BUILD_PLATFORM_CPU") - 1, - val, o_default, 0); + define_variable_cname ("BUILD_PLATFORM_CPU", val, o_default, 0); /* The host kernel version. */ #if defined(WINDOWS32) @@ -1266,31 +1343,23 @@ define_automatic_variables (void) #endif sprintf (buf, "%lu.%lu.%lu.%lu", ulMajor, ulMinor, ulPatch, ul4th); - define_variable ("KBUILD_HOST_VERSION", sizeof ("KBUILD_HOST_VERSION") - 1, - buf, o_default, 0); + define_variable_cname ("KBUILD_HOST_VERSION", buf, o_default, 0); sprintf (buf, "%lu", ulMajor); - define_variable ("KBUILD_HOST_VERSION_MAJOR", sizeof ("KBUILD_HOST_VERSION_MAJOR") - 1, - buf, o_default, 0); + define_variable_cname ("KBUILD_HOST_VERSION_MAJOR", buf, o_default, 0); sprintf (buf, "%lu", ulMinor); - define_variable ("KBUILD_HOST_VERSION_MINOR", sizeof ("KBUILD_HOST_VERSION_MINOR") - 1, - buf, o_default, 0); + define_variable_cname ("KBUILD_HOST_VERSION_MINOR", buf, o_default, 0); sprintf (buf, "%lu", ulPatch); - define_variable ("KBUILD_HOST_VERSION_PATCH", sizeof ("KBUILD_HOST_VERSION_PATCH") - 1, - buf, o_default, 0); + define_variable_cname ("KBUILD_HOST_VERSION_PATCH", buf, o_default, 0); /* The kBuild locations. */ - define_variable ("KBUILD_PATH", sizeof ("KBUILD_PATH") - 1, - get_kbuild_path (), o_default, 0); - define_variable ("KBUILD_BIN_PATH", sizeof ("KBUILD_BIN_PATH") - 1, - get_kbuild_bin_path (), o_default, 0); + define_variable_cname ("KBUILD_PATH", get_kbuild_path (), o_default, 0); + define_variable_cname ("KBUILD_BIN_PATH", get_kbuild_bin_path (), o_default, 0); - define_variable ("PATH_KBUILD", sizeof ("PATH_KBUILD") - 1, - get_kbuild_path (), o_default, 0); - define_variable ("PATH_KBUILD_BIN", sizeof ("PATH_KBUILD_BIN") - 1, - get_kbuild_bin_path (), o_default, 0); + define_variable_cname ("PATH_KBUILD", get_kbuild_path (), o_default, 0); + define_variable_cname ("PATH_KBUILD_BIN", get_kbuild_bin_path (), o_default, 0); /* Define KMK_FEATURES to indicate various working KMK features. */ # if defined (CONFIG_WITH_RSORT) \ @@ -1319,36 +1388,36 @@ define_automatic_variables (void) && defined (CONFIG_WITH_STRING_FUNCTIONS) \ && defined (CONFIG_WITH_DEFINED_FUNCTIONS) \ && defined (KMK_HELPERS) - (void) define_variable ("KMK_FEATURES", 12, - "append-dash-n abspath includedep-queue install-hard-linking umask" - " kBuild-define" - " rsort" - " abspathex" - " toupper tolower" - " defined" - " comp-vars comp-cmds comp-cmds-ex" - " stack" - " math-int" - " xargs" - " explicit-multitarget" - " dot-must-make" - " prepend-assignment" - " set-conditionals intersects" - " date" - " file-size" - " expr if-expr select" - " where" - " which" - " evalctx evalval evalvalctx evalcall evalcall2 eval-opt-var" - " make-stats" - " commands" - " printf" - " for while" - " root" - " length insert pos lastpos substr translate" - " kb-src-tool kb-obj-base kb-obj-suff kb-src-prop kb-src-one kb-exp-tmpl" - " firstdefined lastdefined" - , o_default, 0); + define_variable_cname ("KMK_FEATURES", + "append-dash-n abspath includedep-queue install-hard-linking umask" + " kBuild-define" + " rsort" + " abspathex" + " toupper tolower" + " defined" + " comp-vars comp-cmds comp-cmds-ex" + " stack" + " math-int" + " xargs" + " explicit-multitarget" + " dot-must-make" + " prepend-assignment" + " set-conditionals intersects" + " date" + " file-size" + " expr if-expr select" + " where" + " which" + " evalctx evalval evalvalctx evalcall evalcall2 eval-opt-var" + " make-stats" + " commands" + " printf" + " for while" + " root" + " length insert pos lastpos substr translate" + " kb-src-tool kb-obj-base kb-obj-suff kb-src-prop kb-src-one kb-exp-tmpl" + " firstdefined lastdefined" + , o_default, 0); # else /* MSC can't deal with strings mixed with #if/#endif, thus the slow way. */ # error "All features should be enabled by default!" strcpy (buf, "append-dash-n abspath includedep-queue install-hard-linking umask" @@ -1431,14 +1500,14 @@ define_automatic_variables (void) # if defined (KMK_HELPERS) strcat (buf, " kb-src-tool kb-obj-base kb-obj-suff kb-src-prop kb-src-one kb-exp-tmpl"); # endif - (void) define_variable ("KMK_FEATURES", 12, buf, o_default, 0); + define_variable_cname ("KMK_FEATURES", buf, o_default, 0); # endif #endif /* KMK */ #ifdef CONFIG_WITH_KMK_BUILTIN /* The supported kMk Builtin commands. */ - (void) define_variable ("KMK_BUILTIN", 11, "append cat chmod cp cmp echo expr install kDepIDB ln md5sum mkdir mv printf rm rmdir sleep test", o_default, 0); + define_variable_cname ("KMK_BUILTIN", "append cat chmod cp cmp echo expr install kDepIDB ln md5sum mkdir mv printf rm rmdir sleep test", o_default, 0); #endif #ifdef __MSDOS__ @@ -1450,13 +1519,13 @@ define_automatic_variables (void) struct variable *mshp = lookup_variable ("MAKESHELL", 9); struct variable *comp = lookup_variable ("COMSPEC", 7); - /* Make $MAKESHELL override $SHELL even if -e is in effect. */ + /* $(MAKESHELL) overrides $(SHELL) even if -e is in effect. */ if (mshp) (void) define_variable (shell_str, shlen, mshp->value, o_env_override, 0); else if (comp) { - /* $COMSPEC shouldn't override $SHELL. */ + /* $(COMSPEC) shouldn't override $(SHELL). */ struct variable *shp = lookup_variable (shell_str, shlen); if (!shp) @@ -1515,7 +1584,7 @@ define_automatic_variables (void) /* This won't override any definition, but it will provide one if there isn't one there. */ - v = define_variable ("SHELL", 5, default_shell, o_default, 0); + v = define_variable_cname ("SHELL", default_shell, o_default, 0); #ifdef __MSDOS__ v->export = v_export; /* Export always SHELL. */ #endif @@ -1544,36 +1613,36 @@ define_automatic_variables (void) #endif /* Make sure MAKEFILES gets exported if it is set. */ - v = define_variable ("MAKEFILES", 9, "", o_default, 0); + v = define_variable_cname ("MAKEFILES", "", o_default, 0); v->export = v_ifset; /* Define the magic D and F variables in terms of the automatic variables they are variations of. */ #ifdef VMS - define_variable ("@D", 2, "$(dir $@)", o_automatic, 1); - define_variable ("%D", 2, "$(dir $%)", o_automatic, 1); - define_variable ("*D", 2, "$(dir $*)", o_automatic, 1); - define_variable ("<D", 2, "$(dir $<)", o_automatic, 1); - define_variable ("?D", 2, "$(dir $?)", o_automatic, 1); - define_variable ("^D", 2, "$(dir $^)", o_automatic, 1); - define_variable ("+D", 2, "$(dir $+)", o_automatic, 1); + define_variable_cname ("@D", "$(dir $@)", o_automatic, 1); + define_variable_cname ("%D", "$(dir $%)", o_automatic, 1); + define_variable_cname ("*D", "$(dir $*)", o_automatic, 1); + define_variable_cname ("<D", "$(dir $<)", o_automatic, 1); + define_variable_cname ("?D", "$(dir $?)", o_automatic, 1); + define_variable_cname ("^D", "$(dir $^)", o_automatic, 1); + define_variable_cname ("+D", "$(dir $+)", o_automatic, 1); #else - define_variable ("@D", 2, "$(patsubst %/,%,$(dir $@))", o_automatic, 1); - define_variable ("%D", 2, "$(patsubst %/,%,$(dir $%))", o_automatic, 1); - define_variable ("*D", 2, "$(patsubst %/,%,$(dir $*))", o_automatic, 1); - define_variable ("<D", 2, "$(patsubst %/,%,$(dir $<))", o_automatic, 1); - define_variable ("?D", 2, "$(patsubst %/,%,$(dir $?))", o_automatic, 1); - define_variable ("^D", 2, "$(patsubst %/,%,$(dir $^))", o_automatic, 1); - define_variable ("+D", 2, "$(patsubst %/,%,$(dir $+))", o_automatic, 1); + define_variable_cname ("@D", "$(patsubst %/,%,$(dir $@))", o_automatic, 1); + define_variable_cname ("%D", "$(patsubst %/,%,$(dir $%))", o_automatic, 1); + define_variable_cname ("*D", "$(patsubst %/,%,$(dir $*))", o_automatic, 1); + define_variable_cname ("<D", "$(patsubst %/,%,$(dir $<))", o_automatic, 1); + define_variable_cname ("?D", "$(patsubst %/,%,$(dir $?))", o_automatic, 1); + define_variable_cname ("^D", "$(patsubst %/,%,$(dir $^))", o_automatic, 1); + define_variable_cname ("+D", "$(patsubst %/,%,$(dir $+))", o_automatic, 1); #endif - define_variable ("@F", 2, "$(notdir $@)", o_automatic, 1); - define_variable ("%F", 2, "$(notdir $%)", o_automatic, 1); - define_variable ("*F", 2, "$(notdir $*)", o_automatic, 1); - define_variable ("<F", 2, "$(notdir $<)", o_automatic, 1); - define_variable ("?F", 2, "$(notdir $?)", o_automatic, 1); - define_variable ("^F", 2, "$(notdir $^)", o_automatic, 1); - define_variable ("+F", 2, "$(notdir $+)", o_automatic, 1); + define_variable_cname ("@F", "$(notdir $@)", o_automatic, 1); + define_variable_cname ("%F", "$(notdir $%)", o_automatic, 1); + define_variable_cname ("*F", "$(notdir $*)", o_automatic, 1); + define_variable_cname ("<F", "$(notdir $<)", o_automatic, 1); + define_variable_cname ("?F", "$(notdir $?)", o_automatic, 1); + define_variable_cname ("^F", "$(notdir $^)", o_automatic, 1); + define_variable_cname ("+F", "$(notdir $+)", o_automatic, 1); #ifdef CONFIG_WITH_LAZY_DEPS_VARS define_variable ("^", 1, "$(deps $@)", o_automatic, 1); define_variable ("+", 1, "$(deps-all $@)", o_automatic, 1); @@ -1741,7 +1810,7 @@ target_environment (struct file *file) strcmp(v->name, "PATH") == 0) convert_Path_to_windows32(value, ';'); #endif - *result++ = xstrdup (concat (v->name, "=", value)); + *result++ = xstrdup (concat (3, v->name, "=", value)); free (value); } else @@ -1751,7 +1820,7 @@ target_environment (struct file *file) strcmp(v->name, "PATH") == 0) convert_Path_to_windows32(v->value, ';'); #endif - *result++ = xstrdup (concat (v->name, "=", v->value)); + *result++ = xstrdup (concat (3, v->name, "=", v->value)); } } @@ -1939,7 +2008,7 @@ do_variable_definition_2 (const struct floc *flocp, if (value_len == ~0U) value_len = strlen (value); if (!free_value) - p = alloc_value = savestring (value, value_len); + p = alloc_value = xstrndup (value, value_len); else { assert (value == free_value); @@ -2033,7 +2102,7 @@ do_variable_definition_2 (const struct floc *flocp, unsigned int oldlen, vallen; const char *val; - char *tp; + char *tp = NULL; val = value; if (v->recursive) @@ -2046,26 +2115,28 @@ do_variable_definition_2 (const struct floc *flocp, when it was set; and from the expanded new value. Allocate memory for the expansion as we may still need the rest of the buffer if we're looking at a target-specific variable. */ - val = alloc_value = allocated_variable_expand (val); + val = tp = allocated_variable_expand (val); oldlen = strlen (v->value); vallen = strlen (val); - tp = alloca (oldlen + 1 + vallen + 1); + p = alloc_value = xmalloc (oldlen + 1 + vallen + 1); # ifdef CONFIG_WITH_PREPEND_ASSIGNMENT if (org_flavor == f_prepend) { - memcpy (tp, val, vallen); - tp[oldlen] = ' '; - memcpy (&tp[oldlen + 1], v->value, oldlen + 1); + memcpy (alloc_value, val, vallen); + alloc_value[oldlen] = ' '; + memcpy (&alloc_value[oldlen + 1], v->value, oldlen + 1); } else # endif /* CONFIG_WITH_PREPEND_ASSIGNMENT */ { - memcpy (tp, v->value, oldlen); - tp[oldlen] = ' '; - memcpy (&tp[oldlen + 1], val, vallen + 1); + memcpy (alloc_value, v->value, oldlen); + alloc_value[oldlen] = ' '; + memcpy (&alloc_value[oldlen + 1], val, vallen + 1); } - p = tp; + + if (tp) + free (tp); #endif /* !CONFIG_WITH_VALUE_LENGTH */ } } @@ -2178,10 +2249,10 @@ do_variable_definition_2 (const struct floc *flocp, } else { - if (alloc_value) - free (alloc_value); + char *tp = alloc_value; alloc_value = allocated_variable_expand (p); + if (find_and_set_default_shell (alloc_value)) { v = define_variable_in_set (varname, varname_len, p, @@ -2197,6 +2268,9 @@ do_variable_definition_2 (const struct floc *flocp, } else v = lookup_variable (varname, varname_len); + + if (tp) + free (tp); } } else @@ -2234,80 +2308,32 @@ do_variable_definition_2 (const struct floc *flocp, return v->special ? set_special_var (v) : v; } -/* Try to interpret LINE (a null-terminated string) as a variable definition. +/* Parse P (a null-terminated string) as a variable definition. - ORIGIN may be o_file, o_override, o_env, o_env_override, - or o_command specifying that the variable definition comes - from a makefile, an override directive, the environment with - or without the -e switch, or the command line. + If it is not a variable definition, return NULL. - See the comments for parse_variable_definition(). + If it is a variable definition, return a pointer to the char after the + assignment token and set *FLAVOR to the type of variable assignment. */ - If LINE was recognized as a variable definition, a pointer to its `struct - variable' is returned. If LINE is not a variable definition, NULL is - returned. */ - -struct variable * -#ifndef CONFIG_WITH_VALUE_LENGTH -parse_variable_definition (struct variable *v, char *line) -#else -parse_variable_definition (struct variable *v, char *line, char *eos) -#endif +char * +parse_variable_definition (const char *p, enum variable_flavor *flavor) { - register int c; - register char *p = line; - register char *beg; - register char *end; - enum variable_flavor flavor = f_bogus; -#ifndef CONFIG_WITH_VALUE_LENGTH - char *name; -#endif + int wspace = 0; + + p = next_token (p); while (1) { - c = *p++; + int c = *p++; + + /* If we find a comment or EOS, it's not a variable definition. */ if (c == '\0' || c == '#') - return 0; - if (c == '=') - { - end = p - 1; - flavor = f_recursive; - break; - } - else if (c == ':') - if (*p == '=') - { - end = p++ - 1; - flavor = f_simple; - break; - } - else - /* A colon other than := is a rule line, not a variable defn. */ - return 0; - else if (c == '+' && *p == '=') - { - end = p++ - 1; - flavor = f_append; - break; - } -#ifdef CONFIG_WITH_PREPEND_ASSIGNMENT - else if (c == '<' && *p == '=') - { - end = p++ - 1; - flavor = f_prepend; - break; - } -#endif - else if (c == '?' && *p == '=') - { - end = p++ - 1; - flavor = f_conditional; - break; - } - else if (c == '$') + return NULL; + + if (c == '$') { - /* This might begin a variable expansion reference. Make sure we - don't misrecognize chars inside the reference as =, := or +=. */ + /* This begins a variable expansion reference. Make sure we don't + treat chars inside the reference as assignment tokens. */ char closeparen; int count; c = *p++; @@ -2316,7 +2342,8 @@ parse_variable_definition (struct variable *v, char *line, char *eos) else if (c == '{') closeparen = '}'; else - continue; /* Nope. */ + /* '$$' or '$X'. Either way, nothing special to do here. */ + continue; /* P now points past the opening paren or brace. Count parens or braces until it is matched. */ @@ -2331,19 +2358,99 @@ parse_variable_definition (struct variable *v, char *line, char *eos) break; } } + continue; } + + /* If we find whitespace skip it, and remember we found it. */ + if (isblank ((unsigned char)c)) + { + wspace = 1; + p = next_token (p); + c = *p; + if (c == '\0') + return NULL; + ++p; + } + + + if (c == '=') + { + *flavor = f_recursive; + return (char *)p; + } + + /* Match assignment variants (:=, +=, ?=) */ + if (*p == '=') + { + switch (c) + { + case ':': + *flavor = f_simple; + break; + case '+': + *flavor = f_append; + break; +#ifdef CONFIG_WITH_PREPEND_ASSIGNMENT + case '<': + *flavor = f_prepend; + break; +#endif + case '?': + *flavor = f_conditional; + break; + default: + /* If we skipped whitespace, non-assignments means no var. */ + if (wspace) + return NULL; + + /* Might be assignment, or might be $= or #=. Check. */ + continue; + } + return (char *)++p; + } + else if (c == ':') + /* A colon other than := is a rule line, not a variable defn. */ + return NULL; + + /* If we skipped whitespace, non-assignments means no var. */ + if (wspace) + return NULL; } - v->flavor = flavor; + + return (char *)p; +} + +/* Try to interpret LINE (a null-terminated string) as a variable definition. + + If LINE was recognized as a variable definition, a pointer to its `struct + variable' is returned. If LINE is not a variable definition, NULL is + returned. */ + +struct variable * +assign_variable_definition (struct variable *v, char *line IF_WITH_VALUE_LENGTH_PARAM(char *eos)) +{ + char *beg; + char *end; + enum variable_flavor flavor; +#ifndef CONFIG_WITH_VALUE_LENGTH + char *name; +#endif beg = next_token (line); + line = parse_variable_definition (beg, &flavor); + if (!line) + return NULL; + + end = line - (flavor == f_recursive ? 1 : 2); while (end > beg && isblank ((unsigned char)end[-1])) --end; - p = next_token (p); - v->value = p; + line = next_token (line); + v->value = line; + v->flavor = flavor; #ifdef CONFIG_WITH_VALUE_LENGTH v->value_alloc_len = ~(unsigned int)0; - v->value_length = eos != NULL ? eos - p : -1; - assert (eos == NULL || strchr (p, '\0') == eos); + v->value_length = eos != NULL ? eos - line : -1; + assert (eos == NULL || strchr (line, '\0') == eos); # ifdef CONFIG_WITH_RDONLY_VARIABLE_VALUE v->rdonly_val = 0; # endif @@ -2372,20 +2479,16 @@ parse_variable_definition (struct variable *v, char *line, char *eos) from a makefile, an override directive, the environment with or without the -e switch, or the command line. - See the comments for parse_variable_definition(). + See the comments for assign_variable_definition(). If LINE was recognized as a variable definition, a pointer to its `struct variable' is returned. If LINE is not a variable definition, NULL is returned. */ struct variable * -#ifndef CONFIG_WITH_VALUE_LENGTH -try_variable_definition (const struct floc *flocp, char *line, +try_variable_definition (const struct floc *flocp, char *line + IF_WITH_VALUE_LENGTH_PARAM(char *eos), enum variable_origin origin, int target_var) -#else -try_variable_definition (const struct floc *flocp, char *line, char *eos, - enum variable_origin origin, int target_var) -#endif { struct variable v; struct variable *vp; @@ -2396,13 +2499,13 @@ try_variable_definition (const struct floc *flocp, char *line, char *eos, v.fileinfo.filenm = 0; #ifndef CONFIG_WITH_VALUE_LENGTH - if (!parse_variable_definition (&v, line)) + if (!assign_variable_definition (&v, line)) return 0; vp = do_variable_definition (flocp, v.name, v.value, origin, v.flavor, target_var); #else - if (!parse_variable_definition (&v, line, eos)) + if (!assign_variable_definition (&v, line, eos)) return 0; vp = do_variable_definition_2 (flocp, v.name, v.value, v.value_length, @@ -2468,6 +2571,8 @@ print_variable (const void *item, void *arg) } fputs ("# ", stdout); fputs (origin, stdout); + if (v->private_var) + fputs (" private", stdout); if (v->fileinfo.filenm) printf (_(" (from `%s', line %lu)"), v->fileinfo.filenm, v->fileinfo.lineno); @@ -2496,7 +2601,7 @@ print_variable (const void *item, void *arg) printf ("define %s\n%s\nendef\n", v->name, v->value); else { - register char *p; + char *p; printf ("%s %s= ", v->name, v->recursive ? v->append ? "+" : "" : ":"); @@ -2642,7 +2747,7 @@ sync_Path_environment (void) * Create something WINDOWS32 world can grok */ convert_Path_to_windows32 (path, ';'); - environ_path = xstrdup (concat ("PATH", "=", path)); + environ_path = xstrdup (concat (3, "PATH", "=", path)); putenv (environ_path); free (path); } diff --git a/src/kmk/variable.h b/src/kmk/variable.h index cc06de1..b885cb4 100644 --- a/src/kmk/variable.h +++ b/src/kmk/variable.h @@ -81,6 +81,8 @@ struct variable unsigned int exportable:1; /* Nonzero if the variable _could_ be exported. */ unsigned int expanding:1; /* Nonzero if currently being expanded. */ + unsigned int private_var:1; /* Nonzero avoids inheritance of this + target-specific variable. */ unsigned int exp_count:EXP_COUNT_BITS; /* If >1, allow this many self-referential expansions. */ @@ -121,6 +123,7 @@ struct variable_set_list { struct variable_set_list *next; /* Link in the chain. */ struct variable_set *set; /* Variable set. */ + int next_is_parent; /* True if next is a parent target. */ }; /* Structure used for pattern-specific variables. */ @@ -136,14 +139,17 @@ struct pattern_var extern char *variable_buffer; extern struct variable_set_list *current_variable_set_list; +extern struct variable *default_goal_var; + #ifdef KMK extern unsigned int variable_buffer_length; -#define VARIABLE_BUFFER_ZONE 5 +# define VARIABLE_BUFFER_ZONE 5 #endif /* expand.c */ #ifndef KMK -char *variable_buffer_output (char *ptr, const char *string, unsigned int length); +char * +variable_buffer_output (char *ptr, const char *string, unsigned int length); #else /* KMK */ /* Subroutine of variable_expand and friends: The text to add is LENGTH chars starting at STRING to the variable_buffer. @@ -208,9 +214,11 @@ void recycle_variable_buffer (char *buffer, unsigned int length); #endif /* CONFIG_WITH_VALUE_LENGTH */ char *expand_argument (const char *str, const char *end); #ifndef CONFIG_WITH_VALUE_LENGTH -char *variable_expand_string (char *line, const char *string, long length); +char * +variable_expand_string (char *line, const char *string, long length); #else /* CONFIG_WITH_VALUE_LENGTH */ -char *variable_expand_string_2 (char *line, const char *string, long length, char **eol); +char * +variable_expand_string_2 (char *line, const char *string, long length, char **eol); __inline static char * variable_expand_string (char *line, const char *string, long length) { @@ -313,15 +321,10 @@ struct variable *do_variable_definition (const struct floc *flocp, enum variable_origin origin, enum variable_flavor flavor, int target_var); -struct variable *parse_variable_definition (struct variable *v, char *line); -struct variable *try_variable_definition (const struct floc *flocp, char *line, - enum variable_origin origin, - int target_var); #else /* CONFIG_WITH_VALUE_LENGTH */ # define do_variable_definition(flocp, varname, value, origin, flavor, target_var) \ do_variable_definition_2 ((flocp), (varname), (value), ~0U, 0, NULL, \ (origin), (flavor), (target_var)) - struct variable *do_variable_definition_2 (const struct floc *flocp, const char *varname, const char *value, @@ -330,13 +333,14 @@ struct variable *do_variable_definition_2 (const struct floc *flocp, enum variable_origin origin, enum variable_flavor flavor, int target_var); -struct variable *parse_variable_definition (struct variable *v, char *line, - char *eos); -struct variable *try_variable_definition (const struct floc *flocp, char *line, - char *eos, +#endif /* CONFIG_WITH_VALUE_LENGTH */ +char *parse_variable_definition (const char *line, + enum variable_flavor *flavor); +struct variable *assign_variable_definition (struct variable *v, char *line IF_WITH_VALUE_LENGTH_PARAM(char *eos)); +struct variable *try_variable_definition (const struct floc *flocp, char *line + IF_WITH_VALUE_LENGTH_PARAM(char *eos), enum variable_origin origin, int target_var); -#endif /* CONFIG_WITH_VALUE_LENGTH */ void init_hash_global_variable_set (void); void hash_init_function_table (void); struct variable *lookup_variable (const char *name, unsigned int length); @@ -366,6 +370,12 @@ struct variable *define_variable_in_set (const char *name, unsigned int length, define_variable_in_set((n),(l),(v),(vl),(dv),(o),(r),\ current_variable_set_list->set,NILF) +/* Define a variable with a constant name in the current variable set. */ + +#define define_variable_cname(n,v,o,r) \ + define_variable_in_set((n),(sizeof (n) - 1),(v),~0U,1,(o),(r),\ + current_variable_set_list->set,NILF) + /* Define a variable with a location in the current variable set. */ #define define_variable_loc(n,l,v,o,r,f) \ @@ -400,6 +410,12 @@ struct variable *define_variable_in_set (const char *name, unsigned int length, define_variable_in_set((n),(l),(v),(o),(r),\ current_variable_set_list->set,NILF) /* force merge conflict */ +/* Define a variable with a constant name in the current variable set. */ + +#define define_variable_cname(n,v,o,r) \ + define_variable_in_set((n),(sizeof (n) - 1),(v),(o),(r),\ + current_variable_set_list->set,NILF) /* force merge conflict */ + /* Define a variable with a location in the current variable set. */ #define define_variable_loc(n,l,v,o,r,f) \ @@ -418,6 +434,15 @@ struct variable *define_variable_in_set (const char *name, unsigned int length, #endif /* !CONFIG_WITH_VALUE_LENGTH */ +void undefine_variable_in_set (const char *name, unsigned int length, + enum variable_origin origin, + struct variable_set *set); + +/* Remove variable from the current variable set. */ + +#define undefine_variable_global(n,l,o) \ + undefine_variable_in_set((n),(l),(o),NULL) + /* Warn that NAME is an undefined variable. */ #define warn_undefined(n,l) do{\ @@ -443,3 +468,4 @@ extern struct strcache2 variable_strcache; #define MAKELEVEL_NAME "MAKELEVEL" #endif #define MAKELEVEL_LENGTH (sizeof (MAKELEVEL_NAME) - 1) + diff --git a/src/kmk/version.c b/src/kmk/version.c index 85c1a4c..a770e22 100644 --- a/src/kmk/version.c +++ b/src/kmk/version.c @@ -1,7 +1,7 @@ /* Record version and build host architecture for GNU make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/vmsdir.h b/src/kmk/vmsdir.h index 2e62cab..cb17818 100644 --- a/src/kmk/vmsdir.h +++ b/src/kmk/vmsdir.h @@ -1,6 +1,6 @@ /* dirent.h for vms Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -2007 Free Software Foundation, Inc. +2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/vmsfunctions.c b/src/kmk/vmsfunctions.c index f3f70e3..5b867d9 100644 --- a/src/kmk/vmsfunctions.c +++ b/src/kmk/vmsfunctions.c @@ -1,6 +1,6 @@ /* VMS functions Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -2007 Free Software Foundation, Inc. +2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -34,13 +34,11 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ DIR * opendir (char *dspec) { - struct DIR *dir = (struct DIR *)xmalloc (sizeof (struct DIR)); - struct NAM *dnam = (struct NAM *)xmalloc (sizeof (struct NAM)); + struct DIR *dir = xcalloc (sizeof (struct DIR)); + struct NAM *dnam = xmalloc (sizeof (struct NAM)); struct FAB *dfab = &dir->fab; char *searchspec = xmalloc (MAXNAMLEN + 1); - memset (dir, 0, sizeof *dir); - *dfab = cc$rms_fab; *dnam = cc$rms_nam; sprintf (searchspec, "%s*.*;", dspec); @@ -91,7 +89,7 @@ readdir (DIR *dir) if (!((i = sys$search (dfab)) & 1)) { - DB (DB_VERBOSE, (_("sys$search failed with %d\n"), i)); + DB (DB_VERBOSE, (_("sys$search() failed with %d\n"), i)); return (NULL); } @@ -141,6 +139,10 @@ getwd (char *cwd) return (getcwd (buf, 512)); } +#if 0 +/* + * Is this used? I don't see any reference, so I suggest to remove it. + */ int vms_stat (char *name, struct stat *buf) { @@ -237,6 +239,7 @@ vms_stat (char *name, struct stat *buf) return 0; } +#endif char * cvt_time (unsigned long tval) diff --git a/src/kmk/vmsify.c b/src/kmk/vmsify.c index 23f0d5a..f58fee7 100644 --- a/src/kmk/vmsify.c +++ b/src/kmk/vmsify.c @@ -1,6 +1,6 @@ /* vmsify.c -- Module for vms <-> unix file name conversion Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -2007 Free Software Foundation, Inc. +2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -120,7 +120,11 @@ trnlog (const char *name) struct dsc$descriptor_s name_dsc; char *s; - INIT_DSC_CSTRING (name_dsc, name); + /* + * the string isn't changed, but there is no string descriptor with + * "const char *dsc$a_pointer" + */ + INIT_DSC_CSTRING (name_dsc, (char *)name); stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc); @@ -227,6 +231,9 @@ vmsify (const char *name, int type) char *vptr; int as_dir; int count; + const char *s; + const char *s1; + const char *s2; if (name == 0) return 0; @@ -239,8 +246,8 @@ vmsify (const char *name, int type) if (t != 0) { - const char *s1; - const char *s2; +// const char *s1; +// const char *s2; if (type == 1) { @@ -272,8 +279,9 @@ vmsify (const char *name, int type) if (t != 0) { - const char *s; - const char *s1 = strchr (t+1, '['); +// const char *s; +// const char *s1 = strchr (t+1, '['); + s1 = strchr (t+1, '['); if (s1 == 0) { strcpy (vmsname, name); @@ -388,8 +396,8 @@ vmsify (const char *name, int type) case 3: /* '//' at start */ { - const char *s; - const char *s1; +// const char *s; +// const char *s1; char *vp; while (*fptr == '/') /* collapse all '/' */ fptr++; diff --git a/src/kmk/vmsjobs.c b/src/kmk/vmsjobs.c index 69591d4..05c8dba 100644 --- a/src/kmk/vmsjobs.c +++ b/src/kmk/vmsjobs.c @@ -2,7 +2,7 @@ This file must be #included in job.c, as it accesses static functions. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -2007 Free Software Foundation, Inc. +2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -110,8 +110,11 @@ vms_handle_apos (char *p) return p; } -/* This is called as an AST when a child process dies (it won't get - interrupted by anything except a higher level AST). +static int ctrlYPressed= 0; +/* This is called at main or AST level. It is at AST level for DONTWAITFORCHILD + and at main level otherwise. In any case it is called when a child process + terminated. At AST level it won't get interrupted by anything except a + inner mode level AST. */ int vmsHandleChildTerm(struct child *child) @@ -123,6 +126,12 @@ vmsHandleChildTerm(struct child *child) vms_jobsefnmask &= ~(1 << (child->efn - 32)); lib$free_ef(&child->efn); + if (child->comname) + { + if (!ISDB (DB_JOBS)&&!ctrlYPressed) + unlink (child->comname); + free (child->comname); + } (void) sigblock (fatal_signal_mask); @@ -219,8 +228,7 @@ vmsHandleChildTerm(struct child *child) static int ctrlMask= LIB$M_CLI_CTRLY; static int oldCtrlMask; static int setupYAstTried= 0; -static int pidToAbort= 0; -static int chan= 0; +static unsigned short int chan= 0; static void reEnableAst(void) @@ -228,14 +236,15 @@ reEnableAst(void) lib$enable_ctrl (&oldCtrlMask,0); } -static void -astHandler (void) +static int +astYHandler (void) { - if (pidToAbort) { - sys$forcex (&pidToAbort, 0, SS$_ABORT); - pidToAbort= 0; - } + struct child *c; + for (c = children; c != 0; c = c->next) + sys$delprc (&c->pid, 0, 0); + ctrlYPressed= 1; kill (getpid(),SIGQUIT); + return SS$_NORMAL; } static void @@ -247,32 +256,28 @@ tryToSetupYAst(void) short int status, count; int dvi; } iosb; + unsigned short int loc_chan; setupYAstTried++; - if (!chan) { - status= sys$assign(&inputDsc,&chan,0,0); + if (chan) + loc_chan= chan; + else { + status= sys$assign(&inputDsc,&loc_chan,0,0); if (!(status&SS$_NORMAL)) { lib$signal(status); return; } } - status= sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0, - astHandler,0,0,0,0,0); - if (status==SS$_NORMAL) - status= iosb.status; - if (status==SS$_ILLIOFUNC || status==SS$_NOPRIV) { - sys$dassgn(chan); -#ifdef CTRLY_ENABLED_ANYWAY - fprintf (stderr, - _("-warning, CTRL-Y will leave sub-process(es) around.\n")); -#else - return; -#endif - } - else if (!(status&SS$_NORMAL)) { - sys$dassgn(chan); - lib$signal(status); + status= sys$qiow (0, loc_chan, IO$_SETMODE|IO$M_CTRLYAST,&iosb,0,0, + astYHandler,0,0,0,0,0); + if (status==SS$_NORMAL) + status= iosb.status; + if (status!=SS$_NORMAL) { + if (!chan) + sys$dassgn(loc_chan); + if (status!=SS$_ILLIOFUNC && status!=SS$_NOPRIV) + lib$signal(status); return; } @@ -287,6 +292,8 @@ tryToSetupYAst(void) lib$signal(status); return; } + if (!chan) + chan = loc_chan; } int @@ -299,13 +306,14 @@ child_execute_job (char *argv, struct child *child) static struct dsc$descriptor_s ofiledsc; static struct dsc$descriptor_s efiledsc; int have_redirection = 0; + int have_append = 0; int have_newline = 0; int spflags = CLI$M_NOWAIT; int status; char *cmd = alloca (strlen (argv) + 512), *p, *q; char ifile[256], ofile[256], efile[256]; - char *comname = 0; + int comnamelen; char procname[100]; int in_string; @@ -314,6 +322,7 @@ child_execute_job (char *argv, struct child *child) ifile[0] = 0; ofile[0] = 0; efile[0] = 0; + child->comname = NULL; DB (DB_JOBS, ("child_execute_job (%s)\n", argv)); @@ -383,6 +392,11 @@ child_execute_job (char *argv, struct child *child) } else { + if (*(p+1) == '>') + { + have_append = 1; + p += 1; + } p = vms_redirect (&ofiledsc, ofile, p); } *q = ' '; @@ -481,9 +495,10 @@ child_execute_job (char *argv, struct child *child) return 0; } - outfile = open_tmpfile (&comname, "sys$scratch:CMDXXXXXX.COM"); + outfile = open_tmpfile (&child->comname, "sys$scratch:CMDXXXXXX.COM"); if (outfile == 0) pfatal_with_name (_("fopen (temporary file)")); + comnamelen = strlen (child->comname); if (ifile[0]) { @@ -501,9 +516,19 @@ child_execute_job (char *argv, struct child *child) if (ofile[0]) { - fprintf (outfile, "$ define sys$output %s\n", ofile); - DB (DB_JOBS, (_("Redirected output to %s\n"), ofile)); - ofiledsc.dsc$w_length = 0; + if (have_append) + { + fprintf (outfile, "$ set noon\n"); + fprintf (outfile, "$ define sys$output %.*s\n", comnamelen-3, child->comname); + DB (DB_JOBS, (_("Append output to %s\n"), ofile)); + ofiledsc.dsc$w_length = 0; + } + else + { + fprintf (outfile, "$ define sys$output %s\n", ofile); + DB (DB_JOBS, (_("Redirected output to %s\n"), ofile)); + ofiledsc.dsc$w_length = 0; + } } p = sep = q = cmd; @@ -558,12 +583,25 @@ child_execute_job (char *argv, struct child *child) } } - fwrite (p, 1, q - p, outfile); + if (*p) + { + fwrite (p, 1, --q - p, outfile); fputc ('\n', outfile); + } + + if (have_append) + { + fprintf (outfile, "$ deassign sys$output ! 'f$verify(0)\n"); + fprintf (outfile, "$ append:=append\n"); + fprintf (outfile, "$ delete:=delete\n"); + fprintf (outfile, "$ append/new %.*s %s\n", comnamelen-3, child->comname, ofile); + fprintf (outfile, "$ delete %.*s;*\n", comnamelen-3, child->comname); + DB (DB_JOBS, (_("Append %.*s and cleanup\n"), comnamelen-3, child->comname)); + } fclose (outfile); - sprintf (cmd, "$ @%s", comname); + sprintf (cmd, "$ @%s", child->comname); DB (DB_JOBS, (_("Executing %s instead\n"), cmd)); } @@ -578,7 +616,15 @@ child_execute_job (char *argv, struct child *child) { status = lib$get_ef ((unsigned long *)&child->efn); if (!(status & 1)) - return 0; + { + if (child->comname) + { + if (!ISDB (DB_JOBS)) + unlink (child->comname); + free (child->comname); + } + return 0; + } } sys$clref (child->efn); @@ -647,9 +693,7 @@ child_execute_job (char *argv, struct child *child) 0, 0, 0); if (status & 1) { - pidToAbort= child->pid; status= sys$waitfr (child->efn); - pidToAbort= 0; vmsHandleChildTerm(child); } #else @@ -677,8 +721,5 @@ child_execute_job (char *argv, struct child *child) } } - if (comname && !ISDB (DB_JOBS)) - unlink (comname); - return (status & 1); } diff --git a/src/kmk/vpath.c b/src/kmk/vpath.c index 79ab82b..2f7bc26 100644 --- a/src/kmk/vpath.c +++ b/src/kmk/vpath.c @@ -1,7 +1,7 @@ /* Implementation of pattern-matching file search paths for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software -Foundation, Inc. +1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -147,7 +147,7 @@ build_vpath_lists () } } -/* Construct the VPATH listing for the pattern and searchpath given. +/* Construct the VPATH listing for the PATTERN and DIRPATH given. This function is called to generate selective VPATH lists and also for the general VPATH list (which is in fact just a selective VPATH that @@ -155,9 +155,9 @@ build_vpath_lists () linked list of all selective VPATH lists or in the GENERAL_VPATH variable. - If SEARCHPATH is nil, remove all previous listings with the same + If DIRPATH is nil, remove all previous listings with the same pattern. If PATTERN is nil, remove all VPATH listings. Existing - and readable directories that are not "." given in the searchpath + and readable directories that are not "." given in the DIRPATH separated by the path element separator (defined in make.h) are loaded into the directory hash table if they are not there already and put in the VPATH searchpath for the given pattern with trailing @@ -202,7 +202,8 @@ construct_vpath_list (char *pattern, char *dirpath) lastpath->next = next; /* Free its unused storage. */ - free (path->searchpath); + /* MSVC erroneously warns without a cast here. */ + free ((void *)path->searchpath); free (path); } else @@ -288,7 +289,7 @@ construct_vpath_list (char *pattern, char *dirpath) entry, to where the nil-pointer terminator goes. Usually this is maxelem - 1. If not, shrink down. */ if (elem < (maxelem - 1)) - vpath = xrealloc (vpath, (elem+1) * sizeof (const char *)); + vpath = (const char **)xrealloc (vpath, (elem+1) * sizeof (const char *)); /* Put the nil-pointer terminator on the end of the VPATH list. */ vpath[elem] = NULL; @@ -307,7 +308,8 @@ construct_vpath_list (char *pattern, char *dirpath) } else /* There were no entries, so free whatever space we allocated. */ - free (vpath); + /* MSVC erroneously warns without a cast here. */ + free ((void *)vpath); } /* Search the GPATH list for a pathname string that matches the one passed @@ -330,11 +332,12 @@ gpath_search (const char *file, unsigned int len) /* Search the given VPATH list for a directory where the name pointed to by FILE exists. If it is found, we return a cached name of the existing file and set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no - stat call was done). Otherwise we return NULL. */ + stat call was done). Also set the matching directory index in PATH_INDEX + if it is not NULL. Otherwise we return NULL. */ static const char * selective_vpath_search (struct vpath *path, const char *file, - FILE_TIMESTAMP *mtime_ptr) + FILE_TIMESTAMP *mtime_ptr, unsigned int* path_index) { int not_target; char *name; @@ -514,6 +517,9 @@ selective_vpath_search (struct vpath *path, const char *file, /* Store the name we found and return it. */ + if (path_index) + *path_index = i; + return strcache_add_len (name, (p + 1 - name) + flen); } } @@ -525,10 +531,12 @@ selective_vpath_search (struct vpath *path, const char *file, /* Search the VPATH list whose pattern matches FILE for a directory where FILE exists. If it is found, return the cached name of an existing file, and set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no - stat call was done). Otherwise we return 0. */ + stat call was done). Also set the matching directory index in VPATH_INDEX + and PATH_INDEX if they are not NULL. Otherwise we return 0. */ const char * -vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr) +vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr, + unsigned int* vpath_index, unsigned int* path_index) { struct vpath *v; @@ -542,23 +550,40 @@ vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr) || (vpaths == 0 && general_vpath == 0)) return 0; + if (vpath_index) + { + *vpath_index = 0; + *path_index = 0; + } + for (v = vpaths; v != 0; v = v->next) - if (pattern_matches (v->pattern, v->percent, file)) - { - const char *p = selective_vpath_search (v, file, mtime_ptr); - if (p) - return p; - } + { + if (pattern_matches (v->pattern, v->percent, file)) + { + const char *p = selective_vpath_search ( + v, file, mtime_ptr, path_index); + if (p) + return p; + } + + if (vpath_index) + ++*vpath_index; + } + if (general_vpath != 0) { - const char *p = selective_vpath_search (general_vpath, file, mtime_ptr); + const char *p = selective_vpath_search ( + general_vpath, file, mtime_ptr, path_index); if (p) return p; } return 0; } + + + /* Print the data base of VPATH search paths. */ diff --git a/src/kmk/w32/Makefile.am b/src/kmk/w32/Makefile.am index 77c6e97..b8e2071 100644 --- a/src/kmk/w32/Makefile.am +++ b/src/kmk/w32/Makefile.am @@ -1,6 +1,6 @@ # Makefile.am to create libw32.a for mingw32 host. # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -# 2007 Free Software Foundation, Inc. +# 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/w32/compat/dirent.c b/src/kmk/w32/compat/dirent.c index bf27b31..6577f72 100644 --- a/src/kmk/w32/compat/dirent.c +++ b/src/kmk/w32/compat/dirent.c @@ -1,6 +1,6 @@ /* Directory entry code for Window platforms. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -16,9 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifdef KMK -# include "config.h" /* my_stat */ -#endif +#include <config.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> @@ -141,7 +139,7 @@ readdir(DIR* pDir) pDir->dir_nNumFiles++; /* fill in struct dirent values */ - pDir->dir_sdReturn.d_ino = -1; + pDir->dir_sdReturn.d_ino = (ino_t)-1; strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName); return &pDir->dir_sdReturn; diff --git a/src/kmk/w32/imagecache.c b/src/kmk/w32/imagecache.c new file mode 100644 index 0000000..157ed8e --- /dev/null +++ b/src/kmk/w32/imagecache.c @@ -0,0 +1,139 @@ +/* $Id: imagecache.c 2640 2012-09-09 01:49:16Z bird $ */ +/** @file + * kBuild specific executable image cache for Windows. + */ + +/* + * Copyright (c) 2012 knut st. osmundsen <bird-kBuild-spamx@anduin.net> + * + * This file is part of kBuild. + * + * kBuild is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * kBuild is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kBuild. If not, see <http://www.gnu.org/licenses/> + * + */ + +/* No GNU coding style here! */ + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include "make.h" + +#include <Windows.h> + + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +typedef struct EXECCACHEENTRY +{ + /** The name hash value. */ + unsigned uHash; + /** The name length. */ + unsigned cchName; + /** Pointer to the next name with the same hash. */ + struct EXECCACHEENTRY *pNext; + /** When it was last referenced. */ + unsigned uLastRef; + /** The module handle. */ + HMODULE hmod1; + /** The module handle. */ + HMODULE hmod2; + /** The executable path. */ + char szName[1]; +} EXECCACHEENTRY; +typedef EXECCACHEENTRY *PEXECCACHEENTRY; + +/******************************************************************************* +* Global Variables * +*******************************************************************************/ +/** The number of cached images. */ +static unsigned g_cCached; +/** Used noting when entries was last used. + * Increased on each kmk_cache_exec_image call. */ +static unsigned g_uNow; + +/** The size of the hash table. */ +#define EXECCACHE_HASHTAB_SIZE 128 +/** The hash table. */ +static PEXECCACHEENTRY g_apHashTab[EXECCACHE_HASHTAB_SIZE]; + + +/* sdbm: + This algorithm was created for sdbm (a public-domain reimplementation of + ndbm) database library. it was found to do well in scrambling bits, + causing better distribution of the keys and fewer splits. it also happens + to be a good general hashing function with good distribution. the actual + function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below + is the faster version used in gawk. [there is even a faster, duff-device + version] the magic constant 65599 was picked out of thin air while + experimenting with different constants, and turns out to be a prime. + this is one of the algorithms used in berkeley db (see sleepycat) and + elsewhere. */ + +static unsigned execcache_calc_hash(const char *psz, unsigned *pcch) +{ + unsigned char *puch = (unsigned char *)psz; + unsigned hash = 0; + int ch; + + while ((ch = *puch++)) + hash = ch + (hash << 6) + (hash << 16) - hash; + + *pcch = (unsigned)(puch - psz - 1); + return hash; +} + + +extern void kmk_cache_exec_image(const char *pszExec) +{ + /* + * Lookup the name. + */ + unsigned cchName; + const unsigned uHash = execcache_calc_hash(pszExec, &cchName); + PEXECCACHEENTRY *ppCur = &g_apHashTab[uHash % EXECCACHE_HASHTAB_SIZE]; + PEXECCACHEENTRY pCur = *ppCur; + while (pCur) + { + if ( pCur->uHash == uHash + && pCur->cchName == cchName + && !memcmp(pCur->szName, pszExec, cchName)) + { + pCur->uLastRef = ++g_uNow; + return; + } + ppCur = &pCur->pNext; + pCur = pCur->pNext; + } + + /* + * Not found, create a new entry. + */ + pCur = xmalloc(sizeof(*pCur) + cchName); + pCur->uHash = uHash; + pCur->cchName = cchName; + pCur->pNext = NULL; + pCur->uLastRef = ++g_uNow; + memcpy(pCur->szName, pszExec, cchName + 1); + pCur->hmod1 = LoadLibraryEx(pszExec, NULL, LOAD_LIBRARY_AS_DATAFILE); + if (pCur->hmod1 != NULL) + pCur->hmod2 = LoadLibraryEx(pszExec, NULL, DONT_RESOLVE_DLL_REFERENCES); + else + pCur->hmod2 = NULL; + + *ppCur = pCur; + g_cCached++; +} + diff --git a/src/kmk/w32/include/dirent.h b/src/kmk/w32/include/dirent.h index 818cf06..6e77c8b 100644 --- a/src/kmk/w32/include/dirent.h +++ b/src/kmk/w32/include/dirent.h @@ -1,6 +1,6 @@ /* Windows version of dirent.h Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -2007 Free Software Foundation, Inc. +2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/w32/include/pathstuff.h b/src/kmk/w32/include/pathstuff.h index 2ff4506..d567b8b 100644 --- a/src/kmk/w32/include/pathstuff.h +++ b/src/kmk/w32/include/pathstuff.h @@ -1,6 +1,6 @@ /* Definitions for Windows path manipulation. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -2007 Free Software Foundation, Inc. +2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/w32/include/sub_proc.h b/src/kmk/w32/include/sub_proc.h index 21ef1a4..8166dce 100644 --- a/src/kmk/w32/include/sub_proc.h +++ b/src/kmk/w32/include/sub_proc.h @@ -1,6 +1,6 @@ /* Definitions for Windows process invocation. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -21,11 +21,11 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Component Name: * - * $Date: 2007/10/24 20:06:32 $ + * $Date: 2010/07/13 01:20:43 $ * * $Source: /sources/make/make/w32/include/sub_proc.h,v $ * - * $Id: sub_proc.h,v 1.10 2007/10/24 20:06:32 eliz Exp $ + * $Id: sub_proc.h,v 1.12 2010/07/13 01:20:43 psmith Exp $ */ #define EXTERN_DECL(entry, args) extern entry args diff --git a/src/kmk/w32/include/w32err.h b/src/kmk/w32/include/w32err.h index 7a66713..65369ba 100644 --- a/src/kmk/w32/include/w32err.h +++ b/src/kmk/w32/include/w32err.h @@ -1,6 +1,6 @@ /* Definitions for Windows error handling. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/w32/pathstuff.c b/src/kmk/w32/pathstuff.c index eca3f24..8eea494 100644 --- a/src/kmk/w32/pathstuff.c +++ b/src/kmk/w32/pathstuff.c @@ -1,6 +1,6 @@ /* Path conversion for Windows pathnames. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -2007, 2009 Free Software Foundation, Inc. +2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -16,10 +16,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <Windows.h> /* bird */ -#include <stdio.h> /* bird */ +#include "make.h" #include <string.h> #include <stdlib.h> -#include "make.h" #include "pathstuff.h" /* @@ -82,7 +81,7 @@ convert_Path_to_windows32(char *Path, char to_delim) if (etok) { *etok = to_delim; p = ++etok; - } else + } else p += strlen(p); } else { /* found another one, no drive letter */ @@ -145,47 +144,6 @@ getcwd_fs(char* buf, int len) return p; } -#undef stat -/* - * Workaround for directory names with trailing slashes. - * Added by bird reasons stated. - */ -int -my_stat(const char *path, struct stat *st) -{ - int rc = stat(path, st); - if ( rc != 0 - && errno == ENOENT - && *path != '\0') - { - char *slash = strchr(path, '\0') - 1; - if (*slash == '/' || *slash == '\\') - { - size_t len_path = slash - path + 1; - char *tmp = alloca(len_path + 4); - memcpy(tmp, path, len_path); - tmp[len_path] = '.'; - tmp[len_path + 1] = '\0'; - errno = 0; - rc = stat(tmp, st); - if ( rc == 0 - && !S_ISDIR(st->st_mode)) - { - errno = ENOTDIR; - rc = -1; - } - } - } -#ifdef KMK_PRF - { - int err = errno; - fprintf(stderr, "stat(%s,) -> %d/%d\n", path, rc, errno); - errno = err; - } -#endif - return rc; -} - #ifdef unused /* * Convert delimiter separated pathnames (e.g. PATH) or single file pathname diff --git a/src/kmk/w32/subproc/NMakefile b/src/kmk/w32/subproc/NMakefile index 1330ab0..46c838c 100644 --- a/src/kmk/w32/subproc/NMakefile +++ b/src/kmk/w32/subproc/NMakefile @@ -2,7 +2,7 @@ # `build.bat' instead. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -# 2006, 2007 Free Software Foundation, Inc. +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can redistribute it and/or modify it under diff --git a/src/kmk/w32/subproc/build.bat b/src/kmk/w32/subproc/build.bat index c9c3522..dee4072 100644 --- a/src/kmk/w32/subproc/build.bat +++ b/src/kmk/w32/subproc/build.bat @@ -18,7 +18,7 @@ gcc -mthreads -Wall -gdwarf-2 -g3 -O2 -I.. -I. -I../include -I../.. -DWINDOWS32 @echo off
rem Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-rem 2005, 2006, 2007 Free Software Foundation, Inc.
+rem 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
rem This file is part of GNU Make.
rem
rem GNU Make is free software; you can redistribute it and/or modify it under
diff --git a/src/kmk/w32/subproc/misc.c b/src/kmk/w32/subproc/misc.c index 3e1981a..6759c17 100644 --- a/src/kmk/w32/subproc/misc.c +++ b/src/kmk/w32/subproc/misc.c @@ -1,6 +1,6 @@ /* Process handling for Windows Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -15,6 +15,7 @@ A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <config.h> #include <stddef.h> #include <stdlib.h> #include <string.h> @@ -77,6 +78,6 @@ arr2envblk(char **arr, char **envblk_out) arrcnt++; } - free(tmp); + free(tmp); return TRUE; } diff --git a/src/kmk/w32/subproc/proc.h b/src/kmk/w32/subproc/proc.h index 393f570..00b4bac 100644 --- a/src/kmk/w32/subproc/proc.h +++ b/src/kmk/w32/subproc/proc.h @@ -1,6 +1,6 @@ /* Definitions for Windows Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/kmk/w32/subproc/sub_proc.c b/src/kmk/w32/subproc/sub_proc.c index 4e03366..4d454b2 100644 --- a/src/kmk/w32/subproc/sub_proc.c +++ b/src/kmk/w32/subproc/sub_proc.c @@ -1,6 +1,6 @@ /* Process handling for Windows. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the @@ -15,8 +15,14 @@ A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <config.h> #include <stdlib.h> #include <stdio.h> +#ifdef _MSC_VER +# include <stddef.h> /* for intptr_t */ +#else +# include <stdint.h> +#endif #include <process.h> /* for msvc _beginthreadex, _endthreadex */ #include <signal.h> #include <windows.h> @@ -24,15 +30,18 @@ this program. If not, see <http://www.gnu.org/licenses/>. */ #include "sub_proc.h" #include "proc.h" #include "w32err.h" -#include "config.h" #include "debug.h" static char *make_command_line(char *shell_name, char *exec_path, char **argv); +extern char *xmalloc (unsigned int); +#ifdef KMK +extern void kmk_cache_exec_image(const char *); /* imagecache.c */ +#endif typedef struct sub_process_t { - int sv_stdin[2]; - int sv_stdout[2]; - int sv_stderr[2]; + intptr_t sv_stdin[2]; + intptr_t sv_stdout[2]; + intptr_t sv_stderr[2]; int using_pipes; char *inp; DWORD incnt; @@ -40,7 +49,7 @@ typedef struct sub_process_t { volatile DWORD outcnt; char * volatile errp; volatile DWORD errcnt; - int pid; + pid_t pid; int exit_code; int signal; long last_err; @@ -315,12 +324,12 @@ process_init() pproc->lerrno = E_SCALL; return((HANDLE)pproc); } - pproc->sv_stdin[0] = (int) stdin_pipes[0]; - pproc->sv_stdin[1] = (int) stdin_pipes[1]; - pproc->sv_stdout[0] = (int) stdout_pipes[0]; - pproc->sv_stdout[1] = (int) stdout_pipes[1]; - pproc->sv_stderr[0] = (int) stderr_pipes[0]; - pproc->sv_stderr[1] = (int) stderr_pipes[1]; + pproc->sv_stdin[0] = (intptr_t) stdin_pipes[0]; + pproc->sv_stdin[1] = (intptr_t) stdin_pipes[1]; + pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0]; + pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1]; + pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0]; + pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1]; pproc->using_pipes = 1; @@ -342,9 +351,9 @@ process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh) * Just pass the provided file handles to the 'child side' of the * pipe, bypassing pipes altogether. */ - pproc->sv_stdin[1] = (int) stdinh; - pproc->sv_stdout[1] = (int) stdouth; - pproc->sv_stderr[1] = (int) stderrh; + pproc->sv_stdin[1] = (intptr_t) stdinh; + pproc->sv_stdout[1] = (intptr_t) stdouth; + pproc->sv_stderr[1] = (intptr_t) stderrh; pproc->last_err = pproc->lerrno = 0; @@ -353,70 +362,54 @@ process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh) static HANDLE -find_file(char *exec_path, LPOFSTRUCT file_info) +find_file(const char *exec_path, const char *path_var, + char *full_fname, DWORD full_len) { HANDLE exec_handle; char *fname; char *ext; -#ifdef KMK - size_t exec_path_len; - - /* - * if there is an .exe extension there already, don't waste time here. - * If .exe scripts become common, they can be handled in a CreateProcess - * failure path instead of here. - */ - exec_path_len = strlen(exec_path); - if ( exec_path_len > 4 - && exec_path[exec_path_len - 4] == '.' - && !stricmp(exec_path + exec_path_len - 3, "exe")){ - return((HANDLE)HFILE_ERROR); - } + DWORD req_len; + int i; + static const char *extensions[] = + /* Should .com come before no-extension case? */ + { ".exe", ".cmd", ".bat", "", ".com", NULL }; - fname = malloc(exec_path_len + 5); -#else - fname = malloc(strlen(exec_path) + 5); -#endif + fname = xmalloc(strlen(exec_path) + 5); strcpy(fname, exec_path); ext = fname + strlen(fname); - strcpy(ext, ".exe"); - if ((exec_handle = (HANDLE)OpenFile(fname, file_info, - OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) { - free(fname); - return(exec_handle); - } - - strcpy(ext, ".cmd"); - if ((exec_handle = (HANDLE)OpenFile(fname, file_info, - OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) { - free(fname); - return(exec_handle); - } - - strcpy(ext, ".bat"); - if ((exec_handle = (HANDLE)OpenFile(fname, file_info, - OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) { - free(fname); - return(exec_handle); - } - - /* should .com come before this case? */ - if ((exec_handle = (HANDLE)OpenFile(exec_path, file_info, - OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) { - free(fname); - return(exec_handle); - } - - strcpy(ext, ".com"); - if ((exec_handle = (HANDLE)OpenFile(fname, file_info, - OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) { - free(fname); - return(exec_handle); + for (i = 0; extensions[i]; i++) { + strcpy(ext, extensions[i]); + if (((req_len = SearchPath (path_var, fname, NULL, full_len, + full_fname, NULL)) > 0 + /* For compatibility with previous code, which + used OpenFile, and with Windows operation in + general, also look in various default + locations, such as Windows directory and + Windows System directory. Warning: this also + searches PATH in the Make's environment, which + might not be what the Makefile wants, but it + seems to be OK as a fallback, after the + previous SearchPath failed to find on child's + PATH. */ + || (req_len = SearchPath (NULL, fname, NULL, full_len, + full_fname, NULL)) > 0) + && req_len <= full_len + && (exec_handle = + CreateFile(full_fname, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL)) != INVALID_HANDLE_VALUE) { + free(fname); + return(exec_handle); + } } free(fname); - return(exec_handle); + return INVALID_HANDLE_VALUE; } @@ -439,6 +432,9 @@ process_begin( char *shell_name = 0; int file_not_found=0; HANDLE exec_handle; + char exec_fname[MAX_PATH]; + const char *path_var = NULL; + char **ep; char buf[256]; DWORD bytes_returned; DWORD flags; @@ -446,26 +442,53 @@ process_begin( STARTUPINFO startInfo; PROCESS_INFORMATION procInfo; char *envblk=NULL; - OFSTRUCT file_info; +#ifdef KMK + size_t exec_path_len; +#endif - /* - * Shell script detection... if the exec_path starts with #! then - * we want to exec shell-script-name exec-path, not just exec-path - * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not - * hard-code the path to the shell or perl or whatever: Instead, we - * assume it's in the path somewhere (generally, the NT tools - * bin directory) - * We use OpenFile here because it is capable of searching the Path. - */ + /* + * Shell script detection... if the exec_path starts with #! then + * we want to exec shell-script-name exec-path, not just exec-path + * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not + * hard-code the path to the shell or perl or whatever: Instead, we + * assume it's in the path somewhere (generally, the NT tools + * bin directory) + */ - exec_handle = find_file(exec_path, &file_info); +#ifdef KMK + /* kmk performance: Don't bother looking for shell scripts in .exe files. */ + exec_path_len = strlen(exec_path); + if (exec_path_len > 4 + && exec_path[exec_path_len - 4] == '.' + && !stricmp(exec_path + exec_path_len - 3, "exe")) { + exec_handle = INVALID_HANDLE_VALUE; + exec_fname[0] = '\0'; + } + else { +#endif /* KMK */ + /* Use the Makefile's value of PATH to look for the program to + execute, because it could be different from Make's PATH + (e.g., if the target sets its own value. */ + if (envp) + for (ep = envp; *ep; ep++) { + if (strncmp (*ep, "PATH=", 5) == 0 + || strncmp (*ep, "Path=", 5) == 0) { + path_var = *ep + 5; + break; + } + } + exec_handle = find_file(exec_path, path_var, + exec_fname, sizeof(exec_fname)); +#ifdef KMK + } +#endif /* - * If we couldn't open the file, just assume that Windows32 will be able - * to find and execute it. + * If we couldn't open the file, just assume that Windows will be + * somehow able to find and execute it. */ - if (exec_handle == (HANDLE)HFILE_ERROR) { + if (exec_handle == INVALID_HANDLE_VALUE) { file_not_found++; } else { @@ -519,8 +542,7 @@ process_begin( if (file_not_found) command_line = make_command_line( shell_name, exec_path, argv); else - command_line = make_command_line( shell_name, file_info.szPathName, - argv); + command_line = make_command_line( shell_name, exec_fname, argv); if ( command_line == NULL ) { pproc->last_err = 0; @@ -540,7 +562,7 @@ process_begin( if ((shell_name) || (file_not_found)) { exec_path = 0; /* Search for the program in %Path% */ } else { - exec_path = file_info.szPathName; + exec_path = exec_fname; } /* @@ -581,6 +603,14 @@ process_begin( DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n", exec_path ? exec_path : "NULL", command_line ? command_line : "NULL")); +#ifdef KMK + if (exec_fname[0]) + kmk_cache_exec_image(exec_fname); + else if (exec_path) + kmk_cache_exec_image(exec_path); + else if (argv[0]) + kmk_cache_exec_image(argv[0]); +#endif if (CreateProcess( exec_path, command_line, @@ -607,7 +637,7 @@ process_begin( } } - pproc->pid = (int)procInfo.hProcess; + pproc->pid = (pid_t)procInfo.hProcess; /* Close the thread handle -- we'll just watch the process */ CloseHandle(procInfo.hThread); diff --git a/src/kmk/w32/subproc/w32err.c b/src/kmk/w32/subproc/w32err.c index 163a0d7..80d796e 100644 --- a/src/kmk/w32/subproc/w32err.c +++ b/src/kmk/w32/subproc/w32err.c @@ -1,6 +1,6 @@ /* Error handling for Windows Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the diff --git a/src/sed/basicdefs.h b/src/sed/basicdefs.h index 5da6887..d4b9e47 100644 --- a/src/sed/basicdefs.h +++ b/src/sed/basicdefs.h @@ -59,7 +59,7 @@ # define bool unsigned # define __bool_true_false_are_defined 1 #else -# if HAVE_STDBOOL_H +# if HAVE_STDBOOL_H || defined(__HAIKU__) /* haiku/gcc2 hack */ # include <stdbool.h> # endif #endif diff --git a/src/sed/config.h.haiku b/src/sed/config.h.haiku new file mode 100644 index 0000000..a925451 --- /dev/null +++ b/src/sed/config.h.haiku @@ -0,0 +1,471 @@ +/* config.h. Generated from config_h.in by configure. */ +/* config_h.in. Generated from configure.ac by autoheader. */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +/* #undef ENABLE_NLS */ + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the <argz.h> header file. */ +/* #undef HAVE_ARGZ_H */ + +/* Define to 1 if you have the `asprintf' function. */ +#define HAVE_ASPRINTF 1 + +/* Define to 1 if you have the `bcopy' function. */ +#define HAVE_BCOPY 1 + +/* Define to 1 if you have the `btowc' function. */ +#define HAVE_BTOWC 1 + +/* Define to 1 if you have the `bzero' function. */ +#define HAVE_BZERO 1 + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +/* #undef HAVE_DCGETTEXT */ + +/* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you + don't. */ +#define HAVE_DECL_FEOF_UNLOCKED 1 + +/* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if + you don't. */ +#define HAVE_DECL_FGETS_UNLOCKED 0 + +/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you + don't. */ +#define HAVE_DECL_GETC_UNLOCKED 1 + +/* Define to 1 if you have the declaration of `_snprintf', and to 0 if you + don't. */ +#define HAVE_DECL__SNPRINTF 0 + +/* Define to 1 if you have the declaration of `_snwprintf', and to 0 if you + don't. */ +#define HAVE_DECL__SNWPRINTF 0 + +/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. + */ +#define HAVE_DIRENT_H 1 + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +/* #undef HAVE_DOPRNT */ + +/* Define to 1 if you have the <errno.h> header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the `fchmod' function. */ +#define HAVE_FCHMOD 1 + +/* Define to 1 if you have the `fchown' function. */ +#define HAVE_FCHOWN 1 + +/* Define to 1 if you have the `fwprintf' function. */ +#define HAVE_FWPRINTF 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define to 1 if you have the `getegid' function. */ +#define HAVE_GETEGID 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the `getgid' function. */ +#define HAVE_GETGID 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if the GNU gettext() function is already present or preinstalled. */ +/* #undef HAVE_GETTEXT */ + +/* Define to 1 if you have the `getuid' function. */ +#define HAVE_GETUID 1 + +/* Define if you have the iconv() function. */ +#define HAVE_ICONV 1 + +/* Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>. */ +#define HAVE_INTMAX_T 1 + +/* Define if <inttypes.h> exists and doesn't clash with <sys/types.h>. */ +#define HAVE_INTTYPES_H 1 + +/* Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, and + declares uintmax_t. */ +#define HAVE_INTTYPES_H_WITH_UINTMAX 1 + +/* Define to 1 if you have the <io.h> header file. */ +/* #undef HAVE_IO_H */ + +/* Define to 1 if you have the `isascii' function. */ +#define HAVE_ISASCII 1 + +/* Define to 1 if you have the `isatty' function. */ +#define HAVE_ISATTY 1 + +/* Define to 1 if you have the `isblank' function. */ +#define HAVE_ISBLANK 1 + +/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */ +#define HAVE_LANGINFO_CODESET 1 + +/* Define if your <locale.h> file defines LC_MESSAGES. */ +#define HAVE_LC_MESSAGES 1 + +/* Define to 1 if you have the `regex' library (-lregex). */ +/* #undef HAVE_LIBREGEX */ + +/* Define to 1 if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the <locale.h> header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if you have the 'long double' type. */ +#define HAVE_LONG_DOUBLE 1 + +/* Define to 1 if you support file names longer than 14 characters. */ +#define HAVE_LONG_FILE_NAMES 1 + +/* Define if you have the 'long long' type. */ +#define HAVE_LONG_LONG 1 + +/* Define to 1 if you have the <malloc.h> header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if mbrtowc and mbstate_t are properly declared. */ +#define HAVE_MBRTOWC 1 + +/* Define to 1 if <wchar.h> declares mbstate_t. */ +#define HAVE_MBSTATE_T 1 + +/* Define to 1 if you have the <mcheck.h> header file. */ +/* #undef HAVE_MCHECK_H */ + +/* Define to 1 if you have the `memchr' function. */ +#define HAVE_MEMCHR 1 + +/* Define to 1 if you have the `memcmp' function. */ +#define HAVE_MEMCMP 1 + +/* Define to 1 if you have the `memcpy' function. */ +#define HAVE_MEMCPY 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mempcpy' function. */ +/* #undef HAVE_MEMPCPY */ + +/* Define to 1 if you have the `memset' function. */ +#define HAVE_MEMSET 1 + +/* Define to 1 if you have the `mkstemp' function. */ +#define HAVE_MKSTEMP 1 + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the `munmap' function. */ +#define HAVE_MUNMAP 1 + +/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the <nl_types.h> header file. */ +#define HAVE_NL_TYPES_H 1 + +/* Define to 1 if libc includes obstacks. */ +/* #undef HAVE_OBSTACK */ + +/* Define to 1 if you have the `pathconf' function. */ +#define HAVE_PATHCONF 1 + +/* Define to 1 if you have the `popen' function. */ +#define HAVE_POPEN 1 + +/* Define if your printf() function supports format strings with positions. */ +#define HAVE_POSIX_PRINTF 1 + +/* Define to 1 if you have the `putenv' function. */ +#define HAVE_PUTENV 1 + +/* Define to 1 if you have the <regex.h> header file. */ +/* #undef HAVE_REGEX_H */ + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define to 1 if you have the <stdarg.h> header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if stdbool.h conforms to C99. */ +/* #undef HAVE_STDBOOL_H */ + +/* Define to 1 if you have the <stddef.h> header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define if <stdint.h> exists, doesn't clash with <sys/types.h>, and declares + uintmax_t. */ +#define HAVE_STDINT_H_WITH_UINTMAX 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `stpcpy' function. */ +#define HAVE_STPCPY 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define to 1 if you have the `strverscmp' function. */ +/* #undef HAVE_STRVERSCMP */ + +/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the <sys/file.h> header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the <sys/param.h> header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `tsearch' function. */ +#define HAVE_TSEARCH 1 + +/* Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>. */ +#define HAVE_UINTMAX_T 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the 'unsigned long long' type. */ +#define HAVE_UNSIGNED_LONG_LONG 1 + +/* Define to 1 if you have the `vprintf' function. */ +#define HAVE_VPRINTF 1 + +/* Define to 1 if you have the <wchar.h> header file. */ +#define HAVE_WCHAR_H 1 + +/* Define if you have the 'wchar_t' type. */ +#define HAVE_WCHAR_T 1 + +/* Define to 1 if you have the `wcrtomb' function. */ +#define HAVE_WCRTOMB 1 + +/* Define to 1 if you have the `wcscoll' function. */ +#define HAVE_WCSCOLL 1 + +/* Define to 1 if you have the `wcslen' function. */ +#define HAVE_WCSLEN 1 + +/* Define to 1 if you have the <wctype.h> header file. */ +#define HAVE_WCTYPE_H 1 + +/* Define if you have the 'wint_t' type. */ +#define HAVE_WINT_T 1 + +/* Define to 1 if the system has the type `_Bool'. */ +/* #undef HAVE__BOOL */ + +/* Define to 1 if you have the `__argz_count' function. */ +/* #undef HAVE___ARGZ_COUNT */ + +/* Define to 1 if you have the `__argz_next' function. */ +/* #undef HAVE___ARGZ_NEXT */ + +/* Define to 1 if you have the `__argz_stringify' function. */ +/* #undef HAVE___ARGZ_STRINGIFY */ + +/* Define to 1 if you have the `__fsetlocking' function. */ +#define HAVE___FSETLOCKING 1 + +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST + +/* Define if integer division by zero raises signal SIGFPE. */ +#define INTDIV0_RAISES_SIGFPE 1 + +/* Name of package */ +#define PACKAGE "sed" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "bonzini@gnu.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "sed" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "sed 4.1.5" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "sed" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "4.1.5" + +/* Define if <inttypes.h> exists and defines unusable PRI* macros. */ +/* #undef PRI_MACROS_BROKEN */ + +/* Define to the version of GNU sed whose features are supported by this sed. + */ +#define SED_FEATURE_VERSION "4.1" + +/* Define as the maximum value of type 'size_t', if the system doesn't define + it. */ +/* #undef SIZE_MAX */ + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + + +/* Version number of package */ +#define VERSION "4.1.5" + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to 1 if on MINIX. */ +/* #undef _MINIX */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* Include BSD functions in regex, used by the testsuite */ +#define _REGEX_RE_COMP 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to a type if <wchar.h> does not define. */ +/* #undef mbstate_t */ + +/* Define to `long int' if <sys/types.h> does not define. */ +/* #undef off_t */ + +/* Define as the type of the result of subtracting two pointers, if the system + doesn't define it. */ +/* #undef ptrdiff_t */ + +/* Define to empty if the C compiler doesn't support this keyword. */ +/* #undef signed */ + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ + +/* Define to `int' if <sys/types.h> does not define. */ +/* #undef ssize_t */ + +/* Define to unsigned long or unsigned long long if <stdint.h> and + <inttypes.h> don't define. */ +/* #undef uintmax_t */ diff --git a/src/sed/lib/regex_internal.h b/src/sed/lib/regex_internal.h index c1c3e97..7ab79e7 100644 --- a/src/sed/lib/regex_internal.h +++ b/src/sed/lib/regex_internal.h @@ -39,7 +39,7 @@ #if defined HAVE_WCTYPE_H || defined _LIBC # include <wctype.h> #endif /* HAVE_WCTYPE_H || _LIBC */ -#if defined HAVE_STDBOOL_H || defined _LIBC +#if defined HAVE_STDBOOL_H || defined _LIBC || defined(__HAIKU__) /* haiku hack */ # include <stdbool.h> #endif /* HAVE_STDBOOL_H || _LIBC */ #if defined _LIBC diff --git a/src/sed/sed/sed.c b/src/sed/sed/sed.c index 575d6ad..f5c1eb9 100644 --- a/src/sed/sed/sed.c +++ b/src/sed/sed/sed.c @@ -406,3 +406,14 @@ to the extent permitted by law.\n\ return return_code; } + +#ifdef __HAIKU__ /* mbrtowc is busted, just stub it and pray the input won't ever acutally be multibyte... */ +size_t mbrtowc(wchar_t *pwc, const char *pch, size_t n, mbstate_t *ps) +{ + if (!n) + return 0; + if (pwc) + *pwc = *pch; + return 1; +} +#endif |